hazo_env 0.2.0 → 0.3.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/CHANGE_LOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # hazo_env — Change Log
2
2
 
3
+ ## 0.3.0 — 2026-06-10
4
+
5
+ ### Added
6
+ - `EnvRoleMap` type (`Record<string, HazoEnvRole>`) in `src/types/index.ts`
7
+ - `roles?: EnvRoleMap` optional field on `EnvDescription` interface
8
+ - `getRoleMap()` client + server: config-driven role map; merges `DEFAULT_ROLE_MAP` → `globalThis.__HAZO_ENV_ROLES__` (client) → `[env.roles]` INI section (server); invalid role values skipped silently
9
+ - `[env.roles]` INI section support: arbitrary env names mapped to the four fixed roles (`development`, `test`, `staging`, `production`)
10
+ - `describeEnv()` server version now includes `roles` field
11
+ - Filesystem progress store: `writeMigrationProgress`, `readMigrationProgress`, `clearMigrationProgress` (`src/migrate/progress.ts`)
12
+ - `MigrationRequest.jobId` + `MigrationRequest.progressDir` optional fields — when both present, `runMigration` writes each progress event to `<progressDir>/<jobId>.json`
13
+ - `loadRuleset`, `syncRulesetFromIni`, `parseIniRules` masking ruleset functions now exported from package index
14
+ - `MaskRule` type now exported from package index
15
+ - `normalize()` utility now exported from package index (trim + lowercase env name string)
16
+
17
+ ### Changed
18
+ - `getEnvRole()` rewritten to be config-driven via role map; unknown env names now default to `'development'` instead of `'production'` — this is a safe behavior fix (unknown names no longer silently get production-level protection)
19
+
20
+ ## 0.2.0 — 2026-06-09
21
+
22
+ - feat: M2 migration engine — `runMigration`, `verifyFiles`, `takeSnapshot`, `restoreSnapshot`
23
+ - feat: M3 PII masking — `registerMask`, built-in transforms (`mask_email`, `fake_name`, `mask_phone`, `jitter_date`, `hash`, `tokenize`, `drop`, `nullify`, `redact_pii`)
24
+ - feat: masking ruleset management — `loadRuleset`, `syncRulesetFromIni`, `parseIniRules`, `MaskRule` (not yet exported from index — fixed in 0.3.0)
25
+ - feat: `MaskTransform` type in `src/types/index.ts`
26
+ - feat: CLI commands `migrate`, `verify`, `restore`, `mask sync`, `mask list`
27
+ - chore: version bump to 0.2.0
28
+
3
29
  ## 0.1.1 — 2026-06-09
4
30
 
5
31
  - fix: provision `sql-wasm.wasm` into test-app `public/` via seed script (fixes Connect page error when SQLite adapter loads via sql.js WASM)
package/README.md CHANGED
@@ -9,7 +9,7 @@ Canonical environment resolver for hazo apps. Typed env names, per-env DB/file/s
9
9
  - **Per-env file config** — `resolveFilesConfig()` maps the current env to a `hazo_files` config rooted at the declared `data_root`.
10
10
  - **Secrets** — `getSecret()` resolves from `.env.local` only; placeholders in `hazo_env_config.ini` are substituted at runtime without storing secrets.
11
11
  - **Migration engine** — `runMigration({ from, to })` copies a DB + files between envs. Validates → snapshots target → copies tables (paged, schema-checked) → copies files → verifies → writes hazo_audit entry. Prod target refused without an explicit confirm token.
12
- - **PII masking** — masking rules declared per table/column in `hazo_env_masking.ini` (seed) and synced to `hazo_app_config` at runtime. Built-in transforms: `mask_email`, `fake_name`, `mask_phone`, `jitter_date`, `hash`, `tokenize`, `drop`, `nullify`. Custom transforms via `registerMask()`. Applied automatically when the migration target role is `testing` or `staging`.
12
+ - **PII masking** — masking rules declared per table/column in `hazo_env_masking.ini` (seed) and synced to `hazo_app_config` at runtime. Built-in transforms: `mask_email`, `fake_name`, `mask_phone`, `jitter_date`, `hash`, `tokenize`, `drop`, `nullify`. Custom transforms via `registerMask()`. Applied automatically when the migration target role is `test` or `staging`.
13
13
  - **Doctor** — `doctor()` / `hazo-env doctor` validates pattern, DB reachability, required secrets (no values printed), data_root writability, and schema level.
14
14
  - **CLI** — `hazo-env current | doctor | snapshot | migrate | verify | restore | mask`.
15
15
 
@@ -64,18 +64,67 @@ const adapter = await createHazoConnect(resolveConnectConfig());
64
64
  ### Env resolution (client-safe — also in `hazo_env/client`)
65
65
 
66
66
  ```ts
67
- import { getEnv, getEnvRole, getPattern, listEnvs, assertEnv, describeEnv,
67
+ import { getEnv, getEnvRole, getRoleMap, getPattern, listEnvs, assertEnv, describeEnv,
68
68
  isDev, isTest, isStaging, isProd } from 'hazo_env';
69
69
 
70
70
  getEnv() // 'dev' | 'test' | 'staging' | 'prod'
71
- getEnvRole() // 'development' | 'testing' | 'staging' | 'production'
71
+ getEnvRole() // 'development' | 'test' | 'staging' | 'production'
72
+ getRoleMap() // EnvRoleMap — full env→role mapping (config-driven; safe defaults)
72
73
  getPattern() // e.g. 'dev_prod'
73
74
  listEnvs() // ['dev', 'prod'] — valid envs for the declared pattern
74
75
  assertEnv() // throws HazoError(ENV_INVALID) if HAZO_ENV is outside the pattern
75
- describeEnv() // { env, role }
76
+ describeEnv() // { env, role, pattern, app, dataRoot, hostHint, roles? }
76
77
  isDev() / isTest() / isStaging() / isProd()
77
78
  ```
78
79
 
80
+ `getEnvRole()` uses a config-driven role map so custom env names (e.g. `preview`, `qa`) resolve to the correct broad role. Unknown names default to `'development'` — never silently treated as production. Configure custom mappings in `[env.roles]`:
81
+
82
+ ```ini
83
+ [env.roles]
84
+ preview = staging
85
+ qa = test
86
+ ```
87
+
88
+ ### Configuring environment roles
89
+
90
+ Canonical env names (`dev`, `test`, `staging`, `prod`) are pre-mapped and require no configuration. Non-canonical names (anything else) must declare their role in the `[env.roles]` INI section, or `doctor` will flag an error. Unknown names without a declaration fall back to `'development'` (safe: no masking, no prod-protection).
91
+
92
+ ```ini
93
+ [env.roles]
94
+ ; Map arbitrary env names to the four fixed roles:
95
+ ; development | test | staging | production
96
+ qa = test
97
+ live = production
98
+ rc = staging
99
+ ```
100
+
101
+ Valid role values: `development`, `test`, `staging`, `production`.
102
+
103
+ #### Client-side global injection
104
+
105
+ On the client (browser), the INI file is not available. Inject the resolved values at render time using `globalThis` globals — the same pattern used for the env pattern:
106
+
107
+ ```ts
108
+ // In your Next.js layout server component or _app (server-side):
109
+ // globalThis.__HAZO_ENV_PATTERN__ = 'dev,prod'; // comma-separated pattern
110
+ // globalThis.__HAZO_ENV_ROLES__ = { live: 'production', qa: 'test' };
111
+
112
+ // Client bundle reads these automatically:
113
+ import { getPattern, getRoleMap } from 'hazo_env/client';
114
+ getPattern() // reads __HAZO_ENV_PATTERN__
115
+ getRoleMap() // merges DEFAULT_ROLE_MAP → __HAZO_ENV_ROLES__
116
+ ```
117
+
118
+ Both globals are optional; omitting them makes the client fall back to canonical defaults.
119
+
120
+ ### Utility
121
+
122
+ ```ts
123
+ import { normalize } from 'hazo_env';
124
+
125
+ normalize(' Dev ') // → 'dev' (trim + lowercase)
126
+ ```
127
+
79
128
  ### Resolvers (server-only)
80
129
 
81
130
  ```ts
@@ -106,7 +155,8 @@ const report = await doctor();
106
155
  ### Migration engine (server-only)
107
156
 
108
157
  ```ts
109
- import { runMigration, verifyFiles, takeSnapshot, restoreSnapshot } from 'hazo_env';
158
+ import { runMigration, verifyFiles, takeSnapshot, restoreSnapshot,
159
+ writeMigrationProgress, readMigrationProgress, clearMigrationProgress } from 'hazo_env';
110
160
 
111
161
  // Copy prod → staging (with PII masking applied automatically)
112
162
  const result = await runMigration({
@@ -116,6 +166,8 @@ const result = await runMigration({
116
166
  // allowProdTarget: true, // required when `to` is 'prod'
117
167
  // confirmToken: '<token>', // required together with allowProdTarget
118
168
  onProgress: (p) => console.log(p.phase, p.message),
169
+ // jobId: '<id>', // optional — persist progress to progressDir/<id>.json
170
+ // progressDir: '/tmp/hazo_jobs', // required when jobId is set
119
171
  });
120
172
  // result.ok, result.db, result.files, result.snapshotId, result.warnings, result.durationMs
121
173
 
@@ -125,10 +177,26 @@ await verifyFiles('staging', dataRoot, { hash: 'sample' });
125
177
  // Manual snapshot / restore
126
178
  const snap = takeSnapshot(connectConfig); // returns { snapshotId }
127
179
  restoreSnapshot(connectConfig, snapshotId);
180
+
181
+ // Filesystem progress store (used by hazo_jobs integration)
182
+ writeMigrationProgress(dir, jobId, progress);
183
+ readMigrationProgress(dir, jobId); // → MigrationProgress | null
184
+ clearMigrationProgress(dir, jobId);
128
185
  ```
129
186
 
130
187
  **Masking** — customize per table/column in `config/hazo_env_masking.ini`. Sync to the DB with `hazo-env mask sync`. Register custom transforms with `registerMask(name, fn)`.
131
188
 
189
+ **Masking ruleset API** — load, parse, and sync rulesets programmatically:
190
+
191
+ ```ts
192
+ import { loadRuleset, syncRulesetFromIni, parseIniRules } from 'hazo_env';
193
+ import type { MaskRule } from 'hazo_env';
194
+
195
+ const rules: MaskRule[] = parseIniRules(iniText); // parse INI text → rules array
196
+ const loaded = await loadRuleset(adapter); // read from hazo_app_config DB
197
+ await syncRulesetFromIni(adapter, '/path/to/masking.ini'); // write parsed rules to DB
198
+ ```
199
+
132
200
  ## CLI
133
201
 
134
202
  ```
@@ -163,12 +231,6 @@ Key sections:
163
231
 
164
232
  Secret placeholders use `${ENV_VAR_NAME}` syntax — hazo_env substitutes them from `.env.local` at runtime.
165
233
 
166
- ## Tailwind v4 (`@source` required if consuming UI)
167
-
168
- ```css
169
- @source "../node_modules/hazo_env/dist";
170
- ```
171
-
172
234
  ## License
173
235
 
174
236
  MIT
@@ -33,6 +33,16 @@ api_key = ${POSTGREST_API_KEY}
33
33
 
34
34
  **Never put secret values directly in the ini file** — use `${ENV_VAR_NAME}` placeholders.
35
35
 
36
+ **Custom env names** — if your pattern uses names other than `dev`/`test`/`staging`/`prod` (e.g. `preview`, `qa`), add an `[env.roles]` section to map them to broad roles:
37
+
38
+ ```ini
39
+ [env.roles]
40
+ preview = staging
41
+ qa = testing
42
+ ```
43
+
44
+ Without this, unknown env names default to `'development'` role (never silently production).
45
+
36
46
  ## 3. Create `.env.local` (gitignored)
37
47
 
38
48
  One file per deployment (dev machine, staging host, prod host). Contains the secrets referenced by `${…}` placeholders in the ini:
@@ -137,3 +147,19 @@ Review row counts and scrub counts before running without `--dry-run`. The migra
137
147
  ```bash
138
148
  npx hazo-env restore staging --snapshot <snapshot-id>
139
149
  ```
150
+
151
+ ## 10. (Required for non-canonical env names) Declare roles in `[env.roles]`
152
+
153
+ If your pattern uses any env name other than `dev`, `test`, `staging`, or `prod` (e.g. `qa`, `preview`, `live`, `rc`), add an `[env.roles]` section to `config/hazo_env_config.ini` to map each name to one of the four fixed roles:
154
+
155
+ ```ini
156
+ [env.roles]
157
+ qa = test
158
+ preview = staging
159
+ live = production
160
+ rc = staging
161
+ ```
162
+
163
+ Valid role values: `development`, `test`, `staging`, `production`.
164
+
165
+ Without this declaration, undeclared non-canonical names default to `'development'` (safe — no masking, no prod-protection) **and `hazo-env doctor` will flag an error** until the mapping is added. Run `npx hazo-env doctor` to verify all env names have a declared role.
@@ -10,6 +10,22 @@ pattern = dev, test, staging, prod
10
10
  ; Application name (used in log output and doctor reports)
11
11
  app = myapp
12
12
 
13
+ ; ─── Environment role map ─────────────────────────────────────────────────────
14
+ ; Map each environment NAME to one of the four fixed ROLES.
15
+ ; Roles drive behavior: masking fires for test+staging roles;
16
+ ; prod-protection fires for the production role.
17
+ ; The four canonical names default automatically — list them only to be explicit.
18
+ ; Non-canonical names MUST be declared here or doctor will flag an error
19
+ ; and the role will default to 'development' (safe but unintended).
20
+ [env.roles]
21
+ ; dev = development (default — no declaration needed)
22
+ ; test = test (default)
23
+ ; staging = staging (default)
24
+ ; prod = production (default)
25
+ qa = test
26
+ preview = staging
27
+ ; live = production (example: a production env with a different name)
28
+
13
29
  [data]
14
30
  ; Base directory for all local file storage (relative to app root or absolute)
15
31
  ; Default: app_data
package/dist/cli.js CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  // hazo_env/src/cli.ts — CLI entry: hazo-env current | doctor | snapshot | migrate | verify | restore
3
3
  import pc from 'picocolors';
4
- import { getEnv, getEnvRole } from './index.client.js';
5
- import { describeEnv } from './env.server.js';
4
+ import { getEnv } from './index.client.js';
5
+ import { describeEnv, getEnvRole, getPattern } from './env.server.js';
6
6
  import { doctor } from './doctor.js';
7
7
  const [, , command, ...args] = process.argv;
8
8
  function statusIcon(status) {
@@ -20,7 +20,7 @@ async function runCurrent() {
20
20
  catch {
21
21
  // Fallback if no config file
22
22
  const env = getEnv();
23
- desc = { env, role: getEnvRole(env), pattern: ['dev', 'test', 'staging', 'prod'], app: '', dataRoot: '(config not found)', hostHint: 'unknown' };
23
+ desc = { env, role: getEnvRole(env), pattern: getPattern(), app: '', dataRoot: '(config not found)', hostHint: 'unknown' };
24
24
  }
25
25
  console.log(`\n${pc.bold('hazo-env current')}\n`);
26
26
  console.log(` env: ${pc.bold(desc.env)}`);
@@ -1 +1 @@
1
- {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,IAAI,GAAG,MAAM,GAAG,OAAO,CAAC;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,kEAAkE;IAClE,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAMD;;;GAGG;AACH,wBAAsB,MAAM,CAAC,IAAI,GAAE,aAAkB,GAAG,OAAO,CAAC,YAAY,CAAC,CA+I5E"}
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,IAAI,GAAG,MAAM,GAAG,OAAO,CAAC;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,kEAAkE;IAClE,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAMD;;;GAGG;AACH,wBAAsB,MAAM,CAAC,IAAI,GAAE,aAAkB,GAAG,OAAO,CAAC,YAAY,CAAC,CA2J5E"}
package/dist/doctor.js CHANGED
@@ -4,9 +4,11 @@ import path from 'node:path';
4
4
  import { HazoConfig } from 'hazo_config/server';
5
5
  import { optional_import } from 'hazo_core';
6
6
  import { getEnv } from './index.client.js';
7
- import { listEnvs } from './env.server.js';
7
+ import { listEnvs, getEnvRole, getRoleMap } from './env.server.js';
8
8
  import { resolveConnectConfig } from './resolve/connect.js';
9
9
  import { resolveFilesConfig } from './resolve/files.js';
10
+ // Canonical env names that have built-in role defaults — no [env.roles] entry required
11
+ const CANONICAL_ENV_NAMES = new Set(['dev', 'test', 'staging', 'prod']);
10
12
  function findConfigFile(pkg) {
11
13
  return path.resolve(process.cwd(), 'config', `${pkg}_config.ini`);
12
14
  }
@@ -110,8 +112,7 @@ export async function doctor(opts = {}) {
110
112
  if (opts.probe) {
111
113
  for (const env of envsToCheck) {
112
114
  // Get role for this env to guard against touching prod unattended
113
- const role = env === 'dev' ? 'development' : env === 'test' ? 'test'
114
- : env === 'staging' ? 'staging' : 'production';
115
+ const role = getEnvRole(env);
115
116
  if (role === 'production' && !opts.all) {
116
117
  checks.push({
117
118
  label: `DB probe [db.${env}]`,
@@ -153,6 +154,18 @@ export async function doctor(opts = {}) {
153
154
  }
154
155
  }
155
156
  }
157
+ // 6. Check that every env in the pattern has an explicit or canonical role mapping
158
+ const roleMap = getRoleMap();
159
+ const allEnvs = listEnvs();
160
+ for (const env of allEnvs) {
161
+ if (!CANONICAL_ENV_NAMES.has(env) && !(env in roleMap)) {
162
+ checks.push({
163
+ label: `Role for env '${env}'`,
164
+ status: 'error',
165
+ detail: `env '${env}' in pattern has no declared role in [env.roles]; defaulting to development`,
166
+ });
167
+ }
168
+ }
156
169
  const passed = checks.every((c) => c.status !== 'error');
157
170
  return { env: targetEnv, checks, passed };
158
171
  }
@@ -1,4 +1,10 @@
1
- import type { EnvPattern, EnvDescription } from './types/index.js';
1
+ import type { EnvPattern, EnvDescription, EnvRoleMap, HazoEnv, HazoEnvRole } from './types/index.js';
2
+ /**
3
+ * Get the role map, merging client defaults with any [env.roles] section from hazo_env_config.ini.
4
+ */
5
+ export declare function getRoleMap(): EnvRoleMap;
6
+ /** Get the broad role for the current environment (server-aware, reads INI) */
7
+ export declare function getEnvRole(env?: HazoEnv): HazoEnvRole;
2
8
  /**
3
9
  * Get the declared env pattern from [env] pattern in hazo_env_config.ini.
4
10
  * Falls back to ['dev','test','staging','prod'] if the config is absent.
@@ -1 +1 @@
1
- {"version":3,"file":"env.server.d.ts","sourceRoot":"","sources":["../src/env.server.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAY,MAAM,kBAAkB,CAAC;AAc7E;;;GAGG;AACH,wBAAgB,UAAU,IAAI,UAAU,CAKvC;AAED,gEAAgE;AAChE,wBAAgB,QAAQ,IAAI,UAAU,CAErC;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI,CAUpD;AAED;;;GAGG;AACH,wBAAgB,WAAW,IAAI,cAAc,CAW5C"}
1
+ {"version":3,"file":"env.server.d.ts","sourceRoot":"","sources":["../src/env.server.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,UAAU,EAAY,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAgB/G;;GAEG;AACH,wBAAgB,UAAU,IAAI,UAAU,CAYvC;AAED,+EAA+E;AAC/E,wBAAgB,UAAU,CAAC,GAAG,CAAC,EAAE,OAAO,GAAG,WAAW,CAGrD;AAED;;;GAGG;AACH,wBAAgB,UAAU,IAAI,UAAU,CAKvC;AAED,gEAAgE;AAChE,wBAAgB,QAAQ,IAAI,UAAU,CAErC;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI,CAUpD;AAED;;;GAGG;AACH,wBAAgB,WAAW,IAAI,cAAc,CAY5C"}
@@ -2,7 +2,7 @@
2
2
  import path from 'node:path';
3
3
  import { HazoConfig } from 'hazo_config/server';
4
4
  import { HazoError } from 'hazo_core';
5
- import { getEnv, getEnvRole } from './index.client.js';
5
+ import { getEnv, getRoleMap as clientGetRoleMap, normalize } from './index.client.js';
6
6
  function findConfigFile(pkg) {
7
7
  return path.resolve(process.cwd(), 'config', `${pkg}_config.ini`);
8
8
  }
@@ -14,6 +14,28 @@ function tryLoadConfig() {
14
14
  return null;
15
15
  }
16
16
  }
17
+ const VALID_ROLES = new Set(['development', 'test', 'staging', 'production']);
18
+ /**
19
+ * Get the role map, merging client defaults with any [env.roles] section from hazo_env_config.ini.
20
+ */
21
+ export function getRoleMap() {
22
+ const config = tryLoadConfig();
23
+ const section = config?.getSection?.('env.roles') ?? {};
24
+ const out = { ...clientGetRoleMap() };
25
+ for (const [name, role] of Object.entries(section)) {
26
+ const r = String(role).trim();
27
+ if (VALID_ROLES.has(r)) {
28
+ out[name.trim()] = r;
29
+ }
30
+ // invalid values: skip silently (doctor will flag them)
31
+ }
32
+ return out;
33
+ }
34
+ /** Get the broad role for the current environment (server-aware, reads INI) */
35
+ export function getEnvRole(env) {
36
+ const e = normalize(env ?? getEnv());
37
+ return getRoleMap()[e] ?? 'development';
38
+ }
17
39
  /**
18
40
  * Get the declared env pattern from [env] pattern in hazo_env_config.ini.
19
41
  * Falls back to ['dev','test','staging','prod'] if the config is absent.
@@ -57,5 +79,6 @@ export function describeEnv() {
57
79
  const dataRoot = config?.getSection('data')?.['root'] ?? 'app_data';
58
80
  const locationRaw = config?.getSection(`host.${env}`)?.['location'] ?? 'unknown';
59
81
  const hostHint = locationRaw === 'local' ? 'local' : locationRaw === 'remote' ? 'remote' : 'unknown';
60
- return { env, role, pattern, app, dataRoot, hostHint };
82
+ const roles = getRoleMap();
83
+ return { env, role, pattern, app, dataRoot, hostHint, roles };
61
84
  }
@@ -1,7 +1,11 @@
1
- import type { HazoEnv, HazoEnvRole, EnvPattern, EnvDescription } from './types/index.js';
2
- export type { HazoEnv, HazoEnvRole, EnvPattern, EnvDescription };
1
+ import type { HazoEnv, HazoEnvRole, EnvPattern, EnvDescription, EnvRoleMap } from './types/index.js';
2
+ export type { HazoEnv, HazoEnvRole, EnvPattern, EnvDescription, EnvRoleMap };
3
+ /** Normalize raw env string to canonical form */
4
+ export declare function normalize(raw: string): HazoEnv;
3
5
  /** Get the current environment name (normalized) */
4
6
  export declare function getEnv(): HazoEnv;
7
+ /** Get the role map, merging any build-time injected overrides from __HAZO_ENV_ROLES__ */
8
+ export declare function getRoleMap(): EnvRoleMap;
5
9
  /** Get the broad role for the current environment */
6
10
  export declare function getEnvRole(env?: HazoEnv): HazoEnvRole;
7
11
  export declare function isDev(env?: HazoEnv): boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"index.client.d.ts","sourceRoot":"","sources":["../src/index.client.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACzF,YAAY,EAAE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,cAAc,EAAE,CAAC;AASjE,oDAAoD;AACpD,wBAAgB,MAAM,IAAI,OAAO,CAEhC;AAED,qDAAqD;AACrD,wBAAgB,UAAU,CAAC,GAAG,CAAC,EAAE,OAAO,GAAG,WAAW,CAMrD;AAED,wBAAgB,KAAK,CAAC,GAAG,CAAC,EAAE,OAAO,GAAG,OAAO,CAA8C;AAC3F,wBAAgB,MAAM,CAAC,GAAG,CAAC,EAAE,OAAO,GAAG,OAAO,CAAuC;AACrF,wBAAgB,SAAS,CAAC,GAAG,CAAC,EAAE,OAAO,GAAG,OAAO,CAA0C;AAC3F,wBAAgB,MAAM,CAAC,GAAG,CAAC,EAAE,OAAO,GAAG,OAAO,CAA6C;AAE3F;;;;GAIG;AACH,wBAAgB,UAAU,IAAI,UAAU,CAMvC;AAED,gEAAgE;AAChE,wBAAgB,QAAQ,IAAI,UAAU,CAErC;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI,CAUpD;AAED,4DAA4D;AAC5D,wBAAgB,WAAW,IAAI,IAAI,CAAC,cAAc,EAAE,KAAK,GAAG,MAAM,CAAC,CAGlE"}
1
+ {"version":3,"file":"index.client.d.ts","sourceRoot":"","sources":["../src/index.client.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACrG,YAAY,EAAE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,cAAc,EAAE,UAAU,EAAE,CAAC;AAE7E,iDAAiD;AACjD,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAI9C;AAED,oDAAoD;AACpD,wBAAgB,MAAM,IAAI,OAAO,CAEhC;AASD,0FAA0F;AAC1F,wBAAgB,UAAU,IAAI,UAAU,CAIvC;AAED,qDAAqD;AACrD,wBAAgB,UAAU,CAAC,GAAG,CAAC,EAAE,OAAO,GAAG,WAAW,CAGrD;AAED,wBAAgB,KAAK,CAAC,GAAG,CAAC,EAAE,OAAO,GAAG,OAAO,CAA8C;AAC3F,wBAAgB,MAAM,CAAC,GAAG,CAAC,EAAE,OAAO,GAAG,OAAO,CAAuC;AACrF,wBAAgB,SAAS,CAAC,GAAG,CAAC,EAAE,OAAO,GAAG,OAAO,CAA0C;AAC3F,wBAAgB,MAAM,CAAC,GAAG,CAAC,EAAE,OAAO,GAAG,OAAO,CAA6C;AAE3F;;;;GAIG;AACH,wBAAgB,UAAU,IAAI,UAAU,CAMvC;AAED,gEAAgE;AAChE,wBAAgB,QAAQ,IAAI,UAAU,CAErC;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI,CAUpD;AAED,4DAA4D;AAC5D,wBAAgB,WAAW,IAAI,IAAI,CAAC,cAAc,EAAE,KAAK,GAAG,MAAM,CAAC,CAGlE"}
@@ -1,7 +1,7 @@
1
1
  // hazo_env/src/index.client.ts — Client-safe entry point
2
2
  import { getCurrentEnv, HazoError } from 'hazo_core/client';
3
3
  /** Normalize raw env string to canonical form */
4
- function normalize(raw) {
4
+ export function normalize(raw) {
5
5
  if (raw === 'development')
6
6
  return 'dev';
7
7
  if (raw === 'production')
@@ -12,16 +12,22 @@ function normalize(raw) {
12
12
  export function getEnv() {
13
13
  return normalize(getCurrentEnv());
14
14
  }
15
+ const DEFAULT_ROLE_MAP = {
16
+ dev: 'development',
17
+ test: 'test',
18
+ staging: 'staging',
19
+ prod: 'production',
20
+ };
21
+ /** Get the role map, merging any build-time injected overrides from __HAZO_ENV_ROLES__ */
22
+ export function getRoleMap() {
23
+ const g = globalThis;
24
+ const injected = g['__HAZO_ENV_ROLES__'];
25
+ return { ...DEFAULT_ROLE_MAP, ...(injected ?? {}) };
26
+ }
15
27
  /** Get the broad role for the current environment */
16
28
  export function getEnvRole(env) {
17
- const e = env ?? getEnv();
18
- if (e === 'dev')
19
- return 'development';
20
- if (e === 'test')
21
- return 'test';
22
- if (e === 'staging')
23
- return 'staging';
24
- return 'production';
29
+ const e = normalize(env ?? getEnv());
30
+ return getRoleMap()[e] ?? 'development';
25
31
  }
26
32
  export function isDev(env) { return getEnvRole(env) === 'development'; }
27
33
  export function isTest(env) { return getEnvRole(env) === 'test'; }
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- export { getEnv, getEnvRole, isDev, isTest, isStaging, isProd } from './index.client.js';
2
- export { getPattern, listEnvs, assertEnv, describeEnv } from './env.server.js';
1
+ export { getEnv, isDev, isTest, isStaging, isProd } from './index.client.js';
2
+ export { getPattern, listEnvs, assertEnv, describeEnv, getEnvRole, getRoleMap } from './env.server.js';
3
3
  export * from './types/index.js';
4
4
  export * from './resolve/secrets.js';
5
5
  export * from './resolve/connect.js';
@@ -8,7 +8,10 @@ export * from './doctor.js';
8
8
  export { runMigration } from './migrate/run.js';
9
9
  export { verifyFiles } from './migrate/verify.js';
10
10
  export { takeSnapshot, restoreSnapshot } from './migrate/snapshot.js';
11
+ export { writeMigrationProgress, readMigrationProgress, clearMigrationProgress } from './migrate/progress.js';
11
12
  export { registerMask } from './mask/registry.js';
13
+ export { loadRuleset, syncRulesetFromIni, parseIniRules } from './mask/ruleset.js';
14
+ export type { MaskRule } from './mask/ruleset.js';
12
15
  export type { MaskTransform } from './types/index.js';
13
16
  export * from './lib/index.js';
14
17
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAEzF,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE/E,cAAc,kBAAkB,CAAC;AAEjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AAEnC,cAAc,aAAa,CAAC;AAE5B,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAEtE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,YAAY,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEtD,cAAc,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE7E,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAEvG,cAAc,kBAAkB,CAAC;AAEjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AAEnC,cAAc,aAAa,CAAC;AAE5B,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACtE,OAAO,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAE9G,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACnF,YAAY,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAClD,YAAY,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEtD,cAAc,gBAAgB,CAAC"}
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  // hazo_env/src/index.ts — Server entry point
2
2
  // Pure client helpers re-exported explicitly (getPattern/listEnvs/assertEnv/describeEnv are overridden below)
3
- export { getEnv, getEnvRole, isDev, isTest, isStaging, isProd } from './index.client.js';
3
+ export { getEnv, isDev, isTest, isStaging, isProd } from './index.client.js';
4
4
  // Server-aware overrides
5
- export { getPattern, listEnvs, assertEnv, describeEnv } from './env.server.js';
5
+ export { getPattern, listEnvs, assertEnv, describeEnv, getEnvRole, getRoleMap } from './env.server.js';
6
6
  // Types
7
7
  export * from './types/index.js';
8
8
  // Resolver + secrets
@@ -15,7 +15,10 @@ export * from './doctor.js';
15
15
  export { runMigration } from './migrate/run.js';
16
16
  export { verifyFiles } from './migrate/verify.js';
17
17
  export { takeSnapshot, restoreSnapshot } from './migrate/snapshot.js';
18
+ export { writeMigrationProgress, readMigrationProgress, clearMigrationProgress } from './migrate/progress.js';
18
19
  // Masking registry
19
20
  export { registerMask } from './mask/registry.js';
21
+ // Masking ruleset
22
+ export { loadRuleset, syncRulesetFromIni, parseIniRules } from './mask/ruleset.js';
20
23
  // Lib
21
24
  export * from './lib/index.js';
@@ -0,0 +1,5 @@
1
+ import type { MigrationProgress } from '../types/index.js';
2
+ export declare function writeMigrationProgress(progressDir: string, jobId: string, p: MigrationProgress): void;
3
+ export declare function readMigrationProgress(progressDir: string, jobId: string): MigrationProgress | null;
4
+ export declare function clearMigrationProgress(progressDir: string, jobId: string): void;
5
+ //# sourceMappingURL=progress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress.d.ts","sourceRoot":"","sources":["../../src/migrate/progress.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAGrG;AAED,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,iBAAiB,GAAG,IAAI,CAQlG;AAED,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAG/E"}
@@ -0,0 +1,24 @@
1
+ // hazo_env/src/migrate/progress.ts — Filesystem-backed migration progress store
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ export function writeMigrationProgress(progressDir, jobId, p) {
5
+ fs.mkdirSync(progressDir, { recursive: true });
6
+ fs.writeFileSync(path.join(progressDir, `${jobId}.json`), JSON.stringify(p), 'utf-8');
7
+ }
8
+ export function readMigrationProgress(progressDir, jobId) {
9
+ const filePath = path.join(progressDir, `${jobId}.json`);
10
+ try {
11
+ const raw = fs.readFileSync(filePath, 'utf-8');
12
+ return JSON.parse(raw);
13
+ }
14
+ catch {
15
+ return null;
16
+ }
17
+ }
18
+ export function clearMigrationProgress(progressDir, jobId) {
19
+ const filePath = path.join(progressDir, `${jobId}.json`);
20
+ try {
21
+ fs.unlinkSync(filePath);
22
+ }
23
+ catch { /* ignore */ }
24
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/migrate/run.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAkC,MAAM,mBAAmB,CAAC;AAgE3G,wBAAsB,YAAY,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC,CAiJlF"}
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/migrate/run.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAkC,MAAM,mBAAmB,CAAC;AA0D3G,wBAAsB,YAAY,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC,CAkJlF"}
@@ -13,13 +13,13 @@ import { copyDb } from './db.js';
13
13
  import { copyFiles } from './files.js';
14
14
  import { verifyFiles } from './verify.js';
15
15
  import { auditMigration } from './audit.js';
16
- // Production roles that require explicit confirmation
17
- const PROD_ROLES = new Set(['prod', 'production']);
18
- function isProdEnv(env) {
19
- return PROD_ROLES.has(env.toLowerCase());
20
- }
16
+ import { writeMigrationProgress } from './progress.js';
17
+ import { getEnvRole } from '../env.server.js';
21
18
  function emitProgress(req, p) {
22
19
  req.onProgress?.(p);
20
+ if (req.jobId && req.progressDir) {
21
+ writeMigrationProgress(req.progressDir, req.jobId, p);
22
+ }
23
23
  }
24
24
  // Resolve the SQLite driver — prefer better-sqlite3 in tests when env var is set
25
25
  function getSqliteDriver() {
@@ -29,9 +29,8 @@ function getSqliteDriver() {
29
29
  }
30
30
  async function buildScrubHook(toEnv, scrubMode, tgtAdapter) {
31
31
  const maskKey = process.env['HAZO_ENV_MASK_KEY'];
32
- const shouldScrub = scrubMode !== 'none' &&
33
- maskKey &&
34
- (toEnv === 'test' || toEnv === 'staging');
32
+ const toRole = getEnvRole(toEnv);
33
+ const shouldScrub = scrubMode !== 'none' && !!maskKey && (toRole === 'test' || toRole === 'staging');
35
34
  if (!shouldScrub)
36
35
  return undefined;
37
36
  const { loadRuleset } = await import('../mask/ruleset.js');
@@ -85,14 +84,15 @@ export async function runMigration(req) {
85
84
  if (req.from === req.to) {
86
85
  throw new HazoError({ code: 'HAZO_ENV_INVALID_REQUEST', pkg: 'hazo_env', message: `Source and target environments must differ (got "${req.from}" for both).` });
87
86
  }
88
- if (isProdEnv(req.to) && !req.allowProdTarget) {
87
+ const toRole = getEnvRole(req.to);
88
+ if (toRole === 'production' && !req.allowProdTarget) {
89
89
  throw new HazoError({
90
90
  code: 'HAZO_ENV_PROD_TARGET_REFUSED',
91
91
  pkg: 'hazo_env',
92
92
  message: `Refusing to migrate to production environment "${req.to}". Pass allowProdTarget:true and a confirmToken to override.`,
93
93
  });
94
94
  }
95
- if (isProdEnv(req.to) && req.allowProdTarget && !req.confirmToken) {
95
+ if (toRole === 'production' && req.allowProdTarget && !req.confirmToken) {
96
96
  throw new HazoError({
97
97
  code: 'HAZO_ENV_PROD_TARGET_REFUSED',
98
98
  pkg: 'hazo_env',
@@ -4,6 +4,8 @@ export type HazoEnv = 'dev' | 'test' | 'staging' | 'prod' | string;
4
4
  export type HazoEnvRole = 'development' | 'test' | 'staging' | 'production';
5
5
  /** The set of valid environment names for this app, from [env] pattern in INI */
6
6
  export type EnvPattern = string[];
7
+ /** Mapping of env name → broad role, for config-driven role resolution */
8
+ export type EnvRoleMap = Record<string, HazoEnvRole>;
7
9
  /** Hint about where an environment runs */
8
10
  export type HostHint = 'local' | 'remote' | 'unknown';
9
11
  /** DB configuration for a single environment (from [db.<env>] in INI) */
@@ -34,6 +36,7 @@ export interface EnvDescription {
34
36
  app: string;
35
37
  dataRoot: string;
36
38
  hostHint: HostHint;
39
+ roles?: EnvRoleMap;
37
40
  }
38
41
  /** Options for resolveConnectConfig */
39
42
  export interface ResolveConnectOptions {
@@ -62,6 +65,8 @@ export interface MigrationRequest {
62
65
  allowProdTarget?: boolean;
63
66
  confirmToken?: string;
64
67
  onProgress?: (p: MigrationProgress) => void;
68
+ jobId?: string;
69
+ progressDir?: string;
65
70
  }
66
71
  export interface MigrationResult {
67
72
  ok: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hazo_env",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Canonical environment resolver — typed env names, per-env DB/file/secret config, doctor and CLI for hazo apps",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",