Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions services/ontology/schemas/geometryEncoding.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://ontology.w3ds.metastate.foundation/schemas/504cacb9-79ef-498c-a352-e17830ed1876",
"schemaId": "504cacb9-79ef-498c-a352-e17830ed1876",
"title": "GeometryEncoding",
"domain": "governance",
"type": "object",
"description": "How a geometry is written down, as opposed to what it means. GeoJSON is the canonical model in this ecosystem — FieldBoundary already uses it — and every other entry here is an ENCODING of that model, with its mapping stated. The permitted values are the `oneOf` list under `id`: this schema is the published list, not a copy of it, in the same way as Domain. Two rules that belong with the list rather than with any one shape. A reader may REFUSE an encoding it does not know; it must never REWRITE the declared value, because a record then decodes as something it never claimed to be. And a reader that meets an unknown encoding while `pointCount` is greater than zero must say so — 'geometry in encoding X, not supported' — and must never render as if the geometry were empty, because an empty drawing is indistinguishable from an absent one.",
"properties": {
"id": {
"type": "string",
"description": "Stable encoding id, used in the `format` field of any shape that carries a geometry.",
"oneOf": [
{
"const": "geojson",
"title": "GeoJSON",
"description": "The canonical model, RFC 7946. Coordinates are [lon, lat] with an optional third element for elevation in metres, in WGS84. Lossless: the numbers stored are the numbers meant. Axis order is LONGITUDE FIRST."
},
{
"const": "polyline5",
"title": "Encoded Polyline, precision 5",
"description": "Google's Encoded Polyline Algorithm Format at 1e-5 precision, referenced rather than restated here. Maps to a GeoJSON LineString. AXIS ORDER IS LATITUDE FIRST, which is the opposite of GeoJSON, so a reader translates in one direction only and a confusion between the two is not a small error — it places a point in another hemisphere without failing. LOSSY: coordinates are rounded to five decimal places, about 1.1 m, so a decoded point must never be compared with its original for equality. Chosen by existing data rather than by design: imported health Workouts and Meshenger location tracks already hold it, and neither can be rewritten on vaults their platform does not own."
}
]
}
},
"required": ["id"],
"additionalProperties": false
}
78 changes: 78 additions & 0 deletions services/ontology/schemas/track.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://ontology.w3ds.metastate.foundation/schemas/dbddf08e-7a18-4c6f-b171-b5acc6b21b6f",
"schemaId": "dbddf08e-7a18-4c6f-b171-b5acc6b21b6f",
"title": "Track",
"domain": "mobility",
"type": "object",
"description": "The movement of ONE THING over time: a person walking, a parcel in transit, a vehicle, a shared live position. Deliberately says nothing about WHY the thing moved — a run, a commute and a delivery are the same geometry, and the meaning belongs to whatever record points at the track. That separation is the whole purpose: two platforms had independently written byte-identical route blocks inside differently-named envelopes (a health Workout and a messenger's location share), so no reader arriving at a vault could tell that one shape served both. A record that owns the geometry and is its only owner may embed this shape inline instead of referencing a Track envelope; see `route`.",
"properties": {
"id": { "type": "string", "description": "Envelope id." },
"subject": {
"type": "string",
"description": "The w3id of the THING that moved — a person, a parcel, a vehicle. Not necessarily an eName: a parcel's movement belongs to no account, and narrowing this to people is what forced the duplicate shapes in the first place."
},
"agent": {
"type": "string",
"description": "eName of whoever RECORDED the movement, when that is not the subject. A phone recording its owner, a carrier recording a parcel."
},
"startedAt": { "type": "string", "format": "date-time", "description": "When recording began." },
"endedAt": {
"type": "string",
"format": "date-time",
"description": "When recording finished. Absent while it is still being appended to. NOTE that this is about the RECORDING and not about any permission: if the track exists because somebody shared their position for a window of time, that window lives on the record that points here, not on the track, so that one fact has one home."
},
"route": {
"type": "object",
"description": "The geometry itself. `format` names an entry in GeometryEncoding; `pointCount` is REQUIRED and is what separates 'empty' from 'could not decode', which is the only defence a reader has when it meets an encoding it does not implement.",
"properties": {
"format": {
"type": "string",
"description": "An `id` from GeometryEncoding (504cacb9-79ef-498c-a352-e17830ed1876). Refuse one you do not know; never rewrite it."
},
"data": {
"type": "string",
"description": "The geometry, written in `format`. For geojson, the JSON text of a LineString; for polyline5, the encoded string."
},
"pointCount": {
"type": "integer",
"minimum": 0,
"description": "How many points the geometry holds. Required so that a reader which cannot decode `data` still knows whether there was anything to decode. Zero means genuinely empty."
}
},
"required": ["format", "data", "pointCount"],
"additionalProperties": false
},
"samples": {
"type": "object",
"description": "Per-point measurements, each array the SAME LENGTH as `pointCount` and in the same order. A samples array out of step with the geometry pairs one moment's speed with another place, silently, so a reader checks the lengths rather than trusting them. An absent array means not measured; a null entry means not measured at that point — never write zero or a default for an unknown, which would be indistinguishable from a real reading.",
"properties": {
"t": {
"type": "array",
"items": { "type": "number" },
"description": "Seconds since `startedAt` for each point."
},
"speed": {
"type": "array",
"items": { "type": ["number", "null"] },
"description": "Metres per second, as the device reported it."
},
"heading": {
"type": "array",
"items": { "type": ["number", "null"] },
"description": "Degrees true."
},
"ele": {
"type": "array",
"items": { "type": ["number", "null"] },
"description": "Metres above the WGS84 ellipsoid."
}
},
"additionalProperties": false
},
"createdAt": { "type": "string", "format": "date-time" },
"updatedAt": { "type": "string", "format": "date-time" }
},
"required": ["id", "subject", "startedAt", "route"],
"additionalProperties": true
}
Loading