@myrobotaxi/contracts 0.1.4 → 0.3.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.
- package/dist/index.cjs +117 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +99 -1
- package/dist/index.d.ts +99 -1
- package/dist/index.js +117 -4
- package/dist/index.js.map +1 -1
- package/dist/types.d.cts +99 -5
- package/dist/types.d.ts +99 -5
- package/package.json +2 -1
- package/schemas/vehicle-summary.schema.json +108 -0
- package/schemas/ws-messages.schema.json +6 -4
package/dist/types.d.ts
CHANGED
|
@@ -244,6 +244,100 @@ interface VehicleState {
|
|
|
244
244
|
lastUpdated: string;
|
|
245
245
|
}
|
|
246
246
|
|
|
247
|
+
/**
|
|
248
|
+
* AUTO-GENERATED by scripts/codegen.mjs from the corresponding JSON Schema
|
|
249
|
+
* in ../schemas/. DO NOT EDIT BY HAND — re-run `npm run codegen` instead.
|
|
250
|
+
*
|
|
251
|
+
* The x-classification / x-atomic-group / x-unit / x-encrypted custom JSON
|
|
252
|
+
* Schema annotations from the source schemas are folded into the generated
|
|
253
|
+
* TSDoc comments so grep can find them without leaving the editor.
|
|
254
|
+
*/
|
|
255
|
+
/**
|
|
256
|
+
* Envelope returned by GET /api/vehicles. Wraps an array of VehicleSummary rows under the `items` key. Pagination fields are reserved per rest-api.md §7.0 and intentionally absent in v1. The envelope itself is part of the wire contract: consumers MUST NOT strip it silently.
|
|
257
|
+
*/
|
|
258
|
+
interface VehicleListResponse {
|
|
259
|
+
/**
|
|
260
|
+
* Per-vehicle summary rows for vehicles the caller has access to. Order is server-defined (currently ORDER BY Vehicle.createdAt ASC in the telemetry list query). An empty array means the caller has no vehicles (or is a v1 viewer-tier caller — see rest-api.md §7.0 RBAC v1 implementation note).
|
|
261
|
+
*/
|
|
262
|
+
items: VehicleSummary[];
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Lean per-vehicle row returned by GET /api/vehicles. A list-view projection of VehicleState containing only the fields the catalog UI needs (identity, model/year/color, status, charge headline, last-updated). No GPS, no navigation, no climate, no encrypted-at-rest fields. Mirrors the Go `vehicleSummary` struct in telemetry/internal/telemetry/vehicles_list_handler.go and the `VehicleSummary` shape in telemetry/specs/rest.openapi.yaml. Use VehicleState for the full snapshot/WebSocket payload; use VehicleSummary for list endpoints.
|
|
266
|
+
*
|
|
267
|
+
* This interface was referenced by `VehicleListResponse`'s JSON-Schema
|
|
268
|
+
* via the `definition` "VehicleSummary".
|
|
269
|
+
*/
|
|
270
|
+
interface VehicleSummary {
|
|
271
|
+
/**
|
|
272
|
+
* Opaque database identifier (cuid). NOT the VIN. All SDK API calls use this ID (FR-4.2). Matches VehicleState.vehicleId.
|
|
273
|
+
*
|
|
274
|
+
* @classification "P0"
|
|
275
|
+
*/
|
|
276
|
+
vehicleId: string;
|
|
277
|
+
/**
|
|
278
|
+
* User-assigned vehicle name from DB Vehicle.name. Matches VehicleState.name.
|
|
279
|
+
*
|
|
280
|
+
* @classification "P0"
|
|
281
|
+
*/
|
|
282
|
+
name: string;
|
|
283
|
+
/**
|
|
284
|
+
* Vehicle model (e.g., 'Model 3', 'Model Y'). Sourced from DB Vehicle.model. Matches VehicleState.model.
|
|
285
|
+
*
|
|
286
|
+
* @classification "P0"
|
|
287
|
+
*/
|
|
288
|
+
model: string;
|
|
289
|
+
/**
|
|
290
|
+
* Model year. Sourced from DB Vehicle.year. Matches VehicleState.year.
|
|
291
|
+
*
|
|
292
|
+
* @classification "P0"
|
|
293
|
+
*/
|
|
294
|
+
year: number;
|
|
295
|
+
/**
|
|
296
|
+
* Vehicle exterior color. Sourced from DB Vehicle.color. Matches VehicleState.color.
|
|
297
|
+
*
|
|
298
|
+
* @classification "P0"
|
|
299
|
+
*/
|
|
300
|
+
color: string;
|
|
301
|
+
/**
|
|
302
|
+
* Last 4 characters of the vehicle's 17-character VIN. The full VIN is never emitted on the list endpoint — vinLast4 is sufficient for human disambiguation in the catalog UI without exposing the full identifier. Empty string when the VIN is unknown.
|
|
303
|
+
*
|
|
304
|
+
* @classification "P1"
|
|
305
|
+
*/
|
|
306
|
+
vinLast4: string;
|
|
307
|
+
/**
|
|
308
|
+
* Derived vehicle status snapshot at the time of the last telemetry update. Same enum as VehicleState.status.
|
|
309
|
+
*
|
|
310
|
+
* @classification "P0"
|
|
311
|
+
*/
|
|
312
|
+
status: 'driving' | 'parked' | 'charging' | 'offline' | 'in_service';
|
|
313
|
+
/**
|
|
314
|
+
* Battery state of charge snapshot at the time of the last telemetry update. Same semantics as VehicleState.chargeLevel.
|
|
315
|
+
*
|
|
316
|
+
* @classification "P0"
|
|
317
|
+
* @unit "percent"
|
|
318
|
+
*/
|
|
319
|
+
chargeLevel: number;
|
|
320
|
+
/**
|
|
321
|
+
* Estimated remaining driving range snapshot at the time of the last telemetry update. Same semantics as VehicleState.estimatedRange.
|
|
322
|
+
*
|
|
323
|
+
* @classification "P0"
|
|
324
|
+
* @unit "miles"
|
|
325
|
+
*/
|
|
326
|
+
estimatedRange: number;
|
|
327
|
+
/**
|
|
328
|
+
* ISO 8601 timestamp of the most recent telemetry update applied to this vehicle. Same semantics as VehicleState.lastUpdated. Telemetry emits RFC 3339 UTC strings (e.g., '2026-05-25T17:30:00Z').
|
|
329
|
+
*
|
|
330
|
+
* @classification "P0"
|
|
331
|
+
*/
|
|
332
|
+
lastUpdated: string;
|
|
333
|
+
/**
|
|
334
|
+
* RBAC role the caller holds against this vehicle. v1 only emits 'owner' rows (every vehicle returned is one the caller owns via Vehicle.userId). The 'viewer' value is reserved for the viewer-merged invite-read pathway tracked as a follow-up — see rest-api.md §7.0 RBAC v1 implementation note.
|
|
335
|
+
*
|
|
336
|
+
* @classification "P0"
|
|
337
|
+
*/
|
|
338
|
+
role: 'owner' | 'viewer';
|
|
339
|
+
}
|
|
340
|
+
|
|
247
341
|
/**
|
|
248
342
|
* AUTO-GENERATED by scripts/codegen.mjs from the corresponding JSON Schema
|
|
249
343
|
* in ../schemas/. DO NOT EDIT BY HAND — re-run `npm run codegen` instead.
|
|
@@ -467,11 +561,11 @@ interface HeartbeatPayload {
|
|
|
467
561
|
*/
|
|
468
562
|
interface ErrorPayload {
|
|
469
563
|
/**
|
|
470
|
-
* Stable typed error code
|
|
564
|
+
* Stable typed error code. Shared enum across the WebSocket and REST transports so the SDK's CoreError is a single union (rest-api.md §4.1.1, §4.1.1.a; ws catalog websocket-protocol.md §6.1.1). Consumer SDKs map these to typed errors per FR-7.1 and MUST NOT string-match on the sibling `message` field. WS emits today: `auth_failed`, `auth_timeout`; the remaining WS values are PLANNED (divergences DV-02 / DV-07 / DV-08 in websocket-protocol.md §10). `not_found` and `invalid_request` are REST-only on the wire (the WS path enforces ownership via silent filtering and has no structured request bodies, rest-api.md §4.1.1.a) but are members of this shared enum by mandate so the SDK union is one enum across transports — they are NOT a WS drift (DV-20 enum slice). `service_unavailable` is intentionally NOT in this enum: it is REST-only and the WS 503 analogue is a close code, not a typed frame (rest-api.md:258); the SDK declares it as a REST-only variant on its side. `rate_limited` has two carriers: (a) HTTP 429 on the WS upgrade (per-IP, pre-auth) and (b) an `error` frame paired with WS close 4003 (per-user, post-auth) — the SDK treats both as the same typed error with the extended backoff in websocket-protocol.md §6.1.1 / §7.1.
|
|
471
565
|
*
|
|
472
566
|
* @classification "P0"
|
|
473
567
|
*/
|
|
474
|
-
code: 'auth_failed' | 'auth_timeout' | 'permission_denied' | 'vehicle_not_owned' | 'rate_limited' | 'internal_error' | 'snapshot_required';
|
|
568
|
+
code: 'auth_failed' | 'auth_timeout' | 'permission_denied' | 'vehicle_not_owned' | 'rate_limited' | 'internal_error' | 'snapshot_required' | 'not_found' | 'invalid_request';
|
|
475
569
|
/**
|
|
476
570
|
* Human-readable description for logs and developer tooling. P0 BUT MUST NOT contain P1 values (no GPS, no addresses, no tokens, no emails, no VINs unless redacted to ***XXXX). Per data-classification.md §2.1-2.2, error message construction sites MUST use opaque IDs only.
|
|
477
571
|
*
|
|
@@ -479,11 +573,11 @@ interface ErrorPayload {
|
|
|
479
573
|
*/
|
|
480
574
|
message: string;
|
|
481
575
|
/**
|
|
482
|
-
* Optional typed sub-code for branching consumer-visible UI when the primary code is ambiguous across carriers.
|
|
576
|
+
* Optional typed sub-code for branching consumer-visible UI when the primary code is ambiguous across carriers. v1 enum: `device_cap` (WS-only) and `reauth_required` (REST-only). `device_cap`: WS server rejected a connection because it breached the per-user cap (post-auth, close 4003); the error frame carries `subCode: "device_cap"` so SDKs surface an actionable 'Too many devices signed in' message instead of a generic rate-limit toast (per-IP HTTP 429 breaches carry no sub-code — see websocket-protocol.md §6.1.1). `reauth_required`: REST-only, emitted with `code: auth_failed` by rest-api.md §7.6 / §7.7 when the bearer token is valid but the most recent fresh OAuth sign-in is older than the recent-auth window — the SDK MUST surface this to the consumer's auth layer to trigger a fresh interactive sign-in and MUST NOT silently retry via getToken() (a silent refresh cannot advance the `auth_time` claim). Declared on this shared enum for single-union SDK typing; the WS transport never emits `reauth_required`.
|
|
483
577
|
*
|
|
484
578
|
* @classification "P0"
|
|
485
579
|
*/
|
|
486
|
-
subCode?: 'device_cap';
|
|
580
|
+
subCode?: 'device_cap' | 'reauth_required';
|
|
487
581
|
}
|
|
488
582
|
/**
|
|
489
583
|
* PLANNED — NOT accepted by the server today. Client->server request to begin or resume streaming a specific vehicle. Today the server implicitly subscribes the client to ALL vehicles owned by the authenticated user as part of the auth handshake (handler.go authenticateClient -> Authenticator.GetUserVehicles). Adding explicit subscribe/unsubscribe is tracked as divergence DV-07 in websocket-protocol.md §10. `sinceSeq` snapshot-resume depends on divergence DV-02 (envelope `seq`) landing first.
|
|
@@ -587,4 +681,4 @@ interface WebSocketEnvelope {
|
|
|
587
681
|
ts?: string;
|
|
588
682
|
}
|
|
589
683
|
|
|
590
|
-
export type { AuthOkPayload, AuthPayload, ConnectivityPayload, DriveEndedPayload, DriveStartedPayload, ErrorPayload, HeartbeatPayload, MessageType, PingPayload, PongPayload, SubscribePayload, UnsubscribePayload, VehicleState, VehicleUpdatePayload, WebSocketEnvelope, WebSocketMessages };
|
|
684
|
+
export type { AuthOkPayload, AuthPayload, ConnectivityPayload, DriveEndedPayload, DriveStartedPayload, ErrorPayload, HeartbeatPayload, MessageType, PingPayload, PongPayload, SubscribePayload, UnsubscribePayload, VehicleListResponse, VehicleState, VehicleSummary, VehicleUpdatePayload, WebSocketEnvelope, WebSocketMessages };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@myrobotaxi/contracts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Canonical wire-protocol schemas for the MyRoboTaxi platform. JSON Schema (draft-2020-12) + pre-generated TypeScript types. Consumed by SDKs (TS, Swift) and the Go telemetry server.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
}
|
|
39
39
|
},
|
|
40
40
|
"./schemas/vehicle-state.json": "./schemas/vehicle-state.schema.json",
|
|
41
|
+
"./schemas/vehicle-summary.json": "./schemas/vehicle-summary.schema.json",
|
|
41
42
|
"./schemas/ws-messages.json": "./schemas/ws-messages.schema.json",
|
|
42
43
|
"./schemas/ws-envelope.json": "./schemas/ws-envelope.schema.json"
|
|
43
44
|
},
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://myrobotaxi.com/schemas/vehicle-summary.schema.json",
|
|
4
|
+
"title": "VehicleListResponse",
|
|
5
|
+
"description": "Envelope returned by GET /api/vehicles. Wraps an array of VehicleSummary rows under the `items` key. Pagination fields are reserved per rest-api.md §7.0 and intentionally absent in v1. The envelope itself is part of the wire contract: consumers MUST NOT strip it silently.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": ["items"],
|
|
9
|
+
"properties": {
|
|
10
|
+
"items": {
|
|
11
|
+
"type": "array",
|
|
12
|
+
"description": "Per-vehicle summary rows for vehicles the caller has access to. Order is server-defined (currently ORDER BY Vehicle.createdAt ASC in the telemetry list query). An empty array means the caller has no vehicles (or is a v1 viewer-tier caller — see rest-api.md §7.0 RBAC v1 implementation note).",
|
|
13
|
+
"items": { "$ref": "#/$defs/VehicleSummary" }
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"$defs": {
|
|
17
|
+
"VehicleSummary": {
|
|
18
|
+
"title": "VehicleSummary",
|
|
19
|
+
"description": "Lean per-vehicle row returned by GET /api/vehicles. A list-view projection of VehicleState containing only the fields the catalog UI needs (identity, model/year/color, status, charge headline, last-updated). No GPS, no navigation, no climate, no encrypted-at-rest fields. Mirrors the Go `vehicleSummary` struct in telemetry/internal/telemetry/vehicles_list_handler.go and the `VehicleSummary` shape in telemetry/specs/rest.openapi.yaml. Use VehicleState for the full snapshot/WebSocket payload; use VehicleSummary for list endpoints.",
|
|
20
|
+
"type": "object",
|
|
21
|
+
"additionalProperties": false,
|
|
22
|
+
"required": [
|
|
23
|
+
"vehicleId",
|
|
24
|
+
"name",
|
|
25
|
+
"model",
|
|
26
|
+
"year",
|
|
27
|
+
"color",
|
|
28
|
+
"vinLast4",
|
|
29
|
+
"status",
|
|
30
|
+
"chargeLevel",
|
|
31
|
+
"estimatedRange",
|
|
32
|
+
"lastUpdated",
|
|
33
|
+
"role"
|
|
34
|
+
],
|
|
35
|
+
"properties": {
|
|
36
|
+
"vehicleId": {
|
|
37
|
+
"type": "string",
|
|
38
|
+
"description": "Opaque database identifier (cuid). NOT the VIN. All SDK API calls use this ID (FR-4.2). Matches VehicleState.vehicleId.",
|
|
39
|
+
"x-classification": "P0",
|
|
40
|
+
"examples": ["clxyz1234567890abcdef"]
|
|
41
|
+
},
|
|
42
|
+
"name": {
|
|
43
|
+
"type": "string",
|
|
44
|
+
"description": "User-assigned vehicle name from DB Vehicle.name. Matches VehicleState.name.",
|
|
45
|
+
"x-classification": "P0",
|
|
46
|
+
"examples": ["Optimus"]
|
|
47
|
+
},
|
|
48
|
+
"model": {
|
|
49
|
+
"type": "string",
|
|
50
|
+
"description": "Vehicle model (e.g., 'Model 3', 'Model Y'). Sourced from DB Vehicle.model. Matches VehicleState.model.",
|
|
51
|
+
"x-classification": "P0",
|
|
52
|
+
"examples": ["Model 3"]
|
|
53
|
+
},
|
|
54
|
+
"year": {
|
|
55
|
+
"type": "integer",
|
|
56
|
+
"description": "Model year. Sourced from DB Vehicle.year. Matches VehicleState.year.",
|
|
57
|
+
"x-classification": "P0",
|
|
58
|
+
"examples": [2024]
|
|
59
|
+
},
|
|
60
|
+
"color": {
|
|
61
|
+
"type": "string",
|
|
62
|
+
"description": "Vehicle exterior color. Sourced from DB Vehicle.color. Matches VehicleState.color.",
|
|
63
|
+
"x-classification": "P0",
|
|
64
|
+
"examples": ["Midnight Silver Metallic"]
|
|
65
|
+
},
|
|
66
|
+
"vinLast4": {
|
|
67
|
+
"type": "string",
|
|
68
|
+
"description": "Last 4 characters of the vehicle's 17-character VIN. The full VIN is never emitted on the list endpoint — vinLast4 is sufficient for human disambiguation in the catalog UI without exposing the full identifier. Empty string when the VIN is unknown.",
|
|
69
|
+
"x-classification": "P1",
|
|
70
|
+
"examples": ["3F5A"]
|
|
71
|
+
},
|
|
72
|
+
"status": {
|
|
73
|
+
"type": "string",
|
|
74
|
+
"enum": ["driving", "parked", "charging", "offline", "in_service"],
|
|
75
|
+
"description": "Derived vehicle status snapshot at the time of the last telemetry update. Same enum as VehicleState.status.",
|
|
76
|
+
"x-classification": "P0"
|
|
77
|
+
},
|
|
78
|
+
"chargeLevel": {
|
|
79
|
+
"type": "integer",
|
|
80
|
+
"description": "Battery state of charge snapshot at the time of the last telemetry update. Same semantics as VehicleState.chargeLevel.",
|
|
81
|
+
"x-classification": "P0",
|
|
82
|
+
"x-unit": "percent",
|
|
83
|
+
"minimum": 0,
|
|
84
|
+
"maximum": 100
|
|
85
|
+
},
|
|
86
|
+
"estimatedRange": {
|
|
87
|
+
"type": "integer",
|
|
88
|
+
"description": "Estimated remaining driving range snapshot at the time of the last telemetry update. Same semantics as VehicleState.estimatedRange.",
|
|
89
|
+
"x-classification": "P0",
|
|
90
|
+
"x-unit": "miles",
|
|
91
|
+
"minimum": 0
|
|
92
|
+
},
|
|
93
|
+
"lastUpdated": {
|
|
94
|
+
"type": "string",
|
|
95
|
+
"format": "date-time",
|
|
96
|
+
"description": "ISO 8601 timestamp of the most recent telemetry update applied to this vehicle. Same semantics as VehicleState.lastUpdated. Telemetry emits RFC 3339 UTC strings (e.g., '2026-05-25T17:30:00Z').",
|
|
97
|
+
"x-classification": "P0"
|
|
98
|
+
},
|
|
99
|
+
"role": {
|
|
100
|
+
"type": "string",
|
|
101
|
+
"enum": ["owner", "viewer"],
|
|
102
|
+
"description": "RBAC role the caller holds against this vehicle. v1 only emits 'owner' rows (every vehicle returned is one the caller owns via Vehicle.userId). The 'viewer' value is reserved for the viewer-merged invite-read pathway tracked as a follow-up — see rest-api.md §7.0 RBAC v1 implementation note.",
|
|
103
|
+
"x-classification": "P0"
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -213,7 +213,7 @@
|
|
|
213
213
|
"properties": {
|
|
214
214
|
"code": {
|
|
215
215
|
"type": "string",
|
|
216
|
-
"description": "Stable typed error code
|
|
216
|
+
"description": "Stable typed error code. Shared enum across the WebSocket and REST transports so the SDK's CoreError is a single union (rest-api.md §4.1.1, §4.1.1.a; ws catalog websocket-protocol.md §6.1.1). Consumer SDKs map these to typed errors per FR-7.1 and MUST NOT string-match on the sibling `message` field. WS emits today: `auth_failed`, `auth_timeout`; the remaining WS values are PLANNED (divergences DV-02 / DV-07 / DV-08 in websocket-protocol.md §10). `not_found` and `invalid_request` are REST-only on the wire (the WS path enforces ownership via silent filtering and has no structured request bodies, rest-api.md §4.1.1.a) but are members of this shared enum by mandate so the SDK union is one enum across transports — they are NOT a WS drift (DV-20 enum slice). `service_unavailable` is intentionally NOT in this enum: it is REST-only and the WS 503 analogue is a close code, not a typed frame (rest-api.md:258); the SDK declares it as a REST-only variant on its side. `rate_limited` has two carriers: (a) HTTP 429 on the WS upgrade (per-IP, pre-auth) and (b) an `error` frame paired with WS close 4003 (per-user, post-auth) — the SDK treats both as the same typed error with the extended backoff in websocket-protocol.md §6.1.1 / §7.1.",
|
|
217
217
|
"enum": [
|
|
218
218
|
"auth_failed",
|
|
219
219
|
"auth_timeout",
|
|
@@ -221,7 +221,9 @@
|
|
|
221
221
|
"vehicle_not_owned",
|
|
222
222
|
"rate_limited",
|
|
223
223
|
"internal_error",
|
|
224
|
-
"snapshot_required"
|
|
224
|
+
"snapshot_required",
|
|
225
|
+
"not_found",
|
|
226
|
+
"invalid_request"
|
|
225
227
|
],
|
|
226
228
|
"x-classification": "P0"
|
|
227
229
|
},
|
|
@@ -232,8 +234,8 @@
|
|
|
232
234
|
},
|
|
233
235
|
"subCode": {
|
|
234
236
|
"type": "string",
|
|
235
|
-
"description": "Optional typed sub-code for branching consumer-visible UI when the primary code is ambiguous across carriers.
|
|
236
|
-
"enum": ["device_cap"],
|
|
237
|
+
"description": "Optional typed sub-code for branching consumer-visible UI when the primary code is ambiguous across carriers. v1 enum: `device_cap` (WS-only) and `reauth_required` (REST-only). `device_cap`: WS server rejected a connection because it breached the per-user cap (post-auth, close 4003); the error frame carries `subCode: \"device_cap\"` so SDKs surface an actionable 'Too many devices signed in' message instead of a generic rate-limit toast (per-IP HTTP 429 breaches carry no sub-code — see websocket-protocol.md §6.1.1). `reauth_required`: REST-only, emitted with `code: auth_failed` by rest-api.md §7.6 / §7.7 when the bearer token is valid but the most recent fresh OAuth sign-in is older than the recent-auth window — the SDK MUST surface this to the consumer's auth layer to trigger a fresh interactive sign-in and MUST NOT silently retry via getToken() (a silent refresh cannot advance the `auth_time` claim). Declared on this shared enum for single-union SDK typing; the WS transport never emits `reauth_required`.",
|
|
238
|
+
"enum": ["device_cap", "reauth_required"],
|
|
237
239
|
"x-classification": "P0"
|
|
238
240
|
}
|
|
239
241
|
}
|