Correct registry validation and contain metadata reads (#1500)
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { test } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from "node:fs";
|
||||
import { mkdtempSync, mkdirSync, writeFileSync, rmSync, cpSync, chmodSync, readdirSync, lstatSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join, dirname, resolve } from "node:path";
|
||||
import { spawnSync } from "node:child_process";
|
||||
@@ -15,12 +15,23 @@ function makeRoot() {
|
||||
return root;
|
||||
}
|
||||
|
||||
function privateTree(root) {
|
||||
chmodSync(root, 0o700);
|
||||
for (const name of readdirSync(root)) {
|
||||
const p = join(root, name);
|
||||
if (lstatSync(p).isDirectory()) privateTree(p);
|
||||
else chmodSync(p, 0o600);
|
||||
}
|
||||
}
|
||||
function writeTree(root, files) {
|
||||
for (const name of ['auth/providers', 'auth/accounts', 'auth/settings', 'harnesses'])
|
||||
mkdirSync(join(root, name), { recursive: true });
|
||||
for (const [name, content] of Object.entries(files)) {
|
||||
const path = join(root, name);
|
||||
mkdirSync(dirname(path), { recursive: true });
|
||||
writeFileSync(path, typeof content === "string" ? content : JSON.stringify(content));
|
||||
}
|
||||
privateTree(root);
|
||||
}
|
||||
|
||||
function runCli(root, command = "validate") {
|
||||
@@ -28,17 +39,21 @@ function runCli(root, command = "validate") {
|
||||
}
|
||||
|
||||
const validTree = () => ({
|
||||
"auth/providers/openai-codex.json": { providerVersion: "1", id: "openai-codex", kind: "native", harnesses: { pi: { providerId: "openai-codex" } }, credentialTypes: ["oauth", "api_key"] },
|
||||
"auth/accounts/openai-codex/homelab/account.json": { accountVersion: "1", id: "homelab", name: "Homelab", provider: "openai-codex", type: "oauth", createdAt: "2026-09-10T00:00:00Z" },
|
||||
"auth/settings/research.json": { settingsVersion: "1", id: "research", allowedAccounts: ["openai-codex/homelab"], providers: ["openai-codex"], defaultAccounts: { "openai-codex": "openai-codex/homelab" } },
|
||||
"harnesses/pi.json": { harnessVersion: "1", id: "pi", executable: "pi", adapter: "pi", compatibleRange: ">=0.85.1 <0.86.0", executionMode: "container", materializers: ["auth-json"] },
|
||||
"auth/providers/openai-codex.json": { providerVersion: 1, id: "openai-codex", kind: "native", harnesses: { pi: { providerId: "openai-codex" } }, credentialTypes: ["oauth", "api_key"] },
|
||||
"auth/accounts/openai-codex/homelab/account.json": { accountVersion: 1, id: "homelab", name: "Homelab", provider: "openai-codex", type: "oauth", createdAt: "2026-09-10T00:00:00Z" },
|
||||
"auth/settings/research.json": { settingsVersion: 1, id: "research", allowedAccounts: ["openai-codex/homelab"], providers: ["openai-codex"], defaultAccounts: { "openai-codex": "openai-codex/homelab" } },
|
||||
"harnesses/pi.json": { harnessVersion: 1, id: "pi", executable: "pi", adapter: "pi", compatibleRange: ">=0.85.1 <0.86.0", executionMode: "container", materializers: ["auth-json"] },
|
||||
});
|
||||
|
||||
test("valid fixture tree validates and lists without secrets", () => {
|
||||
const r = runCli(validFixture);
|
||||
const root = makeRoot();
|
||||
try {
|
||||
cpSync(validFixture, root, { recursive: true });
|
||||
privateTree(root);
|
||||
const r = runCli(root);
|
||||
assert.equal(r.status, 0, r.stderr);
|
||||
assert.match(r.stdout, /^valid\n$/);
|
||||
const l = runCli(validFixture, "list");
|
||||
const l = runCli(root, "list");
|
||||
assert.equal(l.status, 0, l.stderr);
|
||||
const listed = JSON.parse(l.stdout);
|
||||
assert.equal(listed.providers.length, 2);
|
||||
@@ -46,20 +61,21 @@ test("valid fixture tree validates and lists without secrets", () => {
|
||||
assert.equal(listed.profiles.length, 1);
|
||||
assert.ok(!JSON.stringify(listed).includes("credential"));
|
||||
assert.ok(!JSON.stringify(listed).includes("token"));
|
||||
} finally { rmSync(root, { recursive: true, force: true }); }
|
||||
});
|
||||
|
||||
test("unknown-field refuses", () => {
|
||||
const errors = validateProvider({ providerVersion: "1", id: "p", kind: "native", harnesses: {}, credentialTypes: ["none"], extra: 1 });
|
||||
const errors = validateProvider({ providerVersion: 1, id: "p", kind: "native", harnesses: {}, credentialTypes: ["none"], extra: 1 });
|
||||
assert.equal(errors[0].code, "unknown-field");
|
||||
});
|
||||
|
||||
test("invalid-id refuses uppercase and traversal shapes", () => {
|
||||
assert.ok(validateProvider({ providerVersion: "1", id: "BadID", kind: "native", harnesses: {}, credentialTypes: ["none"] }).some((e) => e.code === "invalid-id"));
|
||||
assert.ok(validateAccount({ accountVersion: "1", id: "../escape", name: "x", provider: "p", type: "oauth", createdAt: "2026-09-10T00:00:00Z" }).some((e) => e.code === "invalid-id"));
|
||||
assert.ok(validateProvider({ providerVersion: 1, id: "BadID", kind: "native", harnesses: {}, credentialTypes: ["none"] }).some((e) => e.code === "invalid-id"));
|
||||
assert.ok(validateAccount({ accountVersion: 1, id: "../escape", name: "x", provider: "p", type: "oauth", createdAt: "2026-09-10T00:00:00Z" }).some((e) => e.code === "invalid-id"));
|
||||
});
|
||||
|
||||
test("plain-http baseUrl requires allowInsecureTransport", () => {
|
||||
const base = { providerVersion: "1", id: "o", kind: "custom-endpoint", harnesses: { pi: { api: "openai-completions", baseUrl: "http://h:11434/v1", models: ["m"] } }, credentialTypes: ["none"] };
|
||||
const base = { providerVersion: 1, id: "o", kind: "custom-endpoint", harnesses: { pi: { api: "openai-completions", baseUrl: "http://h:11434/v1", models: ["m"] } }, credentialTypes: ["none"] };
|
||||
assert.ok(validateProvider(base).some((e) => e.code === "insecure-transport-not-allowed"));
|
||||
assert.equal(validateProvider({ ...base, allowInsecureTransport: true }).length, 0);
|
||||
const https = JSON.parse(JSON.stringify(base));
|
||||
@@ -68,30 +84,30 @@ test("plain-http baseUrl requires allowInsecureTransport", () => {
|
||||
});
|
||||
|
||||
test("native provider rejects allowInsecureTransport", () => {
|
||||
assert.ok(validateProvider({ providerVersion: "1", id: "p", kind: "native", harnesses: {}, credentialTypes: ["none"], allowInsecureTransport: true }).some((e) => e.code === "insecure-transport-unsupported-for-native"));
|
||||
assert.ok(validateProvider({ providerVersion: 1, id: "p", kind: "native", harnesses: {}, credentialTypes: ["none"], allowInsecureTransport: true }).some((e) => e.code === "insecure-transport-unsupported-for-native"));
|
||||
});
|
||||
|
||||
test("unsupported credential type and kind refuse", () => {
|
||||
assert.ok(validateAccount({ accountVersion: "1", id: "a", name: "x", provider: "p", type: "basic", createdAt: "2026-09-10T00:00:00Z" }).some((e) => e.code === "unsupported-credential-type"));
|
||||
assert.ok(validateProvider({ providerVersion: "1", id: "p", kind: "weird", harnesses: {}, credentialTypes: ["none"] }).some((e) => e.code === "unsupported-kind"));
|
||||
assert.ok(validateAccount({ accountVersion: 1, id: "a", name: "x", provider: "p", type: "basic", createdAt: "2026-09-10T00:00:00Z" }).some((e) => e.code === "unsupported-credential-type"));
|
||||
assert.ok(validateProvider({ providerVersion: 1, id: "p", kind: "weird", harnesses: {}, credentialTypes: ["none"] }).some((e) => e.code === "unsupported-kind"));
|
||||
});
|
||||
|
||||
test("account provider-path mismatch refuses", () => {
|
||||
assert.ok(validateAccount({ accountVersion: "1", id: "a", name: "x", provider: "other", type: "oauth", createdAt: "2026-09-10T00:00:00Z" }, "right").some((e) => e.code === "provider-path-mismatch"));
|
||||
assert.ok(validateAccount({ accountVersion: 1, id: "a", name: "x", provider: "other", type: "oauth", createdAt: "2026-09-10T00:00:00Z" }, "right").some((e) => e.code === "provider-path-mismatch"));
|
||||
});
|
||||
|
||||
test("profile account refs must be provider/account shaped", () => {
|
||||
const errors = validateSettingsProfile({ settingsVersion: "1", id: "s", allowedAccounts: ["justone"], providers: [], defaultAccounts: {} });
|
||||
const errors = validateSettingsProfile({ settingsVersion: 1, id: "s", allowedAccounts: ["justone"], providers: [], defaultAccounts: {} });
|
||||
assert.ok(errors.some((e) => e.code === "invalid-account-ref-list"));
|
||||
});
|
||||
|
||||
test("seat selection accepts fork pin field, validates account refs", () => {
|
||||
assert.equal(validateSeatSelection({ selectionVersion: "1", profile: "research", accounts: { "openai-codex": "openai-codex/homelab" }, updatedAt: "2026-09-10T00:00:00Z", pinnedFromSession: "abc123" }).length, 0);
|
||||
assert.ok(validateSeatSelection({ selectionVersion: "1", profile: "research", accounts: { "openai-codex": "nope" } }).some((e) => e.code === "invalid-account-ref"));
|
||||
assert.equal(validateSeatSelection({ selectionVersion: 1, profile: "research", accounts: { "openai-codex": "openai-codex/homelab" }, updatedAt: "2026-09-10T00:00:00Z", pinnedFromSession: "abc123" }).length, 0);
|
||||
assert.ok(validateSeatSelection({ selectionVersion: 1, profile: "research", accounts: { "openai-codex": "nope" } }).some((e) => e.code === "invalid-account-ref"));
|
||||
});
|
||||
|
||||
test("harness manifest id must equal executable (gate 1)", () => {
|
||||
assert.ok(validateHarnessManifest({ harnessVersion: "1", id: "pi", executable: "claude", adapter: "x", compatibleRange: ">=1", executionMode: "container", materializers: ["m"] }).some((e) => e.code === "id-executable-mismatch"));
|
||||
assert.ok(validateHarnessManifest({ harnessVersion: 1, id: "pi", executable: "claude", adapter: "x", compatibleRange: ">=1", executionMode: "container", materializers: ["m"] }).some((e) => e.code === "id-executable-mismatch"));
|
||||
});
|
||||
|
||||
test("CLI validate: duplicate provider id across files refuses", () => {
|
||||
|
||||
Reference in New Issue
Block a user