v0.8.5: Extension composability — slots, contributes, lib.require relaxation
All checks were successful
CI/CD / detect-changes (pull_request) Successful in 5s
CI/CD / test-runners (pull_request) Has been skipped
CI/CD / e2e-smoke (pull_request) Has been skipped
CI/CD / test-frontend (pull_request) Successful in 6s
CI/CD / test-go-pg (pull_request) Successful in 2m42s
CI/CD / test-sqlite (pull_request) Successful in 2m58s
CI/CD / build-and-deploy (pull_request) Successful in 1m33s

Manifest declarations for slots (host surfaces declare injection points)
and contributes (extensions declare UI contributions). lib.require()
relaxed from library-only to any package with exports. Admin slots
aggregation endpoint. SDK renderAll() helper. 7 new tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-03 11:14:04 +00:00
parent 3c403dd884
commit 68713bf539
14 changed files with 586 additions and 26 deletions

View File

@@ -79,19 +79,21 @@ func BuildLibModule(ctx context.Context, r *Runner, consumerPkgID string, rc *Ru
return nil, fmt.Errorf("lib.require: package %q does not declare dependency on %q", consumerPkgID, libraryID)
}
// 4. Load library's PackageRegistration
// 4. Load target PackageRegistration
libPkg, err := r.stores.Packages.Get(ctx, libraryID)
if err != nil {
return nil, fmt.Errorf("lib.require: library %q not found: %w", libraryID, err)
return nil, fmt.Errorf("lib.require: package %q not found: %w", libraryID, err)
}
if libPkg.Type != "library" {
return nil, fmt.Errorf("lib.require: package %q is type %q, not library", libraryID, libPkg.Type)
// Any package with exports is callable — not just type "library"
exports := extractExports(libPkg.Manifest)
if len(exports) == 0 {
return nil, fmt.Errorf("lib.require: package %q declares no exports", libraryID)
}
if libPkg.Status != models.PackageStatusActive {
return nil, fmt.Errorf("lib.require: library %q is %s, not active", libraryID, libPkg.Status)
return nil, fmt.Errorf("lib.require: package %q is %s, not active", libraryID, libPkg.Status)
}
if libPkg.Tier != models.ExtTierStarlark {
return nil, fmt.Errorf("lib.require: library %q is tier %s, not starlark", libraryID, libPkg.Tier)
return nil, fmt.Errorf("lib.require: package %q is tier %s, not starlark", libraryID, libPkg.Tier)
}
// 5. Build library's module set (library's own permissions)
@@ -113,12 +115,7 @@ func BuildLibModule(ctx context.Context, r *Runner, consumerPkgID string, rc *Ru
return nil, fmt.Errorf("lib.require: error executing library %q: %w", libraryID, err)
}
// 8. Extract exports from manifest
exports := extractExports(libPkg.Manifest)
if len(exports) == 0 {
return nil, fmt.Errorf("lib.require: library %q declares no exports", libraryID)
}
// 8. Build exported members (exports already extracted above)
members := make(starlark.StringDict, len(exports))
for _, name := range exports {
val, ok := result.Globals[name]