Skip to main content

Documentation

SDKs & clients

The two SDK families — app SDKs for building, client SDKs for consuming — the five gates in every language, and the package & version reference.

Two SDK families

The platform ships two kinds of SDK, and picking the right one is the first decision.

App SDKs are for building a platform-native app — a service that mounts tiered routers, resolves tenant context, applies access gates, and emits events through the outbox. There are two — a Python backend runtime (egav-app-sdk) and a TypeScript SDK (@egav/app-sdk) for React frontends — plus the shared Python platform clients you compose alongside them. All of that lives on the App SDKs page.

Client SDKs are for consuming the platform from an existing program in any language — headless OIDC login, an authenticated retrying JSON client that decodes the standard BaseResponse envelope, and the five access gates ported natively. There are four, each with its own page: Go, Rust, PHP, and Node. They deliberately omit the app-building runtime (no app factory, tenant middleware, outbox, or scoped CRUD) — that lives in the app SDKs.

FamilySDKUse it toPage
App runtimeegav-app-sdk (Python)Build a backend app: tier routers, gates, outbox, scoped CRUDApp SDKs
App SDK@egav/app-sdk (TypeScript)Build a React app: manifest parsing, tenant context, feature gates, field widgets, ApiClientApp SDKs
Shared clientsegav-authz-client, egav-cp-client, …Compose auth, config, audit and notifications into a Python appApp SDKs
Clientgithub.com/djokodonev/egav-sdk-goCall the platform from GoGo
Clientcrate egav-sdkCall the platform from RustRust
Clientegav/sdkCall the platform from PHPPHP
Client@egav/sdkCall the platform from NodeNode

The distinction is stated in the client SDKs themselves — for example, the Go SDK's README notes the app-building runtime "lives in the Python (egav-app-sdk) and TypeScript (@egav/app-sdk) app SDKs. This package is for programs that consume the platform from Go."

The five gates, in any language

Every client SDK ships the same five access gates, applied in the same order to protect an endpoint:

  1. auth — validate the inbound end-user bearer, returning the resolved identity.
  2. permission — AuthZ confirms the user may perform the action.
  3. subscription-active — the org's subscription is active.
  4. feature — the org's plan enables the feature.
  5. quota — the org is under its plan limit for the metric.

Two credentials, correct trust model — no shortcut: the end-user bearer is used only for gate 1; the app's service x-api-key is used for gates 2–5 (the /internal/* endpoints are service-to-service). Every gate fails closed — an unreachable Control Plane or AuthZ raises 503 rather than default-allowing. The Auth & the five gates page covers the request-time model in depth.

The method surface is the same shape in every language; each client page shows the exact signatures:

GateGoRust / PHPFailed-gate status
authAuthenticateauthenticate401
permissionRequirePermissionrequire_permission / requirePermission403
subscriptionRequireActiveSubscriptionrequire_active_subscription / requireActiveSubscription402
featureRequireFeaturerequire_feature / requireFeature403
quotaEnforceQuotaenforce_quota / enforceQuota429

Any unreachable dependency (Control Plane, AuthZ) is 503 on every gate — refused, never degraded to allow.

Inside a Python backend app the same contract is composed from FastAPI dependencies — RequireAuthz from egav_authz_client (which authenticates the portal bearer and checks the permission in one dependency) plus require_active_subscription / require_feature / require_quota from egav_cp_client.feature_gates (see App SDKs):

routes.pypython
from fastapi import APIRouter, Depends, Request
from egav_authz_client import RequireAuthz
from egav_cp_client.feature_gates import (
    require_active_subscription, require_feature, require_quota,
)

router = APIRouter()

async def project_count(request: Request) -> int:
    return await count_projects(request.state.identity.org_guid)

@router.post(
    "/v1/my-saas/portal/projects",
    dependencies=[
        Depends(RequireAuthz("project", "create")),                          # auth + permission -> 401/403
        Depends(require_active_subscription),                                 # subscription      -> 402
        Depends(require_feature("projects")),                                 # feature           -> 403
        Depends(require_quota("max_projects", current_usage=project_count)),  # quota             -> 429
    ],
)
async def create_project(payload: ProjectCreate):
    return await save_project(payload)

Package & version reference

Every identifier below is taken from the SDK's own manifest (pyproject.toml, package.json, go.mod, Cargo.toml, composer.json). Use these exact names; nothing here is aspirational.

SDKPackage / moduleImportVersionDistribution
Python app runtimeegav-app-sdkimport egav_app_sdk0.2.0GitHub tarball or local pip install -e (not on PyPI)
TypeScript app SDK@djokodonev/egav-app-sdk (alias @egav/app-sdk)from '@egav/app-sdk'0.31.0GitHub Packages (npm.pkg.github.com), restricted
Go clientgithub.com/djokodonev/egav-sdk-goimport egavsdk "github.com/djokodonev/egav-sdk-go"v0.1.0public GitHub repository, tagged; go get resolves through the module proxy
Rust clientcrate egav-sdk (lib egav_sdk)use egav_sdk::...0.1.0path dependency; crates.io publish pending
PHP clientegav/sdk (Egav\Sdk\)use Egav\Sdk\...0.1.0Composer path repository; Packagist publish pending
Node client@djokodonev/egav-sdk (alias @egav/sdk)from '@egav/sdk'0.1.0GitHub Packages (npm.pkg.github.com), restricted

A note on honesty. The Node client is published to GitHub Packages and installs from there with a read:packages token — a restricted registry, so a bare npm install from the public index still will not find it. The Go client is public and tagged (v0.1.0), so go get works with no extra setup. The Rust and PHP clients remain pre-publication: their import paths are stable, but no registry install is live yet, so they wire in via path / Composer-path steps. When those are tagged and published, this table gets version dependencies and those steps drop away — the import lines in your code will not change. The per-language pages (Go, Rust, PHP, Node) carry the full install + worked example for each.