Feat v0.8.0 files sandbox module
All checks were successful
CI/CD / detect-changes (pull_request) Successful in 4s
CI/CD / test-frontend (pull_request) Has been skipped
CI/CD / test-runners (pull_request) Has been skipped
CI/CD / e2e-smoke (pull_request) Has been skipped
CI/CD / test-go-pg (pull_request) Successful in 2m44s
CI/CD / test-sqlite (pull_request) Successful in 2m57s
CI/CD / build-and-deploy (pull_request) Successful in 1m25s
All checks were successful
CI/CD / detect-changes (pull_request) Successful in 4s
CI/CD / test-frontend (pull_request) Has been skipped
CI/CD / test-runners (pull_request) Has been skipped
CI/CD / e2e-smoke (pull_request) Has been skipped
CI/CD / test-go-pg (pull_request) Successful in 2m44s
CI/CD / test-sqlite (pull_request) Successful in 2m57s
CI/CD / build-and-deploy (pull_request) Successful in 1m25s
Bridge ObjectStore (PVC/S3) into the Starlark sandbox with extension-scoped key namespacing. New files module with put/get/meta/list/delete/exists builtins gated by files.read and files.write permissions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -211,6 +211,78 @@ func (s *PVCStore) Exists(ctx context.Context, key string) (bool, error) {
|
||||
return false, fmt.Errorf("storage/pvc: exists %q: %w", key, err)
|
||||
}
|
||||
|
||||
// List returns objects under the given prefix, up to limit entries.
|
||||
func (s *PVCStore) List(ctx context.Context, prefix string, limit int) ([]ObjectEntry, error) {
|
||||
if prefix != "" {
|
||||
if err := validateKey(prefix); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if limit <= 0 {
|
||||
limit = 100
|
||||
}
|
||||
|
||||
absPrefix := s.resolve(prefix)
|
||||
|
||||
// If the prefix path doesn't exist, return empty.
|
||||
info, err := os.Stat(absPrefix)
|
||||
if os.IsNotExist(err) {
|
||||
return nil, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("storage/pvc: list %q: %w", prefix, err)
|
||||
}
|
||||
|
||||
var entries []ObjectEntry
|
||||
|
||||
if !info.IsDir() {
|
||||
// Prefix points to a single file — return it.
|
||||
s.mu.RLock()
|
||||
ct := s.mimeMap[prefix]
|
||||
s.mu.RUnlock()
|
||||
if ct == "" {
|
||||
ct = "application/octet-stream"
|
||||
}
|
||||
return []ObjectEntry{{Key: prefix, Size: info.Size(), ContentType: ct}}, nil
|
||||
}
|
||||
|
||||
// Walk the directory tree under the prefix.
|
||||
walkRoot := absPrefix
|
||||
err = filepath.Walk(walkRoot, func(path string, fi os.FileInfo, walkErr error) error {
|
||||
if walkErr != nil {
|
||||
return nil // skip inaccessible entries
|
||||
}
|
||||
if fi.IsDir() {
|
||||
return nil
|
||||
}
|
||||
if len(entries) >= limit {
|
||||
return filepath.SkipAll
|
||||
}
|
||||
|
||||
// Recover the storage key by stripping basePath + "/".
|
||||
rel, relErr := filepath.Rel(s.basePath, path)
|
||||
if relErr != nil {
|
||||
return nil
|
||||
}
|
||||
key := filepath.ToSlash(rel)
|
||||
|
||||
s.mu.RLock()
|
||||
ct := s.mimeMap[key]
|
||||
s.mu.RUnlock()
|
||||
if ct == "" {
|
||||
ct = "application/octet-stream"
|
||||
}
|
||||
|
||||
entries = append(entries, ObjectEntry{Key: key, Size: fi.Size(), ContentType: ct})
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return entries, fmt.Errorf("storage/pvc: list walk %q: %w", prefix, err)
|
||||
}
|
||||
|
||||
return entries, nil
|
||||
}
|
||||
|
||||
// Healthy verifies the storage path is writable.
|
||||
func (s *PVCStore) Healthy(ctx context.Context) error {
|
||||
probe := filepath.Join(s.basePath, ".health-probe")
|
||||
|
||||
Reference in New Issue
Block a user