import { type PostSynthCheck, type PostSynthContext, type PostSynthDiagnostic } from "./post-synth.js"; import { armSandboxPolicyExecution, isSandboxPolicyExecutionArmed, resetSandboxPolicyExecutionForTests } from "./policy-import.js"; import type { EncodablePolicyBuildResult } from "../discovery/sandbox/policy-wire.js"; /** * chant #1131 — decides WHERE a project's `lint.policies` checks run. * * A policy is project-authored code. Every other piece of project code moved * behind the `--sandbox` boundary in chant #1045 (run-fallback source), #1093 * (composite factories, constructors, intrinsic tags) and #1113 * (`chant.config.ts`), and all three had to leave this one out: the config * declares its policies as *paths*, so putting the config behind the boundary * did not put them there with it. `chant build` imported each policy module and * called its `check` function in the CLI's own process, after discovery was * over, with the CLI's filesystem, network, environment and process-spawn * access. This module closes it. * * ## Why an armed process mode rather than a threaded option * * The same reason `../config-sandbox.ts` gives. `./policy.ts`'s * `loadPolicyChecks` is exported from chant-core's public surface and called * from more than one place (`../cli/commands/build.ts` for a build, and * `evaluateProjectPolicies` for the `policyGate` Op step). Threading a * `sandbox` flag to each is fail-OPEN: miss one and project code executes in * the CLI process with nothing to notice. Arming the process once, before any * policy is loaded, is fail-CLOSED — `loadPolicyChecks` REFUSES while armed, so * a call site nobody remembered gets a loud error rather than a silent * execution. * * ## What arms it * * Both ways of turning sandboxing on, unlike `../config-sandbox.ts`. That * asymmetry is not an oversight: the config has a bootstrap limit (reading * `build.sandbox` out of `chant.config.ts` means running it, so only the CLI * flag, known before any config is touched, can cover the config's own * evaluation). Policies have no such limit — they are loaded long after the * config is known — so `build.sandbox: true` in a project's config sandboxes * them just as `--sandbox` does, and `../cli/commands/build.ts` arms this from * the RESOLVED value. * * There is deliberately no disarm: a security mode that can be turned off * partway through a process is not one. */ /** * The mode itself lives on `./policy-import.ts` — the leaf module that actually * performs an in-process policy import, so the refusal sits on the narrowest * possible thing and `./policy.ts` can consult it without importing this file * (which imports `./policy.ts`). Re-exported here because this is where the * decision is documented and where callers look. * * `armSandboxPolicyExecution` is called from `../cli/commands/build.ts` once * `build.sandbox`/`--sandbox` has resolved, and from `../cli/main.ts` off the * parsed flag. */ export { armSandboxPolicyExecution, isSandboxPolicyExecutionArmed, resetSandboxPolicyExecutionForTests }; export interface ProjectPolicyRun { /** `lint.policies` as declared in the config — relative paths, resolved against {@link configDir}. */ policies: readonly string[]; /** The `chant.config.*` directory (`lint.policies` paths are relative to it), also the child's read allowance. */ configDir: string; /** The merged, serialized build result the checks run over. */ buildResult: EncodablePolicyBuildResult & PostSynthContext["buildResult"]; /** `--env`, else `ownership.env`. Becomes `ctx.env`. */ env?: string; /** * Checks the caller already loaded into THIS process, before the build ran. * * `chant build` has always loaded `lint.policies` up front rather than at the * point of use, so a policy path that doesn't resolve fails the command * immediately — including when the build itself goes on to fail, which is * exactly when a typo'd path would otherwise go unnoticed. Preserving that * for the unsandboxed path is the whole reason this field exists. * * Ignored when armed: under `--sandbox` there is nothing loaded here to pass, * and `loadPolicyChecks` refuses outright. */ preloaded?: PostSynthCheck[]; } /** * Run a project's organizational policy checks over a finished build and return * their diagnostics. Sandboxed in a post-merge child when armed, in-process * otherwise. * * The unarmed path is byte-for-byte what `chant build` has always done: load * the modules, hand every check one `PostSynthContext`, concatenate what they * return. The armed path does the same thing on the other side of a process * boundary — see `../discovery/sandbox/policy-run.ts`. */ export declare function runProjectPolicies(run: ProjectPolicyRun): Promise; //# sourceMappingURL=policy-sandbox.d.ts.map