RecordWeb Protocol (RWP)

Draft Community Group Report,

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

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), snapshot 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

This specification was published by the Web Platform Incubator Community Group. It is not a W3C Standard nor is it on the W3C Standards Track. Please note that under the W3C Community Contributor License Agreement (CLA) there is a limited opt-out and other conditions apply. Learn more about W3C Community and Business Groups.

1. Introduction

1.1. Status of This Document

This document is a CG Draft of the RecordWeb Community Group. It is an Editor’s Draft and does not represent a W3C standard or endorsed position.

The published baseline is available at [ZENODO-RWP] (Version 0.1, DOI: 10.5281/zenodo.20475345). This working document reflects ongoing development toward the Community Group deliverable.

Feedback is invited via GitHub Issues.

2. 1 Introduction and Scope

2.1. 1.1 Purpose

The RecordWeb Protocol (RWP) defines the technical standards for the creation, identification, versioning, linking, and proof of Records in an RWP-compliant system.

RWP is the normative counterpart to the RecordWeb Concept ([RWC]). The RWC describes the conceptual foundations; RWP translates these into binding technical requirements that MUST be observed for interoperable implementation.

2.2. 1.2 Scope

This document applies to:

This document does not apply to:

Standard Relationship
[ISO15489] RWP structurally implements the requirements for authenticity, reliability, integrity, and usability
[ISO14721] (OAIS) RWP is complementary; finalised Records MAY be migrated to long-term archives according to OAIS principles
[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; this is non-normative
[ECH-0164] RWP maps the eCH information lifecycle as states; no structural dependency
[RWC] v1.0 Conceptual foundation; in the event of conflict, RWP takes precedence

2.4. 1.4 Versioning of This Document

This document uses semantic versioning (SemVer): MAJOR.MINOR.PATCH.

The current version is 0.0.1 (Draft — not yet approved for production implementations).

3. 2 Record Identity (DID)

3.1. 2.1 Requirements for Record Identity

Every Record MUST possess a globally unique, permanent identity.

This identity:

3.2. 2.2 DID Format

The identity of a Record MUST be expressed as a Decentralized Identifier (DID) in accordance with [DID-CORE].

Normative format: did:rwp:{namespace}:{unique-id}

Component Requirement
did Literal; immutable
rwp DID method for RecordWeb Protocol; immutable
<namespace> Identifier of the organisation or system; MUST be uniquely registered. During the transition phase, a namespace MAY be formed on the basis of the DNS domain name of the organisation (e.g. did:rwp:bern.ch:<uuid>).
<unique-id> Unique identifier of the Record within the namespace; MUST be a UUID v4 or a cryptographically equivalent random value

Example: did:rwp:bern.ch:f47ac10b-58cc-4372-a567-0e02b2c3d479

3.3. 2.3 DID Document

For every Record DID, a DID document MUST exist containing the following fields:

{
  "@context": "https://www.w3.org/ns/did/v1",
  "id": "did:rwp:bern.ch:f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "recordEndpoint": "https://records.bern.ch/api/v1/records/f47ac10b",
  "created": "2026-05-31T14:00:00Z",
  "updated": "2026-05-31T14:00:00Z",
  "currentVersion": "sha256:e3b0c44298fc1c149afb...",
  "controller": "did:rwp:bern.ch:controller-001",
  "verificationMethod": [
    {
      "id": "did:rwp:bern.ch:f47ac10b#key-1",
      "type": "Ed25519VerificationKey2020",
      "controller": "did:rwp:bern.ch:controller-001",
      "publicKeyMultibase": "z6MkhaXgBZDvotDkL..."
    }
  ]
}
Field Required Description
@context MUST W3C DID Context URI
id MUST DID of the Record; identical to the Record DID
recordEndpoint MUST URL at which the Record can be retrieved
created MUST ISO 8601 timestamp of DID creation
updated MUST ISO 8601 timestamp of last DID document update
currentVersion MUST Content hash of the current finalised version (empty for pure draft)
controller MUST DID of the controlling entity (organisation or person)
verificationMethod MUST At least one verification method for signature validation

The DID document MUST be updated when the physical storage location changes (recordEndpoint, updated, currentVersion). All other fields MUST NOT be changed.

3.4. 2.4 DID Resolver Requirements

An RWP-compliant system MUST provide a DID resolver that:

4. 3 Record Structure

4.1. 3.1 Overview

Every Record MUST consist of exactly three components:

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

  2. **Payload** — the content of the Record (Chapter 4)

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

Together, these three components form a snapshot — an immutable, versioned representation of the Record at a specific point in time.

4.2. 3.2 Snapshot Definition

A snapshot is the atomic unit of versioning in RecordWeb.

A snapshot MUST fulfil the following properties:

4.3. 3.3 Minimum Metadata Set

Every snapshot MUST contain the following metadata fields:

{
  "did": "did:rwp:bern.ch:f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "snapshotHash": "sha256:e3b0c44298fc1c149afb4c8996fb924...",
  "recordType": "did:rwp:ech-standards.ch:schema-baubewilligung-antrag",
  "schemaVersion": "sha256:a665a45920422f9d417e4867efdc4fb8a...",
  "state": "finalized",
  "created": "2026-05-31T14:00:00Z",
  "finalized": "2026-05-31T15:30:00Z",
  "owner": "did:rwp:bern.ch:user-petra-muster",
  "parents": ["sha256:previousSnapshotHash..."],
  "classification": "internal",
  "retentionPolicy": "did:rwp:bern.ch:retention-bauakten-30y",
  "tags": ["building-permit", "parcel-451", "2026"],
  "accessPolicy": null,
  "payloadHash": "sha256:d2d2d2d2d2...",
  "payloadFormat": "application/pdf;profile=PDF-A-2b",
  "signature": "z3FttV7..."
}
Field Required Type Description
did MUST DID Identity of the Record
snapshotHash MUST SHA-256 Hash of this snapshot (incl. payload and metadata)
recordType MUST DID Reference to the SchemaRecord of the type
schemaVersion MUST SHA-256 Hash of the schema version against which this snapshot was validated
state MUST Enum draft or finalized; additional values permitted per type schema
created MUST ISO 8601 Timestamp of snapshot creation
finalized MUST (when finalized) ISO 8601 Timestamp of finalisation
owner MUST DID Responsible person or organisational unit
parents MUST Array<SHA-256> Hashes of predecessor snapshots; empty for first snapshot
classification SHOULD String Protection level per the organisation’s internal scheme
retentionPolicy SHOULD DID Reference to retention rule
tags MAY Array<String> Free-text markers for search and filtering
accessPolicy MAY Object|null Delegated authorisation model (Chapter 11)
payloadHash MUST SHA-256 Hash of the payload
payloadFormat MUST MIME-Type Format of the primary payload incl. profiles
signature MUST (when finalized) Multibase Cryptographic signature of the record owner over the snapshot hash

4.4. 3.4 Snapshot Hash Calculation

The snapshotHash MUST be calculated as follows:

  1. Serialise the metadata fields (without snapshotHash itself) as canonical JSON ([RFC8785])

  2. Concatenate: canonicalMetadataJSON || payloadBytes

  3. Calculate SHA-256 over the result

snapshotHash = SHA-256( canonicalize(metadata \ {snapshotHash}) || payloadBytes )

A system MUST verify the snapshotHash after every finalisation before the snapshot is accepted as valid.

5. 4 Payload and Formats

5.1. 4.1 Payload Definition

The payload of a Record is the content the Record carries, the actual information.

A payload:

5.2. 4.2 Permitted Payload Types

RWP distinguishes three payload categories:

Category Description Examples
Structured Machine-readable, schema-validatable data JSON, XML, YAML
Documentary Human-readable documents with defined structure PDF/A, DOCX, ODT, Markdown
Binary Non-textual data with descriptive schema TIFF, JPEG 2000, MP4, ZIP

5.3. 4.3 Multi-Representation

A snapshot MAY carry multiple representations of the same payload. This is provided in particular for the transition from working format (draft) to long-term format (finalised).

If a snapshot contains multiple representations, ALL of the following MUST apply:

{
  "payloadRepresentations": [
    {
      "format": "text/markdown",
      "hash": "sha256:aabbcc...",
      "primary": false,
      "role": "source"
    },
    {
      "format": "application/pdf;profile=PDF-A-2b",
      "hash": "sha256:ddeeff...",
      "primary": true,
      "role": "publication"
    }
  ]
}
Field Required Description
format MUST MIME type incl. profiles
hash MUST SHA-256 of this representation
primary MUST Exactly one representation MUST be true
role SHOULD Semantic role: source, publication, preview, archive

5.4. 4.4 Format Requirements per State

The schema of a Record type MUST define the permitted payload formats for each state. If a schema contains no explicit format requirements, the following defaults apply:

State Permitted formats (default)
draft All MIME types not explicitly excluded in the schema of the Record type
finalized Only formats from the RWP list of archival-grade formats (Annex A, Table A-1)

RWP archival-grade formats (normative):

MIME Type Format Suitability
application/pdf;profile=PDF-A-1b PDF/A-1b Documents without embedded multimedia
application/pdf;profile=PDF-A-2b PDF/A-2b Documents with embedded files
application/pdf;profile=PDF-A-3b PDF/A-3b Documents with arbitrary attachments
text/xml XML (well-formed) Structured data
application/json JSON Structured data (with schema reference)
image/tiff TIFF Raster images
image/jp2 JPEG 2000 Raster images (near-lossless)
text/plain;charset=UTF-8 Plain Text UTF-8 Pure text documents
text/markdown CommonMark Markdown Source format with publication representation

5.5. 4.5 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 the snapshot (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.

6. 5 Record Types and Schemas

6.1. 5.1 Record Type Definition

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

6.2. 5.2 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" }
    }
  }
}

6.3. 5.3 Core Record Types (normative)

RWP defines the following core Record types that every compliant system MUST support:

Type Name DID Suffix Description
SchemaRecord schema-record Definition of a Record type
MergeRecord merge-record Documentation of a merge act
DeletionRecord deletion-record Log of a payload deletion (Chapter 13)
CaseRecord case-record Case (Chapter 8)
MigrationRecord migration-record Log of a system migration

Additional Record types MAY be defined by organisations or standards bodies. They MUST be published as SchemaRecords and be resolvable via a DID.

6.4. 5.4 Schema Versioning and Backward Compatibility

When a SchemaRecord is finalised in a new version, the following applies:

7. 6 States and Transitions

7.1. 6.1 State Model

Every Record snapshot has exactly one *state. The state describes the validity and linkability status of the snapshot.

Core states (normative, for all Record types):

State Linkable Immutable Description
draft NO NO Being processed; content may change
finalized YES YES Complete; content cryptographically secured

Record types MAY define additional states. These MUST be specified in the SchemaRecord and MUST be reachable from one of the core states or lead into one.

Example of an extended state machine for type "contract":

draft → in-review → finalized
↓
rejected (terminal state, not linkable)

7.2. 6.2 Linkability

A Record MUST NOT be used as the target of a hard link when its current state is draft.

A system MUST return an error when an attempt is made to set a hard link to a draft Record.

Exception: Working references (soft links) per Section 8.4 MAY point to draft Records.

7.3. 6.3 Finalisation Requirements

A system MUST perform the following checks before finalising a snapshot:

  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 snapshot hash. 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 snapshot and MUST return an error with a validation code.

7.4. 6.4 Irreversibility of Finalisation

A finalized snapshot MUST NOT be reverted to the state draft.

Corrections to a finalized Record are made exclusively by creating a new snapshot with:

8. 7 Version Graph (DAG)

8.1. 7.1 Graph Structure

The totality of all snapshots of a Record and their parent-child relationships forms the version graph.

The version graph MUST be a Directed Acyclic Graph (DAG):

A system MUST check upon receipt of a new snapshot whether adding its parent references would create a cycle. If so, the snapshot MUST be rejected.

8.2. 7.2 Nodes

Every node in the version graph is a snapshot per Section 3.2.

Property Requirement
Unique identity SHA-256 of the snapshot (snapshotHash); MUST be unique
Immutability Finalised nodes MUST NOT be changed
Resolvability Every node MUST be retrievable in the system via its snapshotHash

8.3. 7.3 Edges (Parent References)

An edge connects a snapshot (child) with its predecessor snapshot (parent).

Edge requirements:

8.4. 7.4 Branches

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

8.5. 7.5 Merges

A merge snapshot is a snapshot with two or more parent references. It consolidates two branches.

Before a merge snapshot can be finalised, a MergeRecord MUST be created:

{
  "mergeRecord": {
    "mergedSnapshots": [
      "sha256:branch-a-snapshot-hash...",
      "sha256:branch-b-snapshot-hash..."
    ],
    "mergeReason": "Consolidation after coordination between departments",
    "mergedBy": "did:rwp:bern.ch:user-petra-muster",
    "mergedAt": "2026-05-31T16:00:00Z",
    "resultSnapshot": "sha256:merged-snapshot-hash..."
  }
}

The MergeRecord MUST be finalised before the merge snapshot can be finalised.

8.6. 7.6 Cross-Record Merges

When a new Record arises from two or more existing finalized Records (cross-Record merge), the following MUST apply:

9. 8 Case Specification

9.1. 8.1 Case as a Specialised Record Type

A Case is a Record of type CaseRecord. It is subject to all requirements for regular Records (Chapters 2–7) and supplements these with Case-specific requirements.

A Case SHOULD be a standalone storage object, it is a persisted view of a set of linked Records.

9.2. 8.2 Case Schema (normative)

A CaseRecord payload MUST contain the following fields:

{
  "caseId": "did:rwp:bern.ch:f47ac10b-case-001",
  "caseType": "did:rwp:bern.ch:schema-building-permit-case",
  "title": "Building Permit Musterstrasse 12, Parcel 451",
  "trigger": {
    "type": "hard",
    "recordDid": "did:rwp:bern.ch:application-001",
    "snapshotHash": "sha256:application-finalized-hash..."
  },
  "context": [
    {
      "type": "hard",
      "recordDid": "did:rwp:bern.ch:zoning-plan-2024",
      "snapshotHash": "sha256:zoning-plan-hash...",
      "role": "Legal basis"
    }
  ],
  "process": [
    {
      "type": "hard",
      "recordDid": "did:rwp:bern.ch:minutes-site-inspection",
      "snapshotHash": "sha256:minutes-hash...",
      "role": "Investigation"
    }
  ],
  "decision": null,
  "result": null,
  "merkleRoot": "sha256:case-merkle-root..."
}

9.3. 8.3 Case Elements (normative)

A complete Case MUST contain all five elements. A Case MAY be finalised if and only if all five elements are present as hard links.

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 Case schema MAY be marked as adhoc: true. Ad-hoc Cases have no mandatory fields other than trigger and caseId. They MUST be marked in the metadata object as caseVariant: "adhoc".

A hard link points to a finalized snapshot (snapshotHash MUST be specified). It is immutable after finalisation of the Case.

A soft link (working reference) points to a Record DID without a snapshot reference. It MAY point to finalized or draft Records. Soft links prevent finalisation of the Case and MUST be converted to hard links before Case finalisation.

A system MUST check during a Case finalisation attempt whether soft links are still present. If so, the system MUST reject the finalisation and return the open soft links.

9.5. 8.5 Case Merkle Root

The Merkle root of a Case MUST be calculated as follows:

  1. Collect all snapshotHash values of all hard links in the Case (trigger, context, process, decision, result)

  2. Sort alphabetically by SHA-256 value

  3. Calculate the Merkle root over the sorted list (algorithm per Section 9.5)

merkleRoot = MerkleRoot( sort( [snapshotHash_1, snapshotHash_2, ... snapshotHash_n] ) )

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

9.6. 8.6 Case Completeness Check

A system SHOULD perform a completeness check on a Case at any time upon request and return:

{
  "caseId": "did:rwp:bern.ch:f47ac10b-case-001",
  "complete": false,
  "missingElements": ["decision", "result"],
  "openWorkingReferences": ["did:rwp:bern.ch:expert-opinion-draft-001"],
  "merkleRootValid": true
}

10. 9 Integrity and Hashing Procedures

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

10.2. 9.2 Canonical JSON Serialisation

For all hash calculations over JSON objects, RFC 8785 (JSON Canonicalization Scheme, JCS) [RFC8785] MUST be used.

Requirements:

10.3. 9.3 Snapshot Integrity

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

If the integrity check fails, the system MUST:

  1. Mark the snapshot 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.

10.4. 9.4 Signature Procedure

If the schema prescribes a signature (signaturePolicy: owner or signaturePolicy: system), the snapshot hash MUST be cryptographically signed during the finalisation act.

Requirements:

10.5. 9.5 Merkle Tree Algorithm

For the calculation of the Case 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

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

11. 10 Optional Ledger Anchoring

11.1. 10.1 Purpose and Scope

Ledger anchoring is an optional extension of RWP. It enables the external, immutable proof of Case 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.

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

11.3. 10.3 Anchoring Protocol

When a finalised Case is anchored, the ledger entry MUST contain the following fields:

{
  "rwpAnchor": {
    "version": "0.1",
    "caseDid": "did:rwp:bern.ch:f47ac10b-case-001",
    "caseSnapshotHash": "sha256:case-finalized-snapshot-hash...",
    "merkleRoot": "sha256:case-merkle-root...",
    "anchoredAt": "2026-05-31T16:00:00Z",
    "anchoredBy": "did:rwp:bern.ch:controller-001",
    "ledgerTxId": "abc123..."
  }
}

The ledger entry MUST NOT contain any payload content, personal data, or classified information. Only cryptographic hash values and identifiers are permitted.

11.4. 10.4 Anchoring Reference in the Case

When a Case has been anchored, the Case snapshot MUST be updated with an anchorReference field:

{
  "anchorReference": {
    "ledgerType": "hyperledger-fabric",
    "ledgerEndpoint": "https://ledger.bern.ch/api/v1",
    "txId": "abc123...",
    "anchoredAt": "2026-05-31T16:00:00Z"
  }
}

12. 11 Access Control (Delegation Framework)

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

12.2. 11.2 Access Policy Block

A Record snapshot MAY contain an accessPolicy block in the metadata:

{
  "accessPolicy": {
    "visibility": "restricted",
    "readAccess": [
      "did:rwp:bern.ch:unit-legal",
      "did:rwp:bern.ch:unit-planning"
    ],
    "writeAccess": [
      "did:rwp:bern.ch:user-petra-muster"
    ],
    "delegationAllowed": true,
    "expiresAt": null
  }
}
Field Required Description
visibility SHOULD public, restricted, or confidential
readAccess MAY Array of DIDs with read permission
writeAccess MAY Array of DIDs with write permission (draft state only)
delegationAllowed MAY Whether listed DIDs may further delegate access
expiresAt MAY ISO 8601 timestamp after which access policy expires

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

13. 12 Federation

13.1. 12.1 Federation Model

RWP federation is modelled after the DNS architecture: a decentralised, hierarchical namespace model without a single point of failure.

Every RWP namespace (the <namespace> component of a DID, e.g. bern.ch) is operated by the owning organisation. Namespace resolvers are federated: each resolver knows its own namespace and can route resolution requests for unknown namespaces to peer resolvers.

13.2. 12.2 Namespace Registry

The authoritative namespace registry is the subject of a future RWP extension. During the transition phase, the following applies:

13.3. 12.3 Resolver Requirements

An RWP federation resolver MUST:

DNS TXT record format for resolver discovery:

_rwp-resolver.bern.ch. 300 IN TXT "v=rwp1;endpoint=https://resolver.bern.ch/api/v1"

13.4. 12.4 Cross-Namespace Links

A Record in namespace bern.ch MAY contain hard links to Records in other namespaces (e.g. did:rwp:bag.admin.ch:guideline-001).

When resolving cross-namespace links, a system MUST:

  1. Extract the namespace component from the linked DID

  2. Discover the resolver endpoint via DNS TXT lookup (Section 12.3)

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

  4. Cache the resolved snapshot locally with the original hash for integrity verification

14. 13 Payload Deletion

14.1. 13.1 Deletion Principles

RecordWeb’s immutability and data protection erasure obligations (GDPR, Swiss DSG) are in tension. RWP resolves this tension through a tiered deletion regime.

The applicable regime is declared in the deletionRegime field of the Record’s metadata at the time of creation. Implementations MUST respect this field and MAY enforce it at the infrastructure level.

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

14.3. 13.3 DeletionRecord Protocol

When a payload deletion is executed, a DeletionRecord MUST be created and finalised before the payload is removed.

The DeletionRecord MUST contain:

{
  "deletionRecord": {
    "targetDid": "did:rwp:bern.ch:f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "targetSnapshotHash": "sha256:snapshot-to-be-deleted...",
    "deletionRegime": "payload-only",
    "legalBasis": "GDPR Art. 17 — Right to erasure",
    "requestedBy": "did:rwp:bern.ch:user-max-mustermann",
    "approvedBy": "did:rwp:bern.ch:unit-legal",
    "deletedAt": "2026-06-01T10:00:00Z",
    "retainedFields": ["did", "metadata", "versionGraph"]
  }
}

After the DeletionRecord is finalised:

  1. The payload bytes are securely overwritten

  2. The payloadHash field in the snapshot is replaced with the string "deleted:<DeletionRecord-DID>"

  3. The DID document’s currentVersion field is updated

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

14.4. 13.4 Solid Pod Delivery (optional)

For Records whose primary subject is an individual citizen, RWP offers an optional delivery extension: delivery of finalised Records into a citizen’s Solid Pod.

When a system implements Solid Pod delivery, it MUST:

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.

15. 14 Conformance Requirements

15.1. 14.1 Conformance Levels

RWP defines two conformance levels.

Level Chapters Description
Level 1 — Basic 2, 3, 4, 5, 6, 7, 9 Record identity, snapshots, payload, hashing, version graph. Systems fulfilling Level 1 can interoperate with one another.
Level 2 — Full 2–9, 8, 12, 13 All Level 1 requirements plus Cases, federation, and payload deletion. Systems fulfilling Level 2 can produce complete, provable Cases.

15.2. 14.2 Level 1 Checklist

A system claiming Level 1 conformance MUST implement:

15.3. 14.3 Level 2 Checklist

A system claiming Level 2 conformance MUST additionally implement:

16. Annex A: Normative JSON Schemas

16.1. A.1 Snapshot Metadata Schema

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://recordweb.github.io/rwp/schemas/snapshot-metadata.json",
  "title": "RWP Snapshot Metadata",
  "type": "object",
  "required": ["did","snapshotHash","recordType","schemaVersion","state",
               "created","owner","parents","payloadHash","payloadFormat"],
  "properties": {
    "did":             { "type": "string", "pattern": "^did:rwp:[^:]+:[^:]+$" },
    "snapshotHash":    { "type": "string", "pattern": "^sha256:[0-9a-f]{64}$" },
    "recordType":      { "type": "string", "pattern": "^did:rwp:" },
    "schemaVersion":   { "type": "string", "pattern": "^sha256:[0-9a-f]{64}$" },
    "state":           { "type": "string", "enum": ["draft","finalized"] },
    "created":         { "type": "string", "format": "date-time" },
    "finalized":       { "type": "string", "format": "date-time" },
    "owner":           { "type": "string", "pattern": "^did:rwp:" },
    "parents":         { "type": "array", "items": { "type": "string",
                         "pattern": "^sha256:[0-9a-f]{64}$" } },
    "classification":  { "type": "string" },
    "retentionPolicy": { "type": "string", "pattern": "^did:rwp:" },
    "tags":            { "type": "array", "items": { "type": "string" } },
    "accessPolicy":    { "type": ["object","null"] },
    "payloadHash":     { "type": "string", "pattern": "^sha256:[0-9a-f]{64}$" },
    "payloadFormat":   { "type": "string" },
    "signature":       { "type": "string" },
    "deletionRegime":  { "type": "string",
                         "enum": ["payload-only","full-delete","exempt"] }
  }
}

16.2. A.2 CaseRecord Payload Schema

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://recordweb.github.io/rwp/schemas/case-record.json",
  "title": "RWP CaseRecord Payload",
  "type": "object",
  "required": ["caseId","caseType","title","trigger","merkleRoot"],
  "properties": {
    "caseId":     { "type": "string", "pattern": "^did:rwp:" },
    "caseType":   { "type": "string", "pattern": "^did:rwp:" },
    "title":      { "type": "string" },
    "trigger":    { "$ref": "#/$defs/hardLink" },
    "context":    { "type": "array", "items": { "$ref": "#/$defs/link" } },
    "process":    { "type": "array", "items": { "$ref": "#/$defs/link" } },
    "decision":   { "oneOf": [{ "$ref": "#/$defs/hardLink" }, { "type": "null" }] },
    "result":     { "type": "array", "items": { "$ref": "#/$defs/hardLink" } },
    "merkleRoot": { "type": "string", "pattern": "^sha256:[0-9a-f]{64}$" }
  },
  "$defs": {
    "hardLink": {
      "type": "object",
      "required": ["type","recordDid","snapshotHash"],
      "properties": {
        "type":         { "const": "hard" },
        "recordDid":    { "type": "string", "pattern": "^did:rwp:" },
        "snapshotHash": { "type": "string", "pattern": "^sha256:[0-9a-f]{64}$" },
        "role":         { "type": "string" }
      }
    },
    "link": {
      "type": "object",
      "required": ["type","recordDid"],
      "properties": {
        "type":         { "type": "string", "enum": ["hard","working"] },
        "recordDid":    { "type": "string", "pattern": "^did:rwp:" },
        "snapshotHash": { "type": "string", "pattern": "^sha256:[0-9a-f]{64}$" },
        "role":         { "type": "string" }
      }
    }
  }
}

16.3. A.3 DeletionRecord Payload Schema

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://recordweb.github.io/rwp/schemas/deletion-record.json",
  "title": "RWP DeletionRecord Payload",
  "type": "object",
  "required": ["deletionRecord"],
  "properties": {
    "deletionRecord": {
      "type": "object",
      "required": ["targetDid","targetSnapshotHash","deletionRegime",
                   "legalBasis","requestedBy","approvedBy","deletedAt"],
      "properties": {
        "targetDid":          { "type": "string", "pattern": "^did:rwp:" },
        "targetSnapshotHash": { "type": "string",
                                "pattern": "^sha256:[0-9a-f]{64}$" },
        "deletionRegime":     { "type": "string",
                                "enum": ["payload-only","full-delete","exempt"] },
        "legalBasis":         { "type": "string" },
        "requestedBy":        { "type": "string", "pattern": "^did:rwp:" },
        "approvedBy":         { "type": "string", "pattern": "^did:rwp:" },
        "deletedAt":          { "type": "string", "format": "date-time" },
        "retainedFields":     { "type": "array",
                                "items": { "type": "string" } }
      }
    }
  }
}

17. Annex B: Reference Implementation Notes (non-normative)

This annex is non-normative. It provides guidance for implementers and does not impose additional requirements.

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

17.2. B.2 Pilot Scope Recommendation

For a first pilot, the following Level 1 subset is recommended:

  1. Implement DID generation and DID document (Sections 2.2–2.3)

  2. Implement snapshot creation with minimum metadata set (Section 3.3)

  3. Implement SHA-256 snapshot hash calculation (Section 3.4)

  4. Implement draft → finalized state transition with schema validation (Section 6.3)

  5. Implement version graph storage (Section 7.1) — 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

[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. 1997. URL: https://www.rfc-editor.org/rfc/rfc2119

Non-Normative References

[DID-CORE]
Decentralized Identifiers (DIDs) v1.0. URL: https://www.w3.org/TR/did-core/
[ECH-0164]
eCH-0164 — Information lifecycle in public administration. URL: https://www.ech.ch
[HYPERLEDGER]
Hyperledger Fabric. URL: https://www.hyperledger.org/projects/fabric
[ISO14721]
ISO 14721:2012 — Open Archival Information System (OAIS). URL: https://www.iso.org/standard/57284.html
[ISO15489]
ISO 15489-1:2016 — Records management. 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
[PROVO]
PROV-O: The PROV Ontology. URL: https://www.w3.org/TR/prov-o/
[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
[RWC]
Nik Jenzer. RecordWeb Concept (RWC). CG-DRAFT. URL: https://recordweb.github.io/rwc/
[ZENODO-RWP]
Nik Jenzer. RecordWeb Protocol (RWP) v0.1 — Published baseline. 2026. URL: https://doi.org/10.5281/zenodo.20475345