Skip to content

Add skill installer and extractor for OCI artifact extraction#3835

Merged
JAORMX merged 2 commits intomainfrom
feat/skill-installer
Feb 17, 2026
Merged

Add skill installer and extractor for OCI artifact extraction#3835
JAORMX merged 2 commits intomainfrom
feat/skill-installer

Conversation

@JAORMX
Copy link
Collaborator

@JAORMX JAORMX commented Feb 16, 2026

Closes #3649

Why

This is the critical-path task for the Skills Lifecycle Management epic — all remaining skill tasks are blocked on having an installer that can extract OCI artifact content to disk and clean up on uninstall.

Today, Install() only creates a pending DB record and Uninstall() only deletes it. Neither touches the filesystem.

What

Filesystem operations (pkg/skills/installer.go):

  • Extract() decompresses tar.gz OCI layers to client skill directories with size limits (500MB total, 100MB/file, 1000 files max) and permission sanitization (setuid/setgid stripped, capped at 0644)
  • Remove() safely deletes skill directories with guards against dangerous paths
  • Security follows skillet's defense-in-depth pattern: pre-extraction symlink validation of target path, pre-write containment check per file, post-extraction filesystem walk

Service layer (pkg/skills/skillsvc/):

  • Install() now handles managed/unmanaged detection (same digest = no-op, different digest = upgrade, unmanaged dir on disk = refuse unless --force)
  • Uninstall() removes files for all clients before deleting the DB record
  • Functional options pattern (WithPathResolver) keeps the service extensible for Skill service implementation #3650 (OCI store/registry)

Wiring:

  • PathResolver interface in pkg/skills/ avoids the pkg/skillspkg/client import cycle
  • clientPathAdapter in pkg/api/server.go bridges *client.ClientManager to PathResolver
  • LayerData/Reference/Digest are internal-only fields (json:"-") — not exposed via HTTP API. The API path still creates pending records; extraction is only reachable from internal code (OCI pull in Skill service implementation #3650)

Large PR Justification

This touched the API so the swagger occupies some space.

🤖 Generated with Claude Code

@github-actions github-actions bot added the size/XL Extra large PR: 1000+ lines changed label Feb 16, 2026
Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Large PR Detected

This PR exceeds 1000 lines of changes and requires justification before it can be reviewed.

How to unblock this PR:

Add a section to your PR description with the following format:

## Large PR Justification

[Explain why this PR must be large, such as:]
- Generated code that cannot be split
- Large refactoring that must be atomic
- Multiple related changes that would break if separated
- Migration or data transformation

Alternative:

Consider splitting this PR into smaller, focused changes (< 1000 lines each) for easier review and reduced risk.

See our Contributing Guidelines for more details.


This review will be automatically dismissed once you add the justification section.

@codecov
Copy link

codecov bot commented Feb 16, 2026

Codecov Report

❌ Patch coverage is 66.95652% with 76 lines in your changes missing coverage. Please review.
✅ Project coverage is 66.72%. Comparing base (c0924fd) to head (d5e3fd9).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
pkg/skills/installer.go 57.44% 24 Missing and 16 partials ⚠️
pkg/skills/skillsvc/skillsvc.go 80.67% 17 Missing and 6 partials ⚠️
pkg/api/server.go 0.00% 13 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff            @@
##             main    #3835    +/-   ##
========================================
  Coverage   66.71%   66.72%            
========================================
  Files         443      444     +1     
  Lines       43847    44060   +213     
========================================
+ Hits        29254    29398   +144     
- Misses      12306    12355    +49     
- Partials     2287     2307    +20     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

jhrozek
jhrozek previously approved these changes Feb 17, 2026
JAORMX and others added 2 commits February 17, 2026 14:03
Implement the skill installer that extracts OCI artifact layers to
client skill directories with security validation and managed/unmanaged
detection.

Key changes:
- Add Extract() and Remove() in pkg/skills/installer.go for filesystem
  operations with defense-in-depth security (path traversal prevention,
  symlink validation, permission sanitization, size/count limits)
- Add PathResolver interface to decouple pkg/skills from pkg/client
- Update skillsvc with functional options pattern (WithPathResolver)
  and full Install/Uninstall logic including upgrade detection and
  file cleanup for all clients on uninstall
- Wire PathResolver via clientPathAdapter in API server
- Expose Client and Force fields in install API request

Closes #3649

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add symlink protection to Remove using Lstat/EvalSymlinks
- Fix cross-platform root detection (filepath.Dir/VolumeName)
- Make Uninstall cleanup best-effort with errors.Join
- Roll back extraction on store Create/Update failure
- Introduce Installer interface for DI and testability

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@JAORMX JAORMX force-pushed the feat/skill-installer branch from bf0362f to d5e3fd9 Compare February 17, 2026 13:13
@github-actions github-actions bot added size/XL Extra large PR: 1000+ lines changed and removed size/XL Extra large PR: 1000+ lines changed labels Feb 17, 2026
@JAORMX JAORMX merged commit 262e8c5 into main Feb 17, 2026
38 checks passed
@JAORMX JAORMX deleted the feat/skill-installer branch February 17, 2026 14:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/XL Extra large PR: 1000+ lines changed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Skill installer and extractor

2 participants