Skip to main content
The HTTP client (@parmanasystems/sdk-client) calls a running Parmana server. This is the standard integration pattern for application services.
npm install @parmanasystems/sdk-client
import { ParmanaClient, ParmanaApiError } from "@parmanasystems/sdk-client";

const client = new ParmanaClient({
  baseUrl: process.env.PARMANA_URL ?? "http://localhost:3000",
  apiKey: process.env.PARMANA_API_KEY,
});

async function main() {
  // Perform authority verification
  const attestation = await client.execute({
    executionId: "txn-20240115-001",   // unique per business transaction
    policyId: "payment-approval",
    policyVersion: "1.0.0",
    signals: {
      amount: 4500,
      currency: "USD",
      accountAge: 730,
      fraudScore: 0.02,
    },
  });

  console.log(attestation.decision.action);         // "approve" | "reject"
  console.log(attestation.execution_state);         // "completed" | "pending_override"
  console.log(attestation.execution_fingerprint);   // SHA-256 of canonical signals
  console.log(attestation.signature);               // Ed25519 signature

  // Verify independently
  const result = await client.verify(attestation);
  console.log(result.valid);  // true
}

main().catch(console.error);

Using the core SDK (in-process)

Run the governance engine directly in your process — no server required.
npm install @parmanasystems/core
import crypto from "crypto";
import {
  executeFromSignals,
  verifyAttestation,
  LocalSigner,
  LocalVerifier,
  MemoryReplayStore,
} from "@parmanasystems/core";

async function main() {
  // Generate keys — use stored keys in production
  const { privateKey, publicKey } = crypto.generateKeyPairSync("ed25519", {
    privateKeyEncoding: { type: "pkcs8", format: "pem" },
    publicKeyEncoding:  { type: "spki",  format: "pem" },
  });

  const signer   = new LocalSigner(privateKey);
  const verifier = new LocalVerifier(publicKey);
  const store    = new MemoryReplayStore();  // use RedisReplayStore in production

  const { attestation } = await executeFromSignals(
    {
      executionId:   "txn-20240115-001",
      policyId:      "payment-approval",
      policyVersion: "1.0.0",
      signals: {
        amount:      4500,
        currency:    "USD",
        accountAge:  730,
        fraudScore:  0.02,
      },
    },
    signer,
    verifier,
    undefined,    // runtimeEnvironment — undefined uses default paths
    store         // required — throws [INV-REPLAY-001] if omitted
  );

  console.log(attestation.decision.action);  // "approve"
  console.log(attestation.signature);        // Ed25519 signature

  // Verify
  const result = verifyAttestation(attestation, verifier);
  console.log(result.valid);  // true
}

main().catch(console.error);
MemoryReplayStore loses all state on process restart and does not work across multiple processes. In production, use RedisReplayStore.

Production replay store

import { RedisReplayStore } from "@parmanasystems/core";

const store = new RedisReplayStore(
  process.env.REDIS_URL!,   // e.g. "redis://localhost:6379"
  {
    reservationTtlSeconds: 300,   // default
    failedTtlSeconds: 30,         // default
  }
);

Client method reference

All methods on ParmanaClient:
// Runtime
client.health()                     → Promise<HealthResult>
client.runtimeManifest()            → Promise<RuntimeManifestResult>
client.runtimeCapabilities()        → Promise<RuntimeCapabilitiesResult>

// Decisions
client.execute(request)             → Promise<ExecutionAttestation>
client.verify(attestation)          → Promise<VerificationResult>
client.evaluate(request)            → Promise<EvaluateResult>      // dry run — no attestation
client.simulate(request)            → Promise<SimulateResult>      // full pipeline dry run

// Post-execution
client.confirmExecution(request)    → Promise<ExecutionIntegrityProof>

// Audit (sub-namespace)
client.audit.decisions(params?)     → Promise<DecisionRow[]>
client.audit.decision(executionId)  → Promise<DecisionDetail>
client.audit.stats()                → Promise<AuditStats>
client.audit.security(params?)      → Promise<SecurityEventRow[]>
There is no client.override() method. To approve or reject a pending override, call POST /override directly using client._request() or fetch. See Override Workflow.

Error handling

try {
  const attestation = await client.execute({ ... });
} catch (err) {
  if (err instanceof ParmanaApiError) {
    console.error(`HTTP ${err.status}: ${err.message}`);

    if (err.status === 422) {
      // Execution failed — check error message for [INV-*] error code
    } else if (err.status === 429) {
      // Rate limited — back off and retry
    } else if (err.status === 401) {
      // Bad or missing API key
    }
  }
}
See Error Handling for the full error code reference.

Troubleshooting

ParmanaApiError: HTTP 503 — The server’s signer is not configured. Check GET /healthverification should be "ok". ParmanaApiError: HTTP 422 with [INV-013@replay] — The executionId was already used. Use a new, unique ID. Do not retry with the same ID. result.valid is false — Do not proceed with the authorized action. Check result.checks to identify which verification check failed. Network error (not ParmanaApiError) — The server is unreachable. Check that the server is running and baseUrl is correct.