@lannguyensi/harness 0.25.1 → 0.26.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 (68) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/dist/cli/apply/apply.d.ts +11 -0
  3. package/dist/cli/apply/apply.js +11 -0
  4. package/dist/cli/apply/apply.js.map +1 -1
  5. package/dist/cli/event-input.d.ts +28 -0
  6. package/dist/cli/event-input.js +72 -0
  7. package/dist/cli/event-input.js.map +1 -0
  8. package/dist/cli/explain-action.d.ts +20 -0
  9. package/dist/cli/explain-action.js +27 -0
  10. package/dist/cli/explain-action.js.map +1 -0
  11. package/dist/cli/index.js +76 -10
  12. package/dist/cli/index.js.map +1 -1
  13. package/dist/cli/init/interactive.js +10 -3
  14. package/dist/cli/init/interactive.js.map +1 -1
  15. package/dist/cli/pack/hook-branch-protection.js +1 -1
  16. package/dist/cli/pack/hook-branch-protection.js.map +1 -1
  17. package/dist/cli/pack/hook-codex-pre-tool-use.js +1 -1
  18. package/dist/cli/pack/hook-codex-pre-tool-use.js.map +1 -1
  19. package/dist/cli/pack/hook-post-tool-use.js +1 -1
  20. package/dist/cli/pack/hook-post-tool-use.js.map +1 -1
  21. package/dist/cli/pack/hook-pre-tool-use.d.ts +8 -0
  22. package/dist/cli/pack/hook-pre-tool-use.js +3 -1
  23. package/dist/cli/pack/hook-pre-tool-use.js.map +1 -1
  24. package/dist/cli/pack/hook-track-active-claim.js +1 -1
  25. package/dist/cli/pack/hook-track-active-claim.js.map +1 -1
  26. package/dist/cli/{pack/pause-check.d.ts → pause-check.d.ts} +1 -1
  27. package/dist/cli/{pack/pause-check.js → pause-check.js} +14 -11
  28. package/dist/cli/pause-check.js.map +1 -0
  29. package/dist/cli/policy/intercept.d.ts +5 -0
  30. package/dist/cli/policy/intercept.js +21 -0
  31. package/dist/cli/policy/intercept.js.map +1 -1
  32. package/dist/cli/resolve-env.d.ts +32 -0
  33. package/dist/cli/resolve-env.js +47 -0
  34. package/dist/cli/resolve-env.js.map +1 -0
  35. package/dist/cli/test-risk.d.ts +26 -0
  36. package/dist/cli/test-risk.js +34 -0
  37. package/dist/cli/test-risk.js.map +1 -0
  38. package/dist/runtime/action-envelope.d.ts +64 -0
  39. package/dist/runtime/action-envelope.js +46 -0
  40. package/dist/runtime/action-envelope.js.map +1 -0
  41. package/dist/runtime/environment-resolver.d.ts +36 -0
  42. package/dist/runtime/environment-resolver.js +138 -0
  43. package/dist/runtime/environment-resolver.js.map +1 -0
  44. package/dist/runtime/home-dir.js +1 -1
  45. package/dist/runtime/home-dir.js.map +1 -1
  46. package/dist/runtime/index.d.ts +4 -0
  47. package/dist/runtime/index.js +4 -0
  48. package/dist/runtime/index.js.map +1 -1
  49. package/dist/runtime/kube-context.d.ts +16 -0
  50. package/dist/runtime/kube-context.js +63 -0
  51. package/dist/runtime/kube-context.js.map +1 -0
  52. package/dist/runtime/risk-classifier.d.ts +38 -0
  53. package/dist/runtime/risk-classifier.js +121 -0
  54. package/dist/runtime/risk-classifier.js.map +1 -0
  55. package/dist/schema/environments.d.ts +215 -0
  56. package/dist/schema/environments.js +101 -0
  57. package/dist/schema/environments.js.map +1 -0
  58. package/dist/schema/index.d.ts +408 -0
  59. package/dist/schema/index.js +8 -0
  60. package/dist/schema/index.js.map +1 -1
  61. package/dist/schema/policies.d.ts +139 -0
  62. package/dist/schema/policies.js +39 -0
  63. package/dist/schema/policies.js.map +1 -1
  64. package/dist/schema/risk.d.ts +131 -0
  65. package/dist/schema/risk.js +87 -0
  66. package/dist/schema/risk.js.map +1 -0
  67. package/package.json +1 -1
  68. package/dist/cli/pack/pause-check.js.map +0 -1
@@ -0,0 +1,215 @@
1
+ import { z } from "zod";
2
+ export declare const EnvironmentNameSchema: z.ZodEnum<["production", "staging", "dev", "local"]>;
3
+ export declare const MatchableEnvironmentSchema: z.ZodEnum<["production", "staging", "dev", "local", "unknown"]>;
4
+ export declare const EnvironmentResolverSchema: z.ZodObject<{
5
+ name: z.ZodString;
6
+ environment: z.ZodEnum<["production", "staging", "dev", "local"]>;
7
+ signals: z.ZodEffects<z.ZodObject<{
8
+ branch_patterns: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
9
+ env_var_patterns: z.ZodOptional<z.ZodArray<z.ZodObject<{
10
+ var: z.ZodString;
11
+ patterns: z.ZodArray<z.ZodString, "many">;
12
+ }, "strict", z.ZodTypeAny, {
13
+ var: string;
14
+ patterns: string[];
15
+ }, {
16
+ var: string;
17
+ patterns: string[];
18
+ }>, "many">>;
19
+ kube_context_patterns: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
20
+ kube_namespace_patterns: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
21
+ }, "strict", z.ZodTypeAny, {
22
+ branch_patterns?: string[] | undefined;
23
+ env_var_patterns?: {
24
+ var: string;
25
+ patterns: string[];
26
+ }[] | undefined;
27
+ kube_context_patterns?: string[] | undefined;
28
+ kube_namespace_patterns?: string[] | undefined;
29
+ }, {
30
+ branch_patterns?: string[] | undefined;
31
+ env_var_patterns?: {
32
+ var: string;
33
+ patterns: string[];
34
+ }[] | undefined;
35
+ kube_context_patterns?: string[] | undefined;
36
+ kube_namespace_patterns?: string[] | undefined;
37
+ }>, {
38
+ branch_patterns?: string[] | undefined;
39
+ env_var_patterns?: {
40
+ var: string;
41
+ patterns: string[];
42
+ }[] | undefined;
43
+ kube_context_patterns?: string[] | undefined;
44
+ kube_namespace_patterns?: string[] | undefined;
45
+ }, {
46
+ branch_patterns?: string[] | undefined;
47
+ env_var_patterns?: {
48
+ var: string;
49
+ patterns: string[];
50
+ }[] | undefined;
51
+ kube_context_patterns?: string[] | undefined;
52
+ kube_namespace_patterns?: string[] | undefined;
53
+ }>;
54
+ }, "strict", z.ZodTypeAny, {
55
+ name: string;
56
+ environment: "production" | "staging" | "dev" | "local";
57
+ signals: {
58
+ branch_patterns?: string[] | undefined;
59
+ env_var_patterns?: {
60
+ var: string;
61
+ patterns: string[];
62
+ }[] | undefined;
63
+ kube_context_patterns?: string[] | undefined;
64
+ kube_namespace_patterns?: string[] | undefined;
65
+ };
66
+ }, {
67
+ name: string;
68
+ environment: "production" | "staging" | "dev" | "local";
69
+ signals: {
70
+ branch_patterns?: string[] | undefined;
71
+ env_var_patterns?: {
72
+ var: string;
73
+ patterns: string[];
74
+ }[] | undefined;
75
+ kube_context_patterns?: string[] | undefined;
76
+ kube_namespace_patterns?: string[] | undefined;
77
+ };
78
+ }>;
79
+ export declare const EnvironmentsSchema: z.ZodEffects<z.ZodObject<{
80
+ resolvers: z.ZodDefault<z.ZodArray<z.ZodObject<{
81
+ name: z.ZodString;
82
+ environment: z.ZodEnum<["production", "staging", "dev", "local"]>;
83
+ signals: z.ZodEffects<z.ZodObject<{
84
+ branch_patterns: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
85
+ env_var_patterns: z.ZodOptional<z.ZodArray<z.ZodObject<{
86
+ var: z.ZodString;
87
+ patterns: z.ZodArray<z.ZodString, "many">;
88
+ }, "strict", z.ZodTypeAny, {
89
+ var: string;
90
+ patterns: string[];
91
+ }, {
92
+ var: string;
93
+ patterns: string[];
94
+ }>, "many">>;
95
+ kube_context_patterns: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
96
+ kube_namespace_patterns: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
97
+ }, "strict", z.ZodTypeAny, {
98
+ branch_patterns?: string[] | undefined;
99
+ env_var_patterns?: {
100
+ var: string;
101
+ patterns: string[];
102
+ }[] | undefined;
103
+ kube_context_patterns?: string[] | undefined;
104
+ kube_namespace_patterns?: string[] | undefined;
105
+ }, {
106
+ branch_patterns?: string[] | undefined;
107
+ env_var_patterns?: {
108
+ var: string;
109
+ patterns: string[];
110
+ }[] | undefined;
111
+ kube_context_patterns?: string[] | undefined;
112
+ kube_namespace_patterns?: string[] | undefined;
113
+ }>, {
114
+ branch_patterns?: string[] | undefined;
115
+ env_var_patterns?: {
116
+ var: string;
117
+ patterns: string[];
118
+ }[] | undefined;
119
+ kube_context_patterns?: string[] | undefined;
120
+ kube_namespace_patterns?: string[] | undefined;
121
+ }, {
122
+ branch_patterns?: string[] | undefined;
123
+ env_var_patterns?: {
124
+ var: string;
125
+ patterns: string[];
126
+ }[] | undefined;
127
+ kube_context_patterns?: string[] | undefined;
128
+ kube_namespace_patterns?: string[] | undefined;
129
+ }>;
130
+ }, "strict", z.ZodTypeAny, {
131
+ name: string;
132
+ environment: "production" | "staging" | "dev" | "local";
133
+ signals: {
134
+ branch_patterns?: string[] | undefined;
135
+ env_var_patterns?: {
136
+ var: string;
137
+ patterns: string[];
138
+ }[] | undefined;
139
+ kube_context_patterns?: string[] | undefined;
140
+ kube_namespace_patterns?: string[] | undefined;
141
+ };
142
+ }, {
143
+ name: string;
144
+ environment: "production" | "staging" | "dev" | "local";
145
+ signals: {
146
+ branch_patterns?: string[] | undefined;
147
+ env_var_patterns?: {
148
+ var: string;
149
+ patterns: string[];
150
+ }[] | undefined;
151
+ kube_context_patterns?: string[] | undefined;
152
+ kube_namespace_patterns?: string[] | undefined;
153
+ };
154
+ }>, "many">>;
155
+ }, "strict", z.ZodTypeAny, {
156
+ resolvers: {
157
+ name: string;
158
+ environment: "production" | "staging" | "dev" | "local";
159
+ signals: {
160
+ branch_patterns?: string[] | undefined;
161
+ env_var_patterns?: {
162
+ var: string;
163
+ patterns: string[];
164
+ }[] | undefined;
165
+ kube_context_patterns?: string[] | undefined;
166
+ kube_namespace_patterns?: string[] | undefined;
167
+ };
168
+ }[];
169
+ }, {
170
+ resolvers?: {
171
+ name: string;
172
+ environment: "production" | "staging" | "dev" | "local";
173
+ signals: {
174
+ branch_patterns?: string[] | undefined;
175
+ env_var_patterns?: {
176
+ var: string;
177
+ patterns: string[];
178
+ }[] | undefined;
179
+ kube_context_patterns?: string[] | undefined;
180
+ kube_namespace_patterns?: string[] | undefined;
181
+ };
182
+ }[] | undefined;
183
+ }>, {
184
+ resolvers: {
185
+ name: string;
186
+ environment: "production" | "staging" | "dev" | "local";
187
+ signals: {
188
+ branch_patterns?: string[] | undefined;
189
+ env_var_patterns?: {
190
+ var: string;
191
+ patterns: string[];
192
+ }[] | undefined;
193
+ kube_context_patterns?: string[] | undefined;
194
+ kube_namespace_patterns?: string[] | undefined;
195
+ };
196
+ }[];
197
+ }, {
198
+ resolvers?: {
199
+ name: string;
200
+ environment: "production" | "staging" | "dev" | "local";
201
+ signals: {
202
+ branch_patterns?: string[] | undefined;
203
+ env_var_patterns?: {
204
+ var: string;
205
+ patterns: string[];
206
+ }[] | undefined;
207
+ kube_context_patterns?: string[] | undefined;
208
+ kube_namespace_patterns?: string[] | undefined;
209
+ };
210
+ }[] | undefined;
211
+ }>;
212
+ export type EnvironmentName = z.infer<typeof EnvironmentNameSchema>;
213
+ export type MatchableEnvironment = z.infer<typeof MatchableEnvironmentSchema>;
214
+ export type EnvironmentResolver = z.infer<typeof EnvironmentResolverSchema>;
215
+ export type EnvironmentsConfig = z.infer<typeof EnvironmentsSchema>;
@@ -0,0 +1,101 @@
1
+ import { z } from "zod";
2
+ // Environment-resolution vocabulary — Phase 7 #1 anchor.
3
+ //
4
+ // STATUS: schema vocabulary only. `harness validate` parses and
5
+ // validates an `environments:` block, but no runtime surface reads it
6
+ // yet. The Context Resolver that consumes `environments.resolvers[]` to
7
+ // classify an Action Envelope as production / staging / dev / local /
8
+ // unknown lands in Phase 7 #4 (see docs/ROADMAP.md and
9
+ // docs/risk-gate.md). Until then an `environments:` block is inert,
10
+ // validated config.
11
+ //
12
+ // "Unknown is not safe": when no resolver matches, the resolved
13
+ // environment is `unknown`. Policy `when.environment.name` clauses are
14
+ // expected to treat `unknown` as approval-worthy, not allow-by-default.
15
+ // That enforcement semantic lives with the Phase 7 #4/#5 runtime; the
16
+ // anchor only fixes the config shape.
17
+ //
18
+ // Design source: lava-ice-logs/2026-04-30/harness-risk-gate-extension.md.
19
+ // The environment names a resolver may assert. `unknown` is the
20
+ // implicit fallback when nothing matches and is deliberately NOT in
21
+ // this set: a resolver that "asserts unknown" is a contradiction.
22
+ export const EnvironmentNameSchema = z.enum([
23
+ "production",
24
+ "staging",
25
+ "dev",
26
+ "local",
27
+ ]);
28
+ // The environment names a policy `when.environment.name` clause may
29
+ // test. Identical to the resolver set plus `unknown`, so a policy can
30
+ // gate the no-resolver-matched case ("unknown is not safe").
31
+ export const MatchableEnvironmentSchema = z.enum([
32
+ "production",
33
+ "staging",
34
+ "dev",
35
+ "local",
36
+ "unknown",
37
+ ]);
38
+ // A signal that fires when a named environment variable's value
39
+ // contains any of the listed substrings. Substring, not regex — kept
40
+ // deliberately blunt for v1; see docs/risk-gate.md.
41
+ const EnvVarSignalSchema = z
42
+ .object({
43
+ var: z.string().min(1),
44
+ patterns: z.array(z.string().min(1)).min(1),
45
+ })
46
+ .strict();
47
+ // The four signal kinds a resolver can combine. Every field is
48
+ // optional, but at least one must be present — a resolver with no
49
+ // signals can never fire and is a config error. Pattern match
50
+ // semantics (glob vs substring vs regex per kind) are defined by the
51
+ // Phase 7 #4 resolver runtime and documented in docs/risk-gate.md; the
52
+ // anchor stores them as plain non-empty strings.
53
+ const EnvironmentSignalsSchema = z
54
+ .object({
55
+ branch_patterns: z.array(z.string().min(1)).min(1).optional(),
56
+ env_var_patterns: z.array(EnvVarSignalSchema).min(1).optional(),
57
+ kube_context_patterns: z.array(z.string().min(1)).min(1).optional(),
58
+ kube_namespace_patterns: z.array(z.string().min(1)).min(1).optional(),
59
+ })
60
+ .strict()
61
+ .superRefine((signals, ctx) => {
62
+ const hasSignal = signals.branch_patterns !== undefined ||
63
+ signals.env_var_patterns !== undefined ||
64
+ signals.kube_context_patterns !== undefined ||
65
+ signals.kube_namespace_patterns !== undefined;
66
+ if (!hasSignal) {
67
+ ctx.addIssue({
68
+ code: z.ZodIssueCode.custom,
69
+ path: [],
70
+ message: "resolver signals must declare at least one of: branch_patterns, env_var_patterns, kube_context_patterns, kube_namespace_patterns",
71
+ });
72
+ }
73
+ });
74
+ export const EnvironmentResolverSchema = z
75
+ .object({
76
+ name: z.string().min(1),
77
+ // The environment this resolver asserts when any of its signals
78
+ // match.
79
+ environment: EnvironmentNameSchema,
80
+ signals: EnvironmentSignalsSchema,
81
+ })
82
+ .strict();
83
+ export const EnvironmentsSchema = z
84
+ .object({
85
+ resolvers: z.array(EnvironmentResolverSchema).default([]),
86
+ })
87
+ .strict()
88
+ .superRefine((envs, ctx) => {
89
+ const seen = new Set();
90
+ envs.resolvers.forEach((r, i) => {
91
+ if (seen.has(r.name)) {
92
+ ctx.addIssue({
93
+ code: z.ZodIssueCode.custom,
94
+ path: ["resolvers", i, "name"],
95
+ message: `duplicate environment resolver name: ${r.name}`,
96
+ });
97
+ }
98
+ seen.add(r.name);
99
+ });
100
+ });
101
+ //# sourceMappingURL=environments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"environments.js","sourceRoot":"","sources":["../../src/schema/environments.ts"],"names":[],"mappings":"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"}