🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@agent-pattern-labs/iso-preflight

Package Overview
Dependencies
Maintainers
1
Versions
2
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@agent-pattern-labs/iso-preflight - npm Package Compare versions

Comparing version
0.1.1
to
0.1.2
+49
-7
dist/preflight.js
import { isJsonObject, isJsonValue } from "./json.js";
const DEFAULT_SKIP_STATUSES = ["skip", "skipped"];
const DEFAULT_BLOCK_STATUSES = ["block", "blocked", "fail", "failed"];
const DEFAULT_PASS_STATUSES = ["pass", "passed", "ok", "allow", "allowed", "ready"];
export function loadPreflightConfig(input) {

@@ -11,5 +12,7 @@ if (!isJsonObject(input))

throw new Error("preflight config workflows must be an array");
const workflows = input.workflows.map((workflow, index) => normalizeWorkflow(workflow, `workflows[${index}]`));
assertUnique(workflows.map((workflow) => workflow.name), "workflow name");
return {
version: 1,
workflows: input.workflows.map((workflow, index) => normalizeWorkflow(workflow, `workflows[${index}]`)),
workflows,
};

@@ -34,2 +37,3 @@ }

const planned = candidateSet.candidates.map((candidate, index) => planCandidate(workflow, candidate, index));
assertUnique(planned.map((candidate) => candidate.id), "candidate id");
const blocked = planned.filter((candidate) => candidate.state === "blocked");

@@ -105,3 +109,5 @@ const skipped = planned.filter((candidate) => candidate.state === "skipped");

throw new Error(`${label} must be an array`);
return input.map((gate, index) => normalizeGate(gate, `${label}[${index}]`));
const gates = input.map((gate, index) => normalizeGate(gate, `${label}[${index}]`));
assertUnique(gates.map((gate) => gate.id), "gate id");
return gates;
}

@@ -124,6 +130,23 @@ function normalizeGate(input, label) {

throw new Error(`${label} must be an object`);
return {
const policy = {
passStatuses: optionalStringArray(input.passStatuses, `${label}.passStatuses`),
skipStatuses: optionalStringArray(input.skipStatuses, `${label}.skipStatuses`),
blockStatuses: optionalStringArray(input.blockStatuses, `${label}.blockStatuses`),
};
const groups = [
["pass", policy.passStatuses ?? DEFAULT_PASS_STATUSES],
["skip", policy.skipStatuses ?? DEFAULT_SKIP_STATUSES],
["block", policy.blockStatuses ?? DEFAULT_BLOCK_STATUSES],
];
const owners = new Map();
for (const [group, statuses] of groups) {
for (const status of statuses) {
const normalized = normalizeStatus(status);
const owner = owners.get(normalized);
if (owner)
throw new Error(`${label} status "${status}" appears in both ${owner} and ${group} statuses`);
owners.set(normalized, group);
}
}
return policy;
}

@@ -135,3 +158,5 @@ function optionalSteps(input, label) {

throw new Error(`${label} must be an array`);
return input.map((step, index) => normalizeStep(step, `${label}[${index}]`));
const steps = input.map((step, index) => normalizeStep(step, `${label}[${index}]`));
assertUnique(steps.map((step) => step.id), "step id");
return steps;
}

@@ -212,2 +237,3 @@ function normalizeStep(input, label) {

const blockStatuses = statusSet(workflow.gatePolicy?.blockStatuses ?? DEFAULT_BLOCK_STATUSES);
const passStatuses = statusSet(workflow.gatePolicy?.passStatuses ?? DEFAULT_PASS_STATUSES);
for (const gate of gates) {

@@ -231,4 +257,12 @@ const status = normalizeStatus(gate.status);

}
else if (!passStatuses.has(status)) {
issues.push({
kind: "unknown-gate-status",
gate: gate.id,
source: gate.source,
message: `gate "${gate.id}" has unknown status "${gate.status}"`,
});
}
}
const state = issues.some((issue) => issue.kind === "missing-fact" || issue.kind === "missing-source" || issue.kind === "gate-block")
const state = issues.some((issue) => issue.kind === "missing-fact" || issue.kind === "missing-source" || issue.kind === "gate-block" || issue.kind === "unknown-gate-status")
? "blocked"

@@ -331,7 +365,15 @@ : issues.some((issue) => issue.kind === "gate-skip")

return undefined;
if (!Array.isArray(value) || value.some((item) => typeof item !== "string")) {
throw new Error(`${label} must be an array of strings`);
if (!Array.isArray(value) || value.some((item) => typeof item !== "string" || !item.trim())) {
throw new Error(`${label} must be an array of non-empty strings`);
}
return value;
}
function assertUnique(values, label) {
const seen = new Set();
for (const value of values) {
if (seen.has(value))
throw new Error(`duplicate ${label} "${value}"`);
seen.add(value);
}
}
//# sourceMappingURL=preflight.js.map
+2
-1

@@ -25,2 +25,3 @@ export type JsonPrimitive = string | number | boolean | null;

export interface PreflightGatePolicy {
passStatuses?: string[];
skipStatuses?: string[];

@@ -86,3 +87,3 @@ blockStatuses?: string[];

export interface PreflightIssue {
kind: "missing-fact" | "missing-source" | "gate-skip" | "gate-block";
kind: "missing-fact" | "missing-source" | "gate-skip" | "gate-block" | "unknown-gate-status";
message: string;

@@ -89,0 +90,0 @@ fact?: string;

{
"name": "@agent-pattern-labs/iso-preflight",
"version": "0.1.1",
"version": "0.1.2",
"description": "Deterministic preflight planning for AI-agent workflows: validate file-backed facts, apply gates, and produce bounded dispatch rounds without model calls.",

@@ -5,0 +5,0 @@ "license": "MIT",

@@ -68,2 +68,3 @@ # @agent-pattern-labs/iso-preflight

"gatePolicy": {
"passStatuses": ["pass"],
"skipStatuses": ["skip"],

@@ -84,2 +85,4 @@ "blockStatuses": ["block", "fail"]

`sourceRequiredFacts` must use the object form with a source.
Gate statuses are fail-closed: every status must appear in the workflow's pass,
skip, or block allowlist. Duplicate candidate IDs are rejected.

@@ -86,0 +89,0 @@ ```json