@haibun/core 3.6.0 → 3.7.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.
Files changed (70) hide show
  1. package/build/currentVersion.d.ts +1 -1
  2. package/build/currentVersion.js +1 -2
  3. package/build/lib/EventLogger.d.ts +0 -2
  4. package/build/lib/EventLogger.d.ts.map +1 -1
  5. package/build/lib/EventLogger.js +1 -2
  6. package/build/lib/EventLogger.js.map +1 -1
  7. package/build/lib/PhaseRunner.d.ts +16 -0
  8. package/build/lib/PhaseRunner.d.ts.map +1 -0
  9. package/build/lib/PhaseRunner.js +39 -0
  10. package/build/lib/PhaseRunner.js.map +1 -0
  11. package/build/lib/defs.d.ts +1 -0
  12. package/build/lib/defs.d.ts.map +1 -1
  13. package/build/lib/defs.js.map +1 -1
  14. package/build/lib/feature-variables.d.ts +1 -19
  15. package/build/lib/feature-variables.d.ts.map +1 -1
  16. package/build/lib/feature-variables.js +3 -31
  17. package/build/lib/feature-variables.js.map +1 -1
  18. package/build/lib/filter-schema.d.ts +49 -0
  19. package/build/lib/filter-schema.d.ts.map +1 -0
  20. package/build/lib/filter-schema.js +104 -0
  21. package/build/lib/filter-schema.js.map +1 -0
  22. package/build/lib/filter-types.d.ts +71 -0
  23. package/build/lib/filter-types.d.ts.map +1 -0
  24. package/build/lib/filter-types.js +121 -0
  25. package/build/lib/filter-types.js.map +1 -0
  26. package/build/lib/monitor-event-collector.d.ts +16 -0
  27. package/build/lib/monitor-event-collector.d.ts.map +1 -0
  28. package/build/lib/monitor-event-collector.js +26 -0
  29. package/build/lib/monitor-event-collector.js.map +1 -0
  30. package/build/lib/secrets.d.ts +17 -0
  31. package/build/lib/secrets.d.ts.map +1 -0
  32. package/build/lib/secrets.js +46 -0
  33. package/build/lib/secrets.js.map +1 -0
  34. package/build/lib/util/actualURI.d.ts +1 -1
  35. package/build/lib/util/actualURI.d.ts.map +1 -1
  36. package/build/phases/Executor.d.ts.map +1 -1
  37. package/build/phases/Executor.js +0 -2
  38. package/build/phases/Executor.js.map +1 -1
  39. package/build/phases/collector.d.ts +3 -2
  40. package/build/phases/collector.d.ts.map +1 -1
  41. package/build/phases/collector.js +19 -7
  42. package/build/phases/collector.js.map +1 -1
  43. package/build/run-policy/run-policy-schema.d.ts +76 -0
  44. package/build/run-policy/run-policy-schema.d.ts.map +1 -0
  45. package/build/run-policy/run-policy-schema.js +124 -0
  46. package/build/run-policy/run-policy-schema.js.map +1 -0
  47. package/build/run-policy/run-policy-types.d.ts +58 -0
  48. package/build/run-policy/run-policy-types.d.ts.map +1 -0
  49. package/build/run-policy/run-policy-types.js +102 -0
  50. package/build/run-policy/run-policy-types.js.map +1 -0
  51. package/build/runfilter/filter-schema.d.ts +76 -0
  52. package/build/runfilter/filter-schema.d.ts.map +1 -0
  53. package/build/runfilter/filter-schema.js +129 -0
  54. package/build/runfilter/filter-schema.js.map +1 -0
  55. package/build/runfilter/filter-types.d.ts +58 -0
  56. package/build/runfilter/filter-types.d.ts.map +1 -0
  57. package/build/runfilter/filter-types.js +102 -0
  58. package/build/runfilter/filter-types.js.map +1 -0
  59. package/build/runner.d.ts +0 -3
  60. package/build/runner.d.ts.map +1 -1
  61. package/build/runner.js +19 -52
  62. package/build/runner.js.map +1 -1
  63. package/build/schema/protocol.d.ts +2 -2
  64. package/build/steps/activities-stepper.d.ts.map +1 -1
  65. package/build/steps/activities-stepper.js +0 -2
  66. package/build/steps/activities-stepper.js.map +1 -1
  67. package/build/steps/variables-stepper.d.ts.map +1 -1
  68. package/build/steps/variables-stepper.js +1 -2
  69. package/build/steps/variables-stepper.js.map +1 -1
  70. package/package.json +1 -1
@@ -0,0 +1,76 @@
1
+ import { z } from 'zod';
2
+ import { type TRunPolicyConfig } from './run-policy-types.js';
3
+ /**
4
+ * Validates the policy file structure itself.
5
+ * The structure mirrors TRunPolicyConfig (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 TRunPolicy = z.infer<typeof PolicyFileSchema>;
47
+ /**
48
+ * Build a Zod validator for the entire TRunPolicyConfig based on the policy.
49
+ * This validator checks the whole config object at once ("wholesale validation").
50
+ */
51
+ export declare function buildConfigValidator(policy: TRunPolicy): 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 loadRunPolicy(schemaPath: string): TRunPolicy;
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 validateRunPolicyConfig(config: TRunPolicyConfig, policy: TRunPolicy, schemaPath: string): string[];
73
+ /** Load policy, validate config, throw on failure. */
74
+ export declare function loadAndValidateRunPolicy(config: TRunPolicyConfig, schemaPath: string): TRunPolicy;
75
+ export {};
76
+ //# sourceMappingURL=run-policy-schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-policy-schema.d.ts","sourceRoot":"","sources":["../../src/run-policy/run-policy-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAiB,KAAK,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAY7E;;;GAGG;AACH,QAAA,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA0BN,CAAC;AAEjB,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAM1D;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,UAAU;;;;;;;;;;;;;;kBAkCtD;AAED,mCAAmC;AACnC,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,UAAU,CAQ5D;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAkBlH;AAED,sDAAsD;AACtD,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,GAAG,UAAU,CAQjG"}
@@ -0,0 +1,124 @@
1
+ import { z } from 'zod';
2
+ import { readFileSync } from 'fs';
3
+ import { ACCESS_LEVELS } from './run-policy-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 mirrors TRunPolicyConfig (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 TRunPolicyConfig 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
+ const validDirs = policy.properties.dirFilters.items.properties.dir.enum;
53
+ const ConfigValidator = z.object({
54
+ env: z.enum(validEnvs),
55
+ dirFilters: z.array(z.object({
56
+ dir: z.enum(validDirs),
57
+ access: z.enum(ACCESS_LEVELS),
58
+ })),
59
+ }).passthrough();
60
+ // Apply deny rules via superRefine on the whole object
61
+ return ConfigValidator.superRefine((data, ctx) => {
62
+ if (!data.dirFilters)
63
+ return;
64
+ data.dirFilters.forEach((filter, index) => {
65
+ const flat = { env: data.env, dir: filter.dir, access: filter.access };
66
+ for (const rule of policy.deny) {
67
+ const match = (!rule.env || rule.env === flat.env)
68
+ && (!rule.dir || rule.dir === flat.dir)
69
+ && (!rule.access || rule.access === flat.access);
70
+ if (match) {
71
+ ctx.addIssue({
72
+ code: 'custom',
73
+ path: ['dirFilters', index],
74
+ message: `Denied by policy: ${JSON.stringify(rule)}`,
75
+ });
76
+ }
77
+ }
78
+ });
79
+ });
80
+ }
81
+ /** Load and parse a policy file */
82
+ export function loadRunPolicy(schemaPath) {
83
+ let raw;
84
+ try {
85
+ raw = readFileSync(schemaPath, 'utf-8');
86
+ }
87
+ catch (err) {
88
+ throw new Error(`Cannot read run policy "${schemaPath}": ${err.message}`);
89
+ }
90
+ return PolicyFileSchema.parse(JSON.parse(raw));
91
+ }
92
+ /**
93
+ * Validate a runtime config against a loaded policy.
94
+ * Uses the generated Zod validator to check the config wholesale.
95
+ */
96
+ export function validateRunPolicyConfig(config, policy, schemaPath) {
97
+ const validator = buildConfigValidator(policy);
98
+ const objectToValidate = { $schema: schemaPath, ...config };
99
+ const result = validator.safeParse(objectToValidate);
100
+ if (!result.success) {
101
+ return result.error.issues.map((issue) => {
102
+ if (issue.path[0] === 'dirFilters' && typeof issue.path[1] === 'number') {
103
+ const idx = issue.path[1];
104
+ const f = config.dirFilters[idx];
105
+ const filterStr = f ? `${f.dir}:${f.access}` : 'unknown';
106
+ const reason = issue.message.replace(/Expected .*, received/, 'Invalid').replace(/'/g, '"');
107
+ return `Filter "${filterStr}" in "${config.env}": ${reason}`;
108
+ }
109
+ return issue.message;
110
+ });
111
+ }
112
+ return [];
113
+ }
114
+ /** Load policy, validate config, throw on failure. */
115
+ export function loadAndValidateRunPolicy(config, schemaPath) {
116
+ const policy = loadRunPolicy(schemaPath);
117
+ const errors = validateRunPolicyConfig(config, policy, schemaPath);
118
+ if (errors.length > 0) {
119
+ const jsonContext = JSON.stringify({ $schema: schemaPath, ...config }, null, 2);
120
+ throw new Error(`Run policy validation failed:\n${jsonContext}\n\nErrors:\n${errors.map((e) => ` • ${e}`).join('\n')}`);
121
+ }
122
+ return policy;
123
+ }
124
+ //# sourceMappingURL=run-policy-schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-policy-schema.js","sourceRoot":"","sources":["../../src/run-policy/run-policy-schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
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=run-policy-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-policy-types.d.ts","sourceRoot":"","sources":["../../src/run-policy/run-policy-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"}
@@ -0,0 +1,102 @@
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=run-policy-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-policy-types.js","sourceRoot":"","sources":["../../src/run-policy/run-policy-types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,76 @@
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
@@ -0,0 +1 @@
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"}
@@ -0,0 +1,129 @@
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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter-schema.js","sourceRoot":"","sources":["../../src/runfilter/filter-schema.ts"],"names":[],"mappings":"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"}