A typed HTTP client for @parmanasystems/server. Use this when your application calls a remote governance server rather than running governance in-process.
Install
npm install @parmanasystems/sdk-client
Setup
import { ParmanaClient } from "@parmanasystems/sdk-client";
const client = new ParmanaClient({
baseUrl: "https://governance.your-domain.com",
apiKey: process.env.PARMANA_API_KEY, // optional — for authenticated deployments
});
apiKey is sent as a Bearer token. Omit it if your server doesn’t require authentication.
Execute a decision
const attestation = await client.execute({
policyId: "loan-approval",
policyVersion: "1.0.0",
signals: {
credit_score: 720,
loan_amount: 15000,
},
});
console.log(attestation.decision.action); // "approve"
console.log(attestation.signature); // Ed25519 over the canonical payload
Verify a decision
Sends the attestation to the server’s /verify endpoint and returns a breakdown of every check:
const result = await client.verify(attestation);
console.log(result.valid); // true
console.log(result.checks.signature_verified); // Ed25519 check
console.log(result.checks.bundle_verified); // policy bundle hash check
client.verify() calls the server. To verify an attestation locally — with only the public key and no server access — use verifyAttestation from @parmanasystems/core or @parmanasystems/verifier directly.
Evaluate without executing
Check what a policy would decide for a given set of signals, without producing an attestation or consuming a replay slot:
const evaluation = await client.evaluate({
policyId: "loan-approval",
policyVersion: "1.0.0",
signals: { credit_score: 720, loan_amount: 15000 },
});
console.log(evaluation.wouldDecide); // "approve"
console.log(evaluation.ruleMatched); // "approve-standard"
console.log(evaluation.reason);
Simulate the full pipeline
Runs the full execution pipeline — including signing — without side effects. Returns a preview shaped like a real attestation:
const sim = await client.simulate({
policyId: "loan-approval",
policyVersion: "1.0.0",
signals: { credit_score: 720, loan_amount: 15000 },
});
console.log(sim.decision.action); // "approve"
console.log(sim.wouldSign); // true
console.log(sim.attestationPreview); // preview of what the attestation would look like
Confirm execution
Verify that a real-world action matches its governance authorization and produce a signed ExecutionIntegrityProof:
const proof = await client.confirmExecution({
attestation,
executedAction: {
type: "LOAN_DISBURSED",
payload: { amount: 15000, account: "ACC-12345" },
executedAt: new Date().toISOString(),
executedBy: "disbursement-service",
},
timeWindowSeconds: 300, // optional, default: 300
});
console.log(proof.match); // true — action matches its authorization
console.log(proof.integrityHash); // SHA-256 linking authorization to action
Health check
const health = await client.health();
console.log(health.status); // "ok"
console.log(health.runtimeVersion); // e.g. "1.0.0"
console.log(health.capabilities); // ["replay-protection", "ed25519-signing", ...]
Runtime manifest
const manifest = await client.runtimeManifest();
console.log(manifest.runtimeHash); // SHA-256 of the runtime definition
console.log(manifest.supported_schemaVersions); // e.g. ["1.0.0"]
Audit namespace
client.audit exposes the server’s audit log:
// Paginated decision timeline
const decisions = await client.audit.decisions({
limit: 50,
policyId: "loan-approval",
decision: "approve", // "approve" | "deny" | "any"
from: "2025-01-01T00:00:00Z",
to: "2025-12-31T23:59:59Z",
});
// Single decision detail
const detail = await client.audit.decision("execution-id-here");
console.log(detail.attestation); // full attestation JSON
console.log(detail.signature_verified); // "verified" | "failed" | "unknown"
// Aggregate counts
const stats = await client.audit.stats();
console.log(stats.total_decisions);
console.log(stats.valid_verifications);
// Security events
const events = await client.audit.security({ limit: 20 });
Error handling
Every non-2xx response throws a ParmanaApiError. Check .status for the HTTP status code and .message for the error text returned by the server:
import { ParmanaClient, ParmanaApiError } from "@parmanasystems/sdk-client";
try {
const attestation = await client.execute({ ... });
} catch (error) {
if (error instanceof ParmanaApiError) {
console.error(error.status); // HTTP status, e.g. 400, 409, 422
console.error(error.message); // server error message
}
}
Common HTTP statuses:
| Status | Meaning |
|---|
400 | Malformed request body or invalid signals |
409 | Replay detected — same fingerprint already executed |
422 | Policy not found or signals failed schema validation |
500 | Internal server error |
See also