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
5.8 KiB
5.8 KiB
Alga PSA Extension Manifest v2
Manifest v2 is the canonical specification for the Enterprise Extension System. It defines out-of-process execution, signed content-addressed bundles, component-model runtime metadata, and iframe-only UI served by the Runner.
- See “Correctness Rules” in the README for canonical routing and UI serving behavior (Gateway route, Runner static UI, iframe bootstrap). Gateway scaffold: server/src/app/api/ext/[extensionId]/[[...path]]/route.ts
Manifest v2 defines signed, content-addressed bundles executed out-of-process and rendered via iframe UI.
Overview
- File name:
manifest.jsoninside the bundle root - Declares runtime, capabilities, API endpoints, and UI entry
- Used by Registry to validate, install, and route requests
Type (abridged)
interface ManifestV2 {
name: string; // reverse‑domain ID, e.g., "com.acme.reports"
publisher: string; // organization name
version: string; // semver
runtime: 'wasm-js@1'; // componentize-js output (see @alga-psa/extension-runtime)
capabilities?: string[]; // e.g., ["http.fetch","storage.kv","secrets.get"]
ui?: { // iframe UI (served by Runner)
type: 'iframe';
entry: string; // e.g., "ui/index.html"
hooks?: { // host integration points
appMenu?: { label: string };
[key: string]: unknown; // future: tabs, placeholders
};
};
api?: {
endpoints: Array<{
method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
path: string; // e.g., "/agreements" or "/agreements/:id"
handler: string; // e.g., "dist/handlers/http/list_agreements"
}>;
};
events?: Array<{ // optional event subscriptions
topic: string;
handler: string;
}>;
entry?: string; // main wasm entry, e.g., "dist/main.wasm"
precompiled?: Record<string, string>; // target triple → cwasm path
assets?: string[]; // glob patterns, e.g., ["ui/**/*"]
sbom?: string; // optional SBOM reference
}
Example
{
"name": "com.alga.softwareone",
"publisher": "SoftwareOne",
"version": "1.2.3",
"runtime": "wasm-js@1",
"capabilities": ["http.fetch", "storage.kv", "secrets.get"],
"ui": {
"type": "iframe",
"entry": "ui/index.html",
"hooks": { "appMenu": { "label": "Agreements" } }
},
"api": {
"endpoints": [
{ "method": "GET", "path": "/agreements", "handler": "dist/handlers/http/list_agreements" },
{ "method": "POST", "path": "/agreements/sync", "handler": "dist/handlers/http/sync" }
]
},
"precompiled": {
"x86_64-linux-gnu": "artifacts/cwasm/x86_64-linux-gnu/main.cwasm",
"aarch64-linux-gnu": "artifacts/cwasm/aarch64-linux-gnu/main.cwasm"
},
"assets": ["ui/**/*"],
"sbom": "sbom.spdx.json"
}
Validation Rules
- name: reverse‑domain, lowercase alphanumeric, dots, hyphens; unique per registry
- version: semver
- runtime: currently
wasm-js@1(componentized handlers) - api.endpoints: optional; when present use unique method+path pairs; paths must start with
/; currently advisory (not enforced by gateway) ui.entrymust exist in the bundle; manifest-levelentryfield is not used by the current runtimeui.hooks.appMenu.labelmust be a non-empty string when present- capabilities: optional array (defaults to empty); must be recognized by the platform; least‑privilege encouraged
- assets: glob patterns limited to static files; no hidden files by default
Signing & Provenance
- Bundles are content‑addressed using SHA256 and signed (e.g.,
sha256:<hex>). - Registry records
content_hash,signature, and publisher certificate/keys. - Signature verification occurs on publish/install and on load.
See Security & Signing.
Routing & Execution
- Gateway maps
/api/ext/[extensionId]/[[...path]]requests to tenant installs. Endpoint metadata from the manifest is surfaced to operators today; strict enforcement is not enabled (see 2025-11-12 plan). - Gateway normalizes the request and calls Runner
POST /v1/executewith{context, http, limits, config, providers, secret_envelope}. - Runner executes the handler under isolation and returns
{status, headers, body_b64}to the Gateway.
See API Routing Guide.
Install Metadata (Config, Providers, Secrets)
Manifest v2 describes the bundle. Tenant-specific configuration is stored separately:
tenant_extension_install_configpersists per-tenant config maps and provider grants (capability enablement).tenant_extension_install_secretsstores sealed envelopes (Vault transit or inline) that the Runner decrypts on demand.- The gateway attaches
config,providers, andsecret_envelopeto each Runner call so host capabilities (storage/http/secrets/ui_proxy) can enforce policy.
Plan dependencies and outstanding gaps are documented in 2025-11-12-extension-system-alignment-plan.
UI Delivery
- UI is served by the Runner at
${RUNNER_PUBLIC_BASE}/ext-ui/{extensionId}/{content_hash}/[...](immutable). The Next.jsext-uiroute is a gate/redirect when rust-host mode is enabled. - The host constructs iframe URLs via buildExtUiSrc() and performs secure bootstrap via bootstrapIframe().
- No in-process UI rendering and no dynamic import of tenant code in the host.