@supacloud/lite 0.27.1 → 0.28.0

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/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.28.0](https://github.com/vibeunion/supacloud/compare/supacloud-lite-v0.27.1...supacloud-lite-v0.28.0) (2026-10-14)
4
+
5
+
6
+ ### Features
7
+
8
+ * **lite:** add offline auth user provisioning ([#1911](https://github.com/vibeunion/supacloud/issues/1911)) ([e9c8931](https://github.com/vibeunion/supacloud/commit/e9c89319cf39d9fe2d71ceac9ab76e6856bb5d84))
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * **lite:** normalize filesystem storage roots ([#1902](https://github.com/vibeunion/supacloud/issues/1902)) ([f1b5141](https://github.com/vibeunion/supacloud/commit/f1b5141c1e831e68aaf94b505909c9e4942a42df))
14
+ * **lite:** report effective local auth configuration in doctor ([#1907](https://github.com/vibeunion/supacloud/issues/1907)) ([c167617](https://github.com/vibeunion/supacloud/commit/c1676176bdd5a2c057114474186570b7e6d5d0dd))
15
+
3
16
  ## [0.27.1](https://github.com/vibeunion/supacloud/compare/supacloud-lite-v0.27.0...supacloud-lite-v0.27.1) (2026-10-14)
4
17
 
5
18
 
package/README.md CHANGED
@@ -159,6 +159,7 @@ supacloud-lite start
159
159
  supacloud-lite migrate
160
160
  supacloud-lite status
161
161
  supacloud-lite keys [--service-role]
162
+ supacloud-lite auth create-user --email <email> --password-stdin [--email-confirm] [--json]
162
163
  supacloud-lite gen types [-o database.types.ts]
163
164
  supacloud-lite db reset
164
165
  supacloud-lite db diff [-f migration_name]
@@ -174,6 +175,21 @@ supacloud-lite version
174
175
 
175
176
  首次初始化或 state 目录不存在/为空时,先运行 `supacloud-lite migrate`。`db reset` 只接受已经初始化且保留有效 `secrets.json` 标记的 state;它不会为 reset 创建或覆盖项目 secrets。
176
177
 
178
+ #### 创建本地 Auth 账号
179
+
180
+ 先停止项目服务,再从受保护的文件或密码管理器管道提供密码:
181
+
182
+ ```sh
183
+ supacloud-lite auth create-user --project-dir ./my-project \
184
+ --email operator@example.com --password-stdin --email-confirm --json < /secure/password.txt
185
+ ```
186
+
187
+ 不要将密码写进命令行参数或 shell 历史;文件应限制为当前用户可读,并按自己的凭据管理流程清理。命令只接受 stdin 的一行 UTF-8 密码(最多 4096 字节),移除末尾一个 LF/CRLF,保留空格。交互终端输入和 `--password` 参数会被拒绝。
188
+
189
+ 这是离线、本地账号创建操作,不连接远程 Auth API,不执行待应用的业务迁移、seed、函数或 webhook;请先用 `migrate` 初始化应用 schema。即使关闭公开注册,也可以由本机管理员创建账号。邮箱默认未确认;只有管理员已核实邮箱时才加 `--email-confirm`。未确认账号能否登录仍受项目的邮箱确认配置控制,命令不会发送确认邮件。
190
+
191
+ 命令遵守有效密码长度策略,拒绝重复邮箱(不覆盖密码)、`--memory`、禁用 Auth、外部身份模式及占用中的数据目录。输出仅含用户 ID、邮箱和确认状态,不含密码、项目密钥或登录 token。该账号使用普通 `authenticated` 角色;业务权限仍由应用自己的成员关系和 RLS 管理。
192
+
177
193
  `db diff` / `db pull` 只读检查现有数据库,不会初始化 live backend 或自动应用待执行迁移;已应用历史必须与本地迁移精确一致。生成的 DDL 先在不含 seed 的临时影子数据库中重放并核对受支持的 Catalog。检测到不能完整重建的 view/function/trigger/policy、权限、RLS 或非追加 enum 变更时拒绝生成,改用官方 Supabase pg-delta;这不是完整 PostgreSQL Catalog 覆盖。
178
194
 
179
195
  `db pull` 默认写入 `.supacloud-lite/schema-drafts`,不修改迁移账本。仅对已审核且已存在于数据库的变更使用 `--baseline`:它记录账本而不执行 DDL,提交确认后才发布到迁移目录,禁止覆盖已有文件。若失败后留下 `.sql.pending`,停止启动/迁移,保留文件并检查对应账本版本与 SQL;只有确认匹配提交后才能发布该文件。不要猜测提交结果或直接重放捕获的 DDL。库调用方在 `baseline: false` 时也应把 `migrationsDir` 指向草稿目录。恢复步骤及文件/数据库非原子边界见仓库 `docs/select-agent-backend.md`。
@@ -599,6 +615,7 @@ supacloud-lite start
599
615
  supacloud-lite migrate
600
616
  supacloud-lite status
601
617
  supacloud-lite keys [--service-role]
618
+ supacloud-lite auth create-user --email <email> --password-stdin [--email-confirm] [--json]
602
619
  supacloud-lite gen types [-o database.types.ts]
603
620
  supacloud-lite db reset
604
621
  supacloud-lite db diff [-f migration_name]
@@ -614,6 +631,21 @@ supacloud-lite version
614
631
 
615
632
  Run `supacloud-lite migrate` first when initializing a project or when the state directory is missing or empty. `db reset` only accepts initialized state with a valid `secrets.json` marker; it never creates or replaces project secrets for a reset.
616
633
 
634
+ #### Create a Local Auth User
635
+
636
+ Stop the project server first, then supply the password through a protected file or password-manager pipe:
637
+
638
+ ```sh
639
+ supacloud-lite auth create-user --project-dir ./my-project \
640
+ --email operator@example.com --password-stdin --email-confirm --json < /secure/password.txt
641
+ ```
642
+
643
+ Keep passwords out of command arguments and shell history. Restrict the file to its owner and remove it according to your credential-handling policy. The command accepts one UTF-8 password line on stdin (at most 4096 bytes), removes one trailing LF/CRLF, and preserves spaces. Interactive terminal input and `--password` arguments are rejected.
644
+
645
+ This is an offline, local operation: it does not contact a remote Auth API or run pending application migrations, seed, functions, or webhooks. Initialize application schemas with `migrate` first. Local administrators can provision accounts even when public signup is disabled. Email is unconfirmed by default; use `--email-confirm` only after verifying the address. Login eligibility for unconfirmed accounts still follows the project's email-confirmation settings; this command does not send confirmation mail.
646
+
647
+ The command enforces the effective password-length policy and rejects duplicate emails without changing passwords, `--memory`, disabled Auth, external identity, and occupied data directories. Output contains only the user ID, email, and confirmation status, never passwords, project keys, or session tokens. Accounts have the ordinary `authenticated` role; application membership and RLS still govern business permissions.
648
+
617
649
  Common flags:
618
650
 
619
651
  - `--project-dir`: the project directory containing `supabase/`
package/dist/cli.js CHANGED
@@ -8,7 +8,7 @@ import { dirname as dirname8, join as join10, resolve as resolve6 } from "path";
8
8
  // package.json
9
9
  var package_default = {
10
10
  name: "@supacloud/lite",
11
- version: "0.27.1",
11
+ version: "0.28.0",
12
12
  description: "Bun-native, single-project Supabase-compatible backend powered by PGlite or native PostgreSQL",
13
13
  type: "module",
14
14
  license: "Apache-2.0",
@@ -13728,12 +13728,20 @@ async function inspectPostgresExtensions(engine, source) {
13728
13728
  }
13729
13729
 
13730
13730
  // src/runtime/node/native/readiness.ts
13731
- function liteCapabilities(engine, replicationProfile) {
13731
+ function liteCapabilities(engine, replicationProfile, authEnabled = true) {
13732
13732
  const extensionSource = engine === "native" ? "native-postgresql" : "pglite-bundled";
13733
13733
  const common = {
13734
13734
  graphql: { status: "unverified", extension: "pg_graphql", reason: "DATABASE_NOT_INSPECTED" },
13735
13735
  runtime_mode: "development",
13736
- identity: { mode: "local", verification: "built-in" },
13736
+ identity: {
13737
+ mode: "local",
13738
+ verification: "built-in",
13739
+ local_auth: {
13740
+ status: authEnabled ? "enabled" : "disabled",
13741
+ reason: authEnabled ? "LOCAL_AUTH_ENABLED" : "AUTH_DISABLED",
13742
+ verification: "configuration-only"
13743
+ }
13744
+ },
13737
13745
  migrations: { formats: ["flat-sql", "timestamp-folder"], content_check: "supported", target_bindings: "supported" },
13738
13746
  project_release_manifests: "unsupported",
13739
13747
  postgres_extensions: {
@@ -14521,7 +14529,7 @@ function isNotFound(error) {
14521
14529
 
14522
14530
  // src/project-runtime.ts
14523
14531
  import { chmod, link as link2, lstat as lstat2, mkdir as mkdir5, readFile as readFile7, realpath as realpath2, unlink as unlink2, writeFile as writeFile5 } from "fs/promises";
14524
- import { dirname as dirname6, isAbsolute, join as join8, parse, relative, resolve as resolve4 } from "path";
14532
+ import { dirname as dirname6, isAbsolute as isAbsolute2, join as join8, parse, relative as relative2, resolve as resolve4 } from "path";
14525
14533
  import { pathToFileURL as pathToFileURL3 } from "url";
14526
14534
 
14527
14535
  // src/runtime/node/bun-server.ts
@@ -14573,16 +14581,18 @@ async function serveBun(backend, opts = {}) {
14573
14581
 
14574
14582
  // src/runtime/node/fs-driver.ts
14575
14583
  import { mkdir as mkdir3, readFile as readFile4, rename, rm as rm2, writeFile as writeFile3 } from "fs/promises";
14576
- import { dirname as dirname4, join as join5, normalize, sep } from "path";
14584
+ import { dirname as dirname4, isAbsolute, join as join5, relative, resolve as resolvePath, sep } from "path";
14577
14585
 
14578
14586
  class FsStorageDriver {
14579
14587
  root;
14580
14588
  constructor(root) {
14581
14589
  this.root = root;
14590
+ this.root = resolvePath(root);
14582
14591
  }
14583
14592
  resolve(key) {
14584
- const path = normalize(join5(this.root, key));
14585
- if (!path.startsWith(normalize(this.root) + sep)) {
14593
+ const path = join5(this.root, key);
14594
+ const relativePath = relative(this.root, path);
14595
+ if (!relativePath || relativePath === ".." || relativePath.startsWith(`..${sep}`) || isAbsolute(relativePath)) {
14586
14596
  throw new Error(`invalid storage key: ${key}`);
14587
14597
  }
14588
14598
  return path;
@@ -14964,10 +14974,10 @@ var RESET_INITIALIZATION_ERROR = 'db reset requires initialized state; run "supa
14964
14974
  var RESET_INVALID_SECRETS_ERROR = "db reset requires a valid project secrets marker; restore the state before retrying";
14965
14975
  function resolveProjectPaths(options = {}) {
14966
14976
  const projectDir = resolve4(options.projectDir ?? process.cwd());
14967
- const stateDir = resolvePath(projectDir, options.stateDir ?? process.env.SUPACLOUD_LITE_STATE_DIR ?? ".supacloud-lite");
14977
+ const stateDir = resolvePath2(projectDir, options.stateDir ?? process.env.SUPACLOUD_LITE_STATE_DIR ?? ".supacloud-lite");
14968
14978
  const databaseEngine = resolveDatabaseEngine(options.engine, options.memory);
14969
- const dataDir = options.memory ? undefined : resolvePath(projectDir, options.dataDir ?? process.env.SUPACLOUD_LITE_DATA_DIR ?? join8(stateDir, databaseEngine === "native" ? "pgdata" : "db"));
14970
- const storageDir = resolvePath(projectDir, options.storageDir ?? process.env.SUPACLOUD_LITE_STORAGE_DIR ?? join8(stateDir, "storage"));
14979
+ const dataDir = options.memory ? undefined : resolvePath2(projectDir, options.dataDir ?? process.env.SUPACLOUD_LITE_DATA_DIR ?? join8(stateDir, databaseEngine === "native" ? "pgdata" : "db"));
14980
+ const storageDir = resolvePath2(projectDir, options.storageDir ?? process.env.SUPACLOUD_LITE_STORAGE_DIR ?? join8(stateDir, "storage"));
14971
14981
  return {
14972
14982
  projectDir,
14973
14983
  stateDir,
@@ -15001,8 +15011,8 @@ async function assertResetPathsSafe(paths) {
15001
15011
  ];
15002
15012
  for (const [label, targetPath] of targets) {
15003
15013
  const target = resolve4(targetPath);
15004
- const relativePath = relative(stateDir, target);
15005
- if (!relativePath || relativePath.startsWith("..") || isAbsolute(relativePath)) {
15014
+ const relativePath = relative2(stateDir, target);
15015
+ if (!relativePath || relativePath.startsWith("..") || isAbsolute2(relativePath)) {
15006
15016
  throw new Error(`refusing to reset ${label} path outside the state directory: ${target}`);
15007
15017
  }
15008
15018
  await assertResetTargetCanonical(stateDir, canonicalStateDir, target, label);
@@ -15049,9 +15059,9 @@ async function assertResetTargetCanonical(stateDir, canonicalStateDir, target, l
15049
15059
  current = parent;
15050
15060
  }
15051
15061
  const existingAncestor = await nearestExistingAncestor(target);
15052
- const canonicalTarget = resolve4(await realpath2(existingAncestor), relative(existingAncestor, target));
15053
- const canonicalRelative = relative(canonicalStateDir, canonicalTarget);
15054
- if (!canonicalRelative || canonicalRelative.startsWith("..") || isAbsolute(canonicalRelative)) {
15062
+ const canonicalTarget = resolve4(await realpath2(existingAncestor), relative2(existingAncestor, target));
15063
+ const canonicalRelative = relative2(canonicalStateDir, canonicalTarget);
15064
+ if (!canonicalRelative || canonicalRelative.startsWith("..") || isAbsolute2(canonicalRelative)) {
15055
15065
  throw new Error(`refusing to reset ${label} path outside the canonical state directory: ${target}`);
15056
15066
  }
15057
15067
  }
@@ -15343,8 +15353,8 @@ async function loadWebhooks(projectDir) {
15343
15353
  throw error;
15344
15354
  }
15345
15355
  }
15346
- function resolvePath(projectDir, path) {
15347
- return isAbsolute(path) ? path : resolve4(projectDir, path);
15356
+ function resolvePath2(projectDir, path) {
15357
+ return isAbsolute2(path) ? path : resolve4(projectDir, path);
15348
15358
  }
15349
15359
  function randomHex(bytes) {
15350
15360
  const value = crypto.getRandomValues(new Uint8Array(bytes));
@@ -15390,7 +15400,7 @@ async function findEphemeralPort(host = "127.0.0.1") {
15390
15400
 
15391
15401
  // src/snapshot.ts
15392
15402
  import { chmod as chmod2, copyFile, lstat as lstat3, mkdir as mkdir6, mkdtemp, readdir as readdir3, readFile as readFile8, rename as rename2, rm as rm5, writeFile as writeFile6 } from "fs/promises";
15393
- import { dirname as dirname7, join as join9, parse as parse2, relative as relative2, resolve as resolve5, sep as sep2 } from "path";
15403
+ import { dirname as dirname7, join as join9, parse as parse2, relative as relative3, resolve as resolve5, sep as sep2 } from "path";
15394
15404
  import { create as createTar, extract as extractTar2 } from "tar";
15395
15405
  var SNAPSHOT_FORMAT = "supacloud-lite-snapshot";
15396
15406
  var SNAPSHOT_VERSION = 1;
@@ -15498,10 +15508,10 @@ async function restoreSnapshot(options) {
15498
15508
  await mkdir6(stateStage, { recursive: true });
15499
15509
  await copyEntry(join9(payloadRoot, "secrets.json"), join9(stateStage, "secrets.json"));
15500
15510
  if (paths.dataDir && isWithin(paths.stateDir, paths.dataDir)) {
15501
- await copyEntry(join9(payloadRoot, "database"), join9(stateStage, relative2(paths.stateDir, paths.dataDir)));
15511
+ await copyEntry(join9(payloadRoot, "database"), join9(stateStage, relative3(paths.stateDir, paths.dataDir)));
15502
15512
  }
15503
15513
  if (options.storageBackend === "fs" && isWithin(paths.stateDir, paths.storageDir)) {
15504
- await copyEntry(join9(payloadRoot, "storage"), join9(stateStage, relative2(paths.stateDir, paths.storageDir)));
15514
+ await copyEntry(join9(payloadRoot, "storage"), join9(stateStage, relative3(paths.stateDir, paths.storageDir)));
15505
15515
  }
15506
15516
  const swaps = [];
15507
15517
  try {
@@ -15816,6 +15826,89 @@ async function waitForShutdown(closeProject, signalSource = process) {
15816
15826
  await closeProject();
15817
15827
  }
15818
15828
 
15829
+ // src/auth-cli.ts
15830
+ async function createLocalAuthUser(options) {
15831
+ if (options.memory)
15832
+ throw new Error("auth create-user requires a persistent project; --memory is not supported");
15833
+ const email = options.email?.trim().toLowerCase();
15834
+ if (!email || email.length > 254 || !/^[^\s@\x00-\x1f\x7f]+@[^\s@\x00-\x1f\x7f]+\.[^\s@\x00-\x1f\x7f]+$/.test(email)) {
15835
+ throw new Error("auth create-user requires a valid --email");
15836
+ }
15837
+ if (!options.passwordStdin)
15838
+ throw new Error("auth create-user requires --password-stdin; passwords are not accepted as arguments");
15839
+ if (process.stdin.isTTY)
15840
+ throw new Error("--password-stdin requires piped or redirected input; terminal input is not accepted");
15841
+ const paths = resolveProjectPaths(options);
15842
+ const config = loadProjectConfig(paths.projectDir, process.env, options.runtimeMode);
15843
+ if (config.auth.enabled === false)
15844
+ throw new Error("cannot create a local user: Auth is disabled in config.toml");
15845
+ if (options.externalIdentity || options.identityModule || config.lite.identityModule) {
15846
+ throw new Error("cannot create a local user: the project uses external identity");
15847
+ }
15848
+ await assertDataDirUnlocked(paths.dataDir);
15849
+ const password = await readPassword();
15850
+ const project = await createProjectBackend({
15851
+ ...options,
15852
+ applyMigrations: false,
15853
+ includeSeed: false,
15854
+ includeFunctions: false,
15855
+ includeWebhooks: false,
15856
+ includeIdentity: false,
15857
+ graphql: { enabled: false },
15858
+ storageBackend: "memory",
15859
+ startRuntimeServices: false,
15860
+ log: () => {}
15861
+ });
15862
+ try {
15863
+ const settings = await loadAuthSettings(project.backend.db, project.config.auth.settings);
15864
+ if (password.length < settings.minPasswordLength) {
15865
+ throw new Error(`password must be at least ${settings.minPasswordLength} characters`);
15866
+ }
15867
+ const existing = await project.backend.db.query("select id from auth.users where email = $1", [email]);
15868
+ if (existing.rows.length > 0)
15869
+ throw new Error("an Auth user with this email already exists; no changes made");
15870
+ const response = await project.backend.fetch("http://local/auth/v1/admin/users", {
15871
+ method: "POST",
15872
+ headers: {
15873
+ apikey: project.backend.serviceRoleKey,
15874
+ authorization: `Bearer ${project.backend.serviceRoleKey}`,
15875
+ "content-type": "application/json"
15876
+ },
15877
+ body: JSON.stringify({ email, password, email_confirm: options.emailConfirm === true })
15878
+ });
15879
+ if (!response.ok)
15880
+ throw new Error(`local Auth user creation failed (HTTP ${response.status})`);
15881
+ const user = await response.json();
15882
+ if (!isRecord(user) || typeof user.id !== "string" || typeof user.email !== "string") {
15883
+ throw new Error("local Auth returned an invalid user response");
15884
+ }
15885
+ return { id: user.id, email: user.email, email_confirmed: typeof user.email_confirmed_at === "string" };
15886
+ } finally {
15887
+ await project.backend.close();
15888
+ }
15889
+ }
15890
+ async function readPassword() {
15891
+ const chunks = [];
15892
+ let length = 0;
15893
+ for await (const chunk of Bun.stdin.stream()) {
15894
+ length += chunk.byteLength;
15895
+ if (length > 4098)
15896
+ throw new Error("password input exceeds 4096 bytes");
15897
+ chunks.push(chunk);
15898
+ }
15899
+ let password;
15900
+ try {
15901
+ password = new TextDecoder("utf-8", { fatal: true }).decode(Buffer.concat(chunks)).replace(/\r?\n$/, "");
15902
+ } catch {
15903
+ throw new Error("password input must be valid UTF-8");
15904
+ }
15905
+ if (!password || /[\r\n\x00]/.test(password))
15906
+ throw new Error("password input must contain one non-empty line");
15907
+ if (Buffer.byteLength(password, "utf8") > 4096)
15908
+ throw new Error("password input exceeds 4096 bytes");
15909
+ return password;
15910
+ }
15911
+
15819
15912
  // src/cli.ts
15820
15913
  function parseArgs(argv) {
15821
15914
  const args = [...argv];
@@ -15896,7 +15989,15 @@ function parseArgs(argv) {
15896
15989
  options.force = true;
15897
15990
  else if (argument === "--json")
15898
15991
  options.json = true;
15899
- else if (argument === "--version") {
15992
+ else if (argument === "--email")
15993
+ options.email = next();
15994
+ else if (argument === "--password-stdin")
15995
+ options.passwordStdin = true;
15996
+ else if (argument === "--email-confirm")
15997
+ options.emailConfirm = true;
15998
+ else if (argument.startsWith("--password")) {
15999
+ throw new Error("password arguments are not supported; use --password-stdin");
16000
+ } else if (argument === "--version") {
15900
16001
  console.log(package_default.version);
15901
16002
  process.exit(0);
15902
16003
  } else if (argument === "--help" || argument === "-h") {
@@ -15911,7 +16012,20 @@ function parseArgs(argv) {
15911
16012
  }
15912
16013
  async function main() {
15913
16014
  const options = parseArgs(process.argv.slice(2));
16015
+ if (options.command !== "auth" && (options.email !== undefined || options.passwordStdin || options.emailConfirm)) {
16016
+ throw new Error("--email, --password-stdin and --email-confirm are only supported by auth create-user");
16017
+ }
15914
16018
  const paths = resolveProjectPaths(options);
16019
+ if (options.command === "auth") {
16020
+ if (options.positionals.length !== 1 || options.positionals[0] !== "create-user") {
16021
+ throw new Error("usage: auth create-user --email <email> --password-stdin [--email-confirm] [--json]");
16022
+ }
16023
+ const user = await createLocalAuthUser(options);
16024
+ await writeStandardOutput(options.json ? `${JSON.stringify(user, null, 2)}
16025
+ ` : `Created Auth user ${user.id} (${user.email}); email confirmed: ${user.email_confirmed ? "yes" : "no"}
16026
+ `);
16027
+ return;
16028
+ }
15915
16029
  if (options.command === "version" || options.command === "--version") {
15916
16030
  await writeStandardOutput(`${package_default.version}
15917
16031
  `);
@@ -15991,10 +16105,18 @@ ${privilegedKey}
15991
16105
  if (options.command === "doctor") {
15992
16106
  const config = loadProjectConfig(paths.projectDir, process.env, options.runtimeMode);
15993
16107
  const replication = resolveNativeReplicationOptions(options, paths.databaseEngine);
15994
- const report = liteCapabilities(paths.databaseEngine, replication?.profile);
16108
+ const report = liteCapabilities(paths.databaseEngine, replication?.profile, config.auth.enabled !== false);
15995
16109
  report.runtime_mode = config.lite.runtimeMode;
15996
16110
  if (options.identityModule ?? config.lite.identityModule) {
15997
- report.identity = { mode: "external", verification: "unverified" };
16111
+ report.identity = {
16112
+ mode: "external",
16113
+ verification: "unverified",
16114
+ local_auth: {
16115
+ status: "disabled",
16116
+ reason: "EXTERNAL_IDENTITY_CONFIGURED",
16117
+ verification: "configuration-only"
16118
+ }
16119
+ };
15998
16120
  }
15999
16121
  if (paths.dataDir && existsSync5(join10(paths.dataDir, "PG_VERSION"))) {
16000
16122
  const engine = paths.databaseEngine === "native" ? await createNativeEngine({ dataDir: paths.dataDir, installDir: options.postgresDir, log: quietLog, replication }) : await createPgliteEngine(paths.dataDir);
@@ -16294,6 +16416,7 @@ async function printDoctor(report) {
16294
16416
  output.push(`graphql: ${report.graphql.status} (${report.graphql.version ?? report.graphql.reason ?? "pg_graphql"})`);
16295
16417
  output.push(`postgres_extensions: ${report.postgres_extensions.status} ` + `(${report.postgres_extensions.source}, ${report.postgres_extensions.available.length} available, ` + `${report.postgres_extensions.installed.length} installed)`);
16296
16418
  output.push(`identity: ${report.identity.mode} (${report.identity.verification})`);
16419
+ output.push(`local_auth: ${report.identity.local_auth.status} (${report.identity.local_auth.reason}, configuration-only)`);
16297
16420
  output.push(`migration_formats: ${report.migrations.formats.join(", ")}`);
16298
16421
  if (report.powersync_readiness) {
16299
16422
  output.push(`powersync_ready: ${report.powersync_readiness.ready}`);
@@ -16330,6 +16453,7 @@ Commands:
16330
16453
  status list applied migrations
16331
16454
  keys print the anon key
16332
16455
  keys --service-role also print the privileged service_role key
16456
+ auth create-user create a local Auth user while the project server is stopped
16333
16457
  gen types emit Supabase-shaped TypeScript database types
16334
16458
  db reset reset initialized database/storage and re-run migrations
16335
16459
  db diff print schema changes outside migrations
@@ -16364,7 +16488,10 @@ Options:
16364
16488
  --replication-tls-cert <p> PostgreSQL TLS certificate
16365
16489
  --replication-tls-key <p> PostgreSQL TLS private key
16366
16490
  --memory use an in-memory PGlite database
16367
- --json emit machine-readable doctor/migrate/status output
16491
+ --json emit machine-readable doctor/migrate/status/auth output
16492
+ --email <email> auth create-user: account email
16493
+ --password-stdin auth create-user: read one password line from redirected stdin
16494
+ --email-confirm auth create-user: explicitly mark the email as confirmed
16368
16495
  --runtime-mode development (default) or strict
16369
16496
  --postgres-dir operator-managed PostgreSQL installation (native only)
16370
16497
  --identity-module trusted external identity bridge module
package/dist/index.js CHANGED
@@ -88,7 +88,7 @@ function randomToken(bytes = 32) {
88
88
  // package.json
89
89
  var package_default = {
90
90
  name: "@supacloud/lite",
91
- version: "0.27.1",
91
+ version: "0.28.0",
92
92
  description: "Bun-native, single-project Supabase-compatible backend powered by PGlite or native PostgreSQL",
93
93
  type: "module",
94
94
  license: "Apache-2.0",
@@ -11736,16 +11736,18 @@ class S3StorageDriver {
11736
11736
  }
11737
11737
  // src/runtime/node/fs-driver.ts
11738
11738
  import { mkdir as mkdir2, readFile as readFile2, rename, rm, writeFile } from "fs/promises";
11739
- import { dirname as dirname2, join, normalize, sep } from "path";
11739
+ import { dirname as dirname2, isAbsolute, join, relative, resolve as resolvePath, sep } from "path";
11740
11740
 
11741
11741
  class FsStorageDriver {
11742
11742
  root;
11743
11743
  constructor(root) {
11744
11744
  this.root = root;
11745
+ this.root = resolvePath(root);
11745
11746
  }
11746
11747
  resolve(key) {
11747
- const path = normalize(join(this.root, key));
11748
- if (!path.startsWith(normalize(this.root) + sep)) {
11748
+ const path = join(this.root, key);
11749
+ const relativePath = relative(this.root, path);
11750
+ if (!relativePath || relativePath === ".." || relativePath.startsWith(`..${sep}`) || isAbsolute(relativePath)) {
11749
11751
  throw new Error(`invalid storage key: ${key}`);
11750
11752
  }
11751
11753
  return path;
@@ -12937,12 +12939,20 @@ function removeStalePidFile(pidPath) {
12937
12939
  } catch {}
12938
12940
  }
12939
12941
  // src/runtime/node/native/readiness.ts
12940
- function liteCapabilities(engine, replicationProfile) {
12942
+ function liteCapabilities(engine, replicationProfile, authEnabled = true) {
12941
12943
  const extensionSource = engine === "native" ? "native-postgresql" : "pglite-bundled";
12942
12944
  const common = {
12943
12945
  graphql: { status: "unverified", extension: "pg_graphql", reason: "DATABASE_NOT_INSPECTED" },
12944
12946
  runtime_mode: "development",
12945
- identity: { mode: "local", verification: "built-in" },
12947
+ identity: {
12948
+ mode: "local",
12949
+ verification: "built-in",
12950
+ local_auth: {
12951
+ status: authEnabled ? "enabled" : "disabled",
12952
+ reason: authEnabled ? "LOCAL_AUTH_ENABLED" : "AUTH_DISABLED",
12953
+ verification: "configuration-only"
12954
+ }
12955
+ },
12946
12956
  migrations: { formats: ["flat-sql", "timestamp-folder"], content_check: "supported", target_bindings: "supported" },
12947
12957
  project_release_manifests: "unsupported",
12948
12958
  postgres_extensions: {
@@ -13216,7 +13226,7 @@ async function inspectPostgresExtensions(engine, source) {
13216
13226
  }
13217
13227
  // src/project-runtime.ts
13218
13228
  import { chmod, link, lstat as lstat2, mkdir as mkdir4, readFile as readFile6, realpath as realpath2, unlink as unlink2, writeFile as writeFile4 } from "fs/promises";
13219
- import { dirname as dirname4, isAbsolute, join as join7, parse, relative, resolve as resolve3 } from "path";
13229
+ import { dirname as dirname4, isAbsolute as isAbsolute2, join as join7, parse, relative as relative2, resolve as resolve3 } from "path";
13220
13230
  import { pathToFileURL as pathToFileURL2 } from "url";
13221
13231
 
13222
13232
  // src/runtime/node/config-toml.ts
@@ -14159,10 +14169,10 @@ function isNotFound(error) {
14159
14169
  // src/project-runtime.ts
14160
14170
  function resolveProjectPaths(options = {}) {
14161
14171
  const projectDir = resolve3(options.projectDir ?? process.cwd());
14162
- const stateDir = resolvePath(projectDir, options.stateDir ?? process.env.SUPACLOUD_LITE_STATE_DIR ?? ".supacloud-lite");
14172
+ const stateDir = resolvePath2(projectDir, options.stateDir ?? process.env.SUPACLOUD_LITE_STATE_DIR ?? ".supacloud-lite");
14163
14173
  const databaseEngine = resolveDatabaseEngine(options.engine, options.memory);
14164
- const dataDir = options.memory ? undefined : resolvePath(projectDir, options.dataDir ?? process.env.SUPACLOUD_LITE_DATA_DIR ?? join7(stateDir, databaseEngine === "native" ? "pgdata" : "db"));
14165
- const storageDir = resolvePath(projectDir, options.storageDir ?? process.env.SUPACLOUD_LITE_STORAGE_DIR ?? join7(stateDir, "storage"));
14174
+ const dataDir = options.memory ? undefined : resolvePath2(projectDir, options.dataDir ?? process.env.SUPACLOUD_LITE_DATA_DIR ?? join7(stateDir, databaseEngine === "native" ? "pgdata" : "db"));
14175
+ const storageDir = resolvePath2(projectDir, options.storageDir ?? process.env.SUPACLOUD_LITE_STORAGE_DIR ?? join7(stateDir, "storage"));
14166
14176
  return {
14167
14177
  projectDir,
14168
14178
  stateDir,
@@ -14444,8 +14454,8 @@ async function loadWebhooks(projectDir) {
14444
14454
  throw error;
14445
14455
  }
14446
14456
  }
14447
- function resolvePath(projectDir, path) {
14448
- return isAbsolute(path) ? path : resolve3(projectDir, path);
14457
+ function resolvePath2(projectDir, path) {
14458
+ return isAbsolute2(path) ? path : resolve3(projectDir, path);
14449
14459
  }
14450
14460
  function randomHex(bytes) {
14451
14461
  const value = crypto.getRandomValues(new Uint8Array(bytes));
@@ -14490,7 +14500,7 @@ async function findEphemeralPort(host = "127.0.0.1") {
14490
14500
  }
14491
14501
  // src/snapshot.ts
14492
14502
  import { chmod as chmod2, copyFile, lstat as lstat3, mkdir as mkdir5, mkdtemp, readdir as readdir3, readFile as readFile7, rename as rename2, rm as rm4, writeFile as writeFile5 } from "fs/promises";
14493
- import { dirname as dirname5, join as join8, parse as parse2, relative as relative2, resolve as resolve4, sep as sep2 } from "path";
14503
+ import { dirname as dirname5, join as join8, parse as parse2, relative as relative3, resolve as resolve4, sep as sep2 } from "path";
14494
14504
  import { create as createTar, extract as extractTar2 } from "tar";
14495
14505
  var SNAPSHOT_FORMAT = "supacloud-lite-snapshot";
14496
14506
  var SNAPSHOT_VERSION = 1;
@@ -14598,10 +14608,10 @@ async function restoreSnapshot(options) {
14598
14608
  await mkdir5(stateStage, { recursive: true });
14599
14609
  await copyEntry(join8(payloadRoot, "secrets.json"), join8(stateStage, "secrets.json"));
14600
14610
  if (paths.dataDir && isWithin(paths.stateDir, paths.dataDir)) {
14601
- await copyEntry(join8(payloadRoot, "database"), join8(stateStage, relative2(paths.stateDir, paths.dataDir)));
14611
+ await copyEntry(join8(payloadRoot, "database"), join8(stateStage, relative3(paths.stateDir, paths.dataDir)));
14602
14612
  }
14603
14613
  if (options.storageBackend === "fs" && isWithin(paths.stateDir, paths.storageDir)) {
14604
- await copyEntry(join8(payloadRoot, "storage"), join8(stateStage, relative2(paths.stateDir, paths.storageDir)));
14614
+ await copyEntry(join8(payloadRoot, "storage"), join8(stateStage, relative3(paths.stateDir, paths.storageDir)));
14605
14615
  }
14606
14616
  const swaps = [];
14607
14617
  try {
@@ -9,8 +9,8 @@ export declare class FsStorageDriver implements StorageDriver {
9
9
  /**
10
10
  * Resolve a storage key to an absolute path inside the root.
11
11
  *
12
- * SECURITY: rejects keys that escape the root (e.g. `../`); the normalized
13
- * path must stay under `root` + separator or the key is refused.
12
+ * SECURITY: rejects keys that escape the root (e.g. `../`) or resolve to
13
+ * the root itself.
14
14
  *
15
15
  * @throws if the key would resolve outside the root directory.
16
16
  */
@@ -1 +1 @@
1
- {"version":3,"file":"fs-driver.d.ts","sourceRoot":"","sources":["../../../src/runtime/node/fs-driver.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAEhD;;;GAGG;AACH,qBAAa,eAAgB,YAAW,aAAa;IACvC,OAAO,CAAC,IAAI;gBAAJ,IAAI,EAAE,MAAM;IAEhC;;;;;;;OAOG;IACH,OAAO,CAAC,OAAO;IAQf,iEAAiE;IAC3D,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAavD,4DAA4D;IACtD,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IASlD,iFAAiF;IAC3E,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAKhD,uDAAuD;IACjD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxC,0CAA0C;IACpC,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAGhD"}
1
+ {"version":3,"file":"fs-driver.d.ts","sourceRoot":"","sources":["../../../src/runtime/node/fs-driver.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAEhD;;;GAGG;AACH,qBAAa,eAAgB,YAAW,aAAa;IACvC,OAAO,CAAC,IAAI;gBAAJ,IAAI,EAAE,MAAM;IAIhC;;;;;;;OAOG;IACH,OAAO,CAAC,OAAO;IASf,iEAAiE;IAC3D,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAavD,4DAA4D;IACtD,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IASlD,iFAAiF;IAC3E,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAKhD,uDAAuD;IACjD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxC,0CAA0C;IACpC,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAGhD"}
@@ -10,6 +10,11 @@ export interface LiteDoctorReport {
10
10
  identity: {
11
11
  mode: 'local' | 'external';
12
12
  verification: 'built-in' | 'unverified';
13
+ local_auth: {
14
+ status: 'enabled' | 'disabled';
15
+ reason: 'LOCAL_AUTH_ENABLED' | 'AUTH_DISABLED' | 'EXTERNAL_IDENTITY_CONFIGURED';
16
+ verification: 'configuration-only';
17
+ };
13
18
  };
14
19
  migrations: {
15
20
  formats: string[];
@@ -78,6 +83,6 @@ export interface PowerSyncReadiness {
78
83
  invalidation_reason: string | null;
79
84
  }>;
80
85
  }
81
- export declare function liteCapabilities(engine: 'pglite' | 'native', replicationProfile?: 'powersync'): LiteDoctorReport;
86
+ export declare function liteCapabilities(engine: 'pglite' | 'native', replicationProfile?: 'powersync', authEnabled?: boolean): LiteDoctorReport;
82
87
  export declare function inspectPowerSyncReadiness(engine: DbEngine, options: PowerSyncReplicationOptions): Promise<PowerSyncReadiness>;
83
88
  //# sourceMappingURL=readiness.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"readiness.d.ts","sourceRoot":"","sources":["../../../../src/runtime/node/native/readiness.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"readiness.d.ts","sourceRoot":"","sources":["../../../../src/runtime/node/native/readiness.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@supacloud/lite",
3
- "version": "0.27.1",
3
+ "version": "0.28.0",
4
4
  "description": "Bun-native, single-project Supabase-compatible backend powered by PGlite or native PostgreSQL",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",