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
Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz Source: /opt/alga-psa on psa.joliet.tech
7.9 KiB
7.9 KiB
Alga PSA Extension System (Enterprise Overview)
This document specifies the Enterprise Edition (EE) extension architecture. It is a v2-only system featuring out-of-process execution, content-addressed signed bundles, a component-model Runner that executes componentize-js artifacts, and iframe-only UI delivery served by the Runner.
Goals
- No tenant code executes in the core app process
- Per-tenant isolation across compute, storage, and egress
- Signed, content-addressed bundles with verified provenance (sha256:…)
- Capability-based host APIs, quotas, and auditable execution
Architecture
- Runner Service (Rust + Wasmtime)
- Executes extension handlers as Wasmtime components generated via
componentize-js+@alga-psa/extension-runtime - Enforces memory/time/concurrency limits
- Exposes a minimal set of namespaced host APIs (alga.*) for storage, http, secrets, logging, and metrics
- Provides additional capability providers (e.g., ui proxy) based on install-scoped grants
- Hosts static UI assets for iframe delivery at ${RUNNER_PUBLIC_BASE}/ext-ui/{extensionId}/{content_hash}/[...]
- Registry & Bundles
- Registry stores extensions, versions, and metadata (content_hash, signature, runtime) plus tenant install configuration (
tenant_extension_install_config) and sealed secret envelopes (tenant_extension_install_secrets) - Bundles are immutable, content-addressed artifacts in object storage
- Signatures are verified on publish/install and on load, against a configured trust bundle
- API Gateway (Next.js)
- Route:
/api/ext/[extensionId]/[[...path]] - Resolves tenant install via installConfig → version/content hash → config + provider grants → secret envelope
- Proxies requests to Runner
POST /v1/executewith strict header/size/time policies and quotas, attachingconfig,providers, andsecret_envelopein the body - Reference scaffold: server/src/app/api/ext/[extensionId]/[[...path]]/route.ts
- Manifest endpoint matching is not enforced today; it is advisory. Enforcement decision is tracked in 2025-11-12 plan.
- UI Delivery (Iframe-Only, served by Runner)
- Static UI assets are served by the Runner at ${RUNNER_PUBLIC_BASE}/ext-ui/{extensionId}/{content_hash}/[...]; the Next.js
ext-uiroute only gates/redirects when rust-host mode is enabled. - The host constructs the iframe src via buildExtUiSrc() and bootstraps via bootstrapIframe()
- Client SDK (@alga/extension-iframe-sdk) provides auth, navigation bridge, and theme token integration
- UI kit (@alga/ui-kit) offers accessible, themed components
- Observability & Policy
- Structured execution logs correlated to requests/events
- Prometheus metrics (duration, memory, fuel, egress bytes, errors)
- Per-tenant/per-extension quotas and egress allowlists
Data Model (Initial)
- extension_registry, extension_version, extension_bundle
- tenant_extension_install, extension_event_subscription
- extension_execution_log, extension_quota_usage
Request Flow (HTTP)
- Client calls
/api/ext/{extensionId}/{...}in the host app (iframe or API consumer). - Gateway resolves the tenant install config (content hash, version, providers, config map, sealed secret envelope).
- Gateway filters headers/body, assembles
{context, http, limits, config, providers, secret_envelope}, and calls RunnerPOST /v1/execute. - Runner fetches/verifies the component by
content_hash, decrypts secrets when permitted, executes the handler, and returns{status, headers, body_b64}. - Gateway maps the response to the client with header allowlists and optional config/secrets version headers.
Manifest v2 Summary
Manifest v2 is the canonical specification for extensions:
- runtime: e.g.,
wasm-js@1(thecomponentize-jspipeline output) - capabilities: least-privilege host APIs requested (storage, http, secrets, etc.)
- api.endpoints: declare HTTP entrypoints (used for docs/UX today; enforcement work tracked in Plan A4)
- ui.iframe: iframe entry HTML and asset mapping; UI is served by Runner using content-addressed paths
- ui.hooks: host integration points such as adding menu entries that launch a full-page iframe; designed to expand for tabs and named placeholders
- precompiled and assets: bundle metadata including sha256 content hash and signatures
See full schema: manifest_schema.md
Security Highlights
- No dynamic importing of tenant JS into the host
- Capability-based host API; deny-by-default egress
- Signature verification and content hashing across the bundle lifecycle
- Iframe sandboxing and origin validation aligned with RUNNER_PUBLIC_BASE
Runner: responsibilities and integration
The Runner is the execution and static asset host for the EE architecture:
- Executes WASM components out-of-process with isolation and quotas (Rust + Wasmtime Component APIs)
- Hosts static UI assets by immutable content hash; the host builds iframe src via buildExtUiSrc() and initializes via bootstrapIframe()
- Provides HTTP interface for handler execution (
POST /v1/execute) called by the API Gateway. Gateway scaffold: server/src/app/api/ext/[extensionId]/[[...path]]/route.ts - Implements host capabilities including HTTP egress, storage KV, secrets, logging, metrics, and the UI proxy (
alga.ui_proxy) with enforcement driven by install-level providers. - Emits live debug events to Redis Streams when
RUNNER_DEBUG_REDIS_URLis configured; EE consumes these via/api/ext-debug/stream. - Signature and provenance enforcement integrate with Registry v2 services. Registry scaffold: ExtensionRegistryServiceV2
Runner-related configuration (host environment):
RUNNER_BASE_URL: internal URL used by the Gateway to call POST /v1/executeRUNNER_PUBLIC_BASE: public base used to construct ext-ui iframe srcEXT_GATEWAY_TIMEOUT_MS: gateway → runner request timeoutSIGNING_TRUST_BUNDLE: path or inline bundle of trusted public keys/certificates for signature verificationRUNNER_DEBUG_REDIS_URL,RUNNER_DEBUG_REDIS_STREAM_PREFIX,RUNNER_DEBUG_REDIS_MAXLEN: enable Redis-backed debug streamingUI_PROXY_BASE_URL,UI_PROXY_AUTH_KEY,UI_PROXY_TIMEOUT_MS: configure the runner-side UI proxy capability
See detailed Runner doc: runner.md
Endpoint and UI delivery correctness
- All extension API calls traverse
/api/ext/[extensionId]/[[...path]]and are proxied to Runner/v1/execute. Enforcement of manifest endpoint lists is TBD (see plan). - UI assets are served by Runner only, at ${RUNNER_PUBLIC_BASE}/ext-ui/{extensionId}/{content_hash}/[...]; there is no Next.js route for ext-ui
Live Debugging
- Runner emits structured
ExtDebugEvententries (stdout/stderr/log) into Redis Streams when debug streaming is enabled. - EE exposes
/api/ext-debug/stream(Server-Sent Events) and a UI at/msp/extensions/[extensionId]/debugto authorized tenant operators. - Capability gating, session TTLs, and audit logging are tracked in Workstream B.