@zerotal/admin 1.5.0 → 1.6.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
@@ -8,6 +8,28 @@ follows the Zerotal monorepo's unified versioning.
8
8
 
9
9
  ## [Unreleased]
10
10
 
11
+ ## [1.6.0] — 2026-08-15
12
+
13
+ ### Fixed
14
+
15
+ - **The environment badge showed on every screen, and always said the same thing.** It read
16
+ `APP_ENV`, which holds the runtime mode once the app has booted — so it rendered `web`,
17
+ which is in nobody's quiet list, and its `staging` tone could never fire. A badge whose
18
+ whole purpose is preventing "I thought this was staging" was displaying the same wrong word
19
+ in every environment. It reads `deployEnv()` now, so local stays quiet and staging is
20
+ visibly staging.
21
+
22
+ ## [1.5.1] — 2026-08-15
23
+
24
+ ### Fixed
25
+
26
+ - **The development bypass never applied.** `AdminGuardMiddleware` and the `ability` helper
27
+ both read `APP_ENV` to decide whether this was a development environment — but by the time
28
+ either runs, `setAppEnv()` has replaced it with the runtime mode. So the panel refused
29
+ access in development exactly as it does in production, which is not what either was
30
+ written to do. Both ask `devSurfacesEnabled()` now, and both still fail closed anywhere
31
+ that is not explicitly a development environment.
32
+
11
33
  ## [1.5.0] — 2026-08-15
12
34
 
13
35
  ### Changed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zerotal/admin",
3
- "version": "1.5.0",
3
+ "version": "1.6.0",
4
4
  "license": "MIT",
5
5
  "maturity": "stable",
6
6
  "private": false,
@@ -31,16 +31,16 @@
31
31
  "typecheck": "tsc --noEmit"
32
32
  },
33
33
  "dependencies": {
34
- "@zerotal/cache": "1.5.0",
35
- "@zerotal/core": "1.5.0",
36
- "@zerotal/flow": "1.5.0",
37
- "@zerotal/flow-ui": "1.5.0",
38
- "@zerotal/validator": "1.5.0"
34
+ "@zerotal/cache": "1.6.0",
35
+ "@zerotal/core": "1.6.0",
36
+ "@zerotal/flow": "1.6.0",
37
+ "@zerotal/flow-ui": "1.6.0",
38
+ "@zerotal/validator": "1.6.0"
39
39
  },
40
40
  "devDependencies": {
41
- "@zerotal/orm": "1.5.0",
42
- "@zerotal/auth": "1.5.0",
43
- "@zerotal/queue": "1.5.0"
41
+ "@zerotal/orm": "1.6.0",
42
+ "@zerotal/auth": "1.6.0",
43
+ "@zerotal/queue": "1.6.0"
44
44
  },
45
45
  "peerDependencies": {
46
46
  "@zerotal/orm": "^1.0.0",
@@ -1,4 +1,4 @@
1
- import { BaseMiddleware, isDevSurfaceAllowed } from "@zerotal/core";
1
+ import { BaseMiddleware, devSurfacesEnabled } from "@zerotal/core";
2
2
  import type { NextFn, HttpContext } from "@zerotal/core";
3
3
 
4
4
  /**
@@ -19,7 +19,9 @@ export class AdminGuardMiddleware extends BaseMiddleware {
19
19
  protected options = {};
20
20
 
21
21
  async handle(_http: HttpContext, next: NextFn): Promise<Response | void> {
22
- if (isDevSurfaceAllowed(Bun.env["APP_ENV"] ?? "")) return next();
22
+ // `devSurfacesEnabled()` — `APP_ENV` holds the runtime mode by now, so reading it
23
+ // directly asked whether "web" is a development environment and always said no.
24
+ if (devSurfacesEnabled()) return next();
23
25
  return new Response(
24
26
  "Admin panel is not accessible: no authentication is configured.\n" +
25
27
  "Set `middleware` in config/admin.ts to a real auth guard before exposing it.\n",
@@ -20,7 +20,7 @@
20
20
  * put a page in the sidebar, but it cannot put one in front of a production user
21
21
  * who has no authorization configured.
22
22
  */
23
- import { tryCurrentApp, isDevSurfaceAllowed } from "@zerotal/core";
23
+ import { tryCurrentApp, devSurfacesEnabled } from "@zerotal/core";
24
24
 
25
25
  /**
26
26
  * The slice of `@zerotal/auth`'s `GateService` the panel uses. Declared locally
@@ -69,5 +69,5 @@ export async function resolveAbility(
69
69
  return false;
70
70
  }
71
71
 
72
- return isDevSurfaceAllowed(Bun.env["APP_ENV"] ?? "");
72
+ return devSurfacesEnabled();
73
73
  }
@@ -6,6 +6,7 @@
6
6
  // admin panel ecosystem grows a plugin for exactly this.
7
7
 
8
8
  import type { HtmlNode } from "@zerotal/flow";
9
+ import { deployEnv } from "@zerotal/core";
9
10
  import type { RenderHook } from "../renderHooks.ts";
10
11
 
11
12
  export interface EnvironmentIndicatorOptions {
@@ -41,7 +42,12 @@ export function environmentIndicator(options: EnvironmentIndicatorOptions = {}):
41
42
  const tones = { ...DEFAULT_TONES, ...(options.tones ?? {}) };
42
43
 
43
44
  return (): HtmlNode | null => {
44
- const env = (options.environment ?? Bun.env["APP_ENV"] ?? "").trim();
45
+ // `deployEnv()` `APP_ENV` holds the runtime mode by the time a page renders, so
46
+ // this badge read "web": never in the quiet list, so it showed on every screen
47
+ // including local, and its `staging` tone could never fire. The one mistake this
48
+ // component exists to prevent is editing production believing it is staging, and
49
+ // a badge that always says the same wrong word prevents nothing.
50
+ const env = (options.environment ?? deployEnv()).trim();
45
51
  if (!env || quiet.has(env.toLowerCase())) return null;
46
52
 
47
53
  const tone = tones[env.toLowerCase()] ?? "bg-amber-500 text-black";