Copyright © 2026 the Contributors to the RecordWeb Protocol (RWP) v0.0.4, published by the RecordWeb Community Group under the W3C Community Contributor License Agreement (CLA). A human-readable summary is available.
1. Introduction and Scope
1.1. Purpose
The RecordWeb Protocol (RWP) is the normative technical specification for the creation, identification, versioning, linking, and cryptographic proof of Records in RWP-compliant systems.
The RecordWeb Concept ([RWC]) is an informative conceptual document. This specification defines the normative terminology and requirements for RWP conformance.
1.2. Scope
This document applies to:
-
Systems that create, store, or manage Records in the sense of the [RWC]
-
Systems that import Records from other RWP-compliant systems or access them
-
Implementations claiming interoperability with other RWP-compliant systems
This document does not apply to:
-
The internal storage architecture of a compliant system (database, file system, object store)
-
User interfaces and workflows built on top of an RWP-compliant system
-
The content of payloads, insofar as these are not standardised by the schema of the Record type
1.3. Relationship to Other Standards
| Standard | Relationship |
|---|---|
| [DID-CORE] | RWP uses DIDs as the identity mechanism; conformance with W3C DID Core 1.0 is REQUIRED |
| [PROVO] | RWP lineage MAY be serialised as PROV-O. PROV-O serialisation is not required for RWP conformance. |
1.4. Versioning of This Document
This document uses semantic versioning (SemVer): MAJOR.MINOR.PATCH.
-
MAJOR: Incompatible changes to existing standards
-
MINOR: Backward-compatible extensions
-
PATCH: Corrections without substantive change
The current version is 0.0.2 (Draft — not yet approved for production implementations).
2. The Record
2.1. Definition {#record-definition}
For the purposes of this specification, Record has the meaning defined in [ISO15489], clause 3.14. A Record MUST have the identity, structure, payload, type, schema, state, version and integrity evidence required by this specification.
For semantic interoperability, a Record is a specialization of 'prov:Entity'. The term Record remains the primary term of this specification. The term 'prov:Entity' is used only for a [PROVO]-compatible semantic representation.
@prefix prov: <http://www.w3.org/ns/prov#> . @prefix rw: <https://w3id.org/recordweb/ontology#> . rw:Record rdfs:subClassOf prov:Entity . rw:InformationRecord rdfs:subClassOf rw:Record . rw:RelationRecord rdfs:subClassOf rw:Record . rw:SystemRecord rdfs:subClassOf rw:Record . rw:CaseRecord rdfs:subClassOf rw:RelationRecord . rw:AssertionRecord rdfs:subClassOf rw:RelationRecord . rw:SchemaRecord rdfs:subClassOf rw:SystemRecord . rw:MergeRecord rdfs:subClassOf rw:SystemRecord . rw:DeletionRecord rdfs:subClassOf rw:SystemRecord . rw:MigrationRecord rdfs:subClassOf rw:SystemRecord . rw:ConformanceRecord rdfs:subClassOf rw:SystemRecord .
2.2. Record taxonomy {#record-taxonomy}
Every Record has one primary conceptual purpose. For the purposes of this specification, a Record is classified as an InformationRecord, a RelationRecord, or a SystemRecord, as described in [RWC].
Any concrete Record Type is defined by a SchemaRecord in accordance with Record Type Definition.
The taxonomy is normative for the interpretation of this specification. It MUST NOT be interpreted as a mandatory implementation inheritance hierarchy, a mandatory JSON type hierarchy, or a replacement for concrete Record Types and their SchemaRecords.
An InformationRecord is a Record whose primary purpose is to carry semantically autonomous institutional or domain information.
Every InformationRecord MUST conform to a concrete Record Type. This specification does not provide a list of InformationRecord Types.
A RelationRecord is a Record whose primary purpose is to establish, preserve, and make provable a meaningful relationship between Records.
A SystemRecord is a Record whose primary purpose is to define, document, or prove a RecordWeb system rule, operation, or capability.
A CaseRecord is a RelationRecord. It represents a persisted, governed view of linked Records. A CaseRecord MUST NOT be a container and MUST NOT contain the payload of the Records to which it relates. The protocol representation and validation requirements for CaseRecords are defined in CaseRecord Specification.
An AssertionRecord is a RelationRecord. It represents an attributable assertion that a subject resource stands in a specified relationship to an object resource. The protocol representation and validation requirements for AssertionRecords are defined in AssertionRecord Specification.
A SchemaRecord is a SystemRecord. It defines a concrete Record Type and its associated schema and validation requirements.
A MergeRecord is a SystemRecord.
A DeletionRecord is a SystemRecord.
A MigrationRecord is a SystemRecord.
A ConformanceRecord is a SystemRecord.
3. Record Identity (DID)
3.1. Requirements for Record Identity
Every Record MUST possess a globally unique, permanent identity.
This identity:
-
MUST be independent of the physical storage location of the Record
-
MUST be independent of the organisation managing the Record
-
MUST NOT be changed after the Record has been created
-
MUST remain valid without change even after a system migration
-
MUST be machine-resolvable (a resolver MUST be able to retrieve the DID document from the identity)
3.2. DID Format
The identity of a Record MUST be expressed as a Decentralized Identifier (DID) in accordance with [DID-CORE].
Normative format:
did:rwp:{namespace}:{unique-id}
| Component | Requirement |
|---|---|
did
| Literal; immutable |
rwp
| DID method for RecordWeb Protocol; immutable |
<namespace>
| Identifier of the organisation or system; MUST be uniquely registered. During the transition phase, a namespace MAY be formed on the basis of the DNS domain name of the organisation (e.g. did:rwp:bern.ch:<uuid>).
|
<unique-id>
| Unique identifier of the Record within the namespace; MUST be a UUID v4 or a cryptographically equivalent random value |
Example: did:rwp:bern.ch:f47ac10b-58cc-4372-a567-0e02b2c3d479
3.3. DID Document
For every Record DID, a DID document MUST exist containing the following fields:
{ "@context" : "https://www.w3.org/ns/did/v1" , "id" : "did:rwp:bern.ch:f47ac10b-58cc-4372-a567-0e02b2c3d479" , "recordEndpoint" : "https://records.bern.ch/api/v1/records/f47ac10b" , "created" : "2026-05-31T14:00:00Z" , "updated" : "2026-05-31T14:00:00Z" , "currentVersion" : "sha256:e3b0c44298fc1c149afb..." , "controller" : "did:rwp:bern.ch:controller-001" , "verificationMethod" : [ { "id" : "did:rwp:bern.ch:f47ac10b#key-1" , "type" : "Ed25519VerificationKey2020" , "controller" : "did:rwp:bern.ch:controller-001" , "publicKeyMultibase" : "z6MkhaXgBZDvotDkL..." } ] }
| Field | Required | Description |
|---|---|---|
@context
| MUST | W3C DID Context URI |
id
| MUST | DID of the Record; identical to the Record DID |
recordEndpoint
| MUST | URL at which the Record can be retrieved |
created
| MUST | ISO 8601 timestamp of DID creation |
updated
| MUST | ISO 8601 timestamp of last DID document update |
currentVersion
| MUST | Content hash of the current finalised version (empty for pure draft) |
controller
| MUST | DID of the controlling entity (organisation or person) |
verificationMethod
| MUST | At least one verification method for signature validation |
The DID document MUST be updated when the physical storage location changes (recordEndpoint, updated, currentVersion). All other fields MUST NOT be changed.
3.4. DID Resolver Requirements
An implementation claiming the resolver role MUST provide a DID resolver that:
-
Resolves DIDs of the method
rwpand returns the associated DID document -
Delivers the DID document as JSON-LD in accordance with [DID-CORE]
-
Returns HTTP 200 when the DID is known
-
Returns HTTP 404 when the DID is unknown
-
Returns HTTP 410 when the DID is known but the Record has been deleted (payload deletion per Payload Deletion)
An implementation claiming another RWP profile or role MAY rely on a resolver operated by another conformant implementation. It is not required to operate a DID resolver itself unless it claims the resolver role.
A producer or custodian that creates or manages RWP Records MUST ensure that the associated Record DIDs remain resolvable in accordance with this specification.
4. Record Structure
4.1. Overview
Every Record MUST consist of exactly three components:
-
**Identity** — the DID of the Record (Record Identity (DID))
-
**Payload** — the content of the Record (Payload and Formats)
-
**Metadata** — descriptive dimensions of the Record (Minimum Metadata Set)
Together, these three components form a snapshot — an immutable, versioned representation of the Record at a specific point in time.
4.2. Snapshot Definition
A snapshot is the atomic unit of versioning in RecordWeb.
A snapshot MUST fulfil the following properties:
-
It is immutable after its creation
-
It is uniquely identifiable by its content hash
-
It references exactly one version of the payload (or multiple representations per Multi-Representation)
-
It references exactly one version of the schema of its Record type
-
It is linked to its predecessor snapshots by directed edges in the version graph
4.3. Minimum Metadata Set
Every snapshot MUST contain the following metadata fields:
{ "did" : "did:rwp:bern.ch:f47ac10b-58cc-4372-a567-0e02b2c3d479" , "snapshotHash" : "sha256:e3b0c44298fc1c149afb4c8996fb924..." , "recordType" : "did:rwp:ech-standards.ch:schema-baubewilligung-antrag" , "schemaVersion" : "sha256:a665a45920422f9d417e4867efdc4fb8a..." , "state" : "finalized" , "created" : "2026-05-31T14:00:00Z" , "finalized" : "2026-05-31T15:30:00Z" , "owner" : "did:rwp:bern.ch:user-petra-muster" , "parents" : [ "sha256:previousSnapshotHash..." ], "classification" : "internal" , "retentionPolicy" : "did:rwp:bern.ch:retention-bauakten-30y" , "tags" : [ "building-permit" , "parcel-451" , "2026" ], "accessPolicy" : null , "payloadHash" : "sha256:d2d2d2d2d2..." , "payloadFormat" : "application/pdf;profile=PDF-A-2b" , "signature" : "z3FttV7..." }
| Field | Required | Type | Description |
|---|---|---|---|
did
| MUST | DID | Identity of the Record |
snapshotHash
| MUST | SHA-256 | Hash of this snapshot (incl. payload and metadata) |
recordType
| MUST | DID | Reference to the SchemaRecord of the type |
schemaVersion
| MUST | SHA-256 | Hash of the schema version against which this snapshot was validated |
state
| MUST | Enum | draft or finalized; additional values permitted per type schema
|
created
| MUST | ISO 8601 | Timestamp of snapshot creation |
finalized
| MUST (when finalized) | ISO 8601 | Timestamp of finalisation |
owner
| MUST | DID | Responsible person or organisational unit |
parents
| MUST | Array<SHA-256> | Hashes of predecessor snapshots; empty for first snapshot |
classification
| SHOULD | String | Protection level per the organisation’s internal scheme |
retentionPolicy
| SHOULD | DID | Reference to retention rule |
tags
| MAY | Array<String> | Free-text markers for search and filtering |
accessPolicy
| MAY | Object|null | Delegated authorisation model (Access Control Delegation Framework) |
payloadHash
| MUST | SHA-256 | Hash of the payload |
payloadFormat
| MUST | MIME-Type | Format of the primary payload incl. profiles |
signature
| MUST (when finalized) | Multibase | Cryptographic signature of the record owner over the snapshot hash |
4.4. Snapshot Hash Calculation
The snapshotHash MUST be calculated as follows:
-
Serialise the metadata fields (without
snapshotHashitself) as canonical JSON ([RFC8785]) -
Concatenate:
canonicalMetadataJSON || payloadBytes -
Calculate SHA-256 over the result
snapshotHash = SHA-256( canonicalize(metadata \ {snapshotHash}) || payloadBytes )
A system MUST verify the snapshotHash after every finalisation before the snapshot is accepted as valid.
5. Payload and Formats
5.1. Payload Definition
The payload of a Record is the content the Record carries, the actual information.
A payload:
-
MUST conform to the schema of the Record type in the referenced schema version
-
MUST be validated against the schema before finalisation
-
MUST NOT be changed after finalisation
-
MUST be uniquely identified in the
payloadHashof the snapshot
5.2. Permitted Payload Types
RWP distinguishes three payload categories:
| Category | Description | Examples |
|---|---|---|
| Structured | Machine-readable, schema-validatable data | JSON, XML, YAML |
| Documentary | Human-readable documents with defined structure | PDF/A, DOCX, ODT, Markdown |
| Binary | Non-textual data with descriptive schema | TIFF, JPEG 2000, MP4, ZIP |
5.3. Multi-Representation
A snapshot MAY carry multiple representations of the same payload. This is provided in particular for the transition from working format (draft) to long-term format (finalised).
If a snapshot contains multiple representations, ALL of the following MUST apply:
-
All representations MUST depict the same content
-
All representations MUST be individually hashed and referenced in the snapshot
-
One representation MUST be designated as primary (
primary: true) -
The
payloadHashMUST contain the hash of the primary representation
{ "payloadRepresentations" : [ { "format" : "text/markdown" , "hash" : "sha256:aabbcc..." , "primary" : false , "role" : "source" }, { "format" : "application/pdf;profile=PDF-A-2b" , "hash" : "sha256:ddeeff..." , "primary" : true , "role" : "publication" } ] }
| Field | Required | Description |
|---|---|---|
format
| MUST | MIME type incl. profiles |
hash
| MUST | SHA-256 of this representation |
primary
| MUST | Exactly one representation MUST be true
|
role
| SHOULD | Semantic role: source, publication, preview, archive
|
5.4. Format Requirements per State
The schema of a Record type MUST define the permitted payload formats for each state. If a schema contains no explicit format requirements, the following defaults apply:
| State | Permitted formats (default) |
|---|---|
draft
| All MIME types not explicitly excluded in the schema of the Record type |
finalized
| Only formats listed under RWP archival-grade formats |
RWP archival-grade formats (normative):
| MIME Type | Format | Suitability |
|---|---|---|
application/pdf;profile=PDF-A-1b
| PDF/A-1b | Documents without embedded multimedia |
application/pdf;profile=PDF-A-2b
| PDF/A-2b | Documents with embedded files |
application/pdf;profile=PDF-A-3b
| PDF/A-3b | Documents with arbitrary attachments |
text/xml
| XML (well-formed) | Structured data |
application/json
| JSON | Structured data (with schema reference) |
image/tiff
| TIFF | Raster images |
image/jp2
| JPEG 2000 | Raster images (near-lossless) |
text/plain;charset=UTF-8
| Plain Text UTF-8 | Pure text documents |
text/markdown
| CommonMark Markdown | Source format with publication representation |
5.5. Conversion During Finalisation
When a system transitions a Record from state draft to finalized, it MUST:
-
Validate the payload against the finalised format of the schema
-
If the current payload is not in archival-grade format: convert automatically or request conversion from the operator
-
Store both formats as multi-representation in the snapshot (SHOULD)
-
Document the conversion act as metadata (
conversionMethod,conversionTimestamp)
A system MUST NOT finalise a Record whose payload does not conform to the format defined for finalized and for which no archival-grade conversion is possible.
6. Record Types and Schemas
6.1. Record Type Definition
Every Record MUST be assigned to a Record type. A Record type:
-
defines the schema of the payload
-
defines the permitted states and their transitions
-
defines the format requirements per state
-
defines mandatory and optional metadata fields beyond the minimum set
-
is itself a Record of the type
SchemaRecord
6.2. SchemaRecord
A SchemaRecord is a specialised Record type that carries the definition of another Record type.
A SchemaRecord MUST:
-
fulfil all requirements for a regular Record (DID, metadata, version graph)
-
contain a JSON Schema (Draft 2020-12 or later, [JSON-SCHEMA]) in the payload
-
contain the field
rwpSchemaVersionin the payload with the RWP version for which it is valid -
contain the field
allowedStatesin the payload with the permitted states and their transitions -
contain the field
payloadFormatsin the payload with the permitted formats per state
Minimal SchemaRecord payload example:
{ "rwpSchemaVersion" : "0.1" , "schemaId" : "did:rwp:bern.ch:schema-building-permit-application" , "displayName" : "Building Permit Application" , "allowedStates" : [ "draft" , "finalized" ], "stateTransitions" : [ { "from" : "draft" , "to" : "finalized" , "requiresOwnerSignature" : true } ], "payloadFormats" : { "draft" : [ "application/vnd.openxmlformats-officedocument.wordprocessingml.document" , "text/markdown" ], "finalized" : [ "application/pdf;profile=PDF-A-2b" ] }, "jsonSchema" : { "$schema" : "https://json-schema.org/draft/2020-12/schema" , "type" : "object" , "required" : [ "parcelNumber" , "applicant" , "constructionProject" , "date" ], "properties" : { "parcelNumber" : { "type" : "string" }, "applicant" : { "type" : "string" }, "constructionProject" : { "type" : "string" }, "date" : { "type" : "string" , "format" : "date" } } } }
6.3. Core Record Types
RWP defines the following core Record types (with DID Suffix):
-
SchemaRecord(schema-record) -
CaseRecord(case-record) -
AssertionRecord(assertion-record) -
MergeRecord(merge-record) -
DeletionRecord(deletion-record) -
MigrationRecord(migration-record) -
ConformanceRecord(conformance-record)
The conformance requirements for these Record types are profile-, role-, and capability-specific. An implementation MUST support a core Record type only where this specification requires that support for a claimed profile, role, or exercised capability.
The capability-bound requirements are defined in Capability-bound requirements.
Additional Record types MAY be defined by organisations or standards bodies. They MUST be published as SchemaRecords and be resolvable via a DID.
6.4. Schema Versioning and Backward Compatibility
When a SchemaRecord is finalised in a new version, the following applies:
-
Existing snapshots referencing an earlier schema version REMAIN valid
-
The new schema MUST contain the field
previousSchemaVersionin the payload with the hash of the predecessor schema -
Systems MUST keep all schema versions referenced by existing Records permanently accessible
-
A system MUST NOT retroactively change an existing SchemaRecord, corrections are made as a new version
7. States and Transitions
7.1. State Model
Every Record snapshot has exactly one state. The state describes the validity and linkability status of the snapshot.
Core states (normative, for all Record types):
| State | Linkable | Immutable | Description |
|---|---|---|---|
draft
| NO | NO | Being processed; content may change |
finalized
| YES | YES | Complete; content cryptographically secured |
Record types MAY define additional states. These MUST be specified in the SchemaRecord and MUST be reachable from one of the core states or lead into one.
Example of an extended state machine for type "contract":
draft → in-review → finalized ↓ rejected (terminal state, not linkable)
7.2. Linkability
A Record MUST be in the finalized state to be used as the target of a hard link.
A system MUST return an error when an attempt is made to set a hard link to a Record that is not in the finalized state.
Exception: Working references (soft links) per working-references MAY point to Records in any state, including draft Records.
7.3. Finalisation Requirements
A system MUST perform the following checks before finalising a snapshot:
-
Schema validation: Payload conforms to the schema in the version defined for
finalized -
Format validation: Payload format conforms to the
payloadFormats.finalizedrequirements of the schema -
Mandatory field check: All MUST metadata fields are present and correctly typed
-
Owner signature: If the schema defines
signaturePolicy: owner, the record owner MUST have cryptographically signed the snapshot hash. ForsignaturePolicy: system, the signature MAY be generated by an authorised system key. ForsignaturePolicy: none, signature validation is omitted. -
Parent integrity: All referenced parent hashes are resolvable in the system
If any of these checks fails, the system MUST NOT finalise the snapshot and MUST return an error with a validation code.
7.4. Irreversibility of Finalisation
A finalized snapshot MUST NOT be reverted to the state draft.
Corrections, revisions, replacements, and other continuations of the same Record MUST be represented as a new snapshot of that Record.
Such a snapshot MUST:
-
retain the DID of the Record;
-
reference the superseded or revised snapshot in its
parentsfield; -
include a
correctionReasonor equivalent schema-defined rationale where applicable; and -
complete the normal finalisation process defined in Finalisation Requirements.
An implementation MUST NOT represent a correction, revision, replacement, or continuation of the same Record as a new Record that is related to the earlier Record only through an AssertionRecord or another cross-Record relationship.
A new Record MAY be created where a new semantically autonomous information object arises. Such a Record MAY document derivation, source, or other relationships to an earlier Record through an AssertionRecord. It MUST NOT thereby be treated as a continuation in the version graph of that earlier Record.
8. Version Graph (DAG)
8.1. Graph Structure
The totality of all snapshots of a Record and their parent-child relationships forms the version graph.
The version graph MUST be a Directed Acyclic Graph (DAG):
-
Directed: Edges point from child to parent (backward in time)
-
Acyclic: There MUST be NO cycles — a snapshot MUST NOT be directly or indirectly its own ancestor
A system MUST check upon receipt of a new snapshot whether adding its parent references would create a cycle. If so, the snapshot MUST be rejected.
8.2. Nodes
Every node in the version graph is a snapshot per Section 3.2.
| Property | Requirement |
|---|---|
| Unique identity | SHA-256 of the snapshot (snapshotHash); MUST be unique
|
| Immutability | Finalised nodes MUST NOT be changed |
| Resolvability | Every node MUST be retrievable in the system via its snapshotHash
|
8.3. Edges (Parent References)
An edge connects a snapshot (child) with its predecessor snapshot (parent).
-
A snapshot MAY have zero, one, or multiple parent references
-
A snapshot without parents is the root snapshot (first snapshot of the Record)
-
A snapshot with exactly one parent reference is a linear continuation
-
A snapshot with multiple parent references is a merge snapshot
Edge requirements:
-
Every parent reference MUST be a valid
snapshotHashof a known snapshot -
Edges MUST NOT point to snapshots of other Records. Cross-Record connections are made via links in the payload or as Case linkage (CaseRecord Specification)
8.4. Branches
A branch arises when two or more new draft snapshots with the same parent reference emerge from a finalized snapshot.
-
Branches are explicitly permitted in RecordWeb and MUST be made visible by the system
-
A system MUST return all active branches (draft snapshots without successors) when a Record is retrieved
-
Branches MAY exist simultaneously as long as they are in state draft
8.5. Merges
A merge snapshot is a snapshot with two or more parent references. It consolidates two branches.
Before a merge snapshot can be finalised, a MergeRecord MUST be created:
{ "mergeRecord" : { "mergedSnapshots" : [ "sha256:branch-a-snapshot-hash..." , "sha256:branch-b-snapshot-hash..." ], "mergeReason" : "Consolidation after coordination between departments" , "mergedBy" : "did:rwp:bern.ch:user-petra-muster" , "mergedAt" : "2026-05-31T16:00:00Z" , "resultSnapshot" : "sha256:merged-snapshot-hash..." } }
The MergeRecord MUST be finalised before the merge snapshot can be finalised.
8.6. Cross-Record Merges
When a new Record arises from two or more existing finalized Records (cross-Record merge), the following MUST apply:
-
The new Record MUST have a root snapshot with an empty
parentsarray -
The
MergeRecordMUST reference the DIDs of the source Records (not their snapshot hashes) -
The source Records MUST remain in state finalized and receive a metadata note
contributedTowith the DID of the new Record
9. CaseRecord Specification
9.1. Case as a specialised Record Type {#case-type}
A CaseRecord is a RelationRecord and a concrete Record type. It is subject to all requirements that apply to Records and supplements them with the Case-specific requirements defined in this section.
A CaseRecord is a persisted, governed view of linked Records. It is itself a Record with its own identity, state, version history, schema association, metadata, and integrity evidence.
A CaseRecord MUST NOT be interpreted as a container into which Records are placed. A Record linked by a CaseRecord remains an independent Record and is not embedded in the CaseRecord payload.
9.2. Case Schema (normative)
A CaseRecord payload MUST contain the following fields:
{ "recordDid" : "did:rwp:bern.ch:f47ac10b-case-001" , "caseType" : "did:rwp:bern.ch:schema-building-permit-case" , "title" : "Building Permit Musterstrasse 12, Parcel 451" , "trigger" : { "type" : "hard" , "recordDid" : "did:rwp:bern.ch:application-001" , "snapshotHash" : "sha256:application-finalized-hash..." }, "context" : [ { "type" : "hard" , "recordDid" : "did:rwp:bern.ch:zoning-plan-2024" , "snapshotHash" : "sha256:zoning-plan-hash..." , "role" : "Legal basis" }, { "type" : "hard" , "recordDid" : "did:rwp:bern.ch:case-planning-approval-001" , "snapshotHash" : "sha256:planning-approval-case-hash..." , "role" : "Related administrative proceeding" } ], "process" : [ { "type" : "hard" , "recordDid" : "did:rwp:bern.ch:minutes-site-inspection" , "snapshotHash" : "sha256:minutes-hash..." , "role" : "Investigation" } ], "decision" : null , "result" : null , "merkleRoot" : "sha256:case-merkle-root..." }
9.3. Case Elements (normative)
A complete CaseRecord MUST contain all five Case elements. An element that permits an empty value is considered present when it is represented in the CaseRecord payload, even if its value is an empty array or null, as applicable. A Record MAY fulfil multiple elements.
Unless a CaseRecord schema defines more specific constraints, every Case element MAY link to any Record type, including another CaseRecord.
| Element | Required for finalisation | Description |
|---|---|---|
trigger
| MUST | Exactly one Record that triggered the Case; MUST be a hard link |
context
| SHOULD | Information relevant to understanding and processing |
process
| MAY (empty allowed) | Documentation of processing steps |
decision
| MAY (empty allowed) | Record(s) documenting the decision; MUST be a hard link |
result
| MUST (min. 1) | At least one Record documenting the outcome; MUST be a hard link |
Exception — ad-hoc Case: A CaseRecord schema MAY be marked as adhoc: true. Ad-hoc Cases have no mandatory fields other than trigger and recordDid. They MUST be marked in the metadata object as caseVariant: "adhoc".
9.4. Hard and Soft Links {#links}
A Case link MAY target any Record, including an InformationRecord, a RelationRecord (including another CaseRecord), or a SystemRecord.
A hard link points to one identified finalized snapshot of a target Record. A hard link MUST contain the target recordDid and snapshotHash.
A hard link is immutable after finalisation of the referencing CaseRecord.
A soft link is a working reference that points to a target recordDid without identifying a target snapshot. A soft link MAY point to a draft or finalized Record.
A CaseRecord containing one or more soft links MUST NOT be finalised. Every soft link MUST be converted to a hard link before finalisation of the CaseRecord.
A system MUST check during a CaseRecord finalisation attempt whether soft links are present. If soft links are present, the system MUST reject the finalisation and return the unresolved soft links.
9.5. CaseRecord-to-CaseRecord Links {#case-to-case-links}
A CaseRecord MAY link to another CaseRecord through a soft link or a hard link.
A hard link to a CaseRecord MUST identify a finalized snapshot of the target CaseRecord through its recordDid and snapshotHash.
During finalisation of a referencing CaseRecord, the system MUST resolve and validate every target CaseRecord snapshot referenced through a hard link, subject to the applicable federation and offline-validation rules.
The snapshotHash of a hard-linked target CaseRecord MUST be included in the Merkle root of the referencing CaseRecord.
A soft link MAY refer to a draft or finalised CaseRecord during work. A soft link to a CaseRecord MUST be converted to a hard link before finalisation of the referencing CaseRecord.
A link from CaseRecord A to CaseRecord B references only the identified snapshot of CaseRecord B.
A CaseRecord-to-CaseRecord link MUST NOT include, copy, inherit, or otherwise treat Records linked by CaseRecord B as direct members of CaseRecord A.
The referenced CaseRecord B snapshot and its Merkle root provide evidence of the Records directly linked by CaseRecord B at the time that snapshot was finalised. A Record is a direct member of CaseRecord A only if CaseRecord A links to that Record explicitly.
9.6. Case Merkle Root
The Merkle root of a CaseRecord MUST be calculated as follows:
-
Collect the
snapshotHashvalue of every hard link in the CaseRecord, including every hard link to another CaseRecord. -
Sort the collected
snapshotHashvalues lexicographically by their canonical serialised value. -
Calculate the Merkle root over the sorted list using the Merkle Tree Algorithm.
merkleRoot = MerkleRoot( sort( [snapshotHash_1, snapshotHash_2, ... snapshotHash_n] ) )
The Merkle root of a CaseRecord MUST include the hash of each directly hard-linked target snapshot. It MUST NOT recursively include the individual hard-link hashes or linked Record snapshots contained in a referenced CaseRecord.
The Merkle root MUST be recalculated every time a hard link is added or removed. A system MUST verify the Merkle root before finalising the CaseRecord.
9.7. Case Completeness Check
A system SHOULD perform a completeness check on a CaseRecord at any time upon request and return:
{ "recordDid" : "did:rwp:bern.ch:f47ac10b-case-001" , "complete" : false , "missingElements" : [ "decision" , "result" ], "openWorkingReferences" : [ "did:rwp:bern.ch:expert-opinion-draft-001" ], "merkleRootValid" : true }
10. AssertionRecord Specification
10.1. Purpose and scope {#assertionrecord-purpose}
An AssertionRecord is a RelationRecord that preserves an attributable assertion that a subject resource stands in a specified relationship to an object resource.
An AssertionRecord is itself a Record. It has its own identity, state, version history, schema association, metadata and integrity evidence. It does not modify, finalise, merge, delete, or otherwise change either the subject or the object to which it refers.
An AssertionRecord MAY refer to Records in the same namespace or in another namespace. Referencing a Record in another namespace MUST NOT imply acceptance, storage, reciprocity, modification, or any other obligation for the custodian of the referenced Record.
10.2. Assertion model {#assertionrecord-model}
An AssertionRecord expresses one directed relationship:
subject -- predicate --> object
The subject identifies the resource from which the relationship is asserted. The predicate identifies the semantics of the relationship. The object identifies the resource to which the relationship is asserted.
The subject and object MUST be resource reference objects containing an id field.
The id field MUST identify the referenced resource. It MAY contain an RWP DID, another DID, or an absolute IRI, subject to the constraints of the applicable predicate declaration.
A resource reference identifying an RWP Record MAY additionally contain a snapshotHash field.
Where snapshotHash is present:
-
idMUST be the DID of an RWP Record; -
snapshotHashMUST identify a snapshot of that Record; -
the AssertionRecord refers to that specific immutable snapshot; and
-
a validating implementation MUST verify that the resolved snapshot belongs to the identified Record where the snapshot is resolvable.
Where snapshotHash is absent, the AssertionRecord refers to the identified Record or other resource independently of a specific version.
An AssertionRecord MUST NOT be interpreted as modifying the subject or object. It preserves only the assertion made by its asserting Agent.
10.3. Relationship predicate {#assertionrecord-predicate}
An AssertionRecord MUST contain a predicate field.
The value of predicate MUST be an absolute IRI conforming to [RFC3987]. The predicate IRI MUST identify a relationship term permitted by the Relationship Vocabulary.
The meaning of an asserted relationship MUST NOT be carried solely by unconstrained natural-language text. A human-readable predicate label MAY be provided as optional, localised presentation metadata. Such a label MUST NOT replace the predicate IRI and MUST NOT be used as the sole basis for semantic interpretation or validation.
The applicable predicate declaration MUST define the predicate’s semantics, direction, permitted subject kinds, permitted object kinds, version, and validation requirements.
10.4. Assertion payload {#assertionrecord-payload}
The payload of an AssertionRecord MUST contain subject, predicate, object, assertedBy, and assertedAt.
The value of assertedBy MUST identify the Agent responsible for the assertion. The applicable SchemaRecord MUST define the relationship between assertedBy, the Record owner, and the verification method used to finalise the AssertionRecord.
{ "subject" : { "id" : "did:rwp:record-A" , "snapshotHash" : "sha256:..." }, "predicate" : "https://www.w3.org/ns/prov#wasDerivedFrom" , "object" : { "id" : "did:rwp:record-B" }, "assertedBy" : "did:rwp:agent-..." , "assertedAt" : "2026-08-13T11:00:00Z" }
The subject and object values MUST be identifiers that can be interpreted according to the applicable predicate and SchemaRecord.
10.5. Validation {#assertionrecord-validation}
An AssertionRecord MUST be validated against its SchemaRecord before it is finalised.
Validation MUST verify at least that:
-
the
predicatevalue is an absolute IRI; -
subject,predicate, andobjectare present; -
the subject and object satisfy the constraints declared for the predicate;
-
the asserting Agent and time of assertion are available; and
-
the AssertionRecord satisfies the normal Record integrity and finalisation requirements.
Where the target namespace exposes an LDN inbox, the asserting party MAY notify the target custodian that a new AssertionRecord refers to one of its Records. Such a notification is informational only. It MUST NOT create an obligation to store, mirror, accept or reciprocate the relationship.
An AssertionRecord MAY valid as an assertion even where a referenced external resource cannot be resolved, provided that the assertion identifies that resource unambiguously and the applicable SchemaRecord permits unresolved references. A failure to resolve a referenced resource MUST NOT be interpreted as a modification of, or rejection by, that resource’s custodian.
11. Relationship Vocabulary
11.1. Scope and conformance {#relationship-vocabulary-scope}
This section defines the controlled relationship vocabulary used by AssertionRecords.
A conforming AssertionRecord MUST use a predicate IRI that is either:
-
an applicable PROV-O predicate defined by this specification; or
-
a predicate explicitly permitted by the SchemaRecord that defines the concrete AssertionRecord type.
A Conformance Profile MAY require an implementation to create, validate, retain, or consume AssertionRecords using specified predicate vocabularies. A Conformance Profile MUST NOT itself define, broaden, reverse, or otherwise alter the semantics of a relationship predicate.
For provenance and version-lineage relationships, the applicable PROV-O predicate MUST be used where PROV-O expresses the intended semantics.
An AssertionRecord MUST NOT use a predicate whose semantics, direction, permitted subject and object kinds, version, and validation requirements are not declared by this specification or by an applicable conformance profile.
The use of an IRI alone does not make a relationship predicate conformant.
11.2. Provenance and version-lineage predicates {#provenance-and-version-lineage-predicates}
For provenance and version-lineage relationships, an AssertionRecord MUST use an applicable [PROVO] predicate where a PROV-O predicate expresses the intended relationship semantics.
The following PROV-O predicates are part of the RWP core relationship vocabulary:
-
prov:wasAttributedTo -
prov:wasGeneratedBy -
prov:wasDerivedFrom -
prov:wasRevisionOf -
prov:actedOnBehalfOf
An AssertionRecord using a PROV-O predicate MUST satisfy the semantic domain and range constraints of that predicate.
11.2.1. Relationship to the RWP version graph {#assertionrecord-version-graph}
The RWP version graph is the authoritative representation of version succession between snapshots of the same Record.
A conforming implementation MUST determine RWP snapshot ancestry, direct parentage, branches, and merge relationships exclusively from the parents field and the rules defined in Version Graph.
An AssertionRecord using prov:wasRevisionOf, prov:wasDerivedFrom, or another provenance predicate MUST NOT create, alter, replace, or repair a version-graph edge.
Where an AssertionRecord documents a relationship between snapshots of the same Record, it MAY provide additional attributable documentary evidence. It MUST NOT be used to infer a parent relationship that is absent from the version graph.
If an AssertionRecord and the version graph make incompatible statements about version succession, a conforming implementation MUST treat the version graph as authoritative for all RWP versioning, ancestry, finalisation, merge, and integrity decisions.
An AssertionRecord that conflicts with the version graph remains an attributable assertion. Its conflict with the version graph MUST NOT alter the integrity or history of either referenced Record.
In particular:
-
prov:wasDerivedFromandprov:wasRevisionOfrelate an Entity to an Entity; -
prov:wasGeneratedByrelates an Entity to an Activity; -
prov:wasAttributedTorelates an Entity to an Agent; and -
prov:actedOnBehalfOfrelates an Agent to an Agent.
A Record is an Entity for the purposes of this section. A Record MUST NOT be used as the subject or object of a PROV-O predicate where the predicate’s declared semantics require an Agent or an Activity.
11.3. Contextual relationships {#contextual-relationships}
Institutional, functional, legal, subject-matter, and archival-context relationships are not necessarily provenance relationships. Such relationships MUST NOT be represented using a PROV-O predicate unless the PROV-O predicate expresses their intended semantics.
A contextual relationship predicate MAY be used only where it is explicitly permitted by the SchemaRecord that defines the concrete AssertionRecord type.
The applicable SchemaRecord MUST identify the permitted predicate IRIs, their applicable vocabulary versions, and the validation constraints that apply to them.
A conformance profile that permits a contextual relationship predicate MUST declare the predicate’s semantics, direction, permitted subject and object kinds, version, and validation requirements.
A profile MAY declare a contextual relationship predicate defined by [RICO]. Where it does so, the profile MUST identify the exact RiC-O predicate IRI and the applicable RiC-O version. The profile MUST NOT redefine, broaden, or contradict the semantics of the declared RiC-O predicate.
11.4. RiC-O contextual predicates {#rico-contextual-predicates}
[RICO] predicates MAY be used as predicate values in AssertionRecords only where they are explicitly permitted by an applicable conformance profile.
The use of a RiC-O predicate does not require an implementation to store, exchange, or process Records as RDF or JSON-LD. In an AssertionRecord, the RiC-O IRI identifies the semantics of the asserted relationship.
A conformance profile that permits a RiC-O predicate MUST declare:
-
the exact predicate IRI;
-
the RiC-O version to which the declaration applies;
-
the semantics and direction of the predicate, with reference to the applicable RiC-O definition;
-
the permitted subject kinds;
-
the permitted object kinds;
-
any additional RWP validation requirements; and
-
the profile version in which the predicate is declared.
A profile MUST NOT permit a RiC-O predicate where an applicable PROV-O predicate expresses the intended provenance or version-lineage semantics.
A profile MAY impose constraints narrower than those of the declared RiC-O predicate. A profile MUST NOT broaden, reverse, or otherwise contradict the semantics or direction of the declared RiC-O predicate.
11.5. Schema predicate extensions {#schema-predicate-extensions}
A conformance SchemaRecord MAY define additional relationship predicates or permit the use of specifically identified external relationship predicates.
For each additional or externally permitted predicate, the SchemaRecord MUST declare:
-
an absolute predicate IRI;
-
a stable, versioned definition of its semantics;
-
the relationship direction;
-
the permitted subject kinds;
-
the permitted object kinds;
-
the required or permitted assertion metadata;
-
the validation requirements; and
-
the SchemaRecord version in which the predicate is declared.
For an externally defined predicate, the SchemaRecord MUST additionally identify the external vocabulary and its applicable version.
A SchemaRecord MUST NOT define or permit a predicate whose semantics duplicate an applicable PROV-O predicate. In that case, the applicable PROV-O predicate MUST be used.
A SchemaRecord MAY constrain the use of an external predicate more narrowly than the defining vocabulary permits. A SchemaRecord MUST NOT broaden, reverse, or contradict the semantics or direction defined by that vocabulary.
11.6. Predicate declarations {#predicate-declarations}
A predicate declaration MUST be versioned and resolvable through its IRI or through the applicable conformance profile.
The declaration MUST provide a human-readable definition. It SHOULD provide machine-readable representations where available, including RDF, JSON-LD, SHACL, JSON Schema, or equivalent validation artefacts.
A localised display label MAY accompany a predicate declaration. A display label is presentation metadata and MUST NOT replace the predicate IRI as the semantic identifier.
12. Integrity and Hashing Procedures
12.1. Hashing Procedure
RWP uses exclusively SHA-256 as the hashing procedure for:
-
Snapshot hashes (
snapshotHash) -
Payload hashes (
payloadHash) -
Schema version hashes (
schemaVersion) -
Parent references (
parents) -
Merkle root calculations
A system MUST NOT use any hashing procedure other than SHA-256 for normative integrity proofs.
Note: A future version of RWP MAY permit SHA-3 or other procedures as an alternative if cryptographic weaknesses in SHA-256 become known. Until then, SHA-256 is the only permitted procedure.
12.2. Canonical JSON Serialisation
For all hash calculations over JSON objects, RFC 8785 (JSON Canonicalization Scheme, JCS) [RFC8785] MUST be used.
Requirements:
-
Keys MUST be sorted alphabetically
-
Unicode characters MUST be normalised (NFC)
-
No superfluous whitespace or line breaks
-
Numbers MUST be represented in their canonical form
12.3. Snapshot Integrity
A system MUST check the integrity of a snapshot on the following events:
-
Receipt of a snapshot from an external system
-
Retrieval of a snapshot for a linking operation
-
Periodic integrity check
If the integrity check fails, the system MUST:
-
Mark the snapshot as
compromised -
Mark all dependent Records as
integrity-warning -
Log the incident in the system log with timestamp and discrepancy
-
Notify the responsible record owner via the DID (SHOULD)
The system MUST NOT automatically attempt to reconstruct the original content.
12.4. Signature Procedure
If the schema prescribes a signature (signaturePolicy: owner or signaturePolicy: system), the snapshot hash MUST be cryptographically signed during the finalisation act.
Requirements:
-
MUST be Ed25519 (EdDSA, [RFC8037]) or P-256 (ECDSA, NIST)
-
The signature MUST be calculated over the canonical
snapshotHashvalue (as hex string) -
The signature MUST be stored in the
signaturefield as a multibase-encoded value -
The key used MUST be published in the DID document of the record owner as a verification method
12.5. Merkle Tree Algorithm
For the calculation of the CaseRecord Merkle root, the following algorithm MUST be used:
function merkleRoot(hashes: SHA256[]) -> SHA256:
if hashes.length == 0: return SHA256("")
if hashes.length == 1: return hashes [0]
sorted = sort(hashes) // alphabetically by hex string
while sorted.length > 1:
nextLevel = []
for i in range(0, sorted.length, 2):
if i + 1 < sorted.length:
nextLevel.append( SHA256( sorted[i] || sorted[i+1] ) )
else:
nextLevel.append( sorted[i] ) // odd element carried over unchanged
sorted = nextLevel
return sorted[0]
13. Optional Ledger Anchoring
13.1. Purpose and Scope
Ledger anchoring is an optional extension of RWP. It enables the external, immutable proof of CaseRecord Merkle roots on a distributed infrastructure.
A system MUST be fully RWP-compliant without ledger anchoring. Ledger anchoring supplements the internal integrity assurance with an external proof independent of the operating organisation.
13.2. Requirements for the Ledger
If a system implements ledger anchoring, the ledger used MUST:
-
be permissioned (no public, anonymous blockchain)
-
guarantee immutable entries (append-only)
-
deliver a provable timestamp per entry
-
be operated independently of the organisation that manages the Records
-
be readable by all authorised verification parties
Recommended implementation: Hyperledger Fabric [HYPERLEDGER]. Other permissioned distributed ledger technologies MAY be used if they fulfil the above requirements.
13.3. Anchoring Protocol
When a finalised CaseRecord is anchored, the ledger entry MUST contain the following fields:
{ "rwpAnchor" : { "version" : "0.1" , "caseDid" : "did:rwp:bern.ch:f47ac10b-case-001" , "caseSnapshotHash" : "sha256:case-finalized-snapshot-hash..." , "merkleRoot" : "sha256:case-merkle-root..." , "anchoredAt" : "2026-05-31T16:00:00Z" , "anchoredBy" : "did:rwp:bern.ch:controller-001" , "ledgerTxId" : "abc123..." } }
The ledger entry MUST NOT contain any payload content, personal data, or classified information. Only cryptographic hash values and identifiers are permitted.
13.4. Anchoring Reference in the Case
When a CaseRecord has been anchored, the CaseRecord snapshot MUST be updated with an anchorReference field:
{ "anchorReference" : { "ledgerType" : "hyperledger-fabric" , "ledgerEndpoint" : "https://ledger.bern.ch/api/v1" , "txId" : "abc123..." , "anchoredAt" : "2026-05-31T16:00:00Z" } }
14. Access Control (Delegation Framework)
14.1. Scope and Principles
RWP deliberately defines no mandatory authorisation model. Data security and information protection are delegated to the implementing systems. This chapter defines an optional, interoperable delegation framework that compliant systems MAY implement.
The core principle: access control in RWP is attribute-based (ABAC) and delegatable. Rights are not assigned to roles in a fixed hierarchy, but expressed as verifiable claims attached to DIDs.
14.2. Access Policy Block
A Record snapshot MAY contain an accessPolicy block in the metadata:
{ "accessPolicy" : { "visibility" : "restricted" , "readAccess" : [ "did:rwp:bern.ch:unit-legal" , "did:rwp:bern.ch:unit-planning" ], "writeAccess" : [ "did:rwp:bern.ch:user-petra-muster" ], "delegationAllowed" : true , "expiresAt" : null } }
| Field | Required | Description |
|---|---|---|
visibility
| SHOULD | public, restricted, or confidential
|
readAccess
| MAY | Array of DIDs with read permission |
writeAccess
| MAY | Array of DIDs with write permission (draft state only) |
delegationAllowed
| MAY | Whether listed DIDs may further delegate access |
expiresAt
| MAY | ISO 8601 timestamp after which access policy expires |
14.3. Delegation Chain
When delegationAllowed: true, a listed DID MAY issue a signed delegation token granting access to a third DID. The delegation token MUST:
-
be signed by the delegating DID’s verification key
-
reference the original Record DID
-
specify the access level being delegated (
readorwrite) -
include an expiry timestamp
Implementing systems MAY enforce delegation chains and MUST validate delegation token signatures before granting access.
15. Federation
15.1. Federation Model
RWP federation is modelled after the DNS architecture: a decentralised, hierarchical namespace model without a single point of failure.
Every RWP namespace (the <namespace> component of a DID, e.g. bern.ch) is operated by the owning organisation. Namespace resolvers are federated: each resolver knows its own namespace and can route resolution requests for unknown namespaces to peer resolvers.
15.2. Namespace Registry
The authoritative namespace registry is the subject of a future RWP extension. During the transition phase, the following applies:
-
A namespace SHOULD be formed on the basis of the DNS domain name of the organisation (e.g.
bern.ch,bag.admin.ch,usz.ch) -
DNS ownership of the domain implies namespace authority, no separate registration required during transition
-
Namespace conflicts are resolved by DNS priority
15.3. Resolver Requirements
An RWP federation resolver MUST:
-
Accept DID resolution requests of the method
rwp -
Resolve DIDs within its own namespace directly
-
For unknown namespaces: query the DNS TXT record of the namespace domain for the
_rwp-resolverentry -
Cache resolver endpoints with a TTL of at least 300 seconds
-
Return a
404response when neither the DID nor a resolver for its namespace can be found
DNS TXT record format for resolver discovery:
_rwp-resolver.bern.ch. 300 IN TXT "v=rwp1;endpoint=https://resolver.bern.ch/api/v1"
15.4. Cross-Namespace Links
A Record in namespace bern.ch MAY contain hard links to Records in other namespaces (e.g. did:rwp:bag.admin.ch:guideline-001).
When resolving cross-namespace links, a system MUST:
-
Extract the namespace component from the linked DID
-
Discover the resolver endpoint via DNS TXT lookup (Resolver Requirements)
-
Verify the snapshot hash of the linked Record after retrieval
-
Cache the resolved snapshot locally with the original hash for integrity verification
16. Payload Deletion
16.1. Deletion Principles
RecordWeb’s immutability and data protection erasure obligations (GDPR, Swiss DSG) are in tension. RWP resolves this tension through a tiered deletion regime.
The applicable regime is declared in the deletionRegime field of the Record’s metadata at the time of creation. Implementations MUST respect this field and MAY enforce it at the infrastructure level.
16.2. Deletion Regimes
RWP defines three deletion regimes:
| Regime | Key | Description | When applicable |
|---|---|---|---|
| Payload deletion | payload-only
| The payload is deleted; DID, metadata, and version graph are retained. The Record continues to exist as a provable "empty shell". | Default. Where provenance continuity is legally required despite erasure (e.g. audit trails, public registers). |
| Full deletion | full-delete
| The entire Record (including DID, metadata, and graph edges) is deleted. | Where no retention obligation exists and the right to erasure is absolute (e.g. erroneously captured personal data with no public interest basis). |
| Deletion exemption | exempt
| No deletion occurs. The statutory retention obligation is documented as metadata. | Where a statutory retention obligation overrides the erasure claim (e.g. tax records, notarial acts, public register entries). |
16.3. DeletionRecord Protocol
When a payload deletion is executed, a DeletionRecord MUST be created and finalised before the payload is removed.
The DeletionRecord MUST contain:
{ "deletionRecord" : { "targetDid" : "did:rwp:bern.ch:f47ac10b-58cc-4372-a567-0e02b2c3d479" , "targetSnapshotHash" : "sha256:snapshot-to-be-deleted..." , "deletionRegime" : "payload-only" , "legalBasis" : "GDPR Art. 17 — Right to erasure" , "requestedBy" : "did:rwp:bern.ch:user-max-mustermann" , "approvedBy" : "did:rwp:bern.ch:unit-legal" , "deletedAt" : "2026-06-01T10:00:00Z" , "retainedFields" : [ "did" , "metadata" , "versionGraph" ] } }
After the DeletionRecord is finalised:
-
The payload bytes are securely overwritten
-
The
payloadHashfield in the snapshot is replaced with the string"deleted:<DeletionRecord-DID>" -
The DID document’s
currentVersionfield is updated -
The DID resolver MUST return HTTP 410 for
full-deleteregimes
16.4. Solid Pod Delivery (optional)
For Records whose primary subject is an individual citizen, RWP offers an optional delivery extension: delivery of finalised Records into a citizen’s Solid Pod.
When a system implements Solid Pod delivery, it MUST:
-
Obtain explicit, revocable write consent from the citizen via their Pod’s access control mechanism
-
Deliver the complete snapshot (DID, metadata, payload) to the Pod
-
Retain the canonical copy in its own RWP system, the Pod copy is an additional output, not a transfer of authority
-
Include a
deliveryTargetfield in the optional metadata extension block
Typical use cases: driving licences, medical images, residence registration confirmations, diplomas, building permits (delivered to the applicant).
The citizen MAY present the Pod-held Record to any third party, who can independently verify its authenticity via the DID and cryptographic hash without querying the issuing authority.
17. Conformance and Implementation Claims
17.1. Scope of conformance {#conformance-scope}
Conformance in RWP applies to an identifiable software implementation or software component.
A conformance claim MUST identify:
-
the implementation;
-
the implementation version;
-
the RWP version;
-
the claimed profile or profiles, if applicable;
-
the claimed role or roles;
-
the assessment method; and
-
the applicable evidence or evidence reference.
A conformance claim applies only to the Records, Record types, operations, and responsibilities covered by the claimed profiles and roles. It MUST NOT be interpreted as a claim that an entire product, organisation, deployment, or source system fulfils all RWP requirements.
An implementation MAY claim multiple profiles and roles.
An implementation claiming an RWP Record profile MUST claim at least one role.
An implementation claiming only the resolver role MAY make a role-only claim without claiming an RWP Record profile.
17.2. Conformance terminology {#conformance-terminology}
17.2.1. Record validation {#record-validation}
Record validation determines whether a specific Record or snapshot satisfies the applicable structural, semantic, and cryptographic requirements.
Depending on the applicable profile and Record type, validation MAY include:
-
DID and DID-document resolution;
-
schema resolution and schema validation;
-
metadata validation;
-
payload and snapshot hash verification;
-
signature verification;
-
version-graph integrity;
-
state and finalisation rules;
-
Case-link and Merkle-root validation; and
-
AssertionRecord predicate and resource validation.
A Record validation result applies only to the tested Record or snapshot. A successful validation result MUST NOT be interpreted as an implementation assessment, attestation, or certification.
17.2.2. Implementation assessment {#implementation-assessment}
Implementation assessment determines whether a named implementation version fulfils all requirements of one or more claimed RWP profiles and roles.
An implementation assessment MUST include positive and negative test cases relevant to every claimed profile and role.
An assessment MAY use an official RecordWeb test suite, an independently developed test suite, or another documented assessment method.
The result of an implementation assessment MAY be documented in a ConformanceRecord.
17.2.3. Attestation {#conformance-attestation}
An attestation is a signed statement by an identifiable attester about an implementation assessment.
An attestation MAY be self-attested or independently assessed.
A ConformanceRecord is the RWP SystemRecord used to preserve such an attestation.
17.2.4. Certification {#conformance-certification}
Certification is an institutional process outside the base RWP protocol.
A certification scheme MAY use ConformanceRecords, test suites, and assessment reports as evidence. RWP does not define or require an accreditation authority, certification mark, liability regime, or certification revocation procedure.
The presence of a ConformanceRecord MUST NOT by itself be interpreted as certification.
17.3. Profiles {#conformance-profiles}
17.3.1. RWP Information Record Conformant {#information-record-profile}
An implementation claiming RWP Information Record Conformant MUST satisfy the applicable RWP requirements for InformationRecords according to its claimed roles.
A producer claiming this profile MUST be able to create and finalise InformationRecords with the required identity, schema association, metadata, payload validation, integrity evidence, and version graph.
A custodian claiming this profile MUST retain and make retrievable the InformationRecord snapshots for which it acts as custodian.
A consumer claiming this profile MUST retrieve and validate InformationRecords in accordance with Record validation.
17.3.2. RWP Case Record Conformant {#case-record-profile}
An implementation claiming RWP Case Record Conformant MUST satisfy the applicable RWP requirements for CaseRecords according to its claimed roles.
A producer claiming this profile MUST create and finalise CaseRecords in accordance with CaseRecord Specification.
A Case implementation MAY reference InformationRecords or other Records managed by another RWP implementation. It is not required to create, store, or own those linked Records.
A CaseRecord producer or consumer MUST apply the applicable hard-link, soft-link, target-validation, and Merkle-root requirements.
17.3.3. RWP Assertion Record Conformant {#assertion-record-profile}
An implementation claiming RWP Assertion Record Conformant MUST satisfy the applicable RWP requirements for AssertionRecords according to its claimed roles.
A producer claiming this profile MUST create AssertionRecords with a valid SchemaRecord, a permitted predicate IRI, valid subject and object references, an asserting Agent, a time of assertion, and the required Record integrity evidence.
A consumer claiming this profile MUST validate AssertionRecords in accordance with AssertionRecord validation and Relationship Vocabulary scope.
A custodian claiming this profile MUST retain and make retrievable the AssertionRecord snapshots for which it acts as custodian.
17.3.4. RWP Relation Record Conformant {#relation-record-profile}
An implementation MAY claim RWP Relation Record Conformant only if it also claims both RWP Case Record Conformant and RWP Assertion Record Conformant.
RWP Relation Record Conformant introduces no requirements beyond the combined requirements of those two profiles.
17.3.5. RWP Source Integration Conformant {#source-integration-profile}
An implementation claiming RWP Source Integration Conformant MUST provide a source-provenance statement for every source object that it exposes to, captures for, or transfers into an RWP context.
The source integration profile is independent of RWP Record production. A source-adapter MAY claim this profile without creating an RWP DID, Record, or snapshot.
If a source-adapter creates and finalises an RWP InformationRecord, it MUST additionally satisfy the applicable requirements of RWP Information Record Conformant.
A source-provenance statement MUST contain:
{ "sourceSystem" : "https://jira.example.org" , "sourceId" : "PROJ-1234" , "sourceObjectType" : "jira:Issue" , "capturedAt" : "2026-08-13T00:00:00Z" , "capturedBy" : "did:rwp:example.org:source-adapter-001" , "sourceIntegrity" : "platform-versioned" }
The following fields are required:
-
sourceSystem; -
sourceId; -
sourceObjectType; -
capturedAt; -
capturedBy; and -
sourceIntegrity.
The combination of sourceSystem and sourceId MUST identify the source object unambiguously within the source system.
A source-provenance statement MAY additionally contain sourceUrl, sourceVersion, sourceRevision, sourceETag, sourceModifiedAt, exportPayload, exportPayloadHash, and exportFormat.
The sourceIntegrity value MUST be one of:
-
none: no independently usable source version or integrity signal is available; -
platform-versioned: the source system exposes a stable version, revision, ETag, or comparable platform-managed state indicator; -
source-signed: the source system exposes a verifiable source signature or equivalent cryptographic origin signal; or -
externally-hashed: the capture component has produced a hash over a defined export representation.
A source-integrity value describes guarantees available about the source object before or at capture. It MUST NOT be interpreted as a statement about the integrity of a subsequently created RWP Record.
17.4. Implementation roles {#conformance-roles}
RWP defines the following implementation roles:
| Role | Responsibility |
|---|---|
producer
| Creates a new Record or a new snapshot, including its finalisation where applicable. |
custodian
| Retains, manages, and makes Records or snapshots retrievable. |
consumer
| Retrieves and validates Records created or managed by another implementation. |
resolver
| Resolves did:rwp identifiers and returns the associated DID documents.
|
source-adapter
| Obtains, normalises, and exposes source-provenance information from a non-RWP source system. |
attester
| Creates and finalises a ConformanceRecord concerning an implementation assessment. |
A role describes a responsibility. It does not imply that an implementation fulfils requirements outside its claimed profiles, roles, or exercised capabilities.
17.5. Capability-bound requirements {#capability-bound-requirements}
Support for a SystemRecord capability MUST be required only where an implementation claims or exercises that capability.
| Capability | Information Record | Case Record | Assertion Record | Source Integration |
|---|---|---|---|---|
| Create a Record DID | MUST for a producer | MUST for a producer | MUST for a producer | Not required |
| Bind a created Record to a SchemaRecord | MUST for a producer | MUST for a producer | MUST for a producer | Not required |
| Create and validate immutable snapshots | MUST for a producer and consumer | MUST for a producer and consumer | MUST for a producer and consumer | Not required |
| Retain and retrieve snapshots | MUST for a custodian | MUST for a custodian | MUST for a custodian | Not required |
| Maintain a version graph | MUST for Records it creates or custodises | MUST for CaseRecords it creates or custodises | MUST for AssertionRecords it creates or custodises | Not required |
| Create and validate Case links | Not required | MUST for a producer and consumer | Not required | Not required |
| Create and validate Assertions | Not required | Not required | MUST for a producer and consumer | Not required |
| Validate external hard-link targets | Not required | MUST when finalising or validating a CaseRecord | MUST when finalising or validating an AssertionRecord | Not required |
| Provide source provenance | MAY | MAY | MAY | MUST |
| Support SchemaRecord | MUST where Records are created or validated against a schema | MUST where CaseRecords are created or validated against a schema | MUST where AssertionRecords are created or validated against a schema | Not required |
| Support CaseRecord | Not required | MUST | Not required | Not required |
| Support AssertionRecord | MUST only when creating, validating, or consuming AssertionRecords | MUST only when creating, validating, or consuming AssertionRecords | MUST | Not required |
| Support MergeRecord | MUST only when creating a merge snapshot | MUST only when creating a merge snapshot | MUST only when creating a merge snapshot | Not required |
| Support DeletionRecord | MUST only when executing payload deletion | MUST only when executing payload deletion | MUST only when executing payload deletion | Not required |
| Support MigrationRecord | MUST only when performing a documented migration | MUST only when performing a documented migration | MUST only when performing a documented migration | Not required |
| Support ConformanceRecord | MUST only for an attester | MUST only for an attester | MUST only for an attester | MUST only for an attester |
A resolver claiming the resolver role MUST satisfy the DID resolution requirements defined in DID Resolver Requirements and, where applicable, Resolver Requirements
.
An implementation MUST NOT claim support for a profile or role unless it fulfils all requirements applicable to that claim.
17.6. ConformanceRecord {#conformance-record}
A ConformanceRecord is a SystemRecord that preserves an attestation concerning an identifiable implementation version.
A ConformanceRecord MUST satisfy all normal Record requirements, including DID, schema association, snapshot integrity, finalisation, and the applicable signature requirements.
The owner of a finalised ConformanceRecord MUST be the attester identified in its payload.
The SchemaRecord for a ConformanceRecord MUST require at least the following payload structure:
{ "subject" : { "implementationDid" : "did:rwp:example.org:implementation-001" , "productName" : "Example Product" , "productVersion" : "1.2.3" }, "rwpVersion" : "0.0.3" , "claims" : [ { "profiles" : [ "RWP Information Record Conformant" ], "roles" : [ "producer" , "custodian" , "consumer" ] } ], "assessment" : { "method" : "self-attested" , "testSuite" : "did:rwp:recordweb.org:test-suite:0.0.3" , "tool" : "Example Validator" , "toolVersion" : "1.0.0" , "testedAt" : "2026-08-13T00:00:00Z" }, "attester" : "did:rwp:example.org:implementation-001" , "issuedAt" : "2026-08-13T00:00:00Z" , "expiresAt" : null , "evidence" : [ { "type" : "test-report" , "url" : "https://example.org/conformance/report.json" , "hash" : "sha256:..." } ], "supersedes" : [] }
The ConformanceRecord payload MUST contain:
-
subject.implementationDid; -
subject.productName; -
subject.productVersion; -
rwpVersion; -
at least one entry in
claims; -
assessment.method; -
attester; -
issuedAt; and -
evidence.
Every claim entry MUST contain at least one role. A claim entry containing a profile MUST identify only profiles defined by this specification or by a versioned extension specification.
The value of assessment.method MUST be one of:
-
self-attested; -
independently-assessed; or -
certified.
The value certified is reserved for use by an external certification regime. Its use MUST NOT imply that RecordWeb operates, endorses, or recognises that regime.
Each evidence entry MUST identify its type and MUST include either a resolvable url, a cryptographic hash, or both.
A ConformanceRecord MAY include expiresAt.
A newer ConformanceRecord MAY supersede an earlier ConformanceRecord. Supersession MUST NOT alter, invalidate, or remove the earlier attestation. A superseding ConformanceRecord MUST identify every superseded ConformanceRecord by DID.
17.7. Conformance claims and evidence {#conformance-claims}
An implementation MAY publish a ConformanceRecord.
An implementation claiming a profile or role SHOULD make its current ConformanceRecord or equivalent signed conformance statement discoverable.
A verifier or procuring organisation MUST evaluate a conformance claim according to its own trust policy, including the identity of the attester, the assessment method, the evidence, the implementation version, and the applicable RWP version.
A verifier MUST NOT treat self-attestation, independent assessment, and certification as equivalent assurance levels.
18. Annex A: Normative JSON Schemas
18.1. A.1 Snapshot Metadata Schema
{ "$schema" : "https://json-schema.org/draft/2020-12/schema" , "$id" : "https://recordweb.github.io/rwp/schemas/snapshot-metadata.json" , "title" : "RWP Snapshot Metadata" , "type" : "object" , "required" : [ "did" , "snapshotHash" , "recordType" , "schemaVersion" , "state" , "created" , "owner" , "parents" , "payloadHash" , "payloadFormat" ], "properties" : { "did" : { "type" : "string" , "pattern" : "^did:rwp:[^:]+:[^:]+$" }, "snapshotHash" : { "type" : "string" , "pattern" : "^sha256:[0-9a-f]{64}$" }, "recordType" : { "type" : "string" , "pattern" : "^did:rwp:" }, "schemaVersion" : { "type" : "string" , "pattern" : "^sha256:[0-9a-f]{64}$" }, "state" : { "type" : "string" , "enum" : [ "draft" , "finalized" ] }, "created" : { "type" : "string" , "format" : "date-time" }, "finalized" : { "type" : "string" , "format" : "date-time" }, "owner" : { "type" : "string" , "pattern" : "^did:rwp:" }, "parents" : { "type" : "array" , "items" : { "type" : "string" , "pattern" : "^sha256:[0-9a-f]{64}$" } }, "classification" : { "type" : "string" }, "retentionPolicy" : { "type" : "string" , "pattern" : "^did:rwp:" }, "tags" : { "type" : "array" , "items" : { "type" : "string" } }, "accessPolicy" : { "type" : [ "object" , "null" ] }, "payloadHash" : { "type" : "string" , "pattern" : "^sha256:[0-9a-f]{64}$" }, "payloadFormat" : { "type" : "string" }, "signature" : { "type" : "string" }, "deletionRegime" : { "type" : "string" , "enum" : [ "payload-only" , "full-delete" , "exempt" ] } } }
18.2. A.2 CaseRecord Payload Schema
{ "$schema" : "https://json-schema.org/draft/2020-12/schema" , "$id" : "https://recordweb.github.io/rwp/schemas/case-record.json" , "title" : "RWP CaseRecord Payload" , "type" : "object" , "required" : [ "recordDid" , "caseType" , "title" , "trigger" , "merkleRoot" ], "properties" : { "recordDid" : { "type" : "string" , "pattern" : "^did:rwp:" }, "caseType" : { "type" : "string" , "pattern" : "^did:rwp:" }, "title" : { "type" : "string" }, "trigger" : { "$ref" : "#/$defs/hardLink" }, "context" : { "type" : "array" , "items" : { "$ref" : "#/$defs/link" } }, "process" : { "type" : "array" , "items" : { "$ref" : "#/$defs/link" } }, "decision" : { "oneOf" : [{ "$ref" : "#/$defs/hardLink" }, { "type" : "null" }] }, "result" : { "type" : "array" , "items" : { "$ref" : "#/$defs/hardLink" } }, "merkleRoot" : { "type" : "string" , "pattern" : "^sha256:[0-9a-f]{64}$" } }, "$defs" : { "hardLink" : { "type" : "object" , "required" : [ "type" , "recordDid" , "snapshotHash" ], "properties" : { "type" : { "const" : "hard" }, "recordDid" : { "type" : "string" , "pattern" : "^did:rwp:" }, "snapshotHash" : { "type" : "string" , "pattern" : "^sha256:[0-9a-f]{64}$" }, "role" : { "type" : "string" } } }, "link" : { "type" : "object" , "required" : [ "type" , "recordDid" ], "properties" : { "type" : { "type" : "string" , "enum" : [ "hard" , "working" ] }, "recordDid" : { "type" : "string" , "pattern" : "^did:rwp:" }, "snapshotHash" : { "type" : "string" , "pattern" : "^sha256:[0-9a-f]{64}$" }, "role" : { "type" : "string" } } } } }
18.3. A.3 DeletionRecord Payload Schema
{ "$schema" : "https://json-schema.org/draft/2020-12/schema" , "$id" : "https://recordweb.github.io/rwp/schemas/deletion-record.json" , "title" : "RWP DeletionRecord Payload" , "type" : "object" , "required" : [ "deletionRecord" ], "properties" : { "deletionRecord" : { "type" : "object" , "required" : [ "targetDid" , "targetSnapshotHash" , "deletionRegime" , "legalBasis" , "requestedBy" , "approvedBy" , "deletedAt" ], "properties" : { "targetDid" : { "type" : "string" , "pattern" : "^did:rwp:" }, "targetSnapshotHash" : { "type" : "string" , "pattern" : "^sha256:[0-9a-f]{64}$" }, "deletionRegime" : { "type" : "string" , "enum" : [ "payload-only" , "full-delete" , "exempt" ] }, "legalBasis" : { "type" : "string" }, "requestedBy" : { "type" : "string" , "pattern" : "^did:rwp:" }, "approvedBy" : { "type" : "string" , "pattern" : "^did:rwp:" }, "deletedAt" : { "type" : "string" , "format" : "date-time" }, "retainedFields" : { "type" : "array" , "items" : { "type" : "string" } } } } } }
19. Annex B: Reference Implementation Notes (non-normative)
This annex is non-normative. It provides guidance for implementers and does not impose additional requirements.
19.1. B.1 Technology Choices
The following technology choices are recommended for a first RWP implementation:
| Component | Recommended | Notes |
|---|---|---|
| DID method | did:web or did:key during pilot
| Full did:rwp method requires resolver deployment
|
| Storage | PostgreSQL + object store (S3-compatible) | Metadata in relational DB; payloads in object store |
| Hashing | Node.js crypto.createHash('sha256')
| Standard library; no external dependency |
| Canonical JSON | canonicalize npm package
| Implements RFC 8785 |
| Signatures | @noble/ed25519
| Audited Ed25519 implementation |
| Schema validation | AJV (JSON Schema validator) | Supports JSON Schema 2020-12 |
19.2. B.2 Pilot Scope Recommendation
For a first pilot, the following Level 1 subset is recommended:
-
Implement DID generation and the DID Format and DID Document requirements
-
Implement snapshot creation with the Minimum Metadata Set
-
Implement Snapshot Hash Calculation
-
Implement the
draft→finalizedstate transition with Finalisation Requirements -
Implement Graph Structure without branch detection initially
This covers the critical path: a Record can be created, finalised, and its integrity verified. Cases and federation can be added in a subsequent iteration.