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
4.6 KiB
4.6 KiB
PRD — Extension SDK Client And Service Read Capabilities
- Slug:
extension-sdk-client-service-read-capabilities - Date:
2026-03-26 - Status: Draft
Summary
Add read-only extension host capabilities for tenant-scoped client and service catalog lookup so extension handlers can read those records without making HTTP API calls.
Problem
Handlers that need client lists or service catalog data currently have to rely on API-like transport patterns. That creates unnecessary coupling to routes and credentials and makes scheduled or webhook-driven extension execution awkward.
Goals
- Add first-class host capabilities for reading clients and services from extension handlers.
- Support both user-backed and non-user execution contexts.
- Keep the extension contract typed, small, and versionable.
- Reuse existing internal query logic instead of duplicating API controllers.
- Enforce capability grants, RBAC behavior, and tenant isolation in one place.
Non-goals
- Mutating clients or services.
- Exposing arbitrary database queries.
- Returning the full internal
IClientorIServiceshapes. - Replacing existing HTTP APIs for the web app.
Users and Primary Flows
- Extension authors building tenant automations that need lookup data.
- Scheduler-driven handlers that need to read clients or services without a user session.
- Webhook-style handlers that need service catalog context during execution.
Primary flows:
- Extension lists clients with simple pagination and search.
- Extension fetches one client by id.
- Extension lists service catalog entries with simple filters.
- Extension fetches one service by id.
UX / UI Notes
This work is backend and SDK facing. The main user-facing ergonomics are:
- extension authors import typed host bindings
- handlers avoid HTTP fetches to Alga
- capability names remain explicit in manifests
Requirements
Functional Requirements
- Introduce
cap:client.readandcap:service.read. - Add
clients.list,clients.get,services.list, andservices.gethost operations. - Return summary-shaped records rather than full internal entities.
- Support pagination and a minimal filter set for list operations.
- Enforce normal
client:readandservice:readpermissions when a user is present. - Allow capability-only tenant-scoped access for non-user contexts.
- Return nullable results for not-found
getoperations.
Non-functional Requirements
- No handler-side HTTP dependency for these reads.
- Stable WIT and TypeScript surface for SDK consumers.
- Clear error semantics for not-allowed, invalid-input, and internal failures.
- Provider behavior must be unit testable without UI or HTTP routing.
Data / API / Integrations
- Extend extension runner WIT with
clientsandservicesinterfaces. - Extend
sdk/extension-runtimehost bindings and mocks. - Add runner capability providers for both interfaces.
- Extract or factor shared read services from the current client and service action layers.
Likely internal reuse points:
packages/clients/src/actions/clientActions.tspackages/billing/src/actions/serviceActions.ts
Security / Permissions
- Install capability grant is mandatory.
- User-backed executions must also pass the existing RBAC checks.
- Non-user executions may read tenant-scoped data when the install capability is granted.
- Extensions cannot override tenant id in capability input.
Observability
- Provider calls should emit structured runner logs for capability name, tenant, extension, result count, and error type.
- Failures should distinguish capability denial, RBAC denial, invalid input, and internal query failure.
Rollout / Migration
- Add the new capabilities behind normal manifest capability declarations.
- Ship a sample extension that exercises the new host APIs.
- Keep existing HTTP-based patterns working; this is additive.
Open Questions
- Include tags in client summaries in v1 or defer.
- Include currency-specific prices in service summaries in v1 or defer.
- Decide whether future write support should be separate capabilities.
Acceptance Criteria (Definition of Done)
- Extensions can read clients through a typed host capability without HTTP.
- Extensions can read services through a typed host capability without HTTP.
- User-backed execution respects existing
client:readandservice:readpermissions. - Non-user execution works when the install capability is granted.
- The SDK exposes typed bindings and mock bindings for both capabilities.
- Runner/provider tests cover user, non-user, denial, invalid input, not-found, and tenant isolation cases.
- A sample extension demonstrates end-to-end usage.