@happyvertical/smrt-app-runtime 0.57.7 → 0.57.8
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/README.md +22 -1
- package/dist/chunks/{src-DeNO6bG_.js → src-C98Cqurb.js} +27 -5
- package/dist/chunks/src-C98Cqurb.js.map +1 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/manifest.json +1 -1
- package/dist/smrt-knowledge.json +3 -3
- package/dist/sveltekit/owner-setup.d.ts +5 -1
- package/dist/sveltekit/owner-setup.d.ts.map +1 -1
- package/dist/sveltekit/runtime.d.ts +3 -0
- package/dist/sveltekit/runtime.d.ts.map +1 -1
- package/dist/sveltekit.js +10 -2
- package/dist/sveltekit.js.map +1 -1
- package/package.json +9 -9
- package/dist/chunks/src-DeNO6bG_.js.map +0 -1
package/README.md
CHANGED
|
@@ -232,7 +232,7 @@ Diagnostics authorize (owner role or `runtime_diagnostics.read` on an active,
|
|
|
232
232
|
session-matching membership) before reading the runtime and return only stable
|
|
233
233
|
`{ schemaVersion: 1, error: { code } }` failures. Owner setup is local-only and
|
|
234
234
|
re-checks on every request that both the peer address and the URL host are
|
|
235
|
-
loopback; its `default` action reads `token`, `name`, `email`, and optional
|
|
235
|
+
loopback; its `default` action reads `token`, `name`, `email`, and optional `password` and
|
|
236
236
|
`tenantName`, sets the session cookie, and redirects 303, or returns
|
|
237
237
|
`fail(status, { code, message })` with `setup_disabled` (404),
|
|
238
238
|
`setup_unavailable` (403), `setup_invalid_input` (400), `setup_invalid`
|
|
@@ -243,6 +243,27 @@ runtime removes the `smrt app setup` / `recover` hand-off files
|
|
|
243
243
|
invitation; failed claims leave them untouched. `onOwnerClaimed` remains for
|
|
244
244
|
extra app cleanup and `removeOnboardingHandoff: false` opts out.
|
|
245
245
|
|
|
246
|
+
Password-based applications should pass `{ requirePassword: true }` to
|
|
247
|
+
`createOwnerSetupPage` and include a password field in their setup form. The
|
|
248
|
+
password is stored in the owner-claim transaction; a rejected password leaves
|
|
249
|
+
the token available for retry. Existing bootstrap consumers may omit it.
|
|
250
|
+
Use one server-only `PasswordPolicyOptions` value for bootstrap and sign-in,
|
|
251
|
+
including any pepper, length constraints, or custom rejection hook:
|
|
252
|
+
|
|
253
|
+
```typescript
|
|
254
|
+
const passwordPolicy = { pepper: serverSecrets.passwordPepper, minLength: 16 };
|
|
255
|
+
const runtime = createSmrtSvelteKitRuntime({ passwordPolicy });
|
|
256
|
+
const passwords = await PasswordCredentialService.create({
|
|
257
|
+
...runtime.classOptions('User'),
|
|
258
|
+
password: passwordPolicy,
|
|
259
|
+
});
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
`initializeLocalApplicationRuntime` accepts the same `passwordPolicy` option.
|
|
263
|
+
It is never taken from form data or included in diagnostics. Bootstrap uses the
|
|
264
|
+
policy on its transaction-bound service, and registers password-management
|
|
265
|
+
permissions before seeding the owner's grants.
|
|
266
|
+
|
|
246
267
|
`resolveApplicationId()` and `runtimeConfigurationFingerprint()` (root entry)
|
|
247
268
|
are the canonical app ID and secret-free configuration fingerprint shared by
|
|
248
269
|
the web health route and process managers.
|
|
@@ -9,7 +9,7 @@ import { resolveApplicationRuntime } from "@happyvertical/smrt-config";
|
|
|
9
9
|
import { SCHEDULED_JOB_QUEUE, ScheduleRunner, TaskRunner } from "@happyvertical/smrt-jobs";
|
|
10
10
|
import { Person, ProfileTypeCollection } from "@happyvertical/smrt-profiles";
|
|
11
11
|
import { withSystemContext } from "@happyvertical/smrt-tenancy";
|
|
12
|
-
import { DEFAULT_ROLE_SLUGS, MembershipCollection, MembershipStatus, PermissionResolver, RoleCollection, SessionCollection, SessionService, TenantCollection, TenantService, TenantStatus, UserCollection, UserStatus } from "@happyvertical/smrt-users";
|
|
12
|
+
import { DEFAULT_ROLE_SLUGS, MembershipCollection, MembershipStatus, PasswordCredentialService, PermissionResolver, RoleCollection, SessionCollection, SessionService, TenantCollection, TenantService, TenantStatus, UserCollection, UserStatus, ensurePasswordPermissionsRegistered } from "@happyvertical/smrt-users";
|
|
13
13
|
import { getDatabase } from "@happyvertical/sql";
|
|
14
14
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
15
15
|
import { chmodSync, closeSync, constants as constants$1, existsSync, lstatSync, mkdirSync, openSync, readFileSync, realpathSync, rmSync, writeFileSync } from "node:fs";
|
|
@@ -1725,6 +1725,7 @@ async function initializeLocalApplicationRuntime(options) {
|
|
|
1725
1725
|
backgroundJobs: options.backgroundJobs === true,
|
|
1726
1726
|
paidCapabilities: options.paidCapabilities === true,
|
|
1727
1727
|
ownerTenant,
|
|
1728
|
+
passwordPolicy: options.passwordPolicy,
|
|
1728
1729
|
now: options.now ?? (() => /* @__PURE__ */ new Date()),
|
|
1729
1730
|
canonicalSourceRoot
|
|
1730
1731
|
});
|
|
@@ -1766,6 +1767,7 @@ var InitializedLocalApplicationRuntime = class {
|
|
|
1766
1767
|
bootstrapTtlSeconds;
|
|
1767
1768
|
sessionTtlSeconds;
|
|
1768
1769
|
ownerTenant;
|
|
1770
|
+
passwordPolicy;
|
|
1769
1771
|
now;
|
|
1770
1772
|
canonicalSourceRoot;
|
|
1771
1773
|
constructor(state) {
|
|
@@ -1776,6 +1778,7 @@ var InitializedLocalApplicationRuntime = class {
|
|
|
1776
1778
|
this.bootstrapTtlSeconds = state.bootstrapTtlSeconds;
|
|
1777
1779
|
this.sessionTtlSeconds = state.sessionTtlSeconds;
|
|
1778
1780
|
this.ownerTenant = state.ownerTenant;
|
|
1781
|
+
this.passwordPolicy = state.passwordPolicy;
|
|
1779
1782
|
this.backgroundJobsEnabled = state.backgroundJobs;
|
|
1780
1783
|
this.paidCapabilitiesEnabled = state.paidCapabilities;
|
|
1781
1784
|
this.now = state.now;
|
|
@@ -1818,6 +1821,7 @@ var InitializedLocalApplicationRuntime = class {
|
|
|
1818
1821
|
const now = this.now();
|
|
1819
1822
|
const nowIso = now.toISOString();
|
|
1820
1823
|
if (!await isBootstrapTokenClaimable(this.db, tokenHash, nowIso)) await throwBootstrapClaimFailure(this.db, now);
|
|
1824
|
+
if (input.password) ensurePasswordPermissionsRegistered();
|
|
1821
1825
|
await (await RoleCollection.create({ db: this.db })).seedSystemRoles({ seedPermissions: true });
|
|
1822
1826
|
return this.db.transaction(async (tx) => {
|
|
1823
1827
|
if ((await tx.query(`UPDATE ${BOOTSTRAP_TABLE}
|
|
@@ -1828,7 +1832,7 @@ var InitializedLocalApplicationRuntime = class {
|
|
|
1828
1832
|
AND expires_at > ?
|
|
1829
1833
|
RETURNING expires_at`, nowIso, tokenHash, nowIso)).rows.length === 0) await throwBootstrapClaimFailure(tx, now);
|
|
1830
1834
|
if (await findExistingOwner(tx)) throw new LocalRuntimeError("bootstrap_claimed", "The local owner has already been claimed.");
|
|
1831
|
-
return createLocalOwnerRecords(tx, input, this.sessionTtlSeconds, this.ownerTenant);
|
|
1835
|
+
return createLocalOwnerRecords(tx, input, this.sessionTtlSeconds, this.ownerTenant, this.passwordPolicy);
|
|
1832
1836
|
});
|
|
1833
1837
|
}
|
|
1834
1838
|
/** Restore the normal server-side session created by owner bootstrap. */
|
|
@@ -1918,7 +1922,7 @@ var InitializedLocalApplicationRuntime = class {
|
|
|
1918
1922
|
return createHmac("sha256", (await validateApplicationSecret(this.paths.applicationSecret, this.canonicalSourceRoot)).trim()).update(token).digest("hex");
|
|
1919
1923
|
}
|
|
1920
1924
|
};
|
|
1921
|
-
async function createLocalOwnerRecords(db, input, sessionTtlSeconds, ownerTenant) {
|
|
1925
|
+
async function createLocalOwnerRecords(db, input, sessionTtlSeconds, ownerTenant, passwordPolicy) {
|
|
1922
1926
|
const existingTenant = await (await TenantCollection.create({ db })).findBySlug(ownerTenant.slug);
|
|
1923
1927
|
const memberships = await MembershipCollection.create({ db });
|
|
1924
1928
|
if (existingTenant) await assertAdoptableOwnerTenant(existingTenant, ownerTenant, memberships);
|
|
@@ -1972,7 +1976,25 @@ async function createLocalOwnerRecords(db, input, sessionTtlSeconds, ownerTenant
|
|
|
1972
1976
|
ttl: sessionTtlSeconds,
|
|
1973
1977
|
userAgent: input.userAgent,
|
|
1974
1978
|
ipAddress: input.ipAddress,
|
|
1975
|
-
data: { localOwner: true }
|
|
1979
|
+
data: { localOwner: true },
|
|
1980
|
+
authMethod: input.password ? "password" : "local-bootstrap"
|
|
1981
|
+
});
|
|
1982
|
+
if (input.password) await (await PasswordCredentialService.create({
|
|
1983
|
+
db,
|
|
1984
|
+
sessionTtl: sessionTtlSeconds,
|
|
1985
|
+
password: passwordPolicy
|
|
1986
|
+
})).setPassword({
|
|
1987
|
+
actor: {
|
|
1988
|
+
user,
|
|
1989
|
+
membership,
|
|
1990
|
+
permissions: [],
|
|
1991
|
+
tenantId: requireId(tenant.id, "Tenant"),
|
|
1992
|
+
sessionId: requireId(session.id, "Session"),
|
|
1993
|
+
authMethod: "password",
|
|
1994
|
+
parent: null
|
|
1995
|
+
},
|
|
1996
|
+
userId,
|
|
1997
|
+
password: input.password
|
|
1976
1998
|
});
|
|
1977
1999
|
return Object.freeze({
|
|
1978
2000
|
profileId: requireId(person.id, "Person"),
|
|
@@ -2750,4 +2772,4 @@ function isDirectoryNotEmpty(error) {
|
|
|
2750
2772
|
//#endregion
|
|
2751
2773
|
export { reclaimStaleRecord as A, deepFrozenPlainCopy as B, findInstalledPackage as C, processExists as D, lockOwnerPid as E, LOCAL_MCP_TOKEN_PRINCIPAL as F, initializeDeployedApplicationRuntime as G, resolveBoundMembershipPermissions as H, LOCAL_MCP_TOKEN_TABLE as I, isSessionTenantAuthorized as K, MAX_LOCAL_MCP_TOKEN_TTL_SECONDS as L, runtimeConfigurationFingerprint as M, DEFAULT_LOCAL_MCP_TOKEN_TTL_SECONDS as N, withOperationLock as O, LOCAL_MCP_TOKEN_PREFIX as P, isLocalMcpTokenPrincipal as R, createProviderReadinessProbe as S, isStaleOperationLock as T, DeployedRuntimeCleanupError as U, ownValue as V, DeployedRuntimeError as W, MAX_RUNTIME_DIAGNOSTIC_TOOLS as _, openLocalMcpTokenStore as a, projectRuntimeDiagnostics as b, validateApplicationId as c, readActiveWriterLease as d, ONBOARDING_HANDOFF_FILES as f, MAX_RUNTIME_DIAGNOSTIC_ERRORS as g, resolveApplicationStateRoot as h, initializeLocalApplicationRuntime as i, resolveApplicationId as j, RECLAIM_MUTEX_FILE as k, validateLocalDatabaseStorage as l, removeOnboardingHandoff as m, MIGRATION_FAILED_MESSAGE as n, prepareLocalDatabaseStorage as o, prepareApplicationStateRoot as p, encodeApplicationId as r, resolveLocalRuntimePaths as s, LocalRuntimeError as t, acquireWriterLease as u, RUNTIME_DIAGNOSTICS_SCHEMA_VERSION as v, resolveReadinessModule as w, PROVIDER_READINESS_SETTINGS as x, RUNTIME_WORKER_FRESHNESS_SECONDS as y, PlainDataError as z };
|
|
2752
2774
|
|
|
2753
|
-
//# sourceMappingURL=src-
|
|
2775
|
+
//# sourceMappingURL=src-C98Cqurb.js.map
|