gemeinwert
BIM CVP

gemeinwert  /  wiki  /  examples  /  alice-bob-max

Alice, Bob, Max: data sharing as signed records

A worked example for the whole workflow. Alice commissions the project, Bob publishes a model, Max creates a BCF coordination issue, Bob resolves it, and Alice approves the package.

Mental model

Think Lightning payment receipt style, but for project information: a person signs a structured record, broadcasts it to relays, and everyone can verify who signed what, which file hash it references, and which earlier record it depends on.

Actors

PersonProject roleKeyTypical actions
AliceClient / appointing partyalice-pubkeyCreates project, defines requirements, approves publication.
BobArchitect / lead appointed partybob-pubkeyPublishes IFC packages, answers issues, requests approval.
MaxMEP engineer / BIM coordinatormax-pubkeyChecks the model, creates BCF topics, comments, validates issues.
RelayShared message boardnoneStores and forwards signed events. It is not the source of truth.
StorageFile holdernoneStores binaries such as IFC, PNG, PDF. Hashes prove file integrity.

Signed-record analogy

The analogy is useful if it stays precise. We do not put BIM data into a payment network. The shared idea is simpler: a signed object references earlier objects and can be verified without asking a platform database for permission.

Verifiable payment recordBIM-CVP event
A payer authorizes a payment.NIP-07 signer signs the event with Alice, Bob or Max's key.
The receipt can be checked later.Nostr event ID and signature can be verified independently.
The payment references a recipient and amount.e, a and file tags reference project, topic, viewpoint and file events.
The network only moves the message.Relays distribute events; clients verify signatures and file hashes.
Settlement history is append-only.Comments and audit events are append-only. Replacements create new signed records.
Alice signs project event
  -> relay stores it
  -> Bob and Max verify Alice's signature

Bob signs model reference
  -> references Alice's project
  -> references a file hash
  -> everyone verifies the same IFC bytes

Max signs BCF issue
  -> references Bob's model
  -> references IFC element GUIDs
  -> references viewpoint and snapshot

Alice signs approval
  -> references the resolved topic and model package
  -> proves who accepted what

End-to-end story

The whole project can be read as a graph. The important part is not that everything is public; private projects can use private relays. The important part is that every actor can take the graph, verify signatures and hashes, and export normal buildingSMART artifacts such as BCFZIP or IFC references.

kind:30902  Alice creates project
   |
   +-- kind:30880  Alice defines requirements
   +-- kind:30810  Alice/Max publish IDS
   |
   +-- kind:1063   Bob uploads IFC file metadata
   +-- kind:30904  Bob publishes IFC file reference
   |
   +-- kind:1063   Max uploads snapshot metadata
   +-- kind:30901  Max publishes immutable BCF viewpoint
   +-- kind:30900  Max publishes current BCF topic
        |
        +-- kind:1170  Bob comments
        +-- kind:1171  Bob changes status, audit record
        +-- kind:30900  Bob publishes replacement topic state
        |
        +-- kind:1180  Max publishes IDS validation result
        +-- kind:30970 Alice approves package

1. Bob shares an IFC model

Bob does not send a model by email. He uploads the IFC to storage, then signs metadata that says: this exact file, with this hash, belongs to Alice's project and represents the architectural model at this revision.

{
  "kind": 1063,
  "pubkey": "bob-pubkey",
  "tags": [
    ["url", "https://storage.example/pilot-arc-r03.ifc"],
    ["m", "application/x-step"],
    ["x", "sha256-of-ifc-file"],
    ["size", "42850432"],
    ["a", "30902:alice-pubkey:pilot-2026"],
    ["filename", "PILOT_ARC_MOD_S2_P03.ifc"]
  ],
  "content": "IFC file uploaded by Bob"
}
{
  "kind": 30904,
  "pubkey": "bob-pubkey",
  "tags": [
    ["d", "pilot-arc-model-r03"],
    ["a", "30902:alice-pubkey:pilot-2026"],
    ["e", "ifc-file-metadata-event-id", "", "file"],
    ["discipline", "architecture"],
    ["schema", "IFC4X3_ADD2"],
    ["mvd", "ReferenceView"],
    ["ifc-project", "0aB1cD2eF3gH4iJ5kL6mN7"],
    ["iso19650-state", "Shared"],
    ["revision", "P03"]
  ],
  "content": "{\"model_name\":\"Architecture model\",\"authoring_tool\":\"Archicad\"}"
}
Bob's event does not prove the model is correct. It proves authorship, file identity, project scope and declared schema. Correctness comes from review, BCF coordination and IDS validation.

2. Max creates a BCF issue

Max opens Bob's IFC in a viewer and sees that an MEP duct crosses a beam. He creates a BCF issue. The signed event does not contain the IFC model; it references Bob's model event, the affected IFC element GUID, a snapshot file and an immutable viewpoint.

{
  "kind": 30901,
  "pubkey": "max-pubkey",
  "tags": [
    ["d", "viewpoint-guid-001"],
    ["a", "30902:alice-pubkey:pilot-2026"],
    ["bcf-guid", "viewpoint-guid-001"],
    ["bcf-version", "3.0"],
    ["ifc-file", "bob-ifc-reference-event-id"],
    ["ifc", "2Y$0aBv19FqQ9rP5J6wQhA"],
    ["e", "snapshot-file-event-id", "", "snapshot"]
  ],
  "content": "{\"camera\":{\"type\":\"perspective\"},\"components\":{\"selection\":[{\"ifc_guid\":\"2Y$0aBv19FqQ9rP5J6wQhA\"}]}}"
}
{
  "kind": 30900,
  "pubkey": "max-pubkey",
  "tags": [
    ["d", "topic-guid-duct-beam"],
    ["a", "30902:alice-pubkey:pilot-2026"],
    ["bcf-guid", "topic-guid-duct-beam"],
    ["bcf-version", "3.0"],
    ["bcf-type", "Clash"],
    ["bcf-status", "Open"],
    ["s", "Open"],
    ["bcf-priority", "High"],
    ["p", "bob-pubkey", "", "assignee"],
    ["p", "alice-pubkey", "", "watcher"],
    ["ifc-file", "bob-ifc-reference-event-id"],
    ["ifc", "2Y$0aBv19FqQ9rP5J6wQhA"],
    ["e", "viewpoint-event-id", "", "viewpoint"],
    ["e", "snapshot-file-event-id", "", "snapshot"]
  ],
  "content": "{\"title\":\"Duct crosses beam at axis 4/B\",\"description\":\"Please reroute duct or confirm structural opening.\",\"labels\":[\"mep\",\"structure\"]}"
}

3. Bob comments and changes status

Bob cannot silently overwrite Max's issue. He signs a comment and then publishes an audit event plus a replacement topic state. The current state is easy to query, while the reason remains visible.

{
  "kind": 1170,
  "pubkey": "bob-pubkey",
  "tags": [
    ["e", "topic-event-id", "", "root"],
    ["a", "30902:alice-pubkey:pilot-2026"],
    ["p", "max-pubkey"]
  ],
  "content": "{\"guid\":\"comment-guid-001\",\"text\":\"I will reroute the duct below the ceiling zone and publish P04.\"}"
}
{
  "kind": 1171,
  "pubkey": "bob-pubkey",
  "tags": [
    ["e", "topic-event-id", "", "root"],
    ["a", "30902:alice-pubkey:pilot-2026"],
    ["audit-field", "bcf-status"],
    ["audit-from", "Open"],
    ["audit-to", "InProgress"],
    ["bcf-action", "update"]
  ],
  "content": "{\"reason\":\"Assignee accepted the issue.\"}"
}

Bob then publishes a new kind:30900 with the same d and bcf-guid, but with bcf-status = InProgress. That is the BCF equivalent of spending the old current state into a new current state, while retaining the full signed history.

4. Alice asks for IDS validation

Alice wants machine-checkable delivery requirements. Max or a validator publishes an IDS spec and then signs a validation result against Bob's model reference.

{
  "kind": 30810,
  "pubkey": "alice-pubkey",
  "tags": [
    ["d", "ids-fire-and-classification-lp4"],
    ["a", "30902:alice-pubkey:pilot-2026"],
    ["schema", "IDS1.0"],
    ["lang", "en"]
  ],
  "content": "{\"title\":\"LP4 delivery requirements\",\"ids_url\":\"https://storage.example/ids-lp4.xml\"}"
}
{
  "kind": 1180,
  "pubkey": "max-validator-pubkey",
  "tags": [
    ["e", "ids-spec-event-id", "", "spec"],
    ["e", "bob-ifc-reference-event-id", "", "model"],
    ["a", "30902:alice-pubkey:pilot-2026"],
    ["result", "pass-with-warnings"],
    ["passed-count", "147"],
    ["failed-count", "3"],
    ["x", "sha256-of-validation-report"],
    ["report-url", "https://storage.example/report-lp4.json"]
  ],
  "content": "{\"summary\":\"147 requirements passed, 3 classification warnings.\"}"
}

5. Alice approves the package

Approval is a new signed decision. It references Bob's model, Max's validation result and the resolved BCF topic. If Alice later needs to prove what was approved, the event graph is enough.

{
  "kind": 30970,
  "pubkey": "alice-pubkey",
  "tags": [
    ["d", "approval-lp4-2026-05-16"],
    ["a", "30902:alice-pubkey:pilot-2026"],
    ["approval-type", "PhaseGate"],
    ["target-state", "Published"],
    ["target-stage", "LP4"],
    ["e", "bob-ifc-reference-event-id", "", "file"],
    ["e", "validation-result-event-id", "", "validation"],
    ["e", "topic-event-id", "", "resolved-topic"],
    ["signers", "alice-pubkey,max-pubkey"],
    ["sig-policy", "2-of-2"]
  ],
  "content": "{\"decision\":\"LP4 architecture package accepted with listed warnings.\"}"
}

buildingSMART process map

buildingSMART / ISO processAlice/Bob/Max exampleSigned records
Project setup / BCF projectAlice creates the project and invites Bob/Max.30902
IFC model exchangeBob publishes the architectural IFC package.1063, 30904
BCF coordinationMax creates a clash topic with viewpoint and snapshot.1063, 30901, 30900
BCF discussionBob answers, Max reviews, Alice watches.1170
BCF status historyOpen becomes InProgress, then Resolved.1171 + replacement 30900
IDS requirement checkMax validates Bob's IFC against Alice's IDS.30810, 1180
ISO 19650 publicationAlice approves the Shared package as Published.30970
BCFZIP exportA classic tool receives a normal BCF file.Event graph to .bcfzip

Why this makes implementation easier

Once the story is fixed, each component has a narrow job. The BCF form only creates a topic. The thread view only reads topic, comments, audit, viewpoint and snapshot. The approval component only references already signed records. The implementation does not need to invent workflow rules; it follows the graph.

BCF form

Creates 30900, then links 1063 and 30901.

Thread view

Queries 30900, 1170, 1171, linked viewpoint and snapshot.

Importer/exporter

Transforms event graph to and from BCFZIP without owning the workflow.

Approval gate

Checks unresolved topics, validation results and file hashes, then signs 30970.

Read on