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

3.5 KiB

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. 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:
    {
      "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:
    {
      "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:
    {
      "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).