@hasna/skills 0.10.50 → 0.10.51
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/README.md +8 -5
- package/bin/index.js +35 -31
- package/bin/maintenance.js +199 -2
- package/bin/mcp.js +29 -26
- package/bin/migrate.js +1 -1
- package/bin/server.js +1 -1
- package/bin/worker.js +1 -1
- package/dist/index.js +32 -28
- package/dist/lib/agent-discovery.d.ts +1 -1
- package/dist/lib/codex-native-compatibility.d.ts +4 -1
- package/dist/sdk/index.js +12 -10
- package/dist/server/maintenance-entry.d.ts +14 -0
- package/dist/server/schema-census.d.ts +77 -0
- package/docs/plugin-admission.md +5 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -592,10 +592,13 @@ skills hook native-catalog --cwd /absolute/project --output /private/catalog.jso
|
|
|
592
592
|
skills hook install --agent codex --codex-native-catalog /private/catalog.json --json
|
|
593
593
|
```
|
|
594
594
|
|
|
595
|
-
Codex 0.159.2 and 0.160.
|
|
596
|
-
transport, capture and review use one capability registry
|
|
597
|
-
|
|
598
|
-
|
|
595
|
+
Codex 0.159.2, 0.160.0 and 0.160.1 have measured qualified-name catalog support.
|
|
596
|
+
Native transport, capture and review use one capability registry of exact
|
|
597
|
+
releases. Unmeasured releases, including 0.160.2 and 0.161.0, refuse until the
|
|
598
|
+
native catalog/name-denial and hook-dispatch acceptance tests pass; an RPC
|
|
599
|
+
handshake alone does not establish those semantics. Admitting a release does not
|
|
600
|
+
admit its corpus: the transport still requires the existing native corpus
|
|
601
|
+
admission (see `docs/codex-corpus-writers.md`).
|
|
599
602
|
|
|
600
603
|
The capture refuses an existing output file, writes mode `0600`, verifies the
|
|
601
604
|
exact bytes, and reports only version, directory, count, file path and SHA-256.
|
|
@@ -643,7 +646,7 @@ different extant, witnessed user version. Individual missing files, current
|
|
|
643
646
|
registered roots, aliases and registration changes still refuse; historical
|
|
644
647
|
source hashes and typed settings witnesses remain intact.
|
|
645
648
|
|
|
646
|
-
For a Codex 0.160.0 remote refresh omitted by an existing qualified-name disable,
|
|
649
|
+
For a Codex 0.160.0 or 0.160.1 remote refresh omitted by an existing qualified-name disable,
|
|
647
650
|
a fresh native catalog and discovery review can plan the new exact path disable
|
|
648
651
|
in the same transaction. The remote installation receipt, namespace and capability
|
|
649
652
|
controls must match; conflicting enable rules, unknown names and ambiguous
|
package/bin/index.js
CHANGED
|
@@ -36888,7 +36888,7 @@ var package_default;
|
|
|
36888
36888
|
var init_package = __esm(() => {
|
|
36889
36889
|
package_default = {
|
|
36890
36890
|
name: "@hasna/skills",
|
|
36891
|
-
version: "0.10.
|
|
36891
|
+
version: "0.10.51",
|
|
36892
36892
|
description: "Skills library for AI coding agents",
|
|
36893
36893
|
type: "module",
|
|
36894
36894
|
bin: {
|
|
@@ -40269,6 +40269,29 @@ var init_sumi_settings_witness = __esm(() => {
|
|
|
40269
40269
|
SUMI_DISCOVERY_PROJECTION_FIELDS = ["skills", "plugin", "plugins", "permissions"];
|
|
40270
40270
|
});
|
|
40271
40271
|
|
|
40272
|
+
// src/lib/codex-native-compatibility.ts
|
|
40273
|
+
function supportsCodexNativeCapability(version, capability) {
|
|
40274
|
+
return typeof version === "string" && Object.hasOwn(MEASURED_CODEX_CAPABILITIES, version) && MEASURED_CODEX_CAPABILITIES[version].includes(capability);
|
|
40275
|
+
}
|
|
40276
|
+
var MEASURED_CODEX_CAPABILITIES, SUPPORTED_CODEX_HOOK_VERSIONS;
|
|
40277
|
+
var init_codex_native_compatibility = __esm(() => {
|
|
40278
|
+
MEASURED_CODEX_CAPABILITIES = {
|
|
40279
|
+
"codex-cli 0.153.0": ["hooks"],
|
|
40280
|
+
"codex-cli 0.154.0": ["hooks"],
|
|
40281
|
+
"codex-cli 0.155.0": ["hooks"],
|
|
40282
|
+
"codex-cli 0.155.1": ["hooks"],
|
|
40283
|
+
"codex-cli 0.156.1": ["hooks"],
|
|
40284
|
+
"codex-cli 0.157.0": ["hooks"],
|
|
40285
|
+
"codex-cli 0.157.1": ["hooks"],
|
|
40286
|
+
"codex-cli 0.158.0": ["hooks"],
|
|
40287
|
+
"codex-cli 0.159.0": ["hooks"],
|
|
40288
|
+
"codex-cli 0.159.2": ["hooks", "qualified-skill-catalog"],
|
|
40289
|
+
"codex-cli 0.160.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"],
|
|
40290
|
+
"codex-cli 0.160.1": ["hooks", "qualified-skill-catalog", "installed-plugin-review"]
|
|
40291
|
+
};
|
|
40292
|
+
SUPPORTED_CODEX_HOOK_VERSIONS = Object.freeze(Object.keys(MEASURED_CODEX_CAPABILITIES).filter((version) => supportsCodexNativeCapability(version, "hooks")));
|
|
40293
|
+
});
|
|
40294
|
+
|
|
40272
40295
|
// src/lib/agent-policy-limits.ts
|
|
40273
40296
|
import { basename as basename3, isAbsolute as isAbsolute3, join as join11, resolve as resolve4, sep as sep2 } from "path";
|
|
40274
40297
|
function object(value) {
|
|
@@ -40335,7 +40358,7 @@ function assertAgentPolicyCollections(policy) {
|
|
|
40335
40358
|
}
|
|
40336
40359
|
if (bridge.codexInactivePlugins !== undefined) {
|
|
40337
40360
|
const controls = array(bridge.codexInactivePlugins, 4096), ids = new Set;
|
|
40338
|
-
requireBound(controls.length === 0 || object(bridge.codexPluginSkillReview) && bridge.codexPluginSkillReview.version
|
|
40361
|
+
requireBound(controls.length === 0 || object(bridge.codexPluginSkillReview) && supportsCodexNativeCapability(bridge.codexPluginSkillReview.version, "installed-plugin-review") && typeof bridge.codexPluginSkillReview.catalogSha256 === "string" && /^[a-f0-9]{64}$/.test(bridge.codexPluginSkillReview.catalogSha256));
|
|
40339
40362
|
for (const control of controls) {
|
|
40340
40363
|
requireBound(object(control) && Object.keys(control).every((key) => ["pluginId", "namespace", "pluginParent", "sourceType", "sourceSha256"].includes(key)));
|
|
40341
40364
|
text(control.pluginId, 1024);
|
|
@@ -40387,7 +40410,7 @@ function assertAgentPolicyCollections(policy) {
|
|
|
40387
40410
|
}
|
|
40388
40411
|
if (value.codexInstallationInputs !== undefined) {
|
|
40389
40412
|
const proof = record(value.codexInstallationInputs, 4), inputs = array(proof.plugins, 4096), ids = new Set;
|
|
40390
|
-
requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && proof.version
|
|
40413
|
+
requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && supportsCodexNativeCapability(proof.version, "installed-plugin-review") && typeof proof.catalogSha256 === "string" && /^[a-f0-9]{64}$/.test(proof.catalogSha256) && inputs.length > 0 && object(bridge.codexPluginSkillReview) && bridge.codexPluginSkillReview.version === proof.version && bridge.codexPluginSkillReview.catalogSha256 === proof.catalogSha256);
|
|
40391
40414
|
for (const input of inputs) {
|
|
40392
40415
|
requireBound(object(input) && Object.keys(input).every((key) => ["pluginId", "namespace", "pluginParent", "sourceRoot", "sourceSha256"].includes(key)));
|
|
40393
40416
|
text(input.pluginId, 1024);
|
|
@@ -40452,6 +40475,7 @@ function assertAgentPolicyCollections(policy) {
|
|
|
40452
40475
|
}
|
|
40453
40476
|
var AGENT_POLICY_LIMITS;
|
|
40454
40477
|
var init_agent_policy_limits = __esm(() => {
|
|
40478
|
+
init_codex_native_compatibility();
|
|
40455
40479
|
AGENT_POLICY_LIMITS = Object.freeze({ bytes: 1024 * 1024, agents: 16, discoverySources: 2048, discoveryRawSourceBytes: 64 * 1024 * 1024, discoveryRawTotalBytes: 256 * 1024 * 1024, discoveryPathLinks: 40, discoveryPathSteps: 256, discoveryPathSourceMetadataBytes: 64 * 1024, discoveryPathTotalMetadataBytes: 8 * 1024 * 1024, discoveryRoots: 512, discoveryDirectories: 64, discoveryDirectoryEntries: 20000, discoveryDirectoryBytes: 8 * 1024 * 1024, builtinNames: 2048, rootAliases: 2, fields: 64, pathCharacters: 4096 });
|
|
40456
40480
|
});
|
|
40457
40481
|
|
|
@@ -51575,28 +51599,6 @@ function isCodexLocalStdioMcpServer(name, server) {
|
|
|
51575
51599
|
}
|
|
51576
51600
|
}
|
|
51577
51601
|
|
|
51578
|
-
// src/lib/codex-native-compatibility.ts
|
|
51579
|
-
function supportsCodexNativeCapability(version, capability) {
|
|
51580
|
-
return typeof version === "string" && Object.hasOwn(MEASURED_CODEX_CAPABILITIES, version) && MEASURED_CODEX_CAPABILITIES[version].includes(capability);
|
|
51581
|
-
}
|
|
51582
|
-
var MEASURED_CODEX_CAPABILITIES, SUPPORTED_CODEX_HOOK_VERSIONS;
|
|
51583
|
-
var init_codex_native_compatibility = __esm(() => {
|
|
51584
|
-
MEASURED_CODEX_CAPABILITIES = {
|
|
51585
|
-
"codex-cli 0.153.0": ["hooks"],
|
|
51586
|
-
"codex-cli 0.154.0": ["hooks"],
|
|
51587
|
-
"codex-cli 0.155.0": ["hooks"],
|
|
51588
|
-
"codex-cli 0.155.1": ["hooks"],
|
|
51589
|
-
"codex-cli 0.156.1": ["hooks"],
|
|
51590
|
-
"codex-cli 0.157.0": ["hooks"],
|
|
51591
|
-
"codex-cli 0.157.1": ["hooks"],
|
|
51592
|
-
"codex-cli 0.158.0": ["hooks"],
|
|
51593
|
-
"codex-cli 0.159.0": ["hooks"],
|
|
51594
|
-
"codex-cli 0.159.2": ["hooks", "qualified-skill-catalog"],
|
|
51595
|
-
"codex-cli 0.160.0": ["hooks", "qualified-skill-catalog"]
|
|
51596
|
-
};
|
|
51597
|
-
SUPPORTED_CODEX_HOOK_VERSIONS = Object.freeze(Object.keys(MEASURED_CODEX_CAPABILITIES).filter((version) => supportsCodexNativeCapability(version, "hooks")));
|
|
51598
|
-
});
|
|
51599
|
-
|
|
51600
51602
|
// src/lib/codex-hook-rpc.ts
|
|
51601
51603
|
import { join as join20 } from "path";
|
|
51602
51604
|
import { execFile, spawn as spawn2 } from "child_process";
|
|
@@ -52193,6 +52195,7 @@ function reviewedCodexPluginCapabilitiesUnchanged(cache3, controls, read2, rules
|
|
|
52193
52195
|
function reviewCodexPluginControls(catalog, documents, cache3, cwd2, read2, rules, pluginSettings, plannedRules, denials = []) {
|
|
52194
52196
|
if (!supportsCodexNativeCapability(catalog?.version, "qualified-skill-catalog") || catalog.cwd !== cwd2)
|
|
52195
52197
|
refuse2();
|
|
52198
|
+
const installedPluginReview = supportsCodexNativeCapability(catalog.version, "installed-plugin-review");
|
|
52196
52199
|
if (!Array.isArray(denials) || denials.length > 4096 || new Set(denials.map((item) => item?.path)).size !== denials.length || denials.some((item) => !item || Object.keys(item).sort().join(",") !== "name,path,sha256" || typeof item.name !== "string" || typeof item.path !== "string" || !/^[a-f0-9]{64}$/.test(item.sha256)))
|
|
52197
52200
|
refuse2();
|
|
52198
52201
|
const usedDenials = new Set;
|
|
@@ -52224,7 +52227,7 @@ function reviewCodexPluginControls(catalog, documents, cache3, cwd2, read2, rule
|
|
|
52224
52227
|
if (listed.length > 1)
|
|
52225
52228
|
refuse2();
|
|
52226
52229
|
const installed = installedPlugins.filter((plugin) => plugin.id === expectedPluginId && plugin.name === pluginName);
|
|
52227
|
-
if (
|
|
52230
|
+
if (installedPluginReview && installed.length === 1 && installed[0].installed && installed[0].localVersion === basename6(located.root) && installed[0].sourceType === "local" && codexPluginSourceIsConfigControlled(installed[0])) {
|
|
52228
52231
|
const plugin = installed[0], input = { pluginId: expectedPluginId, namespace: located.namespace, pluginParent: located.pluginParent, sourceRoot: plugin.sourcePath, sourceSha256: plugin.sourceSha256 };
|
|
52229
52232
|
if (input.sourceRoot !== located.root && !input.sourceRoot.startsWith(cache3 + sep6) && (lstatSync13(input.sourceRoot, { throwIfNoEntry: false }) || documents.some((path) => path.startsWith(input.sourceRoot + sep6)))) {
|
|
52230
52233
|
if (skills.some((skill) => skill.path === input.sourceRoot || skill.path.startsWith(input.sourceRoot + sep6)) || !sourceInputUnchanged(input, cache3, read2))
|
|
@@ -52233,7 +52236,7 @@ function reviewCodexPluginControls(catalog, documents, cache3, cwd2, read2, rule
|
|
|
52233
52236
|
}
|
|
52234
52237
|
}
|
|
52235
52238
|
const settings = pluginSettings && typeof pluginSettings === "object" && !Array.isArray(pluginSettings) ? pluginSettings : undefined;
|
|
52236
|
-
if (
|
|
52239
|
+
if (installedPluginReview && !listed.length && !skills.some((skill) => skill.pluginId === expectedPluginId) && installed.length === 1 && installed[0].installed && !installed[0].enabled && codexPluginSourceIsConfigControlled(installed[0]) && settings && Object.hasOwn(settings, expectedPluginId) && settings[expectedPluginId]?.enabled === false) {
|
|
52237
52240
|
if (!Array.isArray(rules))
|
|
52238
52241
|
refuse2();
|
|
52239
52242
|
const exactPathDeny = rules.some((rule) => rule?.path === document3 && rule?.enabled === false);
|
|
@@ -52266,12 +52269,12 @@ function reviewCodexPluginControls(catalog, documents, cache3, cwd2, read2, rule
|
|
|
52266
52269
|
const exactPathDeny = Array.isArray(rules) && rules.some((rule) => rule?.path === document3 && rule?.enabled === false);
|
|
52267
52270
|
const nativeSkill = { name: parsed.name, path: document3, pluginId: expectedPluginId, enabled: true };
|
|
52268
52271
|
const denial = denials.find((item) => item.path === document3);
|
|
52269
|
-
const explicitDeny = denial !== undefined && remotePluginId !== undefined &&
|
|
52272
|
+
const explicitDeny = denial !== undefined && remotePluginId !== undefined && installedPluginReview && denial.name === parsed.name && denial.sha256 === createHash12("sha256").update(read2(document3)).digest("hex") && Array.isArray(rules) && !rules.some((rule) => (rule?.path === document3 || typeof rule?.name === "string" && rule.name.trim() === parsed.name) && rule.enabled !== false) && Array.isArray(plannedRules) && plannedRules.some((rule) => rule?.path === document3 && rule.enabled === false);
|
|
52270
52273
|
if (denial && !explicitDeny)
|
|
52271
52274
|
refuse2();
|
|
52272
52275
|
if (explicitDeny)
|
|
52273
52276
|
usedDenials.add(document3);
|
|
52274
|
-
const plannedPathDeny =
|
|
52277
|
+
const plannedPathDeny = installedPluginReview && remotePluginId !== undefined && Array.isArray(rules) && rules.some((rule) => typeof rule?.name === "string" && rule.name.trim() === parsed.name && rule.enabled === false) && !rules.some((rule) => (rule?.path === document3 || typeof rule?.name === "string" && rule.name.trim() === parsed.name) && rule.enabled !== false) && Array.isArray(plannedRules) && plannedRules.some((rule) => rule?.path === document3 && rule.enabled === false) && isCodexNativeSkillDisabled(nativeSkill, plannedRules);
|
|
52275
52278
|
if (!explicitDeny && (!exactPathDeny && !plannedPathDeny || !isCodexNativeSkillDisabled(nativeSkill, rules)))
|
|
52276
52279
|
refuse2();
|
|
52277
52280
|
}
|
|
@@ -55052,7 +55055,7 @@ function planAgentIntegration(options) {
|
|
|
55052
55055
|
const { codexInstallationInputs: previousInputs, ...current } = rebound;
|
|
55053
55056
|
const inputs = codexPluginSourceInputs.map((input) => input.sourceRoot);
|
|
55054
55057
|
const directories = options.codexNativeCatalog || !previousInputs ? captureDiscoveryDirectories((binding.directories ?? []).filter((directory) => inputs.some((root) => root.startsWith(directory.path + sep7))).map((directory) => directory.path), inputs) : previousInputs.directories;
|
|
55055
|
-
const installed = codexPluginSourceInputs.length ? { ...current, codexInstallationInputs: { version:
|
|
55058
|
+
const installed = codexPluginSourceInputs.length ? { ...current, codexInstallationInputs: { version: codexPluginSkillReview.version, catalogSha256: codexPluginSkillReview.catalogSha256, plugins: codexPluginSourceInputs, ...directories?.length ? { directories } : {} } } : current;
|
|
55056
55059
|
return captureRetiredCodexDiscovery(installed, codexPluginSkills, Bun.TOML.parse(changes.find((change) => change.path === canonicalAgentPath(join28(home, ".codex/config.toml"), aliases))?.after ?? codexConfigBefore ?? "").skills?.config ?? []);
|
|
55057
55060
|
});
|
|
55058
55061
|
const nextPolicy = { ...policy, version: 1, loading: "cli", profileId, bridge: {
|
|
@@ -59325,7 +59328,7 @@ function codexInstallationRoots(binding) {
|
|
|
59325
59328
|
const proof = binding.codexInstallationInputs;
|
|
59326
59329
|
if (proof === undefined)
|
|
59327
59330
|
return [];
|
|
59328
|
-
if (binding.agent !== "codex" || binding.method !== "reviewed" || proof.version
|
|
59331
|
+
if (binding.agent !== "codex" || binding.method !== "reviewed" || !supportsCodexNativeCapability(proof.version, "installed-plugin-review") || !/^[a-f0-9]{64}$/.test(proof.catalogSha256) || !Array.isArray(proof.plugins) || !proof.plugins.length)
|
|
59329
59332
|
throw new Error("Invalid native installation input proof");
|
|
59330
59333
|
const cache3 = dirname19(dirname19(proof.plugins[0].pluginParent));
|
|
59331
59334
|
const config = join37(dirname19(dirname19(cache3)), "config.toml"), home = dirname19(dirname19(dirname19(cache3)));
|
|
@@ -59720,6 +59723,7 @@ var init_agent_discovery = __esm(() => {
|
|
|
59720
59723
|
init_codex_plugin_skill_controls();
|
|
59721
59724
|
init_agent_sumi();
|
|
59722
59725
|
init_native_discovery_roots();
|
|
59726
|
+
init_codex_native_compatibility();
|
|
59723
59727
|
init_agent_discovery_directories();
|
|
59724
59728
|
});
|
|
59725
59729
|
|
package/bin/maintenance.js
CHANGED
|
@@ -1909,7 +1909,7 @@ var {
|
|
|
1909
1909
|
// src/server/maintenance-entry.ts
|
|
1910
1910
|
import { closeSync, constants, fstatSync, lstatSync, openSync, readSync } from "fs";
|
|
1911
1911
|
import { createHash as createHash3 } from "crypto";
|
|
1912
|
-
var {SQL:
|
|
1912
|
+
var {SQL: SQL3 } = globalThis.Bun;
|
|
1913
1913
|
|
|
1914
1914
|
// src/server/execution-grant-store.ts
|
|
1915
1915
|
import { randomUUID } from "crypto";
|
|
@@ -3991,6 +3991,140 @@ async function inspectEnrollment(databaseUrl, input) {
|
|
|
3991
3991
|
}
|
|
3992
3992
|
}
|
|
3993
3993
|
|
|
3994
|
+
// src/server/schema-census.ts
|
|
3995
|
+
var {SQL: SQL2 } = globalThis.Bun;
|
|
3996
|
+
|
|
3997
|
+
class SchemaCensusError extends Error {
|
|
3998
|
+
code;
|
|
3999
|
+
constructor(code) {
|
|
4000
|
+
super(code);
|
|
4001
|
+
this.code = code;
|
|
4002
|
+
this.name = "SchemaCensusError";
|
|
4003
|
+
}
|
|
4004
|
+
}
|
|
4005
|
+
var refuse2 = (code) => {
|
|
4006
|
+
throw new SchemaCensusError(code);
|
|
4007
|
+
};
|
|
4008
|
+
var FIXED_SCHEMA = "public";
|
|
4009
|
+
var STATEMENT_TIMEOUT_MS = 5000;
|
|
4010
|
+
var LOCK_TIMEOUT_MS = 1000;
|
|
4011
|
+
var MAX_MIGRATION_VERSIONS = 128;
|
|
4012
|
+
var MAX_MIGRATION_VERSION_CHARS = 64;
|
|
4013
|
+
var MAX_IDENTIFIER_CHARS = 128;
|
|
4014
|
+
var MAX_SERVER_VERSION_CHARS = 256;
|
|
4015
|
+
var MAX_CENSUS_BYTES = 16 * 1024;
|
|
4016
|
+
var boundedText = (value, max) => {
|
|
4017
|
+
if (typeof value !== "string" || value.length === 0 || /[\u0000-\u001f\u007f]/.test(value))
|
|
4018
|
+
return refuse2("CENSUS_INVALID_RESULT");
|
|
4019
|
+
if (value.length > max)
|
|
4020
|
+
return refuse2("CENSUS_OUTPUT_UNBOUNDED");
|
|
4021
|
+
return value;
|
|
4022
|
+
};
|
|
4023
|
+
var boundedCount = (value) => {
|
|
4024
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0)
|
|
4025
|
+
return refuse2("CENSUS_INVALID_RESULT");
|
|
4026
|
+
return value;
|
|
4027
|
+
};
|
|
4028
|
+
async function inspectSchemaCensus(databaseUrl) {
|
|
4029
|
+
try {
|
|
4030
|
+
const url = new URL(databaseUrl);
|
|
4031
|
+
if (!["postgres:", "postgresql:"].includes(url.protocol) || !url.hostname)
|
|
4032
|
+
refuse2("CENSUS_POSTGRES_REQUIRED");
|
|
4033
|
+
} catch {
|
|
4034
|
+
refuse2("CENSUS_POSTGRES_REQUIRED");
|
|
4035
|
+
}
|
|
4036
|
+
let sql;
|
|
4037
|
+
try {
|
|
4038
|
+
sql = new SQL2(databaseUrl, { max: 1, connectionTimeout: 5, idleTimeout: 5 });
|
|
4039
|
+
return await sql.begin("ISOLATION LEVEL REPEATABLE READ READ ONLY", async (tx) => {
|
|
4040
|
+
await tx.unsafe("SET LOCAL statement_timeout = '5s'");
|
|
4041
|
+
await tx.unsafe("SET LOCAL lock_timeout = '1s'");
|
|
4042
|
+
const mode = await tx`SELECT current_setting('transaction_read_only') AS read_only,
|
|
4043
|
+
current_setting('transaction_isolation') AS isolation,
|
|
4044
|
+
current_setting('statement_timeout') AS statement_timeout,
|
|
4045
|
+
current_setting('lock_timeout') AS lock_timeout`;
|
|
4046
|
+
if (mode.length !== 1 || mode[0].read_only !== "on" || mode[0].isolation !== "repeatable read" || mode[0].statement_timeout !== "5s" || mode[0].lock_timeout !== "1s") {
|
|
4047
|
+
refuse2("CENSUS_FAILED");
|
|
4048
|
+
}
|
|
4049
|
+
const identity = await tx`SELECT current_database() AS database, current_user AS role,
|
|
4050
|
+
version() AS server_version, current_schema() AS schema`;
|
|
4051
|
+
if (identity.length !== 1)
|
|
4052
|
+
refuse2("CENSUS_INVALID_RESULT");
|
|
4053
|
+
const database = boundedText(identity[0].database, MAX_IDENTIFIER_CHARS);
|
|
4054
|
+
const role = boundedText(identity[0].role, MAX_IDENTIFIER_CHARS);
|
|
4055
|
+
const serverVersion = boundedText(identity[0].server_version, MAX_SERVER_VERSION_CHARS);
|
|
4056
|
+
if (identity[0].schema !== FIXED_SCHEMA)
|
|
4057
|
+
refuse2("CENSUS_TARGET_MISMATCH");
|
|
4058
|
+
const ledger = await tx`SELECT version FROM public.schema_migrations ORDER BY version LIMIT ${MAX_MIGRATION_VERSIONS + 1}`;
|
|
4059
|
+
if (ledger.length > MAX_MIGRATION_VERSIONS)
|
|
4060
|
+
refuse2("CENSUS_OUTPUT_UNBOUNDED");
|
|
4061
|
+
const versions = ledger.map((row) => boundedText(row.version, MAX_MIGRATION_VERSION_CHARS));
|
|
4062
|
+
const registryCount = await tx`SELECT count(*)::int AS rows FROM public.skills_registry`;
|
|
4063
|
+
const versionCount = await tx`SELECT count(*)::int AS rows FROM public.skills_versions`;
|
|
4064
|
+
if (registryCount.length !== 1 || versionCount.length !== 1)
|
|
4065
|
+
refuse2("CENSUS_INVALID_RESULT");
|
|
4066
|
+
const registryRows = boundedCount(registryCount[0].rows);
|
|
4067
|
+
const versionRows = boundedCount(versionCount[0].rows);
|
|
4068
|
+
const groups = await tx`SELECT lifecycle, (tombstoned_at IS NOT NULL) AS tombstoned, count(*)::int AS rows
|
|
4069
|
+
FROM public.skills_registry GROUP BY 1, 2 LIMIT 5`;
|
|
4070
|
+
if (groups.length > 4)
|
|
4071
|
+
refuse2("CENSUS_INVALID_RESULT");
|
|
4072
|
+
const lifecycle = { active: { live: 0, tombstoned: 0 }, archived: { live: 0, tombstoned: 0 } };
|
|
4073
|
+
for (const group of groups) {
|
|
4074
|
+
const name = group.lifecycle;
|
|
4075
|
+
const tombstoned = group.tombstoned;
|
|
4076
|
+
if (name !== "active" && name !== "archived" || typeof tombstoned !== "boolean")
|
|
4077
|
+
return refuse2("CENSUS_INVALID_RESULT");
|
|
4078
|
+
lifecycle[name][tombstoned ? "tombstoned" : "live"] = boundedCount(group.rows);
|
|
4079
|
+
}
|
|
4080
|
+
const epochColumn = await tx`SELECT count(*)::int AS rows FROM information_schema.columns
|
|
4081
|
+
WHERE table_schema = ${FIXED_SCHEMA} AND table_name = 'skills_registry' AND column_name = 'authorization_epoch'`;
|
|
4082
|
+
if (epochColumn.length !== 1)
|
|
4083
|
+
refuse2("CENSUS_INVALID_RESULT");
|
|
4084
|
+
const epochPresent = boundedCount(epochColumn[0].rows);
|
|
4085
|
+
if (epochPresent > 1)
|
|
4086
|
+
refuse2("CENSUS_INVALID_RESULT");
|
|
4087
|
+
let authorizationEpoch;
|
|
4088
|
+
if (epochPresent === 0)
|
|
4089
|
+
authorizationEpoch = { exists: false };
|
|
4090
|
+
else {
|
|
4091
|
+
const epochNulls = await tx`SELECT count(*)::int AS rows FROM public.skills_registry WHERE authorization_epoch IS NULL`;
|
|
4092
|
+
if (epochNulls.length !== 1)
|
|
4093
|
+
refuse2("CENSUS_INVALID_RESULT");
|
|
4094
|
+
authorizationEpoch = { exists: true, nullCount: boundedCount(epochNulls[0].rows) };
|
|
4095
|
+
}
|
|
4096
|
+
const result = {
|
|
4097
|
+
status: "inspected",
|
|
4098
|
+
database,
|
|
4099
|
+
role,
|
|
4100
|
+
serverVersion,
|
|
4101
|
+
schema: FIXED_SCHEMA,
|
|
4102
|
+
transaction: { readOnly: true, isolation: "repeatable read", statementTimeoutMs: STATEMENT_TIMEOUT_MS, lockTimeoutMs: LOCK_TIMEOUT_MS },
|
|
4103
|
+
migrations: { count: versions.length, versions },
|
|
4104
|
+
registry: { rows: registryRows },
|
|
4105
|
+
versions: { rows: versionRows },
|
|
4106
|
+
lifecycle,
|
|
4107
|
+
authorizationEpoch
|
|
4108
|
+
};
|
|
4109
|
+
if (Buffer.byteLength(JSON.stringify(result), "utf8") > MAX_CENSUS_BYTES)
|
|
4110
|
+
refuse2("CENSUS_OUTPUT_UNBOUNDED");
|
|
4111
|
+
return result;
|
|
4112
|
+
});
|
|
4113
|
+
} catch (error) {
|
|
4114
|
+
if (error instanceof SchemaCensusError)
|
|
4115
|
+
throw error;
|
|
4116
|
+
const state2 = error instanceof SQL2.PostgresError ? error.errno : undefined;
|
|
4117
|
+
const code = state2 === "42P01" || state2 === "42703" ? "CENSUS_SCHEMA_UNAVAILABLE" : state2 === "42501" ? "CENSUS_ACCESS_DENIED" : state2 === "25006" ? "CENSUS_WRITE_REFUSED" : state2 === "57014" || state2 === "55P03" ? "CENSUS_TIMEOUT" : ["08000", "08001", "08003", "08004", "08006", "08007", "08P01", "28000", "28P01", "57P03"].includes(state2 ?? "") ? "CENSUS_CONNECTION_FAILED" : "CENSUS_FAILED";
|
|
4118
|
+
throw new SchemaCensusError(code);
|
|
4119
|
+
} finally {
|
|
4120
|
+
try {
|
|
4121
|
+
await sql?.close({ timeout: 1 });
|
|
4122
|
+
} catch {
|
|
4123
|
+
throw new SchemaCensusError("CENSUS_FAILED");
|
|
4124
|
+
}
|
|
4125
|
+
}
|
|
4126
|
+
}
|
|
4127
|
+
|
|
3994
4128
|
// src/server/maintenance-entry.ts
|
|
3995
4129
|
class InspectionInputError extends Error {
|
|
3996
4130
|
code;
|
|
@@ -3999,6 +4133,14 @@ class InspectionInputError extends Error {
|
|
|
3999
4133
|
this.code = code;
|
|
4000
4134
|
}
|
|
4001
4135
|
}
|
|
4136
|
+
|
|
4137
|
+
class SchemaCensusInputError extends Error {
|
|
4138
|
+
code;
|
|
4139
|
+
constructor(code) {
|
|
4140
|
+
super(code);
|
|
4141
|
+
this.code = code;
|
|
4142
|
+
}
|
|
4143
|
+
}
|
|
4002
4144
|
var MAX_MANIFEST_BYTES = 32 * 1024;
|
|
4003
4145
|
function sha256(value) {
|
|
4004
4146
|
return createHash3("sha256").update(value).digest("hex");
|
|
@@ -4109,6 +4251,41 @@ function readInspectionManifest(path, receiptPath) {
|
|
|
4109
4251
|
}
|
|
4110
4252
|
return parsed;
|
|
4111
4253
|
}
|
|
4254
|
+
function readSchemaCensusManifest(path, receiptPath) {
|
|
4255
|
+
let input;
|
|
4256
|
+
let parsed;
|
|
4257
|
+
try {
|
|
4258
|
+
input = readBoundedJson(path);
|
|
4259
|
+
const value = input.value;
|
|
4260
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
4261
|
+
throw new Error;
|
|
4262
|
+
const fields = ["app", "operation", "manifestVersion", "operationId", "stationId", "keyId", "orgId", "expiresAt", "manifestDigest"];
|
|
4263
|
+
if (Object.keys(value).length !== fields.length || fields.some((field) => !Object.hasOwn(value, field)))
|
|
4264
|
+
throw new Error;
|
|
4265
|
+
if (value.app !== "skills" || value.operation !== "inspect-schema" || value.manifestVersion !== 1)
|
|
4266
|
+
throw new Error;
|
|
4267
|
+
for (const field of ["operationId", "stationId", "keyId", "orgId"]) {
|
|
4268
|
+
const item = value[field];
|
|
4269
|
+
if (typeof item !== "string" || item.trim().length === 0 || item.length > 256 || /[\u0000-\u001f\u007f]/.test(item))
|
|
4270
|
+
throw new Error;
|
|
4271
|
+
}
|
|
4272
|
+
if (typeof value.expiresAt !== "string" || value.expiresAt.length > 64 || !Number.isFinite(Date.parse(value.expiresAt)) || Date.parse(value.expiresAt) <= Date.now())
|
|
4273
|
+
throw new Error;
|
|
4274
|
+
if (typeof value.manifestDigest !== "string" || !/^[a-f0-9]{64}$/.test(value.manifestDigest))
|
|
4275
|
+
throw new Error;
|
|
4276
|
+
if (sha256(canonical(value)) !== value.manifestDigest)
|
|
4277
|
+
throw new Error;
|
|
4278
|
+
parsed = value;
|
|
4279
|
+
} catch {
|
|
4280
|
+
throw new SchemaCensusInputError("INVALID_CENSUS_MANIFEST");
|
|
4281
|
+
}
|
|
4282
|
+
try {
|
|
4283
|
+
verifyOperatorReceipt(input, readBoundedJson(receiptPath).value);
|
|
4284
|
+
} catch {
|
|
4285
|
+
throw new SchemaCensusInputError("INVALID_OPERATOR_RECEIPT");
|
|
4286
|
+
}
|
|
4287
|
+
return parsed;
|
|
4288
|
+
}
|
|
4112
4289
|
function registerMaintenance(parent) {
|
|
4113
4290
|
const maintenance = parent.command("maintenance").description("Run protected, metadata-only Skills maintenance operations");
|
|
4114
4291
|
maintenance.command("inspect-enrollment").description("Inspect one enrollment with a database-enforced read-only snapshot").requiredOption("--manifest <path>", "Fresh inspection authorization supplied by the protected task wrapper").requiredOption("--operator-receipt <path>", "Verified actor receipt written by the protected task wrapper").option("--json", "Output a safe JSON receipt", false).action(async (options) => {
|
|
@@ -4133,6 +4310,26 @@ function registerMaintenance(parent) {
|
|
|
4133
4310
|
process.exitCode = 1;
|
|
4134
4311
|
}
|
|
4135
4312
|
});
|
|
4313
|
+
maintenance.command("inspect-schema").description("Census the fixed Skills schema and migration ledger with a database-enforced read-only snapshot").requiredOption("--manifest <path>", "Fresh census authorization supplied by the protected task wrapper").requiredOption("--operator-receipt <path>", "Verified actor receipt written by the protected task wrapper").option("--json", "Output a safe JSON receipt", false).action(async (options) => {
|
|
4314
|
+
try {
|
|
4315
|
+
const manifest = readSchemaCensusManifest(options.manifest, options.operatorReceipt);
|
|
4316
|
+
const census = await inspectSchemaCensus(process.env.HASNA_SKILLS_DATABASE_URL ?? "");
|
|
4317
|
+
console.log(JSON.stringify({
|
|
4318
|
+
...census,
|
|
4319
|
+
operationId: manifest.operationId,
|
|
4320
|
+
keyId: manifest.keyId,
|
|
4321
|
+
orgId: manifest.orgId,
|
|
4322
|
+
stationId: manifest.stationId
|
|
4323
|
+
}));
|
|
4324
|
+
} catch (error) {
|
|
4325
|
+
const code = error instanceof SchemaCensusInputError || error instanceof SchemaCensusError ? error.code : "CENSUS_FAILED";
|
|
4326
|
+
if (options.json || !process.stdout.isTTY)
|
|
4327
|
+
console.log(JSON.stringify({ status: "failed", code }));
|
|
4328
|
+
else
|
|
4329
|
+
console.error(code);
|
|
4330
|
+
process.exitCode = 1;
|
|
4331
|
+
}
|
|
4332
|
+
});
|
|
4136
4333
|
maintenance.command("enroll-publish").requiredOption("--manifest <path>", "Bounded target manifest supplied by the protected task wrapper").requiredOption("--operator-receipt <path>", "Verified actor receipt written by the protected task wrapper").option("--apply", "Commit the bounded scope update; defaults to dry-run", false).option("--json", "Output a safe JSON receipt", false).action(async (options) => {
|
|
4137
4334
|
let manifest;
|
|
4138
4335
|
let store;
|
|
@@ -4167,7 +4364,7 @@ function registerMaintenance(parent) {
|
|
|
4167
4364
|
process.exitCode = 1;
|
|
4168
4365
|
} catch (error) {
|
|
4169
4366
|
const message = error instanceof Error ? error.message : "";
|
|
4170
|
-
const state2 = error instanceof
|
|
4367
|
+
const state2 = error instanceof SQL3.PostgresError ? error.errno : undefined;
|
|
4171
4368
|
const code = state2 === "42P01" || state2 === "42703" ? "MAINTENANCE_SCHEMA_UNAVAILABLE" : state2 === "42501" ? "MAINTENANCE_ACCESS_DENIED" : state2 === "25006" ? "MAINTENANCE_WRITE_REFUSED" : state2 === "57014" || state2 === "55P03" ? "MAINTENANCE_TIMEOUT" : ["08000", "08001", "08003", "08004", "08006", "08007", "08P01", "28000", "28P01", "57P03"].includes(state2 ?? "") ? "MAINTENANCE_CONNECTION_FAILED" : message.includes("expired") || message.includes("expiry") ? "INVALID_EXPIRY" : message.includes("receipt") || message.includes("operator") ? "INVALID_OPERATOR_RECEIPT" : message.includes("manifest") || message.includes("input") ? "INVALID_MANIFEST" : message.includes("database") || message.includes("store") ? "STORE_UNAVAILABLE" : "MAINTENANCE_FAILED";
|
|
4172
4369
|
if (options.json || !process.stdout.isTTY)
|
|
4173
4370
|
console.log(JSON.stringify({ status: "failed", code }));
|
package/bin/mcp.js
CHANGED
|
@@ -20019,7 +20019,7 @@ var package_default;
|
|
|
20019
20019
|
var init_package = __esm(() => {
|
|
20020
20020
|
package_default = {
|
|
20021
20021
|
name: "@hasna/skills",
|
|
20022
|
-
version: "0.10.
|
|
20022
|
+
version: "0.10.51",
|
|
20023
20023
|
description: "Skills library for AI coding agents",
|
|
20024
20024
|
type: "module",
|
|
20025
20025
|
bin: {
|
|
@@ -38538,6 +38538,29 @@ var init_sumi_settings_witness = __esm(() => {
|
|
|
38538
38538
|
SUMI_DISCOVERY_PROJECTION_FIELDS = ["skills", "plugin", "plugins", "permissions"];
|
|
38539
38539
|
});
|
|
38540
38540
|
|
|
38541
|
+
// src/lib/codex-native-compatibility.ts
|
|
38542
|
+
function supportsCodexNativeCapability(version2, capability) {
|
|
38543
|
+
return typeof version2 === "string" && Object.hasOwn(MEASURED_CODEX_CAPABILITIES, version2) && MEASURED_CODEX_CAPABILITIES[version2].includes(capability);
|
|
38544
|
+
}
|
|
38545
|
+
var MEASURED_CODEX_CAPABILITIES, SUPPORTED_CODEX_HOOK_VERSIONS;
|
|
38546
|
+
var init_codex_native_compatibility = __esm(() => {
|
|
38547
|
+
MEASURED_CODEX_CAPABILITIES = {
|
|
38548
|
+
"codex-cli 0.153.0": ["hooks"],
|
|
38549
|
+
"codex-cli 0.154.0": ["hooks"],
|
|
38550
|
+
"codex-cli 0.155.0": ["hooks"],
|
|
38551
|
+
"codex-cli 0.155.1": ["hooks"],
|
|
38552
|
+
"codex-cli 0.156.1": ["hooks"],
|
|
38553
|
+
"codex-cli 0.157.0": ["hooks"],
|
|
38554
|
+
"codex-cli 0.157.1": ["hooks"],
|
|
38555
|
+
"codex-cli 0.158.0": ["hooks"],
|
|
38556
|
+
"codex-cli 0.159.0": ["hooks"],
|
|
38557
|
+
"codex-cli 0.159.2": ["hooks", "qualified-skill-catalog"],
|
|
38558
|
+
"codex-cli 0.160.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"],
|
|
38559
|
+
"codex-cli 0.160.1": ["hooks", "qualified-skill-catalog", "installed-plugin-review"]
|
|
38560
|
+
};
|
|
38561
|
+
SUPPORTED_CODEX_HOOK_VERSIONS = Object.freeze(Object.keys(MEASURED_CODEX_CAPABILITIES).filter((version2) => supportsCodexNativeCapability(version2, "hooks")));
|
|
38562
|
+
});
|
|
38563
|
+
|
|
38541
38564
|
// src/lib/agent-policy-limits.ts
|
|
38542
38565
|
import { basename as basename4, isAbsolute as isAbsolute4, join as join10, resolve as resolve3, sep as sep3 } from "path";
|
|
38543
38566
|
function object4(value) {
|
|
@@ -38604,7 +38627,7 @@ function assertAgentPolicyCollections(policy) {
|
|
|
38604
38627
|
}
|
|
38605
38628
|
if (bridge.codexInactivePlugins !== undefined) {
|
|
38606
38629
|
const controls = array3(bridge.codexInactivePlugins, 4096), ids = new Set;
|
|
38607
|
-
requireBound(controls.length === 0 || object4(bridge.codexPluginSkillReview) && bridge.codexPluginSkillReview.version
|
|
38630
|
+
requireBound(controls.length === 0 || object4(bridge.codexPluginSkillReview) && supportsCodexNativeCapability(bridge.codexPluginSkillReview.version, "installed-plugin-review") && typeof bridge.codexPluginSkillReview.catalogSha256 === "string" && /^[a-f0-9]{64}$/.test(bridge.codexPluginSkillReview.catalogSha256));
|
|
38608
38631
|
for (const control of controls) {
|
|
38609
38632
|
requireBound(object4(control) && Object.keys(control).every((key) => ["pluginId", "namespace", "pluginParent", "sourceType", "sourceSha256"].includes(key)));
|
|
38610
38633
|
text(control.pluginId, 1024);
|
|
@@ -38656,7 +38679,7 @@ function assertAgentPolicyCollections(policy) {
|
|
|
38656
38679
|
}
|
|
38657
38680
|
if (value.codexInstallationInputs !== undefined) {
|
|
38658
38681
|
const proof = record3(value.codexInstallationInputs, 4), inputs = array3(proof.plugins, 4096), ids = new Set;
|
|
38659
|
-
requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && proof.version
|
|
38682
|
+
requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && supportsCodexNativeCapability(proof.version, "installed-plugin-review") && typeof proof.catalogSha256 === "string" && /^[a-f0-9]{64}$/.test(proof.catalogSha256) && inputs.length > 0 && object4(bridge.codexPluginSkillReview) && bridge.codexPluginSkillReview.version === proof.version && bridge.codexPluginSkillReview.catalogSha256 === proof.catalogSha256);
|
|
38660
38683
|
for (const input2 of inputs) {
|
|
38661
38684
|
requireBound(object4(input2) && Object.keys(input2).every((key) => ["pluginId", "namespace", "pluginParent", "sourceRoot", "sourceSha256"].includes(key)));
|
|
38662
38685
|
text(input2.pluginId, 1024);
|
|
@@ -38721,6 +38744,7 @@ function assertAgentPolicyCollections(policy) {
|
|
|
38721
38744
|
}
|
|
38722
38745
|
var AGENT_POLICY_LIMITS;
|
|
38723
38746
|
var init_agent_policy_limits = __esm(() => {
|
|
38747
|
+
init_codex_native_compatibility();
|
|
38724
38748
|
AGENT_POLICY_LIMITS = Object.freeze({ bytes: 1024 * 1024, agents: 16, discoverySources: 2048, discoveryRawSourceBytes: 64 * 1024 * 1024, discoveryRawTotalBytes: 256 * 1024 * 1024, discoveryPathLinks: 40, discoveryPathSteps: 256, discoveryPathSourceMetadataBytes: 64 * 1024, discoveryPathTotalMetadataBytes: 8 * 1024 * 1024, discoveryRoots: 512, discoveryDirectories: 64, discoveryDirectoryEntries: 20000, discoveryDirectoryBytes: 8 * 1024 * 1024, builtinNames: 2048, rootAliases: 2, fields: 64, pathCharacters: 4096 });
|
|
38725
38749
|
});
|
|
38726
38750
|
|
|
@@ -47952,28 +47976,6 @@ function isCodexLocalStdioMcpServer(name, server) {
|
|
|
47952
47976
|
}
|
|
47953
47977
|
}
|
|
47954
47978
|
|
|
47955
|
-
// src/lib/codex-native-compatibility.ts
|
|
47956
|
-
function supportsCodexNativeCapability(version2, capability) {
|
|
47957
|
-
return typeof version2 === "string" && Object.hasOwn(MEASURED_CODEX_CAPABILITIES, version2) && MEASURED_CODEX_CAPABILITIES[version2].includes(capability);
|
|
47958
|
-
}
|
|
47959
|
-
var MEASURED_CODEX_CAPABILITIES, SUPPORTED_CODEX_HOOK_VERSIONS;
|
|
47960
|
-
var init_codex_native_compatibility = __esm(() => {
|
|
47961
|
-
MEASURED_CODEX_CAPABILITIES = {
|
|
47962
|
-
"codex-cli 0.153.0": ["hooks"],
|
|
47963
|
-
"codex-cli 0.154.0": ["hooks"],
|
|
47964
|
-
"codex-cli 0.155.0": ["hooks"],
|
|
47965
|
-
"codex-cli 0.155.1": ["hooks"],
|
|
47966
|
-
"codex-cli 0.156.1": ["hooks"],
|
|
47967
|
-
"codex-cli 0.157.0": ["hooks"],
|
|
47968
|
-
"codex-cli 0.157.1": ["hooks"],
|
|
47969
|
-
"codex-cli 0.158.0": ["hooks"],
|
|
47970
|
-
"codex-cli 0.159.0": ["hooks"],
|
|
47971
|
-
"codex-cli 0.159.2": ["hooks", "qualified-skill-catalog"],
|
|
47972
|
-
"codex-cli 0.160.0": ["hooks", "qualified-skill-catalog"]
|
|
47973
|
-
};
|
|
47974
|
-
SUPPORTED_CODEX_HOOK_VERSIONS = Object.freeze(Object.keys(MEASURED_CODEX_CAPABILITIES).filter((version2) => supportsCodexNativeCapability(version2, "hooks")));
|
|
47975
|
-
});
|
|
47976
|
-
|
|
47977
47979
|
// src/lib/codex-hook-rpc.ts
|
|
47978
47980
|
var init_codex_hook_rpc = __esm(() => {
|
|
47979
47981
|
init_codex_corpus_write();
|
|
@@ -50795,7 +50797,7 @@ function codexInstallationRoots(binding) {
|
|
|
50795
50797
|
const proof = binding.codexInstallationInputs;
|
|
50796
50798
|
if (proof === undefined)
|
|
50797
50799
|
return [];
|
|
50798
|
-
if (binding.agent !== "codex" || binding.method !== "reviewed" || proof.version
|
|
50800
|
+
if (binding.agent !== "codex" || binding.method !== "reviewed" || !supportsCodexNativeCapability(proof.version, "installed-plugin-review") || !/^[a-f0-9]{64}$/.test(proof.catalogSha256) || !Array.isArray(proof.plugins) || !proof.plugins.length)
|
|
50799
50801
|
throw new Error("Invalid native installation input proof");
|
|
50800
50802
|
const cache = dirname15(dirname15(proof.plugins[0].pluginParent));
|
|
50801
50803
|
const config2 = join26(dirname15(dirname15(cache)), "config.toml"), home = dirname15(dirname15(dirname15(cache)));
|
|
@@ -51122,6 +51124,7 @@ var init_agent_discovery = __esm(() => {
|
|
|
51122
51124
|
init_codex_plugin_skill_controls();
|
|
51123
51125
|
init_agent_sumi();
|
|
51124
51126
|
init_native_discovery_roots();
|
|
51127
|
+
init_codex_native_compatibility();
|
|
51125
51128
|
init_agent_discovery_directories();
|
|
51126
51129
|
});
|
|
51127
51130
|
|
package/bin/migrate.js
CHANGED
package/bin/server.js
CHANGED
|
@@ -24140,7 +24140,7 @@ restoreLaunchCwd();
|
|
|
24140
24140
|
// package.json
|
|
24141
24141
|
var package_default = {
|
|
24142
24142
|
name: "@hasna/skills",
|
|
24143
|
-
version: "0.10.
|
|
24143
|
+
version: "0.10.51",
|
|
24144
24144
|
description: "Skills library for AI coding agents",
|
|
24145
24145
|
type: "module",
|
|
24146
24146
|
bin: {
|
package/bin/worker.js
CHANGED
|
@@ -24143,7 +24143,7 @@ import { randomUUID as randomUUID6 } from "crypto";
|
|
|
24143
24143
|
// package.json
|
|
24144
24144
|
var package_default = {
|
|
24145
24145
|
name: "@hasna/skills",
|
|
24146
|
-
version: "0.10.
|
|
24146
|
+
version: "0.10.51",
|
|
24147
24147
|
description: "Skills library for AI coding agents",
|
|
24148
24148
|
type: "module",
|
|
24149
24149
|
bin: {
|
package/dist/index.js
CHANGED
|
@@ -9380,6 +9380,28 @@ function upgradeSumiSettingsWitness(previous, reviewedSettingsPath) {
|
|
|
9380
9380
|
|
|
9381
9381
|
// src/lib/agent-policy-limits.ts
|
|
9382
9382
|
import { basename as basename3, isAbsolute as isAbsolute3, join as join7, resolve as resolve3, sep as sep2 } from "path";
|
|
9383
|
+
|
|
9384
|
+
// src/lib/codex-native-compatibility.ts
|
|
9385
|
+
var MEASURED_CODEX_CAPABILITIES = {
|
|
9386
|
+
"codex-cli 0.153.0": ["hooks"],
|
|
9387
|
+
"codex-cli 0.154.0": ["hooks"],
|
|
9388
|
+
"codex-cli 0.155.0": ["hooks"],
|
|
9389
|
+
"codex-cli 0.155.1": ["hooks"],
|
|
9390
|
+
"codex-cli 0.156.1": ["hooks"],
|
|
9391
|
+
"codex-cli 0.157.0": ["hooks"],
|
|
9392
|
+
"codex-cli 0.157.1": ["hooks"],
|
|
9393
|
+
"codex-cli 0.158.0": ["hooks"],
|
|
9394
|
+
"codex-cli 0.159.0": ["hooks"],
|
|
9395
|
+
"codex-cli 0.159.2": ["hooks", "qualified-skill-catalog"],
|
|
9396
|
+
"codex-cli 0.160.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"],
|
|
9397
|
+
"codex-cli 0.160.1": ["hooks", "qualified-skill-catalog", "installed-plugin-review"]
|
|
9398
|
+
};
|
|
9399
|
+
function supportsCodexNativeCapability(version, capability) {
|
|
9400
|
+
return typeof version === "string" && Object.hasOwn(MEASURED_CODEX_CAPABILITIES, version) && MEASURED_CODEX_CAPABILITIES[version].includes(capability);
|
|
9401
|
+
}
|
|
9402
|
+
var SUPPORTED_CODEX_HOOK_VERSIONS = Object.freeze(Object.keys(MEASURED_CODEX_CAPABILITIES).filter((version) => supportsCodexNativeCapability(version, "hooks")));
|
|
9403
|
+
|
|
9404
|
+
// src/lib/agent-policy-limits.ts
|
|
9383
9405
|
var AGENT_POLICY_LIMITS = Object.freeze({ bytes: 1024 * 1024, agents: 16, discoverySources: 2048, discoveryRawSourceBytes: 64 * 1024 * 1024, discoveryRawTotalBytes: 256 * 1024 * 1024, discoveryPathLinks: 40, discoveryPathSteps: 256, discoveryPathSourceMetadataBytes: 64 * 1024, discoveryPathTotalMetadataBytes: 8 * 1024 * 1024, discoveryRoots: 512, discoveryDirectories: 64, discoveryDirectoryEntries: 20000, discoveryDirectoryBytes: 8 * 1024 * 1024, builtinNames: 2048, rootAliases: 2, fields: 64, pathCharacters: 4096 });
|
|
9384
9406
|
function object(value) {
|
|
9385
9407
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
@@ -9445,7 +9467,7 @@ function assertAgentPolicyCollections(policy) {
|
|
|
9445
9467
|
}
|
|
9446
9468
|
if (bridge.codexInactivePlugins !== undefined) {
|
|
9447
9469
|
const controls = array(bridge.codexInactivePlugins, 4096), ids = new Set;
|
|
9448
|
-
requireBound(controls.length === 0 || object(bridge.codexPluginSkillReview) && bridge.codexPluginSkillReview.version
|
|
9470
|
+
requireBound(controls.length === 0 || object(bridge.codexPluginSkillReview) && supportsCodexNativeCapability(bridge.codexPluginSkillReview.version, "installed-plugin-review") && typeof bridge.codexPluginSkillReview.catalogSha256 === "string" && /^[a-f0-9]{64}$/.test(bridge.codexPluginSkillReview.catalogSha256));
|
|
9449
9471
|
for (const control of controls) {
|
|
9450
9472
|
requireBound(object(control) && Object.keys(control).every((key) => ["pluginId", "namespace", "pluginParent", "sourceType", "sourceSha256"].includes(key)));
|
|
9451
9473
|
text(control.pluginId, 1024);
|
|
@@ -9497,7 +9519,7 @@ function assertAgentPolicyCollections(policy) {
|
|
|
9497
9519
|
}
|
|
9498
9520
|
if (value.codexInstallationInputs !== undefined) {
|
|
9499
9521
|
const proof = record(value.codexInstallationInputs, 4), inputs = array(proof.plugins, 4096), ids = new Set;
|
|
9500
|
-
requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && proof.version
|
|
9522
|
+
requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && supportsCodexNativeCapability(proof.version, "installed-plugin-review") && typeof proof.catalogSha256 === "string" && /^[a-f0-9]{64}$/.test(proof.catalogSha256) && inputs.length > 0 && object(bridge.codexPluginSkillReview) && bridge.codexPluginSkillReview.version === proof.version && bridge.codexPluginSkillReview.catalogSha256 === proof.catalogSha256);
|
|
9501
9523
|
for (const input of inputs) {
|
|
9502
9524
|
requireBound(object(input) && Object.keys(input).every((key) => ["pluginId", "namespace", "pluginParent", "sourceRoot", "sourceSha256"].includes(key)));
|
|
9503
9525
|
text(input.pluginId, 1024);
|
|
@@ -11596,7 +11618,7 @@ function replaceSkillSession(expected, replacement, plan, options = {}, beforeCo
|
|
|
11596
11618
|
// package.json
|
|
11597
11619
|
var package_default = {
|
|
11598
11620
|
name: "@hasna/skills",
|
|
11599
|
-
version: "0.10.
|
|
11621
|
+
version: "0.10.51",
|
|
11600
11622
|
description: "Skills library for AI coding agents",
|
|
11601
11623
|
type: "module",
|
|
11602
11624
|
bin: {
|
|
@@ -13684,25 +13706,6 @@ function isCodexLocalStdioMcpServer(name, server) {
|
|
|
13684
13706
|
import { basename as basename6, dirname as dirname11, join as join17, relative as relative5, resolve as resolve10, sep as sep6 } from "path";
|
|
13685
13707
|
import { lstatSync as lstatSync13, readdirSync as readdirSync6, readlinkSync as readlinkSync3, realpathSync as realpathSync6 } from "fs";
|
|
13686
13708
|
|
|
13687
|
-
// src/lib/codex-native-compatibility.ts
|
|
13688
|
-
var MEASURED_CODEX_CAPABILITIES = {
|
|
13689
|
-
"codex-cli 0.153.0": ["hooks"],
|
|
13690
|
-
"codex-cli 0.154.0": ["hooks"],
|
|
13691
|
-
"codex-cli 0.155.0": ["hooks"],
|
|
13692
|
-
"codex-cli 0.155.1": ["hooks"],
|
|
13693
|
-
"codex-cli 0.156.1": ["hooks"],
|
|
13694
|
-
"codex-cli 0.157.0": ["hooks"],
|
|
13695
|
-
"codex-cli 0.157.1": ["hooks"],
|
|
13696
|
-
"codex-cli 0.158.0": ["hooks"],
|
|
13697
|
-
"codex-cli 0.159.0": ["hooks"],
|
|
13698
|
-
"codex-cli 0.159.2": ["hooks", "qualified-skill-catalog"],
|
|
13699
|
-
"codex-cli 0.160.0": ["hooks", "qualified-skill-catalog"]
|
|
13700
|
-
};
|
|
13701
|
-
function supportsCodexNativeCapability(version, capability) {
|
|
13702
|
-
return typeof version === "string" && Object.hasOwn(MEASURED_CODEX_CAPABILITIES, version) && MEASURED_CODEX_CAPABILITIES[version].includes(capability);
|
|
13703
|
-
}
|
|
13704
|
-
var SUPPORTED_CODEX_HOOK_VERSIONS = Object.freeze(Object.keys(MEASURED_CODEX_CAPABILITIES).filter((version) => supportsCodexNativeCapability(version, "hooks")));
|
|
13705
|
-
|
|
13706
13709
|
// src/lib/codex-native-skill-catalog.ts
|
|
13707
13710
|
import { realpathSync as realpathSync5 } from "fs";
|
|
13708
13711
|
import { isAbsolute as isAbsolute11, normalize as normalize2 } from "path";
|
|
@@ -14297,6 +14300,7 @@ function reviewedCodexPluginCapabilitiesUnchanged(cache, controls, read2, rules)
|
|
|
14297
14300
|
function reviewCodexPluginControls(catalog, documents, cache, cwd, read2, rules, pluginSettings, plannedRules, denials = []) {
|
|
14298
14301
|
if (!supportsCodexNativeCapability(catalog?.version, "qualified-skill-catalog") || catalog.cwd !== cwd)
|
|
14299
14302
|
refuse2();
|
|
14303
|
+
const installedPluginReview = supportsCodexNativeCapability(catalog.version, "installed-plugin-review");
|
|
14300
14304
|
if (!Array.isArray(denials) || denials.length > 4096 || new Set(denials.map((item) => item?.path)).size !== denials.length || denials.some((item) => !item || Object.keys(item).sort().join(",") !== "name,path,sha256" || typeof item.name !== "string" || typeof item.path !== "string" || !/^[a-f0-9]{64}$/.test(item.sha256)))
|
|
14301
14305
|
refuse2();
|
|
14302
14306
|
const usedDenials = new Set;
|
|
@@ -14328,7 +14332,7 @@ function reviewCodexPluginControls(catalog, documents, cache, cwd, read2, rules,
|
|
|
14328
14332
|
if (listed.length > 1)
|
|
14329
14333
|
refuse2();
|
|
14330
14334
|
const installed = installedPlugins.filter((plugin) => plugin.id === expectedPluginId && plugin.name === pluginName);
|
|
14331
|
-
if (
|
|
14335
|
+
if (installedPluginReview && installed.length === 1 && installed[0].installed && installed[0].localVersion === basename6(located.root) && installed[0].sourceType === "local" && codexPluginSourceIsConfigControlled(installed[0])) {
|
|
14332
14336
|
const plugin = installed[0], input = { pluginId: expectedPluginId, namespace: located.namespace, pluginParent: located.pluginParent, sourceRoot: plugin.sourcePath, sourceSha256: plugin.sourceSha256 };
|
|
14333
14337
|
if (input.sourceRoot !== located.root && !input.sourceRoot.startsWith(cache + sep6) && (lstatSync13(input.sourceRoot, { throwIfNoEntry: false }) || documents.some((path) => path.startsWith(input.sourceRoot + sep6)))) {
|
|
14334
14338
|
if (skills.some((skill) => skill.path === input.sourceRoot || skill.path.startsWith(input.sourceRoot + sep6)) || !sourceInputUnchanged(input, cache, read2))
|
|
@@ -14337,7 +14341,7 @@ function reviewCodexPluginControls(catalog, documents, cache, cwd, read2, rules,
|
|
|
14337
14341
|
}
|
|
14338
14342
|
}
|
|
14339
14343
|
const settings = pluginSettings && typeof pluginSettings === "object" && !Array.isArray(pluginSettings) ? pluginSettings : undefined;
|
|
14340
|
-
if (
|
|
14344
|
+
if (installedPluginReview && !listed.length && !skills.some((skill) => skill.pluginId === expectedPluginId) && installed.length === 1 && installed[0].installed && !installed[0].enabled && codexPluginSourceIsConfigControlled(installed[0]) && settings && Object.hasOwn(settings, expectedPluginId) && settings[expectedPluginId]?.enabled === false) {
|
|
14341
14345
|
if (!Array.isArray(rules))
|
|
14342
14346
|
refuse2();
|
|
14343
14347
|
const exactPathDeny = rules.some((rule) => rule?.path === document2 && rule?.enabled === false);
|
|
@@ -14370,12 +14374,12 @@ function reviewCodexPluginControls(catalog, documents, cache, cwd, read2, rules,
|
|
|
14370
14374
|
const exactPathDeny = Array.isArray(rules) && rules.some((rule) => rule?.path === document2 && rule?.enabled === false);
|
|
14371
14375
|
const nativeSkill = { name: parsed.name, path: document2, pluginId: expectedPluginId, enabled: true };
|
|
14372
14376
|
const denial = denials.find((item) => item.path === document2);
|
|
14373
|
-
const explicitDeny = denial !== undefined && remotePluginId !== undefined &&
|
|
14377
|
+
const explicitDeny = denial !== undefined && remotePluginId !== undefined && installedPluginReview && denial.name === parsed.name && denial.sha256 === createHash12("sha256").update(read2(document2)).digest("hex") && Array.isArray(rules) && !rules.some((rule) => (rule?.path === document2 || typeof rule?.name === "string" && rule.name.trim() === parsed.name) && rule.enabled !== false) && Array.isArray(plannedRules) && plannedRules.some((rule) => rule?.path === document2 && rule.enabled === false);
|
|
14374
14378
|
if (denial && !explicitDeny)
|
|
14375
14379
|
refuse2();
|
|
14376
14380
|
if (explicitDeny)
|
|
14377
14381
|
usedDenials.add(document2);
|
|
14378
|
-
const plannedPathDeny =
|
|
14382
|
+
const plannedPathDeny = installedPluginReview && remotePluginId !== undefined && Array.isArray(rules) && rules.some((rule) => typeof rule?.name === "string" && rule.name.trim() === parsed.name && rule.enabled === false) && !rules.some((rule) => (rule?.path === document2 || typeof rule?.name === "string" && rule.name.trim() === parsed.name) && rule.enabled !== false) && Array.isArray(plannedRules) && plannedRules.some((rule) => rule?.path === document2 && rule.enabled === false) && isCodexNativeSkillDisabled(nativeSkill, plannedRules);
|
|
14379
14383
|
if (!explicitDeny && (!exactPathDeny && !plannedPathDeny || !isCodexNativeSkillDisabled(nativeSkill, rules)))
|
|
14380
14384
|
refuse2();
|
|
14381
14385
|
}
|
|
@@ -16963,7 +16967,7 @@ function planAgentIntegration(options) {
|
|
|
16963
16967
|
const { codexInstallationInputs: previousInputs, ...current } = rebound;
|
|
16964
16968
|
const inputs = codexPluginSourceInputs.map((input) => input.sourceRoot);
|
|
16965
16969
|
const directories = options.codexNativeCatalog || !previousInputs ? captureDiscoveryDirectories((binding.directories ?? []).filter((directory) => inputs.some((root) => root.startsWith(directory.path + sep7))).map((directory) => directory.path), inputs) : previousInputs.directories;
|
|
16966
|
-
const installed = codexPluginSourceInputs.length ? { ...current, codexInstallationInputs: { version:
|
|
16970
|
+
const installed = codexPluginSourceInputs.length ? { ...current, codexInstallationInputs: { version: codexPluginSkillReview.version, catalogSha256: codexPluginSkillReview.catalogSha256, plugins: codexPluginSourceInputs, ...directories?.length ? { directories } : {} } } : current;
|
|
16967
16971
|
return captureRetiredCodexDiscovery(installed, codexPluginSkills, Bun.TOML.parse(changes.find((change) => change.path === canonicalAgentPath(join23(home, ".codex/config.toml"), aliases))?.after ?? codexConfigBefore ?? "").skills?.config ?? []);
|
|
16968
16972
|
});
|
|
16969
16973
|
const nextPolicy = { ...policy, version: 1, loading: "cli", profileId, bridge: {
|
|
@@ -20637,7 +20641,7 @@ function codexInstallationRoots(binding) {
|
|
|
20637
20641
|
const proof = binding.codexInstallationInputs;
|
|
20638
20642
|
if (proof === undefined)
|
|
20639
20643
|
return [];
|
|
20640
|
-
if (binding.agent !== "codex" || binding.method !== "reviewed" || proof.version
|
|
20644
|
+
if (binding.agent !== "codex" || binding.method !== "reviewed" || !supportsCodexNativeCapability(proof.version, "installed-plugin-review") || !/^[a-f0-9]{64}$/.test(proof.catalogSha256) || !Array.isArray(proof.plugins) || !proof.plugins.length)
|
|
20641
20645
|
throw new Error("Invalid native installation input proof");
|
|
20642
20646
|
const cache = dirname19(dirname19(proof.plugins[0].pluginParent));
|
|
20643
20647
|
const config = join32(dirname19(dirname19(cache)), "config.toml"), home = dirname19(dirname19(dirname19(cache)));
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
/** `installed-plugin-review`: the 0.160 `plugin/installed` source identities and
|
|
2
|
+
* plugin loader semantics behind local installation inputs, inert disabled
|
|
3
|
+
* nonremote plugins and remote refresh denials. */
|
|
4
|
+
export type CodexNativeCapability = "hooks" | "qualified-skill-catalog" | "installed-plugin-review";
|
|
2
5
|
export declare function supportsCodexNativeCapability(version: unknown, capability: CodexNativeCapability): boolean;
|
|
3
6
|
export declare const SUPPORTED_CODEX_HOOK_VERSIONS: readonly string[];
|
package/dist/sdk/index.js
CHANGED
|
@@ -32373,7 +32373,7 @@ var init_event_sink = __esm(() => {
|
|
|
32373
32373
|
// package.json
|
|
32374
32374
|
var package_default = {
|
|
32375
32375
|
name: "@hasna/skills",
|
|
32376
|
-
version: "0.10.
|
|
32376
|
+
version: "0.10.51",
|
|
32377
32377
|
description: "Skills library for AI coding agents",
|
|
32378
32378
|
type: "module",
|
|
32379
32379
|
bin: {
|
|
@@ -38426,7 +38426,8 @@ var MEASURED_CODEX_CAPABILITIES = {
|
|
|
38426
38426
|
"codex-cli 0.158.0": ["hooks"],
|
|
38427
38427
|
"codex-cli 0.159.0": ["hooks"],
|
|
38428
38428
|
"codex-cli 0.159.2": ["hooks", "qualified-skill-catalog"],
|
|
38429
|
-
"codex-cli 0.160.0": ["hooks", "qualified-skill-catalog"]
|
|
38429
|
+
"codex-cli 0.160.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"],
|
|
38430
|
+
"codex-cli 0.160.1": ["hooks", "qualified-skill-catalog", "installed-plugin-review"]
|
|
38430
38431
|
};
|
|
38431
38432
|
function supportsCodexNativeCapability(version, capability) {
|
|
38432
38433
|
return typeof version === "string" && Object.hasOwn(MEASURED_CODEX_CAPABILITIES, version) && MEASURED_CODEX_CAPABILITIES[version].includes(capability);
|
|
@@ -39027,6 +39028,7 @@ function reviewedCodexPluginCapabilitiesUnchanged(cache, controls, read, rules)
|
|
|
39027
39028
|
function reviewCodexPluginControls(catalog, documents, cache, cwd, read, rules, pluginSettings, plannedRules, denials = []) {
|
|
39028
39029
|
if (!supportsCodexNativeCapability(catalog?.version, "qualified-skill-catalog") || catalog.cwd !== cwd)
|
|
39029
39030
|
refuse3();
|
|
39031
|
+
const installedPluginReview = supportsCodexNativeCapability(catalog.version, "installed-plugin-review");
|
|
39030
39032
|
if (!Array.isArray(denials) || denials.length > 4096 || new Set(denials.map((item) => item?.path)).size !== denials.length || denials.some((item) => !item || Object.keys(item).sort().join(",") !== "name,path,sha256" || typeof item.name !== "string" || typeof item.path !== "string" || !/^[a-f0-9]{64}$/.test(item.sha256)))
|
|
39031
39033
|
refuse3();
|
|
39032
39034
|
const usedDenials = new Set;
|
|
@@ -39058,7 +39060,7 @@ function reviewCodexPluginControls(catalog, documents, cache, cwd, read, rules,
|
|
|
39058
39060
|
if (listed.length > 1)
|
|
39059
39061
|
refuse3();
|
|
39060
39062
|
const installed = installedPlugins.filter((plugin) => plugin.id === expectedPluginId && plugin.name === pluginName);
|
|
39061
|
-
if (
|
|
39063
|
+
if (installedPluginReview && installed.length === 1 && installed[0].installed && installed[0].localVersion === basename4(located.root) && installed[0].sourceType === "local" && codexPluginSourceIsConfigControlled(installed[0])) {
|
|
39062
39064
|
const plugin = installed[0], input = { pluginId: expectedPluginId, namespace: located.namespace, pluginParent: located.pluginParent, sourceRoot: plugin.sourcePath, sourceSha256: plugin.sourceSha256 };
|
|
39063
39065
|
if (input.sourceRoot !== located.root && !input.sourceRoot.startsWith(cache + sep3) && (lstatSync7(input.sourceRoot, { throwIfNoEntry: false }) || documents.some((path) => path.startsWith(input.sourceRoot + sep3)))) {
|
|
39064
39066
|
if (skills.some((skill) => skill.path === input.sourceRoot || skill.path.startsWith(input.sourceRoot + sep3)) || !sourceInputUnchanged(input, cache, read))
|
|
@@ -39067,7 +39069,7 @@ function reviewCodexPluginControls(catalog, documents, cache, cwd, read, rules,
|
|
|
39067
39069
|
}
|
|
39068
39070
|
}
|
|
39069
39071
|
const settings = pluginSettings && typeof pluginSettings === "object" && !Array.isArray(pluginSettings) ? pluginSettings : undefined;
|
|
39070
|
-
if (
|
|
39072
|
+
if (installedPluginReview && !listed.length && !skills.some((skill) => skill.pluginId === expectedPluginId) && installed.length === 1 && installed[0].installed && !installed[0].enabled && codexPluginSourceIsConfigControlled(installed[0]) && settings && Object.hasOwn(settings, expectedPluginId) && settings[expectedPluginId]?.enabled === false) {
|
|
39071
39073
|
if (!Array.isArray(rules))
|
|
39072
39074
|
refuse3();
|
|
39073
39075
|
const exactPathDeny = rules.some((rule) => rule?.path === document && rule?.enabled === false);
|
|
@@ -39100,12 +39102,12 @@ function reviewCodexPluginControls(catalog, documents, cache, cwd, read, rules,
|
|
|
39100
39102
|
const exactPathDeny = Array.isArray(rules) && rules.some((rule) => rule?.path === document && rule?.enabled === false);
|
|
39101
39103
|
const nativeSkill = { name: parsed.name, path: document, pluginId: expectedPluginId, enabled: true };
|
|
39102
39104
|
const denial = denials.find((item) => item.path === document);
|
|
39103
|
-
const explicitDeny = denial !== undefined && remotePluginId !== undefined &&
|
|
39105
|
+
const explicitDeny = denial !== undefined && remotePluginId !== undefined && installedPluginReview && denial.name === parsed.name && denial.sha256 === createHash8("sha256").update(read(document)).digest("hex") && Array.isArray(rules) && !rules.some((rule) => (rule?.path === document || typeof rule?.name === "string" && rule.name.trim() === parsed.name) && rule.enabled !== false) && Array.isArray(plannedRules) && plannedRules.some((rule) => rule?.path === document && rule.enabled === false);
|
|
39104
39106
|
if (denial && !explicitDeny)
|
|
39105
39107
|
refuse3();
|
|
39106
39108
|
if (explicitDeny)
|
|
39107
39109
|
usedDenials.add(document);
|
|
39108
|
-
const plannedPathDeny =
|
|
39110
|
+
const plannedPathDeny = installedPluginReview && remotePluginId !== undefined && Array.isArray(rules) && rules.some((rule) => typeof rule?.name === "string" && rule.name.trim() === parsed.name && rule.enabled === false) && !rules.some((rule) => (rule?.path === document || typeof rule?.name === "string" && rule.name.trim() === parsed.name) && rule.enabled !== false) && Array.isArray(plannedRules) && plannedRules.some((rule) => rule?.path === document && rule.enabled === false) && isCodexNativeSkillDisabled(nativeSkill, plannedRules);
|
|
39109
39111
|
if (!explicitDeny && (!exactPathDeny && !plannedPathDeny || !isCodexNativeSkillDisabled(nativeSkill, rules)))
|
|
39110
39112
|
refuse3();
|
|
39111
39113
|
}
|
|
@@ -40353,7 +40355,7 @@ function assertAgentPolicyCollections(policy) {
|
|
|
40353
40355
|
}
|
|
40354
40356
|
if (bridge.codexInactivePlugins !== undefined) {
|
|
40355
40357
|
const controls = array(bridge.codexInactivePlugins, 4096), ids = new Set;
|
|
40356
|
-
requireBound(controls.length === 0 || object4(bridge.codexPluginSkillReview) && bridge.codexPluginSkillReview.version
|
|
40358
|
+
requireBound(controls.length === 0 || object4(bridge.codexPluginSkillReview) && supportsCodexNativeCapability(bridge.codexPluginSkillReview.version, "installed-plugin-review") && typeof bridge.codexPluginSkillReview.catalogSha256 === "string" && /^[a-f0-9]{64}$/.test(bridge.codexPluginSkillReview.catalogSha256));
|
|
40357
40359
|
for (const control of controls) {
|
|
40358
40360
|
requireBound(object4(control) && Object.keys(control).every((key) => ["pluginId", "namespace", "pluginParent", "sourceType", "sourceSha256"].includes(key)));
|
|
40359
40361
|
text(control.pluginId, 1024);
|
|
@@ -40405,7 +40407,7 @@ function assertAgentPolicyCollections(policy) {
|
|
|
40405
40407
|
}
|
|
40406
40408
|
if (value.codexInstallationInputs !== undefined) {
|
|
40407
40409
|
const proof = record3(value.codexInstallationInputs, 4), inputs = array(proof.plugins, 4096), ids = new Set;
|
|
40408
|
-
requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && proof.version
|
|
40410
|
+
requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && supportsCodexNativeCapability(proof.version, "installed-plugin-review") && typeof proof.catalogSha256 === "string" && /^[a-f0-9]{64}$/.test(proof.catalogSha256) && inputs.length > 0 && object4(bridge.codexPluginSkillReview) && bridge.codexPluginSkillReview.version === proof.version && bridge.codexPluginSkillReview.catalogSha256 === proof.catalogSha256);
|
|
40409
40411
|
for (const input of inputs) {
|
|
40410
40412
|
requireBound(object4(input) && Object.keys(input).every((key) => ["pluginId", "namespace", "pluginParent", "sourceRoot", "sourceSha256"].includes(key)));
|
|
40411
40413
|
text(input.pluginId, 1024);
|
|
@@ -43487,7 +43489,7 @@ function codexInstallationRoots(binding) {
|
|
|
43487
43489
|
const proof = binding.codexInstallationInputs;
|
|
43488
43490
|
if (proof === undefined)
|
|
43489
43491
|
return [];
|
|
43490
|
-
if (binding.agent !== "codex" || binding.method !== "reviewed" || proof.version
|
|
43492
|
+
if (binding.agent !== "codex" || binding.method !== "reviewed" || !supportsCodexNativeCapability(proof.version, "installed-plugin-review") || !/^[a-f0-9]{64}$/.test(proof.catalogSha256) || !Array.isArray(proof.plugins) || !proof.plugins.length)
|
|
43491
43493
|
throw new Error("Invalid native installation input proof");
|
|
43492
43494
|
const cache = dirname16(dirname16(proof.plugins[0].pluginParent));
|
|
43493
43495
|
const config = join26(dirname16(dirname16(cache)), "config.toml"), home = dirname16(dirname16(dirname16(cache)));
|
|
@@ -45083,7 +45085,7 @@ function planAgentIntegration(options) {
|
|
|
45083
45085
|
const { codexInstallationInputs: previousInputs, ...current } = rebound;
|
|
45084
45086
|
const inputs = codexPluginSourceInputs.map((input) => input.sourceRoot);
|
|
45085
45087
|
const directories = options.codexNativeCatalog || !previousInputs ? captureDiscoveryDirectories((binding.directories ?? []).filter((directory) => inputs.some((root2) => root2.startsWith(directory.path + sep7))).map((directory) => directory.path), inputs) : previousInputs.directories;
|
|
45086
|
-
const installed = codexPluginSourceInputs.length ? { ...current, codexInstallationInputs: { version:
|
|
45088
|
+
const installed = codexPluginSourceInputs.length ? { ...current, codexInstallationInputs: { version: codexPluginSkillReview.version, catalogSha256: codexPluginSkillReview.catalogSha256, plugins: codexPluginSourceInputs, ...directories?.length ? { directories } : {} } } : current;
|
|
45087
45089
|
return captureRetiredCodexDiscovery(installed, codexPluginSkills, Bun.TOML.parse(changes.find((change) => change.path === canonicalAgentPath(join27(home, ".codex/config.toml"), aliases))?.after ?? codexConfigBefore ?? "").skills?.config ?? []);
|
|
45088
45090
|
});
|
|
45089
45091
|
const nextPolicy = { ...policy, version: 1, loading: "cli", profileId, bridge: {
|
|
@@ -9,7 +9,21 @@ type InspectionManifest = EnrollmentInspectionInput & {
|
|
|
9
9
|
expiresAt: string;
|
|
10
10
|
manifestDigest: string;
|
|
11
11
|
};
|
|
12
|
+
/** The schema census has its own authorization; no enrollment or inspection manifest can authorize it. */
|
|
13
|
+
type SchemaCensusManifest = {
|
|
14
|
+
app: "skills";
|
|
15
|
+
operation: "inspect-schema";
|
|
16
|
+
manifestVersion: 1;
|
|
17
|
+
operationId: string;
|
|
18
|
+
stationId: string;
|
|
19
|
+
keyId: string;
|
|
20
|
+
orgId: string;
|
|
21
|
+
expiresAt: string;
|
|
22
|
+
manifestDigest: string;
|
|
23
|
+
};
|
|
12
24
|
/** Inspection has its own authorization; a failed enrollment manifest cannot authorize it. */
|
|
13
25
|
export declare function readInspectionManifest(path: string, receiptPath: string): InspectionManifest;
|
|
26
|
+
/** The census has its own authorization; a failed enrollment or inspection manifest cannot authorize it. */
|
|
27
|
+
export declare function readSchemaCensusManifest(path: string, receiptPath: string): SchemaCensusManifest;
|
|
14
28
|
export declare function registerMaintenance(parent: Command): void;
|
|
15
29
|
export {};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One fixed, closed census of the Skills database maintenance surface.
|
|
3
|
+
*
|
|
4
|
+
* Why it exists (I6-00024): a production migration is held until the exact
|
|
5
|
+
* current registry, version ledger and migration ledger are read from the live
|
|
6
|
+
* database. The enrollment inspection answers a different question (one
|
|
7
|
+
* operator key), and no existing reader returns the fixed aggregate + ledger
|
|
8
|
+
* census. This module is that reader, and it is deliberately shaped so it
|
|
9
|
+
* cannot become a general SQL console:
|
|
10
|
+
*
|
|
11
|
+
* - No target, query, schema or table input exists. The only argument is the
|
|
12
|
+
* database URL, and the operation refuses to run unless the connection
|
|
13
|
+
* resolves to the fixed public schema the Skills store uses.
|
|
14
|
+
* - Every owned-table read is schema-qualified to `public`. A connection whose
|
|
15
|
+
* search path falls through to a later schema cannot substitute another
|
|
16
|
+
* schema's tables: a missing public table refuses (CENSUS_SCHEMA_UNAVAILABLE)
|
|
17
|
+
* instead of counting rows that do not belong to the fixed target.
|
|
18
|
+
* - The transaction is READ ONLY, REPEATABLE READ, with a five-second
|
|
19
|
+
* statement timeout and a one-second lock timeout, asserted from inside the
|
|
20
|
+
* read path rather than assumed.
|
|
21
|
+
* - The output is a closed shape with per-field size bounds, a bounded
|
|
22
|
+
* migration ledger and a total serialized-size gate. Nothing is truncated
|
|
23
|
+
* silently: a census that would exceed a bound refuses instead.
|
|
24
|
+
* - Nothing imports the application store: no initialization, migrations,
|
|
25
|
+
* backfills or writes happen on this path.
|
|
26
|
+
*/
|
|
27
|
+
export interface SchemaCensusResult {
|
|
28
|
+
status: "inspected";
|
|
29
|
+
database: string;
|
|
30
|
+
role: string;
|
|
31
|
+
serverVersion: string;
|
|
32
|
+
schema: "public";
|
|
33
|
+
transaction: {
|
|
34
|
+
readOnly: true;
|
|
35
|
+
isolation: "repeatable read";
|
|
36
|
+
statementTimeoutMs: number;
|
|
37
|
+
lockTimeoutMs: number;
|
|
38
|
+
};
|
|
39
|
+
migrations: {
|
|
40
|
+
count: number;
|
|
41
|
+
versions: string[];
|
|
42
|
+
};
|
|
43
|
+
registry: {
|
|
44
|
+
rows: number;
|
|
45
|
+
};
|
|
46
|
+
versions: {
|
|
47
|
+
rows: number;
|
|
48
|
+
};
|
|
49
|
+
lifecycle: {
|
|
50
|
+
active: {
|
|
51
|
+
live: number;
|
|
52
|
+
tombstoned: number;
|
|
53
|
+
};
|
|
54
|
+
archived: {
|
|
55
|
+
live: number;
|
|
56
|
+
tombstoned: number;
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
authorizationEpoch: {
|
|
60
|
+
exists: false;
|
|
61
|
+
} | {
|
|
62
|
+
exists: true;
|
|
63
|
+
nullCount: number;
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
type CensusCode = "CENSUS_POSTGRES_REQUIRED" | "CENSUS_SCHEMA_UNAVAILABLE" | "CENSUS_ACCESS_DENIED" | "CENSUS_WRITE_REFUSED" | "CENSUS_TIMEOUT" | "CENSUS_CONNECTION_FAILED" | "CENSUS_TARGET_MISMATCH" | "CENSUS_INVALID_RESULT" | "CENSUS_OUTPUT_UNBOUNDED" | "CENSUS_FAILED";
|
|
67
|
+
export declare class SchemaCensusError extends Error {
|
|
68
|
+
readonly code: CensusCode;
|
|
69
|
+
constructor(code: CensusCode);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Census metadata only. Deliberately does not import or initialize the application store.
|
|
73
|
+
*
|
|
74
|
+
* @param databaseUrl explicit PostgreSQL URL; there is no implicit localhost fallback.
|
|
75
|
+
*/
|
|
76
|
+
export declare function inspectSchemaCensus(databaseUrl: string): Promise<SchemaCensusResult>;
|
|
77
|
+
export {};
|
package/docs/plugin-admission.md
CHANGED
|
@@ -404,8 +404,8 @@ witness intersecting the write still refuses instead of adopting a new inode.
|
|
|
404
404
|
|
|
405
405
|
## Codex bundled cleanup controls
|
|
406
406
|
|
|
407
|
-
Qualified native skill review supports a narrow subset of Codex 0.159.2
|
|
408
|
-
0.160.0's bundled cleanup hooks. The identities `browser`, `chrome`, `chrome-dev`,
|
|
407
|
+
Qualified native skill review supports a narrow subset of Codex 0.159.2,
|
|
408
|
+
0.160.0 and 0.160.1's bundled cleanup hooks. The identities `browser`, `chrome`, `chrome-dev`,
|
|
409
409
|
`chrome-internal` and `computer-use` in `openai-bundled` may call
|
|
410
410
|
`node_repl.turn_ended`; `unified-computer-use` may call `cua_repl.turn_ended`.
|
|
411
411
|
Only `Interrupt`, `SubagentStop` and `Stop` are accepted, with one group and one
|
|
@@ -421,4 +421,6 @@ apply and subsequent discovery checks. This review preserves native cleanup;
|
|
|
421
421
|
it neither enables plugins nor grants hook trust, browser authority or signing.
|
|
422
422
|
The upstream contracts are
|
|
423
423
|
[0.159.2 bundled hooks](https://github.com/openai/codex/blob/ff6aec96948b70d94983af2641a6b67c94faeff5/codex-rs/plugin/src/bundled_hooks.rs)
|
|
424
|
-
and [0.160.0 bundled hooks](https://github.com/openai/codex/blob/a956835d020762cb2b570053af06f643a11c0ecc/codex-rs/plugin/src/bundled_hooks.rs)
|
|
424
|
+
and [0.160.0 bundled hooks](https://github.com/openai/codex/blob/a956835d020762cb2b570053af06f643a11c0ecc/codex-rs/plugin/src/bundled_hooks.rs);
|
|
425
|
+
0.160.1 carries the identical file
|
|
426
|
+
([0.160.1 bundled hooks](https://github.com/openai/codex/blob/d27764b82f7118f674371e6d6e76271d9d606edb/codex-rs/plugin/src/bundled_hooks.rs)).
|