skills-layer 0.1.7 → 0.1.9
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 +2 -2
- package/SECURITY.md +18 -0
- package/package.json +6 -6
- package/public/skills-layer-public.mjs +360 -126
- package/tests/public-cli-package.test.mjs +0 -216
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
import { execFile } from "node:child_process";
|
|
2
|
-
import test from "node:test";
|
|
3
|
-
import assert from "node:assert/strict";
|
|
4
|
-
import { mkdtemp, readFile } from "node:fs/promises";
|
|
5
|
-
import { tmpdir } from "node:os";
|
|
6
|
-
import { join } from "node:path";
|
|
7
|
-
import { fileURLToPath } from "node:url";
|
|
8
|
-
|
|
9
|
-
const packageUrl = new URL("../package.json", import.meta.url);
|
|
10
|
-
const runtimeUrl = new URL("../public/skills-layer-public.mjs", import.meta.url);
|
|
11
|
-
const readmeUrl = new URL("../README.md", import.meta.url);
|
|
12
|
-
const licenseUrl = new URL("../LICENSE", import.meta.url);
|
|
13
|
-
const wrapperUrl = new URL("../scripts/skills-layer.mjs", import.meta.url);
|
|
14
|
-
const securityUrl = new URL("../SECURITY.md", import.meta.url);
|
|
15
|
-
const contributingUrl = new URL("../CONTRIBUTING.md", import.meta.url);
|
|
16
|
-
const codeOfConductUrl = new URL("../CODE_OF_CONDUCT.md", import.meta.url);
|
|
17
|
-
const dependabotUrl = new URL("../.github/dependabot.yml", import.meta.url);
|
|
18
|
-
const ciWorkflowUrl = new URL("../.github/workflows/ci.yml", import.meta.url);
|
|
19
|
-
const trustedPublishWorkflowUrl = new URL("../.github/workflows/publish.yml", import.meta.url);
|
|
20
|
-
const binPath = fileURLToPath(new URL("../bin/skills-layer.js", import.meta.url));
|
|
21
|
-
|
|
22
|
-
async function loadRuntime() {
|
|
23
|
-
return await import(runtimeUrl.href);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
async function makeHome() {
|
|
27
|
-
return await mkdtemp(join(tmpdir(), "skills-layer-cli-package-home-"));
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function packageEnv(home) {
|
|
31
|
-
const env = {
|
|
32
|
-
...process.env,
|
|
33
|
-
HOME: home,
|
|
34
|
-
SKILLS_LAYER_NO_BANNER: "1"
|
|
35
|
-
};
|
|
36
|
-
delete env.SKILLS_LAYER_API_KEY;
|
|
37
|
-
delete env.SKILLS_LAYER_BASE_URL;
|
|
38
|
-
delete env.SKILLS_LAYER_MCP_TOKEN;
|
|
39
|
-
return env;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
async function runPublic(args, options = {}) {
|
|
43
|
-
const runtime = await loadRuntime();
|
|
44
|
-
return await runtime.executePublicCli(args, {
|
|
45
|
-
env: packageEnv(options.home ?? await makeHome()),
|
|
46
|
-
cwd: options.cwd,
|
|
47
|
-
stdoutIsTty: false,
|
|
48
|
-
fetch: options.fetch ?? (async () => { throw new Error("Unexpected network call from package contract test."); })
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
async function runBin(args) {
|
|
53
|
-
const home = await makeHome();
|
|
54
|
-
return await new Promise((resolve) => {
|
|
55
|
-
execFile(process.execPath, [binPath, ...args], { env: packageEnv(home) }, (error, stdout, stderr) => {
|
|
56
|
-
resolve({
|
|
57
|
-
exitCode: typeof error?.code === "number" ? error.code : 0,
|
|
58
|
-
stdout,
|
|
59
|
-
stderr
|
|
60
|
-
});
|
|
61
|
-
});
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function parseJsonOutput(result) {
|
|
66
|
-
assert.equal(result.stderr, "");
|
|
67
|
-
return JSON.parse(result.stdout);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function parseJsonError(result) {
|
|
71
|
-
assert.equal(result.stdout, "");
|
|
72
|
-
return JSON.parse(result.stderr);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
test("public package metadata keeps the npm tree narrow and non-lifecycle", async () => {
|
|
76
|
-
const packageJson = JSON.parse(await readFile(packageUrl, "utf8"));
|
|
77
|
-
assert.equal(packageJson.name, "skills-layer");
|
|
78
|
-
assert.equal(packageJson.private, false);
|
|
79
|
-
assert.equal(packageJson.type, "module");
|
|
80
|
-
assert.equal(packageJson.bin["skills-layer"], "bin/skills-layer.js");
|
|
81
|
-
assert.equal(packageJson.dependencies, undefined);
|
|
82
|
-
assert.equal(packageJson.devDependencies, undefined);
|
|
83
|
-
assert.equal(packageJson.license, "Apache-2.0");
|
|
84
|
-
assert.deepEqual(packageJson.repository, {
|
|
85
|
-
type: "git",
|
|
86
|
-
url: "git+https://github.com/ankurdhoom/skills-layer.git"
|
|
87
|
-
});
|
|
88
|
-
assert.deepEqual(packageJson.bugs, { url: "https://github.com/ankurdhoom/skills-layer/issues" });
|
|
89
|
-
assert.deepEqual(packageJson.files, [
|
|
90
|
-
"bin/skills-layer.js",
|
|
91
|
-
"public/skills-layer-public.mjs",
|
|
92
|
-
"scripts/skills-layer.mjs",
|
|
93
|
-
"docs/assets/*.svg",
|
|
94
|
-
"tests/public-cli-package.test.mjs"
|
|
95
|
-
]);
|
|
96
|
-
assert.deepEqual(Object.keys(packageJson.scripts).sort(), ["test", "test:coverage", "typecheck"]);
|
|
97
|
-
for (const lifecycleScript of ["preinstall", "install", "postinstall", "prepare", "prepack", "postpack", "prepublishOnly"]) {
|
|
98
|
-
assert.equal(packageJson.scripts[lifecycleScript], undefined);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const workflow = await readFile(trustedPublishWorkflowUrl, "utf8");
|
|
102
|
-
assert.match(workflow, /name: Publish skills-layer to npm/u);
|
|
103
|
-
assert.match(workflow, /id-token: write/u);
|
|
104
|
-
assert.match(workflow, /npm publish --access public --provenance/u);
|
|
105
|
-
assert.doesNotMatch(workflow, /NPM_TOKEN/u);
|
|
106
|
-
|
|
107
|
-
const ciWorkflow = await readFile(ciWorkflowUrl, "utf8");
|
|
108
|
-
assert.match(ciWorkflow, /name: CLI package CI/u);
|
|
109
|
-
assert.match(ciWorkflow, /npm run typecheck/u);
|
|
110
|
-
assert.match(ciWorkflow, /npm run test:coverage/u);
|
|
111
|
-
assert.doesNotMatch(ciWorkflow, /NPM_TOKEN/u);
|
|
112
|
-
|
|
113
|
-
const dependabot = await readFile(dependabotUrl, "utf8");
|
|
114
|
-
assert.match(dependabot, /package-ecosystem: npm/u);
|
|
115
|
-
|
|
116
|
-
const [security, contributing, codeOfConduct] = await Promise.all([
|
|
117
|
-
readFile(securityUrl, "utf8"),
|
|
118
|
-
readFile(contributingUrl, "utf8"),
|
|
119
|
-
readFile(codeOfConductUrl, "utf8")
|
|
120
|
-
]);
|
|
121
|
-
assert.match(security, /Please do not open public issues for active vulnerabilities/u);
|
|
122
|
-
assert.match(security, /hello@skills-layer\.com/u);
|
|
123
|
-
assert.match(contributing, /Do not submit backend service code/u);
|
|
124
|
-
assert.match(codeOfConduct, /Expected Behavior/u);
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
test("public package text stays limited to public CLI surface", async () => {
|
|
128
|
-
const [packageText, readme, license, runtime, wrapper] = await Promise.all([
|
|
129
|
-
readFile(packageUrl, "utf8"),
|
|
130
|
-
readFile(readmeUrl, "utf8"),
|
|
131
|
-
readFile(licenseUrl, "utf8"),
|
|
132
|
-
readFile(runtimeUrl, "utf8"),
|
|
133
|
-
readFile(wrapperUrl, "utf8")
|
|
134
|
-
]);
|
|
135
|
-
const combined = `${packageText}\n${readme}\n${license}\n${runtime}\n${wrapper}`;
|
|
136
|
-
assert.match(combined, /Skills Layer/u);
|
|
137
|
-
assert.match(combined, /skills-layer/u);
|
|
138
|
-
assert.match(readme, /open-source CLI, MCP setup, and local agent integration layer/u);
|
|
139
|
-
assert.match(readme, /hosted backend code, marketplace services, Guardian scoring internals, and service operations remain proprietary/u);
|
|
140
|
-
assert.match(readme, /actions\/workflows\/ci\.yml\/badge\.svg/u);
|
|
141
|
-
assert.match(readme, /https:\/\/unpkg\.com\/skills-layer\/docs\/assets\/skills-layer-logo\.svg/u);
|
|
142
|
-
assert.match(readme, /https:\/\/unpkg\.com\/skills-layer\/docs\/assets\/skills-layer-hero\.svg/u);
|
|
143
|
-
assert.match(readme, /https:\/\/unpkg\.com\/skills-layer\/docs\/assets\/skills-layer-flow\.svg/u);
|
|
144
|
-
assert.match(readme, /https:\/\/unpkg\.com\/skills-layer\/docs\/assets\/skills-layer-marketplace-flow\.svg/u);
|
|
145
|
-
assert.doesNotMatch(readme, /src="docs\/assets\//u);
|
|
146
|
-
for (const forbidden of [
|
|
147
|
-
new RegExp(["", "api", "v1", "admin"].join("/"), "u"),
|
|
148
|
-
new RegExp(["x", "skills", "layer", "admin", "key"].join("-"), "u"),
|
|
149
|
-
new RegExp(["SKILLS", "LAYER", "ADMIN", "API", "KEY"].join("_"), "u"),
|
|
150
|
-
new RegExp(["--", "admin", "api", "key"].join("-"), "u"),
|
|
151
|
-
new RegExp(["github.com", "openai", "openskills"].join("/"), "u")
|
|
152
|
-
]) {
|
|
153
|
-
assert.doesNotMatch(combined, forbidden);
|
|
154
|
-
}
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
test("public bin wrapper and runtime expose deterministic package smoke commands", async () => {
|
|
158
|
-
const packageJson = JSON.parse(await readFile(packageUrl, "utf8"));
|
|
159
|
-
const expectedVersionLine = `skills-layer ${packageJson.version}`;
|
|
160
|
-
const runtime = await loadRuntime();
|
|
161
|
-
const binVersion = await runBin(["--version"]);
|
|
162
|
-
assert.equal(binVersion.exitCode, 0);
|
|
163
|
-
assert.equal(binVersion.stderr, "");
|
|
164
|
-
assert.equal(binVersion.stdout.trim(), expectedVersionLine);
|
|
165
|
-
|
|
166
|
-
const version = await runtime.executePublicCli(["--version"]);
|
|
167
|
-
assert.equal(version.exitCode, 0);
|
|
168
|
-
assert.equal(version.stdout.trim(), expectedVersionLine);
|
|
169
|
-
|
|
170
|
-
const jsonVersion = await runPublic(["version", "--json"]);
|
|
171
|
-
assert.equal(jsonVersion.exitCode, 0);
|
|
172
|
-
assert.equal(parseJsonOutput(jsonVersion).data.version, packageJson.version);
|
|
173
|
-
|
|
174
|
-
const loginHelp = await runtime.executePublicCli(["login", "--help"]);
|
|
175
|
-
assert.equal(loginHelp.exitCode, 0);
|
|
176
|
-
assert.match(loginHelp.stdout, /Skills Layer login help/u);
|
|
177
|
-
assert.match(loginHelp.stdout, /skills-layer mcp setup/u);
|
|
178
|
-
|
|
179
|
-
const fullHelp = await runtime.executePublicCli(["help", "full"]);
|
|
180
|
-
assert.equal(fullHelp.exitCode, 0);
|
|
181
|
-
assert.match(fullHelp.stdout, /Start here:/u);
|
|
182
|
-
assert.match(fullHelp.stdout, /skills-layer help full/u);
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
test("public runtime persists backend preference without network access", async () => {
|
|
186
|
-
const home = await makeHome();
|
|
187
|
-
const update = await runPublic(["backend", "--base-url", "https://staging.findfigg.co.uk", "--json"], { home });
|
|
188
|
-
assert.equal(update.exitCode, 0);
|
|
189
|
-
assert.equal(parseJsonOutput(update).data.selectedBaseUrl, "https://staging.findfigg.co.uk");
|
|
190
|
-
|
|
191
|
-
const preference = JSON.parse(await readFile(join(home, ".skills-layer", "backend-preference.json"), "utf8"));
|
|
192
|
-
assert.equal(preference.preferredBaseUrl, "https://staging.findfigg.co.uk");
|
|
193
|
-
|
|
194
|
-
const status = await runPublic(["backend", "status", "--json"], { home });
|
|
195
|
-
assert.equal(status.exitCode, 0);
|
|
196
|
-
const statusPayload = parseJsonOutput(status);
|
|
197
|
-
assert.equal(statusPayload.data.selectedBaseUrl, "https://staging.findfigg.co.uk");
|
|
198
|
-
assert.equal(statusPayload.data.loggedIn, false);
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
test("public runtime fails closed for internal and login-required commands", async () => {
|
|
202
|
-
const admin = await runPublic(["admin", "status", "--json"]);
|
|
203
|
-
assert.equal(admin.exitCode, 1);
|
|
204
|
-
const adminPayload = parseJsonError(admin);
|
|
205
|
-
assert.equal(adminPayload.status, "error");
|
|
206
|
-
assert.match(adminPayload.summary, /does not include internal commands/u);
|
|
207
|
-
|
|
208
|
-
const whoami = await runPublic(["whoami", "--json"]);
|
|
209
|
-
assert.equal(whoami.exitCode, 1);
|
|
210
|
-
const whoamiPayload = parseJsonError(whoami);
|
|
211
|
-
assert.equal(whoamiPayload.status, "login_required");
|
|
212
|
-
assert.equal(whoamiPayload.reasonCode, "login_required");
|
|
213
|
-
assert.equal(whoamiPayload.nextAction, "login");
|
|
214
|
-
assert.match(whoamiPayload.nextStep, /skills-layer login/u);
|
|
215
|
-
assert.doesNotMatch(whoamiPayload.summary, /--api-key/u);
|
|
216
|
-
});
|