codex-openai-proxy 0.1.0-rc.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.
- package/LICENSE +21 -0
- package/README.md +253 -0
- package/dist/app-server/app-server.d.ts +39 -0
- package/dist/app-server/app-server.js +261 -0
- package/dist/app-server/app-server.js.map +1 -0
- package/dist/app-server/auth.d.ts +16 -0
- package/dist/app-server/auth.js +102 -0
- package/dist/app-server/auth.js.map +1 -0
- package/dist/app-server/json-rpc.d.ts +29 -0
- package/dist/app-server/json-rpc.js +141 -0
- package/dist/app-server/json-rpc.js.map +1 -0
- package/dist/bin.d.ts +2 -0
- package/dist/bin.js +11 -0
- package/dist/bin.js.map +1 -0
- package/dist/cli/cli.d.ts +6 -0
- package/dist/cli/cli.js +319 -0
- package/dist/cli/cli.js.map +1 -0
- package/dist/continuation/state.d.ts +71 -0
- package/dist/continuation/state.js +460 -0
- package/dist/continuation/state.js.map +1 -0
- package/dist/core/abort.d.ts +13 -0
- package/dist/core/abort.js +74 -0
- package/dist/core/abort.js.map +1 -0
- package/dist/core/canonical.d.ts +6 -0
- package/dist/core/canonical.js +22 -0
- package/dist/core/canonical.js.map +1 -0
- package/dist/core/config.d.ts +33 -0
- package/dist/core/config.js +139 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/logger.d.ts +17 -0
- package/dist/core/logger.js +44 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/policy.d.ts +98 -0
- package/dist/core/policy.js +242 -0
- package/dist/core/policy.js.map +1 -0
- package/dist/core/redact.d.ts +2 -0
- package/dist/core/redact.js +35 -0
- package/dist/core/redact.js.map +1 -0
- package/dist/http/chat-execute.d.ts +24 -0
- package/dist/http/chat-execute.js +491 -0
- package/dist/http/chat-execute.js.map +1 -0
- package/dist/http/chat-normalize.d.ts +100 -0
- package/dist/http/chat-normalize.js +379 -0
- package/dist/http/chat-normalize.js.map +1 -0
- package/dist/http/chat-sse.d.ts +14 -0
- package/dist/http/chat-sse.js +52 -0
- package/dist/http/chat-sse.js.map +1 -0
- package/dist/http/chat-validate.d.ts +37 -0
- package/dist/http/chat-validate.js +190 -0
- package/dist/http/chat-validate.js.map +1 -0
- package/dist/http/chat.d.ts +8 -0
- package/dist/http/chat.js +137 -0
- package/dist/http/chat.js.map +1 -0
- package/dist/http/errors.d.ts +19 -0
- package/dist/http/errors.js +56 -0
- package/dist/http/errors.js.map +1 -0
- package/dist/http/server.d.ts +19 -0
- package/dist/http/server.js +254 -0
- package/dist/http/server.js.map +1 -0
- package/package.json +67 -0
- package/protocol/VERSION.json +10 -0
- package/protocol/schemas/response-mapping.schema.json +38 -0
- package/protocol/schemas/x-codex.schema.json +12 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
/** Canonicalizes JSON values so equivalent structures serialize identically. */
|
|
3
|
+
export function canonicalJson(value) {
|
|
4
|
+
if (Array.isArray(value))
|
|
5
|
+
return `[${value.map(canonicalJson).join(",")}]`;
|
|
6
|
+
if (value && typeof value === "object") {
|
|
7
|
+
const entries = Object.entries(value).sort(([a], [b]) => a.localeCompare(b));
|
|
8
|
+
return `{${entries.map(([key, item]) => `${JSON.stringify(key)}:${canonicalJson(item)}`).join(",")}}`;
|
|
9
|
+
}
|
|
10
|
+
return JSON.stringify(value) ?? "null";
|
|
11
|
+
}
|
|
12
|
+
/** Returns a stable SHA-256 binding for a JSON-compatible value. */
|
|
13
|
+
export function bindingHash(value) {
|
|
14
|
+
return createHash("sha256").update(canonicalJson(value)).digest("hex");
|
|
15
|
+
}
|
|
16
|
+
/** Narrows an unknown value to a non-null, non-array object record. */
|
|
17
|
+
export function record(value) {
|
|
18
|
+
return typeof value === "object" && value !== null && !Array.isArray(value)
|
|
19
|
+
? value
|
|
20
|
+
: undefined;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=canonical.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canonical.js","sourceRoot":"","sources":["../../src/core/canonical.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,gFAAgF;AAChF,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,KAAK,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;IAC3E,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC,CAAC,IAAI,CACnE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CACjC,CAAC;QACF,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;IACxG,CAAC;IACD,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC;AACzC,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,WAAW,CAAC,KAAc;IACxC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACzE,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,MAAM,CAAC,KAAc;IACnC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QACzE,CAAC,CAAE,KAAiC;QACpC,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/** Default maximum accepted HTTP request-body size. */
|
|
2
|
+
export declare const DEFAULT_BODY_LIMIT: number;
|
|
3
|
+
/** User-facing description of the root-namespaced state default. */
|
|
4
|
+
export declare const DEFAULT_STATE_DIR_DESCRIPTION = "per-root under ~/.codex-openai-proxy";
|
|
5
|
+
/** Fully validated configuration for the proxy server. */
|
|
6
|
+
export interface ServeOptions {
|
|
7
|
+
host: "127.0.0.1" | "::1";
|
|
8
|
+
port: number;
|
|
9
|
+
root: string;
|
|
10
|
+
codexPath: string;
|
|
11
|
+
toolTimeoutMs: number;
|
|
12
|
+
implicitToolContinuation: boolean;
|
|
13
|
+
requestTimeoutMs: number;
|
|
14
|
+
shutdownTimeoutMs: number;
|
|
15
|
+
bodyLimitBytes: number;
|
|
16
|
+
maxRequests: number;
|
|
17
|
+
logLevel: LogLevel;
|
|
18
|
+
stateDir: string;
|
|
19
|
+
}
|
|
20
|
+
/** Syntactically valid CLI options awaiting canonical root finalization. */
|
|
21
|
+
export interface ParsedServeOptions extends Omit<ServeOptions, "stateDir"> {
|
|
22
|
+
stateDir?: string | undefined;
|
|
23
|
+
}
|
|
24
|
+
/** Supported structured-log severity levels. */
|
|
25
|
+
export declare const LOG_LEVELS: readonly ["debug", "info", "warn", "error"];
|
|
26
|
+
/** A supported structured-log severity level. */
|
|
27
|
+
export type LogLevel = (typeof LOG_LEVELS)[number];
|
|
28
|
+
/** Normalizes accepted host spellings to validated loopback addresses. */
|
|
29
|
+
export declare function normalizeLoopbackHost(value: string): ServeOptions["host"];
|
|
30
|
+
/** Canonicalizes the root and derives every root-dependent serve option. */
|
|
31
|
+
export declare function resolveServeOptions(parsed: ParsedServeOptions): Promise<ServeOptions>;
|
|
32
|
+
/** Parses and validates CLI syntax without accessing the filesystem. */
|
|
33
|
+
export declare function parseServeOptions(args: readonly string[], cwd?: string): ParsedServeOptions;
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { realpathSync } from "node:fs";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { isAbsolute, join, resolve } from "node:path";
|
|
5
|
+
import { canonicalizeRoot, isPathWithinRoot } from "./policy.js";
|
|
6
|
+
/** Default maximum accepted HTTP request-body size. */
|
|
7
|
+
export const DEFAULT_BODY_LIMIT = 1024 * 1024;
|
|
8
|
+
/** User-facing description of the root-namespaced state default. */
|
|
9
|
+
export const DEFAULT_STATE_DIR_DESCRIPTION = "per-root under ~/.codex-openai-proxy";
|
|
10
|
+
/** Supported structured-log severity levels. */
|
|
11
|
+
export const LOG_LEVELS = ["debug", "info", "warn", "error"];
|
|
12
|
+
/** Normalizes accepted host spellings to validated loopback addresses. */
|
|
13
|
+
export function normalizeLoopbackHost(value) {
|
|
14
|
+
const host = value.trim().toLowerCase();
|
|
15
|
+
if (host === "127.0.0.1")
|
|
16
|
+
return "127.0.0.1";
|
|
17
|
+
if (host === "::1")
|
|
18
|
+
return "::1";
|
|
19
|
+
if (host === "localhost")
|
|
20
|
+
return "127.0.0.1";
|
|
21
|
+
throw new Error(`Invalid --host ${JSON.stringify(value)}. Only 127.0.0.1, ::1, and localhost are allowed.`);
|
|
22
|
+
}
|
|
23
|
+
/** Parses a bounded integer CLI option. */
|
|
24
|
+
function integer(name, value, minimum, maximum) {
|
|
25
|
+
if (!/^\d+$/.test(value))
|
|
26
|
+
throw new Error(`${name} must be an integer.`);
|
|
27
|
+
const parsed = Number(value);
|
|
28
|
+
if (!Number.isSafeInteger(parsed) || parsed < minimum || parsed > maximum) {
|
|
29
|
+
throw new Error(`${name} must be between ${minimum} and ${maximum}.`);
|
|
30
|
+
}
|
|
31
|
+
return parsed;
|
|
32
|
+
}
|
|
33
|
+
/** Parses a positive duration CLI option into milliseconds. */
|
|
34
|
+
function duration(name, value) {
|
|
35
|
+
const match = /^(\d+)(ms|s|m)?$/.exec(value);
|
|
36
|
+
if (!match)
|
|
37
|
+
throw new Error(`${name} must be a duration such as 500ms, 30s, or 5m.`);
|
|
38
|
+
const amount = Number(match[1]);
|
|
39
|
+
const multiplier = match[2] === "m" ? 60_000 : match[2] === "s" ? 1_000 : 1;
|
|
40
|
+
const result = amount * multiplier;
|
|
41
|
+
if (!Number.isSafeInteger(result) || result < 1)
|
|
42
|
+
throw new Error(`${name} must be positive.`);
|
|
43
|
+
return result;
|
|
44
|
+
}
|
|
45
|
+
/** Parses an explicit true-or-false CLI option. */
|
|
46
|
+
function boolean(name, value) {
|
|
47
|
+
if (value === "true")
|
|
48
|
+
return true;
|
|
49
|
+
if (value === "false")
|
|
50
|
+
return false;
|
|
51
|
+
throw new Error(`${name} must be true or false.`);
|
|
52
|
+
}
|
|
53
|
+
/** Validates a CLI string against a fixed list and returns its member type. */
|
|
54
|
+
function oneOf(name, value, allowed) {
|
|
55
|
+
const selected = allowed.find((candidate) => candidate === value);
|
|
56
|
+
if (selected === undefined) {
|
|
57
|
+
const last = allowed.at(-1);
|
|
58
|
+
const choices = allowed.length < 2
|
|
59
|
+
? (last ?? "a supported value")
|
|
60
|
+
: `${allowed.slice(0, -1).join(", ")}, or ${last}`;
|
|
61
|
+
throw new Error(`${name} must be ${choices}.`);
|
|
62
|
+
}
|
|
63
|
+
return selected;
|
|
64
|
+
}
|
|
65
|
+
/** Builds the default per-root state directory from a canonical root. */
|
|
66
|
+
function defaultStateDir(root) {
|
|
67
|
+
const namespace = createHash("sha256")
|
|
68
|
+
.update(root)
|
|
69
|
+
.digest("hex")
|
|
70
|
+
.slice(0, 16);
|
|
71
|
+
return join(realpathSync(homedir()), ".codex-openai-proxy", namespace);
|
|
72
|
+
}
|
|
73
|
+
/** Canonicalizes the root and derives every root-dependent serve option. */
|
|
74
|
+
export async function resolveServeOptions(parsed) {
|
|
75
|
+
const canonicalRoot = await canonicalizeRoot(parsed.root);
|
|
76
|
+
const usesDefaultStateDir = parsed.stateDir === undefined;
|
|
77
|
+
const stateDir = parsed.stateDir === undefined
|
|
78
|
+
? defaultStateDir(canonicalRoot)
|
|
79
|
+
: isAbsolute(parsed.stateDir)
|
|
80
|
+
? parsed.stateDir
|
|
81
|
+
: resolve(canonicalRoot, parsed.stateDir);
|
|
82
|
+
if (usesDefaultStateDir && isPathWithinRoot(canonicalRoot, stateDir))
|
|
83
|
+
throw new Error("The default --state-dir falls inside --root; set --state-dir to a directory outside the root.");
|
|
84
|
+
return { ...parsed, root: canonicalRoot, stateDir };
|
|
85
|
+
}
|
|
86
|
+
/** Parses and validates CLI syntax without accessing the filesystem. */
|
|
87
|
+
export function parseServeOptions(args, cwd = process.cwd()) {
|
|
88
|
+
const values = new Map();
|
|
89
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
90
|
+
const token = args[index];
|
|
91
|
+
if (token === undefined || !token.startsWith("--"))
|
|
92
|
+
throw new Error(`Unexpected argument: ${token}`);
|
|
93
|
+
const equals = token.indexOf("=");
|
|
94
|
+
const name = equals < 0 ? token : token.slice(0, equals);
|
|
95
|
+
const next = equals < 0 ? args[index + 1] : token.slice(equals + 1);
|
|
96
|
+
if (next === undefined || (equals < 0 && next.startsWith("--")))
|
|
97
|
+
throw new Error(`Missing value for ${name}.`);
|
|
98
|
+
if (values.has(name))
|
|
99
|
+
throw new Error(`Duplicate option: ${name}.`);
|
|
100
|
+
values.set(name, next);
|
|
101
|
+
if (equals < 0)
|
|
102
|
+
index += 1;
|
|
103
|
+
}
|
|
104
|
+
const known = new Set([
|
|
105
|
+
"--host",
|
|
106
|
+
"--port",
|
|
107
|
+
"--root",
|
|
108
|
+
"--codex-path",
|
|
109
|
+
"--tool-timeout",
|
|
110
|
+
"--implicit-tool-continuation",
|
|
111
|
+
"--request-timeout",
|
|
112
|
+
"--shutdown-timeout",
|
|
113
|
+
"--body-limit",
|
|
114
|
+
"--max-requests",
|
|
115
|
+
"--log-level",
|
|
116
|
+
"--state-dir",
|
|
117
|
+
]);
|
|
118
|
+
for (const name of values.keys())
|
|
119
|
+
if (!known.has(name))
|
|
120
|
+
throw new Error(`Unknown option: ${name}.`);
|
|
121
|
+
const root = resolve(cwd, values.get("--root") ?? ".");
|
|
122
|
+
const stateValue = values.get("--state-dir");
|
|
123
|
+
const logLevel = oneOf("--log-level", values.get("--log-level") ?? "info", LOG_LEVELS);
|
|
124
|
+
return {
|
|
125
|
+
host: normalizeLoopbackHost(values.get("--host") ?? "127.0.0.1"),
|
|
126
|
+
port: integer("--port", values.get("--port") ?? "8787", 0, 65_535),
|
|
127
|
+
root,
|
|
128
|
+
codexPath: values.get("--codex-path") ?? "codex",
|
|
129
|
+
toolTimeoutMs: duration("--tool-timeout", values.get("--tool-timeout") ?? "5m"),
|
|
130
|
+
implicitToolContinuation: boolean("--implicit-tool-continuation", values.get("--implicit-tool-continuation") ?? "true"),
|
|
131
|
+
requestTimeoutMs: duration("--request-timeout", values.get("--request-timeout") ?? "30s"),
|
|
132
|
+
shutdownTimeoutMs: duration("--shutdown-timeout", values.get("--shutdown-timeout") ?? "10s"),
|
|
133
|
+
bodyLimitBytes: integer("--body-limit", values.get("--body-limit") ?? String(DEFAULT_BODY_LIMIT), 1, 100 * 1024 * 1024),
|
|
134
|
+
maxRequests: integer("--max-requests", values.get("--max-requests") ?? "100", 1, 10_000),
|
|
135
|
+
logLevel,
|
|
136
|
+
...(stateValue === undefined ? {} : { stateDir: stateValue }),
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { LogLevel } from "./config.js";
|
|
2
|
+
/** Receives one structured log entry. */
|
|
3
|
+
export type LogWriter = (entry: Record<string, unknown>) => void;
|
|
4
|
+
/** Paths that default-visible failure summaries must mask. */
|
|
5
|
+
export interface RedactionContext {
|
|
6
|
+
root: string;
|
|
7
|
+
sensitivePaths: readonly string[];
|
|
8
|
+
}
|
|
9
|
+
/** Structured logger with failure reporting bound to one redaction context. */
|
|
10
|
+
export interface Logger {
|
|
11
|
+
(entryLevel: LogLevel, event: string, fields?: Record<string, unknown>): void;
|
|
12
|
+
failure(event: string, fields: Record<string, unknown>, error: unknown): void;
|
|
13
|
+
}
|
|
14
|
+
/** Writes an unconfigured startup failure using the standard log envelope. */
|
|
15
|
+
export declare function writeStartupError(error: unknown): void;
|
|
16
|
+
/** Creates a structured logger filtered at the configured level. */
|
|
17
|
+
export declare function createLogger(level: LogLevel, write?: LogWriter, redaction?: RedactionContext): Logger;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { redact } from "./redact.js";
|
|
2
|
+
/** Numeric severity ordering used for log filtering. */
|
|
3
|
+
const priorities = {
|
|
4
|
+
debug: 10,
|
|
5
|
+
info: 20,
|
|
6
|
+
warn: 30,
|
|
7
|
+
error: 40,
|
|
8
|
+
};
|
|
9
|
+
/** Writes an unconfigured startup failure using the standard log envelope. */
|
|
10
|
+
export function writeStartupError(error) {
|
|
11
|
+
defaultWriter({
|
|
12
|
+
time: new Date().toISOString(),
|
|
13
|
+
level: "error",
|
|
14
|
+
event: "startup_failed",
|
|
15
|
+
error: error instanceof Error ? error.message : String(error),
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
/** Creates a structured logger filtered at the configured level. */
|
|
19
|
+
export function createLogger(level, write = defaultWriter, redaction = { root: "", sensitivePaths: [] }) {
|
|
20
|
+
const log = ((entryLevel, event, fields = {}) => {
|
|
21
|
+
if (priorities[entryLevel] < priorities[level])
|
|
22
|
+
return;
|
|
23
|
+
write({
|
|
24
|
+
time: new Date().toISOString(),
|
|
25
|
+
level: entryLevel,
|
|
26
|
+
event,
|
|
27
|
+
...fields,
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
log.failure = (event, fields, error) => {
|
|
31
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
32
|
+
log("error", event, {
|
|
33
|
+
...fields,
|
|
34
|
+
error: redact(message, redaction.root, redaction.sensitivePaths),
|
|
35
|
+
});
|
|
36
|
+
log("debug", `${event}_detail`, { ...fields, error: message });
|
|
37
|
+
};
|
|
38
|
+
return log;
|
|
39
|
+
}
|
|
40
|
+
/** Writes structured logs to stderr as newline-delimited JSON. */
|
|
41
|
+
function defaultWriter(entry) {
|
|
42
|
+
process.stderr.write(`${JSON.stringify(entry)}\n`);
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/core/logger.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,wDAAwD;AACxD,MAAM,UAAU,GAA6B;IAC3C,KAAK,EAAE,EAAE;IACT,IAAI,EAAE,EAAE;IACR,IAAI,EAAE,EAAE;IACR,KAAK,EAAE,EAAE;CACV,CAAC;AAiBF,8EAA8E;AAC9E,MAAM,UAAU,iBAAiB,CAAC,KAAc;IAC9C,aAAa,CAAC;QACZ,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QAC9B,KAAK,EAAE,OAAO;QACd,KAAK,EAAE,gBAAgB;QACvB,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;KAC9D,CAAC,CAAC;AACL,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,YAAY,CAC1B,KAAe,EACf,QAAmB,aAAa,EAChC,YAA8B,EAAE,IAAI,EAAE,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE;IAE9D,MAAM,GAAG,GAAG,CAAC,CACX,UAAoB,EACpB,KAAa,EACb,SAAkC,EAAE,EAC9B,EAAE;QACR,IAAI,UAAU,CAAC,UAAU,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC;YAAE,OAAO;QACvD,KAAK,CAAC;YACJ,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YAC9B,KAAK,EAAE,UAAU;YACjB,KAAK;YACL,GAAG,MAAM;SACV,CAAC,CAAC;IACL,CAAC,CAAW,CAAC;IACb,GAAG,CAAC,OAAO,GAAG,CACZ,KAAa,EACb,MAA+B,EAC/B,KAAc,EACR,EAAE;QACR,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,GAAG,CAAC,OAAO,EAAE,KAAK,EAAE;YAClB,GAAG,MAAM;YACT,KAAK,EAAE,MAAM,CAAC,OAAO,EAAE,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,cAAc,CAAC;SACjE,CAAC,CAAC;QACH,GAAG,CAAC,OAAO,EAAE,GAAG,KAAK,SAAS,EAAE,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;IACjE,CAAC,CAAC;IACF,OAAO,GAAG,CAAC;AACb,CAAC;AAED,kEAAkE;AAClE,SAAS,aAAa,CAAC,KAA8B;IACnD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AACrD,CAAC"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/** Sandbox modes exposed by the x_codex request extension. */
|
|
2
|
+
export declare const SANDBOX_MODES: readonly ["read-only", "workspace-write", "danger-full-access"];
|
|
3
|
+
/** A sandbox mode exposed by the x_codex request extension. */
|
|
4
|
+
export type SandboxMode = (typeof SANDBOX_MODES)[number];
|
|
5
|
+
/** Per-request web-search modes supported by the pinned app-server. */
|
|
6
|
+
export declare const WEB_SEARCH_MODES: readonly ["disabled", "cached", "indexed", "live"];
|
|
7
|
+
/** A per-request web-search mode supported by the pinned app-server. */
|
|
8
|
+
export type WebSearchMode = (typeof WEB_SEARCH_MODES)[number];
|
|
9
|
+
/** Non-interactive approval policies in the proxy's preference order. */
|
|
10
|
+
declare const APPROVAL_POLICY_ORDER: readonly ["never", "on-request", "untrusted"];
|
|
11
|
+
/** A non-interactive approval policy that the proxy can safely own. */
|
|
12
|
+
export type ApprovalPolicy = (typeof APPROVAL_POLICY_ORDER)[number];
|
|
13
|
+
/** Approval reviewers in the proxy's preference order. */
|
|
14
|
+
declare const APPROVAL_REVIEWER_ORDER: readonly ["auto_review", "guardian_subagent", "user"];
|
|
15
|
+
/** An approval reviewer accepted by the pinned app-server protocol. */
|
|
16
|
+
export type ApprovalsReviewer = (typeof APPROVAL_REVIEWER_ORDER)[number];
|
|
17
|
+
/** Relevant managed requirements read from app-server at startup. */
|
|
18
|
+
export interface PolicyRequirements {
|
|
19
|
+
allowedApprovalPolicies: ApprovalPolicy[] | null;
|
|
20
|
+
allowedApprovalsReviewers: ApprovalsReviewer[] | null;
|
|
21
|
+
allowedSandboxModes: SandboxMode[] | null;
|
|
22
|
+
allowedWebSearchModes: WebSearchMode[] | null;
|
|
23
|
+
}
|
|
24
|
+
/** The validated request-side x_codex policy extension. */
|
|
25
|
+
export interface RequestPolicy {
|
|
26
|
+
cwd?: string | undefined;
|
|
27
|
+
sandbox?: SandboxMode | undefined;
|
|
28
|
+
webSearch?: WebSearchMode | undefined;
|
|
29
|
+
}
|
|
30
|
+
/** JSON-safe policy material persisted as the continuation binding. */
|
|
31
|
+
export interface PolicyBindingInput {
|
|
32
|
+
cwd: string;
|
|
33
|
+
sandbox: SandboxMode;
|
|
34
|
+
webSearch: WebSearchMode;
|
|
35
|
+
approvalPolicy: ApprovalPolicy;
|
|
36
|
+
approvalsReviewer: ApprovalsReviewer | null;
|
|
37
|
+
}
|
|
38
|
+
/** Full app-server sandbox policy applied explicitly to every turn. */
|
|
39
|
+
export type EffectiveSandboxPolicy = {
|
|
40
|
+
type: "readOnly";
|
|
41
|
+
networkAccess: false;
|
|
42
|
+
} | {
|
|
43
|
+
type: "workspaceWrite";
|
|
44
|
+
writableRoots: string[];
|
|
45
|
+
networkAccess: false;
|
|
46
|
+
excludeTmpdirEnvVar: false;
|
|
47
|
+
excludeSlashTmp: false;
|
|
48
|
+
} | {
|
|
49
|
+
type: "dangerFullAccess";
|
|
50
|
+
};
|
|
51
|
+
/** Canonical effective settings bound to a response and Codex thread. */
|
|
52
|
+
export interface EffectivePolicy {
|
|
53
|
+
cwd: string;
|
|
54
|
+
sandbox: SandboxMode;
|
|
55
|
+
webSearch: WebSearchMode;
|
|
56
|
+
approvalPolicy: ApprovalPolicy;
|
|
57
|
+
approvalsReviewer?: ApprovalsReviewer | undefined;
|
|
58
|
+
sandboxPolicy: EffectiveSandboxPolicy;
|
|
59
|
+
}
|
|
60
|
+
/** A request-policy failure safe to expose without filesystem details. */
|
|
61
|
+
export declare class PolicyError extends Error {
|
|
62
|
+
readonly code: string;
|
|
63
|
+
readonly param: string;
|
|
64
|
+
constructor(code: string, param: string, message: string);
|
|
65
|
+
}
|
|
66
|
+
/** Requirements used when app-server reports no managed restrictions. */
|
|
67
|
+
export declare const UNRESTRICTED_POLICY_REQUIREMENTS: PolicyRequirements;
|
|
68
|
+
/** Minimal path semantics needed for cross-platform containment checks. */
|
|
69
|
+
export interface PathSemantics {
|
|
70
|
+
isAbsolute(path: string): boolean;
|
|
71
|
+
relative(from: string, to: string): string;
|
|
72
|
+
sep: string;
|
|
73
|
+
}
|
|
74
|
+
/** Checks canonical path containment using host or supplied platform semantics. */
|
|
75
|
+
export declare function isPathWithinRoot(root: string, candidate: string, paths?: PathSemantics): boolean;
|
|
76
|
+
/** Resolves and verifies the configured working-directory root. */
|
|
77
|
+
export declare function canonicalizeRoot(path: string): Promise<string>;
|
|
78
|
+
/** Validates the complete public x_codex extension without ignoring fields. */
|
|
79
|
+
export declare function validateRequestPolicy(value: unknown): RequestPolicy;
|
|
80
|
+
/** Parses the relevant portion of configRequirements/read strictly. */
|
|
81
|
+
export declare function parsePolicyRequirements(value: unknown): PolicyRequirements;
|
|
82
|
+
/** Resolves request selections against the canonical root and managed policy. */
|
|
83
|
+
export declare function resolveEffectivePolicy(request: RequestPolicy, root: string, requirements: PolicyRequirements): Promise<EffectivePolicy>;
|
|
84
|
+
/** Selects a managed-allowed reviewer, preferring non-interactive review. */
|
|
85
|
+
export declare function selectApprovalsReviewer(requirements: PolicyRequirements): ApprovalsReviewer;
|
|
86
|
+
/**
|
|
87
|
+
* Chooses the strictest usable non-interactive approval policy, preferring the
|
|
88
|
+
* least-interactive option app-server allows (`never`, then `on-request`, then
|
|
89
|
+
* `untrusted`) so the proxy never depends on an interactive approver.
|
|
90
|
+
*/
|
|
91
|
+
export declare function selectApprovalPolicy(requirements: PolicyRequirements): ApprovalPolicy;
|
|
92
|
+
/** Builds the exact app-server sandbox policy for a canonical cwd. */
|
|
93
|
+
export declare function sandboxPolicy(sandbox: SandboxMode, cwd: string): EffectiveSandboxPolicy;
|
|
94
|
+
/** Returns the canonical effective fields whose meaning must not change. */
|
|
95
|
+
export declare function policyBindingInput(policy: EffectivePolicy): PolicyBindingInput;
|
|
96
|
+
/** Computes a stable continuation hash for canonical effective settings. */
|
|
97
|
+
export declare function policyBindingHash(policy: EffectivePolicy): string;
|
|
98
|
+
export {};
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import { constants } from "node:fs";
|
|
2
|
+
import { access, realpath, stat } from "node:fs/promises";
|
|
3
|
+
import { isAbsolute, relative, sep } from "node:path";
|
|
4
|
+
import { bindingHash, record } from "./canonical.js";
|
|
5
|
+
/** Sandbox modes exposed by the x_codex request extension. */
|
|
6
|
+
export const SANDBOX_MODES = [
|
|
7
|
+
"read-only",
|
|
8
|
+
"workspace-write",
|
|
9
|
+
"danger-full-access",
|
|
10
|
+
];
|
|
11
|
+
/** Per-request web-search modes supported by the pinned app-server. */
|
|
12
|
+
export const WEB_SEARCH_MODES = [
|
|
13
|
+
"disabled",
|
|
14
|
+
"cached",
|
|
15
|
+
"indexed",
|
|
16
|
+
"live",
|
|
17
|
+
];
|
|
18
|
+
/** Non-interactive approval policies in the proxy's preference order. */
|
|
19
|
+
const APPROVAL_POLICY_ORDER = ["never", "on-request", "untrusted"];
|
|
20
|
+
/** Approval reviewers in the proxy's preference order. */
|
|
21
|
+
const APPROVAL_REVIEWER_ORDER = [
|
|
22
|
+
"auto_review",
|
|
23
|
+
"guardian_subagent",
|
|
24
|
+
"user",
|
|
25
|
+
];
|
|
26
|
+
/** A request-policy failure safe to expose without filesystem details. */
|
|
27
|
+
export class PolicyError extends Error {
|
|
28
|
+
code;
|
|
29
|
+
param;
|
|
30
|
+
constructor(code, param, message) {
|
|
31
|
+
super(message);
|
|
32
|
+
this.code = code;
|
|
33
|
+
this.param = param;
|
|
34
|
+
this.name = "PolicyError";
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/** Requirements used when app-server reports no managed restrictions. */
|
|
38
|
+
export const UNRESTRICTED_POLICY_REQUIREMENTS = {
|
|
39
|
+
allowedApprovalPolicies: null,
|
|
40
|
+
allowedApprovalsReviewers: null,
|
|
41
|
+
allowedSandboxModes: null,
|
|
42
|
+
allowedWebSearchModes: null,
|
|
43
|
+
};
|
|
44
|
+
/** Checks canonical path containment using host or supplied platform semantics. */
|
|
45
|
+
export function isPathWithinRoot(root, candidate, paths = { isAbsolute, relative, sep }) {
|
|
46
|
+
const fromRoot = paths.relative(root, candidate);
|
|
47
|
+
return (fromRoot === "" ||
|
|
48
|
+
(fromRoot !== ".." &&
|
|
49
|
+
!fromRoot.startsWith(`..${paths.sep}`) &&
|
|
50
|
+
!paths.isAbsolute(fromRoot)));
|
|
51
|
+
}
|
|
52
|
+
/** Resolves and verifies the configured working-directory root. */
|
|
53
|
+
export async function canonicalizeRoot(path) {
|
|
54
|
+
if (!isAbsolute(path))
|
|
55
|
+
throw new Error("--root must name an absolute readable directory.");
|
|
56
|
+
try {
|
|
57
|
+
return await canonicalDirectory(path);
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
throw new Error("--root must name a readable directory.");
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/** Validates the complete public x_codex extension without ignoring fields. */
|
|
64
|
+
export function validateRequestPolicy(value) {
|
|
65
|
+
if (value === undefined)
|
|
66
|
+
return {};
|
|
67
|
+
const extension = record(value);
|
|
68
|
+
if (!extension)
|
|
69
|
+
throw new PolicyError("invalid_x_codex", "x_codex", "x_codex must be an object.");
|
|
70
|
+
const allowed = new Set(["cwd", "sandbox", "web_search"]);
|
|
71
|
+
if (Object.keys(extension).some((key) => !allowed.has(key)))
|
|
72
|
+
throw new PolicyError("invalid_x_codex", "x_codex", "x_codex contains unsupported fields.");
|
|
73
|
+
if (extension.cwd !== undefined &&
|
|
74
|
+
(typeof extension.cwd !== "string" || extension.cwd.length === 0))
|
|
75
|
+
throw new PolicyError("invalid_cwd", "x_codex.cwd", "x_codex.cwd must be a non-empty string.");
|
|
76
|
+
const sandbox = validateEnumField(extension.sandbox, SANDBOX_MODES, "unsupported_sandbox", "x_codex.sandbox", "x_codex.sandbox is not supported.");
|
|
77
|
+
const webSearch = validateEnumField(extension.web_search, WEB_SEARCH_MODES, "unsupported_web_search", "x_codex.web_search", "x_codex.web_search is not supported.");
|
|
78
|
+
return {
|
|
79
|
+
...(typeof extension.cwd === "string" ? { cwd: extension.cwd } : {}),
|
|
80
|
+
...(sandbox === undefined ? {} : { sandbox }),
|
|
81
|
+
...(webSearch === undefined ? {} : { webSearch }),
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
/** Parses the relevant portion of configRequirements/read strictly. */
|
|
85
|
+
export function parsePolicyRequirements(value) {
|
|
86
|
+
const response = record(value);
|
|
87
|
+
if (!response || !("requirements" in response))
|
|
88
|
+
throw new Error("configRequirements/read returned a malformed response.");
|
|
89
|
+
if (response.requirements === null)
|
|
90
|
+
return UNRESTRICTED_POLICY_REQUIREMENTS;
|
|
91
|
+
const requirements = record(response.requirements);
|
|
92
|
+
if (!requirements)
|
|
93
|
+
throw new Error("configRequirements/read returned malformed requirements.");
|
|
94
|
+
return {
|
|
95
|
+
allowedApprovalPolicies: stringAllowlist(requirements.allowedApprovalPolicies, APPROVAL_POLICY_ORDER, "allowedApprovalPolicies", true),
|
|
96
|
+
allowedApprovalsReviewers: stringAllowlist(requirements.allowedApprovalsReviewers, APPROVAL_REVIEWER_ORDER, "allowedApprovalsReviewers"),
|
|
97
|
+
allowedSandboxModes: stringAllowlist(requirements.allowedSandboxModes, SANDBOX_MODES, "allowedSandboxModes"),
|
|
98
|
+
allowedWebSearchModes: stringAllowlist(requirements.allowedWebSearchModes, WEB_SEARCH_MODES, "allowedWebSearchModes"),
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
/** Resolves request selections against the canonical root and managed policy. */
|
|
102
|
+
export async function resolveEffectivePolicy(request, root, requirements) {
|
|
103
|
+
// `root` is already canonical (the CLI resolves it once via canonicalizeRoot),
|
|
104
|
+
// so a request that names no cwd needs no per-request filesystem walk. Only a
|
|
105
|
+
// client-supplied cwd is canonicalized and bounded here.
|
|
106
|
+
const cwd = request.cwd === undefined
|
|
107
|
+
? root
|
|
108
|
+
: await canonicalizeRequestCwd(request.cwd, root);
|
|
109
|
+
const sandbox = request.sandbox ?? "read-only";
|
|
110
|
+
const webSearch = request.webSearch ?? "disabled";
|
|
111
|
+
requireAllowed(sandbox, requirements.allowedSandboxModes, "x_codex.sandbox", "sandbox_not_allowed");
|
|
112
|
+
requireAllowed(webSearch, requirements.allowedWebSearchModes, "x_codex.web_search", "web_search_not_allowed");
|
|
113
|
+
const approvalPolicy = selectApprovalPolicy(requirements);
|
|
114
|
+
const approvalsReviewer = selectApprovalsReviewer(requirements);
|
|
115
|
+
return {
|
|
116
|
+
cwd,
|
|
117
|
+
sandbox,
|
|
118
|
+
webSearch,
|
|
119
|
+
approvalPolicy,
|
|
120
|
+
approvalsReviewer,
|
|
121
|
+
sandboxPolicy: sandboxPolicy(sandbox, cwd),
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
/** Selects a managed-allowed reviewer, preferring non-interactive review. */
|
|
125
|
+
export function selectApprovalsReviewer(requirements) {
|
|
126
|
+
return firstAllowed(APPROVAL_REVIEWER_ORDER, requirements.allowedApprovalsReviewers, "approval_reviewer_not_allowed", "x_codex", "Managed requirements allow no supported approval reviewer.");
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Chooses the strictest usable non-interactive approval policy, preferring the
|
|
130
|
+
* least-interactive option app-server allows (`never`, then `on-request`, then
|
|
131
|
+
* `untrusted`) so the proxy never depends on an interactive approver.
|
|
132
|
+
*/
|
|
133
|
+
export function selectApprovalPolicy(requirements) {
|
|
134
|
+
return firstAllowed(APPROVAL_POLICY_ORDER, requirements.allowedApprovalPolicies, "approval_policy_not_allowed", "x_codex", "Managed requirements allow no supported non-interactive approval policy.");
|
|
135
|
+
}
|
|
136
|
+
/** Builds the exact app-server sandbox policy for a canonical cwd. */
|
|
137
|
+
export function sandboxPolicy(sandbox, cwd) {
|
|
138
|
+
if (sandbox === "read-only")
|
|
139
|
+
return { type: "readOnly", networkAccess: false };
|
|
140
|
+
if (sandbox === "workspace-write")
|
|
141
|
+
return {
|
|
142
|
+
type: "workspaceWrite",
|
|
143
|
+
writableRoots: [cwd],
|
|
144
|
+
networkAccess: false,
|
|
145
|
+
excludeTmpdirEnvVar: false,
|
|
146
|
+
excludeSlashTmp: false,
|
|
147
|
+
};
|
|
148
|
+
return { type: "dangerFullAccess" };
|
|
149
|
+
}
|
|
150
|
+
/** Returns the canonical effective fields whose meaning must not change. */
|
|
151
|
+
export function policyBindingInput(policy) {
|
|
152
|
+
return {
|
|
153
|
+
cwd: policy.cwd,
|
|
154
|
+
sandbox: policy.sandbox,
|
|
155
|
+
webSearch: policy.webSearch,
|
|
156
|
+
approvalPolicy: policy.approvalPolicy,
|
|
157
|
+
approvalsReviewer: policy.approvalsReviewer ?? null,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
/** Computes a stable continuation hash for canonical effective settings. */
|
|
161
|
+
export function policyBindingHash(policy) {
|
|
162
|
+
return bindingHash(policyBindingInput(policy));
|
|
163
|
+
}
|
|
164
|
+
/** Resolves a requested cwd and enforces canonical root containment. */
|
|
165
|
+
async function canonicalizeRequestCwd(requested, root) {
|
|
166
|
+
if (!isAbsolute(requested))
|
|
167
|
+
throw new PolicyError("invalid_cwd", "x_codex.cwd", "x_codex.cwd must be an absolute path to a readable directory.");
|
|
168
|
+
let canonical;
|
|
169
|
+
try {
|
|
170
|
+
canonical = await canonicalDirectory(requested);
|
|
171
|
+
}
|
|
172
|
+
catch {
|
|
173
|
+
throw new PolicyError("invalid_cwd", "x_codex.cwd", "x_codex.cwd must be an absolute path to a readable directory.");
|
|
174
|
+
}
|
|
175
|
+
if (!isPathWithinRoot(root, canonical))
|
|
176
|
+
throw new PolicyError("cwd_outside_root", "x_codex.cwd", "x_codex.cwd must resolve within the configured root.");
|
|
177
|
+
return canonical;
|
|
178
|
+
}
|
|
179
|
+
/** Resolves a readable directory while preserving filesystem check ordering. */
|
|
180
|
+
async function canonicalDirectory(path) {
|
|
181
|
+
const canonical = await realpath(path);
|
|
182
|
+
await access(canonical, constants.R_OK | constants.X_OK);
|
|
183
|
+
if (!(await stat(canonical)).isDirectory())
|
|
184
|
+
throw new Error("not directory");
|
|
185
|
+
return canonical;
|
|
186
|
+
}
|
|
187
|
+
/** Returns the first managed-allowed value in the proxy's preference order. */
|
|
188
|
+
function firstAllowed(order, allowed, code, param, message) {
|
|
189
|
+
for (const candidate of order)
|
|
190
|
+
if (allowed === null || allowed.includes(candidate))
|
|
191
|
+
return candidate;
|
|
192
|
+
throw new PolicyError(code, param, message);
|
|
193
|
+
}
|
|
194
|
+
/** Rejects a managed-disallowed request selection without approximation. */
|
|
195
|
+
function requireAllowed(value, allowed, param, code) {
|
|
196
|
+
if (allowed !== null && !allowed.includes(value))
|
|
197
|
+
throw new PolicyError(code, param, "The requested setting is disallowed by managed policy.");
|
|
198
|
+
}
|
|
199
|
+
/** Parses a nullable managed string allowlist and rejects malformed entries. */
|
|
200
|
+
function stringAllowlist(value, supported, name, allowGranular = false) {
|
|
201
|
+
if (value === null || value === undefined)
|
|
202
|
+
return null;
|
|
203
|
+
if (!Array.isArray(value))
|
|
204
|
+
throw new Error(`configRequirements/read returned malformed ${name}.`);
|
|
205
|
+
const result = [];
|
|
206
|
+
for (const entry of value) {
|
|
207
|
+
if (allowGranular && isGranularApproval(entry))
|
|
208
|
+
continue;
|
|
209
|
+
if (typeof entry !== "string" || !includesString(supported, entry))
|
|
210
|
+
throw new Error(`configRequirements/read returned malformed ${name}.`);
|
|
211
|
+
result.push(entry);
|
|
212
|
+
}
|
|
213
|
+
return result;
|
|
214
|
+
}
|
|
215
|
+
/** Validates an optional request string against a supported enum tuple. */
|
|
216
|
+
function validateEnumField(value, allowed, code, param, message) {
|
|
217
|
+
if (value === undefined)
|
|
218
|
+
return undefined;
|
|
219
|
+
if (typeof value !== "string" || !includesString(allowed, value))
|
|
220
|
+
throw new PolicyError(code, param, message);
|
|
221
|
+
return value;
|
|
222
|
+
}
|
|
223
|
+
/** Narrows a string after membership checking without weakening tuple types. */
|
|
224
|
+
function includesString(values, value) {
|
|
225
|
+
return values.some((candidate) => candidate === value);
|
|
226
|
+
}
|
|
227
|
+
/** Recognizes the generated granular approval-policy shape for safe omission. */
|
|
228
|
+
function isGranularApproval(value) {
|
|
229
|
+
const outer = record(value);
|
|
230
|
+
const granular = record(outer?.granular);
|
|
231
|
+
if (!outer ||
|
|
232
|
+
!granular ||
|
|
233
|
+
Object.keys(outer).some((key) => key !== "granular"))
|
|
234
|
+
return false;
|
|
235
|
+
const required = ["sandbox_approval", "rules", "mcp_elicitations"];
|
|
236
|
+
const optional = ["skill_approval", "request_permissions"];
|
|
237
|
+
const accepted = [...required, ...optional];
|
|
238
|
+
return (Object.keys(granular).every((key) => accepted.includes(key)) &&
|
|
239
|
+
required.every((key) => typeof granular[key] === "boolean") &&
|
|
240
|
+
optional.every((key) => granular[key] === undefined || typeof granular[key] === "boolean"));
|
|
241
|
+
}
|
|
242
|
+
//# sourceMappingURL=policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.js","sourceRoot":"","sources":["../../src/core/policy.ts"],"names":[],"mappings":"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"}
|