EnfinitOSEnfinitOS
DevelopersOperator & brand
Production-ready scaffold

Operator Web SDK

React component library — embed the EnfinitOS operator surfaces (rights, proof, billing, pacing, pilots) in your own admin UI.

@enfinitos/sdk-operator-webSubstrate ALLTypeScript
Install

Get the SDK

npm install @enfinitos/sdk-operator-web

About this status badge

Typed, tested, documented, and grounded in the 2026 platform reality. Awaiting first customer-integration validation.

README

The developer-facing documentation in full

Rendered from packages/sdks/operator-web/README.md at build time — the same source the package ships with.

@enfinitos/sdk-operator-web

EnfinitOS Operator Web SDK — a React component library that tenants embed in their own admin UIs to surface the EnfinitOS operator surfaces (rights registry, proof centre, compliance flows, billing, pacing, pilots) without rebuilding the dashboards that ship in apps/web/app/_workspace/.

Who should use this. Any tenant who: - already has an admin UI (Cloudflare-style, AWS-Console-style, or a custom React-based shell) and wants to drop EnfinitOS panels inside their chrome rather than iframe a third-party dashboard; - has their own identity/SSO and wants to issue short-lived JWTs to the SDK without going through the platform's login flow; - prefers a small, themeable, white-label-ready component library over a hosted Workspace experience.

Architecture

        ┌──────────────────────────────────────────────────┐
        │                Tenant Admin UI                   │
        │       (React/Next.js/Remix/Vite — host's choice) │
        │                                                  │
        │  ┌────────────────────────────────────────────┐  │
        │  │           <OperatorProvider>               │  │
        │  │  client = new EnfinitOSOperatorClient(…)   │  │
        │  │                                            │  │
        │  │   ┌────────────────────────────────────┐   │  │
        │  │   │  ThemeProvider (CSS variables,     │   │  │
        │  │   │  tenant-overridable tokens)        │   │  │
        │  │   │                                    │   │  │
        │  │   │   <RightsRegistryPanel/>           │   │  │
        │  │   │   <ProofExplorer/>                 │   │  │
        │  │   │   <ProofVerifier                   │   │  │
        │  │   │      auditorVerify={…}/>           │   │  │
        │  │   │   <PacingDashboard/>               │   │  │
        │  │   │   <UsageMeter/>                    │   │  │
        │  │   │   <DsarRequestForm/>               │   │  │
        │  │   │   <PilotEnrolmentFlow/>            │   │  │
        │  │   └────────────────────────────────────┘   │  │
        │  └────────────────────────────────────────────┘  │
        │                       │                          │
        └───────────────────────┼──────────────────────────┘
                                │  HTTPS, JWT auth
                                │  X-Org-Id, Accept-Version
                                ▼
        ┌──────────────────────────────────────────────────┐
        │             EnfinitOS Platform API               │
        │                                                  │
        │  /v1/rights              /v1/proof               │
        │  /v1/offers              /v1/compliance/{dsar,…} │
        │  /v1/challenges          /v1/billing/{invoices…} │
        │  /v1/consent             /v1/pacing/health       │
        │                          /v1/pilot/enrolment     │
        └──────────────────────────────────────────────────┘

The SDK has no compile-time dependency on apps/api, apps/web, or any other EnfinitOS package. It speaks the public REST contract via Accept-Version negotiation and re-states the contract types in src/types.ts so tenants can install the SDK without dragging in the platform's internal schemas.

Installation

pnpm add @enfinitos/sdk-operator-web
# or: npm install @enfinitos/sdk-operator-web

Peer dependencies (provided by the host):

  • react ^18.0.0 || ^19.0.0
  • react-dom ^18.0.0 || ^19.0.0

The SDK pulls in zero runtime UI libraries — no MUI, no Chakra, no Ant Design, no Tailwind. Components ship with inline styles driven by CSS variables; tenants override those variables to brand the SDK to their own chrome.

5-minute getting started

import {
  EnfinitOSOperatorClient,
  OperatorProvider,
  RightsRegistryPanel,
} from "@enfinitos/sdk-operator-web";

const client = new EnfinitOSOperatorClient({
  apiBaseUrl: "https://api.enfinitos.com",
  orgId: "org_acme",
  authToken: () => fetchYourJwt(),   // sync or async
  // optional:
  timeoutMs: 10_000,
  retries: 3,
});

export function AdminRightsPage() {
  return (
    <OperatorProvider client={client}>
      <RightsRegistryPanel />
    </OperatorProvider>
  );
}

That's it. The panel paginates, filters by status / substrate, opens a detail card on click, and exposes lifecycle actions (suspend / resume / revoke) inline.

Theming

The SDK reads a flat dictionary of CSS variables prefixed with --enfinitos-. Override any subset via the tokens prop on <OperatorProvider> or <ThemeProvider>:

<OperatorProvider
  client={client}
  tokens={{
    "--enfinitos-color-brand": "#0066cc",
    "--enfinitos-color-brand-fg": "#ffffff",
    "--enfinitos-color-text": "#1a1a1a",
    "--enfinitos-color-surface": "#ffffff",
    "--enfinitos-color-surface-alt": "#f4f6f8",
    "--enfinitos-color-border": "#e2e8f0",
    "--enfinitos-font-family": "Inter, sans-serif",
  }}
>
  …
</OperatorProvider>

CSS-variable reference

TokenDefaultPurpose
--enfinitos-color-brand#2563ebPrimary brand colour — buttons, links, focus accents.
--enfinitos-color-brand-fg#ffffffText on top of brand.
--enfinitos-color-accent#7c3aedSecondary highlight (rare).
--enfinitos-color-success#16a34aStatusBadge, success rows.
--enfinitos-color-warning#d97706Warning state.
--enfinitos-color-danger#dc2626Errors, destructive actions.
--enfinitos-color-info#0284c7Info chips.
--enfinitos-color-neutral#64748bNeutral chips.
--enfinitos-color-bg#0f172aPage background (if SDK is the root).
--enfinitos-color-surfacedark glassCard surface.
--enfinitos-color-surface-altdark glassAlt rows / hover.
--enfinitos-color-borderdim slateBorders.
--enfinitos-color-text#e2e8f0Primary text.
--enfinitos-color-text-muted#94a3b8Secondary text.
--enfinitos-color-text-inverse#0f172aText on inverse surfaces.
--enfinitos-font-familysystem stackBody font.
--enfinitos-font-family-monomono stackIDs / hashes.
--enfinitos-font-size-{xs,sm,md,lg,xl}11–20pxTypography scale.
--enfinitos-font-weight-{regular,medium,bold}400/500/600Font weight.
--enfinitos-space-{0..6}0–32pxSpacing scale.
--enfinitos-radius-{sm,md,lg}6/10/14Radius scale.
--enfinitos-shadow-{sm,md,lg}layeredDrop-shadows.
--enfinitos-focus-ringbrand glowFocus outline.
--enfinitos-motion-{fast,medium}120/240msAnimation timing.

Tenants who already use design tokens (Tailwind, Radix Colors, a custom system) typically write a one-liner mapping their token names onto --enfinitos-* and inherit their brand automatically.

Component catalogue

Rights Registry

ComponentWhat it renders
<RightsRegistryPanel/>Top-of-page panel: status-counts header, filter strip (status + substrate + search), paginated list (<DataTable/>), per-row click handler. Suspends to <RightDetailCard/> on selection.
<RightDetailCard/>Full right detail: status badge, scope label, basis link, full rules dump, provenance chain, action buttons (suspend / resume / revoke).
<ComposeRuleForm/>Rule-composition form covering every BehaviourRule kind (max-speed, exclusion zones, age-gate, consent-required, territory restrict, custom). Used to issue rights or counter-offer.
<ChallengeInbox/>Open challenges list, per-row resolve / withdraw, rationale textarea.

Proof Centre

ComponentWhat it renders
<ProofExplorer/>Paginated proof-record list with filter by type + rightId, expandable per-row payload viewer, signature preview.
<ProofExportButton/>One-click signed-export trigger; opens the resulting archive URL when ready.

Verification Centre

ComponentWhat it renders
<ProofVerifier/>Server-side verification result for a chain. If a auditorVerify callable is provided (typically @enfinitos/sdk-auditor), it runs a second-opinion verification client-side and displays both results.

Compliance

ComponentWhat it renders
<DsarRequestForm/>GDPR Art. 15 (Data Subject Access Request) form: subject ref, note, submit + status polling.
<ErasureRequestForm/>GDPR Art. 17 (erasure) form. Surfaces BLOCKED reason when legal basis conflicts.
<ConsentRecordsList/>Paginated subject-consent list, revocation action inline.

Pacing

ComponentWhat it renders
<PacingDashboard/>Grid of <DeliveryHealthCard/> per scope, auto-refreshes on a tenant-configurable interval.
<DeliveryHealthCard/>Single scope: pace index, render success rate, p95 resolve latency, pending impressions. Colour-coded by paceIndex.

Billing

ComponentWhat it renders
<UsageMeter/>Bar chart for usage meters with used / included / cap. Shows percentage and remaining budget.
<InvoiceList/>Paginated invoice table, status badge, due-by, line items expandable.
<SettlementBreakdown/>Per-settlement split table: party, percentage, amount.

Pilot

ComponentWhat it renders
<PilotEnrolmentFlow/>Multi-step enrolment form for first-time tenants: cohort selection, contract upload, primary-contact details.
<PilotCohortBadge/>Single pill conveying the current pilot cohort + tier.

Shared building blocks (composable on their own)

ComponentWhat it renders
<Card/>The SDK's analogue of cp-glass-card — section label, title, subtitle, toolbar slot, body.
<DataTable/>Typed, accessible table: column renderers, sort indicators, keyboard navigation, empty state.
<StatusBadge/>Status pill with colour + dot. Includes a statusKindFor(status) helper to map domain enums.
<SignedEvidenceCard/>Surfaces a signed export: digest, signer, signature preview, download link.
<AsyncBoundary/>Loading / error / data renderer for the SDK's async hooks.
<EmptyState/>Title + body + CTA for zero-row lists.

API client reference

Top-level construction:

const client = new EnfinitOSOperatorClient({
  apiBaseUrl: "https://api.enfinitos.com",
  orgId: "org_acme",
  authToken: "ey…",                   // or () => Promise<string>
  timeoutMs: 10_000,
  retries: 3,
  fetchImpl: customFetch,             // optional override
  userAgentTag: "acme-admin/1.2.3",   // optional, appended to X-Operator-Web-SDK
});

Sub-API surface:

client.rights      → list / get / issue / suspend / resume / revoke /
                     statusCounts / family / provenance / listBases
client.offers      → listInbox / get / propose / accept / reject /
                     counter / withdraw
client.challenges  → listOpen / get / open / resolve / withdraw
client.proof       → list / get / chain / verify / exportSigned
client.consent     → list / get / issue / revoke / check
client.compliance  → listDsar / getDsar / fileDsar / listErasure /
                     fileErasure
client.billing     → listInvoices / getInvoice / listSettlements /
                     getSettlement / listMeters
client.pacing      → listHealth / getHealth
client.pilot       → getEnrolment / enrol / listCohorts

Every method returns the unwrapped data from the platform's envelope; non-2xx responses throw an OperatorApiError carrying the platform's RFC-7807-ish code/message/details triple.

Retry policy

  • 5xx and 429 responses retry up to retries times (default 3).
  • 4xx responses (other than 429) are fatal — they throw immediately.
  • Backoff is exponential with a small jitter to spread retry storms.
  • A network/timeout error is treated as retryable.

Auth

authToken accepts either a static string or a callable returning a string | Promise<string>. The callable form is invoked on every request so a tenant can rotate tokens without reconstructing the client (and it slots cleanly into OAuth-refresh flows).

Cancellation

Every request races an AbortSignal against the configured timeoutMs. The hook layer (useAsync) also wires an abort signal so deps-changes cancel in-flight calls.

Hooks

For tenants that want the SDK's React-flavoured data layer rather than rolling their own:

useRightsList(filter)        // → AsyncResult<Page<Right>>
useRight(rightId)            // → AsyncResult<{ right, provenance } | null>
useRightFamily(rightId)      // → AsyncResult<{ ancestors, descendants } | null>
useRightsStatusCounts()      // → AsyncResult<Record<RightStatus, number>>
useProofList(opts)           // → AsyncResult<Page<ProofRecord>>
useProofChain(headProofId)   // → AsyncResult<ProofChain | null>
useConsentList(subjectRef)   // → AsyncResult<Page<ConsentRecord>>
useConsentCheck(input)       // → AsyncResult<{ granted, consentId }>
useInvoices(opts)            // → AsyncResult<Page<Invoice>>
useSettlements(opts)         // → AsyncResult<Page<Settlement>>
useUsageMeters()             // → AsyncResult<Page<UsageMeter>>
usePacingHealth(opts)        // → AsyncResult<DeliveryHealth[]>

Every hook returns { data, error, loading, refreshing, refetch }, shaped to plug into <AsyncBoundary state={…}> without ceremony.

Tenants who want raw control reach for useOperatorClient() and hit the typed client directly.

Sample integration — minimal viable operator dashboard

A complete, copy-pasteable 30-line dashboard:

import {
  EnfinitOSOperatorClient,
  OperatorProvider,
  RightsRegistryPanel,
  ProofExplorer,
  PacingDashboard,
  UsageMeter,
  InvoiceList,
  DsarRequestForm,
} from "@enfinitos/sdk-operator-web";

const client = new EnfinitOSOperatorClient({
  apiBaseUrl: process.env.NEXT_PUBLIC_ENFINITOS_API!,
  orgId: process.env.NEXT_PUBLIC_ENFINITOS_ORG!,
  authToken: async () => (await fetch("/api/jwt")).text(),
});

export default function OperatorDashboard() {
  return (
    <OperatorProvider client={client} tokens={{ "--enfinitos-color-brand": "#0066cc" }}>
      <div style={{ display: "grid", gap: 24, padding: 24 }}>
        <RightsRegistryPanel />
        <PacingDashboard refreshIntervalMs={30_000} />
        <UsageMeter />
        <InvoiceList />
        <ProofExplorer />
        <DsarRequestForm />
      </div>
    </OperatorProvider>
  );
}

Verification gate

Components that render signed evidence (proof records, signed exports) accept an optional auditorVerify prop typed against @enfinitos/sdk-auditor. The SDK does NOT pull the auditor as a hard dep — tenants on edge-runtime hosts (Cloudflare Workers, Vercel Edge) opt-in only when they have the crypto primitives available.

import { verifyChain } from "@enfinitos/sdk-auditor";

<ProofVerifier headProofId="p_abc123" auditorVerify={verifyChain} />

What's SDK-side vs platform-side

ConcernThis SDKPlatform
REST contract typesmirrored verbatim in src/types.tssource-of-truth in apps/api/src/modules/*/contracts
Auth — JWT issuance / SSONOT part of SDKreuses the platform's /auth/* plane
Theming / brandingtenant-overridable CSS variablesn/a (platform's Workspace is a separate skin)
Pacing datarenders via client.pacing.listHealth()apps/api/src/modules/pacing/routes.ts
Audit log persistencethe platform writes; the SDK readsplatform-owned
Offline proof verificationoptional via auditorVerify prop + @enfinitos/sdk-auditorplatform also verifies on /v1/proof/:id/verify

Accessibility

  • Every interactive element has an explicit aria-label or visible label.
  • All clickable rows are keyboard-activatable (Enter / Space) with tabIndex=0 and role="button".
  • Status badges use role="status" with a sensible aria-label.
  • Focus rings honour --enfinitos-focus-ring so tenants can keep brand contrast.
  • Async boundaries announce loading + error states via role="status" and role="alert" so screen readers track state changes.

Versioning

  • The SDK ships SDK_VERSION (semver) and CONTRACT_VERSION (an ISO date matching the platform's accepted contract). Every REST call sends both as headers (X-Operator-Web-SDK, Accept-Version).
  • The platform pins responses to the negotiated contract version — a newer platform never returns shapes the SDK can't parse.

See also

  • packages/sdks/auditor-ts — independent signature verifier you can wire into <ProofVerifier auditorVerify={…}/>.
  • packages/sdks/robotics-ts — the reference SDK for the ROBOTICS substrate (this Operator SDK speaks the same BehaviourRule union).
  • apps/web/app/_workspace/ — first-party operator dashboard rendered against the same API surface; useful as a worked example.
  • docs/launch/substrate-readiness-matrix.md — per-substrate readiness status.
API reference

Hit the HTTP surface directly

The Operator Web SDK is a thin client over the same governed HTTP API every other SDK calls. The full OpenAPI 3.1 reference lives on the docs site.

Sandbox

Run this SDK against a real tenant

The hosted sandbox is the fastest way to verify Operator Web SDK against a real EnfinitOS tenant before committing to a pilot. Launching Q4 2026.