@haibun/core 3.8.2 → 3.8.4

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.
@@ -1,2 +1,2 @@
1
- export declare const currentVersion = "3.8.1";
1
+ export declare const currentVersion = "3.8.4";
2
2
  //# sourceMappingURL=currentVersion.d.ts.map
@@ -1,2 +1,2 @@
1
- export const currentVersion = '3.8.1';
1
+ export const currentVersion = '3.8.4';
2
2
  //# sourceMappingURL=currentVersion.js.map
@@ -1023,8 +1023,8 @@ export declare const ControlEvent: z.ZodObject<{
1023
1023
  }>>;
1024
1024
  kind: z.ZodLiteral<"control">;
1025
1025
  signal: z.ZodEnum<{
1026
- step: "step";
1027
1026
  fail: "fail";
1027
+ step: "step";
1028
1028
  continue: "continue";
1029
1029
  retry: "retry";
1030
1030
  next: "next";
@@ -1408,8 +1408,8 @@ export declare const HaibunEvent: z.ZodUnion<readonly [z.ZodUnion<readonly [z.Zo
1408
1408
  }>>;
1409
1409
  kind: z.ZodLiteral<"control">;
1410
1410
  signal: z.ZodEnum<{
1411
- step: "step";
1412
1411
  fail: "fail";
1412
+ step: "step";
1413
1413
  continue: "continue";
1414
1414
  retry: "retry";
1415
1415
  next: "next";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@haibun/core",
3
3
  "type": "module",
4
- "version": "3.8.2",
4
+ "version": "3.8.4",
5
5
  "description": "",
6
6
  "author": "",
7
7
  "exports": {
@@ -27,4 +27,4 @@
27
27
  "dependencies": {
28
28
  "zod": "^4.3.6"
29
29
  }
30
- }
30
+ }
@@ -1,49 +0,0 @@
1
- import { z } from 'zod';
2
- import { type TFilterConfig } from './filter-types.js';
3
- /**
4
- * Zod schema for the filter policy JSON file.
5
- *
6
- * The JSON Schema file defines which env+dir+access combinations are allowed.
7
- * Structure:
8
- * {
9
- * "environments": ["local", "dev", "test", "prod"],
10
- * "directories": ["smoke", "api", "web", "regression"],
11
- * "deny": [
12
- * { "env": "prod", "access": "w" },
13
- * { "env": "prod", "dir": "regression", "access": "a" }
14
- * ]
15
- * }
16
- *
17
- * - `environments`: valid environment names
18
- * - `directories`: valid directory names
19
- * - `deny`: rules that block specific combinations. Each rule matches when
20
- * all specified fields match. Omitted fields match everything (wildcard).
21
- */
22
- export declare const FilterPolicySchema: z.ZodObject<{
23
- environments: z.ZodArray<z.ZodString>;
24
- directories: z.ZodArray<z.ZodString>;
25
- deny: z.ZodDefault<z.ZodArray<z.ZodObject<{
26
- env: z.ZodOptional<z.ZodString>;
27
- dir: z.ZodOptional<z.ZodString>;
28
- access: z.ZodOptional<z.ZodEnum<{
29
- r: "r";
30
- a: "a";
31
- w: "w";
32
- }>>;
33
- }, z.core.$strip>>>;
34
- }, z.core.$strip>;
35
- export type TFilterPolicy = z.infer<typeof FilterPolicySchema>;
36
- /**
37
- * Load and parse a filter policy JSON file.
38
- */
39
- export declare function loadFilterPolicy(schemaPath: string): TFilterPolicy;
40
- /**
41
- * Validate a runtime filter config against a loaded filter policy.
42
- * Returns an array of error messages (empty = valid).
43
- */
44
- export declare function validateFilterConfig(config: TFilterConfig, policy: TFilterPolicy): string[];
45
- /**
46
- * Load schema, validate config, and throw on failure.
47
- */
48
- export declare function loadAndValidateFilters(config: TFilterConfig): TFilterPolicy;
49
- //# sourceMappingURL=filter-schema.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"filter-schema.d.ts","sourceRoot":"","sources":["../../src/lib/filter-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEtE;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;iBAU7B,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE/D;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,aAAa,CAsBlE;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,aAAa,GAAG,MAAM,EAAE,CAiC3F;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,aAAa,GAAG,aAAa,CAO3E"}
@@ -1,104 +0,0 @@
1
- import { z } from 'zod';
2
- import { readFileSync } from 'fs';
3
- import { ACCESS_LEVELS } from './filter-types.js';
4
- /**
5
- * Zod schema for the filter policy JSON file.
6
- *
7
- * The JSON Schema file defines which env+dir+access combinations are allowed.
8
- * Structure:
9
- * {
10
- * "environments": ["local", "dev", "test", "prod"],
11
- * "directories": ["smoke", "api", "web", "regression"],
12
- * "deny": [
13
- * { "env": "prod", "access": "w" },
14
- * { "env": "prod", "dir": "regression", "access": "a" }
15
- * ]
16
- * }
17
- *
18
- * - `environments`: valid environment names
19
- * - `directories`: valid directory names
20
- * - `deny`: rules that block specific combinations. Each rule matches when
21
- * all specified fields match. Omitted fields match everything (wildcard).
22
- */
23
- export const FilterPolicySchema = z.object({
24
- environments: z.array(z.string()).min(1),
25
- directories: z.array(z.string()).min(1),
26
- deny: z.array(z.object({
27
- env: z.string().optional(),
28
- dir: z.string().optional(),
29
- access: z.enum(ACCESS_LEVELS).optional(),
30
- })).default([]),
31
- });
32
- /**
33
- * Load and parse a filter policy JSON file.
34
- */
35
- export function loadFilterPolicy(schemaPath) {
36
- let raw;
37
- try {
38
- raw = readFileSync(schemaPath, 'utf-8');
39
- }
40
- catch (err) {
41
- throw new Error(`Cannot read filter schema file "${schemaPath}": ${err.message}`);
42
- }
43
- let parsed;
44
- try {
45
- parsed = JSON.parse(raw);
46
- }
47
- catch {
48
- throw new Error(`Filter schema file "${schemaPath}" is not valid JSON`);
49
- }
50
- const result = FilterPolicySchema.safeParse(parsed);
51
- if (!result.success) {
52
- const issues = result.error.issues.map((i) => ` ${i.path.join('.')}: ${i.message}`).join('\n');
53
- throw new Error(`Filter schema file "${schemaPath}" has invalid structure:\n${issues}`);
54
- }
55
- return result.data;
56
- }
57
- /**
58
- * Validate a runtime filter config against a loaded filter policy.
59
- * Returns an array of error messages (empty = valid).
60
- */
61
- export function validateFilterConfig(config, policy) {
62
- const errors = [];
63
- // Validate environment
64
- if (!policy.environments.includes(config.env)) {
65
- errors.push(`Environment "${config.env}" is not allowed. Valid: ${policy.environments.join(', ')}`);
66
- }
67
- // Validate directories
68
- for (const df of config.dirFilters) {
69
- if (!policy.directories.includes(df.dir)) {
70
- errors.push(`Directory "${df.dir}" is not allowed. Valid: ${policy.directories.join(', ')}`);
71
- }
72
- }
73
- // Check deny rules
74
- for (const rule of policy.deny) {
75
- for (const df of config.dirFilters) {
76
- const envMatch = !rule.env || rule.env === config.env;
77
- const dirMatch = !rule.dir || rule.dir === df.dir;
78
- const accessMatch = !rule.access || rule.access === df.access;
79
- if (envMatch && dirMatch && accessMatch) {
80
- const parts = [];
81
- if (rule.env)
82
- parts.push(`env=${rule.env}`);
83
- if (rule.dir)
84
- parts.push(`dir=${rule.dir}`);
85
- if (rule.access)
86
- parts.push(`access=${rule.access}`);
87
- errors.push(`Denied by policy rule: ${parts.join(', ')} (matched ${df.dir}:${df.access} in ${config.env})`);
88
- }
89
- }
90
- }
91
- return errors;
92
- }
93
- /**
94
- * Load schema, validate config, and throw on failure.
95
- */
96
- export function loadAndValidateFilters(config) {
97
- const policy = loadFilterPolicy(config.schemaPath);
98
- const errors = validateFilterConfig(config, policy);
99
- if (errors.length > 0) {
100
- throw new Error(`Filter validation failed:\n${errors.map((e) => ` • ${e}`).join('\n')}`);
101
- }
102
- return policy;
103
- }
104
- //# sourceMappingURL=filter-schema.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"filter-schema.js","sourceRoot":"","sources":["../../src/lib/filter-schema.ts"],"names":[],"mappings":"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"}
@@ -1,71 +0,0 @@
1
- import { z } from 'zod';
2
- /** CLI option name for filters */
3
- export declare const OPTION_FILTERS = "--filters";
4
- /** Environment variable for filters (format: "schema.json env dir:access,dir:access") */
5
- export declare const HAIBUN_FILTERS = "HAIBUN_FILTERS";
6
- /** Valid access levels, forming a strict hierarchy: r ⊂ a ⊂ w */
7
- export declare const ACCESS_LEVELS: readonly ["r", "a", "w"];
8
- /** Feature filename prefixes corresponding to access levels */
9
- export declare const ACCESS_PREFIX_R = "r_";
10
- export declare const ACCESS_PREFIX_A = "a_";
11
- export declare const ACCESS_PREFIX_W = "w_";
12
- export declare const ACCESS_PREFIXES: readonly ["r_", "a_", "w_"];
13
- export type AccessLevel = (typeof ACCESS_LEVELS)[number];
14
- export declare const AccessLevelSchema: z.ZodEnum<{
15
- r: "r";
16
- a: "a";
17
- w: "w";
18
- }>;
19
- /** A single directory + access pair, e.g. "smoke:r" */
20
- export type TDirFilter = {
21
- dir: string;
22
- access: AccessLevel;
23
- };
24
- /** Parsed --filters configuration */
25
- export type TFilterConfig = {
26
- schemaPath: string;
27
- env: string;
28
- dirFilters: TDirFilter[];
29
- };
30
- /**
31
- * Parse the dir:access,dir:access string into TDirFilter[].
32
- * E.g. "smoke:r,api:a" → [{ dir: "smoke", access: "r" }, { dir: "api", access: "a" }]
33
- */
34
- export declare function parseDirFilters(input: string): TDirFilter[];
35
- /**
36
- * Parse --filters arguments: schemaPath env dir:access[,dir:access]
37
- */
38
- export declare function parseFilterArgs(schemaPath: string, env: string, dirAccessStr: string): TFilterConfig;
39
- /**
40
- * Parse HAIBUN_FILTERS env var value: "schema.json env dir:access,dir:access"
41
- */
42
- export declare function parseFilterEnv(value: string): TFilterConfig;
43
- /**
44
- * Returns the numeric rank of an access level for comparison.
45
- * r=0, a=1, w=2
46
- */
47
- export declare function accessRank(level: AccessLevel): number;
48
- /**
49
- * Check if a granted access level includes the required level.
50
- * Access levels are cumulative: w includes a includes r.
51
- */
52
- export declare function accessLevelIncludes(granted: AccessLevel, required: AccessLevel): boolean;
53
- /**
54
- * Extract the access prefix from a feature filename.
55
- * Returns the access level if the file starts with r_, a_, or w_.
56
- * Returns undefined for unprefixed/unrecognized files (they will be skipped).
57
- */
58
- export declare function getFeatureAccessPrefix(filename: string): AccessLevel | undefined;
59
- /**
60
- * Determine if a feature file should run given the active filters.
61
- *
62
- * - Unprefixed/unrecognized files are silently skipped (returns false).
63
- * - Files whose access prefix exceeds the granted level are skipped.
64
- * - Files in directories not listed in the filters are skipped.
65
- *
66
- * @param featurePath - relative path from features root, e.g. "/smoke/r_health.feature"
67
- * @param dirFilters - active directory filters
68
- * @returns true if the feature should execute
69
- */
70
- export declare function featureMatchesFilter(featurePath: string, dirFilters: TDirFilter[]): boolean;
71
- //# sourceMappingURL=filter-types.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"filter-types.d.ts","sourceRoot":"","sources":["../../src/lib/filter-types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB,kCAAkC;AAClC,eAAO,MAAM,cAAc,cAAc,CAAC;AAE1C,yFAAyF;AACzF,eAAO,MAAM,cAAc,mBAAmB,CAAC;AAE/C,iEAAiE;AACjE,eAAO,MAAM,aAAa,0BAA2B,CAAC;AAEtD,+DAA+D;AAC/D,eAAO,MAAM,eAAe,OAAO,CAAC;AACpC,eAAO,MAAM,eAAe,OAAO,CAAC;AACpC,eAAO,MAAM,eAAe,OAAO,CAAC;AACpC,eAAO,MAAM,eAAe,6BAA+D,CAAC;AAM5F,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AACzD,eAAO,MAAM,iBAAiB;;;;EAAwB,CAAC;AAEvD,uDAAuD;AACvD,MAAM,MAAM,UAAU,GAAG;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,WAAW,CAAC;CACrB,CAAC;AAEF,qCAAqC;AACrC,MAAM,MAAM,aAAa,GAAG;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,UAAU,EAAE,CAAC;CAC1B,CAAC;AAMF;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,EAAE,CAY3D;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,aAAa,CAUpG;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,CAM3D;AAMD;;;GAGG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAErD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,GAAG,OAAO,CAExF;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAKhF;AAMD;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,GAAG,OAAO,CAe3F"}
@@ -1,121 +0,0 @@
1
- import { z } from 'zod';
2
- // ============================================================================
3
- // Constants
4
- // ============================================================================
5
- /** CLI option name for filters */
6
- export const OPTION_FILTERS = '--filters';
7
- /** Environment variable for filters (format: "schema.json env dir:access,dir:access") */
8
- export const HAIBUN_FILTERS = 'HAIBUN_FILTERS';
9
- /** Valid access levels, forming a strict hierarchy: r ⊂ a ⊂ w */
10
- export const ACCESS_LEVELS = ['r', 'a', 'w'];
11
- /** Feature filename prefixes corresponding to access levels */
12
- export const ACCESS_PREFIX_R = 'r_';
13
- export const ACCESS_PREFIX_A = 'a_';
14
- export const ACCESS_PREFIX_W = 'w_';
15
- export const ACCESS_PREFIXES = [ACCESS_PREFIX_R, ACCESS_PREFIX_A, ACCESS_PREFIX_W];
16
- export const AccessLevelSchema = z.enum(ACCESS_LEVELS);
17
- // ============================================================================
18
- // Parsing
19
- // ============================================================================
20
- /**
21
- * Parse the dir:access,dir:access string into TDirFilter[].
22
- * E.g. "smoke:r,api:a" → [{ dir: "smoke", access: "r" }, { dir: "api", access: "a" }]
23
- */
24
- export function parseDirFilters(input) {
25
- return input.split(',').map((pair) => {
26
- const [dir, accessStr] = pair.split(':');
27
- if (!dir || !accessStr) {
28
- throw new Error(`Invalid dir:access pair "${pair}". Expected format: dir:access (e.g. smoke:r)`);
29
- }
30
- const parsed = AccessLevelSchema.safeParse(accessStr);
31
- if (!parsed.success) {
32
- throw new Error(`Invalid access level "${accessStr}" in "${pair}". Must be one of: ${ACCESS_LEVELS.join(', ')}`);
33
- }
34
- return { dir, access: parsed.data };
35
- });
36
- }
37
- /**
38
- * Parse --filters arguments: schemaPath env dir:access[,dir:access]
39
- */
40
- export function parseFilterArgs(schemaPath, env, dirAccessStr) {
41
- if (!schemaPath)
42
- throw new Error(`${OPTION_FILTERS} requires a schema path`);
43
- if (!env)
44
- throw new Error(`${OPTION_FILTERS} requires an environment`);
45
- if (!dirAccessStr)
46
- throw new Error(`${OPTION_FILTERS} requires dir:access pairs`);
47
- return {
48
- schemaPath,
49
- env,
50
- dirFilters: parseDirFilters(dirAccessStr),
51
- };
52
- }
53
- /**
54
- * Parse HAIBUN_FILTERS env var value: "schema.json env dir:access,dir:access"
55
- */
56
- export function parseFilterEnv(value) {
57
- const parts = value.trim().split(/\s+/);
58
- if (parts.length !== 3) {
59
- throw new Error(`${HAIBUN_FILTERS} must have 3 space-separated parts: "schema env dir:access[,dir:access]" (got ${parts.length})`);
60
- }
61
- return parseFilterArgs(parts[0], parts[1], parts[2]);
62
- }
63
- // ============================================================================
64
- // Access Level Logic
65
- // ============================================================================
66
- /**
67
- * Returns the numeric rank of an access level for comparison.
68
- * r=0, a=1, w=2
69
- */
70
- export function accessRank(level) {
71
- return ACCESS_LEVELS.indexOf(level);
72
- }
73
- /**
74
- * Check if a granted access level includes the required level.
75
- * Access levels are cumulative: w includes a includes r.
76
- */
77
- export function accessLevelIncludes(granted, required) {
78
- return accessRank(granted) >= accessRank(required);
79
- }
80
- /**
81
- * Extract the access prefix from a feature filename.
82
- * Returns the access level if the file starts with r_, a_, or w_.
83
- * Returns undefined for unprefixed/unrecognized files (they will be skipped).
84
- */
85
- export function getFeatureAccessPrefix(filename) {
86
- const match = filename.match(/^([raw])_/);
87
- if (!match)
88
- return undefined;
89
- const parsed = AccessLevelSchema.safeParse(match[1]);
90
- return parsed.success ? parsed.data : undefined;
91
- }
92
- // ============================================================================
93
- // Feature Matching
94
- // ============================================================================
95
- /**
96
- * Determine if a feature file should run given the active filters.
97
- *
98
- * - Unprefixed/unrecognized files are silently skipped (returns false).
99
- * - Files whose access prefix exceeds the granted level are skipped.
100
- * - Files in directories not listed in the filters are skipped.
101
- *
102
- * @param featurePath - relative path from features root, e.g. "/smoke/r_health.feature"
103
- * @param dirFilters - active directory filters
104
- * @returns true if the feature should execute
105
- */
106
- export function featureMatchesFilter(featurePath, dirFilters) {
107
- const parts = featurePath.replace(/^\//, '').split('/');
108
- const filename = parts[parts.length - 1];
109
- const featureDir = parts.length > 1 ? parts[0] : undefined;
110
- // Unrecognized prefix → skip silently
111
- const requiredAccess = getFeatureAccessPrefix(filename);
112
- if (!requiredAccess)
113
- return false;
114
- // No matching directory filter → skip
115
- const matchingFilter = dirFilters.find((f) => f.dir === featureDir);
116
- if (!matchingFilter)
117
- return false;
118
- // Check access hierarchy
119
- return accessLevelIncludes(matchingFilter.access, requiredAccess);
120
- }
121
- //# sourceMappingURL=filter-types.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"filter-types.js","sourceRoot":"","sources":["../../src/lib/filter-types.ts"],"names":[],"mappings":"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"}
@@ -1,16 +0,0 @@
1
- import { AStepper, IHasCycles } from './astepper.js';
2
- import { IStepperCycles } from './defs.js';
3
- import { THaibunEvent } from '../schema/protocol.js';
4
- export declare class EventCollectorStepper extends AStepper implements IHasCycles {
5
- description: string;
6
- kind: "MONITOR";
7
- private events;
8
- steps: {};
9
- cycles: IStepperCycles;
10
- getEvents(): THaibunEvent[];
11
- getStepEvents(): THaibunEvent[];
12
- findEvents(predicate: (e: THaibunEvent) => boolean): THaibunEvent[];
13
- clear(): void;
14
- }
15
- export default EventCollectorStepper;
16
- //# sourceMappingURL=monitor-event-collector.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"monitor-event-collector.d.ts","sourceRoot":"","sources":["../../src/lib/monitor-event-collector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAgB,MAAM,eAAe,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAErD,qBAAa,qBAAsB,SAAQ,QAAS,YAAW,UAAU;IACvE,WAAW,SAAyC;IACpD,IAAI,YAAwB;IAE5B,OAAO,CAAC,MAAM,CAAsB;IAEpC,KAAK,KAAM;IAEX,MAAM,EAAE,cAAc,CAIpB;IAEF,SAAS,IAAI,YAAY,EAAE;IAI3B,aAAa,IAAI,YAAY,EAAE;IAI/B,UAAU,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,YAAY,KAAK,OAAO,GAAG,YAAY,EAAE;IAGnE,KAAK,IAAI,IAAI;CAGd;AAED,eAAe,qBAAqB,CAAC"}
@@ -1,26 +0,0 @@
1
- import { AStepper, StepperKinds } from './astepper.js';
2
- export class EventCollectorStepper extends AStepper {
3
- description = 'Collects events for test inspection';
4
- kind = StepperKinds.MONITOR;
5
- events = [];
6
- steps = {};
7
- cycles = {
8
- onEvent: (event) => {
9
- this.events.push(event);
10
- }
11
- };
12
- getEvents() {
13
- return [...this.events];
14
- }
15
- getStepEvents() {
16
- return this.events.filter(e => 'type' in e && e.type === 'step');
17
- }
18
- findEvents(predicate) {
19
- return this.events.filter(predicate);
20
- }
21
- clear() {
22
- this.events = [];
23
- }
24
- }
25
- export default EventCollectorStepper;
26
- //# sourceMappingURL=monitor-event-collector.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"monitor-event-collector.js","sourceRoot":"","sources":["../../src/lib/monitor-event-collector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAc,YAAY,EAAE,MAAM,eAAe,CAAC;AAInE,MAAM,OAAO,qBAAsB,SAAQ,QAAQ;IACjD,WAAW,GAAG,qCAAqC,CAAC;IACpD,IAAI,GAAG,YAAY,CAAC,OAAO,CAAC;IAEpB,MAAM,GAAmB,EAAE,CAAC;IAEpC,KAAK,GAAG,EAAE,CAAC;IAEX,MAAM,GAAmB;QACvB,OAAO,EAAE,CAAC,KAAmB,EAAE,EAAE;YAC/B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC;KACF,CAAC;IAEF,SAAS;QACP,OAAO,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;IAC1B,CAAC;IAED,aAAa;QACX,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;IACnE,CAAC;IAED,UAAU,CAAC,SAAuC;QAChD,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACvC,CAAC;IACD,KAAK;QACH,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;IACnB,CAAC;CACF;AAED,eAAe,qBAAqB,CAAC"}
@@ -1,17 +0,0 @@
1
- /** Marker type for sanitized objects */
2
- export type Sanitized<T> = T & {
3
- readonly __sanitized: unique symbol;
4
- };
5
- /**
6
- * Escapes special regex characters in a string.
7
- */
8
- export declare function escapeRegex(s: string): string;
9
- /**
10
- * Replaces all occurrences of secret values in text with OBSCURED_VALUE.
11
- */
12
- export declare function replaceSecrets(text: string, secrets: string[]): string;
13
- /**
14
- * Sanitizes an object by recursively replacing all secret values.
15
- */
16
- export declare function sanitizeObject<T>(obj: T, secrets: string[]): Sanitized<T>;
17
- //# sourceMappingURL=secrets.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"secrets.d.ts","sourceRoot":"","sources":["../../src/lib/secrets.ts"],"names":[],"mappings":"AAEA,wCAAwC;AACxC,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI,CAAC,GAAG;IAAE,QAAQ,CAAC,WAAW,EAAE,OAAO,MAAM,CAAA;CAAE,CAAC;AAEvE;;GAEG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,CAQtE;AAuBD;;GAEG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC,CAEzE"}
@@ -1,46 +0,0 @@
1
- import { OBSCURED_VALUE } from './feature-variables.js';
2
- /**
3
- * Escapes special regex characters in a string.
4
- */
5
- export function escapeRegex(s) {
6
- return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
7
- }
8
- /**
9
- * Replaces all occurrences of secret values in text with OBSCURED_VALUE.
10
- */
11
- export function replaceSecrets(text, secrets) {
12
- let result = text;
13
- for (const secret of secrets) {
14
- if (secret && secret.length > 0) {
15
- result = result.replace(new RegExp(escapeRegex(secret), 'g'), OBSCURED_VALUE);
16
- }
17
- }
18
- return result;
19
- }
20
- /**
21
- * Recursively sanitizes a value by replacing secret strings.
22
- * Handles primitives, arrays, and plain objects.
23
- */
24
- function sanitizeValue(value, secrets) {
25
- if (typeof value === 'string') {
26
- return replaceSecrets(value, secrets);
27
- }
28
- if (Array.isArray(value)) {
29
- return value.map(v => sanitizeValue(v, secrets));
30
- }
31
- if (value !== null && typeof value === 'object') {
32
- const result = {};
33
- for (const [k, v] of Object.entries(value)) {
34
- result[k] = sanitizeValue(v, secrets);
35
- }
36
- return result;
37
- }
38
- return value;
39
- }
40
- /**
41
- * Sanitizes an object by recursively replacing all secret values.
42
- */
43
- export function sanitizeObject(obj, secrets) {
44
- return sanitizeValue(obj, secrets);
45
- }
46
- //# sourceMappingURL=secrets.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"secrets.js","sourceRoot":"","sources":["../../src/lib/secrets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAKxD;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,CAAS;IACnC,OAAO,CAAC,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;AAClD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,OAAiB;IAC5D,IAAI,MAAM,GAAG,IAAI,CAAC;IAClB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,MAAM,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChC,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,EAAE,cAAc,CAAC,CAAC;QAChF,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,SAAS,aAAa,CAAI,KAAQ,EAAE,OAAiB;IACnD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,cAAc,CAAC,KAAK,EAAE,OAAO,CAAM,CAAC;IAC7C,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,EAAE,OAAO,CAAC,CAAM,CAAC;IACxD,CAAC;IACD,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAChD,MAAM,MAAM,GAA4B,EAAE,CAAC;QAC3C,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC,EAAE,CAAC;YACtE,MAAM,CAAC,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QACxC,CAAC;QACD,OAAO,MAAW,CAAC;IACrB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAI,GAAM,EAAE,OAAiB;IACzD,OAAO,aAAa,CAAC,GAAG,EAAE,OAAO,CAAiB,CAAC;AACrD,CAAC"}
@@ -1,76 +0,0 @@
1
- import { z } from 'zod';
2
- import { type TFilterConfig } from './filter-types.js';
3
- /**
4
- * Validates the policy file structure itself.
5
- * The structure now mimics TFilterConfig (env + dirFilters array).
6
- */
7
- declare const PolicyFileSchema: z.ZodObject<{
8
- type: z.ZodDefault<z.ZodLiteral<"object">>;
9
- properties: z.ZodObject<{
10
- env: z.ZodObject<{
11
- type: z.ZodDefault<z.ZodLiteral<"string">>;
12
- enum: z.ZodArray<z.ZodString>;
13
- }, z.core.$loose>;
14
- dirFilters: z.ZodObject<{
15
- type: z.ZodDefault<z.ZodLiteral<"array">>;
16
- items: z.ZodObject<{
17
- type: z.ZodDefault<z.ZodLiteral<"object">>;
18
- properties: z.ZodObject<{
19
- dir: z.ZodObject<{
20
- type: z.ZodDefault<z.ZodLiteral<"string">>;
21
- enum: z.ZodArray<z.ZodString>;
22
- }, z.core.$loose>;
23
- access: z.ZodOptional<z.ZodObject<{
24
- type: z.ZodDefault<z.ZodLiteral<"string">>;
25
- enum: z.ZodOptional<z.ZodArray<z.ZodEnum<{
26
- r: "r";
27
- a: "a";
28
- w: "w";
29
- }>>>;
30
- }, z.core.$loose>>;
31
- }, z.core.$loose>;
32
- required: z.ZodOptional<z.ZodArray<z.ZodString>>;
33
- }, z.core.$loose>;
34
- }, z.core.$loose>;
35
- }, z.core.$loose>;
36
- deny: z.ZodDefault<z.ZodArray<z.ZodObject<{
37
- env: z.ZodOptional<z.ZodString>;
38
- dir: z.ZodOptional<z.ZodString>;
39
- access: z.ZodOptional<z.ZodEnum<{
40
- r: "r";
41
- a: "a";
42
- w: "w";
43
- }>>;
44
- }, z.core.$strip>>>;
45
- }, z.core.$loose>;
46
- export type TFilterPolicy = z.infer<typeof PolicyFileSchema>;
47
- /**
48
- * Build a Zod validator for the entire TFilterConfig based on the policy.
49
- * This validator checks the whole config object at once ("wholesale validation").
50
- */
51
- export declare function buildConfigValidator(policy: TFilterPolicy): z.ZodObject<{
52
- env: z.ZodEnum<{
53
- [x: string]: string;
54
- }>;
55
- dirFilters: z.ZodArray<z.ZodObject<{
56
- dir: z.ZodEnum<{
57
- [x: string]: string;
58
- }>;
59
- access: z.ZodEnum<{
60
- r: "r";
61
- a: "a";
62
- w: "w";
63
- }>;
64
- }, z.core.$strip>>;
65
- }, z.core.$loose>;
66
- /** Load and parse a policy file */
67
- export declare function loadFilterPolicy(schemaPath: string): TFilterPolicy;
68
- /**
69
- * Validate a runtime config against a loaded policy.
70
- * Uses the generated Zod validator to check the config wholesale.
71
- */
72
- export declare function validateFilterConfig(config: TFilterConfig, policy: TFilterPolicy, schemaPath: string): string[];
73
- /** Load schema, validate config, throw on failure. */
74
- export declare function loadAndValidateFilters(config: TFilterConfig, schemaPath: string): TFilterPolicy;
75
- export {};
76
- //# sourceMappingURL=filter-schema.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"filter-schema.d.ts","sourceRoot":"","sources":["../../src/runfilter/filter-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAYtE;;;GAGG;AACH,QAAA,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA0BN,CAAC;AAEjB,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAM7D;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,aAAa;;;;;;;;;;;;;;kBAsCzD;AAED,mCAAmC;AACnC,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,aAAa,CAQlE;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAmB/G;AAED,sDAAsD;AACtD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,GAAG,aAAa,CAQ/F"}
@@ -1,129 +0,0 @@
1
- import { z } from 'zod';
2
- import { readFileSync } from 'fs';
3
- import { ACCESS_LEVELS } from './filter-types.js';
4
- // ============================================================================
5
- // Policy File Schema — Hierarchical JSON Schema
6
- // ============================================================================
7
- const DenyRuleSchema = z.object({
8
- env: z.string().optional(),
9
- dir: z.string().optional(),
10
- access: z.enum(ACCESS_LEVELS).optional(),
11
- });
12
- /**
13
- * Validates the policy file structure itself.
14
- * The structure now mimics TFilterConfig (env + dirFilters array).
15
- */
16
- const PolicyFileSchema = z.object({
17
- type: z.literal('object').default('object'),
18
- properties: z.object({
19
- env: z.object({
20
- type: z.literal('string').default('string'),
21
- enum: z.array(z.string()).min(1, 'At least one environment required'),
22
- }).passthrough(),
23
- dirFilters: z.object({
24
- type: z.literal('array').default('array'),
25
- items: z.object({
26
- type: z.literal('object').default('object'),
27
- properties: z.object({
28
- dir: z.object({
29
- type: z.literal('string').default('string'),
30
- enum: z.array(z.string()).min(1, 'At least one directory required'),
31
- }).passthrough(),
32
- access: z.object({
33
- type: z.literal('string').default('string'),
34
- enum: z.array(z.enum(ACCESS_LEVELS)).optional(),
35
- }).passthrough().optional()
36
- }).passthrough(),
37
- required: z.array(z.string()).optional()
38
- }).passthrough()
39
- }).passthrough()
40
- }).passthrough(),
41
- deny: z.array(DenyRuleSchema).default([]),
42
- }).passthrough();
43
- // ============================================================================
44
- // Validation — Hierarchical Object Validation
45
- // ============================================================================
46
- /**
47
- * Build a Zod validator for the entire TFilterConfig based on the policy.
48
- * This validator checks the whole config object at once ("wholesale validation").
49
- */
50
- export function buildConfigValidator(policy) {
51
- const validEnvs = policy.properties.env.enum;
52
- // Extract enums from nested structure: properties.dirFilters.items.properties.dir.enum
53
- const validDirs = policy.properties.dirFilters.items.properties.dir.enum;
54
- const ConfigValidator = z.object({
55
- env: z.enum(validEnvs),
56
- dirFilters: z.array(z.object({
57
- dir: z.enum(validDirs),
58
- access: z.enum(ACCESS_LEVELS),
59
- })),
60
- // Allow extra properties like schemaPath or $schema
61
- }).passthrough();
62
- // Apply deny rules via superRefine on the whole object
63
- return ConfigValidator.superRefine((data, ctx) => {
64
- // Check each directory filter against all deny rules
65
- // data.dirFilters is available because ConfigValidator ensures it exists (or Zod parse fails before here)
66
- if (!data.dirFilters)
67
- return;
68
- data.dirFilters.forEach((filter, index) => {
69
- const flat = { env: data.env, dir: filter.dir, access: filter.access };
70
- for (const rule of policy.deny) {
71
- const match = (!rule.env || rule.env === flat.env)
72
- && (!rule.dir || rule.dir === flat.dir)
73
- && (!rule.access || rule.access === flat.access);
74
- if (match) {
75
- ctx.addIssue({
76
- code: 'custom',
77
- path: ['dirFilters', index],
78
- message: `Denied by policy: ${JSON.stringify(rule)}`,
79
- });
80
- }
81
- }
82
- });
83
- });
84
- }
85
- /** Load and parse a policy file */
86
- export function loadFilterPolicy(schemaPath) {
87
- let raw;
88
- try {
89
- raw = readFileSync(schemaPath, 'utf-8');
90
- }
91
- catch (err) {
92
- throw new Error(`Cannot read filter schema "${schemaPath}": ${err.message}`);
93
- }
94
- return PolicyFileSchema.parse(JSON.parse(raw));
95
- }
96
- /**
97
- * Validate a runtime config against a loaded policy.
98
- * Uses the generated Zod validator to check the config wholesale.
99
- */
100
- export function validateFilterConfig(config, policy, schemaPath) {
101
- const validator = buildConfigValidator(policy);
102
- const objectToValidate = { $schema: schemaPath, ...config };
103
- const result = validator.safeParse(objectToValidate);
104
- if (!result.success) {
105
- return result.error.issues.map((issue) => {
106
- // Improve error message context
107
- if (issue.path[0] === 'dirFilters' && typeof issue.path[1] === 'number') {
108
- const idx = issue.path[1];
109
- const f = config.dirFilters[idx];
110
- const filterStr = f ? `${f.dir}:${f.access}` : 'unknown';
111
- const reason = issue.message.replace(/Expected .*, received/, 'Invalid').replace(/'/g, '"');
112
- return `Filter "${filterStr}" in "${config.env}": ${reason}`;
113
- }
114
- return issue.message;
115
- });
116
- }
117
- return [];
118
- }
119
- /** Load schema, validate config, throw on failure. */
120
- export function loadAndValidateFilters(config, schemaPath) {
121
- const policy = loadFilterPolicy(schemaPath);
122
- const errors = validateFilterConfig(config, policy, schemaPath);
123
- if (errors.length > 0) {
124
- const jsonContext = JSON.stringify({ $schema: schemaPath, ...config }, null, 2);
125
- throw new Error(`Filter validation failed:\n${jsonContext}\n\nErrors:\n${errors.map((e) => ` • ${e}`).join('\n')}`);
126
- }
127
- return policy;
128
- }
129
- //# sourceMappingURL=filter-schema.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"filter-schema.js","sourceRoot":"","sources":["../../src/runfilter/filter-schema.ts"],"names":[],"mappings":"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"}
@@ -1,58 +0,0 @@
1
- import { z } from 'zod';
2
- /** CLI option name for run-policy */
3
- export declare const OPTION_RUN_POLICY = "--run-policy";
4
- /** CLI option for dry-run mode (preview which features pass/fail the run policy) */
5
- export declare const OPTION_DRY_RUN = "--dry-run";
6
- /** Environment variable for run-policy (format: "env dir:access[,dir:access]") */
7
- export declare const HAIBUN_RUN_POLICY = "HAIBUN_RUN_POLICY";
8
- /** Valid access levels, forming a strict hierarchy: r ⊂ a ⊂ w */
9
- export declare const ACCESS_LEVELS: readonly ["r", "a", "w"];
10
- /** Feature filename prefixes corresponding to access levels */
11
- export declare const ACCESS_PREFIXES: readonly ["r_", "a_", "w_"];
12
- export declare const AccessLevelSchema: z.ZodEnum<{
13
- r: "r";
14
- a: "a";
15
- w: "w";
16
- }>;
17
- export type AccessLevel = z.infer<typeof AccessLevelSchema>;
18
- export type TDirFilter = {
19
- dir: string;
20
- access: string;
21
- };
22
- export type TRunPolicyConfig = {
23
- env: string;
24
- dirFilters: TDirFilter[];
25
- };
26
- /** Parses "smoke:r" → { dir: "smoke", access: "r" } */
27
- export declare const DirFilterSchema: z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<{
28
- dir: string;
29
- access: string;
30
- }, string>>, z.ZodObject<{
31
- dir: z.ZodString;
32
- access: z.ZodString;
33
- }, z.core.$strip>>;
34
- /** Parse dir:access[,dir:access] string */
35
- export declare function parseDirFilters(input: string): TDirFilter[];
36
- export declare const RunPolicyConfigSchema: z.ZodPipe<z.ZodObject<{
37
- env: z.ZodString;
38
- dirAccessStr: z.ZodString;
39
- }, z.core.$strip>, z.ZodTransform<TRunPolicyConfig, {
40
- env: string;
41
- dirAccessStr: string;
42
- }>>;
43
- /** Parse --run-policy arguments: env dir:access[,dir:access] */
44
- export declare function parseRunPolicyArgs(env: string, dirAccessStr: string): TRunPolicyConfig;
45
- /** Parse HAIBUN_RUN_POLICY env var: "env dir:access[,dir:access]" */
46
- export declare function parseRunPolicyEnv(envVar: string): TRunPolicyConfig;
47
- /** Numeric rank for hierarchy comparison: r=0, a=1, w=2 */
48
- export declare function accessRank(level: string): number;
49
- /** Check if granted level includes required level (w ⊃ a ⊃ r) */
50
- export declare function accessLevelIncludes(granted: string, required: string): boolean;
51
- /** Extract access prefix from feature filename, or undefined if unrecognized */
52
- export declare function getFeatureAccessPrefix(filename: string): AccessLevel | undefined;
53
- /**
54
- * Determine if a feature file should run given the active dir filters.
55
- * Exclusive: only features with a recognized prefix in a listed directory pass.
56
- */
57
- export declare function featureMatchesFilter(featurePath: string, dirFilters: TDirFilter[]): boolean;
58
- //# sourceMappingURL=filter-types.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"filter-types.d.ts","sourceRoot":"","sources":["../../src/runfilter/filter-types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB,qCAAqC;AACrC,eAAO,MAAM,iBAAiB,iBAAiB,CAAC;AAEhD,oFAAoF;AACpF,eAAO,MAAM,cAAc,cAAc,CAAC;AAE1C,kFAAkF;AAClF,eAAO,MAAM,iBAAiB,sBAAsB,CAAC;AAErD,iEAAiE;AACjE,eAAO,MAAM,aAAa,0BAA2B,CAAC;AAEtD,+DAA+D;AAC/D,eAAO,MAAM,eAAe,6BAA8B,CAAC;AAQ3D,eAAO,MAAM,iBAAiB;;;;EAAwB,CAAC;AACvD,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE5D,MAAM,MAAM,UAAU,GAAG;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,UAAU,EAAE,CAAC;CAC1B,CAAC;AAEF,uDAAuD;AACvD,eAAO,MAAM,eAAe;;;;;;kBASiD,CAAC;AAE9E,2CAA2C;AAC3C,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,EAAE,CAE3D;AAED,eAAO,MAAM,qBAAqB;;;;;;GAMhC,CAAC;AAMH,gEAAgE;AAChE,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,gBAAgB,CAUtF;AAED,qEAAqE;AACrE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,gBAAgB,CAMlE;AAMD,2DAA2D;AAC3D,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,iEAAiE;AACjE,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAE9E;AAED,gFAAgF;AAChF,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAGhF;AAMD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,GAAG,OAAO,CAY3F"}
@@ -1,102 +0,0 @@
1
- import { z } from 'zod';
2
- // ============================================================================
3
- // Constants
4
- // ============================================================================
5
- /** CLI option name for run-policy */
6
- export const OPTION_RUN_POLICY = '--run-policy';
7
- /** CLI option for dry-run mode (preview which features pass/fail the run policy) */
8
- export const OPTION_DRY_RUN = '--dry-run';
9
- /** Environment variable for run-policy (format: "env dir:access[,dir:access]") */
10
- export const HAIBUN_RUN_POLICY = 'HAIBUN_RUN_POLICY';
11
- /** Valid access levels, forming a strict hierarchy: r ⊂ a ⊂ w */
12
- export const ACCESS_LEVELS = ['r', 'a', 'w'];
13
- /** Feature filename prefixes corresponding to access levels */
14
- export const ACCESS_PREFIXES = ['r_', 'a_', 'w_'];
15
- // ============================================================================
16
- // Zod Schemas — types are inferred, parsing via transforms
17
- // ============================================================================
18
- // Basic types
19
- const InputAccessLevelSchema = z.string();
20
- export const AccessLevelSchema = z.enum(ACCESS_LEVELS);
21
- /** Parses "smoke:r" → { dir: "smoke", access: "r" } */
22
- export const DirFilterSchema = z.string()
23
- .transform((val, ctx) => {
24
- const parts = val.split(':');
25
- if (parts.length !== 2) {
26
- ctx.addIssue({ code: z.ZodIssueCode.custom, message: `Invalid filter format "${val}". Expected "dir:access"` });
27
- return z.NEVER;
28
- }
29
- return { dir: parts[0], access: parts[1] };
30
- })
31
- .pipe(z.object({ dir: z.string().min(1), access: InputAccessLevelSchema }));
32
- /** Parse dir:access[,dir:access] string */
33
- export function parseDirFilters(input) {
34
- return input.split(',').map(s => DirFilterSchema.parse(s));
35
- }
36
- export const RunPolicyConfigSchema = z.object({
37
- env: z.string().min(1),
38
- dirAccessStr: z.string(),
39
- }).transform((data) => {
40
- const dirFilters = parseDirFilters(data.dirAccessStr);
41
- return { env: data.env, dirFilters };
42
- });
43
- // ============================================================================
44
- // Parsing — thin wrappers delegating to Zod
45
- // ============================================================================
46
- /** Parse --run-policy arguments: env dir:access[,dir:access] */
47
- export function parseRunPolicyArgs(env, dirAccessStr) {
48
- try {
49
- return RunPolicyConfigSchema.parse({ env, dirAccessStr });
50
- }
51
- catch (e) {
52
- if (e instanceof z.ZodError) {
53
- const detail = e.issues.map((i) => ` • ${i.path.join('.')}: ${i.message}`).join('\n');
54
- throw new Error(`Run policy configuration failed:\n${detail}`);
55
- }
56
- throw e;
57
- }
58
- }
59
- /** Parse HAIBUN_RUN_POLICY env var: "env dir:access[,dir:access]" */
60
- export function parseRunPolicyEnv(envVar) {
61
- const parts = envVar.trim().split(/\s+/);
62
- if (parts.length !== 2) {
63
- throw new Error(`Invalid format. Expected "env dir:access"`);
64
- }
65
- return parseRunPolicyArgs(parts[0], parts[1]);
66
- }
67
- // ============================================================================
68
- // Access Level Logic — minimal procedural (pure domain logic)
69
- // ============================================================================
70
- /** Numeric rank for hierarchy comparison: r=0, a=1, w=2 */
71
- export function accessRank(level) {
72
- return ACCESS_LEVELS.indexOf(level);
73
- }
74
- /** Check if granted level includes required level (w ⊃ a ⊃ r) */
75
- export function accessLevelIncludes(granted, required) {
76
- return accessRank(granted) >= accessRank(required);
77
- }
78
- /** Extract access prefix from feature filename, or undefined if unrecognized */
79
- export function getFeatureAccessPrefix(filename) {
80
- const result = AccessLevelSchema.safeParse(filename.charAt(0));
81
- return result.success && filename.charAt(1) === '_' ? result.data : undefined;
82
- }
83
- // ============================================================================
84
- // Feature Matching — runtime matching (must be procedural)
85
- // ============================================================================
86
- /**
87
- * Determine if a feature file should run given the active dir filters.
88
- * Exclusive: only features with a recognized prefix in a listed directory pass.
89
- */
90
- export function featureMatchesFilter(featurePath, dirFilters) {
91
- const parts = featurePath.replace(/^\//, '').split('/');
92
- const filename = parts[parts.length - 1];
93
- const featureDir = parts.length > 1 ? parts[0] : undefined;
94
- const requiredAccess = getFeatureAccessPrefix(filename);
95
- if (!requiredAccess)
96
- return false;
97
- const matchingFilter = dirFilters.find((f) => f.dir === featureDir);
98
- if (!matchingFilter)
99
- return false;
100
- return accessLevelIncludes(matchingFilter.access, requiredAccess);
101
- }
102
- //# sourceMappingURL=filter-types.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"filter-types.js","sourceRoot":"","sources":["../../src/runfilter/filter-types.ts"],"names":[],"mappings":"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"}