Using the HTTP client (recommended)
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 /health — verification 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.