Documentation

Build with Orbis Relay

Everything you need to ask “may I do this?” before your software acts — and to prove what happened afterwards.

Quickstart

1. Create a key in Developer → API keys (the demo sandbox key works out of the box). 2. Call preflight right before the risky step. 3. Execute only what Orbis authorized, then report the outcome.

TypeScript
import { OrbisClient } from "@orbis/sdk";
const orbis = new OrbisClient({ apiKey: process.env.ORBIS_API_KEY!, baseUrl: "http://localhost:4310" });

const decision = await orbis.preflight({ actor, action, resources, destination, intent });
if (decision.isAllowed()) await execute();
else if (decision.requiresApproval()) {
  const final = await decision.waitForResolution({ timeoutMs: 600_000 });
  if (final.approved) await execute(final.approvedParameters);
}
await orbis.reportOutcome(decision.actionId, "succeeded");
Python
from orbis_relay import OrbisClient
orbis = OrbisClient(api_key=os.environ["ORBIS_API_KEY"], base_url="http://localhost:4310")
d = orbis.preflight(actor=..., action=..., resources=[...], destination=..., intent=...)
if d.is_allowed: execute()
elif d.requires_approval:
    final = d.wait_for_resolution(timeout=600)
    if final.approved: execute(final.approved_parameters)

Action envelope

Describe the action, not its payload. Orbis never needs raw documents or secrets — send classifications, counts, amounts and a redacted summary. The tenant is derived from your API key, never from the body.

POST /v1/decisions/preflight
{
  "request_id": "req_01J…",            // idempotency key
  "actor": { "type": "agent", "id": "procurement-agent", "owner": "finance" },
  "action": { "type": "external_send", "tool": "llm.summarize", "arguments_summary": "4 vendor contracts" },
  "resources": [{ "type": "document", "classification": "confidential", "count": 4 }],
  "destination": { "type": "external_model", "value": "quickscribe-ai.app" },
  "intent": { "reason": "Respond to vendor RFP", "source": "agent" },
  "business_context": { "deal_id": "D-82" },
  "signals": { "incident_active": false },
  "evidence": [{ "label": "Data class", "value": "Confidential — pricing terms", "source": "DLP" }],
  "blast_radius": ["4 contracts leave the trust boundary"],
  "ttl_seconds": 600
}

Decision states

received → evaluating → allow | warn | deny | approval_required
approval_required → pending → approved | approved_modified | rejected | expired | cancelled
final authorization → outcome: succeeded | failed | not_executed | unknown

approved_modified means a human edited parameters or chose a safe alternative. Always execute with approved_parameters — e.g. the redirected destination.

Policy model

Policies are versioned rule sets. Published versions are immutable; drafts are simulated against real history and published with a second admin. Every enabled policy is evaluated; the most severe matching effect wins: allow < allow_log < warn < require_confirmation < require_approval < require_quorum < deny < freeze. A frozen actor is always denied.

rule
{
  "id": "ext_model_confidential",
  "when": { "all": [
    { "field": "destination.type", "op": "eq", "value": "external_model" },
    { "field": "resource.classification_rank", "op": "gte", "value": 2 },
    { "field": "destination.approved", "op": "neq", "value": true } ] },
  "effect": "require_approval", "route": "ai-governance", "step_up": "biometric",
  "safe_alternatives": [{ "id": "redirect_internal_model", "type": "redirect",
    "apply": { "destination": "northstar-private-llm" } }]
}

The risk score (0–100) prioritizes and routes. It never overrides a hard rule, and core enforcement never calls a model.

Approval lifecycle

Approvals route to a group (resource owner, role, on-call). The server verifies assignment, tenant, state, expiry and required step-up before any response mutates state. SLA escalation fires at 50% of TTL; quorum rules require N distinct approvers; any rejection rejects. Push notifications carry only a title and a deep link.

Receipts

Every final decision yields a receipt: canonical JSON (sorted keys) signed with Ed25519, plus its SHA-256. Reporting an outcome issues revision 2, which commits to revision 1's hash. Verify with POST /v1/receipts/:id/verify, offline with the JWK at /v1/receipts/public-key, or on the verifier page.

Webhooks

Orbis-Signature header
Orbis-Signature: t=1791234567,v1=5f2b…   // HMAC-SHA256(secret, t + "." + rawBody)

import { verifyWebhookSignature } from "@orbis/sdk";
if (!(await verifyWebhookSignature(secret, req.headers["orbis-signature"], rawBody))) return 401;

Reject if the timestamp is more than 5 minutes old, compare in constant time, and dedupe on Idempotency-Key. Callback URLs must be public https endpoints — private, loopback and link-local addresses are rejected.

Agent adapter

TypeScript
import { createAgentAdapter } from "@orbis/sdk";
const adapter = createAgentAdapter(orbis, { type: "agent", id: "procurement-agent" });
const summarize = adapter.wrap({
  name: "llm.summarize",
  classify: (a) => ({ action: { type: "external_send" }, resources: [{ type: "document", classification: a.classification, count: a.docs.length }],
                      destination: { type: "external_model", value: a.provider } }),
  applyApproved: (a, p) => ({ ...a, provider: String(p.destination ?? a.provider) }),
  run: (a) => llm.summarize(a),
});
// Denials throw ToolBlockedError — the agent can explain and re-plan.

Endpoint intelligence

An optional macOS endpoint runtime (apps/macos-endpoint, Swift + Core ML) scores each action locally from privacy-preserving metadata. Destinations are hashed on the device and content never leaves it. The gateway also scores every action itself. The edge risk model is advisory: deterministic policy decides first, and the model can only raise an outcome (allow → warn → approval), never lower one. It is ignored when unavailable, stale, incompatible or killed, and that rule is recorded on the decision and the receipt.

Attach a local signal to a preflight (what orbis-endpoint does)
POST /v1/decisions/preflight
{ …envelope,
  "endpoint_signal": { "endpoint_id": "ep_procurement-agent_host",
    "signal": { "model_version": "1.0.0", "feature_schema": "edge-features/1", "class": "high_risk",
                "risk": 0.99, "abstain": false, "runtime": "coreml-fp32", "reasons": [ … ] } } }

→ "ml": { "source": "local+cloud", "model": "orbis-edge-risk@1.0.0", "class": "high_risk",
          "explanation": "High risk because sensitive data is going to an unverified destination…",
          "fusion": { "rule": "deterministic_approval_wins", "changed": false } }

Endpoints fetch an Ed25519-signed manifest (GET /v1/endpoint/models/manifest). It is bound to a tenant, feature schema, minimum app version, expiry and a monotonic sequence. The endpoint verifies the artifact sha256, compiles and smoke-tests the model, and activates it atomically. Model mutations (/v1/ml/models/:v/promote, /rollback, /v1/ml/settings) need an admin role, passkey step-up and a passing release-gate report. Analyst labels from POST /v1/ml/review/:prediction_id are exported with GET /v1/ml/feedback/export for offline retraining; they never change the live model. See Console → Intelligence for the registry, evaluation, fleet, drift and review queue.

Errors

{ "error": { "code": "step_up_required", "message": "…", "remediation": "Complete Face ID and resubmit." } }

401 unauthenticated · invalid_key · key_revoked     403 not_assigned · forbidden · device_not_trusted
404 not_found     409 already_resolved · idempotency_conflict     410 expired
413 payload_too_large     422 validation_error · field_not_editable · out_of_range     428 step_up_required

API reference

Machine-readable contract: /api/v1/openapi (OpenAPI 3.1).

POST/v1/decisions/preflightEvaluate a proposed action before it executes
POST/v1/approvalsCreate a human approval explicitly
GET/v1/approvalsApprover inbox / console queue
GET/v1/approvals/{id}Read status and safe display context
POST/v1/approvals/{id}/respondAuthorized response; server verifies assignment, state, expiry and step-up
POST/v1/approvals/{id}/cancelCaller withdraws a pending approval
GET/v1/actionsSearch actions and their decisions/outcomes
POST/v1/actions/{id}/outcomeCaller reports execution outcome (idempotent)
GET/v1/receipts/{id}Fetch the final signed decision receipt
POST/v1/receipts/{id}/verifyVerify receipt integrity (stored or supplied copy)
GET/v1/receipts/public-keyEd25519 JWK set for offline verification
GET/v1/actorsActor registry with freeze state
POST/v1/actors/{id}/freezeFreeze an actor — gateway denies all new requests
DELETE/v1/actors/{id}/freezeUnfreeze with permission and audit reason
GET/v1/policiesList policies and versions
POST/v1/policies/simulateRun a candidate policy against historical actions
PUT/v1/policies/{id}/draftSave draft (published versions are immutable)
POST/v1/policies/{id}/publishPublish draft with second approver
POST/v1/webhooks/testValidate a callback endpoint and preview the signed request
GET/v1/audit/eventsSearch the tenant audit trail
GET/v1/audit/verifyRecompute the audit hash chain
POST/v1/protect/analyzeExplicit user-submitted URL/text/QR/screenshot-text risk analysis
POST/v1/auth/deviceOrbis iOS sign-in + device registration (demo SSO)
GET/v1/meCurrent user, device and permissions
GET/v1/streamServer-Sent Events for live updates
GET/v1/endpoint/models/manifestEd25519-signed model manifest for this endpoint (production or canary by bucket). Header X-Orbis-Endpoint.
GET/v1/endpoint/models/signing-keyPublic Ed25519 key (JWK) for model manifests
GET/v1/endpoint/models/{name}/{version}/artifactRedirect to the zipped .mlpackage (integrity from the signed manifest sha256)
POST/v1/endpoint/models/{name}/{version}/activation-resultReport activation success/failure (signature, hash, compile, smoke test)
POST/v1/endpoint/healthEndpoint health snapshot (latency, memory, failures); may trigger automatic canary rollback
POST/v1/endpoint/events/batchPrivacy-filtered telemetry batch (summary fields only)
GET/v1/ml/modelsModel registry: lifecycle, release gates, parity, benchmarks, lineage
GET/v1/ml/models/{id}One model version
GET/v1/ml/models/{id}/evaluationMachine-readable evaluation report
POST/v1/ml/models/{id}/promotePromote to shadow / canary / production (admin + step-up + passing gates)
POST/v1/ml/models/{id}/rollbackRoll back to the previous production model (step-up)
POST/v1/ml/settingsFusion mode (off/advisory/escalate) and model kill switch (step-up)
GET/v1/ml/driftFeature/prediction PSI per 7-day window, OOD rate, behavioural drift, retrain trigger
GET/v1/ml/qualityPrediction mix, abstention, policy/human disagreement, confirmed FP/FN
GET/v1/ml/endpointsFleet: active vs assigned model, health, activations
GET/v1/ml/reviewActive-review queue
POST/v1/ml/review/{id}Analyst label for a prediction (enters the next dataset version, never the live model)
GET/v1/ml/feedback/exportJSONL of reviewed labels with canonical events (input to orbis_ml retrain)