Feat v0.8.2 capability negotiation (#69)
All checks were successful
CI/CD / detect-changes (push) Successful in 4s
CI/CD / test-frontend (push) Has been skipped
CI/CD / test-runners (push) Has been skipped
CI/CD / e2e-smoke (push) Has been skipped
CI/CD / test-go-pg (push) Successful in 2m47s
CI/CD / test-sqlite (push) Successful in 2m52s
CI/CD / build-and-deploy (push) Successful in 30s

Co-authored-by: Jeffrey Smith <jasafpro@gmail.com>
Co-committed-by: Jeffrey Smith <jasafpro@gmail.com>
This commit was merged in pull request #69.
This commit is contained in:
2026-04-03 09:14:00 +00:00
committed by xcaliber
parent 435f972ded
commit 00ef970163
16 changed files with 593 additions and 96 deletions

View File

@@ -40,7 +40,7 @@ var defaultBundledPackages = map[string]bool{}
//
// Design: install-once, skip-if-present. If an admin uninstalls a bundled
// package, it won't be re-installed on the next restart.
func InstallBundledPackages(bundledDir, packagesDir, allowlist string, stores store.Stores, runner *sandbox.Runner) {
func InstallBundledPackages(bundledDir, packagesDir, allowlist string, stores store.Stores, runner *sandbox.Runner, detectedCaps map[string]bool) {
entries, err := os.ReadDir(bundledDir)
if err != nil {
if os.IsNotExist(err) {
@@ -82,7 +82,7 @@ func InstallBundledPackages(bundledDir, packagesDir, allowlist string, stores st
}
pkgPath := filepath.Join(bundledDir, entry.Name())
result, err := installBundledPackage(pkgPath, packagesDir, stores, runner, adminUserID)
result, err := installBundledPackage(pkgPath, packagesDir, stores, runner, adminUserID, detectedCaps)
if err != nil {
log.Printf("[bundled] ⚠️ Failed to install %s: %v", entry.Name(), err)
continue
@@ -129,7 +129,7 @@ func parseBundleAllowlist(s string) map[string]bool {
// installBundledPackage installs a single .pkg archive if its package ID
// doesn't already exist in the database. Returns "installed" or "skipped".
func installBundledPackage(pkgPath, packagesDir string, stores store.Stores, runner *sandbox.Runner, adminUserID string) (string, error) {
func installBundledPackage(pkgPath, packagesDir string, stores store.Stores, runner *sandbox.Runner, adminUserID string, detectedCaps map[string]bool) (string, error) {
ctx := context.Background()
// Open as zip
@@ -237,20 +237,17 @@ func installBundledPackage(pkgPath, packagesDir string, stores store.Stores, run
}
}
// Handle dormant status for packages with unmet requires
knownCaps := map[string]bool{}
if reqs, ok := manifest["requires"].([]any); ok && len(reqs) > 0 {
var unmetReqs []string
for _, r := range reqs {
req, _ := r.(string)
if req != "" && !knownCaps[req] {
unmetReqs = append(unmetReqs, req)
}
// Validate required capabilities — skip package if unmet
if caps, ok := ParseCapabilities(manifest); ok {
missing := CheckRequiredCapabilities(caps.Required, detectedCaps)
if len(missing) > 0 {
stores.Packages.Delete(ctx, pkgID)
log.Printf("[bundled] %s: skipped (missing required capabilities: %v)", pkgID, missing)
return "skipped", nil
}
if len(unmetReqs) > 0 {
stores.Packages.SetStatus(ctx, pkgID, "dormant")
stores.Packages.SetEnabled(ctx, pkgID, false)
log.Printf("[bundled] %s: dormant (unmet requires: %v)", pkgID, unmetReqs)
unmetOpt := CheckRequiredCapabilities(caps.Optional, detectedCaps)
if len(unmetOpt) > 0 {
log.Printf("[bundled] %s: optional capabilities unavailable: %v", pkgID, unmetOpt)
}
}