@simtec-consult/field-location-contract
v0.2.0
Published
Shared JSON contract and validation for field QR provisioning and location ingest pings.
Downloads
263
Maintainers
Readme
@simtec-consult/field-location-contract
Single source of truth for QR provisioning JSON and location ping POST bodies: Zod schemas, schemaVersion literals, and parse* helpers. No HTTP, no frameworks.
Install
pnpm add @simtec-consult/field-location-contractNode: ESM-only, Node 18+.
Exports
| Export | Role |
|--------|------|
| PROVISIONING_SCHEMA_VERSION | 1 |
| PING_PAYLOAD_SCHEMA_VERSION | 2 |
| PingSettingsV1 | Provisioning shape after parse |
| LocationPingPayloadV2 | POST body shape after parse |
| parseProvisioningJson(input, options?) | { ok: true, settings } or { ok: false, error } |
| parseLocationPingJson(input) | { ok: true, payload } or { ok: false, error } |
| serializeProvisioning(settings) | Minified JSON string for QR |
| provisioningObjectSchema / locationPingObjectSchema | Zod schemas if you need refinements |
Rules
Provisioning (QR JSON)
schemaVersionmust be1.ingestUrlrequired, valid URL. HTTPS only unlessparseProvisioningJson(input, { allowHttp: true })(e.g. dev parity with mobile__DEV__).authTokenoptional non-empty string; when present, clients should sendAuthorization: Bearer <authToken>to the ingest endpoint.
Location ping (POST JSON)
schemaVersionmust be2.recordedAt: ISO 8601 string (must parse withDate.parse).latitude,longitude: finite numbers.accuracyMeters: finite number ornull.clientInstanceIdoptional: UUID string when present. Use a random UUID generated on first app launch and persisted locally — not IDFA/GAID. It can link this install to your backend; say so in app / store privacy text if required.
QR sample (minify before encoding)
{"schemaVersion":1,"ingestUrl":"https://api.example.com/api/field-pings","authToken":"your-shared-secret"}HTTP ingest (device → your API)
The path is app-defined (not fixed by this package). Typical integration:
| Item | Value |
|------|--------|
| Method | POST |
| Headers | Content-Type: application/json; optional Authorization: Bearer <token> if provisioning included authToken |
| Body | LocationPingPayloadV2 JSON |
| Success | 200 with body { "ok": true } (when using @simtec-consult/field-location-ingest) |
| Client errors | 400 invalid JSON/body; 401 when server requires Bearer and it is missing/wrong |
| Timeouts | Clients often use ~15s; keep handler fast or queue work |
Ping body example
{"schemaVersion":2,"recordedAt":"2026-04-11T12:00:00.000Z","latitude":51.5,"longitude":-0.12,"accuracyMeters":null,"clientInstanceId":"550e8400-e29b-41d4-a716-446655440000"}clientInstanceId may be omitted.
Versioning
- Bump JSON
schemaVersionwhen required fields or semantics change. - Bump npm semver when parser behaviour changes (e.g. stricter URL rules).
See CHANGELOG.md for release notes.
Security note
Today, anyone with the QR can replay ingestUrl + optional authToken. A future schemaVersion may use short-lived setup tokens instead; this package would add a new provisioning variant.
Compatibility matrix
| Mobile / client | Contract ping schemaVersion |
|-----------------|-------------------------------|
| (fill when you ship app versions) | 2 |
