PSA/ee/docs/extension-system/runner-s3-integration.md
Hermes 284313f908
Some checks are pending
Bidi Control Character Guard / bidi-control-guard (push) Waiting to run
Circular Dependency Check / Check for new circular dependencies (push) Waiting to run
Citus Migration Smoke / Combined migrations on single-node Citus (push) Waiting to run
E2E Fresh Install Tests / fresh-install-e2e (push) Waiting to run
ext-v2 guardrails / Run ext-v2 guard and ESLint (push) Waiting to run
Integration Tests / Check for relevant changes (push) Waiting to run
Integration Tests / ${{ (github.event_name == 'schedule' || github.event.inputs.suite == 'full') && 'Full integration suite' || 'Tier-1 integration subset' }} (push) Blocked by required conditions
Mobile checks / Mobile lint + typecheck (push) Waiting to run
Mobile checks / Mobile unit tests (push) Waiting to run
Mobile checks / Mobile dependency audit (report) (push) Waiting to run
Mobile checks / Mobile reproducibility checks (push) Waiting to run
Secrets guard (env backups) / Ensure no tracked env backup files (push) Waiting to run
Temporal Readiness / fast-readiness (push) Waiting to run
Temporal Readiness / docker-parity (push) Waiting to run
TypeScript Type Check / Nx affected typecheck (push) Waiting to run
Unit Tests / Skipped-test budget (push) Waiting to run
Unit Tests / Nx affected unit tests (push) Waiting to run
Unit Tests / Server unit coverage (informational) (push) Waiting to run
Validate Tenant Management Schema / Check for relevant changes (push) Waiting to run
Validate Tenant Management Schema / Validate Tenant Management Schema (push) Blocked by required conditions
EE Workflows Build Guard / ee-workflows-build-guard (push) Waiting to run
Initial import of AlgaPSA codebase from PSA server
Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz

Source: /opt/alga-psa on psa.joliet.tech
2026-06-22 16:12:17 -05:00

118 lines
5.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Runner S3 Integration Guide
This document specifies how the Runner integrates with S3-compatible storage (e.g., MinIO) to fetch extension bundles by content hash and serve static UI assets.
Links:
- Overview: [ee/docs/extension-system/overview.md](ee/docs/extension-system/overview.md:1)
- Serving system: [ee/docs/extension-system/serving-system.md](ee/docs/extension-system/serving-system.md:1)
## Responsibilities
- Fetch and cache extension bundle by content hash:
- Download canonical object from S3 at:
- sha256/<content_hash>/bundle.tar.zst
- sha256/<content_hash>/manifest.json
- Verify integrity (content hash, size if provided), and only accept immutable artifacts.
- Serve extension UI assets:
- Public base: ${RUNNER_PUBLIC_BASE}/ext-ui/{extensionId}/{content_hash}/…
- Static assets resolved from the unpacked bundle according to manifest.json (e.g., index.html, JS/CSS assets, media).
- Execution API:
- Expose an HTTP endpoint to execute extension handlers when invoked by Gateway:
- POST /v1/execute
- Ensure runtime fetches entry.wasm (or equivalent) mapped by content_hash and reuses local cache.
## Configuration Parity with Server
The Runner should use the same S3 settings as the server for consistent access and path semantics.
Required environment variables:
- STORAGE_S3_ENDPOINT: S3/MinIO endpoint (e.g., http://localhost:9000 for MinIO).
- STORAGE_S3_BUCKET: Bucket name used to store/read bundles.
- STORAGE_S3_REGION: Region string; for MinIO use a placeholder like us-east-1 unless configured otherwise.
- STORAGE_S3_ACCESS_KEY: Access key.
- STORAGE_S3_SECRET_KEY: Secret key.
- STORAGE_S3_FORCE_PATH_STYLE: true to force path-style addressing for MinIO.
- STORAGE_S3_BUNDLE_BUCKET: optional override for the bundles bucket (if server publishes to a separate bucket).
- STORAGE_TLS: Optional; set true if using HTTPS and the cert is trusted (otherwise provide appropriate trust settings).
Runner-specific:
- RUNNER_PUBLIC_BASE: Base URL path to serve UI (e.g., /runner).
- RUNNER_CACHE_DIR: Filesystem directory for caching fetched bundles (e.g., /var/cache/alga-runner or ./.cache/runner for local).
- RUNNER_MAX_CACHE_SIZE_BYTES: Optional LRU cap for cache eviction.
- RUNNER_OFFLINE: Optional; if true, disables network fetches and requires bundles to be pre-cached.
Server parity notes:
- The server writes bundles to canonical S3 paths under sha256/<hash>/. The Runner must only read from canonical locations and never mutate them.
- If the server enforces declaredHash, the Runner should assume sha256/<hash>/… objects are immutable.
## Cache Behavior and Integrity
- On first request for {extensionId, content_hash}:
- Fetch sha256/<content_hash>/manifest.json, validate basic fields (extension, version, entry paths).
- Fetch sha256/<content_hash>/bundle.tar.zst, verify sha256(content) equals content_hash.
- Unpack into RUNNER_CACHE_DIR/<content_hash>/… with a marker indicating successful extraction (e.g., .ready).
- Subsequent requests:
- Serve from cache if .ready is present.
- For HTTP GETs of UI assets, set ETag to the content hash or the assets digest.
- Respect If-None-Match and return 304 when ETag matches for immutable assets.
- Eviction:
- If RUNNER_MAX_CACHE_SIZE_BYTES is set, implement LRU eviction of least-recently-used content hashes.
## HTTP Flows
- Execution (from Gateway to Runner):
- POST /v1/execute
- Body includes { extensionId, content_hash, handler, payload, tenant, … }.
- Runner ensures bundle for content_hash is present (fetch+cache if missing), loads entry.wasm, and executes handler.
- UI (from Browser to Runner):
- GET ${RUNNER_PUBLIC_BASE}/ext-ui/{extensionId}/{content_hash}/index.html
- GET ${RUNNER_PUBLIC_BASE}/ext-ui/{extensionId}/{content_hash}/assets/<file>
- The Runner maps the path to RUNNER_CACHE_DIR/<content_hash>/ui/… (or equivalent layout from the bundle).
- Set headers:
- Cache-Control: public, max-age=31536000, immutable (safe for immutable paths)
- ETag: "<content_hash>" or strong per-asset digest
- Content-Type: resolved from file extension
## Expected S3 Paths
Canonical objects written by the server:
- sha256/<hash>/bundle.tar.zst
- sha256/<hash>/manifest.json
The Runner must not depend on non-canonical staging keys; only canonical content-hash keys are considered valid.
## Immutability and Conditional Requests
- All content under sha256/<hash>/ is immutable.
- For GET of UI assets, use ETag based on content hash (or a per-file digest within the bundle).
- Honor If-None-Match to enable 304 responses and reduce bandwidth.
- Do not attempt to overwrite or delete S3 objects; cache management is local.
## Acceptance Checks (Local Runner with MinIO)
- With MinIO configured via STORAGE_* and path-style:
- Given a content hash H from a finalized upload:
- Runner fetches sha256/H/manifest.json and sha256/H/bundle.tar.zst.
- Runner unpacks and serves UI at:
- ${RUNNER_PUBLIC_BASE}/ext-ui/{extensionId}/H/index.html returns 200
- Subsequent GETs with If-None-Match: "H" return 304
- Execute flow:
- POST /v1/execute with content_hash H executes against entry.wasm and returns a handler result or structured error.
## Notes
- entry.wasm resolution:
- The manifests entry.wasm path is relative to the bundle root; ensure it is present after unpacking.
- Security:
- Validate manifest format and restrict file types and paths during unpack to avoid path traversal.
- Consider running Wasm in a sandbox with appropriate capabilities.
- Timeouts and retries:
- On transient S3 errors, implement exponential backoff for fetches.
- Fail closed if content hash validation fails.
## References
- Overview: [ee/docs/extension-system/overview.md](ee/docs/extension-system/overview.md:1)
- Serving system: [ee/docs/extension-system/serving-system.md](ee/docs/extension-system/serving-system.md:1)