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
115 lines
4.6 KiB
Markdown
115 lines
4.6 KiB
Markdown
# 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 `IClient` or `IService` shapes.
|
|
- 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.read` and `cap:service.read`.
|
|
- Add `clients.list`, `clients.get`, `services.list`, and `services.get` host operations.
|
|
- Return summary-shaped records rather than full internal entities.
|
|
- Support pagination and a minimal filter set for list operations.
|
|
- Enforce normal `client:read` and `service:read` permissions when a user is present.
|
|
- Allow capability-only tenant-scoped access for non-user contexts.
|
|
- Return nullable results for not-found `get` operations.
|
|
|
|
### 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 `clients` and `services` interfaces.
|
|
- Extend `sdk/extension-runtime` host 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.ts`
|
|
- `packages/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:read` and `service:read` permissions.
|
|
- 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.
|