# Map v0.1 — A Carrier for Place Status: **Draft Standard**. Reference implementation: [`map-rs/`](map-rs/) (Rust workspace, Apache-2.0). Specification text: CC-BY-4.0. The keywords **MUST**, **MUST NOT**, **REQUIRED**, **SHALL**, **SHALL NOT**, **SHOULD**, **SHOULD NOT**, **MAY**, and **OPTIONAL** are to be interpreted as described in RFC 2119. --- ## 1. Scope and doctrine Map specifies how a region of the world — at a place, an altitude, an instant, and a fidelity — is identified, addressed, resolved through an energy-tiered fidelity cascade, and reported with its energy cost. It is the **geospatial cargo class** of the Transaction Science substrate. Where [Smart Byte](../smart-byte/) carries value, [Joule Code](../joule-code/) carries coding work, and [EOC](../eoc/) carries compute, Map carries **place**. The **doctrine** is one sentence: *the map is a file, not a service.* Three normative consequences follow. ### 1.1 The tile is the cargo (REQUIRED) The unit of place is a **tile**: a content-addressed, signed unit of the world at a single 4D cell, with its energy cost intrinsic. A tile is not an image and not an API response. It is a vesicle carrying exactly five things — identity (the BLAKE3 content address of its canonical serialization), a cell key (where/when/how-detailed it is), provenance (the prior tileset root it was published under, and the author key that signed it), cargo (the payload — terrain, a field, vector features, or splats), and a two-part joule cost (`measured + estimated`, honestly tagged). ### 1.2 The cascade (REQUIRED) A conforming resolver **MUST** resolve every render request through an explicit energy-tiered **fidelity cascade**, **MUST** return the highest tier that is at or below the requested fidelity *and* holds data for the cell, and **MUST** fall back toward the base floor — which always closes the request. The tiers are energy-ordered: | Tier | Wire tag | Named tag | Joule class | Payload for a render request | |------|----------|------------|-----------------|-------------------------------------------------------------------------| | F0 | `F0` | Cache | picojoules | content-addressed tile already resolved in the local store (OPFS) | | F1 | `F1` | Base | microjoules | terrain DEM + coastlines + borders — the universal floor, always present | | F2 | `F2` | Field | sub-millijoules | raster + scalar/vector field tiles (imagery, weather grids, wind) | | F3 | `F3` | Feature | millijoules | vector feature tiles (roads, POIs, labels, airspace) + live entities | | F4 | `F4` | Photoreal | joules | 3D Gaussian splats — dense, sparse-coverage; the escape hatch | A resolver **MUST NOT** return a tier above the requested fidelity. A resolver **MUST NOT** fail a render request for a covered region: F1 **SHALL** be defined everywhere on the datum, so graceful fallback is a property of the standard, not of an implementation. A resolver **MUST** record in the receipt the tier that actually closed the request. F0 is the cache short-circuit and **MAY** close any request whose cell key was previously resolved. > The cascade is inverted relative to compute cascades (JouleClaw, Joule Code) only in *intent*: there the cheapest sufficient tier wins; here the highest *available* tier at or below the request wins, with the cheap floor as the guaranteed fallback. The shared invariant is identical — **stop at the first tier that closes the request, and record it.** ### 1.3 The receipt (REQUIRED) Every resolve/decode operation **MUST** report a two-part energy cost in integer microjoules — `measured + estimated` — with a `Provenance` tag (`HwShunt | ModelBased | Estimator`) on every reading, sealed as a **JCR-1** envelope (canonical det-CBOR + COSE_Sign1/EdDSA — the family's shared signed-receipt format). A `measured` figure **MUST** originate from a hardware energy interface; the spec never claims an accuracy the platform cannot deliver. --- ## 2. The cell key A tile is addressed by a 4D **cell key** with four orthogonal axes (`map-schema::CellKey`): ``` CellKey { s2: S2CellId, // horizontal position + extent (hierarchical, levels 0..30) alt: AltBand, // altitude band index (signed; band 0 = datum surface) time: TimeBucket, // half-open [start, start+width) interval; bucket 0 = atemporal lod: Lod, // 0..=MAX detail level within the tier } ``` - **Horizontal (REQUIRED).** The `s2` axis **MUST** be an S2 cell identifier. S2 is a hierarchical, space-filling (Hilbert-ordered) decomposition of the sphere: adjacent cells are adjacent in the integer key space, which is what makes a tileset range-requestable (§4). An implementation **MUST** treat the S2 level as the horizontal LOD. - **Vertical (REQUIRED).** The `alt` axis **MUST** be a signed band index against a declared band schedule (`map-schema::AltSchedule`). Band 0 is the datum surface; negative bands are sub-surface; positive bands are altitude. Atmospheric and orbital payloads occupy positive bands; bathymetry occupies negative bands. - **Temporal (REQUIRED).** The `time` axis **MUST** be a `TimeBucket`: a half-open interval anchored to TAI. Bucket 0 is reserved for **atemporal** tiles (a coastline, a border). A weather forecast cycle, an AIRAC navigation cycle, and an ADS-B snapshot are distinct, non-zero buckets. The temporal axis is first-class: a "map of Tuesday at 14:00Z" is a different, equally addressable region from "the same place on Wednesday." - **Detail (REQUIRED).** The `lod` axis is the within-tier detail level, independent of the S2 level (which is the horizontal extent). A splat tile at S2 level 20 **MAY** carry LODs 0..N of progressively denser Gaussians. Two cell keys are equal iff all four axes are equal. The canonical serialization of a `CellKey` (§3) is deterministic, so its BLAKE3 hash is a stable join key across implementations. --- ## 3. Canonical serialization and content addressing Every Map structure that is hashed or signed **MUST** be serialized with the family's deterministic CBOR profile (det-CBOR: definite-length, canonically-ordered keys, no floats where an integer suffices). The **content id** of a tile is `blake3(canonical_serialization)` (`map-schema::ContentId`, 32 bytes). Content ids are the only cross-reference Map uses internally: a tileset directory maps cell keys to content ids; a manifest commits to content ids; a receipt references the content ids it resolved. A tile is **immutable**: changing any byte changes its content id and therefore its identity. There is no in-place edit. Revision happens at the tileset level (§5). --- ## 4. The tileset (REQUIRED) A **tileset** is the on-disk, range-requestable archive — the "it's just a file" deliverable. A conforming tileset is a single addressable blob on dumb storage (object store, static host, OPFS) with three parts: 1. A **header** with a magic tag, the standard version, the datum, the alt schedule, and the byte offset of the directory. 2. A **directory** mapping `CellKey → (byte_offset, byte_len, content_id)` for every tile in the set, **MUST** be ordered by the S2 (Hilbert) key so that the tiles of one viewport occupy a near-contiguous byte range. A reader **MUST** be able to fetch the directory, compute the cell keys a viewport needs, and issue HTTP range requests for only those byte ranges — no server-side logic, no per-request billing. 3. The **tile payloads**, content-addressable and independently decodable. A reader **MUST NOT** be required to download the whole tileset to render a viewport. A reader **MUST** verify that each fetched payload hashes to the `content_id` the directory claims. --- ## 5. The manifest and signed transitions (REQUIRED) A tileset's authenticity rests on a signed **manifest** (`map-schema::Manifest`): a commitment to the directory root (a BLAKE3 Merkle root over the sorted `CellKey → content_id` pairs), the publisher's Ed25519 public key, the standard version, and the cell-key bounds of the set. The manifest **MUST** be signed (Ed25519 over the det-CBOR of the manifest body). A **revision** is a signed transition `prev_root → new_root` (`map-schema::Revision`): a new manifest that names the root it supersedes and is signed by the same publisher key (or a successor key it endorses). Revisions are **append-only and dated** (each carries a TAI timestamp). A new weather forecast hour, a new 28-day AIRAC cycle, and a re-flight of a corridor are revisions — never in-place mutations. A reader **MAY** pin any historical root and **MUST** be able to verify a revision chain back to a trusted root without contacting the publisher. This is the "works forever" guarantee made normative: a newsroom's election map, an archived flight plan, or a forecast cycle is a signed, dated file whose validity does not depend on any service remaining online. --- ## 6. Energy and the receipt (REQUIRED) The receipt is the family's JCR-1 envelope (`map-receipt`). A receipt **MUST** carry: - the `CellKey` and `content_id` of the tile(s) it covers; - the cascade `Tier` that closed the request; - an `Energy` record: `measured_uj: Option`, `estimated_uj: u64`, `provenance: Provenance`; - the publisher/resolver identity and an Ed25519 signature (COSE_Sign1/EdDSA over canonical det-CBOR). The provenance coupling is normative: `HwShunt` **REQUIRES** a present `measured_uj`; `Estimator` **MUST** leave it absent; `ModelBased` **MAY** include it. A session's total cost is the sum of its tile receipts. A resolver **MUST NOT** report a `measured` figure it did not measure. A reference (non-normative) estimator orders the tiers by joule class: a cache hit is picojoules; a base/terrain tile is microjoules; a field tile is sub-millijoules; a feature/entity tile is millijoules; a splat tile is joules. The standard is that the figure is reported and honestly tagged — not the constant. --- ## 7. No capture (REQUIRED) Map carries no protocol-level token. Reading a tileset **MUST** require nothing but the bytes and the publisher's public key. A conforming reader performs its core function — resolve a cell, verify it, render it, meter it — against static storage, with no contact with any single company's servers as a condition of operation. Transaction Science is one steward: it publishes the spec, ships the reference implementation, and operates optional commercial services (capture pipelines, hosted tilesets, a registry) around the substrate — not its proprietor. --- ## 8. Conformance An implementation is **conformant** if it round-trips the vectors in [`conformance/v1/`](conformance/v1/): - **C1 — cell key.** Canonical serialization and `ContentId` of the cell-key vectors match byte-for-byte. - **C2 — tileset directory.** A reader resolves the correct byte range for a viewport over the sample tileset and verifies every payload hash. - **C3 — manifest & revision.** Signature verification and revision-chain validation against the sample roots; a tampered directory root **MUST** fail. - **C4 — cascade.** For each render-request vector, the resolver closes at the specified tier and falls back to F1 where higher tiers are absent. - **C5 — receipt.** JCR-1 receipts seal, verify, and enforce the provenance ↔ measured coupling; vectors are interoperable with the family's existing JCR-1 verifiers. A negative pack (`C-neg`) covers tampered payloads, an out-of-order directory, a revision signed by an unendorsed key, and a receipt claiming `HwShunt` with no `measured_uj`. --- ## 9. Non-goals Map is a **substrate for read-heavy, published geospatial data**. It is explicitly **not** a live geocoding/routing *service* (the reference ships `map-route` as a local capability over a tileset, not a hosted API), and it is **not** a certified primary navigation source. Air-navigation payloads are for **situational awareness, planning, and simulation only** — never a DO-178C/TSO-certified source of primary flight guidance. A conforming flight-nav tileset **MUST** carry this disclaimer in its manifest metadata.