@solidnumber/cli 1.9.28 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/agent.js +85 -0
- package/dist/commands/agent.js.map +1 -1
- package/dist/commands/ai.d.ts.map +1 -1
- package/dist/commands/ai.js +15 -0
- package/dist/commands/ai.js.map +1 -1
- package/dist/commands/doctor.js +94 -0
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/mcp.d.ts +17 -0
- package/dist/commands/mcp.d.ts.map +1 -0
- package/dist/commands/mcp.js +261 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/schema.d.ts.map +1 -1
- package/dist/commands/schema.js +60 -0
- package/dist/commands/schema.js.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/api-client.d.ts +7 -0
- package/dist/lib/api-client.d.ts.map +1 -1
- package/dist/lib/api-client.js +76 -9
- package/dist/lib/api-client.js.map +1 -1
- package/dist/lib/command-kit.d.ts.map +1 -1
- package/dist/lib/command-kit.js +20 -1
- package/dist/lib/command-kit.js.map +1 -1
- package/dist/lib/dry-run.d.ts +11 -0
- package/dist/lib/dry-run.d.ts.map +1 -1
- package/dist/lib/dry-run.js +90 -0
- package/dist/lib/dry-run.js.map +1 -1
- package/dist/lib/error-codes.d.ts +81 -0
- package/dist/lib/error-codes.d.ts.map +1 -0
- package/dist/lib/error-codes.js +166 -0
- package/dist/lib/error-codes.js.map +1 -0
- package/dist/lib/list-envelope.d.ts +67 -0
- package/dist/lib/list-envelope.d.ts.map +1 -0
- package/dist/lib/list-envelope.js +170 -0
- package/dist/lib/list-envelope.js.map +1 -0
- package/dist/lib/mcp-client-config.d.ts +57 -0
- package/dist/lib/mcp-client-config.d.ts.map +1 -0
- package/dist/lib/mcp-client-config.js +166 -0
- package/dist/lib/mcp-client-config.js.map +1 -0
- package/dist/lib/program-registry.d.ts +19 -0
- package/dist/lib/program-registry.d.ts.map +1 -0
- package/dist/lib/program-registry.js +17 -0
- package/dist/lib/program-registry.js.map +1 -0
- package/dist/lib/scope-diagnostic.d.ts +42 -0
- package/dist/lib/scope-diagnostic.d.ts.map +1 -0
- package/dist/lib/scope-diagnostic.js +104 -0
- package/dist/lib/scope-diagnostic.js.map +1 -0
- package/dist/lib/verb-manifest.d.ts +66 -0
- package/dist/lib/verb-manifest.d.ts.map +1 -0
- package/dist/lib/verb-manifest.js +104 -0
- package/dist/lib/verb-manifest.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.DEFAULT_MCP_PACKAGE = exports.SUPPORTED_CLIENTS = void 0;
|
|
37
|
+
exports.isSupportedClient = isSupportedClient;
|
|
38
|
+
exports.configPathForClient = configPathForClient;
|
|
39
|
+
exports.buildServerEntry = buildServerEntry;
|
|
40
|
+
exports.mergeIntoConfig = mergeIntoConfig;
|
|
41
|
+
exports.removeFromConfig = removeFromConfig;
|
|
42
|
+
exports.serializeConfig = serializeConfig;
|
|
43
|
+
/**
|
|
44
|
+
* MCP client config helpers (Sprint 1 T1.5).
|
|
45
|
+
*
|
|
46
|
+
* Write/update the client-side JSON that tells Claude Desktop / Cursor /
|
|
47
|
+
* Windsurf how to launch the Solid# MCP server. All pure — no fs here,
|
|
48
|
+
* no network. Callers in src/commands/mcp.ts handle I/O.
|
|
49
|
+
*
|
|
50
|
+
* Supported client shapes (as of 2026-04):
|
|
51
|
+
*
|
|
52
|
+
* Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json):
|
|
53
|
+
* {
|
|
54
|
+
* "mcpServers": {
|
|
55
|
+
* "solid": { "command": "npx", "args": ["@solidnumber/mcp"],
|
|
56
|
+
* "env": { "SOLID_API_KEY": "sk_..." } }
|
|
57
|
+
* }
|
|
58
|
+
* }
|
|
59
|
+
*
|
|
60
|
+
* Cursor (~/.cursor/mcp.json): same shape as Claude Desktop
|
|
61
|
+
*
|
|
62
|
+
* Windsurf (~/.codeium/windsurf/mcp_config.json): same shape
|
|
63
|
+
*/
|
|
64
|
+
const os = __importStar(require("os"));
|
|
65
|
+
const path = __importStar(require("path"));
|
|
66
|
+
exports.SUPPORTED_CLIENTS = ['claude', 'cursor', 'windsurf'];
|
|
67
|
+
/** Returns true if the string is a known supported client. */
|
|
68
|
+
function isSupportedClient(value) {
|
|
69
|
+
return !!value && exports.SUPPORTED_CLIENTS.includes(value);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Per-OS default path for each supported client. Returns the path
|
|
73
|
+
* relative to `homeDir` so callers can pass their own for testing.
|
|
74
|
+
*/
|
|
75
|
+
function configPathForClient(client, opts = {}) {
|
|
76
|
+
const platform = opts.platform ?? process.platform;
|
|
77
|
+
const home = opts.homeDir ?? os.homedir();
|
|
78
|
+
switch (client) {
|
|
79
|
+
case 'claude':
|
|
80
|
+
if (platform === 'darwin') {
|
|
81
|
+
return path.join(home, 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json');
|
|
82
|
+
}
|
|
83
|
+
if (platform === 'win32') {
|
|
84
|
+
// %APPDATA% → fall back to ~/AppData/Roaming when not set
|
|
85
|
+
const appdata = opts.platform === undefined ? process.env.APPDATA : undefined;
|
|
86
|
+
const base = appdata ?? path.join(home, 'AppData', 'Roaming');
|
|
87
|
+
return path.join(base, 'Claude', 'claude_desktop_config.json');
|
|
88
|
+
}
|
|
89
|
+
// Linux — Claude Desktop isn't officially supported there but keep
|
|
90
|
+
// a sane default so tests have something to assert.
|
|
91
|
+
return path.join(home, '.config', 'Claude', 'claude_desktop_config.json');
|
|
92
|
+
case 'cursor':
|
|
93
|
+
return path.join(home, '.cursor', 'mcp.json');
|
|
94
|
+
case 'windsurf':
|
|
95
|
+
if (platform === 'darwin' || platform === 'linux') {
|
|
96
|
+
return path.join(home, '.codeium', 'windsurf', 'mcp_config.json');
|
|
97
|
+
}
|
|
98
|
+
if (platform === 'win32') {
|
|
99
|
+
const appdata = opts.platform === undefined ? process.env.APPDATA : undefined;
|
|
100
|
+
const base = appdata ?? path.join(home, 'AppData', 'Roaming');
|
|
101
|
+
return path.join(base, 'Codeium', 'Windsurf', 'mcp_config.json');
|
|
102
|
+
}
|
|
103
|
+
return path.join(home, '.codeium', 'windsurf', 'mcp_config.json');
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/** Default package that ships the stdio MCP server. */
|
|
107
|
+
exports.DEFAULT_MCP_PACKAGE = '@solidnumber/mcp';
|
|
108
|
+
/**
|
|
109
|
+
* Build the `mcpServers.solid` entry. Pure — no I/O, no env reads.
|
|
110
|
+
*/
|
|
111
|
+
function buildServerEntry(input = {}) {
|
|
112
|
+
const env = {};
|
|
113
|
+
if (input.apiKey)
|
|
114
|
+
env.SOLID_API_KEY = input.apiKey;
|
|
115
|
+
if (input.apiUrl)
|
|
116
|
+
env.SOLID_API_URL = input.apiUrl;
|
|
117
|
+
if (input.companyId !== undefined && input.companyId !== null && input.companyId !== '') {
|
|
118
|
+
env.SOLID_COMPANY_ID = String(input.companyId);
|
|
119
|
+
}
|
|
120
|
+
if (input.extraEnv) {
|
|
121
|
+
for (const [k, v] of Object.entries(input.extraEnv)) {
|
|
122
|
+
if (typeof v === 'string' && v.length > 0)
|
|
123
|
+
env[k] = v;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
const entry = {
|
|
127
|
+
command: 'npx',
|
|
128
|
+
args: ['-y', input.packageName ?? exports.DEFAULT_MCP_PACKAGE],
|
|
129
|
+
};
|
|
130
|
+
if (Object.keys(env).length > 0)
|
|
131
|
+
entry.env = env;
|
|
132
|
+
return entry;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Merge a new `solid` server entry into an existing config file.
|
|
136
|
+
* Preserves any other mcpServers keys and any top-level keys we don't
|
|
137
|
+
* recognize. Returns a NEW object — input is not mutated.
|
|
138
|
+
*/
|
|
139
|
+
function mergeIntoConfig(existing, entry, serverKey = 'solid') {
|
|
140
|
+
const base = existing && typeof existing === 'object' ? { ...existing } : {};
|
|
141
|
+
const servers = { ...(base.mcpServers ?? {}) };
|
|
142
|
+
servers[serverKey] = entry;
|
|
143
|
+
base.mcpServers = servers;
|
|
144
|
+
return base;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Remove the `solid` entry from a config, preserving other keys.
|
|
148
|
+
* Returns the NEW config (unmutated input). When only `solid` existed
|
|
149
|
+
* in mcpServers, keeps an empty `mcpServers: {}` to be explicit.
|
|
150
|
+
*/
|
|
151
|
+
function removeFromConfig(existing, serverKey = 'solid') {
|
|
152
|
+
const base = existing && typeof existing === 'object' ? { ...existing } : {};
|
|
153
|
+
if (base.mcpServers && typeof base.mcpServers === 'object') {
|
|
154
|
+
const { [serverKey]: _, ...rest } = base.mcpServers;
|
|
155
|
+
base.mcpServers = rest;
|
|
156
|
+
}
|
|
157
|
+
return base;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Pretty-print a config with stable key order + 2-space indent. Writes
|
|
161
|
+
* this string is the caller's responsibility.
|
|
162
|
+
*/
|
|
163
|
+
function serializeConfig(cfg) {
|
|
164
|
+
return JSON.stringify(cfg, null, 2) + '\n';
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=mcp-client-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-client-config.js","sourceRoot":"","sources":["../../src/lib/mcp-client-config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* program-registry — lazy handle on the root Commander program so any
|
|
3
|
+
* command module can introspect the full verb tree without creating an
|
|
4
|
+
* import cycle with index.ts.
|
|
5
|
+
*
|
|
6
|
+
* Sprint 1 T1.3: `solid schema verbs --json` needs to walk every
|
|
7
|
+
* subcommand. Without this registry, schema.ts would have to import
|
|
8
|
+
* program from index.ts, which already imports schemaCommand from
|
|
9
|
+
* schema.ts — cycle.
|
|
10
|
+
*
|
|
11
|
+
* Pure module state: one writer (index.ts) + many readers (schema,
|
|
12
|
+
* doctor, etc.). No async, no I/O.
|
|
13
|
+
*/
|
|
14
|
+
import type { Command } from 'commander';
|
|
15
|
+
export declare function setProgram(p: Command): void;
|
|
16
|
+
export declare function getProgram(): Command | null;
|
|
17
|
+
/** Reset for tests. */
|
|
18
|
+
export declare function resetProgramForTest(): void;
|
|
19
|
+
//# sourceMappingURL=program-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"program-registry.d.ts","sourceRoot":"","sources":["../../src/lib/program-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIzC,wBAAgB,UAAU,CAAC,CAAC,EAAE,OAAO,GAAG,IAAI,CAE3C;AAED,wBAAgB,UAAU,IAAI,OAAO,GAAG,IAAI,CAE3C;AAED,uBAAuB;AACvB,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.setProgram = setProgram;
|
|
4
|
+
exports.getProgram = getProgram;
|
|
5
|
+
exports.resetProgramForTest = resetProgramForTest;
|
|
6
|
+
let _program = null;
|
|
7
|
+
function setProgram(p) {
|
|
8
|
+
_program = p;
|
|
9
|
+
}
|
|
10
|
+
function getProgram() {
|
|
11
|
+
return _program;
|
|
12
|
+
}
|
|
13
|
+
/** Reset for tests. */
|
|
14
|
+
function resetProgramForTest() {
|
|
15
|
+
_program = null;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=program-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"program-registry.js","sourceRoot":"","sources":["../../src/lib/program-registry.ts"],"names":[],"mappings":";;AAiBA,gCAEC;AAED,gCAEC;AAGD,kDAEC;AAbD,IAAI,QAAQ,GAAmB,IAAI,CAAC;AAEpC,SAAgB,UAAU,CAAC,CAAU;IACnC,QAAQ,GAAG,CAAC,CAAC;AACf,CAAC;AAED,SAAgB,UAAU;IACxB,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,uBAAuB;AACvB,SAAgB,mBAAmB;IACjC,QAAQ,GAAG,IAAI,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scope/feature-gap diagnostic (Sprint 1 T1.6).
|
|
3
|
+
*
|
|
4
|
+
* Compares the scopes currently granted on an API key against the scopes
|
|
5
|
+
* the tenant's enabled features *should* grant (per backend service
|
|
6
|
+
* services/scope_expansion.py, Sprint 0 T0.5). Surfaces mismatches so
|
|
7
|
+
* `solid doctor` can tell the operator: "your key is missing agents:read
|
|
8
|
+
* because your tenant enabled the agents feature after the key was
|
|
9
|
+
* issued — rotate the key and you'll pick up the new scopes."
|
|
10
|
+
*
|
|
11
|
+
* Pure — takes primitives, returns primitives. No HTTP, no fs. The
|
|
12
|
+
* backend has the same map in services/scope_expansion.py; this is a
|
|
13
|
+
* narrow client-side mirror so operators see drift without a round-trip.
|
|
14
|
+
* Kept small on purpose: if it diverges from the backend map, the only
|
|
15
|
+
* impact is a diagnostic miss — enforcement is still server-side.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Feature key → scopes it should grant on issuance.
|
|
19
|
+
* MUST stay in lock-step with solid-backend/services/scope_expansion.py
|
|
20
|
+
* FEATURE_TO_SCOPES. Keep small — every entry is a permission decision.
|
|
21
|
+
*/
|
|
22
|
+
export declare const FEATURE_TO_SCOPES: Readonly<Record<string, readonly string[]>>;
|
|
23
|
+
/**
|
|
24
|
+
* Given the key's current scopes and the tenant's feature flags, return
|
|
25
|
+
* a sorted list of scopes that SHOULD be granted but aren't.
|
|
26
|
+
*
|
|
27
|
+
* Pure — no I/O.
|
|
28
|
+
*/
|
|
29
|
+
export declare function computeScopeGap(currentScopes: readonly string[] | null | undefined, featureSettings: Record<string, unknown> | null | undefined, featureToScopes?: Readonly<Record<string, readonly string[]>>): string[];
|
|
30
|
+
export interface ScopeDiagnosticFinding {
|
|
31
|
+
severity: 'ok' | 'warn' | 'fail';
|
|
32
|
+
code: 'SCOPE_GAP' | 'NO_FEATURES' | 'NO_SCOPES' | 'ALL_GRANTED';
|
|
33
|
+
message: string;
|
|
34
|
+
missing_scopes: string[];
|
|
35
|
+
hint?: string;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Wrap computeScopeGap with a pre-canned diagnostic payload — the shape
|
|
39
|
+
* `solid doctor` surfaces to the operator. Pure.
|
|
40
|
+
*/
|
|
41
|
+
export declare function diagnoseScopeGap(currentScopes: readonly string[] | null | undefined, featureSettings: Record<string, unknown> | null | undefined): ScopeDiagnosticFinding;
|
|
42
|
+
//# sourceMappingURL=scope-diagnostic.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope-diagnostic.d.ts","sourceRoot":"","sources":["../../src/lib/scope-diagnostic.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAGzE,CAAC;AASF;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,aAAa,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,GAAG,SAAS,EACnD,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,EAC3D,eAAe,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAAqB,GAC/E,MAAM,EAAE,CAgBV;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;IACjC,IAAI,EAAE,WAAW,GAAG,aAAa,GAAG,WAAW,GAAG,aAAa,CAAC;IAChE,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,aAAa,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,GAAG,SAAS,EACnD,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,GAC1D,sBAAsB,CAkCxB"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Scope/feature-gap diagnostic (Sprint 1 T1.6).
|
|
4
|
+
*
|
|
5
|
+
* Compares the scopes currently granted on an API key against the scopes
|
|
6
|
+
* the tenant's enabled features *should* grant (per backend service
|
|
7
|
+
* services/scope_expansion.py, Sprint 0 T0.5). Surfaces mismatches so
|
|
8
|
+
* `solid doctor` can tell the operator: "your key is missing agents:read
|
|
9
|
+
* because your tenant enabled the agents feature after the key was
|
|
10
|
+
* issued — rotate the key and you'll pick up the new scopes."
|
|
11
|
+
*
|
|
12
|
+
* Pure — takes primitives, returns primitives. No HTTP, no fs. The
|
|
13
|
+
* backend has the same map in services/scope_expansion.py; this is a
|
|
14
|
+
* narrow client-side mirror so operators see drift without a round-trip.
|
|
15
|
+
* Kept small on purpose: if it diverges from the backend map, the only
|
|
16
|
+
* impact is a diagnostic miss — enforcement is still server-side.
|
|
17
|
+
*/
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.FEATURE_TO_SCOPES = void 0;
|
|
20
|
+
exports.computeScopeGap = computeScopeGap;
|
|
21
|
+
exports.diagnoseScopeGap = diagnoseScopeGap;
|
|
22
|
+
/**
|
|
23
|
+
* Feature key → scopes it should grant on issuance.
|
|
24
|
+
* MUST stay in lock-step with solid-backend/services/scope_expansion.py
|
|
25
|
+
* FEATURE_TO_SCOPES. Keep small — every entry is a permission decision.
|
|
26
|
+
*/
|
|
27
|
+
exports.FEATURE_TO_SCOPES = {
|
|
28
|
+
agents: ['agents:read', 'agents:write', 'agents:data', 'agents:converse'],
|
|
29
|
+
'ai-agents-platform': ['agents:read', 'agents:write', 'agents:data', 'agents:converse'],
|
|
30
|
+
};
|
|
31
|
+
function isTruthy(v) {
|
|
32
|
+
if (typeof v === 'boolean')
|
|
33
|
+
return v;
|
|
34
|
+
if (typeof v === 'number')
|
|
35
|
+
return v !== 0;
|
|
36
|
+
if (typeof v === 'string')
|
|
37
|
+
return /^(1|true|yes|on)$/i.test(v.trim());
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Given the key's current scopes and the tenant's feature flags, return
|
|
42
|
+
* a sorted list of scopes that SHOULD be granted but aren't.
|
|
43
|
+
*
|
|
44
|
+
* Pure — no I/O.
|
|
45
|
+
*/
|
|
46
|
+
function computeScopeGap(currentScopes, featureSettings, featureToScopes = exports.FEATURE_TO_SCOPES) {
|
|
47
|
+
const current = new Set(currentScopes ?? []);
|
|
48
|
+
const implied = new Set();
|
|
49
|
+
if (featureSettings) {
|
|
50
|
+
for (const [feature, scopes] of Object.entries(featureToScopes)) {
|
|
51
|
+
if (isTruthy(featureSettings[feature])) {
|
|
52
|
+
for (const s of scopes)
|
|
53
|
+
implied.add(s);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const gap = [];
|
|
58
|
+
for (const s of implied) {
|
|
59
|
+
if (!current.has(s))
|
|
60
|
+
gap.push(s);
|
|
61
|
+
}
|
|
62
|
+
gap.sort();
|
|
63
|
+
return gap;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Wrap computeScopeGap with a pre-canned diagnostic payload — the shape
|
|
67
|
+
* `solid doctor` surfaces to the operator. Pure.
|
|
68
|
+
*/
|
|
69
|
+
function diagnoseScopeGap(currentScopes, featureSettings) {
|
|
70
|
+
if (!featureSettings || Object.keys(featureSettings).length === 0) {
|
|
71
|
+
return {
|
|
72
|
+
severity: 'warn',
|
|
73
|
+
code: 'NO_FEATURES',
|
|
74
|
+
message: 'Tenant feature flags not available; cannot check scope gap.',
|
|
75
|
+
missing_scopes: [],
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
const gap = computeScopeGap(currentScopes, featureSettings);
|
|
79
|
+
if (gap.length === 0) {
|
|
80
|
+
return {
|
|
81
|
+
severity: 'ok',
|
|
82
|
+
code: 'ALL_GRANTED',
|
|
83
|
+
message: 'Key scopes match tenant features.',
|
|
84
|
+
missing_scopes: [],
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
if (!currentScopes || currentScopes.length === 0) {
|
|
88
|
+
return {
|
|
89
|
+
severity: 'fail',
|
|
90
|
+
code: 'NO_SCOPES',
|
|
91
|
+
message: 'Current API key has no scopes — every tenant feature is under-privileged.',
|
|
92
|
+
missing_scopes: gap,
|
|
93
|
+
hint: 'Rotate with: solid keys rotate --scopes "' + gap.join(',') + '"',
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
severity: 'fail',
|
|
98
|
+
code: 'SCOPE_GAP',
|
|
99
|
+
message: `API key is missing ${gap.length} scope(s) that tenant features imply.`,
|
|
100
|
+
missing_scopes: gap,
|
|
101
|
+
hint: 'Rotate with: solid keys rotate --add-scope ' + gap.join(' --add-scope '),
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=scope-diagnostic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope-diagnostic.js","sourceRoot":"","sources":["../../src/lib/scope-diagnostic.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;GAeG;;;AAyBH,0CAoBC;AAcD,4CAqCC;AA9FD;;;;GAIG;AACU,QAAA,iBAAiB,GAAgD;IAC5E,MAAM,EAAE,CAAC,aAAa,EAAE,cAAc,EAAE,aAAa,EAAE,iBAAiB,CAAC;IACzE,oBAAoB,EAAE,CAAC,aAAa,EAAE,cAAc,EAAE,aAAa,EAAE,iBAAiB,CAAC;CACxF,CAAC;AAEF,SAAS,QAAQ,CAAC,CAAU;IAC1B,IAAI,OAAO,CAAC,KAAK,SAAS;QAAE,OAAO,CAAC,CAAC;IACrC,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IAC1C,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IACtE,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;GAKG;AACH,SAAgB,eAAe,CAC7B,aAAmD,EACnD,eAA2D,EAC3D,kBAA+D,yBAAiB;IAEhF,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC;IAC7C,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,IAAI,eAAe,EAAE,CAAC;QACpB,KAAK,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,EAAE,CAAC;YAChE,IAAI,QAAQ,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;gBACvC,KAAK,MAAM,CAAC,IAAI,MAAM;oBAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YACzC,CAAC;QACH,CAAC;IACH,CAAC;IACD,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;YAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACnC,CAAC;IACD,GAAG,CAAC,IAAI,EAAE,CAAC;IACX,OAAO,GAAG,CAAC;AACb,CAAC;AAUD;;;GAGG;AACH,SAAgB,gBAAgB,CAC9B,aAAmD,EACnD,eAA2D;IAE3D,IAAI,CAAC,eAAe,IAAI,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClE,OAAO;YACL,QAAQ,EAAE,MAAM;YAChB,IAAI,EAAE,aAAa;YACnB,OAAO,EAAE,6DAA6D;YACtE,cAAc,EAAE,EAAE;SACnB,CAAC;IACJ,CAAC;IACD,MAAM,GAAG,GAAG,eAAe,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC;IAC5D,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO;YACL,QAAQ,EAAE,IAAI;YACd,IAAI,EAAE,aAAa;YACnB,OAAO,EAAE,mCAAmC;YAC5C,cAAc,EAAE,EAAE;SACnB,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,aAAa,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjD,OAAO;YACL,QAAQ,EAAE,MAAM;YAChB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,2EAA2E;YACpF,cAAc,EAAE,GAAG;YACnB,IAAI,EAAE,2CAA2C,GAAG,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG;SACxE,CAAC;IACJ,CAAC;IACD,OAAO;QACL,QAAQ,EAAE,MAAM;QAChB,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,sBAAsB,GAAG,CAAC,MAAM,uCAAuC;QAChF,cAAc,EAAE,GAAG;QACnB,IAAI,EAAE,6CAA6C,GAAG,GAAG,CAAC,IAAI,CAAC,eAAe,CAAC;KAChF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure verb-manifest walker.
|
|
3
|
+
*
|
|
4
|
+
* Walks a Commander tree and emits a flat list of {path, description,
|
|
5
|
+
* options, args, subcommands} entries. Used by `solid schema verbs
|
|
6
|
+
* --json` so agents (Claude Code, Cursor) can discover every verb the
|
|
7
|
+
* CLI exposes without scraping --help.
|
|
8
|
+
*
|
|
9
|
+
* No I/O, no commander parsing — just tree traversal + field
|
|
10
|
+
* extraction. Unit-tested in src/__tests__/verb-manifest.test.ts.
|
|
11
|
+
*/
|
|
12
|
+
import type { Command } from 'commander';
|
|
13
|
+
export interface VerbOption {
|
|
14
|
+
flags: string;
|
|
15
|
+
description: string;
|
|
16
|
+
required: boolean;
|
|
17
|
+
default?: unknown;
|
|
18
|
+
}
|
|
19
|
+
export interface VerbArg {
|
|
20
|
+
name: string;
|
|
21
|
+
required: boolean;
|
|
22
|
+
description?: string;
|
|
23
|
+
variadic?: boolean;
|
|
24
|
+
}
|
|
25
|
+
export interface VerbEntry {
|
|
26
|
+
/** Short name — e.g. "pages". */
|
|
27
|
+
verb: string;
|
|
28
|
+
/** Full invocation path — e.g. "solid schema pages". */
|
|
29
|
+
path: string;
|
|
30
|
+
/** One-line description from .description(). */
|
|
31
|
+
description: string;
|
|
32
|
+
/** How deep in the tree (0 = root children, 1 = grandchildren, ...). */
|
|
33
|
+
depth: number;
|
|
34
|
+
/** Options on this command (NOT inherited). */
|
|
35
|
+
options: VerbOption[];
|
|
36
|
+
/** Positional args declared on this command. */
|
|
37
|
+
args: VerbArg[];
|
|
38
|
+
/** Subcommand names (not full paths). */
|
|
39
|
+
subcommands: string[];
|
|
40
|
+
/** True when this command has no subcommands and can be invoked directly. */
|
|
41
|
+
is_leaf: boolean;
|
|
42
|
+
}
|
|
43
|
+
export interface WalkOptions {
|
|
44
|
+
/** Prefix prepended to every path. Defaults to "solid". */
|
|
45
|
+
prefix?: string;
|
|
46
|
+
/** Skip the root cmd itself — emit only its descendants. Default true. */
|
|
47
|
+
skipRoot?: boolean;
|
|
48
|
+
/** Include hidden commands (commander hides some with .hidden()). Default false. */
|
|
49
|
+
includeHidden?: boolean;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Recursively walk a Commander tree and return a flat manifest.
|
|
53
|
+
*
|
|
54
|
+
* Pure — depends only on properties accessible through Commander's public
|
|
55
|
+
* surface plus tolerant fallbacks for its internal fields.
|
|
56
|
+
*/
|
|
57
|
+
export declare function walkVerbs(root: Command, opts?: WalkOptions): VerbEntry[];
|
|
58
|
+
/** Build the wire payload for `solid schema verbs --json`. */
|
|
59
|
+
export interface VerbManifest {
|
|
60
|
+
version: '1.0';
|
|
61
|
+
cli_version: string;
|
|
62
|
+
count: number;
|
|
63
|
+
verbs: VerbEntry[];
|
|
64
|
+
}
|
|
65
|
+
export declare function buildVerbManifest(root: Command, cliVersion: string, opts?: WalkOptions): VerbManifest;
|
|
66
|
+
//# sourceMappingURL=verb-manifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verb-manifest.d.ts","sourceRoot":"","sources":["../../src/lib/verb-manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,SAAS;IACxB,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAC;IACb,gDAAgD;IAChD,WAAW,EAAE,MAAM,CAAC;IACpB,wEAAwE;IACxE,KAAK,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,gDAAgD;IAChD,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,yCAAyC;IACzC,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,6EAA6E;IAC7E,OAAO,EAAE,OAAO,CAAC;CAClB;AAwDD,MAAM,WAAW,WAAW;IAC1B,2DAA2D;IAC3D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,oFAAoF;IACpF,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,GAAE,WAAgB,GAAG,SAAS,EAAE,CAgD5E;AAED,8DAA8D;AAC9D,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,KAAK,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,SAAS,EAAE,CAAC;CACpB;AAED,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,OAAO,EACb,UAAU,EAAE,MAAM,EAClB,IAAI,CAAC,EAAE,WAAW,GACjB,YAAY,CAQd"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.walkVerbs = walkVerbs;
|
|
4
|
+
exports.buildVerbManifest = buildVerbManifest;
|
|
5
|
+
/** Safely extract option metadata, tolerant of both commander v7 and v10 shapes. */
|
|
6
|
+
function toOption(o) {
|
|
7
|
+
const entry = {
|
|
8
|
+
flags: o.flags ?? '',
|
|
9
|
+
description: o.description ?? '',
|
|
10
|
+
required: Boolean(o.required ?? o.mandatory ?? false),
|
|
11
|
+
};
|
|
12
|
+
if (o.defaultValue !== undefined) {
|
|
13
|
+
entry.default = o.defaultValue;
|
|
14
|
+
}
|
|
15
|
+
return entry;
|
|
16
|
+
}
|
|
17
|
+
/** Safely extract arg metadata from commander's Argument class. */
|
|
18
|
+
function toArg(a) {
|
|
19
|
+
// commander v7 stores args as { _name, required, description, variadic }
|
|
20
|
+
// commander v10 Argument class has a .name() method
|
|
21
|
+
let name = '';
|
|
22
|
+
if (typeof a.name === 'function') {
|
|
23
|
+
try {
|
|
24
|
+
name = a.name();
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
name = '';
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
else if (typeof a.name === 'string') {
|
|
31
|
+
name = a.name;
|
|
32
|
+
}
|
|
33
|
+
else if (a._name) {
|
|
34
|
+
name = a._name;
|
|
35
|
+
}
|
|
36
|
+
const entry = {
|
|
37
|
+
name,
|
|
38
|
+
required: Boolean(a.required ?? false),
|
|
39
|
+
};
|
|
40
|
+
if (a.description)
|
|
41
|
+
entry.description = a.description;
|
|
42
|
+
if (a.variadic)
|
|
43
|
+
entry.variadic = true;
|
|
44
|
+
return entry;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Recursively walk a Commander tree and return a flat manifest.
|
|
48
|
+
*
|
|
49
|
+
* Pure — depends only on properties accessible through Commander's public
|
|
50
|
+
* surface plus tolerant fallbacks for its internal fields.
|
|
51
|
+
*/
|
|
52
|
+
function walkVerbs(root, opts = {}) {
|
|
53
|
+
const prefix = opts.prefix ?? 'solid';
|
|
54
|
+
const skipRoot = opts.skipRoot ?? true;
|
|
55
|
+
const includeHidden = opts.includeHidden ?? false;
|
|
56
|
+
const out = [];
|
|
57
|
+
function visit(cmd, pathPrefix, depth) {
|
|
58
|
+
// commander exposes _hidden (v7) or cmd._hidden — tolerant access.
|
|
59
|
+
const hidden = Boolean(cmd._hidden);
|
|
60
|
+
if (hidden && !includeHidden)
|
|
61
|
+
return;
|
|
62
|
+
const name = cmd.name();
|
|
63
|
+
const thisPath = pathPrefix ? `${pathPrefix} ${name}` : name;
|
|
64
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
65
|
+
const rawArgs = cmd._args ?? cmd.registeredArguments ?? [];
|
|
66
|
+
const options = (cmd.options || []).map(toOption);
|
|
67
|
+
const args = rawArgs.map(toArg);
|
|
68
|
+
const subcommands = (cmd.commands || []).map((sc) => sc.name());
|
|
69
|
+
out.push({
|
|
70
|
+
verb: name,
|
|
71
|
+
path: thisPath,
|
|
72
|
+
description: cmd.description() || '',
|
|
73
|
+
depth,
|
|
74
|
+
options,
|
|
75
|
+
args,
|
|
76
|
+
subcommands,
|
|
77
|
+
is_leaf: subcommands.length === 0,
|
|
78
|
+
});
|
|
79
|
+
for (const sc of cmd.commands || []) {
|
|
80
|
+
visit(sc, thisPath, depth + 1);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (skipRoot) {
|
|
84
|
+
// Emit the root's children only — typical for a CLI where the root IS
|
|
85
|
+
// the program name and has no verb of its own.
|
|
86
|
+
for (const sc of root.commands || []) {
|
|
87
|
+
visit(sc, prefix, 0);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
visit(root, '', 0);
|
|
92
|
+
}
|
|
93
|
+
return out;
|
|
94
|
+
}
|
|
95
|
+
function buildVerbManifest(root, cliVersion, opts) {
|
|
96
|
+
const verbs = walkVerbs(root, opts);
|
|
97
|
+
return {
|
|
98
|
+
version: '1.0',
|
|
99
|
+
cli_version: cliVersion,
|
|
100
|
+
count: verbs.length,
|
|
101
|
+
verbs,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=verb-manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verb-manifest.js","sourceRoot":"","sources":["../../src/lib/verb-manifest.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solidnumber/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.0",
|
|
4
4
|
"description": "AI business infrastructure from the terminal — CRM, payments, voice AI, 116 agents, 52 industry templates. solid clone plumber → instant business. Also: programmatic TS SDK via @solidnumber/cli/sdk.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|