Task 21 — Маркетплейс навыков
Phase: 2
Status: done
Owner: —
Slug: skill-marketplace
Goal
data/Skills/marketplace/: import/export CLI, integrity hashes, signed packages, разрешение зависимостей, public template repository.
Acceptance criteria
Sub-tasks
MarketplaceConfigвConfig/AppConfig.cs— SigningKey (default null), RequireSignature (default false), AllowHttpImport (default false), SignatureAlgorithm (“hmac-sha256”), MaxPackageSizeMb (default 50)SkillPackageManifest.Dependencies— List(Id, VersionConstraint — semver range string) SkillDependencyrecord — Id, VersionConstraint (e.g. “≥1.0.0,<2.0.0”), IsRequired (default true)MarketplaceSigningService.cs— ComputeHash (SHA256 of zip bytes), ComputeSignature (HMAC-SHA256), VerifyHash, VerifySignature; interfaceIMarketplaceSigningServiceSkillPackager.Export— compute and writesignature.txt(HMAC-SHA256) alongside the .skillpkg; includehash_sha256.txt(SHA256)SkillPackager.Validate— verify signature and hash on import; fail with clear error if mismatchDependencyResolver.csinSkills/Marketplace/— ResolveAsync(skillId, marketplace) → topologically sorted list of skills to install; detects cycles; respects version constraintsDependencyResolverimplements graph traversal (Kahn-style topological sort with explicit enter/exit markers; cycle detection via onStack set)SkillMarketplace— addInstallWithDeps(skillId, resolver)→ installs skill + all dependencies;GetDependencies(manifest)→ list declared dependenciesMarketplaceController.cs— WebAPI endpoints: GET /api/marketplace, GET /api/marketplace/search, POST /api/marketplace/publish, POST /api/marketplace/import, POST /api/marketplace/install, POST /api/marketplace/install-with-deps, POST /api/marketplace/import-url, GET /api/marketplace/{file}/verify, GET /api/marketplace/{file}/deps, DELETE /api/marketplace/{file}ConsoleUI— extend /marketplace:verify {file}(check hash+signature),deps {file}(show dependency tree),import-url {url}(HTTP download + install with deps)Phase2Config— add MarketplaceConfig sub-sectionProgram.cs(CLI + WebAPI) — register IMarketplaceSigningService in DI; register MarketplaceConfig- Unit tests:
MarketplaceSigningServiceTests.cs— 13 tests: compute hash, verify hash, compute/verify signature, mismatch detection, empty input - Unit tests:
DependencyResolverTests.cs— 15 tests: no deps, linear deps, cycle detection, version constraint matching, missing required/optional deps, version mismatch, cancellation, deduplication dotnet buildпроходит без warningsdotnet testпроходит (Phase2 tests: 68/68 passed; full suite: 678/684, 6 pre-existing failures in OtelServiceTests + BudgetGuardTests)
Scope / Likely files
src/agent/Skills/Marketplace/, src/agent/Skills/SkillPackager.cs, src/agent/CLI/ConsoleUI.cs, src/agent/Hercules.WebApi/Controllers/MarketplaceController.cs
Dependencies
- блокирует / опирается на: task_019 — skill-package-format
- блокирует / опирается на: task_020 — skill-manifest
Risks / Rollback
Supply chain; подпись пакетов обязательна для prod.
Implementation notes
2026-08-12
Добавлено:
Config/AppConfig.cs — MarketplaceConfig секция:
SigningKey(base64-encoded, default null)RequireSignature(default false)AllowHttpImport(default false)SignatureAlgorithm(“hmac-sha256”)MaxPackageSizeMb(default 50)TemplateRepositoryUrl(опционально)
Skills/SkillPackageManifest.cs — SkillDependency record + Dependencies поле:
Id— ID зависимого навыкаVersionConstraint— semver range (“^1.0.0”, “~1.2.3”, “>=2.0.0”, “1.2.3” — major-only, etc.)IsRequired(default true) — false = warn but don’t block
Skills/Marketplace/MarketplaceSigningService.cs — IMarketplaceSigningService + реализация:
ComputeHash(byte[])— SHA256 hexComputeSignature(hashHex)— HMAC-SHA256 base64 (usesMarketplaceConfig.SigningKey)VerifyHash(bytes, expectedHashHex)— case-insensitive compareVerifySignature(hashHex, sigBase64)— constant-timeCryptographicOperations.FixedTimeEquals- Throws
InvalidOperationExceptionwhen signing requested but key not configured - Catches all crypto errors and returns
falsefromVerifySignaturefor safe failure mode
Skills/SkillPackager.cs — integrity sidecars + signing:
WriteIntegritySidecars— после записи ZIP в temp, читает bytes, вычисляет hash, опционально подписывает- Записывает
hash_sha256.txt(всегда) иsignature.txt(если ключ сконфигурирован) - Атомарный rename из temp в final path
Validate— после read package проверяет hash и signature, добавляет errors если mismatch
Skills/Marketplace/DependencyResolver.cs — iterative DFS с enter/exit markers:
- Iterative post-order traversal с
Stack<string>маркированных entries (enter:{id}/exit:{id}) - Cycle detection через
onStackset getManifestcallback:null= manifest not found,[]= no deps,[deps]= declared depsVersionMatchesConstraint— поддержка^,~,>=,<=,>,<,=, exact- Version encoding:
int = major*10000 + minor*100 + patch
Skills/SkillMarketplace.cs — InstallWithDeps + GetDependencies:
- Сканирует .skillpkg в marketplace/, читает manifest
InstallWithDeps— устанавливает все required deps перед root skillGetDependencies— возвращаетDependencyInfoдля UI отображенияImportFromUrlAsync— HTTP download (еслиAllowHttpImport = true), size limit 50MB, validate before importVerifyPackage— проверяет hash + signature
Hercules.WebApi/Controllers/MarketplaceController.cs — 10 endpoints:
GET /api/marketplace— listGET /api/marketplace/search?q=— searchPOST /api/marketplace/publish— multipart upload (publish to marketplace)POST /api/marketplace/import— multipart upload (import to local skills)POST /api/marketplace/install— install from marketplace (with conflict resolution)POST /api/marketplace/install-with-deps— install with depsPOST /api/marketplace/import-url— HTTP importGET /api/marketplace/{file}/verify— hash+signature checkGET /api/marketplace/{file}/deps— dependency treeDELETE /api/marketplace/{file}— remove from marketplace
CLI/ConsoleUI.cs — /marketplace sub-commands:
list— таблица пакетовsearch {q}— поискinstall {f}— установкаinstall-deps {f}— установка с зависимостямиverify {f}— hash + signature checkdeps {f}— показать дерево зависимостейpublish {path}— опубликоватьimport-url {url}— HTTP import
DI (CLI + WebAPI):
MarketplaceConfigsingletonIMarketplaceSigningService→MarketplaceSigningService
Tests — 28 new tests:
MarketplaceSigningServiceTests(13): hash/signature compute+verify, mismatch, case-insensitive, without-key throwsDependencyResolverTests(15): no deps, linear chain, missing required, missing optional, already installed, version mismatch, cancellation, dedup, cycle detection, semver constraints (^, ~, >=, <=, <, exact)
Validation:
dotnet buildHercules.csproj — 0 errors, 0 warningsdotnet buildHercules.WebApi.csproj — 0 errors, 0 warningsdotnet test --filter "FullyQualifiedName~Phase2"— 68/68 passeddotnet test(full) — 678/684 passed (6 pre-existing: OTel activity source + BudgetGuard emoji)
Links
- Backlog: ../backlog.md
- Roadmap (EN): ../../ROADMAP-EN.md
- Roadmap (RU): ../../ROADMAP-RU.md