Skip to content

RFC: single-source rule for spatial: properties (resolves #6, #8, #12, #23) #32

Description

@wietzesuijker

Resolves: #6, #8, #12, #23
Composes with: #19

The bug

spatial: lets you store the same fact in two slots. Array level today:

{
  "node_type": "array",
  "attributes": {
    "spatial:shape": [1024, 1024],
    "spatial:transform": [10.0, 0.0, 500000.0, 0.0, -10.0, 5000000.0],
    "spatial:bbox": [500000.0, 4990000.0, 510000.0, 5000000.0]
  }
}

For an affine transform, the bbox is fully determined by transform + shape (four-corner walk). Storing it again invites floating-point drift between the two copies. Each consumer picks its own tolerance and its own tiebreaker. Same store, different rectangles in different viewers.

The fix

One slot per fact:

  • Affine array: carry spatial:transform + spatial:shape. MUST NOT carry spatial:bbox (derivable).
  • Non-affine array (rpc, polynomial, lookup, custom): MUST carry spatial:bbox. No closed-form derivation exists.
  • Group: MAY carry spatial:bbox only. No per-array spatial: properties belong at the group level.

JSON Schema enforces all three rules directly. No tolerance arithmetic, no normative prose for validators to ignore.

The cost

Two example fixtures need a one-line edit. Both included in the draft PRs below. No deployed production producers identified so far; if you know one that emits the forbidden pattern, flag it.

The proof

Draft PRs, both ready to run:

Receipts

For prior art (STAC, OGC, GeoTIFF, CF), rejected alternatives, per-issue cross-references, and out-of-scope reasoning, see notes/single-source-rule-rationale.md in the spec PR.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions