Skip to content

8. The registration

Contents of FBL 0.6

8.1 The line form

A registration is a small text file, *.adp, that names what a document is and keeps the view data a user placed. It is UTF-8 lines:

databricks/job
body: resources/nightly_ingest.yml
resource: nightly_ingest
layout:
  task:ingest: 0 0
  task:quality_gate: 260 0
  1. Line 1 is the origin of the tool type (language.origin, DISL §3.2), after a byte-order mark if there is one. A host finds the tool type's specification with that origin, and through its persistence the binding: the one a DISL specification's persistence.binding names, or, of the bindings a DESL specification's persistence.bindings names, the one whose claims take the body (section 12.1). A body two of them claim is refused with a reason, and a validator reports a specification whose bindings claim one extension twice.
  2. Headers follow, one per line, key: value (the first : separates them; blank lines are skipped). FBL defines body, view and resource; a binding declares others in registration.headers (the SKOS reading's language). A header neither defines is kept and reported as fbl.unknown-header. The header region ends at the first line that is not a header.
  3. Blocks follow the headers: layout: (section 8.3) and identities: (section 8.6), each a line holding only the block's name and colon, followed by its entries, each indented by two spaces (any whitespace is read), <key>: <value>, where the key is everything before the last : of the line, so keys may contain : .

Anything after the blocks is kept as unbound content. $defs/Registration in fbl.schema.json describes the parsed form; the examples in registrations/ validate against it.

8.2 Finding the body

body is a path relative to the registration's folder, /-separated. Without it, the body is the sibling file with the registration's base name and one of the binding's extensions (the first that exists, in the order of claims.extensions), or, for a folder binding, the folder the registration is in. A body that does not exist opens the document empty with fbl.missing-body, and nothing is written until the user points the registration at a file. A host MUST NOT follow a body outside the workspace without the user's consent (section 16).

view names which view of the body the document shows (section 9.3). resource selects one resource of a body that holds several: its value binds the selector capture the binding's registration.resource.capture names (a Databricks bundle file's job key); without the header, the first such entry in document order is used.

8.3 The layout block

layout: holds the positions the user placed, and only those: one entry per placed element, <id>: <x> <y>, the top-left corner of the element in the reading's canvas units. An element without an entry is placed by layout. Entries are:

  • written in the ordinal order of their ids (byte order of the UTF-8 encoding);
  • with numbers in {decimals: 3} form (section 6.3), so 120.5 and 640;
  • with the registration's own line ending by the rules of section 6.3.

Placing an element for the first time inserts its entry (insert-entry), creating layout: after the headers first when it is missing (ensure-container); moving it replaces its numbers (replace-value); undoing the first placement removes the entry, and the layout: line with the last entry (remove-container). Other view data (sizes, waypoints, label offsets) is not stored in FBL 0.1.

8.4 Writing the registration

A registration is written with the splice rules of section 6, so a user's hand edits, comments below the blocks and unknown headers survive. View changes write only the registration; model changes write only the body, except where one edit concerns both (a rename of a stored id moves its layout entry in the same edit, with splices in both files, undone together). A host creates a registration beside a body the first time the user places an element, when the binding's registration.createOnFirstPlacement is true, and refuses the placement with a reason otherwise; a registration created this way is <origin> then body: <name> when the body's base name differs from the registration's, with the body's dominant line ending.

8.5 Stale and ephemeral ids

A layout entry whose id is not in the model is stale: it is not applied to any other element, it is reported as fbl.stale-view-data, and it is removed at the next write of the registration, as part of that edit. A host MUST NOT store a position for an element whose id DISL marks ephemeral; dragging such an element moves it for the current session only, and the host tells the user why the position will not be kept. A layout entry found for an ephemeral id is ignored and reported by DISL's std.ephemeralViewData (DISL §11.5.3).

8.6 Identities

identities: holds ids for bindings whose rules use id.sidecar (section 5.3): one entry per element, <natural key>: <id>, where the natural key is the value of the rule's sidecar.key expression and the id is made by DISL's strategy the first time the element is read without one. Entries are written, ordered and pruned like layout entries. Two elements with the same natural key share nothing: the second is reported as DISL's std.duplicateId and gets an id that is not stored.

8.7 Legacy sidecars

Two sidecar files that hosts wrote before FBL are read, so existing documents keep their view data:

  • registration.legacyLayout, such as {base}.layout.json for the C4 types: a JSON object keyed by view key, then by element id, each {"x": …, "y": …}. Positions of the registration's view are read from it when the registration has no layout: block, and written back to it, by json splices, as long as it exists; view keys are matched ignoring case.
  • registration.legacyIdentities, such as {base}.identities.json for the Wardley map: a JSON object mapping a natural key to an id, read when the registration has no identities: block and written back to it while it exists.

A host MUST NOT create either file for a new document.

Referenced from