Part XVIII. Review and issue
This part is a part of OpenEik 0.2. It comes from plan 688, "One review flow", which the steward decided on 25 October 2026: the reference implementation and a host share one review flow, written into the standard, on which contracts will later rest. It binds every conformance class it names, the host and the authoring tool among them (section 9; Conformance). OpenEik 0.1 had it as a proposal, which no class of 0.1 required: a reader of 0.1 keeps its files as kept files (Part III, 7) while they are UTF-8 text of at most 1 MiB, and leaves larger ones alone. It builds on Part XIV: its registry of people and keys (XIV.5), the codes of its drawing profile (XIV.4), its issues (XIV.12) and its signed statements (XIV.14). The steward decided its questions, open questions 61 to 68, on 26 October 2026, each as the proposal had them (section 10). @openeik/tools applies it to every model of 0.2, and to a model of 0.1 when asked: checkFolder(…, { proposals: ["review"] }), or openeik check --proposal review, which apply Part XIV too (section 9).
1. Status and scope
Plan 688 states five rules, which this part and Part XIV keep:
- The building is the truth. What is reviewed, issued and signed is a version of the model, or a revision drawn from one, named by its digests (SHA-256).
- A drawing is reviewed as it was issued. A round on a drawing is on one revision, its issued SVG and its records (Part XIV, 13), never on a print of it.
- A print is paper. A PDF printed from a revision and an IFC exported from a version are copies: never the record, and never compared (section 7).
- A decision has a name. Only a signed-in person, a person of the registry (Part XIV, 5), gives an item, a decision or a signature. A link without sign-in looks and prints, nothing more (section 8, rule 1).
- The authoring tool keeps the record. It saves into the building what a host offers: closed rounds, statements, receipts and acceptances. A host coordinates, and never writes the building.
Part XIV says how a drawing is issued, reviewed and signed. This part says what that leaves out:
- a review round on a version of the model itself, in 3D (section 2);
- an issue that releases a version, and names the prints sent with it (section 3);
- a signed issue: the sender's statement, and a recipient's (section 4);
- a host's receipt of an issue, signed with a key the host publishes, and the file in which it publishes its keys (section 5);
- a record that a person accepted named terms (section 6);
- prints that say they are prints: an IFC that names the version it came from (section 7), and the PDF rendition's margin note (Part XIV, 15.3);
- the shapes of review items (Part XIV, 13.2; open question 61).
Status. The rules of this part bind every implementation of 0.2 of a class they name (section 9). They are numbered, and cited as XVIII.<section>.<rule>: XVIII.4.3.2 is section 4.3, rule 2. A validator reports a breach of a MUST as an error and a breach of a SHOULD as a warning (section 9). The part's schemas are among those of 0.2 (schemas/0.2/review/), and its conformance cases in the suite of 0.2. An implementation of this part implements, of Part XIV, at least its drawing profile (4), its registry (5), its issues (12) and its statements and their verification (14.1 to 14.3).
1.1 What it leaves out
- Delivery. How a host sends an issue, its links and how long they live, its notifications and its seen ticks are the host's (Part XIV, 1.2). A receipt records what the host saw, not how it delivered.
- Accounts and sign-in. How a person signs in, and which account is which person, are the host's. The building names people by the registry's ids (Part XIV, 5).
- The terms' text, which is the project's or the host's: this part names terms by their digest.
- Law. Whether a signature, a receipt or an acceptance binds anyone is the law's to say, as Part XIV, 1.2 says of signatures. The legal tier waits for a legal review (Part XIV, 14.6).
- A 2D extension of BCF, as Part XIV, 18 says.
1.2 Words
| Word | Meaning |
|---|---|
| model review | a review round on one version of the model, in 3D: items on its elements, each seen from a viewpoint |
| viewpoint | where an item is seen from: a camera, and a section where there is one |
| a rendition made for people to read or for another tool, a PDF of a revision or an IFC of a version: a copy, never the record | |
| statement | a signed in-toto statement in a DSSE envelope, time-stamped, as Part XIV, 14 makes a sign-off |
| receipt | a host's signed record of what happened to an issue for one recipient |
| terms accepted | a signed record that a person accepted named terms, for the building or for an issue |
1.3 Where its files live
| File | Path | Kind | Section |
|---|---|---|---|
| a model review | project/reviews/<review>.json | a file of this part | 2 |
| what an issue releases beside revisions | in drawings/issues/<issue>.json | members of Part XIV's issue | 3 |
| an issue's statements | drawings/issues/<issue>/signoffs/<n>.json | a statement | 4 |
| an issue's receipts | drawings/issues/<issue>/receipts/<n>.json | a statement | 5 |
| terms accepted | project/terms-accepted/<n>.json | a statement | 6 |
| the terms' text, where the folder keeps it | assets/<sha256>.pdf | an asset (Part XV) | 6 |
Every JSON file of this part is a drawing file as Part XIV, 7.2 says: it has a format, is in the stored form, writes times in UTC, names people by the registry's ids and is complete without a host. The file of a host's keys (5.6) is the one file of this part that no building holds: a host serves it on its own origin. A statement is a file of Part XIV, 14.2's format, openeik-drawing-signoff/0.1, which its predicate type tells apart from a drawing's sign-off. <review> and <issue> are path segments of ids, and <n> is s- and the first 12 hexadecimal digits of the envelope's hash, as Part XIV, 14.2 makes it.
1.4 How it fits into 0.1 and Part XIV
A 0.1 reader keeps every file of this part as a kept file while it is UTF-8 text of at most 1 MiB, and leaves a larger one alone (Part III, 7). A reader of 0.1 that applies the proposal drawings alone reads the members this part adds to an issue as Part XIV, 12.1 lists them, and checks them only as the schema does.
1.5 The parts it extends
In 0.2 its text stays in this part. These are the sections of Parts I to VIII and of the other parts that it extends, where a later version may move it:
- Part XIV: model reviews beside drawing reviews, what an issue releases, statements, receipts and terms accepted;
- Part VI: an issued version, which the history keeps (3.2, rule 3);
- Part VIII: an IFC that names its version (7.2);
- Conformance: the classes' new duties (section 9);
- Security and privacy: receipts and acceptances as personal data, a host's keys, and what a link without sign-in may do (section 8).
2. Reviewing the model
A model review is a round on one version of the model, as a review of Part XIV, 13 is a round on one revision: the same reviewers, item kinds, states, decisions, replies and close, so that a reviewer who knows one knows the other. Its items sit on elements of the version, each seen from a viewpoint in 3D, and the version is named by its root tree hash, which no later change alters. A host keeps a round and its working state while it is open; at the close it offers the round in this file, and the authoring tool saves it into the building with the next version it records, so that the building holds the conclusion.
2.1 The file
project/reviews/<review>.json, held to schemas/0.2/review/model-review.schema.json:
| Member | Type | Meaning | |
|---|---|---|---|
format | required | "openeik-model-review/0.1" | |
id | required | Part I, 6 | unique without coordination across hosts and forks, such as a ULID, and never a host's sequence number; the file's name |
model | required | {version, root, ref?} | the version reviewed: its id, as Part VI, 8.2's computedFrom.version names one (null for a folder under no version control); its root tree hash (Part VI, 2, rule 4), which is what the round reviews; and the line of work it is on |
issue | optional | {id, hash} | the issue that released the version (section 3), by its id and its record's hash, where the round reviews an issued version |
compared | optional | {version, root} | the version the round compared it with |
profile | required | {id, code?, purpose?} | the drawing profile (Part XIV, 4), and the status or purpose code the round reviewed for |
opened | required | {by, at} | |
due | optional | date | |
closed | optional | {by, at} | absent while the round is open |
reviewers | required | list | {person, role, decision?}, as Part XIV, 13.1 has them |
items | required | list (2.2) |
2.2 Items
An item has these members of Part XIV, 13.2, as that section has them: id, kind (comment, cloud, arrow, text, measure or highlight), author, at, text, replies, state, history, carriedFrom, bcf and attachments. It has no change or anchorState, which are a revision's. In place of a sheet's anchors, its fallback and its shape it has:
| Member | Meaning | |
|---|---|---|
anchors | required, and may be empty | tried in order: {element, hash?, point?}: an element of the model at the reviewed version, by its id; the hash of its record there (Part III, 6), so that a later reader sees whether it has changed since without the history; and a point on it, [x, y, z] in mm of the model |
viewpoint | required | where the item is seen from (2.3) |
shape | optional | {points, closed?, form?}, each point [x, y, z] in mm of the model: a cloud's, an arrow's, a highlight's or a measure's geometry, or the frame of a text's or a comment's words, its form as Part XIV, 13.2 says. A measure's value is derived: the length along its points |
A highlight marks its anchors' elements, and its shape where it has one. carriedFrom may name an item of a model review or of a drawing's review (Part XIV, 13): a point raised on a drawing can be carried to the model, and back.
Seen ticks, read receipts and each person's progress are the host's, and stay out of the file, as they do of Part XIV's.
2.3 Viewpoints
viewpoint is {camera, section?}, in the model's coordinates: millimetres, Z up (Part I, 4).
| Member | Meaning | |
|---|---|---|
camera.projection | required | perspective or orthographic |
camera.position | required | [x, y, z]: where the camera stands |
camera.direction | required | [x, y, z]: where it looks; a direction only, which a reader uses as a unit vector |
camera.up | required | [x, y, z]: which way is up in the picture |
camera.fieldOfView | for perspective | the vertical field of view, in degrees, more than 0 and less than 180 |
camera.height | for orthographic | the height of what it shows, in mm of the model, more than 0 |
camera.aspect | optional | the picture's width over its height, as the reviewer saw it |
section | optional | {planes} or {box}: what the viewpoint cuts away |
section.planes | 1 to 6 {point, normal}: each hides what lies on the side its normal points to, as BCF's clipping planes do | |
section.box | {min, max}: shows only what lies inside the box, whose sides run along the model's axes. A box turned in plan is six planes |
What else a viewer showed (elements hidden, coloured or isolated, the path of a walk) is the viewer's, and stays out of the file.
2.4 Example
A round on the version of the L-house from which Part XIV's A-101 P02 was drawn, with one comment on the window study-window-east, seen from outside the east facade with the roof cut away above the wall heads (the camera's numbers are illustrative):
{
"format": "openeik-model-review/0.1",
"id": "mr-01jcq7d2v9",
"items": [
{
"anchors": [
{"element": "study-window-east", "hash": "21df22d8acaa1d8d85a9be9238cf35e85a152cd808170c3b73b767dc5091b4eb", "point": [12000, 4000, 1650]}
],
"at": "2026-10-26T09:12:00Z",
"author": {"person": "person-r4t8wd"},
"id": "i-1",
"kind": "comment",
"state": "new",
"text": "Check the sill height after the move.",
"viewpoint": {
"camera": {"direction": [-1, 0, 0], "fieldOfView": 60, "position": [18000, 4000, 1650], "projection": "perspective", "up": [0, 0, 1]},
"section": {"box": {"max": [13000, 7000, 2500], "min": [-1000, -1000, -500]}}
}
}
],
"model": {"ref": "main", "root": "6b572fb1e20adea6f4d012a31588f32aef0dc7995796d2630497fb3f74e1f378", "version": null},
"opened": {"at": "2026-10-26T09:00:00Z", "by": "person-k2m9xa"},
"profile": {"code": "S3", "id": "example"},
"reviewers": [{"person": "person-r4t8wd", "role": "checker"}]
}
2.5 Rules
- The file MUST validate against its schema, and its
idMUST be its name read back. - A folder that holds a model review MUST hold the drawing profile (Part XIV, 4).
profile.idMUST be the profile's; every item'sstateand every state of itshistoryMUST be a code of itsreviewStates; everydecision.codeMUST be a code of itsdecisions. - Every reviewer MUST be a person of the registry of the kind
person: a decision is a person's, and an agent gives none (Part XIV, 3.2, the AI rule). - An item's anchors SHOULD name elements of the model at the reviewed version, and an anchor's
hash, where given, MUST be the hash of that element's record there. A validator checks this rule where it has that version. - A closed review MUST be frozen: no item, reply, state or decision is later than
closed.at, and a later version holds the file unchanged. carriedFromSHOULD name an item of another review, a model review or a drawing's, where the folder holds it.- A camera's
directionandupMUST NOT be zero, nor parallel to each other; aperspectivecamera MUST givefieldOfViewand noheight, and anorthographiconeheightand nofieldOfView. The schema states the second part. - A section's plane MUST have a
normalthat is not zero, and its box aminbelow itsmaxon each axis. - A shape's
formMUST be as Part XIV, 13.4, rule 9 says, its points in mm of the model. issue, where given, MUST name an issue of the folder by its record's hash, and that issue MUST release the reviewed version: itsversionsholdmodel.root.- The people it names MUST follow Part XIV, 5.2, rules 2 and 3.
2.6 BCF (informative)
A model review exchanges as BCF 3.0, whose viewpoints are 3D, more directly than a drawing's review does (Part XIV, 18). Each item is a topic: its GUID the item's bcf, or one made from the review's id and the item's; its type the item's kind; its status the profile's review state; its replies its comments. Its viewpoint is the item's: the camera's position, direction and up, in metres, as a PerspectiveCamera with the field of view or an OrthogonalCamera whose ViewToWorldScale is the height in metres, and AspectRatio the item's aspect, or 1; each plane of its section as a ClippingPlane, and a box as six; its shape as Lines, one for each two points that follow each other, and one from the last to the first where it is closed; and its anchors' elements selected, by their OpenEik ids as AuthoringToolId. A bridge that derives GlobalIds from the project's id and the record's id (Part VIII, 1, rule 3) can give each its IfcGuid too, so that the topic opens on the IFC print of the same version. The round's version is named in each topic's document reference, by its root.
3. Issuing a version
An issue (Part XIV, 12) releases revisions to recipients for a purpose. In 0.2 it may also release a version of the model, which the recipients then review in 3D (section 2), and it names the prints sent with it.
3.1 The members
An issue MAY give, beside the members of Part XIV, 12.1:
| Member | Type | Meaning | |
|---|---|---|---|
versions | optional | list, 1 to 20 | {version, root, ref?}: the versions released, each by its root tree hash (Part VI, 2, rule 4), its id as Part VI, 8.2 names a version (null for a folder under no version control), and its line of work. Two lines of one model, a design and its alternative, can be released together |
renditions | optional | list, at most 10 000 | the prints sent with it: {of, format, sha256, bytes, by}. of is what it was printed from: {root}, a version the issue releases, or {drawing, sequence}, a revision it releases; format, its kind by its file's extension (pdf, ifc); sha256 and bytes, the SHA-256 and the length of the file sent; and by, {name, version}, the bridge or renderer that made it |
terms | optional | list, at most 20 | {sha256, title, version?}: the terms the issue is sent under, by the SHA-256 of their text, with their title and version as people know them (section 6) |
An issue then releases revisions, versions or both: Part XIV, 12.1's revisions is required unless versions is given.
A print the issue names is named by its digest, and kept nowhere: the digest says which file was sent, and the print is not the record of what was issued (section 7). The folder keeps no IFC, and a PDF only where Part XIV, 15 keeps a signed rendition.
3.2 Rules
- Each version an issue releases MUST be listed once, by its
root. - A rendition's
ofMUST name a version or a revision that the issue releases. - An issuer SHOULD record a named version (Part VI, 3) of each version it issues, and push it where the recipients read: a version of the kind
autostays local (Part VI, 6.3, rule 3), and a recipient could not fetch it. - Each version an issue releases MUST be a version of the building's history. A validator checks this rule where it has the history.
3.3 Example
A-101 at P02, and the version it was drawn from, released for review with an IFC print of that version:
{
"format": "openeik-drawing-issue/0.1",
"id": "iss-01jcq6x4k7",
"purpose": {"code": "S3", "profile": "example"},
"recipients": [{"person": "person-r4t8wd"}],
"renditions": [
{"by": {"name": "@openeik/tools", "version": "0.1.0-draft"}, "bytes": 1482211, "format": "ifc", "of": {"root": "6b572fb1e20adea6f4d012a31588f32aef0dc7995796d2630497fb3f74e1f378"}, "sha256": "<sha256 of the IFC file>"}
],
"revisions": [
{"drawing": "A-101", "record": "<hash of revision.json>", "revision": "P02", "sequence": 2}
],
"sent": {"at": "2026-10-26T08:30:00Z", "by": "person-k2m9xa"},
"versions": [
{"ref": "main", "root": "6b572fb1e20adea6f4d012a31588f32aef0dc7995796d2630497fb3f74e1f378", "version": null}
]
}
4. Signing an issue
4.1 The statement
An issue is signed as a revision is (Part XIV, 14): an in-toto Statement v1 in a DSSE envelope, signed by a person of the registry with a key of their record, a passkey among them, each signature time-stamped (RFC 3161), in a file of Part XIV, 14.2's format. Its statement:
_type:https://in-toto.io/Statement/v1;subject: exactly one, the issue record:drawings/issues/<issue>.json, with its hash (Part III, 6);predicateType:https://openeik.org/attestation/issue/v0.1;predicate:
| Member | Meaning | |
|---|---|---|
issue | required | {id, hash}: the issue, by its id and its record's hash |
action | required | issued, received or withdrawn |
signer | required | a person of the registry |
role | optional | the role in which the signer acts, a plain value |
at | required | the signer's own time; the time-stamp's is the trusted one |
withdraws | required for withdrawn | the hash of the statement file it withdraws |
issued is the sender's: "I released exactly these revisions, versions and prints, to these recipients, for this purpose." received is a recipient's, one the issue names or one a host sent it to (5.2): "I received exactly this issue." withdrawn withdraws a statement of the signer's own about the same issue; it does not unsend the issue, which stays as it was released, and a later issue supersedes it.
{
"_type": "https://in-toto.io/Statement/v1",
"predicate": {
"action": "issued",
"at": "2026-10-26T08:31:00Z",
"issue": {"hash": "<hash of the issue record>", "id": "iss-01jcq6x4k7"},
"role": "issuer",
"signer": "person-k2m9xa"
},
"predicateType": "https://openeik.org/attestation/issue/v0.1",
"subject": [
{"digest": {"sha256": "<hash of the issue record>"}, "name": "drawings/issues/iss-01jcq6x4k7.json"}
]
}
4.2 The file
drawings/issues/<issue>/signoffs/<n>.json, in Part XIV, 14.2's format, named as 14.2 names a sign-off.
4.3 Rules
- The file MUST validate against Part XIV, 14.2's schema; its payload MUST decode to an in-toto Statement v1 whose
predicateTypeishttps://openeik.org/attestation/issue/v0.1, and its predicate MUST validate against its schema. - The statement's subject MUST be exactly one, the issue record of the folder it is in, by its path and its hash, and the predicate's
issueMUST be that issue'sidand that hash. signerMUST name a person of the registry of the kindperson, and each signature'skeyida key of that record: an agent never signs a statement about an issue.- An
issuedstatement's signer MUST be the issue'ssent.by, and areceivedstatement's signer a recipient that the issue names byperson, or a person that a receipt of the issue, which the folder holds, names as itsrecipient. A recipient outside the registry, named byname, signs nothing. - Every signature MUST have a time-stamp.
- Each signature MUST verify, with its time-stamp, as Part XIV, 14.7, rule 9 says.
- A
withdrawnstatement'swithdrawsMUST name a statement of the same issue by the same signer, by its file's hash. - The file's name SHOULD be made as Part XIV, 14.2 says.
4.4 Verifying
A verifier checks a statement as Part XIV, 14.3 checks a sign-off: the DSSE signature with the registry's key, the time-stamp and its imprint, the key's window of validity at the time-stamp's time, the subject's digest against the issue record, and the predicate type, explicitly. It then follows the record: each revision it lists against its drawing's register (Part XIV, 12.2, rule 2), and, where it has the history or a store, each version's root. A print's file is checked against its digest where the verifier has the file. It needs the folder and the time-stamp authority's certificate, and no host.
5. Receipts
5.1 What a host knows
A host that sends an issue knows, for each recipient, what happened to it:
| Event | What happened |
|---|---|
sent | the host sent the issue to the recipient |
delivered | the recipient's mail system took the message, as the host's mail provider reported |
opened | the recipient opened the issue for the first time |
viewed | the recipient looked at a revision or a version that the issue releases |
downloaded | the recipient took a file: a print, one the issue names or one the host printed on demand, or the issue's set of files |
withdrawn | the sender withdrew the issue from the recipient, and the host stopped showing it |
superseded | a later issue released a later revision of a drawing that this issue released, and the host showed the recipient the later one |
These events, the links that lead to them and how long a link lives are the host's. The building holds them only as a receipt.
The issue record is written once, by the authoring tool, when it issues; a host never writes the building. A host may then send that issue as one transmittal or several, days later, and to people the record does not name, as when a consultant forwards it to a subcontractor; and it may print on demand what the issue releases, the same bytes each time (7.2, rule 6; Part XIV, 15.3), a print the record does not list. The record does not change: those sendings and prints reach the building only in receipts (5.2).
5.2 The receipt
A receipt is a statement the host signs, with a key it publishes, about one recipient of one issue: a file of Part XIV, 14.2's format, its envelope signed with the host's key and time-stamped, so that it is checked offline, without the host. Its statement:
subject: exactly one, the issue record, as in 4.1;predicateType:https://openeik.org/attestation/issue-receipt/v0.1;predicate:
| Member | Meaning | |
|---|---|---|
issue | required | {id, hash}, as in 4.1 |
host | required | {name}: the host, as people know it |
recipient | required | the recipient: {person}, or {name, organisation?}; one the issue names, as it names them, or one the host sent the issue to |
sentBy | required for a recipient the issue does not name | {person}: who on the host sent the issue to that recipient, a person of the registry |
transmittal | required for a recipient the issue does not name | the host's own id for that sending, a plain string of 1 to 200 characters, unique only together with the receipt's host.name |
events | required | 1 to 10 000, oldest first: {event, at, drawing?, sequence?, root?, sha256?, of?, issue?}: the event (5.1) and when it happened, by the host's clock; for viewed, downloaded and superseded, the revision (drawing and sequence), the version (root) or the print (sha256) it was about; for a print the issue does not list, of, what it was printed from, {drawing, sequence} or {root}; and for superseded, the later issue's id |
at | required | when the host made the receipt: it holds the events until then |
For a recipient the issue does not name, the receipt is the building's only record that the host sent the issue to them, and says by whom (sentBy) and in which sending (transmittal). transmittal is the one id that only a host knows which a file of this part holds, as Part XIV, 7.2 otherwise forbids: it tells one sending from another, for people and for the host, and nothing in the building resolves it. It is unique only together with the receipt's host.name: two hosts' ids are never compared alone. A print the issue does not list is named by its digest and by what it was printed from: since a print is the same bytes each time, anyone who can read the issue can print it again and compare.
The file is drawings/issues/<issue>/receipts/<n>.json, named as 4.2 names a statement. A host MAY make a later receipt for the same recipient, with the events since; it holds that host's earlier events too. Two hosts that send one issue to one recipient never see each other's events: each makes receipts of its own, which hold its own events only, and are told apart by their host.name.
5.3 Rules
- The file MUST validate against Part XIV, 14.2's schema; its payload MUST decode to an in-toto Statement v1 whose
predicateTypeishttps://openeik.org/attestation/issue-receipt/v0.1, and its predicate MUST validate against its schema. - The statement's subject MUST be exactly one, the issue record of the folder it is in, by its path and its hash, and the predicate's
issueMUST be that issue'sidand that hash. recipientMUST be a recipient the issue names, as it names them, or one the host sent the issue to: for one the issue does not name, the predicate MUST givesentByandtransmittal.- The events MUST be in the order of their times, and none later than the receipt's
at. - An event's
drawingandsequenceMUST name a revision that the issue releases, itsroota version that it releases, and itssha256a print that it names or, withof, a print of whatofnames, which MUST be a revision or a version that the issue releases. - Every signature MUST have a time-stamp.
- Each signature MUST verify, with its time-stamp, by a key the host publishes (5.6), of a file whose
host.nameis the receipt's: a verifier is given the host's keys, with their windows of validity, as trust anchors, as it is given the time-stamp authority's certificate (Part XIV, 14.3). - A later receipt for the same recipient from the same host, by its
host.name, SHOULD hold every event of an earlier one. Receipts of two hosts are not compared: neither sees the other's events. - The file's name SHOULD be made as Part XIV, 14.2 says.
5.4 The recipient's own word
A receipt is the host's word. A recipient MAY also sign received (section 4): their own word, with their own key, about exactly this issue. A contract that rests on receipt SHOULD ask for the recipient's statement.
5.5 Where they are kept
A host keeps its events, its delivery and its links, and offers a receipt as this file; the authoring tool saves it beside its issue, as it saves reviews (Part XIV, 13) and sign-offs (Part XIV, 14.4). A host never writes the building. A receipt names a person and says when they looked at what: it is personal data (section 8, rule 2).
5.6 A host's keys
A host publishes the keys it signs with in one file on its own origin, so that a verifier can fetch them, or be given them, as the trust anchors of 5.3, rule 7. It is no file of the building, which names no host's URL (section 8, rule 5): the folder never holds it, and which origin is a host's is the verifier's caller's to say, as which time-stamp authority to trust is.
The file is /.well-known/openeik/host-keys.json at the host's origin, over HTTPS (https://host.example/.well-known/openeik/host-keys.json), held to schemas/0.2/review/host-keys.schema.json, which is closed, as this part's other schemas are:
| Member | Type | Meaning | |
|---|---|---|---|
format | required | "openeik-host-keys/0.1" | |
host | required | {name} | the host, as people know it: the host.name of its receipts and of its attestations (5.2; 6.1) |
keys | required | list, 1 to 100 | the keys it signs with, each in the shape of a key of the registry (Part XIV, 5.1), {keyid, algorithm, public, validFrom, validUntil?}, with no rpId: algorithm is ed25519 or ecdsa-p256, as Part XIV allows; public, the base64 of its DER SubjectPublicKeyInfo; and validFrom and validUntil, RFC 3339 times in UTC, the window in which it signs |
{
"format": "openeik-host-keys/0.1",
"host": {"name": "Example Host"},
"keys": [
{"algorithm": "ed25519", "keyid": "k-host-3f2a9c1d7e40", "public": "<base64 SPKI>", "validFrom": "2026-10-26T00:00:00Z", "validUntil": "2027-04-26T00:00:00Z"},
{"algorithm": "ed25519", "keyid": "k-host-8b51e6a0c2d9", "public": "<base64 SPKI>", "validFrom": "2027-04-20T00:00:00Z"}
]
}
The first key is retired and stays listed; the second took over a few days before the first ended, as a host rolls one key over to the next.
The path is a well-known URI (RFC 8615) under the name openeik, which other files of the standard that a host serves can share. The name is not registered with IANA, as RFC 8615, 3 asks of a well-known URI: that registration is not done. The steward decided on 26 October 2026 that it is done once this part is published in 0.2 (open question 84).
- A host that signs a receipt, or attests terms accepted, MUST serve its keys in this file, at
/.well-known/openeik/host-keys.jsonon its origin, over HTTPS, asapplication/json, and the file MUST validate against its schema. It SHOULD let any origin read it (Access-Control-Allow-Origin: *), so that a verifier in a browser can fetch it. host.nameMUST be, exactly, thehost.nameof each receipt and attestation the host signs with a key of the file.- A key of the file MUST sign only the host's statements of this part: its receipts (5.2) and its attestations of terms accepted (6.1,
byhost). The host signs nothing else with it, and signs those with no key the file does not list. - Each key's
publicMUST be a key of itsalgorithm, and itsvalidUntil, where given, MUST NOT be before itsvalidFrom. AkeyidMUST be listed once, and a host MUST NOT give a key id to another key, ever, not even one of a key it no longer lists. - A host retires a key by giving it a
validUntil. A retired key MUST stay listed, itsvalidUntilunchanged, and a host MUST NOT remove a key, nor change itsalgorithm,publicorvalidFrom, once it has signed with it. Several keys MAY be valid at once, as while a host rolls a key over. - A verifier fetches the file from the host's origin over HTTPS, or is given it by its caller, and pins it: it records the SHA-256 of the bytes it trusted, and verifies with the keys of that file, not with what the host serves later. A later file it takes in place of a pinned one SHOULD hold every key of the pinned one, unchanged but for a
validUntilgiven to a key that had none; a verifier that finds a key removed or changed SHOULD NOT take the later file without its caller's word. - A verifier verifies a receipt, or a host's attestation of terms accepted, only by a key of a file whose
host.nameis the statement'shost.name, and only where the key was valid at the time-stamp's time: from itsvalidFrom, and before itsvalidUntil(5.3, rule 7; 6.2, rule 7).
6. Terms accepted
6.1 The record
project/terms-accepted/<n>.json says that a named person accepted named terms, for the building or for one issue. It is a statement in a file of Part XIV, 14.2's format, signed by the person with a key of their record, or attested by a host with a key it publishes, where the person accepted the terms on the host after signing in. Its statement:
subject: the terms,terms/<sha256>with the SHA-256 of their text, and, where they are an issue's, the issue record as in 4.1;predicateType:https://openeik.org/attestation/terms-accepted/v0.1;predicate:
| Member | Meaning | |
|---|---|---|
person | required | who accepted them, a person of the registry |
terms | required | {sha256, title, version?}: the terms, by the SHA-256 of their text, with their title and version as people know them |
for | required | {project, issue?}: the building, by its project's id (Part II, 2), and, where the terms are an issue's, the issue as {id, hash} |
by | required | person, where the person signed with their own key; host, where a host attests it |
host | required for host, and absent for person | {name}: the host, as people know it |
at | required | when the person accepted them, by the signer's clock |
The folder MAY keep the terms' text as an asset, assets/<sha256>.pdf (Part XV). Terms that change are new terms, with a new digest: an acceptance names the text it accepted.
6.2 Rules
- The file MUST validate against Part XIV, 14.2's schema; its payload MUST decode to an in-toto Statement v1 whose
predicateTypeishttps://openeik.org/attestation/terms-accepted/v0.1, and its predicate MUST validate against its schema. - The subjects MUST be the terms,
terms/<sha256>with their digest, and, wherefornames an issue, that issue's record by its path and its hash: nothing else. personMUST name a person of the registry of the kindperson.- With
byperson, each signature'skeyidMUST be a key of that person's record; withbyhost, the signature is the host's, by a key the host publishes (5.3, rule 7; 5.6). for.projectMUST be the project's id, andfor.issue, where given, MUST name an issue of the folder by its record's hash.- Every signature MUST have a time-stamp.
- Each signature MUST verify, with its time-stamp, as Part XIV, 14.7, rule 9 says, or, with
byhost, as 5.3, rule 7 says. - The file's name SHOULD be made as Part XIV, 14.2 says.
6.3 What it says
An acceptance says that a person named in the registry accepted the terms with this digest, for this building or this issue, at a time that a time-stamp proves. Whether that binds anyone is the law's (1.1). A host that asks a recipient to accept terms before an issue opens keeps its own record, and offers this file; the authoring tool saves it. An acceptance is personal data (section 8, rule 2).
7. Prints
7.1 A print is not the record
A print is a copy made for people to read or for another tool: a PDF of a revision (Part XIV, 15), or an IFC exported from a version by a bridge (Part VIII). It is dead matter, as paper is. What was issued, reviewed and signed is the revision or the version, by its digests; a print says only what it is a copy of. Two prints are never compared to find what changed: revisions are (Part XIV, 9 and 17.3), and so are versions (Part VI, 4). One print is kept: a PDF rendition signed in the legal tier, beside its revision as its signed copy (Part XIV, 15.1). A consultant's PDF that is the drawing, an unlinked drawing (Part XIV, 8.3), is no print: it is issued and reviewed as it is.
- An application MUST NOT take a print in place of the revision or the version it was printed from: a review, a sign-off and a statement are about the revision or the version, never about a print.
- A tool SHOULD NOT compare two prints to say what changed between them; it compares the revisions or the versions they were printed from.
- A host or an application that offers a print SHOULD call it one ("Print as PDF", "Print as IFC"), so that no one takes it for the record.
7.2 An IFC names its version
- A bridge that exports IFC from a version MUST name in the file the version it was exported from, where it knows it: an
IfcPropertySetnamedOpenEik_Source, related to theIfcProjectby anIfcRelDefinesByProperties, with the single-value propertiesVersionRoot, the version's root tree hash (Part VI, 2, rule 4), andVersionId, its id, each where it knows it;ProjectId, the project's id (Part II, 2);Bridge, the bridge and its version (@openeik/tools 0.1.0-draft); andPrint, theIfcBooleantrue.VersionRoot,VersionIdandProjectIdareIfcIdentifiers, andBridgeanIfcLabel. - Its
IfcApplicationMUST name the bridge and its version, and itsIfcOwnerHistorythat application. - The file SHOULD say that it is a print where people read it: the header's
FILE_DESCRIPTION, in its description list, and theIfcProject'sDescriptionSHOULD each carry a sentence that names the version by the short form of its root, says that the file is a copy, like paper, and that the OpenEik building is its source, such as "A print of OpenEik version 6b572fb1e20a: a copy, like paper. The OpenEik building is the source."Printis the mark a program reads; the sentence is for people. - The
IfcOrganizationof itsIfcOwnerHistory, the organisation of its owning user, SHOULD name who printed the file, a host or an application, as people know it, which the bridge's caller gives; theIfcApplicationnames the bridge, which did the printing for it. - The fidelity report of Part VIII, 1, rule 2 goes with every export, as before, and a short form of it SHOULD travel in the file: an
IfcDocumentInformationnamedFidelity report, associated with theIfcProjectby anIfcRelAssociatesDocument, saying the IFC schema written, the counts and what the export leaves out or approximates. - A bridge SHOULD give the same bytes for the same version, bridge and options, who printed the file among them. It writes no time but one its caller gives it, or else a fixed time it states, in the header's
time_stampand inIfcOwnerHistory'sCreationDate; and no id, order or name that changes from one export to the next.
OpenEik_Source is no Pset_ set: IFC keeps the prefix Pset_ for buildingSMART's own property sets, and a reader finds this one by its name on the project. Rules 1 and 2 let a program tell a print and the version it came from; rules 3 and 4 tell a person, in any IFC viewer, what they are looking at and who printed it; rule 5 keeps what the print leaves out with the print.
7.3 A PDF's margin note
Part XIV, 15.3 says it, by plan 688's decision 6: a PDF rendition carries in its bottom margin the drawing's number and revision code, the building, the version it was drawn from, a sentence saying it is a copy, and a QR code that names the revision by its SVG's digest; and no time of printing, so that it stays the same bytes.
8. Security and privacy
- A link looks, a person decides. A host MUST NOT offer, as a person's item, reply, decision or statement, anything made by someone who has not signed in as that person. A link without sign-in looks and prints: it gives nothing that the building records.
- Personal data. A receipt says when a named person opened what and looked at it; an acceptance, that they accepted terms; a model review, what they said. Each is personal data, kept in every version that holds it (Security and privacy, 2.4). An authoring tool SHOULD save a receipt only where the project needs it, as a contract may, and a host SHOULD tell a recipient that what it records of them may be saved into the building.
- A host's word. A receipt and a host's attestation are as good as the host's key. A verifier trusts a host's key only as its caller says, within the key's window of validity, and a host ends a key it stops using, and never reuses it. A receipt's time-stamp proves when the receipt was made, not when its events happened: those are the host's clock. The file of a host's keys (5.6) is a trust anchor, and its integrity is the verifier's business: HTTPS proves only that the host's origin served it when it was fetched. So a verifier records the SHA-256 of the file it trusted, and a host never removes a key once it has signed with it: what verified once verifies again with the same file, and a host that serves another file later cannot change it.
- The check code. A print's QR code names a digest, and the page it leads to is the host's. That page SHOULD say only whether the revision is current, and the later revision's code where there is one, and SHOULD show nothing more to anyone who has not signed in: whoever holds the paper has seen what it holds, and no more.
- No host in the building. No file of this part holds a host's URL, an account's id or an email address (Part XIV, 7.2): a host is named as people know it, and its key by a keyid. A receipt's
transmittalis the one id of a host's it holds, and names a sending, never an account (5.2).
9. Conformance
A claim of conformance to OpenEik 0.2 is a claim to what this section asks of each class it names, the host and the authoring tool among them (Conformance, 1 and 1.1). A claim to 0.1 says nothing about it. Of 0.2, each class does as follows:
- a validator checks the rules of sections 2 to 6 that the folder decides, reporting a breach of a MUST as an error and a breach of a SHOULD as a warning, and naming the file and the rule, as
XVIII.2.5.7; - a drawing validator (Part XIV, 19.2) also verifies statements, receipts and acceptances (4.3, rule 6; 5.3, rule 7; 6.2, rule 7), given the hosts' keys (5.6) and the time-stamp authorities' certificates as trust anchors, and keeps 5.6, rules 6 and 7;
- a bridge names the version it exports from (7.2);
- a host keeps the events of 5.1 and offers receipts, publishes its keys as 5.6, rules 1 to 5 say, and keeps section 8, rules 1 and 4;
- an authoring tool saves what a host offers, and records a named version of what it issues (3.2, rule 3).
The folder alone decides most rules. These need more:
- the reviewed version, or the history: 2.5, rule 4; 2.5, rule 5, for the file held unchanged; 3.2, rule 4;
- cryptography beyond hashing: 4.3, rule 6; 5.3, rule 7; 6.2, rule 7;
- a host's keys, which the folder never holds: 5.3, rule 7; 5.6; 6.2, rule 7 for
byhost; - the bridge's output: 7.2.
A validator reports a breach of these rules as an error: 2.5, rules 1 to 3, 5 and 7 to 11, and rule 4 for an anchor's hash; 3.2, rules 1, 2 and 4; 4.3, rules 1 to 7; 5.3, rules 1 to 7; and 6.2, rules 1 to 7. It reports a breach of these as a warning: 2.5, rule 4 for an anchor's element, and rule 6; 4.3, rule 8; 5.3, rules 8 and 9; and 6.2, rule 8. A verifier does not take a host's file of keys that does not validate or breaks 5.6, rule 4, and reports a statement that 5.6, rule 7 does not let verify as a breach of 5.3, rule 7 or 6.2, rule 7. The other rules bind issuers, tools, bridges, hosts and verifiers, and a validator does not check them from the folder: 3.2, rule 3; 5.6, rules 1 to 3, 5 and 6; section 7; and section 8.
10. The questions
The steward decided these questions on 26 October 2026, each as this part proposed it (open questions 61 to 68). Question 84 is proposed.
| Question | What | Decided |
|---|---|---|
| 61 | Markup shapes | an optional shape.form (freehand, polyline, polygon, rectangle, ellipse), a rectangle or an ellipse by the four corners of its rectangle, turned as it lies, and shape on a text and a comment as its words' frame; the six item kinds stay; colour and line weight are extension members (Part XIV, 13.2 and 13.4, rule 9) |
| 62 | Where a model's review lives | in this part, a part of its own with its own proposal, review, built on Part XIV's registry, profile, issues and statements, rather than in Part XIV or Part VI (sections 1 and 2) |
| 63 | How a version is issued | by Part XIV's issue, which gains versions, renditions and terms, rather than by a file of its own (section 3) |
| 64 | What an issue's statement signs | the issue record alone, one subject, which names everything else by its hash (section 4) |
| 65 | How a host's receipt is checked | with a key the host publishes, which a verifier is given as a trust anchor, rather than a record of the building's registry (section 5) |
| 66 | Terms accepted | a statement in project/terms-accepted/, signed by the person or attested by a host, for the building or an issue (section 6) |
| 67 | A profile without fonts | drawings/profile.json serves a model's reviews too, and needs fonts only where the folder holds a linked issued drawing (Part XIV, 4.1 and 4.3, rule 5) |
| 68 | Recipients a host adds | a receipt may be for someone the host sent the issue to and the record does not name, with sentBy and transmittal; an event may name a print the host made on demand, by its digest and what it was printed from (of); and such a recipient, a person of the registry, may sign received (sections 4 and 5) |
| 84 | The well-known name openeik | proposed, not decided: registered with IANA as a well-known URI (RFC 8615) once this part is published in 0.2, with a template in this part; until then a host serves its keys at the path 5.6 gives, unregistered |