01
Control plane
DID, key, schema, chain-relationship, and audit capabilities are exposed as ConnectRPC services. State lives in YAML and files, and a node may run as a pure registry with no pipeline loops.
source ↗IMPLEMENTATION SPECIFICATIONS
This page reads the provin OSS code, dependencies, and defaults as an implementation snapshot—not a roadmap. It states not only what is selected, but what each choice guarantees at runtime and what remains outside that guarantee.
SYSTEM SHAPE
A standalone node composes a control plane for registry and coordination with a data plane for event processing from one configuration. Evidence crossing both can be taken away from the live node and verified independently. Note: the standalone layout is as of this snapshot — it has since been retired; current main splits the planes into the cmd/network + cmd/pipeline binaries (see CHANGELOG).
01
DID, key, schema, chain-relationship, and audit capabilities are exposed as ConnectRPC services. State lives in YAML and files, and a node may run as a pure registry with no pipeline loops.
source ↗02
Source, Chained, Sink, and Custom processes pass events over NATS and repeat verify, transform, and sign. Each process is a peer following the same contract.
source ↗03
Credentials, audit verdicts, transparency-log entries, and receipts are retained append-only and can be exported as a bundle for offline verification. Transport trust is distinct from provenance verification.
source ↗SELECTION CATALOG
Versions come from go.mod and generator configuration at this snapshot. Rationale is limited to responsibilities and behavior that can be confirmed in the code.
| Area | Selection | Implementation effect | Current boundary |
|---|---|---|---|
| Runtime | Go 1.25.5 | The standalone node and provin operator CLI build from one module, sharing concurrency, standard-library TLS, and built-in testing. | Artifacts are dist/standalone and dist/provin (as of the snapshot — standalone has since been retired in favor of cmd/network + cmd/pipeline). No database or second language runtime is mandatory. source ↗ |
| Service API | Protobuf + Buf v2 + ConnectRPC | Service contracts live in dplaax.*.v1 protobuf packages, generating Go types and Connect handlers. Buf uses STANDARD lint and FILE-level breaking checks. | Services share one HTTP listener. API compatibility is managed through v1 packages and breaking checks. source ↗ |
| Event transport | Core NATS · server 2.12.6 / Go client 1.50.0 | Subject-based pub/sub decouples processes; operator/account JWTs grant cross-organization subjects. A FlushTimeout after publish confirms broker receipt. | This is not JetStream. There is no durable queue, redelivery, or exactly-once behavior; the residual delivery guarantee is at-most-once. source ↗ |
| Transformation | JSONata 1.5.4 + JSON Schema 2020-12 | Configuration compiles filters and a converter, while schemas validate input and output boundaries. JSONata expressions compile at startup. | Chained processing is stateless one-in/one-out. Stateful aggregation belongs on the Source/aggregate side. source ↗ |
| Credential proof | W3C VC Data Integrity + Ed25519 | A signed credential records content hashes, process, time, and predecessor rather than embedding the payload. eddsa-jcs-2022 is the default suite. | Ed25519 is the only signing key type. P-256 and P-384 are outside the current PoC. source ↗ |
| Canonicalization | RFC 8785 JCS + URDNA2015 | Equivalent JSON representations become the same signing input. JCS is default; the RDFC suite uses embedded JSON-LD contexts and URDNA2015. | JSON-LD contexts are never fetched at runtime. Integers over 2^53 in RDFC @json values must be represented as strings. source ↗ |
| Identity & keys | did:dplaax + delegation credentials | An Owner → Pipeline → Process hierarchy resolves issuers, authentication keys, and delegated authority. Process signing keys remain in registry custody. | The current keystore is file/YAML based. Vault, HSM, and cloud KMS are interface targets, not shipped integrations. source ↗ |
| Configuration & state | HOCON + YAML / files | reference.conf, application.conf, and an environment overlay are layered in order. Reference stores keep control state and evidence in YAML/files; storage and PDP remain interface boundaries. | The provin node can run without a database. A database-backed registry is not shipped; the selected auth provider, PDP, or adapter may have its own database requirements. source ↗ |
| Observability | OpenTelemetry 1.44 + Prometheus | Emit, verification, audit-verdict, and related counters use OTel and can be exposed in Prometheus format at /metrics. | The metrics endpoint is disabled by default. No tracing backend or dashboard is embedded as a product dependency. source ↗ |
PIPELINE RUNTIME
The order from reception to onward publish is the execution contract that preserves provenance continuity and payload identity. An input that becomes unverifiable does not produce the next credential.
Evaluate predecessor Data Integrity, signer authenticity, and chain consistency.
Synchronously retain evidence required for later verification; fail when it cannot be stored.
Obtain inline or by-reference payload bytes.
Compare payload SHA-256 with the content hash declared by the credential.
When configured, validate the structure before transformation.
Run JSONata filters in order; a mismatch is recorded as an intentional drop.
Use JSONata to transform one input into one output.
When configured, validate the transformed structure.
Reject duplicate keys and trailing data while retaining numbers as json.Number.
Fix both sides of the processing step as content-addressed values.
Carry exactly one previousCredential and extend a linear chain.
Notify the observer, publish to the primary subject, then append the emission log after success.
Only ConfidenceVerified advances on a producing process. Failed and indeterminate verdicts close the path as errors.
Core NATS publish plus flush confirms broker receipt, but it does not provide consumer redelivery or persistence.
A stop after publish but before log append leaves a delivered-but-unlogged gap. File log records durable intent first, preventing number reuse; a flush timeout after broker acceptance can still look failed and permit reuse.
CONCRETE SAMPLE
An E2E walkthrough proves that the whole deployment runs. This fixed sample lets a reviewer inspect the wire shape and result without running the stack. Hashes and proofValue are abbreviated for display.
01 / INPUT
POST /ingest/src/push
{"sensor":"temp-01","celsius":21.5} 02 / FIRSTDROP CREDENTIAL — EXCERPT
{
"issuer": "did:dplaax:…:pipeline:readings:process:s1",
"credentialSubject": {
"pipelineId": "readings",
"processId": "s1",
"transformationClaim": "provin:convert",
"inputHash": "sha256:3b8…",
"outputHash": "sha256:3b8…"
},
"proof": {
"type": "DataIntegrityProof",
"cryptosuite": "eddsa-jcs-2022",
"proofValue": "z…"
}
} 03 / VERIFICATION RESULT — EXCERPT
{
"confidence": "CONFIDENCE_VERIFIED",
"axes": {
"dataIntegrity": "CONFIDENCE_VERIFIED",
"signerAuthenticity": "CONFIDENCE_VERIFIED",
"chainConsistency": "CONFIDENCE_VERIFIED"
}
} A FirstDrop issued by a Source Process has no previousCredential. The next Chained Process adds previousCredential and extends a line satisfying outputHash[n] == inputHash[n+1].
The grammar of a claim like "provin:convert" in this sample (a single token) is fixed by dPLaaX; what asserting it warrants is normatively defined by the provin wire profile. The core is closure: a closed claim warrants that the declared inputs are the output’s complete information source, which is what licenses exclusion inferences ("this lot cannot be in that output").
provin:filter | closed — declared inputs are the complete information source |
provin:convert | closed |
provin:filter-convert | closed |
provin:aggregate | closed fold over the declared input set |
provin:enrich | conformant-closed — exclusion holds for conformant flows only |
provin:generate | open — information beyond the declared inputs is acknowledged |
provin:sink-receipt | identity — a receipt, not a transformation |
PROOF & CANONICALIZATION
The credential body is the single source of truth. Proof configuration and document are canonicalized and hashed separately, then concatenated. Unknown signed-scope fields remain in the body map, so re-encoding does not silently discard them.
Data Integrity signing input
hashData = SHA-256(canon(proofConfig)) ‖ SHA-256(canon(document))
proofValue = base58btc(Ed25519.sign(hashData)) source ↗ Canonicalizes JSON with RFC 8785 JCS and signs with Ed25519. This is the Phase 1 required suite.
RDFC suite using embedded contexts and URDNA2015. External context fetching is forbidden at runtime.
Avoids duplicate keys, trailing data, and implicit float64 conversion. Lint constrains signed JSON to one decode path.
previousCredential is singular. Payloads are not embedded; input and output hashes bind content to the record.
The verifier evaluates data integrity, signer authenticity, and chain consistency. The weakest result on the failed < indeterminate < verified lattice becomes the overall verdict.
TRUST BOUNDARIES
Whether a request may enter, whether a peer is authentic, and whether the data provenance is valid are different questions. provin handles them as three layers with different evidence and failure conditions.
| Layer | Protected boundary | Mechanism | Failure behavior |
|---|---|---|---|
| L1 · Service authorization | Administration and registry APIs | Bearer token → PDP, enforced by protobuf method-policy annotations and PEP interceptors. The default o3co backend verifies JWTs. | Missing configuration stops startup. An empty static allow-list means deny all. |
| L2 · Peer wire proof | ChainPeer and Payload services | Ed25519 signs a JCS view of signerDID, operation, nonce, issuedAt, and fields; the authentication key resolves from DID. | Checks time window, one-time nonce, and restart epoch. There is no auth-off mode. |
| L3 · Provenance evidence | The data itself | Credential chain, content hashes, transparency log, and audit verdicts verify provenance independently of transport trust. | A failed or unresolved axis closes the producing path. |
o3co verifies JWTs. OPA relies on policy to perform authentication; Cedar receives a raw bearer principal unless policy adds validation; static checks token presence or an allow-list only. Backend labels must not be treated as equivalent assurance.
Post-signature record changes, payload/content-hash mismatches, declared-chain discontinuity, and unauthorized signers or requests fail closed at their respective boundaries.
Issuer key custody, DID registry and resolution, verifier trust policy, transport confidentiality, clocks, and nonce operation support parts of the guarantee.
Correctly signed false data, unrecorded processing, a compromised authorized key, and guessing low-entropy payload hashes are not prevented by the chain alone. A repository-wide threat model remains post-public-release work.
CONFIGURATION & EVIDENCE
The provin node can run on YAML and files alone, while storage and PDP boundaries remain replaceable interfaces. Configuration, control state, evidence, and ephemeral state stay distinct; external requirements follow the selected auth provider, PDP, and adapter.
Complete embedded defaults. There are no hidden Go-side defaults.
Optional node-specific settings override reference values when present.
The selected environment overlay is applied last before decoding into typed configuration.
Registry state for DID, pipeline/process, schemas, and chain configuration.
Credential variants, resolution pool, audit queue/verdicts, receipts, and sink rejects. Credentials are content-addressed and append-only.
Wire-auth nonces and related ephemeral state. A restart-epoch barrier closes cross-restart replay, but this is not a nonce store shared across nodes.
provin bundle export collects credentials and dependent evidence; provin bundle verify validates them with no network access. JSON-LD contexts are embedded in the binary. Evidence is rotated to cold archive rather than deleted or mutated.
source ↗The current implementation replays a hash-chained file log to detect modification. A CT-style log with Merkle inclusion and consistency proofs is staged work, not part of the present guarantee.
source ↗OPERATIONS
Defaults lean toward local and bounded operation, while the table also identifies PoC behavior that operators must account for.
| Item | Default / implementation | Operational meaning |
|---|---|---|
| Listen address | 127.0.0.1:8443 | Loopback by default; the node is not implicitly exposed. |
| HTTP mode | cleartext h2c on loopback | Non-loopback requires node-native TLS or explicit allow-cleartext behind an isolated TLS terminator. |
| TLS | minimum 1.2 | Go standard-library secure cipher defaults. Certificate rotation requires restart; there is no hot reload. |
| Health | /healthz · /readyz | Liveness and readiness are separate. |
| Metrics | /metrics · default off | Exposes OpenTelemetry counters in Prometheus format when enabled. |
| Data-plane dependency | Core NATS | Process-event transport. JetStream durable queues and redelivery are not used. |
| Authorization dependency | external PDP or static | o3co, OPA, and Cedar use an external PDP. Static is an in-process allow-list, not authentication. Auth-provider storage follows the selected implementation. |
| Durable state | YAML / files · unbounded by default | Back up the data directory and monitor disk. Relationship evidence can be rotated to cold archive while the node is stopped. |
| Resource sizing | not published | Minimum CPU, memory, disk, throughput, and latency recommendations are not published. Small container-limit E2E runs establish a lower bound; repeatable benchmarks are separately required for steady-state performance. |
| Credential / push limit | 1 MiB / 1 MiB | Credential and request-body sizes are bounded. |
| Resolver worker | 30s · batch 64 · retry 5 · depth 1024 | Re-evaluates unresolved chains in bounded batches with retry and depth limits. |
| Audit runner | 30s · batch 64 · attempts 10 | Processes the audit queue in bounded batches. |
Commands cover owner init, pipeline/process create, schema registration, chain-relationship management, organization verify/diagnose, bundle export/verify, and evidence rotation. Owner private keys are RFC 8037 OKP JWK files written with mode 0600.
IMPLEMENTATION BOUNDARY
Only code confirmed in the 0.x / PoC snapshot is labeled implemented. Staged work expresses direction, not an availability promise.
| Area | Current state | How to evaluate it |
|---|---|---|
| Public release | provin OSS v0.3.0 and public E2E v0.2.0 are available. The technical detail on this page reflects the pinned 2026-07-17 snapshot; the node has since been reorganized into separate cmd/network + cmd/pipeline binaries (see CHANGELOG). | Because this is a 0.x PoC, evaluate the public artifact and E2E in the intended environment. |
| Compatibility | The credential Data Integrity wire is frozen. Go APIs, configuration, and other signed views remain mutable in 0.x. The freeze scope and its enforcement are detailed in the "wire freeze" section below. | Evaluate wire and API stability separately even though both carry a 0.x version. |
| Security maintenance | After publication, only the latest minor line is assessed and fixed. There is no SLA or bug-bounty program. | Do not assume production support or backports. |
| Governance | Maintainer-led (1o1 Co. Ltd.). GOVERNANCE.md defines the next-MAJOR procedure for wire changes and the path to a broader maintainer group. | Maintainership does not yet span multiple organizations. See GOVERNANCE.md for the procedure; continuity still requires review. |
| Operational evidence | Conformance vectors, W3C vectors, KATs, and E2E tests exist; production soak and public benchmarks do not. | Reproduce the intended topology and workload before adoption. |
The v0 credential Data Integrity wire — every byte that participates in a credential signature — is frozen. What holds the freeze is not a declaration or a process but tests in the repository: the official W3C vc-di-eddsa vectors, KATs, and sha256-pinned contexts.
Changing any of the above breaks proof compatibility with already-issued credentials and is a next-MAJOR change. The procedure is defined in GOVERNANCE.md.
Each is pinned by its own golden tests, and compatibility-relevant changes are called out in the CHANGELOG. Being able to state what is not frozen is what makes the frozen scope credible.
This site’s claim that evidence remains verifiable after the original system is gone rests on this freeze being fixed by tests. Future verifiability cannot be demonstrated in advance — the grounds are that the frozen scope and its enforcement are public.
This boundary prevents “extensible” from being confused with “available now.” Evaluate a pinned commit in the intended environment before making a deployment decision.
Open the pinned commit on GitHub