Copyright © 2026 the Contributors to the RecordWeb Protocol (RWP) v0.0.8, published by the RecordWeb Community Group under the W3C Community Contributor License Agreement (CLA). A human-readable summary is available.
Part I: Introduction & Conformance
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
2. Conformance and Implementation Claims
2.1. Scope of conformance
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 any conformance profile MUST claim at least one role, except that an implementation claiming only the resolver role MAY make a role-only claim as specified below.
An implementation claiming the resolver role MAY make a role-only claim without claiming an RWP Record profile. A role-only resolver claim MUST identify the resolver role and MUST NOT include an RWP Record profile unless the implementation also claims the roles required for that profile.
2.2. Conformance terminology
2.2.1. Record validation
2.2.2. 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 applies to the identified implementation version and claimed conformance scope. It does not establish the validity of every Record that the implementation has produced or may produce.
An implementation assessment MUST include positive and negative test cases relevant to every claimed profile and role.
The documented assessment method MUST identify the test cases, test data or test criteria, the assessment date, and the implementation version assessed.
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.
2.2.3. Attestation
An attestation is a signed statement by an identifiable attester about an implementation assessment.
An attestation MUST identify the assessed implementation version, the claimed profiles and roles, the applicable RWP version, the assessment method, and the attester.
An attestation MAY be self-attested or independently assessed.
A ConformanceRecord is the RWP SystemRecord used to express and preserve a durable, machine-readable attestation.
2.2.4. 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.
2.2.5. 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.
2.2.6. 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.
2.2.7. 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.
2.3. Profiles
2.3.1. RWP Information Record Conformant
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 versions for which it acts as custodian.
A consumer claiming this profile MUST retrieve and validate InformationRecords in accordance with Record validation.
2.3.2. RWP Case Record Conformant
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.
2.3.3. RWP Assertion Record Conformant
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 versions for which it acts as custodian.
2.3.4. RWP Relation Record Conformant
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.
2.3.5. RWP Source Integration Conformant
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 version.
A source-adapter MAY provide source content and source-provenance information for a source object to a producer by any mechanism agreed by the involved implementations.
The transfer mechanism, message format, transport, authentication, delivery semantics, retry behaviour, and operational workflow between a source-adapter and a producer are outside the scope of this specification. This scope boundary is deliberate and lasting; it is not intended to be narrowed by a future Source Integration binding without a dedicated specification change.
The provision of source content or source-provenance information by a source-adapter MUST NOT, by itself, be represented as the creation, finalization, transfer, or validation of an RWP Record or RWP version.
A producer that creates or finalizes an RWP Record from source content supplied by a source-adapter MUST fulfil all requirements applicable to that Record, including applicable schema validation, payload-format validation, version creation, integrity evidence, version-graph maintenance, and finalization requirements.
A source-adapter MAY also exercise the producer role. Where it does so, it MUST fulfil all requirements applicable to that role and Record. A receiving implementation MUST apply the applicable consumer and custodian requirements to the resulting RWP Record or version.
For every source object within its claimed scope, a conforming source-adapter MUST make the corresponding source-provenance statement available to the receiving RWP implementation or include it in the exported representation. The statement MAY be represented as JSON. Where the source-adapter retains the statement after transfer, it MUST make the statement retrievable by the combination of sourceSystem and sourceId.
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.
2.4. Implementation roles
RWP defines the following implementation roles:
-
A producer creates a new Record or a new version, including its finalisation where applicable. A producer MUST fulfil all requirements applicable to the profile, Record type, and operation it performs when creating, modifying, or finalising a Record representation.
-
A custodian retains, manages, and makes Records or versions retrievable. For each Record representation within its claimed scope, a custodian MUST preserve the information required to verify its applicable RWP integrity and versioning requirements. A custodian is not required to create a new Record or version solely by claiming the custodian role.
-
A consumer retrieves and validates Records created or managed by another implementation. A consumer MAY validate Records according to chapter Validation. A consumer MUST NOT represent an object as successfully validated unless the validation response is 200.
-
A resolver resolves
did:rwpidentifiers and returns the associated DID documents according to the applicable RWP DID-document requirements. -
A source-adapter obtains, normalises, and exposes source-provenance information from a non-RWP source system. A source-adapter MAY provide source content to a producer through a mutually agreed mechanism. A source-adapter MUST NOT represent a source-integrity statement as an RWP Record-integrity statement unless it has also created and validated the corresponding RWP Record representation.
-
An 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.
An implementation MAY perform more than one RWP role.
2.5. 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 immutable versions; retrieve and validate versions | A producer MUST create immutable versions. A consumer MUST retrieve and validate versions in accordance with Record validation. | A producer MUST create immutable versions. A consumer MUST retrieve and validate versions in accordance with Record validation. | A producer MUST create immutable versions. A consumer MUST retrieve and validate versions in accordance with Record validation. | Not required |
| Retain and retrieve versions | 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 references | Not required | MUST when finalising or validating a CaseRecord. The implementation MUST resolve each hard-link target and verify that the identified version belongs to the identified Record, subject to the applicable federation and offline-validation rules. | Where an AssertionRecord resource reference contains versionHash and the target version is resolvable, MUST verify that the version belongs to the identified Record. An unresolved external resource MUST be handled in accordance with the applicable AssertionRecord SchemaRecord.
| 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 version | MUST only when creating a merge version | MUST only when creating a merge version | 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, Global Namespace Registry.
An implementation MUST NOT claim support for a profile or role unless it fulfils all requirements applicable to that claim.
2.6. ConformanceRecord
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, version 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" , "assurance" : "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 RWP Source Integration Conformant MUST contain the source-adapter 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; or -
independently-assessed.
A ConformanceRecord MAY contain an assurance field. If present, its value MUST be one of:
-
self-attested; -
independently-assessed; or -
certified.
The assurance value describes the assurance context asserted for the claim. It is not an assessment method and does not replace the required assessment.method or evidence.
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. Each evidence entry that refers to externally retrievable evidence MUST include a resolvable url and a cryptographic hash of the referenced evidence bytes. An evidence entry without a url MUST include a cryptographic hash and sufficient embedded or separately identified content for an independent verifier to obtain the hashed evidence.
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.
2.7. Conformance claims and evidence
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.
2.8. Conformance Attestation {#section-conformance-attestation}
A conformance attestation is an inspectable statement about a claimed conformance scope and its assessment. A ConformanceRecord is the RWP SystemRecord used to express a durable, machine-readable conformance attestation.
Until an implementation publishes a ConformanceRecord, it MAY make its attestation available by another inspectable means. Such an attestation MUST still identify all information required by this section.
Part II: The Record Model
3. The Record
Every Record MUST consist of exactly four components:
3.1. Components
-
**Identity** — the DID of the Record (Record Identity (DID))
-
**Payload** — the content of the Record (Payload and Versions)
-
**Metadata** — descriptive dimensions of the Record (Metadata)
-
**Integrity** — the hash of the Record (Record Integrity)
{ "did" : "did:rwp:5264d2c3-d3b1-411c-829f-90e61165251a:f47ac10b-58cc-4372-a567-0e02b2c3d479" , "payload" : [], "metadata" : {}, "recordHash" : "sha256:9f8e7d6c5b4a3928170695a4b3c2d1e0f9e8d7c6b5a4938271605948372615" }
3.2. 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 . rw:Agent rdfs:subClassOf prov:Agent . rw:AgentRecord rdfs:subClassOf rw:Agent .
3.3. Record taxonomy
Every Record has one primary conceptual purpose. For the purposes of this specification, a Record is classified as an InformationRecord, a RelationRecord, an AgentRecord 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.
An AgentRecord is a Record whose primary purpose is to identifies an entity that bears responsibility for a Record, in the sense of prov:Agent ([PROVO]). The protocol representation and validation requirements for AgentRecords are defined in AgentRecord 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.
4. Record Identity (DID)
4.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)
4.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>:<record-id>[:<versionHash>][:<contentHash>]
The <namespace> component identifies the resolution scope of the DID.
The <record-id> component identifies a Record within that scope.
The <versionHash> component MUST NOT be part of the identity a Record.
The <contentHash> component MUST NOT be part of the identity a Record.
| Component | Requirement Level | Encoding | Meaning | Constraints |
|---|---|---|---|---|
did:rwp:
| MUST | fixed, lowercase | DID scheme and method | MUST be prefixed exactly as shown; no uppercase variants permitted |
<namespace>
| MUST | UUIDv4 (global) or implementation-defined (local) | Identifies the resolution scope of the DID | See below, globally or locally resolvable RWP DIDs |
<record-id>
| MUST | UUIDv4 (global) or implementation-defined (local) | Identifies a Record within the namespace scope | See below, globally or locally resolvable RWP DIDs |
<versionHash>
| MAY (optional) | 64 lowercase hex characters | References a specific version of the Record | MUST NOT carry an algorithm prefix (see also (Chapter Payload)[https://recordweb.github.io/rwp/#section-payload-definition]); MUST NOT be treated as part of DID identity; resolver behaviour undefined |
<contentHash>
| MAY (optional) | 64 lowercase hex characters | References a specific content of a Version of the Record | MUST NOT carry an algorithm prefix (see also (Chapter Payload)[https://recordweb.github.io/rwp/#section-payload-definition]); MUST NOT be treated as part of DID identity; resolver behaviour undefined |
| Further segments | MUST NOT (global); MAY (local) | --- | Reserved for local extension | Global: implementations MUST assume that no additional segments exist. Local: entirely implementation-defined, no constraint by this specification |
Examples:
| Type | DID-Example |
|---|---|
| Global | did:rwp:57b69e22-c8ae-4d5e-8675-ff454ea20fcc:f0168b06-3ac8-41c7-b529-1e548e2128bb
|
| Global with versionHash | did:rwp:57b69e22-c8ae-4d5e-8675-ff454ea20fcc:f0168b06-3ac8-41c7-b529-1e548e2128bb:1df47289b6c8374fa9d2d0399e3ccc88e2b0cd259b66fed96be6b92b69f3bbc2
|
| Local | did:rwp:example.com:f47ac10b
|
4.2.1. Globally resolvable RWP DIDs
A globally resolvable RWP DID MUST use a Universally Unique Identifier as <namespace> and <record-id>, both encoded as UUID version 4 in canonical textual representation.
The canonical UUIDv4 representation MUST:
-
consist of 36 characters;
-
use lowercase hexadecimal characters only;
-
use hyphens in the
8-4-4-4-12form; -
encode UUID version 4 and the RFC 4122 variant.
<namespace> and <record-id> MUST be opaque. They MUST NOT encode organisational names, geographical identifiers, network locations, resolver endpoints, or other routing semantics.
A DID conforming to this form is eligible for resolution through the RecordWeb Global Namespace Registry (RW GNR). Eligibility for global resolution does not imply that the Record, its metadata, or a DID Document is publicly accessible (see also Chapter (Access Control)[https://recordweb.github.io/rwp/#chapter-access-control]).
4.2.2. Locally scoped RWP DIDs
A DID whose <namespace> component does not conform to the canonical UUIDv4 syntax is a locally scoped RWP DID.
A locally scoped RWP DID MUST NOT be submitted to, registered in, or resolved through the RecordWeb Global Namespace Registry.
The <record-id> component of a locally scoped RWP DID is implementation-defined. It MAY use any syntax supported by the local resolution environment.
Resolution of a locally scoped RWP DID requires additional local knowledge, configuration, credentials, or an applicable local resolver. A client that does not possess such information MUST treat the DID as not globally resolvable and MUST NOT infer a resolver endpoint from the DID value.
4.2.3. Version and Content Hash component
A RWP DID MAY include optional segments.
The <versionHash> and <contentHash> component, where present, MUST be encoded as a bare SHA-256 digest in lowercase hexadecimal representation, consisting of exactly 64 characters. It MUST NOT carry an algorithm prefix (such as sha256:) or any other decorator, to avoid introducing an additional colon-delimited substructure within a colon-delimited DID segment.
The <versionHash> and the <contentHash>components are not part of the identity of the DID. The identity of an RWP DID is established exclusively by the <namespace> and <record-id> components. Two DIDs that differ only in the presence, absence, or value of a <versionHash> and <contentHash> component MUST be treated as identifying the same Record.
Where present, <versionHash> and <contentHash> MAY be used by a resolver as an optional aid when resolving the DID to a specific Record version.
4.2.4. Additional segments
For a locally scoped RWP DID, the structure of the DID beyond the <namespace>, <record-id>, <versionHash> and <contentHash> component, including the number, syntax, and semantics of any further colon-delimited segments, is entirely implementation-defined.
4.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), identified by an AgentRecord |
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.
A did:rwp resolution result MAY include the DID Resolution metadata properties versionId and versionTime.
The versionId MUST be calculated as follows:
-
Serialise the DID document fields
id,recordEndpoint,created,updated,currentVersion,controllerandverificationMethod(withoutversionIdandversionTimethemselves) as canonical JSON ([RFC8785]) -
Calculate SHA-256 over the result
versionId = SHA-256( canonicalize({id, recordEndpoint, created, updated, currentVersion, controller, verificationMethod}) )
4.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 403 where the resolver’s applicable access policy does not permit the requester to obtain the DID document
-
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.
5. Payload and Versions
5.1. Payload Structure
A Record MAY exist without a payload property and therefore without a Version.
When present, the payload property MUST contain one or more Version objects.
Each Version object MUST contain one or more Representations.
A Version object represents a specific materialised version of a Record. The versionHash property identifies that Version and provides its integrity value as defined in § 7.3 Version Hash Calculation.
A payload entry that does not contain at least one valid Representation is not a Version and MUST NOT be used as a payload entry.
The payload of a Record is an ordered array of versions. Each version is one immutable, versioned representation of the Record’s content at a specific point in time.
{ "payload" : [ { "versionHash" : "sha256:eef9dd41ca22103acab33303607139d2d39a9de0e8c5deb21373dd2184b7d57f" , "state" : "finalized" , "parents" : [ "sha256:6ce834139509cc20a5b1b0e0e8007f46fb14ef72532e87c4f33894d150e997c0" ], "createdAt" : "2026-05-31T14:00:00Z" , "modifiedAt" : "2026-05-31T15:30:00Z" , "signature" : "z3FttV7VjukA1LhqSDgOxupHy..." , "representations" : [ { "format" : "text/markdown" , "content" : "sample text" , "contentHash" : "sha256:3a84b2f508f5b93056e427aa67ad0c88d1b5366c6d423f59b61ece99286005d9" , "primary" : true , "role" : "source" }, { "format" : "application/pdf;profile=PDF-A-2b" , "ref" : "sample reference" , "primary" : false , "role" : "publication" } ] } ] }
| Field | Type | Required | Description |
|---|---|---|---|
versionHash
| SHA-256 | MUST | Contains the hash calculated in accordance with § 7.3 Version Hash Calculation. |
state
| Enum | MUST | draft or finalized; additional values permitted per type schema
|
parents
| Array<SHA-256> | MUST | Hashes of predecessor Versions; empty for the root Version |
createdAt
| ISO 8601 | MUST | Timestamp of Version creation |
modifiedAt
| ISO 8601 | MUST | Timestamp of the last change to this Version. For a finalized Version this is the finalisation timestamp, since a finalized version cannot change thereafter.
|
signature
| Multibase | MUST (when finalized) | Cryptographic signature of the record owner over the versionHash. See Signature Procedure.
|
representations
| Array | MUST (min. 1) | Format representations of this versions’s content, per Representation |
Each payload entry:
-
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 by its
versionHashfield -
MUST be immutable after its creation
-
MUST link to its predecessor versions by directed edges in the version graph (see Version Graph (DAG))
5.2. 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 |
5.3. 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 a Version (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.
A system MUST verify the versionHash after every finalisation before the Version is accepted as valid.
5.4. States and Transitions
5.4.1. State Model
Every Record Version has exactly one state. The state describes the validity and linkability status of the Version.
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)
5.4.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: Soft links per Hard and Soft Links MAY point to Records in any state, including draft Records.
5.4.3. Finalisation Requirements
A system MUST perform the following checks before finalising a Version:
-
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 versionHash. 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 Version and MUST return an error with a validation code.
5.4.4. Irreversibility of Finalisation
A finalized Version MUST NOT be reverted to the state draft.
Corrections, revisions, replacements, and other continuations of the same Record MUST be represented as a new Version of that Record.
Such a Version MUST:
-
retain the DID of the Record;
-
reference the superseded or revised versionHash 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.
5.5. Version Graph (DAG)
5.5.1. Graph Structure
The totality of all versions 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 Version MUST NOT be directly or indirectly its own ancestor
A system MUST check upon receipt of a new Version whether adding its parent references would create a cycle. If so, the Version MUST be rejected.
5.5.2. Nodes
Every node in the version graph is a versionHash entry in the payload array (see Version Fields).
5.5.3. Edges (Parent References)
An edge connects a Version (child) with its predecessor Version (parent).
-
A Version MAY have zero, one, or multiple parent references
-
A Version without parents is the root Version (first Version of the Record)
-
A Version with exactly one parent reference is a linear continuation
-
A Version with multiple parent references is a merge Version
Edge requirements:
-
Every parent reference MUST be a valid
versionHashof a known Version within the samepayloadarray -
Edges MUST NOT point to Versions of other Records. Cross-Record connections are made via links in the payload of a CaseRecord or AssertionRecord (CaseRecord Specification)
5.5.4. Branches
A branch arises when two or more new draft versions with the same parent reference emerge from a finalized Version.
-
Branches are explicitly permitted in RecordWeb and MUST be made visible by the system
-
A system MUST return all active branches (draft versions without successors) when a Record is retrieved
-
Branches MAY exist simultaneously as long as they are in state draft
5.5.5. Merges
A merge Version is a version with two or more parent references. It consolidates two branches.
Before a merge Version can be finalised, a MergeRecord MUST be created:
{ "mergeRecord" : { "mergedVersions" : [ "sha256:4b10e80a5c3e85acff145587d17a4a7561d517726dd1096d08eb30125d0bdf5f" , "sha256:5f42b3f3cb9330d01765552d5c612ac146738badb811f818a7f9318a9f762be8" ], "mergeReason" : "Consolidation after coordination between departments" , "mergedBy" : "did:rwp:5264d2c3-d3b1-411c-829f-90e61165251a:83fb7055-2779-45f6-a9db-98d1c852d3da" , "mergedAt" : "2026-05-31T16:00:00Z" , "mergeHash" : "sha256:4fdab47550acadcb5d60b9122848e11c78708859fe60b43e624537678d9b5a58" } }
The MergeRecord MUST be finalised before the merge version can be finalised.
5.5.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 version with an empty
parentsarray -
The
MergeRecordMUST reference the DIDs of the source Records (not their version hashes) -
The source Records MUST remain in state finalized and receive a metadata note
contributedTowith the DID of the new Record
5.6. Representations
A Representation describes one material form of the content of a Version.
Each Representation MUST contain exactly one of content or ref.
A Representation that contains content MUST contain contentHash.
A Representation that contains ref MUST NOT contain contentHash.
A Representation MUST NOT contain both content and ref.
A Version MAY carry multiple representations. This is provided in particular for the transition from working format (draft) to long-term format (finalised). Representations express the same content in different formats at the same point in the version graph; they MUST NOT be used to express different versions over time — that is the purpose of separate versionHash entries linked via parents.
If a Version contains multiple representations, ALL of the following MUST apply:
-
All representations MUST depict the same content
-
Exactly one representation MUST be designated as primary (
primary: true), this content will be used for further work (new Versions).
| Field | Type | Required | Description |
|---|---|---|---|
format
| string | MUST | MIME type incl. profiles |
content
| blob | MUST WHEN no ref exists | Contains the inline content of the Representation |
contentHash
| SHA-256 | MUST WHEN content exists | Contains the hash calculated in accordance with § 7.4 Content Hash Calculation |
ref
| string | MUST WHEN no content exists | Contains a reference to externally held, locally held, or physical content |
primary
| boolean | MUST | Exactly one representation MUST be true
|
role
| string | SHOULD | Semantic role: source, publication, preview, archive
|
5.7. Permitted Payload Content Types
RWP distinguishes three payload content 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.8. 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 |
6. Metadata
Metadata is the descriptive and governing information attached to a Record, independent of its payload. Unlike payload entries, metadata is not itself versioned as a sequence of versions; it MAY be updated in place. Metadata changes are nonetheless covered by the Record-level recordHash defined in Record Integrity, so that any change to metadata is detectable.
Metadata is organised into three groups: core, governance, and extensions.
{ "metadata" : { "core" : { "recordType" : "did:rwp:2fe14680-575a-4da4-aa65-6e72e0866e9b:5264d2c3-d3b1-411c-829f-90e61165251a" , "schemaVersion" : "sha256:a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae" }, "governance" : { "owner" : "did:rwp:bern.ch:unit-baubewilligung" , "classification" : "internal" , "retentionPolicy" : "did:rwp:bern.ch:retention-bauakten-30y" , "tags" : [ "building-permit" , "parcel-451" , "2026" ] }, "extensions" : [] } }
6.1. metadata.core
Every Record MUST contain the following core metadata fields:
| Field | Required | Type | Description |
|---|---|---|---|
recordType
| MUST | DID | Reference to the SchemaRecord of the type |
schemaVersion
| MUST | SHA-256 | Hash of the schema version against which the Record’s current version was validated |
6.2. metadata.governance
A Record MAY contain the following governance metadata fields. These fields express Records Management concerns (accountability, classification, retention, discoverability) as defined in [ISO15489].
| Field | Required | Type | Description |
|---|---|---|---|
owner
| SHOULD | DID | The person or organisational unit currently responsible for the Record, identified by an AgentRecord. See note below on the relationship between owner and version signature.
|
classification
| SHOULD | String | Protection level per the organisation’s internal scheme |
retentionPolicy
| SHOULD | DID | Reference to a retention rule. See Payload Deletion for how this field interacts with the applicable deletion regime. |
tags
| MAY | Array<String> | Free-text markers for search and filtering |
The owner field expresses organisational accountability and MAY change over the lifetime of a Record (e.g. following a transfer of responsibility). It is independent of the cryptographic signature carried by an individual version (see versionHash):
-
signatureprovides cryptographic evidence of who authorised a specific version’s content at finalisation, resolvable via the DID document’scontrollerfield. -
ownerprovides the current, human-readable statement of organisational responsibility for the Record as a whole, independent of which key signed the most recent version.
Where a schema defines signaturePolicy: system (see Finalisation Requirements), the signature identifies an authorised system key rather than a responsible person or unit. In this case, owner is the only field that expresses organisational accountability.
An implementation MUST NOT infer the current owner solely from the controller of the most recent version’s signature.
6.3. metadata.extensions
A Record MAY contain an extensions array. Each entry is a self-describing object that extends metadata with schema- or profile-specific information not defined by this specification.
Every extension entry MUST contain:
| Field | Required | Type | Description |
|---|---|---|---|
type
| MUST | DID | Identifies the SchemaRecord or profile that defines the semantics and additional fields of this extension entry |
Additional fields within an extension entry are defined entirely by the SchemaRecord or profile identified in type. This specification does not itself define any extension entry.
A Record MAY contain zero, one, or multiple extension entries. A conforming implementation MUST NOT require support for any extension type unless it claims the corresponding profile or capability.
Chapters of this specification that define an optional capability MAY specify that the capability’s data is carried as an extension entry. Where they do so, they identify the applicable type value and the additional fields of that entry.
7. Record Integrity
7.1. Purpose
The recordHash is a Record-level integrity value that covers the entire Record (its did, payload, and metadata) at the time the hash was calculated. It provides evidence that a Record has not been altered since that point, independent of whether the alteration occurred in payload or in metadata.
The recordHash is distinct from the signature carried by an individual Version (see Signature Procedure). A signature is an owner’s cryptographic authorisation of one specific versions’s content at finalisation. The recordHash is an unsigned, purely computational value; it does not require, and MUST NOT be interpreted as, an authorisation or attestation. It exists solely to make unauthorised or accidental modification of any part of the Record detectable.
7.2. Record Hash Calculation
The recordHash MUST be calculated as follows:
-
Serialise
did,payload, andmetadata(withoutrecordHashitself) as canonical JSON ([RFC8785]) -
Calculate SHA-256 over the result
recordHash = SHA-256( canonicalize({did, payload, metadata}) )
7.3. Version Hash Calculation
The versionHash hash MUST be calculated as follows:
-
Serialise the version fields
state,parents,createdAt,modifiedAt, andrepresentations(withoutversionHashandsignaturethemselves) as canonical JSON ([RFC8785]) -
Calculate SHA-256 over the result
versionHash = SHA-256( canonicalize({state, parents, createdAt, modifiedAt, representations}) )
7.4. Content Hash Calculation
The contentHash hash MUST be calculated as follows:
-
Serialise the version fields
format,content,primary, androle(withoutcontentHashitself) as canonical JSON ([RFC8785]) -
Calculate SHA-256 over the result
contentHash = SHA-256( canonicalize({format, content, primary, role}) )
7.5. Validation
RWP provides data structures and calculation rules that enable a Consumer to validate a RecordWeb object whenever the required information is available.
RWP does not require a Consumer to perform a Validation, does not prescribe when a Consumer performs a Validation, and does not prescribe the business, legal, or operational consequence of a Validation result.
A Consumer MAY perform a Validation at any time and MAY repeat a Validation.
A Consumer MUST NOT represent the integrity of a RecordWeb object as successfully validated unless it has recalculated the applicable hash in accordance with § 7 Record Integrity and the calculated value equals the declared hash value.
A Consumer MAY retain, exchange, display, or discard a Validation result. RWP does not require a Consumer to retain a Validation result or to create a RecordWeb Record for that purpose.
7.5.1. Validation Object
A Validation applies to exactly one validationObject identified by a did:rwp identifier.
The type of the identified object determines the applicable integrity calculation:
-
A Record identifier determines
recordHashcalculation. -
A Version identifier determines
versionHashcalculation. -
A Content identifier determines
contentHashcalculation.
A Validation of one object MUST NOT be represented as a Validation of any related Record, Version, or Content object unless those objects have been validated separately.
In particular, a Validation of a Record MUST NOT be represented as a Validation of all Versions of that Record. A Validation of a Version MUST NOT be represented as a Validation of all Representations or Content objects associated with that Version.
A Version identifier MAY additionally be validated by verifying signature over versionHash against a verification method of the DID document, in accordance with § 19.4.
7.5.2. Validation Result
When a Consumer retains or exchanges the result of a Validation, the result MUST contain:
-
validationObject, containing thedid:rwpidentifier of the validated object; -
validationTimestamp, containing the date and time at which the Consumer performed the Validation; and -
validationResponse, containing one of the Validation response codes defined in this Section.
The result is a statement by the Consumer that performed the Validation at the stated time. It is not a new state of the validated object and does not by itself establish the truth, authority, legal effect, or current availability of the validated object.
The following example records a successful Validation of one Version:
{
"validationObject": "did:rwp:5264d2c3-d3b1-411c-829f-90e61165251a:f47ac10b-58cc-4372-a567-0e02b2c3d479:eef9dd41ca22103acab33303607139d2d39a9de0e8c5deb21373dd2184b7d57f",
"validationTimestamp": "2026-09-16T12:55:00Z",
"validationResponse": 200
}
7.5.3. Validation Response Codes
The validationResponse property communicates the result of a Validation for the identified validationObject.
| Code | Name | Meaning |
| --- | --- | --- |
| 200 | OK | The applicable hash calculation was performed and the calculated hash equals the declared recordHash, versionHash, or contentHash. |
| 400 | Bad Request | The validationObject or the Validation request is syntactically or semantically invalid. |
| 403 | Forbidden | The identified object or information required to calculate its applicable hash exists or was identified, but the Consumer was not authorised to obtain it. |
| 404 | Not Found | The identified object, or information required to calculate its applicable hash, could not be found or resolved. A system MAY use this outcome to conceal the existence of an object it does not permit the Consumer to access. |
| 406 | Not Acceptable | The Consumer cannot process a required format, content type, representation, or other input required for the applicable calculation. |
| 422 | Unprocessable Content | The required input was available and the applicable hash calculation was performed, but the calculated hash does not equal the declared hash. |
| 424 | Failed Dependency | The Validation could not be completed because a required dependent resource or information was unavailable, incomplete, or could not be validated. Where the cause is a denied authorisation, 403 applies instead. |
The codes defined in this section are Validation result codes. They do not define HTTP response semantics.
When Validation is exposed through an HTTP API, server-side failures MAY be communicated using applicable HTTP 5xx response codes. Such API failures are not Validation result codes defined by RWP.
A Consumer MUST NOT represent the result 403, 404, 406, or 424 as evidence that the object is invalid or has been altered. Only 422 indicates that the applicable hash calculation was performed and the calculated hash does not equal the declared hash.
8. Payload Deletion
8.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 metadata.governance at the time of creation. This field is closely related to retentionPolicy (see metadata.governance): retentionPolicy references the applicable retention rule, while deletionRegime states the deletion behaviour required once that rule’s retention period has elapsed or an erasure request is granted. Implementations MUST respect this field and MAY enforce it at the infrastructure level.
8.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). |
8.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" , "targetVersion" : "sha256:version-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 content bytes are securely overwritten
-
The
hashfield of the affectedrepresentationsentry in the version is replaced with the string"deleted:<DeletionRecord-DID>" -
The Record’s
recordHashis recalculated to reflect the deletion -
The DID document’s
currentVersionfield is updated -
The DID resolver MUST return HTTP 410 for
full-deleteregimes
9. Record Types
9.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
metadata.core(see Metadata) -
is itself a Record of the type
SchemaRecord
9.2. Core Record Types
RWP defines the following core Record types (with DID Suffix):
Relation Records:
-
CaseRecord(see CaseRecord Specification) -
AssertionRecord(see AssertionRecord Specification)
System Records:
-
SchemaRecord(see SchemaRecord) -
ConformanceRecord(see ConformanceRecord) -
DeletionRecord(see DeletionRecord) -
MergeRecord(see MergeRecord) -
MigrationRecord(see MigrationRecord)
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.
Part III: Relation Records
10. CaseRecord Specification
10.1. Case as a specialised Record Type {#section-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.
10.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" , "versionHash" : "sha256:application-finalized-hash0000000000000000000000000000000000" }, "context" : [ { "type" : "hard" , "recordDid" : "did:rwp:bern.ch:zoning-plan-2024" , "versionHash" : "sha256:zoning-plan-hash0000000000000000000000000000000000000000000" , "role" : "Legal basis" }, { "type" : "hard" , "recordDid" : "did:rwp:bern.ch:case-planning-approval-001" , "versionHash" : "sha256:planning-approval-case-hash00000000000000000000000000000000" , "role" : "Related administrative proceeding" } ], "process" : [ { "type" : "hard" , "recordDid" : "did:rwp:bern.ch:minutes-site-inspection" , "versionHash" : "sha256:minutes-hash00000000000000000000000000000000000000000000000" , "role" : "Investigation" } ], "decision" : null , "result" : null , "merkleRoot" : "sha256:case-merkle-root..." }
10.3. Case Elements (normative)
Before a CaseRecord is finalised, its payload MUST contain all five Case element fields: trigger, context, process, decision, and result. The finalisation constraints for each element are defined in the following table. 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.
A draft CaseRecord MAY omit one or more Case element fields. Before finalisation, the system MUST validate and, where necessary, require completion of the Case element fields in accordance with this section.
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".
10.4. Hard and Soft 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 version of a target Record. A hard link MUST contain the target recordDid and versionHash (the target version’s hash, per versionHash).
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 version. 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.
A notification, callback, or other message received through Source Integration MAY trigger a refresh, retry, or user-interface indication. It MUST NOT replace the target resolution and validation required before a producer finalizes a CaseRecord containing a hard link.
10.5. CaseRecord-to-CaseRecord 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 version of the target CaseRecord through its recordDid and versionHash.
During finalisation of a referencing CaseRecord, the system MUST resolve and validate every target CaseRecord version referenced through a hard link, subject to the applicable federation and offline-validation rules.
The versionHash value 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 version 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 version and its Merkle root provide evidence of the Records directly linked by CaseRecord B at the time that version was finalised. A Record is a direct member of CaseRecord A only if CaseRecord A links to that Record explicitly.
10.6. Case Merkle Root
The Merkle root of a CaseRecord provides a cryptographically verifiable representation of the set of versions directly hard-linked by that CaseRecord.
For the purposes of this section, a versionHash value and a merkleRoot MUST be represented in the canonical textual form sha256: followed by the lowercase hexadecimal encoding of exactly 32 octets.
The Merkle root of a CaseRecord MUST be calculated as follows:
-
An implementation MUST collect the
versionHashvalue of every hard link in the CaseRecord, including every hard link to another CaseRecord. -
For each collected
versionHashvalue, the implementation MUST remove thesha256:prefix and decode the remaining hexadecimal value into its 32-octet SHA-256 digest value. -
The implementation MUST sort the decoded digest values in ascending lexicographic order over unsigned octets.
-
For each sorted digest value
d, the implementation MUST calculate a leaf node value as follows:
leaf = SHA-256(0x00 || d)
-
The implementation MUST construct successive tree levels by pairing adjacent node values from left to right. For each pair consisting of a left node value
land a right node valuer, the implementation MUST calculate the parent node value as follows:
parent = SHA-256(0x01 || l || r)
-
If a tree level contains an odd number of node values, the implementation MUST duplicate the final node value and use it as both the left and right input of the final pair at that level.
-
The sole node value remaining after the construction of all tree levels is the Merkle root. The implementation MUST serialise this value as
sha256:followed by its lowercase hexadecimal encoding.
In this section, || denotes byte concatenation. The values 0x00 and 0x01 are single-octet domain-separation tags. They MUST be included exactly as specified. The 0x00 tag distinguishes leaf-node inputs from all internal-node inputs. The 0x01 tag distinguishes internal-node inputs from leaf-node inputs.
A CaseRecord with no hard links MUST NOT be finalised. This specification therefore defines no Merkle root for an empty set of hard links.
The Merkle root of a CaseRecord MUST include the hash of each directly hard-linked target version. It MUST NOT recursively include the individual hard-link hashes or linked Record versions 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.
10.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 }
11. AssertionRecord Specification
11.1. Purpose and scope
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.
11.2. Assertion 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 versionHash field.
Where versionHash is present:
-
idMUST be the DID of an RWP Record; -
versionHashMUST identify a version of that Record (per versionHash); -
the AssertionRecord refers to that specific immutable version; and
-
a validating implementation MUST verify that the resolved version belongs to the identified Record where the version is resolvable.
Where versionHash 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.
11.3. Relationship 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.
11.4. Assertion 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" , "versionHash" : "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.
11.5. 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.
12. Relationship Vocabulary
12.1. Scope and conformance
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.
12.2. Provenance and version-lineage predicates {#section-relationship-vocabulary-provenance}
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.
12.2.1. Relationship to the RWP version graph {#subsection-assertionrecord-version-graph}
The RWP version graph is the authoritative representation of version succession between versions of the same Record.
A conforming implementation MUST determine RWP version 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 versions 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.
12.3. Contextual relationships {#section-relationship-vocabulary-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.
12.4. RiC-O 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.
12.5. 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.
12.6. Predicate declarations {#section-relationship-vocabulary-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.
Part IV: Agent Records
13. AgentRecord Specification
13.1. Purpose and scope
Every did:rwp identifying a responsible party MUST identify either:
-
an AgentRecord; or
-
an InformationRecord or AssertionRecord, where the applicable SchemaRecord explicitly permits a Record to act as the responsible party (for example, a
source-adapterimplementation identified by its own Record).
An implementation MUST NOT use a did:rwp identifier in such a field to identify an entity that is neither an AgentRecord, an InformationRecord nor an AssertionRecord. Where no such typed identity exists or is required, the field MUST use an identifier scheme other than did:rwp, or the applicable SchemaRecord MUST define an untyped-reference exception explicitly.
Examples:
| Type | Agent |
|---|---|
| DID identified | did:rwp:57b69e22-c8ae-4d5e-8675-ff454ea20fcc:adb9e1e3-4a51-42b2-870b-7bf2c560325f
|
| Other | sam.doe@example.com
|
Additional fields are defined entirely by extensions in the metadata of the SchemaRecord. RWP does not itself define any AgentRecord type.
Part V: System Records
14. 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" } } } }
14.1. Schema Versioning and Backward Compatibility
When a SchemaRecord is finalised in a new version, the following applies:
-
Existing versions 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
15. ConformanceRecord
16. DeletionRecord
See Payload Deletion
17. MergeRecord
See Merges and Cross-Record Merges.
18. MigrationRecord
TBDPart VI: Security & Privacy
19. Cryptographic Procedures
19.1. Hashing Procedure
RWP uses exclusively SHA-256 as the hashing procedure for:
-
Version hashes (
versionHash) -
Representation hashes (
representations[].hash) -
Record-level hashes (
recordHash) -
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.
19.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
19.3. Version Integrity
A system MUST check the integrity of a version on the following events:
-
Receipt of a version from an external system
-
Retrieval of a version for a linking operation
-
Periodic integrity check
If the integrity check fails, the system MUST:
-
Mark the version 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.
19.4. Signature Procedure
If the schema prescribes a signature (signaturePolicy: owner or signaturePolicy: system), the versionHash 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
versionHashhash value (as hex string) -
The signature MUST be stored in the
signaturefield of the version entry as a multibase-encoded value -
The key used MUST be published in the DID document of the record owner as a verification method
19.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]
20. Privacy and Security Considerations
RWP defines integrity, provenance, and interoperability requirements for Records. It does not define a general authorisation, confidentiality, key management, transport-security, retention, or data-protection regime. Implementations MUST apply the legal, organisational, and technical safeguards applicable to their deployment.
20.1. Privacy
A did:rwp identifier MUST NOT contain personal data or other information whose disclosure is restricted by the applicable rules.
The payload-only deletion regime removes payload bytes but retains the DID, metadata, and version graph. An implementation MUST NOT represent a payload-only deletion as full deletion of the Record.
20.2. Security
The integrity and signature procedures defined in Cryptographic Procedures provide evidence of the integrity of a version and, where applicable, of the verification method used to sign it. They do not by themselves establish confidentiality, authorisation, or the substantive correctness of a Record.
A notification or other externally received signal that refers to an RWP Record or version is non-authoritative. Before creating, finalising, modifying, deleting, linking to, or otherwise acting on the referenced Record or version, an implementation MUST independently resolve and validate it according to the applicable requirements of this specification.
Part VII: Miscellaneous
21. Federation
This chapter specifies how a system locates the DID Resolver responsible for a namespace and obtains the information needed to access a Record (Logistics). It also specifies the governance requirements of the GNR network (Constitution), which determine the basis on which a Global Namespace Identifier is registered and maintained.
A system MUST NOT treat successful resolution as evidence of trust. Whether a registration, a controller, or a resolver is accepted is a separate decision, see Trust Assumptions in [RWC].
21.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. 57b69e22-c8ae-4d5e-8675-ff454ea20fcc) 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.
21.2. Global Namespace Registry
21.2.1. Purpose
The Global Namespace Registry (GNR) is a distributed namespace directory for globally resolvable did:rwp identifiers. It maps a Global Namespace Identifier to the DID Resolver endpoint responsible for that namespace.
The GNR is not a DID Resolver. It does not resolve individual did:rwp identifiers, and it does not participate in Record access.
21.2.2. Scope 3
For a Global Namespace Identifier, as defined in Record Identity, the GNR MUST provide routing information identifying the DID Resolver responsible for resolving DIDs within that namespace.
The GNR MUST NOT resolve or store any of the following:
-
DID Documents;
-
Records or Record content;
-
access-control decisions;
-
organisational directory information.
A GNR deployment that stores or exposes any of the above is not conformant with RWP, irrespective of the underlying implementation technology.
21.2.3. Namespace Classification
A conforming GNR implementation MUST classify the namespace component of a did:rwp identifier, per Record Identity, before attempting resolution.
For a globally resolvable RWP DID, the GNR Resolver MUST obtain the DID Resolver endpoint through a configured GNR peer before attempting DID resolution.
For a locally scoped RWP DID, the GNR Resolver MUST NOT submit the local namespace to the GNR network. It MAY use a local resolution mechanism only where the necessary local context is available.
21.2.4. Global Namespace Registry Response
A GNR response MUST identify the namespace for which it was issued and MUST provide the currently applicable DID Resolver endpoint.
A successful namespace resolution MUST NOT be interpreted as evidence that:
-
the DID exists;
-
its DID Document is publicly accessible;
-
the associated Record can be accessed; or
-
the registrant of the namespace is the organisation it claims to be.
21.2.5. Resolution Obligation
A system MUST resolve the complete DID against the DID Resolver identified by the GNR.
A system MUST obtain RecordWeb service information from the resulting DID Document. A system MUST NOT infer a Record service endpoint directly from the namespace or DID value.
21.2.6. Platform
The GNR MUST be operated on Hyperledger Fabric. This requirement ensures interoperability between independently operated GNR nodes sharing a common ledger.
21.2.7. Registry Data Model
The GNR MUST accept registrations only for Global Namespace Identifiers, per Record Identity, and MUST reject registrations of locally scoped namespaces.
The Global Namespace Identifier MUST serve as the unique key for its current routing record. For every registered namespace, the current routing record MUST contain at least:
-
namespace; -
resolverEndpoint; -
registeredBy; -
registeredAt; -
txId.
The registeredBy value MUST be derived from the registrant’s authenticated network identity and MUST NOT be settable through transaction input.
21.2.8. Registry Operations
The GNR MUST provide an operation equivalent to ResolveNamespace(namespace) that returns the currently applicable routing record.
The GNR MUST provide an operation equivalent to GetNamespaceHistory(namespace) for authorised audit, verification, or migration use cases. Historical resolution MUST NOT be required for the normal client resolution path defined in § 21.2.5 Resolution Obligation.
The transaction history underlying GetNamespaceHistory MUST be immutable.
21.2.9. Governance Requirements
The GNR network MUST have a named operating organisation: RecordWeb Trust Association (recordweb.org).
The operating organisation MUST publish and maintain a governance framework applicable to the GNR network. The governance framework MUST define, at minimum:
-
eligibility, admission, suspension, withdrawal, and exclusion of participating organisations;
-
the process for registering, updating, suspending, and, where necessary, retiring Global Namespace Identifiers;
-
roles and authorisation requirements for network identities and namespace registrars;
-
endorsement and approval requirements for registry mutations and network configuration changes;
-
procedures for compromised keys, incorrect resolver endpoints, service outages, and other security incidents;
-
procedures for chaincode, platform configuration, and protocol-profile upgrades;
-
availability, monitoring, backup, recovery, and continuity requirements;
-
mechanisms for publishing trusted GNR peer entry points;
-
audit access and retention requirements for namespace-routing history.
The governance framework MAY define additional operational, organisational, legal, financial, or jurisdiction-specific provisions.
A conforming GNR deployment MUST implement its applicable governance decisions through network identities, endorsement policies, channel configuration, chaincode authorisation rules, or documented operational controls.
21.3. Cross-Namespace Links
A Record in namespace 57b69e22-c8ae-4d5e-8675-ff454ea20fcc MAY contain hard links to Records in other namespaces (e.g. did:rwp:f32bcec3-b453-4cbb-b416-132117325dc3:d460adee-e574-4064-86c2-fd58e3f678ed).
When resolving cross-namespace links, a system MUST:
-
Extract the namespace component from the linked DID
-
Discover the resolver endpoint via GNR lookup
-
Verify the version hash of the linked Record after retrieval
-
Cache the resolved version locally with the original hash for integrity verification
22. Access Control (Delegation Framework)
22.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.
A denied access is not an integrity result. How a denial is communicated is defined in Validation Response Codes.
22.2. Access Policy Block
An implementation claiming this optional capability MAY carry the accessPolicy block as an entry in the Record’s metadata.extensions array (see metadata.extensions), using the reserved type identifier did:rwp:recordweb.org:extension-access-policy:
{ "type" : "did:rwp:recordweb.org:extension-access-policy" , "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 |
An implementation MUST NOT require another implementation to support this extension unless both claim the applicable access-control capability.
22.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.
23. Optional Ledger Anchoring
23.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.
23.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.
23.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" , "caseVersionHash" : "sha256:case-finalized-version-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.
23.4. Anchoring Reference in the Case
When a CaseRecord has been anchored, the anchored CaseRecord version MUST NOT be modified. The system MAY create a new CaseRecord version that references the anchored predecessor through parents and contains an anchorReference field. The caseVersionHash in the ledger entry MUST always identify the immutable version that was actually anchored.
{ "anchorReference" : { "ledgerType" : "hyperledger-fabric" , "ledgerEndpoint" : "https://ledger.bern.ch/api/v1" , "txId" : "abc123..." , "anchoredAt" : "2026-05-31T16:00:00Z" } }
24. Optional Solid Pod Delivery
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 version (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.
Part VIII: Annexes
25. Annex A: Normative JSON Schemas
25.1. A.1 Record, Version, and Metadata Schemas
{ "$schema" : "https://json-schema.org/draft/2020-12/schema" , "$id" : "https://recordweb.github.io/rwp/schemas/record.json" , "title" : "RWP Record" , "type" : "object" , "required" : [ "did" , "payload" , "metadata" , "recordHash" ], "properties" : { "did" : { "type" : "string" , "pattern" : "^did:rwp:[^:]+:[^:]+$" }, "payload" : { "type" : "array" , "items" : { "$ref" : "#/$defs/version" } }, "metadata" : { "$ref" : "#/$defs/metadata" }, "recordHash" : { "type" : "string" , "pattern" : "^sha256:[0-9a-f]{64}$" } }, "$defs" : { "version" : { "type" : "object" , "required" : [ "version" , "state" , "parents" , "createdAt" , "modifiedAt" , "representations" ], "properties" : { "version" : { "type" : "string" , "pattern" : "^sha256:[0-9a-f]{64}$" }, "state" : { "type" : "string" , "enum" : [ "draft" , "finalized" ] }, "parents" : { "type" : "array" , "items" : { "type" : "string" , "pattern" : "^sha256:[0-9a-f]{64}$" } }, "createdAt" : { "type" : "string" , "format" : "date-time" }, "modifiedAt" : { "type" : "string" , "format" : "date-time" }, "signature" : { "type" : "string" }, "representations" : { "type" : "array" , "minItems" : 1 , "items" : { "$ref" : "#/$defs/representation" } } } }, "representation" : { "type" : "object" , "required" : [ "format" , "hash" , "primary" ], "properties" : { "format" : { "type" : "string" }, "hash" : { "type" : "string" , "pattern" : "^sha256:[0-9a-f]{64}$" }, "primary" : { "type" : "boolean" }, "role" : { "type" : "string" , "enum" : [ "source" , "publication" , "preview" , "archive" ] } } }, "metadata" : { "type" : "object" , "required" : [ "core" ], "properties" : { "core" : { "type" : "object" , "required" : [ "recordType" , "schemaVersion" ], "properties" : { "recordType" : { "type" : "string" , "pattern" : "^did:rwp:" }, "schemaVersion" : { "type" : "string" , "pattern" : "^sha256:[0-9a-f]{64}$" } } }, "governance" : { "type" : "object" , "properties" : { "owner" : { "type" : "string" , "pattern" : "^did:rwp:" }, "classification" : { "type" : "string" }, "retentionPolicy" : { "type" : "string" , "pattern" : "^did:rwp:" }, "tags" : { "type" : "array" , "items" : { "type" : "string" } }, "deletionRegime" : { "type" : "string" , "enum" : [ "payload-only" , "full-delete" , "exempt" ] } } }, "extensions" : { "type" : "array" , "items" : { "type" : "object" , "required" : [ "type" ], "properties" : { "type" : { "type" : "string" , "pattern" : "^did:rwp:" } } } } } } } }
25.2. A.2 CaseRecord Payload Schema
This schema defines structural validation only. State-dependent finalisation requirements, including the required presence of all five Case element fields, the prohibition of soft links and the minimum cardinality of result, are defined in Case Elements and Hard and Soft Links.
{ "$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" , "context" , "process" , "decision" , "result" , "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" , "minItems" : 1 , "items" : { "$ref" : "#/$defs/hardLink" } }, "merkleRoot" : { "type" : "string" , "pattern" : "^sha256:[0-9a-f]{64}$" } }, "$defs" : { "hardLink" : { "type" : "object" , "required" : [ "type" , "recordDid" , "version" ], "properties" : { "type" : { "const" : "hard" }, "recordDid" : { "type" : "string" , "pattern" : "^did:rwp:" }, "version" : { "type" : "string" , "pattern" : "^sha256:[0-9a-f]{64}$" }, "role" : { "type" : "string" } } }, "link" : { "type" : "object" , "required" : [ "type" , "recordDid" ], "properties" : { "type" : { "type" : "string" , "enum" : [ "hard" , "soft" ] }, "recordDid" : { "type" : "string" , "pattern" : "^did:rwp:" }, "version" : { "type" : "string" , "pattern" : "^sha256:[0-9a-f]{64}$" }, "role" : { "type" : "string" } } } } }
25.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" , "targetVersion" , "deletionRegime" , "legalBasis" , "requestedBy" , "approvedBy" , "deletedAt" ], "properties" : { "targetDid" : { "type" : "string" , "pattern" : "^did:rwp:" }, "targetVersion" : { "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" } } } } } }
26. Annex B: Reference Implementation Notes (non-normative)
This annex is non-normative. It provides guidance for implementers and does not impose additional requirements.
26.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 |
26.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 version creation with the Metadata
-
Implement Version 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.