@intentius/chant 0.51.0 → 0.52.1
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/dist/cli/build-options.d.ts +68 -0
- package/dist/cli/build-options.d.ts.map +1 -0
- package/dist/cli/commands/build.d.ts.map +1 -1
- package/dist/cli/handlers/lifecycle.d.ts.map +1 -1
- package/dist/cli/handlers/run.d.ts +0 -21
- package/dist/cli/handlers/run.d.ts.map +1 -1
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/discovery/fold-import.d.ts.map +1 -1
- package/dist/lexicon.d.ts +10 -9
- package/dist/lexicon.d.ts.map +1 -1
- package/dist/lifecycle/assert-live.d.ts +2 -3
- package/dist/lifecycle/assert-live.d.ts.map +1 -1
- package/dist/lifecycle/change-set.d.ts +23 -0
- package/dist/lifecycle/change-set.d.ts.map +1 -1
- package/dist/lint/policy.d.ts +16 -0
- package/dist/lint/policy.d.ts.map +1 -1
- package/dist/op/local-executor.d.ts +15 -1
- package/dist/op/local-executor.d.ts.map +1 -1
- package/dist/ownership.d.ts +5 -4
- package/dist/ownership.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/cli/build-options.test.ts +101 -0
- package/src/cli/build-options.ts +109 -0
- package/src/cli/commands/build.ts +24 -53
- package/src/cli/handlers/lifecycle.test.ts +19 -0
- package/src/cli/handlers/lifecycle.ts +14 -7
- package/src/cli/handlers/run.test.ts +96 -0
- package/src/cli/handlers/run.ts +37 -1
- package/src/cli/main.ts +2 -0
- package/src/discovery/fold-import.test.ts +102 -0
- package/src/discovery/fold-import.ts +54 -4
- package/src/lexicon.ts +10 -9
- package/src/lifecycle/assert-live.ts +2 -3
- package/src/lifecycle/change-set.test.ts +144 -1
- package/src/lifecycle/change-set.ts +133 -11
- package/src/lint/policy-build-parity.test.ts +232 -0
- package/src/lint/policy.ts +51 -6
- package/src/op/local-executor.ts +28 -0
- package/src/ownership.ts +5 -4
package/src/lint/policy.ts
CHANGED
|
@@ -7,6 +7,8 @@ import { resolve, dirname } from "node:path";
|
|
|
7
7
|
import { loadChantConfigUpward, resolveOwnershipEnv, resolveOwnershipMarker } from "../config";
|
|
8
8
|
import { resolveBuildParams } from "../build-params";
|
|
9
9
|
import { resolveProjectLexicons, loadPlugins } from "../cli/plugins";
|
|
10
|
+
import { resolveBuildModes, resolveProjectBuildOptions } from "../cli/build-options";
|
|
11
|
+
import { formatWarning } from "../cli/format";
|
|
10
12
|
import { build } from "../build";
|
|
11
13
|
import { runPostSynthChecks, isPostSynthCheck } from "./post-synth";
|
|
12
14
|
import type { PostSynthCheck, PostSynthDiagnostic } from "./post-synth";
|
|
@@ -63,6 +65,15 @@ export interface PolicyEvaluation {
|
|
|
63
65
|
* of the finding just vanishing.
|
|
64
66
|
*/
|
|
65
67
|
suppressed: PostSynthDiagnostic[];
|
|
68
|
+
/**
|
|
69
|
+
* chant #2002 — divergences between this evaluation and what `chant build`
|
|
70
|
+
* would do, named rather than left silent. Today that is a project whose
|
|
71
|
+
* resolved `build.sandbox` is `true`: the gate builds unsandboxed, because
|
|
72
|
+
* running it inside the boundary needs the per-execution arming decision
|
|
73
|
+
* tracked on #1157. Also written to stderr — the gate's caller is an
|
|
74
|
+
* activity wrapper that surfaces output, not a structured result.
|
|
75
|
+
*/
|
|
76
|
+
warnings: string[];
|
|
66
77
|
}
|
|
67
78
|
|
|
68
79
|
/**
|
|
@@ -70,6 +81,13 @@ export interface PolicyEvaluation {
|
|
|
70
81
|
* standalone — used by the `policyGate` Op step to gate an apply on the same
|
|
71
82
|
* organizational policy `chant build` enforces. Loads the project's lexicons,
|
|
72
83
|
* builds, then runs the policy pack with `env` (explicit, else `ownership.env`).
|
|
84
|
+
*
|
|
85
|
+
* chant #2002 — "the same organizational policy `chant build` enforces" only
|
|
86
|
+
* holds if it is the same build. The build options are assembled by
|
|
87
|
+
* `../cli/build-options.ts`'s `resolveProjectBuildOptions`, the single function
|
|
88
|
+
* `chant build` also calls, rather than by a second list here; a build option
|
|
89
|
+
* added for one caller and not the other is what let a gate pass a build
|
|
90
|
+
* `chant build` fails.
|
|
73
91
|
*/
|
|
74
92
|
export async function evaluateProjectPolicies(opts: {
|
|
75
93
|
path: string;
|
|
@@ -96,10 +114,37 @@ export async function evaluateProjectPolicies(opts: {
|
|
|
96
114
|
}
|
|
97
115
|
const env = opts.env ?? resolveOwnershipEnv(config, params.provenance);
|
|
98
116
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
117
|
+
// chant #2002 — the build options come from the shared assembler
|
|
118
|
+
// (`../cli/build-options.ts`), the same one `chant build` uses, so the gate
|
|
119
|
+
// decides on the project `chant build` produces: folded by default (#1134),
|
|
120
|
+
// with the project's config reaching the serializers, and with
|
|
121
|
+
// config-declared build roots contributing their entities. Assembling a
|
|
122
|
+
// second, shorter list here is what let the two drift apart.
|
|
123
|
+
const modes = resolveBuildModes(config);
|
|
124
|
+
const warnings: string[] = [];
|
|
125
|
+
if (modes.sandbox) {
|
|
126
|
+
// Resolved, reported, and not yet honoured. Building inside the boundary
|
|
127
|
+
// needs per-execution arming (#1157) — until that lands, saying so is the
|
|
128
|
+
// difference between a known gap and a silent one.
|
|
129
|
+
warnings.push(
|
|
130
|
+
`build.sandbox is enabled for this project, but the policy gate builds it in this process — the project's source files and its lint.policies modules execute here, unsandboxed (chant #1157). Run \`chant build --sandbox\` for a sandboxed build of the same project.`,
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
for (const warning of warnings) console.error(formatWarning({ message: warning }));
|
|
134
|
+
|
|
135
|
+
const result = await build(
|
|
136
|
+
buildPath,
|
|
137
|
+
serializers,
|
|
138
|
+
undefined,
|
|
139
|
+
resolveProjectBuildOptions({
|
|
140
|
+
config,
|
|
141
|
+
configDir,
|
|
142
|
+
plugins,
|
|
143
|
+
modes: { fold: modes.fold, sandbox: false },
|
|
144
|
+
ownership: resolveOwnershipMarker(config, params.provenance),
|
|
145
|
+
buildParams: params.provenance,
|
|
146
|
+
}),
|
|
147
|
+
);
|
|
103
148
|
if (result.errors.length > 0) {
|
|
104
149
|
throw new Error("Build failed — cannot evaluate policy on a broken build");
|
|
105
150
|
}
|
|
@@ -108,7 +153,7 @@ export async function evaluateProjectPolicies(opts: {
|
|
|
108
153
|
? await loadPolicyChecks(config.lint.policies, configDir)
|
|
109
154
|
: [];
|
|
110
155
|
if (checks.length === 0) {
|
|
111
|
-
return { diagnostics: [], violations: [], env, suppressed: [] };
|
|
156
|
+
return { diagnostics: [], violations: [], env, suppressed: [], warnings };
|
|
112
157
|
}
|
|
113
158
|
|
|
114
159
|
const raw = runPostSynthChecks(checks, result, env);
|
|
@@ -118,5 +163,5 @@ export async function evaluateProjectPolicies(opts: {
|
|
|
118
163
|
// fails on it either, and vice versa for a check turned UP to "error".
|
|
119
164
|
const { diagnostics, suppressed } = applyConfiguredSeverity(raw, config.lint?.rules);
|
|
120
165
|
const violations = diagnostics.filter((d) => d.severity === "error");
|
|
121
|
-
return { diagnostics, violations, env, suppressed };
|
|
166
|
+
return { diagnostics, violations, env, suppressed, warnings };
|
|
122
167
|
}
|
package/src/op/local-executor.ts
CHANGED
|
@@ -136,6 +136,34 @@ export function findGate(config: OpConfig): GateStep | undefined {
|
|
|
136
136
|
return undefined;
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
+
/**
|
|
140
|
+
* Find the first `policyGate` step anywhere in the Op (phases + `onFailure`,
|
|
141
|
+
* including steps nested inside effect steps), if any.
|
|
142
|
+
*
|
|
143
|
+
* chant #2003 — `--sandbox` is a GLOBAL flag (`../cli/registry.ts`), and
|
|
144
|
+
* `../cli/main.ts` arms the process-wide policy latch off it for every command,
|
|
145
|
+
* `chant run` included. A `policyGate` step then reaches `loadPolicyChecks`,
|
|
146
|
+
* which refuses while armed with a message written for a chant maintainer —
|
|
147
|
+
* shown to a user who passed a documented flag. The combination cannot be
|
|
148
|
+
* honoured until the gate can build and load policies inside the boundary
|
|
149
|
+
* (#1157), so both `chant run` paths pre-flight it with this and refuse before
|
|
150
|
+
* any phase executes, the same shape as {@link findGate}'s pre-flight.
|
|
151
|
+
*/
|
|
152
|
+
export function findPolicyGateStep(config: OpConfig): ActivityStep | undefined {
|
|
153
|
+
const all = [...config.phases, ...(config.onFailure ?? [])];
|
|
154
|
+
const isPolicyGate = (s: StepDefinition): s is ActivityStep => isActivity(s) && s.fn === "policyGate";
|
|
155
|
+
for (const phase of all) {
|
|
156
|
+
for (const step of phase.steps) {
|
|
157
|
+
if (isPolicyGate(step)) return step;
|
|
158
|
+
if (isEffect(step)) {
|
|
159
|
+
const nested = step.steps.find(isPolicyGate);
|
|
160
|
+
if (nested) return nested;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return undefined;
|
|
165
|
+
}
|
|
166
|
+
|
|
139
167
|
const sleep = (ms: number): Promise<void> => new Promise((r) => setTimeout(r, ms));
|
|
140
168
|
|
|
141
169
|
/**
|
package/src/ownership.ts
CHANGED
|
@@ -133,10 +133,11 @@ export function readOwnership(
|
|
|
133
133
|
* A read path that can resolve an ownership verdict from the marker (#1348).
|
|
134
134
|
*
|
|
135
135
|
* Per-path rather than per-lexicon because the answer genuinely differs by
|
|
136
|
-
* path
|
|
137
|
-
* on
|
|
138
|
-
* `describe-stack-resources`,
|
|
139
|
-
*
|
|
136
|
+
* path — in granularity as much as in availability. aws stamps tags at
|
|
137
|
+
* synthesis and reads them per resource on the deep observation and on live
|
|
138
|
+
* export; its `describeResources` is sourced from `describe-stack-resources`,
|
|
139
|
+
* which returns no per-resource tags, so it resolves the verdict from the
|
|
140
|
+
* STACK's own tags instead (#1998).
|
|
140
141
|
*/
|
|
141
142
|
export type OwnershipReadPath = "describeResources" | "observeResourcesDeep" | "exportResources";
|
|
142
143
|
|