RecordWeb Protocol (RWP)

Draft Community Group Report,

More details about this document
This version:
https://recordweb.github.io/rwp/
Previous Versions:
Version History:
https://github.com/recordweb/rwp/commits/main/index.bs
Issue Tracking:
GitHub
Editor:

Abstract

This is the input for the proposed Community Group. The RecordWeb Protocol (RWP) is the normative technical specification for the creation, identification, versioning, linking, and cryptographic proof of Records in RWP-compliant systems. It defines the requirements a system must fulfil in order to create, manage, link, and prove Records in the sense of the RecordWeb Concept ([RWC]). RWP uses RFC 2119 compliance terminology and covers Record identity (DID), version structure, payload validation, version graph (DAG), Case specification, integrity procedures, federation, and payload deletion across 14 chapters and three normative annexes.

Status of this document

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:

This document does not apply to:

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.

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:

  1. the implementation;

  2. the implementation version;

  3. the RWP version;

  4. the claimed profile or profiles, if applicable;

  5. the claimed role or roles;

  6. the assessment method; and

  7. 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

See 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:

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:

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:

  1. 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.

  2. 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.

  3. 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.

  4. A resolver resolves did:rwp identifiers and returns the associated DID documents according to the applicable RWP DID-document requirements.

  5. 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.

  6. 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:

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:

A ConformanceRecord MAY contain an assurance field. If present, its value MUST be one of:

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

  1. **Identity** — the DID of the Record (Record Identity (DID))

  2. **Payload** — the content of the Record (Payload and Versions)

  3. **Metadata** — descriptive dimensions of the Record (Metadata)

  4. **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:

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:

<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:

  1. Serialise the DID document fields id, recordEndpoint, created, updated, currentVersion, controller and verificationMethod (without versionId and versionTime themselves) as canonical JSON ([RFC8785])

  2. 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:

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:

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:

  1. Validate the payload against the finalised format of the schema

  2. If the current payload is not in archival-grade format: convert automatically or request conversion from the operator

  3. Store both formats as multi-representation in a Version (SHOULD)

  4. 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:

  1. Schema validation: Payload conforms to the schema in the version defined for finalized

  2. Format validation: Payload format conforms to the payloadFormats.finalized requirements of the schema

  3. Mandatory field check: All MUST metadata fields are present and correctly typed

  4. Owner signature: If the schema defines signaturePolicy: owner, the record owner MUST have cryptographically signed the versionHash. For signaturePolicy: system, the signature MAY be generated by an authorised system key. For signaturePolicy: none, signature validation is omitted.

  5. 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:

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):

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).

Edge requirements:

5.5.4. Branches

A branch arises when two or more new draft versions with the same parent reference emerge from a finalized Version.

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:

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:

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):

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:

  1. Serialise did, payload, and metadata (without recordHash itself) as canonical JSON ([RFC8785])

  2. 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:

  1. Serialise the version fields state, parents, createdAt, modifiedAt, and representations (without versionHash and signature themselves) as canonical JSON ([RFC8785])

  2. 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:

  1. Serialise the version fields format, content, primary, and role (without contentHash itself) as canonical JSON ([RFC8785])

  2. 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 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:

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:

  1. The payload content bytes are securely overwritten

  2. The hash field of the affected representations entry in the version is replaced with the string "deleted:<DeletionRecord-DID>"

  3. The Record’s recordHash is recalculated to reflect the deletion

  4. The DID document’s currentVersion field is updated

  5. The DID resolver MUST return HTTP 410 for full-delete regimes

9. Record Types

9.1. Record Type Definition

Every Record MUST be assigned to a Record type. A Record type:

9.2. Core Record Types

RWP defines the following core Record types (with DID Suffix):

Relation Records:

System Records:

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".

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.

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:

  1. An implementation MUST collect the versionHash value of every hard link in the CaseRecord, including every hard link to another CaseRecord.

  2. For each collected versionHash value, the implementation MUST remove the sha256: prefix and decode the remaining hexadecimal value into its 32-octet SHA-256 digest value.

  3. The implementation MUST sort the decoded digest values in ascending lexicographic order over unsigned octets.

  4. For each sorted digest value d, the implementation MUST calculate a leaf node value as follows:

leaf = SHA-256(0x00 || d)
  1. 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 l and a right node value r, the implementation MUST calculate the parent node value as follows:

parent = SHA-256(0x01 || l || r)
  1. 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.

  2. 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:

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:

  1. the predicate value is an absolute IRI;

  2. subject, predicate, and object are present;

  3. the subject and object satisfy the constraints declared for the predicate;

  4. the asserting Agent and time of assertion are available; and

  5. 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:

  1. an applicable PROV-O predicate defined by this specification; or

  2. 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:

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:

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:

  1. the exact predicate IRI;

  2. the RiC-O version to which the declaration applies;

  3. the semantics and direction of the predicate, with reference to the applicable RiC-O definition;

  4. the permitted subject kinds;

  5. the permitted object kinds;

  6. any additional RWP validation requirements; and

  7. 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:

  1. an absolute predicate IRI;

  2. a stable, versioned definition of its semantics;

  3. the relationship direction;

  4. the permitted subject kinds;

  5. the permitted object kinds;

  6. the required or permitted assertion metadata;

  7. the validation requirements; and

  8. 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:

  1. an AgentRecord; or

  2. an InformationRecord or AssertionRecord, where the applicable SchemaRecord explicitly permits a Record to act as the responsible party (for example, a source-adapter implementation 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:

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:

15. ConformanceRecord

See ConformanceRecord

16. DeletionRecord

See Payload Deletion

17. MergeRecord

See Merges and Cross-Record Merges.

18. MigrationRecord

TBD

Part VI: Security & Privacy

19. Cryptographic Procedures

19.1. Hashing Procedure

RWP uses exclusively SHA-256 as the hashing procedure for:

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:

19.3. Version Integrity

A system MUST check the integrity of a version on the following events:

If the integrity check fails, the system MUST:

  1. Mark the version as compromised

  2. Mark all dependent Records as integrity-warning

  3. Log the incident in the system log with timestamp and discrepancy

  4. 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:

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:

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:

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:

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:

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:

  1. Extract the namespace component from the linked DID

  2. Discover the resolver endpoint via GNR lookup

  3. Verify the version hash of the linked Record after retrieval

  4. 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:

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:

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:

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:

  1. Implement DID generation and the DID Format and DID Document requirements

  2. Implement version creation with the Metadata

  3. Implement Version Hash Calculation

  4. Implement the draft → finalized state transition with Finalisation Requirements

  5. 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.

Conformance

Document conventions

Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this document are to be interpreted as described in RFC 2119. However, for readability, these words do not appear in all uppercase letters in this specification.

All of the text of this specification is normative except sections explicitly marked as non-normative, examples, and notes. [RFC2119]

Examples in this specification are introduced with the words “for example” or are set apart from the normative text with class="example", like this:

This is an example of an informative example.

Informative notes begin with the word “Note” and are set apart from the normative text with class="note", like this:

Note, this is an informative note.

Index

Terms defined by this specification

References

Normative References

[PROVO]
PROV-O: The PROV Ontology. URL: https://www.w3.org/TR/prov-o/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. 1997. URL: https://www.rfc-editor.org/rfc/rfc2119
[RFC3987]
Internationalized Resource Identifiers (IRIs). 2005. URL: https://www.rfc-editor.org/rfc/rfc3987

Non-Normative References

[DID-CORE]
Decentralized Identifiers (DIDs) v1.0. URL: https://www.w3.org/TR/did-core/
[HYPERLEDGER]
Hyperledger Fabric. URL: https://www.hyperledger.org/projects/fabric
[ISO15489]
Information and documentation — Records management, Part 1: Concepts and principles. 2016. URL: https://www.iso.org/standard/62542.html
[JSON-SCHEMA]
JSON Schema: A Media Type for Describing JSON Documents. 2020. URL: https://json-schema.org/draft/2020-12/json-schema-core
[RFC8037]
CFRG Elliptic Curves for JOSE and COSE (Ed25519). 2017. URL: https://www.rfc-editor.org/rfc/rfc8037
[RFC8785]
JSON Canonicalization Scheme (JCS). 2020. URL: https://www.rfc-editor.org/rfc/rfc8785
[RICO]
Records in Contexts Ontology (RiC-O). 2024-09-04. URL: https://www.ica.org/standards/RiC/RiC-O_1-0-2.html
[RWC]
RecordWeb CG. RecordWeb Concept (RWC). CG-DRAFT. URL: https://recordweb.github.io/rwc/