@sierragridteam/sdk 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +49 -2
  2. package/dist/fixtures-data.d.ts +609 -0
  3. package/dist/fixtures-data.js +2676 -0
  4. package/dist/fixtures.d.ts +12 -0
  5. package/dist/fixtures.js +139 -0
  6. package/dist/generated/client/client.gen.d.ts +2 -0
  7. package/dist/generated/client/client.gen.js +216 -0
  8. package/dist/generated/client/index.d.ts +10 -0
  9. package/dist/generated/client/index.js +6 -0
  10. package/dist/generated/client/types.gen.d.ts +120 -0
  11. package/dist/generated/client/types.gen.js +2 -0
  12. package/dist/generated/client/utils.gen.d.ts +37 -0
  13. package/dist/generated/client/utils.gen.js +228 -0
  14. package/dist/generated/client.gen.d.ts +12 -0
  15. package/dist/generated/client.gen.js +3 -0
  16. package/dist/generated/core/auth.gen.d.ts +25 -0
  17. package/dist/generated/core/auth.gen.js +14 -0
  18. package/dist/generated/core/bodySerializer.gen.d.ts +25 -0
  19. package/dist/generated/core/bodySerializer.gen.js +57 -0
  20. package/dist/generated/core/params.gen.d.ts +43 -0
  21. package/dist/generated/core/params.gen.js +109 -0
  22. package/dist/generated/core/pathSerializer.gen.d.ts +33 -0
  23. package/dist/generated/core/pathSerializer.gen.js +106 -0
  24. package/dist/generated/core/queryKeySerializer.gen.d.ts +18 -0
  25. package/dist/generated/core/queryKeySerializer.gen.js +92 -0
  26. package/dist/generated/core/serverSentEvents.gen.d.ts +71 -0
  27. package/dist/generated/core/serverSentEvents.gen.js +132 -0
  28. package/dist/generated/core/types.gen.d.ts +83 -0
  29. package/dist/generated/core/types.gen.js +2 -0
  30. package/dist/generated/core/utils.gen.d.ts +19 -0
  31. package/dist/generated/core/utils.gen.js +87 -0
  32. package/dist/generated/index.d.ts +2 -0
  33. package/dist/generated/index.js +2 -0
  34. package/dist/generated/sdk.gen.d.ts +210 -0
  35. package/dist/generated/sdk.gen.js +336 -0
  36. package/dist/generated/types.gen.d.ts +3474 -0
  37. package/dist/generated/types.gen.js +2 -0
  38. package/dist/generated/zod.gen.d.ts +6537 -0
  39. package/dist/generated/zod.gen.js +1849 -0
  40. package/dist/index.d.ts +1287 -0
  41. package/dist/index.js +99 -0
  42. package/package.json +42 -4
@@ -0,0 +1,1849 @@
1
+ // This file is auto-generated by @hey-api/openapi-ts
2
+ import * as z from 'zod';
3
+ export const zBurnLineReading = z.object({
4
+ cleaned_transcription: z.string().optional(),
5
+ confidence: z.int().gte(0).lte(100).optional(),
6
+ line_id: z.string(),
7
+ message: z.string().optional(),
8
+ observed_at: z.iso.datetime(),
9
+ status: z.enum([
10
+ 'green',
11
+ 'red',
12
+ 'orange'
13
+ ])
14
+ });
15
+ /**
16
+ * `burn.line` (schema_version 1): readings of the county burn-day phone
17
+ * recordings, sent as ONE batched report per run (the per-reporter rate
18
+ * limit would 429 a second push). Each reading is staged durably.
19
+ *
20
+ */
21
+ export const zBurnLineReport = z.object({
22
+ generated_at: z.iso.datetime().optional(),
23
+ readings: z.array(zBurnLineReading).min(1).max(1000),
24
+ schema_version: z.literal(1)
25
+ });
26
+ /**
27
+ * The 202 body. Validated and queued, not yet stored; it lands on the next ingest cycle (about a minute).
28
+ */
29
+ export const zIngestAccepted = z.object({
30
+ accepted: z.int(),
31
+ receivedAt: z.iso.datetime(),
32
+ reporterId: z.string(),
33
+ stream: z.string(),
34
+ warnings: z.array(z.string()).optional()
35
+ });
36
+ /**
37
+ * A JSON-RPC 2.0 request. Omit `id` for a notification (answered 202, no body).
38
+ */
39
+ export const zJsonRpcRequest = z.object({
40
+ id: z.unknown().optional(),
41
+ jsonrpc: z.enum(['2.0']),
42
+ method: z.enum([
43
+ 'initialize',
44
+ 'ping',
45
+ 'tools/list',
46
+ 'tools/call',
47
+ 'resources/list',
48
+ 'resources/read',
49
+ 'prompts/list',
50
+ 'prompts/get',
51
+ 'notifications/initialized'
52
+ ]),
53
+ params: z.record(z.string(), z.unknown()).optional()
54
+ });
55
+ export const zJsonRpcResponse = z.object({
56
+ error: z.object({
57
+ code: z.int(),
58
+ message: z.string()
59
+ }).optional(),
60
+ id: z.unknown().optional(),
61
+ jsonrpc: z.enum(['2.0']),
62
+ result: z.record(z.string(), z.unknown()).optional()
63
+ });
64
+ /**
65
+ * camera block - a Caltrans CCTV camera, same data as GET /api/v1/cameras?place=. Load the image and stream directly from Caltrans; they are not proxied.
66
+ */
67
+ export const zMapCameraProps = z.object({
68
+ county: z.string().optional(),
69
+ direction: z.string().optional(),
70
+ distanceMeters: z.int(),
71
+ elevationFeet: z.int().optional(),
72
+ imageRefreshMinutes: z.int().optional(),
73
+ imageUrl: z.string(),
74
+ route: z.string().optional(),
75
+ streamUrl: z.string().optional()
76
+ });
77
+ /**
78
+ * chain_control block. Severity follows the level (R1 MINOR, R2 MODERATE, R3 SEVERE); a seasonal pass closure (`category` closed) is MINOR.
79
+ */
80
+ export const zMapChainControlProps = z.object({
81
+ direction: z.string().optional(),
82
+ highway: z.string().optional(),
83
+ level: z.enum([
84
+ 'R1',
85
+ 'R2',
86
+ 'R3'
87
+ ]).optional()
88
+ });
89
+ /**
90
+ * Set on Caltrans planned lane closures (category `closure`) only. One
91
+ * feature per work window. `plannedEnd` is an estimate crews overrun: an
92
+ * ACTIVE closure past it is still on the road until Caltrans records it
93
+ * picked up.
94
+ *
95
+ */
96
+ export const zMapClosureProps = z.object({
97
+ closureType: z.string().optional(),
98
+ estimatedDelayMinutes: z.int().optional(),
99
+ lanesClosed: z.string().optional(),
100
+ plannedEnd: z.iso.datetime().optional(),
101
+ plannedStart: z.iso.datetime().optional(),
102
+ setUpAt: z.iso.datetime().optional(),
103
+ totalLanes: z.int().optional(),
104
+ windowId: z.string(),
105
+ workType: z.string().optional()
106
+ });
107
+ /**
108
+ * earthquake block (USGS).
109
+ */
110
+ export const zMapEarthquakeProps = z.object({
111
+ depthKm: z.number(),
112
+ felt: z.int().optional(),
113
+ magnitude: z.number()
114
+ });
115
+ /**
116
+ * evacuation block (Cal OES / Genasys zones). Life-safety; reference only, link `source.url`.
117
+ */
118
+ export const zMapEvacuationProps = z.object({
119
+ county: z.string().optional(),
120
+ eventType: z.string().optional(),
121
+ level: z.enum([
122
+ 'ORDER',
123
+ 'WARNING',
124
+ 'ADVISORY',
125
+ 'SHELTER_IN_PLACE'
126
+ ]),
127
+ zoneId: z.string().optional()
128
+ });
129
+ /**
130
+ * The upstream feed this feature came from. Render `attribution` with the feature.
131
+ */
132
+ export const zMapFeatureSource = z.object({
133
+ attribution: z.string().optional(),
134
+ fetchedAt: z.iso.datetime().optional(),
135
+ id: z.string(),
136
+ name: z.string(),
137
+ url: z.string().optional()
138
+ });
139
+ /**
140
+ * fire_weather block. The region banner (id `fw:region`, null geometry)
141
+ * carries the ISSUED `state`; only NWS products set it (Fire Weather Watch
142
+ * -> elevated, Red Flag Warning -> red-flag). Forecast points (id
143
+ * `fw:forecast:<location>`) carry `forecast` instead, are always INFO and
144
+ * never imply a warning.
145
+ *
146
+ */
147
+ export const zMapFireWeatherProps = z.object({
148
+ forecast: z.object({
149
+ horizonHours: z.int().optional(),
150
+ issuedAt: z.iso.datetime().optional(),
151
+ minHumidityPercent: z.int().optional(),
152
+ peakWindGustAt: z.iso.datetime().optional(),
153
+ peakWindGustKmh: z.int().optional(),
154
+ source: z.string().optional()
155
+ }).optional(),
156
+ sourceEvent: z.string().optional(),
157
+ state: z.enum([
158
+ 'normal',
159
+ 'elevated',
160
+ 'red-flag'
161
+ ]).optional(),
162
+ zones: z.array(z.string()).optional()
163
+ });
164
+ /**
165
+ * An RFC 7946 geometry, or `null` for a feature with no location (NWS zone
166
+ * alerts and the fire-weather region banner): render those as a banner
167
+ * or list row, not a shape.
168
+ *
169
+ * A position is `[longitude, latitude]`, longitude FIRST (RFC 7946
170
+ * §3.1.1), the reverse of the `{lat, lng}` objects on the JSON RPCs.
171
+ * Store-derived positions are trimmed to 5 decimals (~1 m).
172
+ *
173
+ * Which types appear: Point (most layers: incidents, signs, cameras,
174
+ * chain controls, quakes, mesh nodes, forecast points, unmapped fires);
175
+ * LineString (road_segment routes, mesh_link edges); Polygon or
176
+ * MultiPolygon (power outage areas, evacuation zones, fire perimeters).
177
+ * Geometry passed through from an upstream ArcGIS feed may be any RFC 7946
178
+ * type except GeometryCollection.
179
+ *
180
+ */
181
+ export const zMapGeometry = z.object({
182
+ coordinates: z.array(z.unknown()),
183
+ type: z.enum([
184
+ 'Point',
185
+ 'MultiPoint',
186
+ 'LineString',
187
+ 'MultiLineString',
188
+ 'Polygon',
189
+ 'MultiPolygon'
190
+ ])
191
+ }).nullable();
192
+ /**
193
+ * An RFC 7946 geometry object, the same shape as a map feature's
194
+ * `geometry` (MapGeometry) but never `null`: an event's or place's
195
+ * `geometry.object` when the request passes `geometryFormat=OBJECT`.
196
+ * A position is `[longitude, latitude]`, longitude first.
197
+ *
198
+ */
199
+ export const zGeoJsonGeometry = zMapGeometry;
200
+ /**
201
+ * road_incident block.
202
+ */
203
+ export const zMapIncidentProps = z.object({
204
+ closure: zMapClosureProps.optional(),
205
+ logNumber: z.string().optional()
206
+ });
207
+ /**
208
+ * Provenance and freshness of the whole layer.
209
+ */
210
+ export const zMapLayerMetadata = z.object({
211
+ area: z.string(),
212
+ attribution: z.string().optional(),
213
+ generatedAt: z.iso.datetime(),
214
+ lastSourceUpdate: z.iso.datetime().optional(),
215
+ layer: z.enum([
216
+ 'road_incident',
217
+ 'chain_control',
218
+ 'road_segment',
219
+ 'message_sign',
220
+ 'weather_alert',
221
+ 'fire_weather',
222
+ 'earthquake',
223
+ 'wildfire',
224
+ 'evacuation',
225
+ 'power',
226
+ 'mesh_node',
227
+ 'mesh_link',
228
+ 'camera'
229
+ ]),
230
+ schemaVersion: z.literal(1),
231
+ sourceStatus: z.enum([
232
+ 'OK',
233
+ 'STALE',
234
+ 'UNAVAILABLE'
235
+ ]),
236
+ sourceUrl: z.string().optional()
237
+ });
238
+ /**
239
+ * The last sample an operator monitor read off the node itself. Gauges the device did not report are absent, never 0.
240
+ */
241
+ export const zMapMeshAdminProps = z.object({
242
+ airtimeMs: z.int().optional(),
243
+ batteryPercent: z.number().optional(),
244
+ batteryPercentSource: z.string().optional(),
245
+ batteryVolts: z.number().optional(),
246
+ lastSuccessAt: z.iso.datetime().optional(),
247
+ noiseFloorDbm: z.int().optional(),
248
+ packetsReceived: z.int().optional(),
249
+ packetsSent: z.int().optional(),
250
+ recvErrors: z.int().optional(),
251
+ reportedAt: z.iso.datetime().optional(),
252
+ reporterId: z.string(),
253
+ rxAirtimeMs: z.int().optional(),
254
+ temperatureC: z.number().optional(),
255
+ txQueueLen: z.int().optional(),
256
+ uptimeSeconds: z.int().optional()
257
+ });
258
+ /**
259
+ * mesh_link edge block - one undirected relay link between two located nodes. Weight by `daysActive`/`observations`, fade by `lastSeen`.
260
+ */
261
+ export const zMapMeshLinkProps = z.object({
262
+ a: z.string(),
263
+ b: z.string(),
264
+ bestSnr: z.number().optional(),
265
+ daysActive: z.int(),
266
+ firstSeen: z.iso.datetime().optional(),
267
+ lastSeen: z.iso.datetime().optional(),
268
+ observations: z.int()
269
+ });
270
+ /**
271
+ * mesh_node block (MeshCore node presence; also on the MESH_NODE points of
272
+ * the mesh_link layer). Signal readings are absent when no bridge heard the
273
+ * node; a present 0 is a reading. A node's freshness is the later of
274
+ * `lastHeardAt` and `lastRelayedAt`, never the feature's `updatedAt`.
275
+ *
276
+ */
277
+ export const zMapMeshProps = z.object({
278
+ admin: zMapMeshAdminProps.optional(),
279
+ gateways: z.array(z.string()).optional(),
280
+ hopCount: z.int().optional(),
281
+ inRegion: z.boolean().optional(),
282
+ lastHeardAt: z.iso.datetime().optional(),
283
+ lastRelayedAt: z.iso.datetime().optional(),
284
+ name: z.string().optional(),
285
+ nodeType: z.enum([
286
+ 'companion',
287
+ 'repeater',
288
+ 'room_server',
289
+ 'sensor'
290
+ ]).optional(),
291
+ publicKey: z.string(),
292
+ reachability: z.enum(['REACHABLE', 'UNREACHABLE']).optional(),
293
+ rssi: z.int().optional(),
294
+ snr: z.number().optional()
295
+ });
296
+ /**
297
+ * message_sign block - what a Caltrans changeable message sign is showing, verbatim. Context, not a hazard.
298
+ */
299
+ export const zMapMessageSignProps = z.object({
300
+ direction: z.string().optional(),
301
+ district: z.int(),
302
+ inService: z.boolean(),
303
+ pages: z.array(z.tuple([
304
+ z.string(),
305
+ z.string(),
306
+ z.string()
307
+ ])).optional(),
308
+ route: z.string().optional(),
309
+ signId: z.string()
310
+ });
311
+ /**
312
+ * power block, both PG&E feeds. `category` unplanned|planned sets the
313
+ * outage fields; `psps` (Public Safety Power Shutoff) sets the PSPS fields.
314
+ * `estimatedRestoration`, `deEnergizationEnd` and `allClear` are PG&E
315
+ * ESTIMATES that are routinely overrun; label them as estimates.
316
+ *
317
+ */
318
+ export const zMapPowerProps = z.object({
319
+ allClear: z.iso.datetime().optional(),
320
+ cause: z.string().optional(),
321
+ crewStatus: z.string().optional(),
322
+ customersAffected: z.int().optional(),
323
+ deEnergizationEnd: z.iso.datetime().optional(),
324
+ deEnergizationStart: z.iso.datetime().optional(),
325
+ estimatedRestoration: z.iso.datetime().optional(),
326
+ eventName: z.string().optional(),
327
+ medicalBaselineAffected: z.int().optional(),
328
+ outageId: z.string().optional(),
329
+ stage: z.enum(['Watch', 'Warning']).optional()
330
+ });
331
+ /**
332
+ * road_segment block (Google Routes travel time over a configured route). The numbers are absent, not 0, until the route has been measured.
333
+ */
334
+ export const zMapRoadProps = z.object({
335
+ congestion: z.enum([
336
+ 'CLEAR',
337
+ 'LIGHT',
338
+ 'MODERATE',
339
+ 'HEAVY',
340
+ 'SEVERE',
341
+ 'UNSPECIFIED'
342
+ ]).optional(),
343
+ delayMinutes: z.int().optional(),
344
+ distanceKm: z.int().optional(),
345
+ durationMinutes: z.int().optional(),
346
+ roadId: z.string()
347
+ });
348
+ /**
349
+ * weather_alert block. The NWS CAP fields are verbatim; `nwsSeverity` is NWS's own scale, distinct from the unified `severity`.
350
+ */
351
+ export const zMapWeatherProps = z.object({
352
+ certainty: z.string().optional(),
353
+ event: z.string().optional(),
354
+ instruction: z.string().optional(),
355
+ nwsSeverity: z.enum([
356
+ 'Extreme',
357
+ 'Severe',
358
+ 'Moderate',
359
+ 'Minor',
360
+ 'Unknown'
361
+ ]).optional(),
362
+ source: z.enum(['NWS']).optional(),
363
+ urgency: z.string().optional(),
364
+ zones: z.array(z.string()).optional()
365
+ });
366
+ /**
367
+ * wildfire block (CAL FIRE incidents and FIRIS perimeters).
368
+ */
369
+ export const zMapWildfireProps = z.object({
370
+ acres: z.number().optional(),
371
+ cause: z.string().optional(),
372
+ containment: z.int().gte(0).lte(100),
373
+ county: z.string().optional(),
374
+ hasPerimeter: z.boolean()
375
+ });
376
+ /**
377
+ * The envelope shared by every feature of every layer, plus exactly one
378
+ * per-kind block named after the layer (`incident`, `road`,
379
+ * `chainControl`, `messageSign`, `weather`, `fireWeather`, `earthquake`,
380
+ * `wildfire`, `evacuation`, `power`, `mesh`, `meshLink`, `camera`).
381
+ * Optional members are omitted, never `""` or `0`, when they have no value.
382
+ *
383
+ */
384
+ export const zMapFeatureProperties = z.object({
385
+ areaLabel: z.string().optional(),
386
+ camera: zMapCameraProps.optional(),
387
+ category: z.string().optional(),
388
+ chainControl: zMapChainControlProps.optional(),
389
+ description: z.string().optional(),
390
+ earthquake: zMapEarthquakeProps.optional(),
391
+ effective: z.iso.datetime().optional(),
392
+ evacuation: zMapEvacuationProps.optional(),
393
+ expires: z.iso.datetime().optional(),
394
+ fireWeather: zMapFireWeatherProps.optional(),
395
+ headline: z.string(),
396
+ id: z.string(),
397
+ incident: zMapIncidentProps.optional(),
398
+ kind: z.enum([
399
+ 'Road incident',
400
+ 'Chain control',
401
+ 'Road segment',
402
+ 'Message sign',
403
+ 'Weather alert',
404
+ 'Fire weather',
405
+ 'Fire-weather forecast',
406
+ 'Earthquake',
407
+ 'Wildfire',
408
+ 'Evacuation',
409
+ 'Power outage',
410
+ 'Public Safety Power Shutoff',
411
+ 'Mesh node',
412
+ 'Relay link',
413
+ 'Traffic camera'
414
+ ]),
415
+ layer: z.enum([
416
+ 'ROAD_INCIDENT',
417
+ 'CHAIN_CONTROL',
418
+ 'ROAD_SEGMENT',
419
+ 'MESSAGE_SIGN',
420
+ 'WEATHER_ALERT',
421
+ 'FIRE_WEATHER',
422
+ 'EARTHQUAKE',
423
+ 'WILDFIRE',
424
+ 'EVACUATION',
425
+ 'POWER',
426
+ 'MESH_NODE',
427
+ 'MESH_LINK',
428
+ 'CAMERA'
429
+ ]),
430
+ mesh: zMapMeshProps.optional(),
431
+ meshLink: zMapMeshLinkProps.optional(),
432
+ messageSign: zMapMessageSignProps.optional(),
433
+ power: zMapPowerProps.optional(),
434
+ road: zMapRoadProps.optional(),
435
+ severity: z.enum([
436
+ 'INFO',
437
+ 'MINOR',
438
+ 'MODERATE',
439
+ 'SEVERE',
440
+ 'EXTREME'
441
+ ]),
442
+ severityRank: z.int().gte(0).lte(4),
443
+ source: zMapFeatureSource,
444
+ status: z.enum([
445
+ 'ACTIVE',
446
+ 'SCHEDULED',
447
+ 'ORDER',
448
+ 'WARNING',
449
+ 'ADVISORY',
450
+ 'SHELTER_IN_PLACE',
451
+ 'OPEN',
452
+ 'CLOSED',
453
+ 'RESTRICTED',
454
+ 'MAINTENANCE',
455
+ 'UNSPECIFIED'
456
+ ]).optional(),
457
+ summary: z.string().optional(),
458
+ summaryEnhanced: z.object({
459
+ enhancedAt: z.iso.datetime().optional()
460
+ }).optional(),
461
+ updatedAt: z.iso.datetime().optional(),
462
+ weather: zMapWeatherProps.optional(),
463
+ wildfire: zMapWildfireProps.optional()
464
+ });
465
+ /**
466
+ * An RFC 7946 Feature.
467
+ */
468
+ export const zMapFeature = z.object({
469
+ geometry: zMapGeometry,
470
+ properties: zMapFeatureProperties,
471
+ type: z.enum(['Feature'])
472
+ });
473
+ /**
474
+ * An RFC 7946 FeatureCollection for one place and one layer. `metadata` is
475
+ * an RFC 7946 §6.1 foreign member that map libraries ignore; read it for
476
+ * source health and attribution before drawing.
477
+ *
478
+ */
479
+ export const zMapFeatureCollection = z.object({
480
+ features: z.array(zMapFeature),
481
+ metadata: zMapLayerMetadata,
482
+ type: z.enum(['FeatureCollection'])
483
+ });
484
+ /**
485
+ * One undirected relay link. Every member is always present.
486
+ */
487
+ export const zMeshLink = z.object({
488
+ a: z.string(),
489
+ b: z.string(),
490
+ bestSnr: z.number(),
491
+ daysActive: z.int(),
492
+ firstSeen: z.iso.datetime(),
493
+ lastSeen: z.iso.datetime(),
494
+ observations: z.int()
495
+ });
496
+ export const zMeshLinkList = z.object({
497
+ generatedAt: z.iso.datetime(),
498
+ links: z.array(zMeshLink),
499
+ window: z.string()
500
+ });
501
+ /**
502
+ * One reception. Extra bridge fields are accepted and ignored.
503
+ */
504
+ export const zMeshPacket = z.object({
505
+ RSSI: z.unknown().optional(),
506
+ SNR: z.unknown().optional(),
507
+ origin_id: z.string().optional(),
508
+ packet_type: z.int(),
509
+ raw: z.string(),
510
+ timestamp: z.string().optional()
511
+ });
512
+ /**
513
+ * `mesh.packet` (schema_version 1): raw MeshCore frames a companion radio
514
+ * heard, in the per-packet envelope the MQTT bridges publish. ADVERTs
515
+ * (packet_type 4) update a node after its Ed25519 signature verifies;
516
+ * other flood-routed packets credit relays. Answers 400 when MeshCore
517
+ * ingest is off on the server.
518
+ *
519
+ */
520
+ export const zMeshPacketReport = z.object({
521
+ generated_at: z.iso.datetime().optional(),
522
+ observer: z.string().regex(/^[0-9a-fA-F]{8,64}$/).optional(),
523
+ packets: z.array(zMeshPacket).max(1000),
524
+ schema_version: z.literal(1)
525
+ });
526
+ export const zMeshRepeaterReading = z.object({
527
+ airtime_ms: z.int().nullish(),
528
+ battery_percent: z.number().nullish(),
529
+ battery_percent_source: z.string().optional(),
530
+ battery_voltage: z.number().nullish(),
531
+ direct_dups: z.int().nullish(),
532
+ flood_dups: z.int().nullish(),
533
+ full_evts: z.int().nullish(),
534
+ humidity: z.number().nullish(),
535
+ id: z.string().regex(/^[0-9a-fA-F]{8,64}$/),
536
+ last_attempt: z.int().nullish(),
537
+ last_rssi_dbm: z.int().nullish(),
538
+ last_snr_db: z.number().nullish(),
539
+ last_success: z.int().nullish(),
540
+ name: z.string().optional(),
541
+ nb_recv: z.int().nullish(),
542
+ nb_sent: z.int().nullish(),
543
+ noise_floor_dbm: z.int().nullish(),
544
+ online: z.boolean().nullish(),
545
+ pressure: z.number().nullish(),
546
+ recv_direct: z.int().nullish(),
547
+ recv_errors: z.int().nullish(),
548
+ recv_flood: z.int().nullish(),
549
+ rx_airtime_ms: z.int().nullish(),
550
+ sent_direct: z.int().nullish(),
551
+ sent_flood: z.int().nullish(),
552
+ temperature_c: z.number().nullish(),
553
+ tx_queue_len: z.int().nullish(),
554
+ uptime_s: z.int().nullish()
555
+ });
556
+ /**
557
+ * `mesh.repeater` (schema_version 1): an operator monitor's COMPLETE
558
+ * current set of MeshCore repeaters it logged into. A report replaces the
559
+ * reporter's previous set; a node left out is no longer monitored. Request
560
+ * bodies are snake_case. Unknown fields are ignored. Unread values are
561
+ * `null`, never `0`.
562
+ *
563
+ */
564
+ export const zMeshRepeaterReport = z.object({
565
+ generated_at: z.iso.datetime().optional(),
566
+ repeaters: z.array(zMeshRepeaterReading).max(1000),
567
+ schema_version: z.literal(1)
568
+ });
569
+ export const zProtobufAny = z.object({
570
+ '@type': z.string().optional()
571
+ });
572
+ /**
573
+ * The error body of every JSON route: the RPCs (gRPC-Gateway rendering of
574
+ * google.rpc.Status) and the hand-built GeoJSON, mesh-links and ingest
575
+ * routes alike. Served with the HTTP status mapped from `code`
576
+ * (3 INVALID_ARGUMENT -> 400, 5 NOT_FOUND -> 404, 13 INTERNAL -> 500,
577
+ * 14 UNAVAILABLE -> 503, ...). All four members are always present.
578
+ *
579
+ */
580
+ export const zRpcStatus = z.object({
581
+ code: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }).optional(),
582
+ codeName: z.enum([
583
+ 'OK',
584
+ 'CANCELLED',
585
+ 'UNKNOWN',
586
+ 'INVALID_ARGUMENT',
587
+ 'DEADLINE_EXCEEDED',
588
+ 'NOT_FOUND',
589
+ 'ALREADY_EXISTS',
590
+ 'PERMISSION_DENIED',
591
+ 'RESOURCE_EXHAUSTED',
592
+ 'FAILED_PRECONDITION',
593
+ 'ABORTED',
594
+ 'OUT_OF_RANGE',
595
+ 'UNIMPLEMENTED',
596
+ 'INTERNAL',
597
+ 'UNAVAILABLE',
598
+ 'DATA_LOSS',
599
+ 'UNAUTHENTICATED'
600
+ ]).optional(),
601
+ details: z.array(zProtobufAny).optional(),
602
+ message: z.string().optional()
603
+ });
604
+ /**
605
+ * BoundingBox is a WGS 84 bounding box in decimal degrees.
606
+ */
607
+ export const zV1BoundingBox = z.object({
608
+ maxLat: z.number(),
609
+ maxLng: z.number(),
610
+ minLat: z.number(),
611
+ minLng: z.number()
612
+ });
613
+ /**
614
+ * BurnDay is the county air district's call for today.
615
+ *
616
+ * - BURN_DAY_UNKNOWN: Not read, unreadable, or older than 36 hours. Never treat as permissive.
617
+ * - BURN_DAY_YES: Permissive burn day: burning allowed (subject to CAL FIRE's status).
618
+ * - BURN_DAY_NO: No-burn day: burning prohibited.
619
+ * - BURN_DAY_MARGINAL: Restricted or partial day (for example elevation limits). Treated as a
620
+ * restriction, not a yes.
621
+ */
622
+ export const zV1BurnDay = z.enum([
623
+ 'BURN_DAY_UNKNOWN',
624
+ 'BURN_DAY_YES',
625
+ 'BURN_DAY_NO',
626
+ 'BURN_DAY_MARGINAL'
627
+ ]).default('BURN_DAY_UNKNOWN');
628
+ /**
629
+ * BurnObservation is the latest reading of one burn line. The line's message
630
+ * names the date, so it changes every day even when the answer does not; that
631
+ * is why it writes no revision.
632
+ *
633
+ */
634
+ export const zV1BurnObservation = z.object({
635
+ confidence: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
636
+ message: z.string(),
637
+ observedAt: z.iso.datetime(),
638
+ transcript: z.string()
639
+ });
640
+ /**
641
+ * BurnLineReading is one recorded phone line's answer for today.
642
+ */
643
+ export const zV1BurnLineReading = z.object({
644
+ burnDay: zV1BurnDay,
645
+ id: z.string(),
646
+ name: z.string(),
647
+ observation: zV1BurnObservation.nullable(),
648
+ phone: z.string()
649
+ });
650
+ /**
651
+ * BurnPermission is the combined answer, deliberately pessimistic.
652
+ *
653
+ * - BURN_PERMISSION_UNKNOWN: At least one facet is unknown or stale and none prohibits: assume nothing.
654
+ * - BURN_PERMISSION_ALLOWED: Both facets are known and permit burning today.
655
+ * - BURN_PERMISSION_PROHIBITED: At least one facet prohibits burning today.
656
+ */
657
+ export const zV1BurnPermission = z.enum([
658
+ 'BURN_PERMISSION_UNKNOWN',
659
+ 'BURN_PERMISSION_ALLOWED',
660
+ 'BURN_PERMISSION_PROHIBITED'
661
+ ]).default('BURN_PERMISSION_UNKNOWN');
662
+ /**
663
+ * CalfireBurnStatus is CAL FIRE's permit status for State Responsibility Area
664
+ * land in the county.
665
+ *
666
+ * - CALFIRE_BURN_STATUS_UNKNOWN: Unknown: CAL FIRE's page has not been read.
667
+ * - CALFIRE_BURNING_SUSPENDED: Permits suspended: no residential burning.
668
+ * - CALFIRE_PERMIT_REQUIRED: Burning allowed with a valid CAL FIRE permit.
669
+ * - CALFIRE_NO_PERMIT_REQUIRED: Off-season: no permit needed.
670
+ */
671
+ export const zV1CalfireBurnStatus = z.enum([
672
+ 'CALFIRE_BURN_STATUS_UNKNOWN',
673
+ 'CALFIRE_BURNING_SUSPENDED',
674
+ 'CALFIRE_PERMIT_REQUIRED',
675
+ 'CALFIRE_NO_PERMIT_REQUIRED'
676
+ ]).default('CALFIRE_BURN_STATUS_UNKNOWN');
677
+ /**
678
+ * BurnStatusDetail is the BURN_STATUS detail block: whether residential/outdoor
679
+ * burning is allowed today in one county.
680
+ *
681
+ * Two independent authorities must BOTH permit a burn, and each is a separate
682
+ * facet because they fail independently: `burnDay`, the county air district's
683
+ * daily permissive-burn-day call (read from its recorded phone line), and
684
+ * `calfireStatus`, CAL FIRE's seasonal suspension of burn permits on State
685
+ * Responsibility Area land (changes about twice a year). `permission` combines
686
+ * them pessimistically.
687
+ *
688
+ * The event exists for each tracked county at all times, is always INFO and
689
+ * ACTIVE, and is left out of the summary's hazard rollup (it has its own `burn`
690
+ * domain). `GET /api/v1/events/burn:{county slug}/history` shows when it changed.
691
+ */
692
+ export const zV1BurnStatusDetail = z.object({
693
+ burnDay: zV1BurnDay,
694
+ burnLines: z.array(zV1BurnLineReading),
695
+ calfireArea: z.string(),
696
+ calfireEffective: z.iso.datetime().nullable(),
697
+ calfireObservedAt: z.iso.datetime().nullable(),
698
+ calfireStatus: zV1CalfireBurnStatus,
699
+ permission: zV1BurnPermission
700
+ });
701
+ /**
702
+ * EarthquakeDetail is the EARTHQUAKE detail block. The USGS event page is the
703
+ * envelope `canonicalUrl`.
704
+ */
705
+ export const zV1EarthquakeDetail = z.object({
706
+ depthKm: z.number(),
707
+ felt: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
708
+ magnitude: z.number()
709
+ });
710
+ /**
711
+ * Enhancement marks AI-generated text so a client can badge it. The model
712
+ * translates and summarizes the upstream text; it never asserts new facts, and
713
+ * the original stays in `description`.
714
+ */
715
+ export const zV1Enhancement = z.object({
716
+ enhancedAt: z.iso.datetime().nullable(),
717
+ fields: z.array(z.string()),
718
+ model: z.string(),
719
+ request: z.string(),
720
+ response: z.string()
721
+ });
722
+ /**
723
+ * EvacuationDetail is the EVACUATION detail block, one Cal OES / Genasys zone.
724
+ */
725
+ export const zV1EvacuationDetail = z.object({
726
+ county: z.string(),
727
+ eventType: z.string(),
728
+ level: z.enum([
729
+ 'ORDER',
730
+ 'WARNING',
731
+ 'ADVISORY',
732
+ 'SHELTER_IN_PLACE'
733
+ ]),
734
+ zoneId: z.string()
735
+ });
736
+ /**
737
+ * EventStatus is an event's lifecycle state. Every transition is a revision, so
738
+ * the history keeps when an event started and ended.
739
+ *
740
+ * - EVENT_STATUS_UNSPECIFIED: Never returned.
741
+ * - SCHEDULED: Planned or forecast and not yet in effect, e.g. a Caltrans lane-closure
742
+ * window the crew has not set up yet.
743
+ * - ACTIVE: In effect now.
744
+ * - RESOLVED: Over: an authoritatively active-only feed (CAL FIRE, Cal OES, CHP, Caltrans,
745
+ * PG&E) stopped listing it after a successful poll, or a closure passed its
746
+ * planned end plus an overrun grace without a pickup call.
747
+ * - EXPIRED: Aged out: past its own `expires`, or unseen for longer than the source's
748
+ * grace (`Source.expireAfterSeconds`). Used where a feed going quiet proves
749
+ * nothing (NWS alerts, FIRIS perimeters, mesh nodes).
750
+ */
751
+ export const zV1EventStatus = z.enum([
752
+ 'EVENT_STATUS_UNSPECIFIED',
753
+ 'SCHEDULED',
754
+ 'ACTIVE',
755
+ 'RESOLVED',
756
+ 'EXPIRED'
757
+ ]).default('EVENT_STATUS_UNSPECIFIED');
758
+ /**
759
+ * FireWeatherConditions is the region's fire-weather state, from issued NWS
760
+ * products only. It never claims a Red Flag Warning that NWS has not issued.
761
+ */
762
+ export const zV1FireWeatherConditions = z.object({
763
+ headline: z.string(),
764
+ state: z.enum([
765
+ 'normal',
766
+ 'elevated',
767
+ 'red-flag',
768
+ ''
769
+ ]),
770
+ zones: z.array(z.string())
771
+ });
772
+ /**
773
+ * FireWeatherDetail is never populated on an event. Fire weather is a condition,
774
+ * served by `GET /api/v1/conditions` (`fireWeather`) and the `fire_weather` map
775
+ * layer.
776
+ *
777
+ */
778
+ export const zV1FireWeatherDetail = z.object({
779
+ sourceEvent: z.string(),
780
+ state: z.enum([
781
+ 'normal',
782
+ 'elevated',
783
+ 'red-flag'
784
+ ]),
785
+ zones: z.array(z.string())
786
+ });
787
+ /**
788
+ * ForecastPeriod is one hour of a location's forecast (NWS gridpoint data),
789
+ * rounded to whole numbers. A value NWS did not give is 0.
790
+ */
791
+ export const zV1ForecastPeriod = z.object({
792
+ humidityPercent: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
793
+ temperatureCelsius: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
794
+ time: z.iso.datetime().nullable(),
795
+ windDirectionDegrees: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
796
+ windGustKmh: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
797
+ windSpeedKmh: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' })
798
+ });
799
+ /**
800
+ * LatLng is one WGS 84 point in decimal degrees. Note the order: unlike GeoJSON
801
+ * coordinates, this is latitude first.
802
+ */
803
+ export const zV1LatLng = z.object({
804
+ lat: z.number(),
805
+ lng: z.number()
806
+ });
807
+ /**
808
+ * Camera is one Caltrans CCTV camera. Every listed camera is in service and has
809
+ * an image; an out-of-service camera is dropped, not flagged.
810
+ */
811
+ export const zV1Camera = z.object({
812
+ county: z.string(),
813
+ description: z.string(),
814
+ direction: z.enum([
815
+ '',
816
+ 'North',
817
+ 'South',
818
+ 'East',
819
+ 'West'
820
+ ]),
821
+ distanceMeters: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
822
+ elevationFeet: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
823
+ id: z.string(),
824
+ imageRefreshMinutes: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
825
+ imageUrl: z.string(),
826
+ location: zV1LatLng,
827
+ name: z.string(),
828
+ nearbyPlace: z.string(),
829
+ route: z.string(),
830
+ streamUrl: z.string()
831
+ });
832
+ /**
833
+ * CameraList is the camera directory.
834
+ */
835
+ export const zV1CameraList = z.object({
836
+ attribution: z.string(),
837
+ cameras: z.array(zV1Camera),
838
+ lastSourceUpdate: z.iso.datetime().nullable(),
839
+ sourceStatus: z.enum([
840
+ 'OK',
841
+ 'STALE',
842
+ 'UNAVAILABLE'
843
+ ])
844
+ });
845
+ /**
846
+ * Geometry is an event's or place's footprint.
847
+ *
848
+ * The GeoJSON comes in one of two forms, chosen per request with
849
+ * `geometryFormat`: `BASE64` (the default and legacy form) fills `geojson`;
850
+ * `OBJECT` fills `object` and leaves `geojson` empty. `bbox` and `centroid`
851
+ * are the same in both.
852
+ */
853
+ export const zV1Geometry = z.object({
854
+ bbox: zV1BoundingBox,
855
+ centroid: zV1LatLng,
856
+ geojson: z.string(),
857
+ object: zGeoJsonGeometry.optional()
858
+ });
859
+ /**
860
+ * LaneClosureDetail is one Caltrans planned lane-closure WINDOW from the CWWP2
861
+ * data portal. Every field is Caltrans data; none of it is AI-generated.
862
+ *
863
+ * A multi-day job is one window (one event) per day, and neither `closureId`
864
+ * nor `logNumber` identifies a job; `windowId` is the only unique key. A window
865
+ * is SCHEDULED until the crew radios it set up (`setUpAt`), then ACTIVE until
866
+ * they radio it picked up, or until `plannedEnd` plus a 12-hour overrun grace
867
+ * passes with no pickup call, when it is presumed over and RESOLVED. The
868
+ * planned end is an estimate crews overrun, so it is never mapped onto the
869
+ * envelope `expires`.
870
+ */
871
+ export const zV1LaneClosureDetail = z.object({
872
+ begin: zV1LatLng.nullable(),
873
+ beginLocation: z.string(),
874
+ closureDuration: z.enum([
875
+ 'Standard',
876
+ 'Long Term',
877
+ 'Intermittent'
878
+ ]),
879
+ closureId: z.string(),
880
+ closureType: z.string(),
881
+ direction: z.string(),
882
+ district: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
883
+ end: zV1LatLng.nullable(),
884
+ endIndefinite: z.boolean(),
885
+ endLocation: z.string(),
886
+ estimatedDelayMinutes: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
887
+ facility: z.string(),
888
+ lanesClosed: z.string(),
889
+ logNumber: z.string(),
890
+ plannedEnd: z.iso.datetime().nullable(),
891
+ plannedStart: z.iso.datetime(),
892
+ route: z.string(),
893
+ setUpAt: z.iso.datetime().nullable(),
894
+ totalLanes: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
895
+ windowId: z.string(),
896
+ workType: z.string()
897
+ });
898
+ /**
899
+ * Layer is the event taxonomy. Response values are these UPPERCASE names; the
900
+ * `layer` query parameter also accepts lowercase slugs (`road_incident`).
901
+ *
902
+ * Only event layers appear here. The condition layers (`road_segment`,
903
+ * `chain_control`, `fire_weather`, `message_sign`) are map layers and summary
904
+ * inputs, never events.
905
+ *
906
+ * - LAYER_UNSPECIFIED: Never returned.
907
+ * - WILDFIRE: Wildfires: CAL FIRE incidents joined with FIRIS/NIFC perimeters (sources
908
+ * `calfire`, `firis`). Scoped wider than other layers, so a fire approaching
909
+ * the region shows up before it arrives.
910
+ * - EVACUATION: Evacuation zones under an order, warning, advisory or shelter-in-place,
911
+ * from Cal OES / Genasys (source `caloes`). Life-safety: see the summary's
912
+ * `activeEvacuations`.
913
+ * - WEATHER_ALERT: National Weather Service watches, warnings and advisories for the region's
914
+ * forecast zones (source `nws`). No geometry; attached to places by zone.
915
+ * - FIRE_WEATHER: Reserved. Fire weather is a condition (`GET /api/v1/conditions`), not an
916
+ * event layer; no event carries it.
917
+ * - EARTHQUAKE: USGS earthquakes of magnitude 2.5 or more in the last 7 days (source `usgs`).
918
+ * - ROAD_INCIDENT: CHP traffic incidents (source `chp`, AI-summarized) and Caltrans planned
919
+ * lane-closure windows (source `caltrans`). Planned windows not yet set up are
920
+ * SCHEDULED.
921
+ * - POWER:
922
+ * PG&E electric outages (source `pge`) and Public Safety Power Shutoffs
923
+ * (source `psps`). Most outages affect one customer and are INFO.
924
+ * - GAUGE: Reserved for stream gauges; no events today.
925
+ * - AIR_QUALITY: Reserved for air quality; no events today.
926
+ * - MESH: MeshCore community radio nodes (source `meshcore`), one event per node.
927
+ * Ambient INFO state, not a hazard. It dominates an unscoped event query.
928
+ * - ANNOUNCEMENT: Reserved for announcements; no events today.
929
+ * - BURN_STATUS: One event per tracked county saying whether residential burning is allowed
930
+ * today (sources `burnline`, `calfire-burn`). Ambient, permanently ACTIVE,
931
+ * always INFO; its revision history is the record of changes.
932
+ */
933
+ export const zV1Layer = z.enum([
934
+ 'LAYER_UNSPECIFIED',
935
+ 'WILDFIRE',
936
+ 'EVACUATION',
937
+ 'WEATHER_ALERT',
938
+ 'FIRE_WEATHER',
939
+ 'EARTHQUAKE',
940
+ 'ROAD_INCIDENT',
941
+ 'POWER',
942
+ 'GAUGE',
943
+ 'AIR_QUALITY',
944
+ 'MESH',
945
+ 'ANNOUNCEMENT',
946
+ 'BURN_STATUS'
947
+ ]).default('LAYER_UNSPECIFIED');
948
+ /**
949
+ * MeshAdminTelemetry is one reading taken from a node's own admin interface by an
950
+ * operator-run monitor. It is the node's self-reported view, which is why it
951
+ * sits beside rather than replaces the gateway-reported `snr`/`rssi`: those are
952
+ * what a distant listener heard, these are what the node measured.
953
+ *
954
+ * Gauges are nullable: `null` means the monitor could not read it, which is not
955
+ * the same as 0 (a 0% battery and an unknown battery must not render alike).
956
+ * Counters are plain, count since the node's last boot (they reset at a
957
+ * reboot), and are 64-bit, so they arrive as JSON STRINGS.
958
+ */
959
+ export const zV1MeshAdminTelemetry = z.object({
960
+ airtimeMs: z.string().regex(/^-?[0-9]+$/),
961
+ batteryPercent: z.number().nullable(),
962
+ batteryPercentSource: z.enum([
963
+ '',
964
+ 'measured',
965
+ 'estimated'
966
+ ]),
967
+ batteryVolts: z.number().nullable(),
968
+ directDups: z.string().regex(/^-?[0-9]+$/),
969
+ floodDups: z.string().regex(/^-?[0-9]+$/),
970
+ fullEvents: z.string().regex(/^-?[0-9]+$/),
971
+ humidity: z.number().nullable(),
972
+ lastAttemptAt: z.iso.datetime().nullable(),
973
+ lastRssiDbm: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }).nullable(),
974
+ lastSnrDb: z.number().nullable(),
975
+ lastSuccessAt: z.iso.datetime().nullable(),
976
+ noiseFloorDbm: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }).nullable(),
977
+ packetsReceived: z.string().regex(/^-?[0-9]+$/),
978
+ packetsSent: z.string().regex(/^-?[0-9]+$/),
979
+ pressure: z.number().nullable(),
980
+ recvDirect: z.string().regex(/^-?[0-9]+$/),
981
+ recvErrors: z.string().regex(/^-?[0-9]+$/),
982
+ recvFlood: z.string().regex(/^-?[0-9]+$/),
983
+ reportedAt: z.iso.datetime().nullable(),
984
+ reporterId: z.string(),
985
+ rxAirtimeMs: z.string().regex(/^-?[0-9]+$/),
986
+ sentDirect: z.string().regex(/^-?[0-9]+$/),
987
+ sentFlood: z.string().regex(/^-?[0-9]+$/),
988
+ temperatureC: z.number().nullable(),
989
+ txQueueLen: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }).nullable(),
990
+ uptimeSeconds: z.string().regex(/^-?[0-9]+$/)
991
+ });
992
+ /**
993
+ * MeshReachability is an operator monitor's verdict on a node's admin interface,
994
+ * smoothed so a marginal link does not flap.
995
+ *
996
+ * - MESH_REACHABILITY_UNSPECIFIED: No monitor watches this node (most nodes). Says nothing about liveness.
997
+ * - REACHABLE: A monitor reached it recently.
998
+ * - UNREACHABLE: A monitor has been failing to reach it for longer than its window.
999
+ */
1000
+ export const zV1MeshReachability = z.enum([
1001
+ 'MESH_REACHABILITY_UNSPECIFIED',
1002
+ 'REACHABLE',
1003
+ 'UNREACHABLE'
1004
+ ]).default('MESH_REACHABILITY_UNSPECIFIED');
1005
+ /**
1006
+ * MeshTelemetry is a mesh node's volatile signal state and activity clocks. None
1007
+ * of it writes a revision, so history snapshots do not reflect it.
1008
+ *
1009
+ * For "is this node up right now", use `lastRelayedAt` (repeaters relay
1010
+ * constantly but advertise only every day or two), then `lastHeardAt`; never
1011
+ * the event's `observedAt`.
1012
+ *
1013
+ */
1014
+ export const zV1MeshTelemetry = z.object({
1015
+ admin: zV1MeshAdminTelemetry.nullable(),
1016
+ gateways: z.array(z.string()),
1017
+ hopCount: z.int().nullable(),
1018
+ lastAdvertAt: z.iso.datetime().nullable(),
1019
+ lastHeardAt: z.iso.datetime().nullable(),
1020
+ lastRelayedAt: z.iso.datetime().nullable(),
1021
+ rssi: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }).nullable(),
1022
+ snr: z.number().nullable()
1023
+ });
1024
+ /**
1025
+ * MeshDetail is the MESH detail block, for one MeshCore radio node, keyed by its
1026
+ * Ed25519 public key.
1027
+ *
1028
+ * Identity, location and reachability changes write a revision. The volatile
1029
+ * signal readings in `telemetry` change constantly without one.
1030
+ *
1031
+ */
1032
+ export const zV1MeshDetail = z.object({
1033
+ name: z.string(),
1034
+ nodeType: z.enum([
1035
+ 'companion',
1036
+ 'repeater',
1037
+ 'room_server',
1038
+ 'sensor'
1039
+ ]),
1040
+ publicKey: z.string().regex(/^[0-9a-f]{64}$/),
1041
+ reachability: zV1MeshReachability,
1042
+ telemetry: zV1MeshTelemetry.nullable()
1043
+ });
1044
+ /**
1045
+ * MeshTelemetryCoverage is the span of the whole archive for one node.
1046
+ */
1047
+ export const zV1MeshTelemetryCoverage = z.object({
1048
+ from: z.iso.datetime().nullable(),
1049
+ samples: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
1050
+ to: z.iso.datetime().nullable()
1051
+ });
1052
+ /**
1053
+ * MeshTelemetrySample is one archived report.
1054
+ *
1055
+ */
1056
+ export const zV1MeshTelemetrySample = z.object({
1057
+ reading: zV1MeshAdminTelemetry,
1058
+ receivedAt: z.iso.datetime()
1059
+ });
1060
+ /**
1061
+ * MeshTelemetryArchive is one node's samples over a window, with what a chart
1062
+ * needs in order not to lie about them.
1063
+ */
1064
+ export const zV1MeshTelemetryArchive = z.object({
1065
+ cadenceSeconds: z.string().regex(/^-?[0-9]+$/).nullable(),
1066
+ coverage: zV1MeshTelemetryCoverage,
1067
+ from: z.iso.datetime(),
1068
+ node: z.string(),
1069
+ reboots: z.array(z.iso.datetime()),
1070
+ samples: z.array(zV1MeshTelemetrySample),
1071
+ to: z.iso.datetime(),
1072
+ truncated: z.boolean()
1073
+ });
1074
+ /**
1075
+ * PlaceKind is the type of a place.
1076
+ *
1077
+ * - PLACE_KIND_UNSPECIFIED: Never returned.
1078
+ * - AREA: A configured coverage area such as `ebbetts-pass` (the Highway 4 corridor
1079
+ * region). Area places own the scanner feeds and the fire-weather zones.
1080
+ * - COUNTY: A county, from Census polygons.
1081
+ * - TOWN: A town, stored as a Point. `places:resolve` matches a town within 3 km of
1082
+ * its point. Events attach to a town only by overlapping polygons (and
1083
+ * wildfires by proximity), never by that radius.
1084
+ * - EVAC_ZONE: Reserved for evacuation zones as places; none exist today.
1085
+ * - CORRIDOR: A highway segment, stored as a LineString. Point events within about 1.5 km
1086
+ * of the line attach to it.
1087
+ * - SITE: Reserved for individual sites; none exist today.
1088
+ */
1089
+ export const zV1PlaceKind = z.enum([
1090
+ 'PLACE_KIND_UNSPECIFIED',
1091
+ 'AREA',
1092
+ 'COUNTY',
1093
+ 'TOWN',
1094
+ 'EVAC_ZONE',
1095
+ 'CORRIDOR',
1096
+ 'SITE'
1097
+ ]).default('PLACE_KIND_UNSPECIFIED');
1098
+ /**
1099
+ * Place is a named geography that events attach to.
1100
+ */
1101
+ export const zV1Place = z.object({
1102
+ geometry: zV1Geometry,
1103
+ id: z.string(),
1104
+ kind: zV1PlaceKind,
1105
+ name: z.string(),
1106
+ parentId: z.string(),
1107
+ slug: z.string()
1108
+ });
1109
+ /**
1110
+ * PlaceList is the place directory.
1111
+ */
1112
+ export const zV1PlaceList = z.object({
1113
+ places: z.array(zV1Place)
1114
+ });
1115
+ /**
1116
+ * PowerDetail is the POWER detail block, for a PG&E outage or a Public Safety
1117
+ * Power Shutoff (PSPS). The envelope `category` says which: `unplanned` and
1118
+ * `planned` outages fill the outage fields; `psps` fills the PSPS fields. The
1119
+ * other group is zero, empty or `null`.
1120
+ *
1121
+ * Every PG&E time here is an estimate PG&E often overruns, so none of them is
1122
+ * mapped onto the envelope `expires` or drives the lifecycle.
1123
+ */
1124
+ export const zV1PowerDetail = z.object({
1125
+ allClear: z.iso.datetime().nullable(),
1126
+ cause: z.string(),
1127
+ crewStatus: z.string(),
1128
+ customersAffected: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
1129
+ deEnergizationEnd: z.iso.datetime().nullable(),
1130
+ deEnergizationStart: z.iso.datetime().nullable(),
1131
+ estimatedRestoration: z.iso.datetime().nullable(),
1132
+ eventId: z.string(),
1133
+ eventName: z.string(),
1134
+ medicalBaselineAffected: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
1135
+ outageId: z.string(),
1136
+ stage: z.enum([
1137
+ '',
1138
+ 'Watch',
1139
+ 'Warning'
1140
+ ]),
1141
+ timePeriod: z.string()
1142
+ });
1143
+ /**
1144
+ * Provenance says which upstream published an event. Show `attribution` next to
1145
+ * the data.
1146
+ */
1147
+ export const zV1Provenance = z.object({
1148
+ attribution: z.string(),
1149
+ fetchedAt: z.iso.datetime(),
1150
+ sourceId: z.enum([
1151
+ 'calfire',
1152
+ 'firis',
1153
+ 'caloes',
1154
+ 'nws',
1155
+ 'usgs',
1156
+ 'chp',
1157
+ 'caltrans',
1158
+ 'pge',
1159
+ 'psps',
1160
+ 'meshcore',
1161
+ 'burnline',
1162
+ 'calfire-burn'
1163
+ ]),
1164
+ sourceName: z.string(),
1165
+ sourceUrl: z.string()
1166
+ });
1167
+ /**
1168
+ * ResolveQuery echoes the point that was resolved.
1169
+ */
1170
+ export const zV1ResolveQuery = z.object({
1171
+ lat: z.number(),
1172
+ lng: z.number(),
1173
+ matchedAddress: z.string()
1174
+ });
1175
+ /**
1176
+ * ResolvePlaceResponse lists the places containing a point.
1177
+ */
1178
+ export const zV1ResolvePlaceResponse = z.object({
1179
+ places: z.array(zV1Place),
1180
+ query: zV1ResolveQuery
1181
+ });
1182
+ /**
1183
+ * RoadIncidentDetail is the ROAD_INCIDENT detail block, for a CHP incident or a
1184
+ * Caltrans lane-closure window. The incident type is the envelope `category`,
1185
+ * the location is `areaLabel`, and the short line is `headline`.
1186
+ */
1187
+ export const zV1RoadIncidentDetail = z.object({
1188
+ closure: zV1LaneClosureDetail.nullable(),
1189
+ duration: z.enum([
1190
+ '',
1191
+ 'unknown',
1192
+ '< 1 hour',
1193
+ 'several hours',
1194
+ 'ongoing'
1195
+ ]),
1196
+ impact: z.enum([
1197
+ '',
1198
+ 'none',
1199
+ 'light',
1200
+ 'moderate',
1201
+ 'severe'
1202
+ ]),
1203
+ logNumber: z.string(),
1204
+ metadata: z.record(z.string(), z.string())
1205
+ });
1206
+ /**
1207
+ * Scanner is one Broadcastify audio feed.
1208
+ */
1209
+ export const zV1Scanner = z.object({
1210
+ agency: z.string(),
1211
+ broadcastifyUrl: z.string(),
1212
+ channelLabel: z.string(),
1213
+ feedId: z.string()
1214
+ });
1215
+ /**
1216
+ * ScannerList is the scanner feeds.
1217
+ */
1218
+ export const zV1ScannerList = z.object({
1219
+ scanners: z.array(zV1Scanner)
1220
+ });
1221
+ /**
1222
+ * Severity is the unified 5-level scale shared by every layer: how urgently the
1223
+ * public should respond, not physical magnitude. The enum number is the rank
1224
+ * (`severityRank`, 0-4), for sorting and colour ramps.
1225
+ *
1226
+ * How each layer is graded. WILDFIRE: the worse of a containment floor (under
1227
+ * 50% contained SEVERE, 50-99% MODERATE, 100% MINOR) and size (1,000+ acres
1228
+ * under 50% contained EXTREME, 100+ acres SEVERE). EVACUATION: ORDER EXTREME,
1229
+ * WARNING and SHELTER_IN_PLACE SEVERE, ADVISORY MODERATE. WEATHER_ALERT: the NWS
1230
+ * severity (Extreme..Minor) one-to-one, otherwise INFO. EARTHQUAKE: M5+ SEVERE,
1231
+ * M4+ MODERATE, M2.5+ MINOR. ROAD_INCIDENT: a CHP incident by its AI-assessed
1232
+ * impact (severe SEVERE, moderate MODERATE, light MINOR, none INFO); a Caltrans
1233
+ * closure by its structure (full closure SEVERE, a travel lane or one-way
1234
+ * traffic MODERATE, shoulder only MINOR). POWER: 1,000+ customers SEVERE, 100+
1235
+ * MODERATE, 10+ MINOR, fewer INFO, unknown count MINOR, planned outages one rank
1236
+ * lower; PSPS Warning SEVERE, Watch MODERATE. MESH and BURN_STATUS: always INFO.
1237
+ * Condition layers on the map: road segment CLOSED SEVERE, restricted or heavy
1238
+ * congestion MODERATE; chain control R3 SEVERE, R2 MODERATE, R1 MINOR, road
1239
+ * closed MINOR; fire weather red-flag SEVERE, elevated MODERATE.
1240
+ *
1241
+ * - INFO: Rank 0. Informational: ambient state, single-customer outages, small quakes,
1242
+ * clear roads. Also the default when a source gives no grade.
1243
+ * - MINOR: Rank 1. Minor impact.
1244
+ * - MODERATE: Rank 2. Moderate impact; worth attention.
1245
+ * - SEVERE: Rank 3. Severe; act or prepare now.
1246
+ * - EXTREME: Rank 4. Extreme; life-safety (evacuation orders, large uncontained fires).
1247
+ */
1248
+ export const zV1Severity = z.enum([
1249
+ 'INFO',
1250
+ 'MINOR',
1251
+ 'MODERATE',
1252
+ 'SEVERE',
1253
+ 'EXTREME'
1254
+ ]).default('INFO');
1255
+ /**
1256
+ * SourceKind says what a source registry row describes.
1257
+ *
1258
+ * - SOURCE_KIND_UNSPECIFIED: Never returned.
1259
+ * - FEED: An upstream feed the Grid fetches on a schedule (CAL FIRE, NWS, PG&E, ...).
1260
+ * Events name it in `provenance.sourceId`.
1261
+ * - REPORTER: An operator-run monitor that pushes to the Grid's ingest endpoint. Health
1262
+ * only: no event carries its id, and `homepageUrl` is empty.
1263
+ */
1264
+ export const zV1SourceKind = z.enum([
1265
+ 'SOURCE_KIND_UNSPECIFIED',
1266
+ 'FEED',
1267
+ 'REPORTER'
1268
+ ]).default('SOURCE_KIND_UNSPECIFIED');
1269
+ /**
1270
+ * SourceStatus is a source's health. The same three values appear as strings in
1271
+ * the summary's domains and sidecar, on `/api/v1/cameras`, and on the map
1272
+ * layers' `metadata.sourceStatus`.
1273
+ *
1274
+ * - SOURCE_STATUS_UNSPECIFIED: Not polled yet since the registry row was created. Treat as UNAVAILABLE.
1275
+ * - OK: The last attempt succeeded.
1276
+ * - STALE: The last attempt failed, but the last success is within
1277
+ * `staleAfterSeconds`; what is served is last-good data.
1278
+ * - UNAVAILABLE: Failing beyond `staleAfterSeconds`, or never succeeded. Nothing current can
1279
+ * be vouched for: render "unknown", never "none".
1280
+ */
1281
+ export const zV1SourceStatus = z.enum([
1282
+ 'SOURCE_STATUS_UNSPECIFIED',
1283
+ 'OK',
1284
+ 'STALE',
1285
+ 'UNAVAILABLE'
1286
+ ]).default('SOURCE_STATUS_UNSPECIFIED');
1287
+ /**
1288
+ * Source is one row of the source registry, with its health.
1289
+ *
1290
+ * Two kinds of row, told apart by `kind`: a FEED is an upstream the Grid
1291
+ * fetches on a schedule, and its id is what events carry in
1292
+ * `provenance.sourceId`. A REPORTER is an operator-run monitor that pushes data
1293
+ * to the Grid (`alanpi`, `relay`, `burn-line`); its row carries health only and
1294
+ * no event names it as its source.
1295
+ *
1296
+ * To judge health, read `status`. It is rewritten at every attempt, so as a
1297
+ * second check against the Grid itself stalling, treat a row as suspect when
1298
+ * `lastAttemptAt` is older than `staleAfterSeconds`. Do not compare
1299
+ * `lastAttemptAt` with `pollIntervalSeconds`: that misfires for reporters.
1300
+ *
1301
+ * Not every source id that appears in the API has a row. The live condition
1302
+ * layers fetch on request, outside the scheduler that writes this registry, so
1303
+ * `google` (the `road_segment` layer's travel times) has no row, and the
1304
+ * `caltrans` and `nws` rows describe the scheduled lane-closure and alert
1305
+ * polls, not the live `chain_control`, `message_sign`, `road_segment` and
1306
+ * `fire_weather` fetches. For those layers read the map layer's
1307
+ * `metadata.sourceStatus` or the summary domain's `status`.
1308
+ */
1309
+ export const zV1Source = z.object({
1310
+ attribution: z.string(),
1311
+ expireAfterSeconds: z.int(),
1312
+ homepageUrl: z.string(),
1313
+ id: z.string(),
1314
+ kind: zV1SourceKind,
1315
+ lastAttemptAt: z.iso.datetime().nullable(),
1316
+ lastError: z.string(),
1317
+ lastSuccessAt: z.iso.datetime().nullable(),
1318
+ name: z.string(),
1319
+ pollIntervalSeconds: z.int(),
1320
+ staleAfterSeconds: z.int(),
1321
+ status: zV1SourceStatus
1322
+ });
1323
+ /**
1324
+ * SourceList is the source registry.
1325
+ */
1326
+ export const zV1SourceList = z.object({
1327
+ sources: z.array(zV1Source)
1328
+ });
1329
+ /**
1330
+ * SummaryDomainHeadline is one item in a domain's headline list: an event, or a
1331
+ * live condition-layer feature (a closed road segment, a chain control, a fire
1332
+ * weather banner). Use `kind` to tell them apart before following `id`.
1333
+ */
1334
+ export const zV1SummaryDomainHeadline = z.object({
1335
+ headline: z.string(),
1336
+ id: z.string(),
1337
+ kind: z.enum(['EVENT', 'CONDITION']),
1338
+ layer: z.enum([
1339
+ 'WILDFIRE',
1340
+ 'EVACUATION',
1341
+ 'WEATHER_ALERT',
1342
+ 'EARTHQUAKE',
1343
+ 'ROAD_INCIDENT',
1344
+ 'POWER',
1345
+ 'MESH',
1346
+ 'BURN_STATUS',
1347
+ 'ROAD_SEGMENT',
1348
+ 'CHAIN_CONTROL',
1349
+ 'FIRE_WEATHER'
1350
+ ]),
1351
+ severity: z.enum([
1352
+ 'INFO',
1353
+ 'MINOR',
1354
+ 'MODERATE',
1355
+ 'SEVERE',
1356
+ 'EXTREME'
1357
+ ])
1358
+ });
1359
+ /**
1360
+ * SummaryDomain is one subject area's status for the place.
1361
+ *
1362
+ * Domain inputs: `fire` = WILDFIRE events + the fire_weather condition;
1363
+ * `evacuation` = EVACUATION; `weather` = WEATHER_ALERT; `roads` = ROAD_INCIDENT
1364
+ * events (not SCHEDULED roadwork) + the chain_control and road_segment
1365
+ * conditions; `seismic` = EARTHQUAKE; `power` = POWER (including INFO
1366
+ * outages); `burn` = BURN_STATUS; `comms` = MESH. A domain counts every one of
1367
+ * its ACTIVE and SCHEDULED events at any severity, but a condition only when it
1368
+ * is above INFO (an open road or normal fire weather is not "active").
1369
+ */
1370
+ export const zV1SummaryDomain = z.object({
1371
+ activeCount: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
1372
+ domain: z.enum([
1373
+ 'fire',
1374
+ 'evacuation',
1375
+ 'weather',
1376
+ 'roads',
1377
+ 'seismic',
1378
+ 'power',
1379
+ 'burn',
1380
+ 'comms'
1381
+ ]),
1382
+ headlines: z.array(zV1SummaryDomainHeadline),
1383
+ highestSeverity: z.enum([
1384
+ 'INFO',
1385
+ 'MINOR',
1386
+ 'MODERATE',
1387
+ 'SEVERE',
1388
+ 'EXTREME'
1389
+ ]),
1390
+ status: z.enum([
1391
+ 'OK',
1392
+ 'STALE',
1393
+ 'UNAVAILABLE'
1394
+ ])
1395
+ });
1396
+ /**
1397
+ * SummarySourceHealth is one source registry row behind the summary's layers.
1398
+ */
1399
+ export const zV1SummarySourceHealth = z.object({
1400
+ id: z.string(),
1401
+ lastSuccessAt: z.iso.datetime().nullable(),
1402
+ status: z.enum([
1403
+ 'OK',
1404
+ 'STALE',
1405
+ 'UNAVAILABLE'
1406
+ ])
1407
+ });
1408
+ /**
1409
+ * SummaryTopEvent is one of the place's most urgent hazard events.
1410
+ */
1411
+ export const zV1SummaryTopEvent = z.object({
1412
+ headline: z.string(),
1413
+ id: z.string(),
1414
+ layer: z.enum([
1415
+ 'WILDFIRE',
1416
+ 'EVACUATION',
1417
+ 'WEATHER_ALERT',
1418
+ 'EARTHQUAKE',
1419
+ 'ROAD_INCIDENT',
1420
+ 'POWER'
1421
+ ]),
1422
+ severity: z.enum([
1423
+ 'INFO',
1424
+ 'MINOR',
1425
+ 'MODERATE',
1426
+ 'SEVERE',
1427
+ 'EXTREME'
1428
+ ]),
1429
+ severityRank: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
1430
+ source: z.string()
1431
+ });
1432
+ /**
1433
+ * SummaryStats is the place's hazard rollup.
1434
+ *
1435
+ * It counts the place's ACTIVE and SCHEDULED events except four carve-outs:
1436
+ * MESH nodes and BURN_STATUS (ambient state, shown in their own domains), POWER
1437
+ * outages at INFO (single-customer service calls), and SCHEDULED road closures
1438
+ * (planned roadwork). A SCHEDULED weather watch or PSPS still counts. Condition
1439
+ * layers never count here.
1440
+ */
1441
+ export const zV1SummaryStats = z.object({
1442
+ activeEvacuations: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }).nullable(),
1443
+ evacuationSourceUrl: z.string(),
1444
+ evacuationStatus: z.enum([
1445
+ 'OK',
1446
+ 'STALE',
1447
+ 'UNAVAILABLE'
1448
+ ]),
1449
+ highestSeverity: z.enum([
1450
+ 'INFO',
1451
+ 'MINOR',
1452
+ 'MODERATE',
1453
+ 'SEVERE',
1454
+ 'EXTREME'
1455
+ ]),
1456
+ highestSeverityRank: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).lte(4),
1457
+ severityCounts: z.record(z.string(), z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' })),
1458
+ topEvents: z.array(zV1SummaryTopEvent),
1459
+ totalActive: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' })
1460
+ });
1461
+ /**
1462
+ * PlaceSummary is the one-call rollup for a place.
1463
+ *
1464
+ * `summary` covers hazards only. Each entry in `domains` covers one subject
1465
+ * area, including the ambient ones (`burn`, `comms`) that the hazard rollup
1466
+ * leaves out.
1467
+ */
1468
+ export const zV1PlaceSummary = z.object({
1469
+ domains: z.array(zV1SummaryDomain),
1470
+ generatedAt: z.iso.datetime(),
1471
+ mode: z.enum([
1472
+ 'QUIET',
1473
+ 'WATCH',
1474
+ 'ACTIVE'
1475
+ ]),
1476
+ place: z.string(),
1477
+ placeId: z.string(),
1478
+ placeName: z.string(),
1479
+ sources: z.array(zV1SummarySourceHealth),
1480
+ summary: zV1SummaryStats
1481
+ });
1482
+ /**
1483
+ * WeatherAlertDetail is the WEATHER_ALERT detail block, for one NWS product.
1484
+ *
1485
+ * It carries only fields the envelope lacks: the NWS event name is the
1486
+ * envelope `category`, and the issuing office is `provenance.sourceName`.
1487
+ */
1488
+ export const zV1WeatherAlertDetail = z.object({
1489
+ areaDesc: z.string(),
1490
+ certainty: z.enum([
1491
+ 'Observed',
1492
+ 'Likely',
1493
+ 'Possible',
1494
+ 'Unlikely',
1495
+ 'Unknown'
1496
+ ]),
1497
+ instruction: z.string(),
1498
+ nwsSeverity: z.enum([
1499
+ 'Extreme',
1500
+ 'Severe',
1501
+ 'Moderate',
1502
+ 'Minor',
1503
+ 'Unknown'
1504
+ ]),
1505
+ urgency: z.enum([
1506
+ 'Immediate',
1507
+ 'Expected',
1508
+ 'Future',
1509
+ 'Past',
1510
+ 'Unknown'
1511
+ ]),
1512
+ zones: z.array(z.string())
1513
+ });
1514
+ /**
1515
+ * WeatherConditions is current weather at one location, from OpenWeatherMap.
1516
+ * Whole numbers, metric units. A value that could not be read is 0.
1517
+ */
1518
+ export const zV1WeatherConditions = z.object({
1519
+ feelsLikeCelsius: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
1520
+ humidityPercent: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
1521
+ locationId: z.string(),
1522
+ locationName: z.string(),
1523
+ temperatureCelsius: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
1524
+ visibilityKm: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
1525
+ weatherDescription: z.string(),
1526
+ weatherIcon: z.string(),
1527
+ weatherMain: z.string(),
1528
+ windDirectionDegrees: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
1529
+ windSpeedKmh: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' })
1530
+ });
1531
+ /**
1532
+ * WeatherForecast is a location's short-range forecast: the hourly NWS gridpoint
1533
+ * series (wind, gust, humidity, temperature) plus an at-a-glance summary.
1534
+ * Informational only: it never implies a fire-weather warning (issued products
1535
+ * are in `fireWeather`).
1536
+ *
1537
+ */
1538
+ export const zV1WeatherForecast = z.object({
1539
+ horizonHours: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
1540
+ issuedAt: z.iso.datetime().nullable(),
1541
+ locationId: z.string(),
1542
+ minHumidityPercent: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
1543
+ peakWindGustAt: z.iso.datetime().nullable(),
1544
+ peakWindGustKmh: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
1545
+ periods: z.array(zV1ForecastPeriod),
1546
+ source: z.string()
1547
+ });
1548
+ /**
1549
+ * Conditions is current, non-event state.
1550
+ */
1551
+ export const zV1Conditions = z.object({
1552
+ fireWeather: zV1FireWeatherConditions.nullable(),
1553
+ forecast: z.array(zV1WeatherForecast),
1554
+ lastUpdated: z.iso.datetime().nullable(),
1555
+ weather: z.array(zV1WeatherConditions)
1556
+ });
1557
+ /**
1558
+ * WildfireDetail is the WILDFIRE detail block.
1559
+ */
1560
+ export const zV1WildfireDetail = z.object({
1561
+ acres: z.number(),
1562
+ cause: z.string(),
1563
+ containment: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }),
1564
+ county: z.string(),
1565
+ hasPerimeter: z.boolean()
1566
+ });
1567
+ /**
1568
+ * Event is one item from one upstream source: a hazard, or a piece of ambient
1569
+ * state such as a mesh node or a county's burn status.
1570
+ *
1571
+ * The envelope fields are the same for every layer, so a client can render a
1572
+ * card from `headline`, `severity`, `status` and `provenance` without knowing the
1573
+ * layer. Layer-specific fields are in exactly one detail block (`wildfire`,
1574
+ * `evacuation`, `weatherAlert`, `earthquake`, `roadIncident`, `mesh`, `power` or
1575
+ * `burnStatus`), chosen by `layer`; the other blocks are absent. `fireWeather`
1576
+ * is never populated on an event.
1577
+ */
1578
+ export const zV1Event = z.object({
1579
+ areaLabel: z.string(),
1580
+ burnStatus: zV1BurnStatusDetail.optional(),
1581
+ canonicalUrl: z.string(),
1582
+ category: z.string(),
1583
+ description: z.string(),
1584
+ earthquake: zV1EarthquakeDetail.optional(),
1585
+ effective: z.iso.datetime().nullable(),
1586
+ enhancement: zV1Enhancement.nullable(),
1587
+ evacuation: zV1EvacuationDetail.optional(),
1588
+ expires: z.iso.datetime().nullable(),
1589
+ fireWeather: zV1FireWeatherDetail.optional(),
1590
+ geometry: zV1Geometry.nullable(),
1591
+ headline: z.string(),
1592
+ id: z.string(),
1593
+ ingestedAt: z.iso.datetime(),
1594
+ layer: zV1Layer,
1595
+ mesh: zV1MeshDetail.optional(),
1596
+ observedAt: z.iso.datetime().nullable(),
1597
+ placeIds: z.array(z.string()),
1598
+ power: zV1PowerDetail.optional(),
1599
+ provenance: zV1Provenance,
1600
+ revision: z.int(),
1601
+ roadIncident: zV1RoadIncidentDetail.optional(),
1602
+ severity: zV1Severity,
1603
+ status: zV1EventStatus,
1604
+ summary: z.string(),
1605
+ weatherAlert: zV1WeatherAlertDetail.optional(),
1606
+ wildfire: zV1WildfireDetail.optional()
1607
+ });
1608
+ /**
1609
+ * EventList is one page of events.
1610
+ */
1611
+ export const zV1EventList = z.object({
1612
+ events: z.array(zV1Event),
1613
+ nextPageToken: z.string()
1614
+ });
1615
+ /**
1616
+ * EventRevision is one stored snapshot of an event.
1617
+ */
1618
+ export const zV1EventRevision = z.object({
1619
+ event: zV1Event,
1620
+ ingestedAt: z.iso.datetime(),
1621
+ observedAt: z.iso.datetime(),
1622
+ revision: z.int()
1623
+ });
1624
+ /**
1625
+ * EventRevisionList is one page of revisions.
1626
+ */
1627
+ export const zV1EventRevisionList = z.object({
1628
+ nextPageToken: z.string(),
1629
+ revisions: z.array(zV1EventRevision)
1630
+ });
1631
+ /**
1632
+ * An `ETag` from an earlier response, for a `304` revalidation.
1633
+ */
1634
+ export const zIfNoneMatch = z.string();
1635
+ /**
1636
+ * Recency window for relay links: a positive Go duration. The documented
1637
+ * choices are `24h`, `72h` (the default), `168h` and `720h`; any positive
1638
+ * duration works (`90m`), and values above `9600h` (400 days) are
1639
+ * clamped. Anything else (`abc`, `0`, `-1h`) is a `400
1640
+ * INVALID_ARGUMENT`. `/api/v1/mesh/links` echoes the applied window in
1641
+ * `window`.
1642
+ *
1643
+ */
1644
+ export const zMeshWindow = z.string().default('72h');
1645
+ /**
1646
+ * A place slug (`calaveras-county`, `ebbetts-pass`, `hwy4-murphys-arnold`)
1647
+ * or namespaced id (`county:calaveras-county`). Slugs are globally unique.
1648
+ * `GET /api/v1/places` lists them; `GET /api/v1/places:resolve` maps an
1649
+ * address or lat/lng to the places containing it.
1650
+ *
1651
+ */
1652
+ export const zPlace = z.string();
1653
+ export const zGridServiceListCamerasQuery = z.object({
1654
+ place: z.string().optional()
1655
+ });
1656
+ /**
1657
+ * A successful response.
1658
+ */
1659
+ export const zGridServiceListCamerasResponse = zV1CameraList;
1660
+ export const zGridServiceGetConditionsQuery = z.object({
1661
+ place: z.string().optional()
1662
+ });
1663
+ /**
1664
+ * A successful response.
1665
+ */
1666
+ export const zGridServiceGetConditionsResponse = zV1Conditions;
1667
+ export const zGridServiceListEventsQuery = z.object({
1668
+ place: z.string().optional(),
1669
+ layer: z.array(z.enum([
1670
+ 'WILDFIRE',
1671
+ 'EVACUATION',
1672
+ 'WEATHER_ALERT',
1673
+ 'EARTHQUAKE',
1674
+ 'ROAD_INCIDENT',
1675
+ 'POWER',
1676
+ 'MESH',
1677
+ 'BURN_STATUS'
1678
+ ])).optional(),
1679
+ status: z.array(z.enum([
1680
+ 'ACTIVE',
1681
+ 'SCHEDULED',
1682
+ 'RESOLVED',
1683
+ 'EXPIRED'
1684
+ ])).optional(),
1685
+ severityMin: z.enum([
1686
+ 'INFO',
1687
+ 'MINOR',
1688
+ 'MODERATE',
1689
+ 'SEVERE',
1690
+ 'EXTREME'
1691
+ ]).optional(),
1692
+ since: z.iso.datetime().optional(),
1693
+ pageSize: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }).optional(),
1694
+ pageToken: z.string().optional(),
1695
+ enhancementIo: z.boolean().optional(),
1696
+ geometryFormat: z.enum(['BASE64', 'OBJECT']).optional().default('BASE64')
1697
+ });
1698
+ /**
1699
+ * A successful response.
1700
+ */
1701
+ export const zGridServiceListEventsResponse = zV1EventList;
1702
+ export const zGridServiceGetEventPath = z.object({
1703
+ id: z.string()
1704
+ });
1705
+ export const zGridServiceGetEventQuery = z.object({
1706
+ enhancementIo: z.boolean().optional(),
1707
+ geometryFormat: z.enum(['BASE64', 'OBJECT']).optional().default('BASE64')
1708
+ });
1709
+ /**
1710
+ * A successful response.
1711
+ */
1712
+ export const zGridServiceGetEventResponse = zV1Event;
1713
+ export const zGridServiceGetEventHistoryPath = z.object({
1714
+ id: z.string()
1715
+ });
1716
+ export const zGridServiceGetEventHistoryQuery = z.object({
1717
+ pageSize: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }).optional(),
1718
+ pageToken: z.string().optional(),
1719
+ enhancementIo: z.boolean().optional(),
1720
+ geometryFormat: z.enum(['BASE64', 'OBJECT']).optional().default('BASE64')
1721
+ });
1722
+ /**
1723
+ * A successful response.
1724
+ */
1725
+ export const zGridServiceGetEventHistoryResponse = zV1EventRevisionList;
1726
+ export const zGridServiceListHistoryQuery = z.object({
1727
+ place: z.string().optional(),
1728
+ layer: z.array(z.enum([
1729
+ 'WILDFIRE',
1730
+ 'EVACUATION',
1731
+ 'WEATHER_ALERT',
1732
+ 'EARTHQUAKE',
1733
+ 'ROAD_INCIDENT',
1734
+ 'POWER',
1735
+ 'MESH',
1736
+ 'BURN_STATUS'
1737
+ ])).optional(),
1738
+ from: z.iso.datetime().optional(),
1739
+ to: z.iso.datetime().optional(),
1740
+ pageSize: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' }).optional(),
1741
+ pageToken: z.string().optional(),
1742
+ enhancementIo: z.boolean().optional(),
1743
+ geometryFormat: z.enum(['BASE64', 'OBJECT']).optional().default('BASE64')
1744
+ });
1745
+ /**
1746
+ * A successful response.
1747
+ */
1748
+ export const zGridServiceListHistoryResponse = zV1EventRevisionList;
1749
+ export const zListMeshLinksHeaders = z.object({
1750
+ 'If-None-Match': z.string().optional()
1751
+ });
1752
+ export const zListMeshLinksQuery = z.object({
1753
+ window: z.string().optional().default('72h')
1754
+ });
1755
+ /**
1756
+ * The links, possibly empty.
1757
+ */
1758
+ export const zListMeshLinksResponse = zMeshLinkList;
1759
+ export const zGridServiceGetMeshTelemetryQuery = z.object({
1760
+ node: z.string().regex(/^([mM][eE][sS][hH][cC][oO][rR][eE]:)?([0-9a-fA-F]{2}){4,32}$/),
1761
+ from: z.iso.datetime().optional(),
1762
+ to: z.iso.datetime().optional()
1763
+ });
1764
+ /**
1765
+ * A successful response.
1766
+ */
1767
+ export const zGridServiceGetMeshTelemetryResponse = zV1MeshTelemetryArchive;
1768
+ export const zGridServiceListPlacesQuery = z.object({
1769
+ kind: z.enum([
1770
+ 'AREA',
1771
+ 'COUNTY',
1772
+ 'TOWN',
1773
+ 'CORRIDOR',
1774
+ 'EVAC_ZONE',
1775
+ 'SITE'
1776
+ ]).optional(),
1777
+ q: z.string().optional(),
1778
+ geometryFormat: z.enum(['BASE64', 'OBJECT']).optional().default('BASE64')
1779
+ });
1780
+ /**
1781
+ * A successful response.
1782
+ */
1783
+ export const zGridServiceListPlacesResponse = zV1PlaceList;
1784
+ export const zGridServiceGetPlacePath = z.object({
1785
+ place: z.string()
1786
+ });
1787
+ export const zGridServiceGetPlaceQuery = z.object({
1788
+ geometryFormat: z.enum(['BASE64', 'OBJECT']).optional().default('BASE64')
1789
+ });
1790
+ /**
1791
+ * A successful response.
1792
+ */
1793
+ export const zGridServiceGetPlaceResponse = zV1Place;
1794
+ export const zGetMapLayerHeaders = z.object({
1795
+ 'If-None-Match': z.string().optional()
1796
+ });
1797
+ export const zGetMapLayerPath = z.object({
1798
+ place: z.string(),
1799
+ layer: z.enum([
1800
+ 'road_incident',
1801
+ 'chain_control',
1802
+ 'road_segment',
1803
+ 'message_sign',
1804
+ 'weather_alert',
1805
+ 'fire_weather',
1806
+ 'earthquake',
1807
+ 'wildfire',
1808
+ 'evacuation',
1809
+ 'power',
1810
+ 'mesh_node',
1811
+ 'mesh_link',
1812
+ 'camera'
1813
+ ])
1814
+ });
1815
+ export const zGetMapLayerQuery = z.object({
1816
+ window: z.string().optional().default('72h')
1817
+ });
1818
+ /**
1819
+ * The layer. Empty `features` is a valid answer; read `metadata.sourceStatus` to know whether it is confirmed-empty or unknown.
1820
+ */
1821
+ export const zGetMapLayerResponse = zMapFeatureCollection;
1822
+ export const zGridServiceGetPlaceSummaryPath = z.object({
1823
+ place: z.string()
1824
+ });
1825
+ /**
1826
+ * A successful response.
1827
+ */
1828
+ export const zGridServiceGetPlaceSummaryResponse = zV1PlaceSummary;
1829
+ export const zGridServiceResolvePlaceQuery = z.object({
1830
+ lat: z.number().optional(),
1831
+ lng: z.number().optional(),
1832
+ address: z.string().optional(),
1833
+ geometryFormat: z.enum(['BASE64', 'OBJECT']).optional().default('BASE64')
1834
+ });
1835
+ /**
1836
+ * A successful response.
1837
+ */
1838
+ export const zGridServiceResolvePlaceResponse = zV1ResolvePlaceResponse;
1839
+ export const zGridServiceListScannersQuery = z.object({
1840
+ place: z.string().optional()
1841
+ });
1842
+ /**
1843
+ * A successful response.
1844
+ */
1845
+ export const zGridServiceListScannersResponse = zV1ScannerList;
1846
+ /**
1847
+ * A successful response.
1848
+ */
1849
+ export const zGridServiceListSourcesResponse = zV1SourceList;