Commit 10aecb3
authored
Support multi-client and all-clients skill installation (#4732)
* Support multiple clients per skill install
Add InstallOptions.Clients, resolve and validate client paths, multi-dir
extract/write with rollback, and legacy empty-Clients digest no-op.
Signed-off-by: Samuele Verzi <samu@stacklok.com>
* Use clients array on skill install request
Breaking: install body field client is replaced by clients []string.
Signed-off-by: Samuele Verzi <samu@stacklok.com>
* Send clients array from skills HTTP client
Mirror API install body; include group on install request DTO.
Signed-off-by: Samuele Verzi <samu@stacklok.com>
* Add --clients flag for skill install
Comma-separated values map to InstallOptions.Clients.
Signed-off-by: Samuele Verzi <samu@stacklok.com>
* Document multi-client skill install
Update OpenAPI install schema and CLI/skill user references.
Signed-off-by: Samuele Verzi <samu@stacklok.com>
* Refactor multi-client skill install for lint limits
Extract git and OCI install paths into smaller helpers, add
missingClients and removeSkillDirs, and fix import order in tests.
Signed-off-by: Samuele Verzi <samu@stacklok.com>
* Wrap skill install --clients flag definition
Signed-off-by: Samuele Verzi <samu@stacklok.com>
* Regenerate OpenAPI and skill install CLI docs
Signed-off-by: Samuele Verzi <samu@stacklok.com>
* Add path-containment validation for resolved skill directories
* Add tests for multi-client rollback and error paths
* Add path-containment validation for resolved skill directories
* Add tests for review-identified multi-client bugs
Cover legacy no-op with explicit client, upgrade extracting to all
existing clients, and multi-client rollback and error paths.
* Add path-containment validation for resolved skill directories
Apply filepath.Clean at path resolution time and validate against
traversal segments before any filesystem operation.
* Sanitize skill directory paths at use site to satisfy CodeQL
Apply filepath.Clean at every point where a path is retrieved from the
clientDirs/allDirs map before a filesystem operation (os.Stat, Extract,
WriteFiles, Remove). CodeQL's taint tracker loses the sanitization done
at storage time once the value flows through a map; cleaning at retrieval
makes the guard visible to the analyzer at each individual sink.
Signed-off-by: Samuele Verzi <samu@stacklok.com>
Made-with: Cursor
* Suppress CodeQL path-injection false positives on os.Stat checks
The four os.Stat(dir) pre-checks in applyGitInstallExisting,
applyGitInstallFresh, installExtractionSameDigestNewClients, and
installExtractionFresh are flagged by CodeQL's go/path-injection query
because 'dir' originates (transitively) from user-supplied client names.
The paths are safe: client names are validated against the known
skill-supporting client list, skill names pass validateLocalPath, and
PathResolver.GetSkillPath constructs paths from fixed base directories
which are then confirmed absolute and traversal-free by validateResolvedDir.
Add the same // lgtm[go/path-injection] suppression used in
pkg/skills/gitresolver/writer.go for the identical taint flow.
Signed-off-by: Samuele Verzi <samu@stacklok.com>
Made-with: Cursor
* Support all sentinel for multi-client skill install
---------
Signed-off-by: Samuele Verzi <samu@stacklok.com>1 parent 098694d commit 10aecb3
File tree
17 files changed
+889
-146
lines changed- cmd/thv/app
- docs
- cli
- server
- pkg
- api/v1
- skills
- client
- skillsvc
- skills/toolhive-cli-user
- references
17 files changed
+889
-146
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
| 7 | + | |
| 8 | + | |
7 | 9 | | |
8 | 10 | | |
9 | 11 | | |
10 | 12 | | |
11 | 13 | | |
12 | 14 | | |
13 | 15 | | |
14 | | - | |
| 16 | + | |
15 | 17 | | |
16 | 18 | | |
17 | 19 | | |
| |||
34 | 36 | | |
35 | 37 | | |
36 | 38 | | |
37 | | - | |
| 39 | + | |
| 40 | + | |
38 | 41 | | |
39 | 42 | | |
40 | 43 | | |
| |||
47 | 50 | | |
48 | 51 | | |
49 | 52 | | |
50 | | - | |
| 53 | + | |
51 | 54 | | |
52 | 55 | | |
53 | 56 | | |
| |||
58 | 61 | | |
59 | 62 | | |
60 | 63 | | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
101 | 101 | | |
102 | 102 | | |
103 | 103 | | |
104 | | - | |
| 104 | + | |
105 | 105 | | |
106 | 106 | | |
107 | 107 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
298 | 298 | | |
299 | 299 | | |
300 | 300 | | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
301 | 321 | | |
302 | 322 | | |
303 | 323 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
25 | 25 | | |
26 | 26 | | |
27 | 27 | | |
28 | | - | |
29 | | - | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
30 | 32 | | |
31 | 33 | | |
32 | 34 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
159 | 159 | | |
160 | 160 | | |
161 | 161 | | |
162 | | - | |
| 162 | + | |
163 | 163 | | |
| 164 | + | |
164 | 165 | | |
165 | 166 | | |
166 | 167 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
130 | 130 | | |
131 | 131 | | |
132 | 132 | | |
133 | | - | |
| 133 | + | |
134 | 134 | | |
135 | 135 | | |
136 | 136 | | |
137 | 137 | | |
138 | 138 | | |
139 | 139 | | |
140 | | - | |
| 140 | + | |
141 | 141 | | |
142 | 142 | | |
143 | 143 | | |
| |||
0 commit comments