Eidos

Eidos File 1.0 format

An Eidos File is a SQLite 3 application file with the .eidos extension. The canonical, implementation-independent contract is Eidos File 1.0.

File identity

PropertyValue
Extension.eidos
Media typeapplication/vnd.eidos+sqlite3
SQLite headerSQLite format 3\0
PRAGMA application_id0x45494453 (EIDS)
PRAGMA user_version1
eidos__meta.format_version1.0

Readers verify all of these identities and the singleton eidos__meta row. The extension alone is not sufficient. Every persistent ID is the same RFC 9562 UUIDv7 representation in SQLite, APIs, JSON, and CSV: lowercase, hyphenated, 36-character TEXT COLLATE BINARY. BLOB, uppercase, braced, URN, and 32-character forms are not canonical IDs.

Every connection enables foreign_keys and disables trusted_schema.

Canonical layout

project.eidos
├── eidos__meta
├── eidos__features
├── eidos__tables
├── eidos__fields
├── eidos__relation_fields
├── eidos__formula_fields
├── eidos__lookup_fields
├── eidos__views
└── user-named STRICT, WITHOUT ROWID tables

eidos__tables.name and eidos__fields.name are display names. physical_name is the exact quoted SQLite identifier. A new or explicitly renamed object first uses its display name verbatim—even when it contains spaces, Chinese text, punctuation, or an SQL keyword. A stable UUID suffix is added for a SQLite identifier collision and for reserved system Field names. A Table display name beginning with sqlite_, eidos__, or x__ uses the frozen readable fallback t__<first-8-id-hex>__<display-name> (with the specified bounded collision extension), so the physical object never enters a reserved namespace.

Field names are unique within a Table under SQLite NOCASE. Field IDs remain stable across rename and are used by Views, Lookup, inverse Relation, and the dependency graph.

User tables and values

Each user Table is STRICT, WITHOUT ROWID and contains:

"_id"         TEXT COLLATE BINARY PRIMARY KEY CHECK(length("_id") = 36)
"_created_at" TEXT NOT NULL
"_updated_at" TEXT NOT NULL

The hidden SQLite rowid is never Eidos identity. Every Table has exactly one Record Label Field, but there is no required Title or Name Field.

FieldCanonical stored value
Text, URLTEXT or NULL
Numberfinite REAL or NULL
IntegerINTEGER or NULL
Date, datetimecanonical TEXT or NULL
Checkbox0, 1, or NULL
Selectoption name as TEXT
Multi-selectordered unique JSON string array
Fileordered JSON object array
JSONcanonical JSON text
Forward Relationordered unique JSON UUID array

A date is exactly YYYY-MM-DD. A datetime and every created_at / updated_at value use the fixed UTC form YYYY-MM-DDTHH:MM:SS.sssZ. API and CSV offset inputs are normalized to UTC before storage; sub-millisecond input is rejected unless the caller explicitly requests a lossy conversion. These fixed-width strings use SQLite BINARY ordering, so lexical order is chronological order.

Select options have no IDs or separate value table. The optional display catalog lives in settings_json as { "options": [{ "name", "color" }] }; unconfigured raw cell values remain valid.

A File item contains canonical UUIDv7 id, non-empty name, RFC 6838 mediaType, uri, and size as a non-negative int64 decimal string. Unknown members are preserved. Relative URIs resolve from the directory containing the Eidos File, use /, and cannot be absolute or escape with ..; HTTPS URIs are also allowed. The bytes remain external to the SQLite cell. Asset existence, authorization, transfer, resolution, and garbage collection belong to the Adapter.

Relation, Formula, and Lookup

A forward Relation is a real JSON source column. Its subtype row records the target Table, cardinality, and restrict, detach, or preserve deletion policy. An inverse Relation is a virtual reverse projection and stores no mirror column or global edge table.

Formula source is one deterministic expression. Every Field reference uses the exact current Field name as a double-quoted identifier, for example:

"Estimate" * 1.2
coalesce("Project budget", 0)

Field rename parses Formula source and rewrites only reference nodes; string literals are unchanged. Formula, Lookup, and inverse Relation results are virtual. Their file-wide Field-ID dependency graph must be acyclic, and Runtime queries evaluate only requested transitive dependencies with set-based SQL.

Queries and writes

View query_json and layout_json use Field IDs. Runtime projection, filtering, multi-sort, keyset paging, grouping, and statistics operate over the same live logical values, including Formula and Lookup results.

Every logical mutation is one transaction. It validates the optional expected revision, updates canonical state, checks affected invariants, increments eidos__meta.revision exactly once, and either commits everything or rolls it all back.

Generated indexes, resolved labels, compiled plans, and caches are disposable Host-private state. They are never required to interpret the .eidos file.

Field capability matrix

The field capability matrix is a live, self-contained .eidos sample — not a screenshot or a second hand-maintained table. Open it in the Eidos File web editor from Choose a template → Field capability matrix, where you can search it, download it, or edit a copy.

Feature negotiation and extensions

Feature support is an exact, case-sensitive (name, version) tuple; versions do not imply Semantic Versioning compatibility. An unsupported or invalid required feature blocks canonical Reader and Writer conformance. Unknown optional state must be preserved byte-semantically, otherwise the Writer must refuse the write.

Third-party objects and features use the x__<vendor>__* namespace. Every extension object needs a matching feature declaration. Extensions cannot add eidos__* objects, attach triggers to core or user tables, shadow user physical names, or reinterpret core raw values.