/ 01The container
A .fieldbook file is a ZIP archive. You can open it with any standard unzip tool — the contents are documented and the structure is stable across versions.
mydata.fieldbook (ZIP) ├── manifest.json # File metadata, version, integrity hashes ├── schema.json # Table and field definitions ├── database.sqlite # SQLite database (may be AES-256-GCM encrypted) ├── oplog.json # Operation log (hash-chained, CRDT-enabled) ├── audit.json # Access/disclosure audit log (hash-chained) ├── qa.json # QA question/answer log (optional) ├── views/grid.json # View configurations (optional) ├── workbook.xlsx # Auto-generated Excel export (native only) ├── documents/ # Embedded documents │ ├── index.json │ └── contract.pdf ├── attachments/ # Cell-level file attachments │ └── {table}/{record}/{filename} └── snapshots/ # Point-in-time backups ├── {id}.sqlite └── {id}.schema.json
Format version is recorded in manifest.json → format_version. Readers below the min_reader_version refuse to open the file rather than risk silent data loss.
/ 02manifest.json
The file's identity card: ID, version, integrity hashes, encryption parameters, retention, legal hold, extension blocks.
{
"fieldbook_version": "1.0.0",
"format_version": "1.1",
"min_reader_version": "1.0",
"id": "fb_a1b2c3d4e5f6",
"name": "My Fieldbook",
"integrity": {
"schema_sha256": "...",
"sqlite_sha256": "...",
"oplog_sha256": "...",
"audit_sha256": "..."
},
"retention": { "default_retention_days": 365 },
"legal_hold": { "active": false },
"extensions": {
"encryption": { "algorithm": "aes-256-gcm", "kdf": "pbkdf2-sha512", "iterations": 256000 }
}
}
/ 03schema.json
Tables and fields. Every table has a stable id, a confidentiality tier, an optional row-policy list, and an ordered field list.
Field types
| Type | SQLite column | Use for |
|---|---|---|
Text · TextLong | TEXT | Short / long text — FTS5 indexed |
Email · Phone · Url | TEXT | Validated text variants |
Number · Currency · Percentage · Duration | REAL | Numeric |
Autonumber · Rating | INTEGER | Sequential / scored |
Date · Datetime | TEXT (ISO 8601) | Temporal |
Checkbox | INTEGER 0/1 | Boolean |
Attachment | TEXT (path) | File reference under attachments/ |
Select · MultiSelect | TEXT | From options list |
Lookup · Rollup · Formula | computed | No column — evaluated at read |
/ 04database.sqlite
The user data, plus system tables. May be AES-256-GCM encrypted as a whole (see encryption & recovery).
System tables
_fb_metaKey-value metadata (current schema version, last sync clock, etc.)_fb_schema_versionMigration history: version, applied_at, description_fb_provenancePer-record data lineage — source, imported_at, original_format_fb_error_logError tracking with timestamp, severity, message, context
User tables
Named fb_{table_id}. Every row carries _fb_id, _fb_created_at, _fb_modified_at plus per-schema field columns. FTS5 virtual tables are auto-created for Text / TextLong fields.
/ 05oplog.json
Append-only mutation log. Hash-chained, CRDT-enabled, the basis of sync.
{
"device_id": "dev_xyz",
"clock": 42,
"entries": [{
"id": "op_...",
"timestamp": "2026-04-15T11:14:22Z",
"op_type": "UPDATE_CELL",
"table_id": "tbl_...",
"record_id": "rec_...",
"field_id": "fld_...",
"old_value_hash": "sha256:...",
"new_value_hash": "sha256:...",
"prev_hash": "sha256:...",
"hash": "sha256:..."
}]
}
Each entry's hash covers prev_hash + id + timestamp + op_type + table_id + record_id + field_id + old_value_hash + new_value_hash. Canonicalisation uses RFC 8785 so Rust, Swift, and the WASM verifier produce identical hashes from identical payloads.
/ 06audit.json
The access and disclosure log. Same hash-chain primitive as the oplog, different event vocabulary.
Action classes
- File —
FileOpened,FileClosed - Access —
ViewAccessed,DocumentViewed,DocumentDownloaded,DocumentSearched - Export —
ExportPerformed,ExportGenerated - Tokens —
VdrTokenUsed,VdrTokenCreated,VdrTokenRevoked - Integrity —
IntegrityCheckPassed,IntegrityCheckFailed - GDPR —
GdprErasePerformed,GdprEraseCompleted - RLS —
RlsFilterApplied,RlsPolicyAdded,RlsAccessDenied
/ 07documents/ & attachments/
documents/ holds file-level embeds — contracts, screenshots, evidence. Each is referenced from documents/index.json with a SHA-256 fingerprint that's verified on open.
attachments/ holds cell-level file attachments, namespaced by {table_id}/{record_id}/{filename}.
Both directories are content-addressed: changing a byte changes the manifest's document_hashes entry, invalidating the integrity check until re-signed.
/ 08snapshots/
Point-in-time SQLite copies, used for rollback, legal hold, and before-destructive-action safety.
| Reason | When taken |
|---|---|
Manual | User-requested |
BeforeTableDelete · BeforeFieldDelete | Schema changes |
BeforeBulkDelete | Bulk row deletion |
BeforeGdprErase | GDPR right-to-erasure |
BeforeRestore · BeforeImport | Risky mutations |
Scheduled | Periodic snapshots |
Maximum 10 snapshots per file. Oldest non-legal-hold snapshots are evicted when the limit is exceeded.
