Skip to content

PROV-O Provenance Model

Why Provenance Is Mandatory

Every instance in CKP has a provenance chain: it was generated by an action, which was associated with a kernel, which was started by a task, which was influenced by a goal. This chain makes the system auditable: given any piece of data, you can trace backwards to understand why it exists, who created it, and what process produced it.

CKP uses the W3C PROV-O ontology because it is a well-established standard for provenance that integrates naturally with RDF and SPARQL. PROV-O provides the vocabulary; CKP provides the enforcement.

Non-Optional

Provenance is not a nice-to-have annotation. Instances without provenance are ontologically incomplete -- they fail compliance and cannot be sealed in the DATA loop. The check.provenance compliance check enforces this.

Three Mandatory Fields

Every instance record MUST include these three PROV-O fields:

FieldTypeDescription
prov:wasGeneratedByURILinks instance to the action that created it
prov:wasAttributedToURILinks instance to the kernel that produced it
prov:generatedAtTimexsd:dateTimeTimestamp of creation

These three fields establish the minimum provenance: what created it, who owns it, and when it was created.

Instance Provenance Example

yaml
# storage/instances/i-tx-a8f3c1-1712345678/manifest.json
{
  "instance_id": "i-tx-a8f3c1-1712345678",
  "instance_type": "exchange",
  "prov:wasGeneratedBy": "ckp://Action#Delvinator.Core/exchange.parse-1712345678",
  "prov:wasAttributedTo": "ckp://Kernel#Delvinator.Core:v1.0",
  "prov:generatedAtTime": "2026-04-05T16:37:25Z"
}

Extended Action Provenance

Every action that produces instances SHOULD also include these fields for a richer audit trail:

FieldTypeDescription
prov:wasAssociatedWithURILinks action to the kernel
prov:usedURI[]Links action to its input entities
prov:wasStartedByURILinks action to the task that initiated it
prov:wasInfluencedByURILinks action to the goal

Action Provenance Example

yaml
# storage/proof/proof-exchange.parse-1712345678.json
{
  "action_urn": "ckp://Action#Delvinator.Core/exchange.parse-1712345678",
  "prov:wasAssociatedWith": "ckp://Kernel#Delvinator.Core:v1.0",
  "prov:wasStartedBy": "ckp://Task#T-a1b2c3d4",
  "prov:wasInfluencedBy": "ckp://Goal#G-e5f6g7h8",
  "prov:startedAtTime": "2026-04-05T16:37:24Z",
  "prov:endedAtTime": "2026-04-05T16:37:25Z"
}

Three-Factor Audit Chain

The full audit chain for any instance traces through three factors:

Instance
  +-- prov:wasGeneratedBy -> Action
       +-- prov:wasAssociatedWith -> Kernel
       +-- prov:wasStartedBy -> Task
            +-- prov:wasInfluencedBy -> Goal

This chain answers four questions:

QuestionAnswer FromPROV-O Link
What was created?Instance(the entity itself)
How was it created?Actionprov:wasGeneratedBy
Who created it?Kernelprov:wasAssociatedWith
Why was it created?Task -> Goalprov:wasStartedBy -> prov:wasInfluencedBy

Tracing a Complete Chain

Given an instance, trace backwards:

1. Instance: i-tx-a8f3c1-1712345678
   prov:wasGeneratedBy -> ckp://Action#Delvinator.Core/exchange.parse-1712345678

2. Action: exchange.parse-1712345678
   prov:wasAssociatedWith -> ckp://Kernel#Delvinator.Core:v1.0
   prov:wasStartedBy -> ckp://Task#T-a1b2c3d4

3. Task: T-a1b2c3d4
   prov:wasInfluencedBy -> ckp://Goal#G-e5f6g7h8

4. Goal: G-e5f6g7h8
   "Improve exchange parsing accuracy by formalizing quality scoring"

The chain is unbroken from data to intent.

Enforcement via check.provenance

Enforcement is through the check.provenance compliance check in CK.ComplianceCheck. A kernel that produces instances without PROV-O fields MUST fail compliance.

What check.provenance Validates

CheckFailure Condition
prov:wasGeneratedBy presentInstance has no link to its creating action
prov:wasAttributedTo presentInstance has no link to its owning kernel
prov:generatedAtTime presentInstance has no creation timestamp
prov:wasGeneratedBy URI is validAction URN does not match CKP URN scheme
prov:wasAttributedTo URI matches kernelInstance attributed to a different kernel than where it is stored

Compliance Failure

Instances without the three mandatory PROV-O fields are rejected by check.provenance. This is not a warning -- it is a hard failure. The instance cannot be sealed, the proof chain is broken, and the kernel's compliance score drops.

Consensus Decision Provenance

Every consensus decision is itself a prov:Activity:

yaml
prov:Activity:
  id: "ckp://Instance#CK.Consensus/decision-2026-04-06T20:00:00Z"
  prov:wasAttributedTo: "ckp://Actor#developer.peter"
  prov:generatedAtTime: "2026-04-06T20:00:00Z"
  prov:wasGeneratedBy: "ckp://Action#CK.Consensus/evaluate"

Tasks generated from the decision carry prov:wasStartedBy linking back to the decision. Instances produced by task execution carry prov:wasGeneratedBy linking to the task. The chain is unbroken:

Proposal -> Decision (prov:Activity)
  -> Task (prov:wasStartedBy -> decision)
    -> Instance (prov:wasGeneratedBy -> task)

PROV-O and the Ontological Graph

Provenance triples are published to the ontological graph in Jena Fuseki, making the full audit chain queryable via SPARQL:

sparql
# Trace provenance chain for an instance
SELECT ?action ?agent ?time WHERE {
  ?instance prov:wasGeneratedBy ?action .
  ?action prov:wasAssociatedWith ?agent ;
          prov:startedAtTime ?time .
}

# Find all instances produced by a kernel
SELECT ?instance ?time WHERE {
  ?instance prov:wasAttributedTo ?kernel ;
            prov:generatedAtTime ?time .
  ?kernel ckp:hasUrn "ckp://Kernel#Delvinator.Core:v1.0" .
}

Conformance Requirements

CriterionLevel
Every instance MUST include prov:wasGeneratedBy, prov:wasAttributedTo, prov:generatedAtTimeREQUIRED
check.provenance MUST enforce PROV-O field presenceREQUIRED
Consensus decisions MUST be recorded as prov:Activity instancesREQUIRED
Tasks MUST reference their parent decision via prov:wasStartedByREQUIRED
The audit chain (instance -> action -> kernel -> task -> goal) SHOULD be completeRECOMMENDED
Provenance URIs MUST follow the CKP URN schemeREQUIRED

Released under the MIT License.