TypeScript / JavaScript SDK

Package: @salanor/aegis (Node 18+, ESM). Full SDK: ingest, policy proxy, and approvals. Other languages: SDK overview (Python record + policy enforce; Go sign/ingest).

Installation

bash
pnpm add @salanor/aegis

Exports

  • signAndIngest(event, signOptions, ingestOptions) — sign with Ed25519 and POST to ingest
  • wrapFetch(url, init, config) — evaluate policy, ingest decision, then run fetch or throw
  • wrapFetchResume(approvalId, url, init, config) — continue after human approval
  • verifyEventSignature(event, publicKeyB64) — local signature check
  • buildGovernanceInsights(events) — derive audit narrative from event payloads

signAndIngest

Record LLM invocations, human steps, or custom agent actions.

typescript
import { signAndIngest, type ApsEvent } from "@salanor/aegis";

const event: ApsEvent = { /* see Event envelope */ };

const result = await signAndIngest(
  event,
  { privateKeyB64: "…", keyId: "key_…" },
  {
    apiBaseUrl: "https://api.salanor.com",
    ingestApiKey: "aegis_…",
    idempotencyKey: "optional-stable-key",
  },
);
// result: { event_id, status: "created"|"replayed", sequence_num?, event_hash? }

wrapFetch

Use for outbound tools (payments, CRM writes). Policy is evaluated before the HTTP call. A signed policy_decision event is always ingested.

typescript
import { wrapFetch, PolicyDeniedError } from "@salanor/aegis";

try {
  const res = await wrapFetch(
    "https://api.stripe.com/v1/payment_intents",
    { method: "POST", body: "…" },
    {
      context: {
        organizationId: "…",
        agentId: "agt_…",
        keyId: "key_…",
        traceId: "trc_…",
        toolName: "stripe.paymentIntents.create",
        actorPrincipal: "support-agent",
        auditPayload: {
          amount_usd: 249,
          trigger_source: "support_ticket",
          trigger_reason: "Customer refund request",
        },
      },
      sign: { privateKeyB64: "…", keyId: "key_…" },
      ingest: { apiBaseUrl: "https://api.salanor.com", ingestApiKey: "aegis_…" },
    },
  );
} catch (e) {
  if (e instanceof PolicyDeniedError) {
    // Policy blocked — no HTTP call was made
  }
}

Typical agent flow

  1. Generate trace_id per user request or ticket.
  2. Each LLM call → signAndIngest with action_kind: llm_invocation and data_touched in payload.
  3. Each external tool → wrapFetch with a stable tool_name matching console policy rules.
  4. On allow_with_obligation, SDK throws ApprovalRequiredError — poll approval API or use console.