@tankpkg/cli 0.4.2 → 0.6.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.
@@ -0,0 +1,181 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import crypto from 'node:crypto';
4
+ import { extract } from 'tar';
5
+ import { logger } from './logger.js';
6
+ import { buildSkillKey } from './dependency-resolver.js';
7
+ export async function downloadAllParallel(nodes, spinner) {
8
+ const results = new Map();
9
+ const CONCURRENCY_LIMIT = 8;
10
+ for (let i = 0; i < nodes.length; i += CONCURRENCY_LIMIT) {
11
+ const batch = nodes.slice(i, i + CONCURRENCY_LIMIT);
12
+ const promises = batch.map(async (node) => {
13
+ spinner.text = `Downloading ${node.name}@${node.version}...`;
14
+ let res;
15
+ try {
16
+ res = await fetch(node.meta.downloadUrl);
17
+ }
18
+ catch (err) {
19
+ throw new Error(`Network error downloading tarball for ${node.name}@${node.version}: ${err instanceof Error ? err.message : String(err)}`);
20
+ }
21
+ if (!res.ok) {
22
+ throw new Error(`Failed to download ${node.name}@${node.version}: ${res.status} ${res.statusText}`);
23
+ }
24
+ const buffer = Buffer.from(await res.arrayBuffer());
25
+ const hash = crypto.createHash('sha512').update(buffer).digest('base64');
26
+ const computedIntegrity = `sha512-${hash}`;
27
+ if (computedIntegrity !== node.meta.integrity) {
28
+ throw new Error(`Integrity mismatch for ${node.name}@${node.version}. Expected: ${node.meta.integrity}, Got: ${computedIntegrity}`);
29
+ }
30
+ return { name: node.name, buffer, integrity: computedIntegrity };
31
+ });
32
+ const batchResults = await Promise.all(promises);
33
+ for (const result of batchResults) {
34
+ results.set(result.name, { buffer: result.buffer, integrity: result.integrity });
35
+ }
36
+ }
37
+ return results;
38
+ }
39
+ export function verifyExtractedDependencies(extractDir, node) {
40
+ const extractedManifestPath = path.join(extractDir, 'skills.json');
41
+ if (!fs.existsSync(extractedManifestPath)) {
42
+ return;
43
+ }
44
+ try {
45
+ const raw = fs.readFileSync(extractedManifestPath, 'utf-8');
46
+ const manifest = JSON.parse(raw);
47
+ const extractedDeps = (manifest.skills ?? {});
48
+ const apiDeps = node.meta.dependencies;
49
+ const extractedSorted = Object.fromEntries(Object.entries(extractedDeps).sort(([a], [b]) => a.localeCompare(b)));
50
+ const apiSorted = Object.fromEntries(Object.entries(apiDeps).sort(([a], [b]) => a.localeCompare(b)));
51
+ if (JSON.stringify(extractedSorted) !== JSON.stringify(apiSorted)) {
52
+ logger.warn(`Dependency mismatch for ${node.name}@${node.version}: manifest deps differ from registry`);
53
+ }
54
+ }
55
+ catch {
56
+ // Non-fatal.
57
+ }
58
+ }
59
+ export function readExtractedDependencies(extractDir) {
60
+ const extractedManifestPath = path.join(extractDir, 'skills.json');
61
+ if (!fs.existsSync(extractedManifestPath)) {
62
+ return {};
63
+ }
64
+ try {
65
+ const raw = fs.readFileSync(extractedManifestPath, 'utf-8');
66
+ const manifest = JSON.parse(raw);
67
+ const extractedDeps = manifest.skills;
68
+ if (!extractedDeps || typeof extractedDeps !== 'object') {
69
+ return {};
70
+ }
71
+ const deps = {};
72
+ for (const [depName, depRange] of Object.entries(extractedDeps)) {
73
+ if (typeof depRange === 'string') {
74
+ deps[depName] = depRange;
75
+ }
76
+ }
77
+ return deps;
78
+ }
79
+ catch {
80
+ return {};
81
+ }
82
+ }
83
+ export function writeLockfileWithResolvedGraph(lock, nodes, downloaded) {
84
+ for (const node of nodes) {
85
+ const key = buildSkillKey(node.name, node.version);
86
+ if (!downloaded.has(node.name) && lock.skills[key]) {
87
+ continue;
88
+ }
89
+ const integrity = downloaded.get(node.name)?.integrity
90
+ ?? lock.skills[key]?.integrity
91
+ ?? node.meta.integrity;
92
+ lock.skills[key] = {
93
+ resolved: node.meta.downloadUrl,
94
+ integrity,
95
+ permissions: node.meta.permissions,
96
+ audit_score: node.meta.auditScore ?? null,
97
+ dependencies: node.dependencies,
98
+ };
99
+ }
100
+ const sortedSkills = {};
101
+ for (const key of Object.keys(lock.skills).sort()) {
102
+ sortedSkills[key] = lock.skills[key];
103
+ }
104
+ lock.skills = sortedSkills;
105
+ return lock;
106
+ }
107
+ /**
108
+ * Extract a tarball safely with security checks.
109
+ * Rejects: absolute paths, path traversal (..), symlinks/hardlinks.
110
+ */
111
+ export async function extractSafely(tarball, destDir) {
112
+ const tmpTarball = path.join(destDir, '.tmp-tarball.tgz');
113
+ fs.writeFileSync(tmpTarball, tarball);
114
+ try {
115
+ await extract({
116
+ file: tmpTarball,
117
+ cwd: destDir,
118
+ filter: (entryPath) => {
119
+ if (path.isAbsolute(entryPath)) {
120
+ throw new Error(`Absolute path in tarball: ${entryPath}`);
121
+ }
122
+ if (entryPath.split('/').includes('..') || entryPath.split(path.sep).includes('..')) {
123
+ throw new Error(`Path traversal in tarball: ${entryPath}`);
124
+ }
125
+ return true;
126
+ },
127
+ onReadEntry: (entry) => {
128
+ if (entry.type === 'SymbolicLink' || entry.type === 'Link') {
129
+ throw new Error(`Symlink/hardlink in tarball: ${entry.path}`);
130
+ }
131
+ },
132
+ });
133
+ }
134
+ finally {
135
+ if (fs.existsSync(tmpTarball)) {
136
+ fs.unlinkSync(tmpTarball);
137
+ }
138
+ }
139
+ }
140
+ export function getExtractDir(projectDir, skillName) {
141
+ if (skillName.startsWith('@')) {
142
+ const [scope, name] = skillName.split('/');
143
+ return path.join(projectDir, '.tank', 'skills', scope, name);
144
+ }
145
+ return path.join(projectDir, '.tank', 'skills', skillName);
146
+ }
147
+ export function getGlobalExtractDir(homedir, skillName) {
148
+ const globalDir = path.join(homedir, '.tank', 'skills');
149
+ if (skillName.startsWith('@')) {
150
+ const [scope, name] = skillName.split('/');
151
+ return path.join(globalDir, scope, name);
152
+ }
153
+ return path.join(globalDir, skillName);
154
+ }
155
+ export function parseLockKey(key) {
156
+ const lastAt = key.lastIndexOf('@');
157
+ if (lastAt <= 0) {
158
+ throw new Error(`Invalid lockfile key: ${key}`);
159
+ }
160
+ return key.slice(0, lastAt);
161
+ }
162
+ export function parseVersionFromLockKey(key) {
163
+ const lastAt = key.lastIndexOf('@');
164
+ if (lastAt <= 0 || lastAt === key.length - 1) {
165
+ throw new Error(`Invalid lockfile key: ${key}`);
166
+ }
167
+ return key.slice(lastAt + 1);
168
+ }
169
+ export function getResolvedNodesInOrder(nodes, installOrder) {
170
+ const orderedNodes = [];
171
+ for (const key of installOrder) {
172
+ const skillName = parseLockKey(key);
173
+ const node = nodes.get(skillName);
174
+ if (!node) {
175
+ throw new Error(`Internal error: missing resolved node for ${key}`);
176
+ }
177
+ orderedNodes.push(node);
178
+ }
179
+ return orderedNodes;
180
+ }
181
+ //# sourceMappingURL=install-pipeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install-pipeline.js","sourceRoot":"","sources":["../../src/lib/install-pipeline.ts"],"names":[],"mappings":"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"}
@@ -19,3 +19,23 @@ export interface PackResult {
19
19
  * - Tarball size <= 50MB
20
20
  */
21
21
  export declare function pack(directory: string): Promise<PackResult>;
22
+ /**
23
+ * Pack a directory into a .tgz tarball for security scanning.
24
+ *
25
+ * Unlike pack(), this function does NOT require skills.json or SKILL.md.
26
+ * It applies the same security checks (no symlinks, no path traversal, etc.)
27
+ * and returns the same PackResult interface.
28
+ *
29
+ * Validates:
30
+ * - Directory exists
31
+ * - No symlinks or hardlinks
32
+ * - No path traversal (.. components)
33
+ * - No absolute paths
34
+ * - File count <= 1000
35
+ * - Tarball size <= 50MB
36
+ *
37
+ * Does NOT validate:
38
+ * - skills.json existence or validity
39
+ * - SKILL.md existence (but reads it if present)
40
+ */
41
+ export declare function packForScan(directory: string): Promise<PackResult>;
@@ -116,6 +116,80 @@ export async function pack(directory) {
116
116
  files,
117
117
  };
118
118
  }
119
+ /**
120
+ * Pack a directory into a .tgz tarball for security scanning.
121
+ *
122
+ * Unlike pack(), this function does NOT require skills.json or SKILL.md.
123
+ * It applies the same security checks (no symlinks, no path traversal, etc.)
124
+ * and returns the same PackResult interface.
125
+ *
126
+ * Validates:
127
+ * - Directory exists
128
+ * - No symlinks or hardlinks
129
+ * - No path traversal (.. components)
130
+ * - No absolute paths
131
+ * - File count <= 1000
132
+ * - Tarball size <= 50MB
133
+ *
134
+ * Does NOT validate:
135
+ * - skills.json existence or validity
136
+ * - SKILL.md existence (but reads it if present)
137
+ */
138
+ export async function packForScan(directory) {
139
+ const absDir = path.resolve(directory);
140
+ // 1. Verify directory exists
141
+ if (!fs.existsSync(absDir)) {
142
+ throw new Error(`Directory does not exist: ${absDir}`);
143
+ }
144
+ const stat = fs.statSync(absDir);
145
+ if (!stat.isDirectory()) {
146
+ throw new Error(`Not a directory: ${absDir}`);
147
+ }
148
+ // 2. Try to read SKILL.md if it exists (optional for scan)
149
+ let readmeContent = '';
150
+ const skillMdPath = path.join(absDir, 'SKILL.md');
151
+ if (fs.existsSync(skillMdPath)) {
152
+ try {
153
+ readmeContent = fs.readFileSync(skillMdPath, 'utf-8');
154
+ }
155
+ catch {
156
+ // If we can't read it, just use empty string
157
+ readmeContent = '';
158
+ }
159
+ }
160
+ // 3. Build ignore filter
161
+ const ig = buildIgnoreFilter(absDir);
162
+ // 4. Collect files with validation
163
+ const files = collectFiles(absDir, absDir, ig);
164
+ // 5. Enforce file count limit
165
+ if (files.length > MAX_FILE_COUNT) {
166
+ throw new Error(`Too many files: ${files.length} exceeds maximum of ${MAX_FILE_COUNT}`);
167
+ }
168
+ // 6. Calculate total size of source files
169
+ let totalSize = 0;
170
+ for (const file of files) {
171
+ const filePath = path.join(absDir, file);
172
+ const fileStat = fs.statSync(filePath);
173
+ totalSize += fileStat.size;
174
+ }
175
+ // 7. Create tarball
176
+ const tarball = await createTarball(absDir, files);
177
+ // 8. Enforce tarball size limit
178
+ if (tarball.length > MAX_PACKAGE_SIZE) {
179
+ throw new Error(`Tarball too large: ${tarball.length} bytes exceeds maximum of ${MAX_PACKAGE_SIZE} bytes (50MB)`);
180
+ }
181
+ // 9. Compute integrity hash
182
+ const hash = crypto.createHash('sha512').update(tarball).digest('base64');
183
+ const integrity = `sha512-${hash}`;
184
+ return {
185
+ tarball,
186
+ integrity,
187
+ fileCount: files.length,
188
+ totalSize,
189
+ readme: readmeContent,
190
+ files,
191
+ };
192
+ }
119
193
  /**
120
194
  * Build an ignore filter from .tankignore, .gitignore, or defaults.
121
195
  */
@@ -1 +1 @@
1
- {"version":3,"file":"packer.js","sourceRoot":"","sources":["../../src/lib/packer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,MAAM,MAAM,aAAa,CAAC;AAEjC,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEhD,SAAS;AACT,MAAM,gBAAgB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO;AAClD,MAAM,cAAc,GAAG,IAAI,CAAC;AAE5B,0EAA0E;AAC1E,MAAM,eAAe,GAAG;IACtB,cAAc;IACd,MAAM;IACN,OAAO;IACP,OAAO;IACP,OAAO;IACP,WAAW;CACZ,CAAC;AAEF,oDAAoD;AACpD,MAAM,cAAc,GAAG;IACrB,cAAc;IACd,MAAM;CACP,CAAC;AAEF,8CAA8C;AAC9C,MAAM,YAAY,GAAG,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC;AAWnD;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,SAAiB;IAC1C,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEvC,6BAA6B;IAC7B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,6BAA6B,MAAM,EAAE,CAAC,CAAC;IACzD,CAAC;IAED,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACjC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,oBAAoB,MAAM,EAAE,CAAC,CAAC;IAChD,CAAC;IAED,4CAA4C;IAC5C,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACxD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACxD,CAAC;IAED,IAAI,iBAAyB,CAAC;IAC9B,IAAI,CAAC;QACH,iBAAiB,GAAG,EAAE,CAAC,YAAY,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;IAC/D,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAChD,CAAC;IAED,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;IACzC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACzD,CAAC;IAED,MAAM,UAAU,GAAG,gBAAgB,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IACtD,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;QACxB,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,MAAM;aACnC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC;aACnD,IAAI,CAAC,IAAI,CAAC,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,yBAAyB,MAAM,EAAE,CAAC,CAAC;IACrD,CAAC;IAED,iDAAiD;IACjD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAClD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;IACrD,CAAC;IAED,IAAI,aAAqB,CAAC;IAC1B,IAAI,CAAC;QACH,aAAa,GAAG,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC7C,CAAC;IAED,yBAAyB;IACzB,MAAM,EAAE,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAErC,mCAAmC;IACnC,MAAM,KAAK,GAAG,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;IAE/C,8BAA8B;IAC9B,IAAI,KAAK,CAAC,MAAM,GAAG,cAAc,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CACb,mBAAmB,KAAK,CAAC,MAAM,uBAAuB,cAAc,EAAE,CACvE,CAAC;IACJ,CAAC;IAED,0CAA0C;IAC1C,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACzC,MAAM,QAAQ,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACvC,SAAS,IAAI,QAAQ,CAAC,IAAI,CAAC;IAC7B,CAAC;IAED,oBAAoB;IACpB,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAEnD,gCAAgC;IAChC,IAAI,OAAO,CAAC,MAAM,GAAG,gBAAgB,EAAE,CAAC;QACtC,MAAM,IAAI,KAAK,CACb,sBAAsB,OAAO,CAAC,MAAM,6BAA6B,gBAAgB,eAAe,CACjG,CAAC;IACJ,CAAC;IAED,6BAA6B;IAC7B,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC1E,MAAM,SAAS,GAAG,UAAU,IAAI,EAAE,CAAC;IAEnC,OAAO;QACL,OAAO;QACP,SAAS;QACT,SAAS,EAAE,KAAK,CAAC,MAAM;QACvB,SAAS;QACT,MAAM,EAAE,aAAa;QACrB,KAAK;KACN,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,iBAAiB,CAAC,GAAW;IACpC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC;IAEpB,gCAAgC;IAChC,EAAE,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAEvB,8DAA8D;IAC9D,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;IACrD,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IAEnD,IAAI,EAAE,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;QAClC,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;QACzD,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAChB,0CAA0C;QAC1C,EAAE,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IACvB,CAAC;SAAM,IAAI,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QACxC,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;QACxD,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAChB,EAAE,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IACvB,CAAC;SAAM,CAAC;QACN,EAAE,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAC1B,CAAC;IAED,OAAO,EAAE,CAAC;AACZ,CAAC;AAED;;GAEG;AACH,SAAS,YAAY,CACnB,OAAe,EACf,UAAkB,EAClB,EAA6B;IAE7B,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,UAAU,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAEpE,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QACnD,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QAEtD,qCAAqC;QACrC,IAAI,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YAChD,MAAM,IAAI,KAAK,CACb,6BAA6B,YAAY,2BAA2B,CACrE,CAAC;QACJ,CAAC;QAED,qCAAqC;QACrC,IAAI,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,4BAA4B,YAAY,GAAG,CAAC,CAAC;QAC/D,CAAC;QAED,6EAA6E;QAC7E,MAAM,WAAW,GAAG,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAC3C,IAAI,WAAW,CAAC,cAAc,EAAE,EAAE,CAAC;YACjC,MAAM,IAAI,KAAK,CACb,sBAAsB,YAAY,gDAAgD,CACnF,CAAC;QACJ,CAAC;QAED,uCAAuC;QACvC,4EAA4E;QAC5E,MAAM,aAAa,GAAG,WAAW,CAAC,WAAW,EAAE;YAC7C,CAAC,CAAC,YAAY,GAAG,GAAG;YACpB,CAAC,CAAC,YAAY,CAAC;QAEjB,IAAI,EAAE,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,CAAC;YAC9B,SAAS;QACX,CAAC;QAED,IAAI,WAAW,CAAC,WAAW,EAAE,EAAE,CAAC;YAC9B,4BAA4B;YAC5B,MAAM,QAAQ,GAAG,YAAY,CAAC,OAAO,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC;YACrD,KAAK,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC;QAC1B,CAAC;aAAM,IAAI,WAAW,CAAC,MAAM,EAAE,EAAE,CAAC;YAChC,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC3B,CAAC;QACD,sEAAsE;IACxE,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,aAAa,CAC1B,GAAW,EACX,KAAe;IAEf,OAAO,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC7C,MAAM,MAAM,GAAa,EAAE,CAAC;QAE5B,sDAAsD;QACtD,MAAM,MAAM,GAAG,MAAM,CACnB;YACE,IAAI,EAAE,IAAI;YACV,GAAG;YACH,QAAQ,EAAE,IAAI,EAAE,gCAAgC;SACjD,EACD,KAAK,CACiB,CAAC;QAEzB,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;YAClC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;YACpB,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAU,EAAE,EAAE;YAChC,MAAM,CAAC,GAAG,CAAC,CAAC;QACd,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"packer.js","sourceRoot":"","sources":["../../src/lib/packer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { Permissions } from '@tank/shared';
2
+ /**
3
+ * Check if a skill's permissions fit within the project's permission budget.
4
+ * Throws if any permission exceeds the budget.
5
+ */
6
+ export declare function checkPermissionBudget(budget: Permissions, skillPerms: Permissions | undefined, skillName: string): void;
7
+ /**
8
+ * Check if a domain is allowed by the budget's domain list.
9
+ * Supports wildcard matching: *.example.com matches sub.example.com
10
+ */
11
+ export declare function isDomainAllowed(domain: string, allowedDomains: string[]): boolean;
12
+ /**
13
+ * Check if a path is allowed by the budget's path list.
14
+ * Simple subset check: skill path must match one of the budget paths.
15
+ */
16
+ export declare function isPathAllowed(requestedPath: string, allowedPaths: string[]): boolean;
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Check if a skill's permissions fit within the project's permission budget.
3
+ * Throws if any permission exceeds the budget.
4
+ */
5
+ export function checkPermissionBudget(budget, skillPerms, skillName) {
6
+ if (!skillPerms)
7
+ return;
8
+ // Check subprocess
9
+ if (skillPerms.subprocess === true && budget.subprocess !== true) {
10
+ throw new Error(`Permission denied: ${skillName} requires subprocess access, but project budget does not allow it`);
11
+ }
12
+ // Check network outbound
13
+ if (skillPerms.network?.outbound && skillPerms.network.outbound.length > 0) {
14
+ const budgetDomains = budget.network?.outbound ?? [];
15
+ for (const domain of skillPerms.network.outbound) {
16
+ if (!isDomainAllowed(domain, budgetDomains)) {
17
+ throw new Error(`Permission denied: ${skillName} requests network access to "${domain}", which is not in the project's permission budget`);
18
+ }
19
+ }
20
+ }
21
+ // Check filesystem read
22
+ if (skillPerms.filesystem?.read && skillPerms.filesystem.read.length > 0) {
23
+ const budgetPaths = budget.filesystem?.read ?? [];
24
+ for (const p of skillPerms.filesystem.read) {
25
+ if (!isPathAllowed(p, budgetPaths)) {
26
+ throw new Error(`Permission denied: ${skillName} requests filesystem read access to "${p}", which is not in the project's permission budget`);
27
+ }
28
+ }
29
+ }
30
+ // Check filesystem write
31
+ if (skillPerms.filesystem?.write && skillPerms.filesystem.write.length > 0) {
32
+ const budgetPaths = budget.filesystem?.write ?? [];
33
+ for (const p of skillPerms.filesystem.write) {
34
+ if (!isPathAllowed(p, budgetPaths)) {
35
+ throw new Error(`Permission denied: ${skillName} requests filesystem write access to "${p}", which is not in the project's permission budget`);
36
+ }
37
+ }
38
+ }
39
+ }
40
+ /**
41
+ * Check if a domain is allowed by the budget's domain list.
42
+ * Supports wildcard matching: *.example.com matches sub.example.com
43
+ */
44
+ export function isDomainAllowed(domain, allowedDomains) {
45
+ for (const allowed of allowedDomains) {
46
+ if (allowed === domain)
47
+ return true;
48
+ // Wildcard matching: *.example.com
49
+ if (allowed.startsWith('*.')) {
50
+ const suffix = allowed.slice(1); // .example.com
51
+ if (domain.endsWith(suffix) || domain === allowed.slice(2)) {
52
+ return true;
53
+ }
54
+ // Also match if the skill requests the same wildcard pattern
55
+ if (domain === allowed)
56
+ return true;
57
+ }
58
+ }
59
+ return false;
60
+ }
61
+ /**
62
+ * Check if a path is allowed by the budget's path list.
63
+ * Simple subset check: skill path must match one of the budget paths.
64
+ */
65
+ export function isPathAllowed(requestedPath, allowedPaths) {
66
+ for (const allowed of allowedPaths) {
67
+ if (allowed === requestedPath)
68
+ return true;
69
+ // If budget allows ./src/** and skill requests ./src/foo, it's allowed
70
+ if (allowed.endsWith('/**')) {
71
+ const prefix = allowed.slice(0, -3); // ./src
72
+ if (requestedPath.startsWith(prefix))
73
+ return true;
74
+ }
75
+ }
76
+ return false;
77
+ }
78
+ //# sourceMappingURL=permission-checker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permission-checker.js","sourceRoot":"","sources":["../../src/lib/permission-checker.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tankpkg/cli",
3
- "version": "0.4.2",
3
+ "version": "0.6.0",
4
4
  "description": "Security-first package manager for AI agent skills",
5
5
  "type": "module",
6
6
  "bin": {