SDK Reference

Complete guide to the Primust SDKs — Python, JavaScript, Java, and C#. Everything you need to instrument governance and produce VPECs.

SDKPackageRegistryMin Runtime
PythonprimustPyPIPython 3.10+
JavaScript@primust/sdknpmNode 18+ / Edge
Javacom.primust:primust-sdkMaven CentralJava 17+
C#Primust.SDKNuGet.NET 8+

Installation

Python

Shellpip install primust

JavaScript / TypeScript

Shellnpm install @primust/sdk

Java (Maven)

XML<dependency>
  <groupId>com.primust</groupId>
  <artifactId>primust-sdk</artifactId>
  <version>1.0.0</version>
</dependency>

Java (Gradle)

Gradleimplementation 'com.primust:primust-sdk:1.0.0'

C# (NuGet)

Shelldotnet add package Primust.SDK --version 0.1.0

Environment Variable

All SDKs read PRIMUST_API_KEY from the environment if no key is passed to the constructor.

Shellexport PRIMUST_API_KEY=pk_sb_xxx
API Key Prefixes

pk_sb_ — sandbox, free, rate-limited. pk_live_ — production, requires paid plan. The SDK auto-detects environment from the key prefix.

Run Lifecycle

Every SDK follows the same three-step pattern:

  1. Open — create a Pipeline and open a Run
  2. Record — record one or more check executions against the Run
  3. Close — close the Run to produce a VPEC
Pythonfrom primust import Pipeline

pipeline = Pipeline(api_key="pk_sb_xxx", workflow_id="loan_review")
run = pipeline.open()

result = run.record(
    check="pii_scan",
    manifest_id="manifest_pii_v2",
    check_result="pass",
    input=document_bytes,              # raw bytes — committed locally, never transmitted
    output=scan_result_bytes,          # optional output commitment
    visibility="opaque",               # default for all regulated data
)

vpec = run.close()                     # VPEC issued — run sealed
print(vpec.vpec_id)                    # vpec_a1b2c3...
print(vpec.is_clean())                 # True if chain intact and no gaps
JavaScriptimport { Pipeline } from '@primust/sdk';

const pipeline = new Pipeline({ apiKey: 'pk_sb_xxx', workflowId: 'loan_review' });
const run = await pipeline.open();

const result = await run.record('pii_scan', 'manifest_pii_v2', 'pass', documentBytes, {
  output: scanResultBytes,
  visibility: 'opaque',
});

const vpec = await run.close();
console.log(vpec.vpecId);             // vpec_a1b2c3...
console.log(vpec.gaps);     // []
Javaimport com.primust.sdk.*;

Pipeline pipeline = Primust.builder()
    .apiKey("pk_sb_xxx")
    .workflowId("loan_review")
    .build();

Run run = pipeline.open();

RecordResult result = run.record(RecordInput.builder()
    .check("pii_scan")
    .manifestId("manifest_pii_v2")
    .checkResult(CheckResult.PASS)
    .input(documentBytes)
    .output(scanResultBytes)
    .visibility(VisibilityMode.OPAQUE)
    .build());

VPEC vpec = run.close();
System.out.println(vpec.vpecId());     // vpec_a1b2c3...
System.out.println(vpec.isClean());    // true
C#using Primust;

var pipeline = new Pipeline("pk_sb_xxx", "loan_review");
var run = pipeline.Open();

var result = await run.RecordAsync(new RecordInput
{
    Check = "pii_scan",
    ManifestId = "manifest_pii_v2",
    CheckResult = CheckResult.Pass,
    Input = documentBytes,
    Output = scanResultBytes,
    Visibility = "opaque",
});

var vpec = await run.CloseAsync();
Console.WriteLine(vpec.VpecId);        // vpec_a1b2c3...
Console.WriteLine(vpec.IsClean);       // True
Immutable After Close

Once close() is called, the Run is sealed. Calling record() after close throws an InvalidOperationException (C#), IllegalStateException (Java), or Error (Python/JS). Calling close() twice also throws.

Pipeline

The Pipeline is the entry point. It holds your API key, workflow identity, and opens Runs.

Constructor

LanguageSignature
Python Pipeline(api_key=None, workflow_id="default", *, surface_id=None, policy=None, process_context_hash=None, base_url="https://api.primust.com")
JavaScript new Pipeline({ apiKey, workflowId, policy?, processContextHash?, baseUrl?, fetch? })
Java Primust.builder().apiKey(key).workflowId(wf).baseUrl(url).surfaceId(sid).build()
C# new Pipeline(apiKey?, workflowId = "default", baseUrl = "https://api.primust.com")

Parameters

ParameterTypeRequiredDescription
apiKeystringYes*Your Primust API key. Falls back to PRIMUST_API_KEY env var. Throws if neither is set.
workflowIdstringNoIdentifies the workflow/process being governed. Default: "default".
policystring | string[]NoBind this pipeline to specific policy bundle(s). E.g. "eu_ai_act_art12_v1".
processContextHashstringNoExternal process correlation hash for cross-system linkage.
surfaceIdstringNoIdentifies the provable surface this pipeline instruments.
baseUrlstringNoAPI endpoint. Default: https://api.primust.com.

Pipeline Methods

MethodReturnsDescription
open(policyPackId?)RunStart a new Run. Calls POST /api/v1/runs. Returns a Run you can record against.
registerCheck(manifest)ManifestRegistrationRegister a check manifest (content-addressed, idempotent). Python/Java only.
setLogger(callback, options?)voidAttach a SIEM logger callback. Python/JS only. See Logger / SIEM.
testModeboolRead-only property. true when API key starts with pk_sb_. The VPEC output uses the environment field ("sandbox" or "production") instead.
Legacy Pipeline API

Python and JS also expose open_check(), open_review(), record(), and close() directly on Pipeline for backward compatibility. For new code, use the Run API: pipeline.open()run.record()run.close().

Run

A Run represents a single governed execution. Created by pipeline.open(). You record check results against it, then close it to produce a VPEC.

Properties

PropertyTypeDescription
runIdstringUnique run identifier (server-assigned).
workflowIdstringWorkflow this run belongs to.
orgIdstringOrganization that owns this run.
policySnapshotHashstringHash of the policy snapshot at run open time. Python/JS only.
lastCommitmentHashstring?Most recent commitment hash from record(). C# only.

run.record()

Record a governance check execution. The raw input is committed locally via SHA-256 — only the hash transits to api.primust.com.

LanguageSignature
Python run.record(check, manifest_id, check_result, input, *, details=None, output=None, visibility="opaque", check_session=None, reviewer_signature=None, display_content=None, rationale=None)
JavaScript run.record(check, manifestId, checkResult, input, options?)
Java run.record(RecordInput) — see RecordInput
C# await run.RecordAsync(RecordInput) — see RecordInput

Parameters

ParameterTypeRequiredDescription
checkstringYesCheck name. E.g. "pii_scan", "bias_audit".
manifestIdstringYesManifest identifier for this check definition.
checkResultstring | CheckResultYesOutcome of the check. See CheckResult enum.
inputbytesYesRaw input bytes. Committed locally via SHA-256. Never transmitted.
outputbytesNoRaw output bytes. If provided, an output commitment hash is computed.
visibilitystringNoDefault: "opaque". Options: "opaque", "selective", "transparent".
detailsdict/mapNoArbitrary metadata (key-value). Transmitted as-is — do NOT put PII here.
checkSessionCheckSessionNoIf provided, links record to a pre-opened check session (for timestamps).
reviewerSignaturestringNoEd25519 signature from a human reviewer (Witnessed proof level).
displayContentanyNoWhat the reviewer saw. Hashed — raw content never transits.
rationalestringNoReviewer's written rationale. Hashed — raw text never transits.

Returns a RecordResult.

run.close()

Close the Run, triggering VPEC issuance. The run is sealed — no further records can be added.

LanguageSignatureReturns
Pythonrun.close()VPEC
JavaScriptawait run.close()VPECResult
Javarun.close()VPEC
C#await run.CloseAsync()VpecResult

run.openCheck() / run.openReview()

For precise timestamp capture, open a check session before recording. The check_open_tst is captured at open time; check_close_tst at record time.

Python# Standard check with timestamps
session = run.open_check("bias_audit", "manifest_bias_v1")
# ... run your check logic ...
result = run.record("bias_audit", "manifest_bias_v1", "pass", input_bytes,
                     check_session=session)

# Human review with minimum duration enforcement
review = run.open_review("legal_review", "manifest_legal_v1",
                          reviewer_key_id="rev_key_001",
                          min_duration_seconds=1800)  # 30 minutes minimum
# ... reviewer examines content ...
result = run.record("legal_review", "manifest_legal_v1", "pass", input_bytes,
                     check_session=review,
                     reviewer_signature=sig,
                     display_content=what_reviewer_saw,
                     rationale="Approved per policy 4.2.1")
JavaScriptconst session = run.openCheck('bias_audit', 'manifest_bias_v1');
const result = await run.record('bias_audit', 'manifest_bias_v1', 'pass', inputBytes, {
  checkSession: session,
});

const review = run.openReview('legal_review', 'manifest_legal_v1', 'rev_key_001', 1800);
const reviewResult = await run.record('legal_review', 'manifest_legal_v1', 'pass', inputBytes, {
  checkSession: review,
  reviewerSignature: sig,
  displayContent: whatReviewerSaw,
  rationale: 'Approved per policy 4.2.1',
});
Witnessed Proof Level

Using openReview() with a reviewer_signature produces a Witnessed proof level record. This requires two RFC 3161 timestamps (check_open_tst and check_close_tst) and an Ed25519 reviewer signature. The review duration is enforced server-side.

RecordInput

Java and C# use a structured RecordInput object. Python and JS pass parameters directly to run.record().

Java

JavaRecordInput input = RecordInput.builder()
    .check("pii_scan")
    .manifestId("manifest_pii_v2")
    .checkResult(CheckResult.PASS)
    .input(documentBytes)                   // byte[]
    .output(scanResultBytes)                // byte[] (optional)
    .visibility(VisibilityMode.OPAQUE)      // default
    .details(Map.of("scanner_version", "3.1.0"))
    .build();

C#

C#var input = new RecordInput
{
    Check = "pii_scan",
    ManifestId = "manifest_pii_v2",
    CheckResult = CheckResult.Pass,
    Input = documentBytes,                  // byte[]
    Output = scanResultBytes,               // byte[]? (optional)
    Visibility = "opaque",                  // default
    Details = new Dictionary<string, object>
    {
        ["scanner_version"] = "3.1.0"
    },
};

RecordInput Fields

FieldTypeRequiredDefaultDescription
CheckstringYesCheck name identifier.
ManifestIdstringYesManifest this check is declared in.
Inputbyte[]YesRaw input bytes. SHA-256 committed locally.
Outputbyte[]?NonullRaw output bytes. Committed if provided.
CheckResultCheckResultYesEnum value. See CheckResult.
Detailsdict/mapNonullArbitrary metadata. Do NOT put PII here.
VisibilitystringNo"opaque""opaque", "selective", or "transparent".

RecordResult

Returned by record(). Contains the commitment hash (your SIEM linkage anchor), chain hash, and proof level.

FieldTypeDescription
recordIdstringUnique record ID. Format: rec_<uuid>.
commitmentHashstringSHA-256 of the input. Format: sha256:<64 hex chars>. Use this as your SIEM linkage anchor.
outputCommitmentstring?SHA-256 of the output, if output was provided.
commitmentAlgorithmstring"sha256" or "poseidon2".
proofLevelstringProof level achieved for this record.
recordedAtstringISO 8601 timestamp.
chainHashstringRolling hash linking this record to all prior records in the run.
queuedbooltrue if the API was unreachable and the record was queued locally.
Pythonresult = run.record("pii_scan", "manifest_pii_v2", "pass", data)

print(result.record_id)            # rec_a1b2c3d4e5f6...
print(result.commitment_hash)      # sha256:9f86d0818...
print(result.chain_hash)           # sha256:e3b0c4429...
print(result.queued)               # False (API was reachable)

VpecResult / VPEC

Returned by close(). The Verifiable Process Execution Credential.

FieldTypeDescription
vpecIdstringUnique VPEC identifier.
runIdstringThe run this VPEC was issued for.
workflowIdstringWorkflow identity.
orgIdstringOrganization that owns this VPEC.
issuedAtstringISO 8601 issuance timestamp.
proofLevelFloorstringOverall proof level floor (weakest-link across all records).
totalChecksRunintNumber of check records in this run.
checksPassedintRecords with pass result.
checksFailedintRecords with fail result.
gapsGovernanceGap[]List of gaps detected. Empty if clean.
chainIntactbooltrue if the hash chain verified end-to-end.
environmentstring"sandbox" or "production". Determined by the API key prefix.
isCleanbooltrue when chainIntact == true AND gaps is empty.

Python and Java VPECs also include:

FieldTypeDescription
proofLevelBreakdownProofLevelBreakdownCount of records at each proof level.
provableSurfacefloatFloat 0.0–1.0 representing the fraction of the policy surface provably covered by this run.
merkleRootstringMerkle root of all commitment hashes.
signaturestringEd25519 signature over the sealed VPEC.
timestampRfc3161stringRFC 3161 timestamp anchor.
rawdictFull server response for advanced use.

GovernanceGap

FieldTypeDescription
gapIdstringUnique gap identifier.
gapTypestringCanonical gap type. See Gap Taxonomy.
severitystringCritical, High, Medium, Low, or Informational.
checkstring?Check name that produced this gap.
sequenceint?Record sequence number.
timestampstringWhen the gap was recorded.

CheckResult Enum

Every record requires a check_result value. The SDK provides an enum in typed languages; Python and JS accept strings directly.

ValuePythonJavaC#Meaning
passCheckResult.PASSCheckResult.PASSCheckResult.PassCheck passed.
failCheckResult.FAILCheckResult.FAILCheckResult.FailCheck failed.
errorCheckResult.ERRORCheckResult.ERRORCheckResult.ErrorCheck encountered an error during execution.
skippedCheckResult.SKIPPEDCheckResult.SKIPPEDCheckResult.SkippedCheck was skipped (provide skip_rationale).
degradedCheckResult.DEGRADEDCheckResult.DEGRADEDCheckResult.DegradedCheck ran in degraded mode (partial coverage).
overrideCheckResult.OVERRIDECheckResult.OVERRIDECheckResult.OverrideCheck result was overridden by an operator.
not_applicableCheckResult.NOT_APPLICABLECheckResult.NOT_APPLICABLECheckResult.NotApplicableCheck does not apply to this input.
Wire Format

All enums serialize to lowercase snake_case strings on the wire. Java: CheckResult.PASS.value()"pass". C#: CheckResult.Pass.ToWireValue()"pass". Python/JS: pass the string directly.

ProofLevel Enum

Available in Python and Java. Ordered strongest to weakest.

ValuePythonJavaMeaning
mathematicalProofLevel.MATHEMATICALProofLevel.MATHEMATICALZK proof — no trust required.
verifiable_inferenceProofLevel.VERIFIABLE_INFERENCEProofLevel.VERIFIABLE_INFERENCEZKML proof of model inference.
executionProofLevel.EXECUTIONProofLevel.EXECUTIONInstrumented execution with commitment hashing.
witnessedProofLevel.WITNESSEDProofLevel.WITNESSEDHuman reviewer signed with Ed25519.
attestationProofLevel.ATTESTATIONProofLevel.ATTESTATIONOrganization self-declares — weakest level.

Java provides ProofLevel.EXECUTION.isWeakerThan(ProofLevel.MATHEMATICAL) for comparison.

VisibilityMode Enum

Controls what information is disclosed in the VPEC about this record.

ValueDescription
opaqueOnly the commitment hash is visible. Default. Use for all regulated data.
selectiveSpecific fields are disclosed as declared in the manifest.
transparentFull input/output visible in the VPEC. Use only for non-sensitive data.

Privacy Model

The core invariant: raw content never leaves your environment.

When you call record() with input bytes, the SDK computes a SHA-256 hash locally before anything is transmitted. The hash is a one-way function — the original content cannot be recovered from the hash. This is what makes VPECs content-blind.

ConceptualYour System                              api.primust.com
──────────                              ─────────────────
input_bytes ──┐
              ├─ SHA-256 ─→ "sha256:9f86d08..." ──→ stored in VPEC
              │
              └─ stays local (never transmitted)

What Transits Primust

What NEVER Transits Primust

Commitment Format

All commitment hashes are prefixed with the algorithm: sha256:<64 hex chars> (71 characters total) or poseidon2:<hex>. The same input always produces the same hash. Different inputs always produce different hashes.

Verifying a Commitment Locally

You can verify that a commitment hash matches a known input using any SHA-256 implementation:

Pythonimport hashlib
raw_input = b"my_document_content"
expected = "sha256:" + hashlib.sha256(raw_input).hexdigest()
assert result.commitment_hash == expected
JavaScriptimport { createHash } from 'crypto';
const hash = createHash('sha256').update(rawInput).digest('hex');
const expected = `sha256:${hash}`;
console.assert(result.commitmentHash === expected);
Shell# Verify from the command line
echo -n "my_document_content" | sha256sum
# Compare with commitment_hash (strip the "sha256:" prefix)

Error Handling

Fail-Open Design

The SDK is designed to never block your business logic. If the Primust API is unreachable:

Python# API unreachable? Record still succeeds.
result = run.record("pii_scan", "manifest_pii_v2", "pass", data)
if result.queued:
    print("Record queued locally - will sync when API is available")

# Close returns a pending VPEC with a gap
vpec = run.close()
print(vpec.is_clean())    # False - has system_unavailable gap
for gap in vpec.gaps:
    print(f"{gap.gap_type}: {gap.severity}")  # system_unavailable: High

Exceptions

ErrorWhenRecovery
ArgumentErrorMissing API key (no env var, no constructor arg)Set PRIMUST_API_KEY or pass api_key to constructor.
InvalidOperationExceptionrecord() called after close()Open a new Run.
InvalidOperationExceptionclose() called twiceA Run can only be closed once.

RecordSystemError (C#)

The C# SDK provides run.RecordSystemError(message) for logging internal errors without producing a check record. The run remains open.

C#try
{
    var scanResult = await RunPiiScan(document);
    await run.RecordAsync(new RecordInput { /* ... */ });
}
catch (Exception ex)
{
    run.RecordSystemError($"PII scan failed: {ex.Message}");
    // Run stays open - continue with other checks
}

Logger / SIEM Integration

Attach a callback to emit structured log events for every record. This creates an auditable linkage between your application logs and the VPEC — your SIEM becomes a second source of truth.

Pythonimport logging
logger = logging.getLogger("myapp")

def on_primust_record(event):
    logger.info("primust_governance_record", extra={
        "primust_record_id": event.primust_record_id,
        "primust_commitment_hash": event.primust_commitment_hash,
        "primust_check_result": event.primust_check_result,
        "primust_proof_level": event.primust_proof_level,
        "primust_workflow_id": event.primust_workflow_id,
        "primust_run_id": event.primust_run_id,
        "primust_recorded_at": event.primust_recorded_at,
    })

pipeline.set_logger(on_primust_record)
# Optionally include gap types:
# pipeline.set_logger(on_primust_record, LoggerOptions(include_gap_types=True))
JavaScriptpipeline.setLogger((event) => {
  console.log('primust_governance_record', {
    primust_record_id: event.primust_record_id,
    primust_commitment_hash: event.primust_commitment_hash,
    primust_check_result: event.primust_check_result,
    primust_proof_level: event.primust_proof_level,
    primust_workflow_id: event.primust_workflow_id,
    primust_run_id: event.primust_run_id,
    primust_recorded_at: event.primust_recorded_at,
  });
});

// With gap types:
pipeline.setLogger(callback, { includeGapTypes: true });

PrimustLogEvent Fields

FieldTypeDescription
primust_record_idstringRecord ID (rec_...)
primust_commitment_hashstringSHA-256 commitment — the SIEM linkage anchor
primust_check_resultstringCheck result (pass, fail, etc.)
primust_proof_levelstringProof level achieved
primust_workflow_idstringWorkflow identity
primust_run_idstringRun identity
primust_recorded_atstringISO 8601 timestamp
gap_types_emittedstring[]?Gap types (only if includeGapTypes: true)
Auditor Verification via SIEM

An auditor can search your SIEM for primust_commitment_hash = <value>, then run primust-verify hash <plaintext_input> to confirm the hash matches. The VPEC proves chain integrity, timestamp independence, and proof level. Two independent sources — SIEM logs and VPEC — that must agree.

Advanced Patterns

Multiple Records per Run

A run can contain any number of records. Each record gets a unique record_id, its own commitment hash, and a chain hash linking it to all prior records.

Pythonrun = pipeline.open()

# Record multiple governance checks in sequence
run.record("schema_validation", "manifest_schema_v1", "pass", schema_input)
run.record("pii_scan", "manifest_pii_v2", "pass", document_bytes)
run.record("bias_audit", "manifest_bias_v1", "pass", model_output)
run.record("cost_check", "manifest_cost_v1", "pass", cost_data)

vpec = run.close()
print(vpec.total_checks_run)  # 4

Delegation — Cross-System Lineage

When your process delegates to another system, pass a lineage token so the downstream system can continue the governance chain.

Python# System A: delegate to System B
token = pipeline.record_delegation({"target": "system_b", "reason": "sub-process"})

# System B: resume from lineage token
resumed = pipeline_b.resume_from_lineage(token)
print(resumed.run_id)          # same run, continued chain

Local Queue (Python)

The Python SDK includes a durable local queue backed by SQLite. If the API is unreachable, records are queued and flushed automatically on next successful connection.

Pythonfrom pathlib import Path

pipeline = Pipeline(
    api_key="pk_sb_xxx",
    workflow_id="batch_job",
    queue_path=Path("/tmp/primust-queue.db"),
)

# Check pending records
print(pipeline.pending_queue_count())  # 0

# Force flush (usually not needed - auto-flushes on record)
flushed = pipeline.flush_queue()
print(f"Flushed {flushed} queued records")

Manifest Registration

Register check manifests before use. Registration is content-addressed and idempotent — registering the same manifest twice returns the same ID.

Pythonreg = pipeline.register_check({
    "name": "pii_scan",
    "version": "2.0.0",
    "stages": [
        {
            "stage_name": "detect_pii",
            "proof_ceiling": "execution",
            "regulatory_references": ["gdpr_art5", "ccpa_1798"],
        }
    ],
})
print(reg.manifest_id)   # sha256:content_addressed_hash
print(reg.name)          # pii_scan
JavaManifestRegistration reg = pipeline.registerCheck(Map.of(
    "name", "pii_scan",
    "version", "2.0.0",
    "stages", List.of(Map.of(
        "stage_name", "detect_pii",
        "proof_ceiling", "execution",
        "regulatory_references", List.of("gdpr_art5", "ccpa_1798")
    ))
));
System.out.println(reg.manifestId());  // sha256:...

Complete End-to-End Example

Pythonfrom primust import Pipeline, CheckResult
import json

# 1. Create pipeline
pipeline = Pipeline(workflow_id="loan_underwriting_v3")
pipeline.set_logger(lambda e: print(f"[PRIMUST] {e.primust_check_result}: {e.primust_commitment_hash[:30]}..."))

# 2. Open a run
run = pipeline.open(policy_pack_id="financial_data_governance_v1")

# 3. Record checks
# --- Schema validation (deterministic = Mathematical ceiling) ---
schema_input = json.dumps({"applicant_id": "hash_only", "amount": 50000}, sort_keys=True).encode()
run.record("schema_validation", "manifest_schema_v1", CheckResult.PASS, schema_input)

# --- Credit score check (vendor API = Attestation ceiling) ---
credit_input = json.dumps({"bureau": "experian", "pull_type": "soft"}, sort_keys=True).encode()
credit_output = json.dumps({"score_band": "good", "factors": 3}, sort_keys=True).encode()
run.record("credit_check", "manifest_credit_v1", CheckResult.PASS, credit_input,
           output=credit_output)

# --- Human underwriter review (Witnessed ceiling) ---
session = run.open_review("underwriter_review", "manifest_review_v1",
                           reviewer_key_id="rev_key_jane",
                           min_duration_seconds=300)
# ... underwriter reviews for 5+ minutes ...
run.record("underwriter_review", "manifest_review_v1", CheckResult.PASS,
           json.dumps({"decision": "approved"}).encode(),
           check_session=session,
           reviewer_signature=jane_signature,
           display_content=what_jane_saw,
           rationale="Debt-to-income ratio within policy limits")

# 4. Close and get VPEC
vpec = run.close()

print(f"VPEC: {vpec.vpec_id}")
print(f"Proof level floor: {vpec.proof_level_floor}")  # "witnessed" (weakest-link)
print(f"Checks: {vpec.total_checks_run}")        # 3
print(f"Clean: {vpec.is_clean()}")               # True
print(f"Coverage: {vpec.provable_surface:.1%}")    # provable surface (0.0–1.0)
JavaScriptimport { Pipeline } from '@primust/sdk';

const pipeline = new Pipeline({ workflowId: 'loan_underwriting_v3' });
pipeline.setLogger((e) => console.log(`[PRIMUST] ${e.primust_check_result}: ${e.primust_commitment_hash.slice(0, 30)}...`));

const run = await pipeline.open('financial_data_governance_v1');

await run.record('schema_validation', 'manifest_schema_v1', 'pass',
  Buffer.from(JSON.stringify({ applicant_id: 'hash_only', amount: 50000 })));

await run.record('credit_check', 'manifest_credit_v1', 'pass',
  Buffer.from(JSON.stringify({ bureau: 'experian', pull_type: 'soft' })),
  { output: Buffer.from(JSON.stringify({ score_band: 'good', factors: 3 })) });

const session = run.openReview('underwriter_review', 'manifest_review_v1', 'rev_key_jane', 300);
await run.record('underwriter_review', 'manifest_review_v1', 'pass',
  Buffer.from(JSON.stringify({ decision: 'approved' })),
  {
    checkSession: session,
    reviewerSignature: janeSignature,
    displayContent: whatJaneSaw,
    rationale: 'Debt-to-income ratio within policy limits',
  });

const vpec = await run.close();
console.log(`VPEC: ${vpec.vpecId}`);
console.log(`Proof level floor: ${vpec.proofLevelFloor}`);
console.log(`Clean: ${vpec.gaps.length === 0}`);
Javaimport com.primust.sdk.*;
import java.nio.charset.StandardCharsets;

Pipeline pipeline = Primust.builder()
    .workflowId("loan_underwriting_v3")
    .build();

Run run = pipeline.open("financial_data_governance_v1");

run.record(RecordInput.builder()
    .check("schema_validation")
    .manifestId("manifest_schema_v1")
    .checkResult(CheckResult.PASS)
    .input("{\"applicant_id\":\"hash_only\",\"amount\":50000}".getBytes(StandardCharsets.UTF_8))
    .build());

run.record(RecordInput.builder()
    .check("credit_check")
    .manifestId("manifest_credit_v1")
    .checkResult(CheckResult.PASS)
    .input("{\"bureau\":\"experian\",\"pull_type\":\"soft\"}".getBytes(StandardCharsets.UTF_8))
    .output("{\"score_band\":\"good\",\"factors\":3}".getBytes(StandardCharsets.UTF_8))
    .build());

VPEC vpec = run.close();
System.out.println("VPEC: " + vpec.vpecId());
System.out.println("Proof level floor: " + vpec.proofLevelFloor());
System.out.println("Clean: " + vpec.isClean());
C#using Primust;
using System.Text;

var pipeline = new Pipeline(workflowId: "loan_underwriting_v3");
var run = pipeline.Open();

await run.RecordAsync(new RecordInput
{
    Check = "schema_validation",
    ManifestId = "manifest_schema_v1",
    CheckResult = CheckResult.Pass,
    Input = Encoding.UTF8.GetBytes("{\"applicant_id\":\"hash_only\",\"amount\":50000}"),
});

await run.RecordAsync(new RecordInput
{
    Check = "credit_check",
    ManifestId = "manifest_credit_v1",
    CheckResult = CheckResult.Pass,
    Input = Encoding.UTF8.GetBytes("{\"bureau\":\"experian\",\"pull_type\":\"soft\"}"),
    Output = Encoding.UTF8.GetBytes("{\"score_band\":\"good\",\"factors\":3}"),
});

var vpec = await run.CloseAsync();
Console.WriteLine($"VPEC: {vpec.VpecId}");
Console.WriteLine($"Proof level floor: {vpec.ProofLevelFloor}");
Console.WriteLine($"Clean: {vpec.IsClean}");