@commonpub/layer 0.21.1 → 0.21.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@commonpub/layer",
3
- "version": "0.21.1",
3
+ "version": "0.21.2",
4
4
  "type": "module",
5
5
  "main": "./nuxt.config.ts",
6
6
  "files": [
@@ -50,16 +50,16 @@
50
50
  "vue": "^3.4.0",
51
51
  "vue-router": "^4.3.0",
52
52
  "zod": "^4.3.6",
53
- "@commonpub/auth": "0.6.0",
54
- "@commonpub/learning": "0.5.2",
55
- "@commonpub/docs": "0.6.2",
56
53
  "@commonpub/config": "0.12.0",
57
54
  "@commonpub/editor": "0.7.9",
58
- "@commonpub/protocol": "0.9.9",
59
- "@commonpub/schema": "0.16.0",
60
55
  "@commonpub/explainer": "0.7.12",
56
+ "@commonpub/learning": "0.5.2",
57
+ "@commonpub/server": "2.51.0",
58
+ "@commonpub/auth": "0.6.0",
61
59
  "@commonpub/ui": "0.8.5",
62
- "@commonpub/server": "2.51.0"
60
+ "@commonpub/protocol": "0.9.9",
61
+ "@commonpub/schema": "0.16.0",
62
+ "@commonpub/docs": "0.6.2"
63
63
  },
64
64
  "devDependencies": {
65
65
  "@testing-library/jest-dom": "^6.9.1",
@@ -1,16 +1,31 @@
1
1
  /**
2
2
  * Admin bootstrap plugin.
3
3
  *
4
- * In development: promotes the first registered user to admin.
5
- * In production: promotes ADMIN_BOOTSTRAP_USER (env var) if no admin exists.
4
+ * Runs once when no admin exists yet:
6
5
  *
7
- * This solves the bootstrap problem where no admin exists to promote users.
8
- * The production path only runs ONCE (when admin count is 0) and requires
9
- * an explicit env var, so it's safe to leave enabled.
6
+ * - Development (NODE_ENV !== 'production'): promotes the first
7
+ * registered user to admin. Zero config.
8
+ * - Production, ADMIN_BOOTSTRAP_USER set: promotes that username.
9
+ * The canonical "set the admin directly" path.
10
+ * - Production, ADMIN_BOOTSTRAP_FIRST_USER truthy (1/true/yes):
11
+ * promotes the first registered user — the frictionless
12
+ * one-click-deploy path (deploy → register → you're admin).
13
+ * - Production, neither set: does nothing (safe default — a public
14
+ * instance shouldn't hand admin to a random first signup unless
15
+ * the operator explicitly opted in).
16
+ *
17
+ * Idempotent: the whole block early-returns once any admin exists, so
18
+ * this is safe to leave enabled forever and ships harmlessly to
19
+ * instances that already have admins (no behavior change there).
10
20
  */
11
21
  import { users } from '@commonpub/schema';
12
22
  import { eq, asc, count } from 'drizzle-orm';
13
23
 
24
+ /** Truthy env check — accepts 1/true/yes (case-insensitive). */
25
+ function envTruthy(value: string | undefined): boolean {
26
+ return /^(1|true|yes)$/i.test(value ?? '');
27
+ }
28
+
14
29
  export default defineNitroPlugin((nitro) => {
15
30
  // Run after a short delay so the DB pool is ready
16
31
  setTimeout(async () => {
@@ -27,14 +42,21 @@ export default defineNitroPlugin((nitro) => {
27
42
 
28
43
  // No admins exist — bootstrap one
29
44
 
30
- // Production: promote specific user from env var
31
45
  const bootstrapUsername = process.env.ADMIN_BOOTSTRAP_USER;
32
- if (process.env.NODE_ENV === 'production' && !bootstrapUsername) return;
46
+ const isProd = process.env.NODE_ENV === 'production';
47
+ // First-user promotion: default in dev, opt-in in prod via
48
+ // ADMIN_BOOTSTRAP_FIRST_USER (the one-click-deploy path).
49
+ const allowFirstUser = !isProd || envTruthy(process.env.ADMIN_BOOTSTRAP_FIRST_USER);
50
+
51
+ // In production, do nothing unless the operator either named a
52
+ // user OR explicitly opted into first-user promotion. Preserves
53
+ // the original safe default for instances that set neither.
54
+ if (isProd && !bootstrapUsername && !allowFirstUser) return;
33
55
 
34
56
  let targetUser: { id: string; username: string } | undefined;
35
57
 
36
58
  if (bootstrapUsername) {
37
- // Promote the specified user
59
+ // Promote the specified user (canonical "set admin directly").
38
60
  const [found] = await db
39
61
  .select({ id: users.id, username: users.username })
40
62
  .from(users)
@@ -44,8 +66,9 @@ export default defineNitroPlugin((nitro) => {
44
66
  if (!targetUser) {
45
67
  console.warn(`[auto-admin] ADMIN_BOOTSTRAP_USER="${bootstrapUsername}" not found`);
46
68
  }
47
- } else {
48
- // Dev mode: promote first registered user
69
+ } else if (allowFirstUser) {
70
+ // Promote the first registered user (dev always; prod only
71
+ // when ADMIN_BOOTSTRAP_FIRST_USER opted in).
49
72
  const [firstUser] = await db
50
73
  .select({ id: users.id, username: users.username })
51
74
  .from(users)