PSA/ee/docs/extension-system/storage-api-contract.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

94 lines
3.5 KiB
Markdown

# Extension Storage API Contract
> **Status:** Archived. The extension-scoped contract has been superseded by the tenant storage service.
The authoritative API contract, resource model, and request/response semantics are maintained in the [Alga Storage Service documentation](../../../docs/storage-system.md). That specification applies uniformly to extensions, workflows, and any other integration consuming the storage platform.
If you are migrating existing extension code:
- Remove any dependency on `extension_install_id` scoping—the service now keys data by tenant and namespace only.
- Adopt the optimistic concurrency and TTL guidance documented in the official spec.
Legacy details from the Phase 1 extension rollout are intentionally omitted here to avoid divergence from the shared platform documentation.
- Request body:
```jsonc
{
"namespace": "settings",
"key": "invoice-defaults",
"ifRevision": 13
}
```
- Response: HTTP 204 with no body on success.
- Errors mirror `REVISION_MISMATCH` and `NOT_FOUND`.
### `storage.bulkPut`
- Request body:
```jsonc
{
"namespace": "settings",
"items": [
{
"key": "invoice-defaults",
"value": { /* JSON payload */ },
"metadata": {},
"ttlSeconds": 86400,
"ifRevision": null
}
]
}
```
- Constraints:
- Max 20 items per call, cumulative payload ≤ 512 KiB.
- Fails fast with `BULK_PARTIAL_FAILURE` if any record violates validation/quota.
- Response mirrors `storage.put` for each item:
```jsonc
{
"items": [
{
"key": "invoice-defaults",
"revision": 13,
"ttlExpiresAt": "2025-10-08T19:00:00Z"
}
]
}
```
## Concurrency & Consistency
- Each record maintains a `revision` counter starting at 1. Writes increment revision atomically.
- `ifRevision` guards enforce optimistic concurrency; Runner returns `409 REVISION_MISMATCH` if mismatch.
- Reads are strongly consistent; `storage.get` returns the latest committed record.
- `storage.list` guarantees results consistent with the snapshot at query start (transactional).
## TTL and Expiration Semantics
- Extensions may set `ttlSeconds` (min 60, max 30 days). Absent TTL implies indefinite retention subject to quota.
- Expired records are soft-deleted on access (reads/writes) by the opportunistic cleanup hook.
- `ttlExpiresAt` is returned so clients can monitor refresh cycles.
## Error Codes (Shared)
| Code | HTTP Status | Description |
|------|-------------|-------------|
| `REVISION_MISMATCH` | 409 | Optimistic concurrency failure |
| `QUOTA_EXCEEDED` | 429 | Namespace or tenant quota exceeded |
| `VALIDATION_FAILED` | 400 | JSON Schema validation error details |
| `NOT_FOUND` | 404 | Record not found or expired |
| `UNAUTHORIZED` | 403 | Missing `alga.storage` capability |
| `RATE_LIMITED` | 429 | Global rate limiting triggered |
| `INTERNAL_ERROR` | 500 | Unexpected server failure |
## Runner Integration Surface
- Internal endpoint: `POST /api/internal/ext-storage/install/{installId}` guarded by `RUNNER_STORAGE_API_TOKEN`.
- Body schema matches the contracts above with an added `operation` field (e.g., `{ "operation": "put", ... }`).
- Responses mirror the public REST endpoints so the runner can forward them directly to guest code.
## Open Items
- Define JSON Schema registration flow (see Phase 1 validation strategy).
- Confirm pagination cursor encoding (opaque Base64 vs. encrypted token).
- Decide SDK default behavior for `includeValues` on list (likely false).