@subbly/plugin-lint 0.0.2 → 0.0.3
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/CHANGELOG.md +6 -0
- package/package.json +1 -1
- package/src/report.mjs +3 -1
- package/src/rules.mjs +32 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @subbly/plugin-lint
|
|
2
2
|
|
|
3
|
+
## 0.0.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- A connector marker may carry a `tools` allowlist beside `auth`, and `auth` becomes optional. `tools` is a non-empty array of unique tool names, 1-100 characters each. A marker with neither field is rejected, as the builder refresh rejects it. Rule ids `connector/marker` and `connector/tools` join `connector/auth`.
|
|
8
|
+
|
|
3
9
|
## 0.0.2
|
|
4
10
|
|
|
5
11
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@subbly/plugin-lint",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "The Subbly marketplace release gate, offline. Lints marketplace.json, plugin manifests, mcp.json, skills, agents and automations.",
|
package/src/report.mjs
CHANGED
|
@@ -64,7 +64,9 @@ export const RULES = {
|
|
|
64
64
|
'setup/missing-install-skill': 'setup: true requires a skills/install skill',
|
|
65
65
|
|
|
66
66
|
// connectors and mcp.json
|
|
67
|
-
'connector/
|
|
67
|
+
'connector/marker': 'a connector marker holds auth, tools or both, and nothing else',
|
|
68
|
+
'connector/auth': 'auth, when present, is exactly "oauth"',
|
|
69
|
+
'connector/tools': 'tools is a non-empty array of unique tool names, 1-100 characters each',
|
|
68
70
|
'connector/name-length': 'connector names are 1-100 characters',
|
|
69
71
|
'connector/undefined-server': 'a declared connector needs a matching mcp.json server',
|
|
70
72
|
'connector/no-mcp': 'declaring a connector requires an mcp.json',
|
package/src/rules.mjs
CHANGED
|
@@ -564,7 +564,7 @@ function lintSchedule(report, file, pos, label, schedule) {
|
|
|
564
564
|
function lintConnectors(report, file, at, check, ns, ext) {
|
|
565
565
|
if (ext.connectors === undefined) return []
|
|
566
566
|
if (!isObject(ext.connectors)) {
|
|
567
|
-
report.error('connector/
|
|
567
|
+
report.error('connector/marker', file, `${ns}.connectors: expected object, received ${typeOf(ext.connectors)}`, at(`${ns}.connectors`))
|
|
568
568
|
return []
|
|
569
569
|
}
|
|
570
570
|
|
|
@@ -577,18 +577,46 @@ function lintConnectors(report, file, at, check, ns, ext) {
|
|
|
577
577
|
report.error('connector/name-length', file, `${label}: connector name must be 1-100 characters`, at(p, { key: true }))
|
|
578
578
|
}
|
|
579
579
|
if (!isObject(marker)) {
|
|
580
|
-
report.error('connector/
|
|
580
|
+
report.error('connector/marker', file, `${label}: expected object, received ${typeOf(marker)}`, at(p))
|
|
581
581
|
continue
|
|
582
582
|
}
|
|
583
|
-
check.strictKeys('connector/
|
|
584
|
-
if (marker.auth
|
|
583
|
+
check.strictKeys('connector/marker', p, marker, ['auth', 'tools'], label)
|
|
584
|
+
if (marker.auth === undefined && marker.tools === undefined) {
|
|
585
|
+
report.error('connector/marker', file, `${label}: declare auth, tools or both`, at(p))
|
|
586
|
+
}
|
|
587
|
+
if (marker.auth !== undefined && marker.auth !== 'oauth') {
|
|
585
588
|
report.error('connector/auth', file, `${label}.auth: expected "oauth", received ${JSON.stringify(marker.auth)}`, at(`${p}.auth`))
|
|
586
589
|
}
|
|
590
|
+
if (marker.tools !== undefined) {
|
|
591
|
+
lintToolAllowlist(report, file, at, check, `${p}.tools`, `${label}.tools`, marker.tools)
|
|
592
|
+
}
|
|
587
593
|
names.push(name)
|
|
588
594
|
}
|
|
589
595
|
return names
|
|
590
596
|
}
|
|
591
597
|
|
|
598
|
+
function lintToolAllowlist(report, file, at, check, p, label, tools) {
|
|
599
|
+
if (!Array.isArray(tools)) {
|
|
600
|
+
report.error('connector/tools', file, `${label}: expected array, received ${typeOf(tools)}`, at(p))
|
|
601
|
+
return
|
|
602
|
+
}
|
|
603
|
+
if (tools.length === 0) {
|
|
604
|
+
report.error('connector/tools', file, `${label}: must name at least one tool`, at(p))
|
|
605
|
+
return
|
|
606
|
+
}
|
|
607
|
+
const seen = new Set()
|
|
608
|
+
for (const [index, tool] of tools.entries()) {
|
|
609
|
+
if (!check.string('connector/tools', `${p}.${index}`, tool, { min: 1, max: 100, label: `${label}[${index}]` })) {
|
|
610
|
+
continue
|
|
611
|
+
}
|
|
612
|
+
if (seen.has(tool)) {
|
|
613
|
+
report.error('connector/tools', file, `${label}[${index}]: duplicate tool name "${tool}"`, at(`${p}.${index}`))
|
|
614
|
+
continue
|
|
615
|
+
}
|
|
616
|
+
seen.add(tool)
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
|
|
592
620
|
// --- mcp.json --------------------------------------------------------------
|
|
593
621
|
|
|
594
622
|
function lintMcp(root, entry, manifest, report) {
|