@huynle/hub 0.11.0 → 0.11.1
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/CHANGELOG.md +26 -0
- package/README.md +19 -5
- package/package.json +1 -1
- package/packages/claude-code/package.json +1 -1
- package/packages/claude-code/src/sessions.ts +4 -1
- package/packages/cli/dist/hub-cli.js +240 -83
- package/packages/cli/package.json +1 -1
- package/packages/cli/src/cli.ts +12 -7
- package/packages/cli/src/decisions.ts +52 -4
- package/packages/cli/src/format.ts +9 -0
- package/packages/cli/src/mcp.ts +20 -4
- package/packages/cli/src/team-intake-mcp.ts +2 -1
- package/packages/cli/src/teams-mcp.ts +7 -3
- package/packages/codex/package.json +1 -1
- package/packages/codex/src/sessions.ts +14 -3
- package/packages/node/package.json +1 -1
- package/packages/preset/package.json +1 -1
- package/packages/protocol/package.json +1 -1
- package/packages/protocol/schema/api/v1/_root.json +119 -0
- package/packages/protocol/schema/api/v1/account.json +419 -0
- package/packages/protocol/schema/api/v1/decisions.json +635 -0
- package/packages/protocol/schema/api/v1/discovery.json +110 -0
- package/packages/protocol/schema/api/v1/events.json +679 -0
- package/packages/protocol/schema/api/v1/session-actions.json +660 -0
- package/packages/protocol/schema/api/v1/sessions.json +2055 -0
- package/packages/protocol/schema/api/v1/speech.json +492 -0
- package/packages/protocol/schema/api/v1/unspecified.json +282 -0
- package/packages/protocol/schema/app-delivery/v1.schema.json +67 -5
- package/packages/protocol/schema/app-front/v1.schema.json +7 -3
- package/packages/protocol/src/api-v1.ts +8 -0
- package/packages/protocol/src/index.ts +2 -0
- package/packages/protocol/src/teams.ts +13 -1
- package/packages/runtime-openshell/package.json +1 -1
- package/packages/runtime-sdk/package.json +1 -1
- package/packages/sdk/package.json +1 -1
- package/packages/sdk/src/app-front.ts +2 -2
- package/packages/sdk/src/ask-fields.ts +76 -0
- package/packages/sdk/src/client.ts +11 -2
- package/packages/sdk/src/envelope.ts +3 -2
- package/packages/sdk/src/index.ts +1 -0
- package/packages/sdk/src/team-intake.ts +6 -0
- package/packages/sdk/src/teams.ts +2 -0
- package/packages/sdk/src/types.ts +36 -4
- package/packages/sdk/src/wake.ts +9 -4
- package/packages/spoke-sdk/package.json +1 -1
- package/src/central/agent/agent-limits.ts +185 -0
- package/src/central/agent/app-decisions.ts +6 -5
- package/src/central/agent/decisions.ts +130 -9
- package/src/central/agent/delivery.ts +134 -22
- package/src/central/agent/errors.ts +2 -1
- package/src/central/agent/events.ts +20 -2
- package/src/central/agent/launch-engine.ts +6 -3
- package/src/central/agent/message-limits.ts +5 -2
- package/src/central/agent/message-routes.ts +33 -6
- package/src/central/agent/messages.ts +7 -0
- package/src/central/agent/placement.ts +4 -2
- package/src/central/agent/read-routes.ts +5 -0
- package/src/central/agent/routes.ts +2 -0
- package/src/central/agent/subscriptions.ts +13 -4
- package/src/central/api-v1.ts +115 -0
- package/src/central/artifacts/store.ts +4 -2
- package/src/central/concierge/board-results.ts +2 -1
- package/src/central/concierge/notifier.ts +4 -2
- package/src/central/config.ts +20 -6
- package/src/central/health/classify.ts +209 -0
- package/src/central/http.ts +285 -23
- package/src/central/recording/index.ts +2 -1
- package/src/central/recording/schema.ts +2 -1
- package/src/central/registry.ts +34 -3
- package/src/central/teams/budgets.ts +144 -0
- package/src/central/teams/hop-stalls.ts +14 -6
- package/src/central/teams/intake.ts +38 -6
- package/src/central/teams/involvement.ts +95 -0
- package/src/central/teams/item-decisions.ts +60 -0
- package/src/central/teams/item-eligibility.ts +35 -0
- package/src/central/teams/item-stalls.ts +87 -0
- package/src/central/teams/loops.ts +40 -0
- package/src/central/teams/progress.ts +154 -0
- package/src/central/teams/routes.ts +2 -2
- package/src/central/teams/store.ts +21 -5
- package/src/central/teams/validation.ts +17 -6
- package/src/central/workspaces/coordinator.ts +3 -1
- package/src/spoke/hub-tool.ts +26 -11
- package/web/dist/assets/{ArtifactPage-C5MMqXLN.js → ArtifactPage-TbFJi59n.js} +1 -1
- package/web/dist/assets/{ArtifactPane-CXSCmhyJ.js → ArtifactPane-7D-M-Ich.js} +1 -1
- package/web/dist/assets/{ArtifactWorkbench-S0RxNGWy.js → ArtifactWorkbench-DlCLEjut.js} +1 -1
- package/web/dist/assets/{Diagram-BGmyRb-R.js → Diagram-PvOPetOI.js} +1 -1
- package/web/dist/assets/{Library-CFmMbXEa.js → Library-Cdi83pOV.js} +2 -2
- package/web/dist/assets/{ProfilesDestination-7jpOc2HM.js → ProfilesDestination-cryC7P6j.js} +1 -1
- package/web/dist/assets/TeamsPage-B4xrlGhp.js +1 -0
- package/web/dist/assets/Watchtower-60B1JX_J.js +2 -0
- package/web/dist/assets/index-DA0gKIzv.js +33 -0
- package/web/dist/assets/live-B2IfKm37.js +5 -0
- package/web/dist/assets/{live-BUofsQpz.css → live-De-kd3eW.css} +1 -1
- package/web/dist/assets/{renderer2d-B2Nh39UN.js → renderer2d-CsZnF3_o.js} +1 -1
- package/web/dist/assets/{renderer3d-CTYbljHH.js → renderer3d-BIMA0wFn.js} +2 -2
- package/web/dist/assets/{safe-area-CkhEclGo.js → safe-area-dtrnw9NF.js} +1 -1
- package/web/dist/index.html +1 -1
- package/web/dist/assets/TeamsPage-C1NGrUR-.js +0 -1
- package/web/dist/assets/Watchtower-DnvlJaU0.js +0 -2
- package/web/dist/assets/index-Da8SKXMw.js +0 -33
- package/web/dist/assets/live-BmqLASSo.js +0 -5
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
{
|
|
2
|
+
"paths": {
|
|
3
|
+
"/api/v1/auth": {
|
|
4
|
+
"get": {
|
|
5
|
+
"operationId": "getAuth",
|
|
6
|
+
"tags": ["account"],
|
|
7
|
+
"x-hub-access": "public",
|
|
8
|
+
"security": [],
|
|
9
|
+
"summary": "How this hub signs people in",
|
|
10
|
+
"description": "What a sign-in screen needs before anyone is signed in.",
|
|
11
|
+
"responses": {
|
|
12
|
+
"200": {
|
|
13
|
+
"description": "The hub's sign-in mode.",
|
|
14
|
+
"content": {
|
|
15
|
+
"application/json": {
|
|
16
|
+
"schema": {
|
|
17
|
+
"$ref": "#/components/schemas/AuthInfo"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"default": {
|
|
23
|
+
"$ref": "#/components/responses/Error"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"/api/v1/pair": {
|
|
29
|
+
"post": {
|
|
30
|
+
"operationId": "pairDevice",
|
|
31
|
+
"tags": ["account"],
|
|
32
|
+
"x-hub-access": "public",
|
|
33
|
+
"security": [],
|
|
34
|
+
"summary": "Pair a browser with a pairing code",
|
|
35
|
+
"description": "Trades a pairing code for a new device, whose secret comes back only as the HttpOnly device cookie (Set-Cookie). For browsers: the request must be same-origin. A native app redeems a link code instead (POST /api/v1/devices/redeem). Fails with 401 unauthorized for an unknown, used or expired code (codes last 5 minutes), 400 invalid for a device name longer than 64 characters, and 429 rate_limited after 10 failed attempts in a minute.",
|
|
36
|
+
"requestBody": {
|
|
37
|
+
"required": true,
|
|
38
|
+
"content": {
|
|
39
|
+
"application/json": {
|
|
40
|
+
"schema": {
|
|
41
|
+
"$ref": "#/components/schemas/PairRequest"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
"responses": {
|
|
47
|
+
"200": {
|
|
48
|
+
"description": "The new device. Its secret is in the Set-Cookie header, not in the body.",
|
|
49
|
+
"content": {
|
|
50
|
+
"application/json": {
|
|
51
|
+
"schema": {
|
|
52
|
+
"$ref": "#/components/schemas/PairedDevice"
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
"default": {
|
|
58
|
+
"$ref": "#/components/responses/Error"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
"/api/v1/devices/redeem": {
|
|
64
|
+
"post": {
|
|
65
|
+
"operationId": "redeemDeviceLink",
|
|
66
|
+
"tags": ["account"],
|
|
67
|
+
"x-hub-access": "public",
|
|
68
|
+
"security": [],
|
|
69
|
+
"summary": "Trade a link code for a device token",
|
|
70
|
+
"description": "How a native app signs in: it sends the single-use code of the console's \"Add the Hub app\" link and gets a device token, which it keeps and sends as `Authorization: Bearer`. The request carries no cookie, no bearer token and no Origin; the code is the credential. No cookie is set. Fails with 401 unauthorized for an unknown, used or expired code (codes last 5 minutes) and 400 invalid for a malformed public key (the code stays valid).",
|
|
71
|
+
"requestBody": {
|
|
72
|
+
"required": true,
|
|
73
|
+
"content": {
|
|
74
|
+
"application/json": {
|
|
75
|
+
"schema": {
|
|
76
|
+
"$ref": "#/components/schemas/RedeemLinkRequest"
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
"responses": {
|
|
82
|
+
"200": {
|
|
83
|
+
"description": "The new device and its token. The token is shown this once.",
|
|
84
|
+
"content": {
|
|
85
|
+
"application/json": {
|
|
86
|
+
"schema": {
|
|
87
|
+
"$ref": "#/components/schemas/LinkedDevice"
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
"default": {
|
|
93
|
+
"$ref": "#/components/responses/Error"
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
"/api/v1/me": {
|
|
99
|
+
"get": {
|
|
100
|
+
"operationId": "getMe",
|
|
101
|
+
"tags": ["account"],
|
|
102
|
+
"x-hub-access": "user",
|
|
103
|
+
"summary": "The signed-in device, its user and the hub",
|
|
104
|
+
"responses": {
|
|
105
|
+
"200": {
|
|
106
|
+
"description": "Who is asking, and which hub is answering.",
|
|
107
|
+
"content": {
|
|
108
|
+
"application/json": {
|
|
109
|
+
"schema": {
|
|
110
|
+
"$ref": "#/components/schemas/Me"
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
"default": {
|
|
116
|
+
"$ref": "#/components/responses/Error"
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
"/api/v1/devices": {
|
|
122
|
+
"get": {
|
|
123
|
+
"operationId": "listDevices",
|
|
124
|
+
"tags": ["account"],
|
|
125
|
+
"x-hub-access": "user",
|
|
126
|
+
"summary": "The user's devices",
|
|
127
|
+
"responses": {
|
|
128
|
+
"200": {
|
|
129
|
+
"description": "Every device of the user: paired browsers and linked apps.",
|
|
130
|
+
"content": {
|
|
131
|
+
"application/json": {
|
|
132
|
+
"schema": {
|
|
133
|
+
"$ref": "#/components/schemas/DeviceList"
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
"default": {
|
|
139
|
+
"$ref": "#/components/responses/Error"
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
"/api/v1/devices/link": {
|
|
145
|
+
"post": {
|
|
146
|
+
"operationId": "createDeviceLink",
|
|
147
|
+
"tags": ["account"],
|
|
148
|
+
"x-hub-access": "user",
|
|
149
|
+
"summary": "Issue a link code for a native app",
|
|
150
|
+
"description": "A single-use code that links a new device to the user, shown as a QR code or deep link. The request has no body. The code is redeemed at POST /api/v1/devices/redeem.",
|
|
151
|
+
"responses": {
|
|
152
|
+
"200": {
|
|
153
|
+
"description": "The code and where to redeem it.",
|
|
154
|
+
"content": {
|
|
155
|
+
"application/json": {
|
|
156
|
+
"schema": {
|
|
157
|
+
"$ref": "#/components/schemas/DeviceLink"
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
},
|
|
162
|
+
"default": {
|
|
163
|
+
"$ref": "#/components/responses/Error"
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
"/api/v1/devices/{id}": {
|
|
169
|
+
"delete": {
|
|
170
|
+
"operationId": "revokeDevice",
|
|
171
|
+
"tags": ["account"],
|
|
172
|
+
"x-hub-access": "user",
|
|
173
|
+
"summary": "Revoke one of the user's devices",
|
|
174
|
+
"description": "The device's cookie and token stop working. Fails with 404 not_found for an unknown device or another user's.",
|
|
175
|
+
"parameters": [
|
|
176
|
+
{
|
|
177
|
+
"name": "id",
|
|
178
|
+
"in": "path",
|
|
179
|
+
"required": true,
|
|
180
|
+
"description": "The device's ID.",
|
|
181
|
+
"schema": {
|
|
182
|
+
"type": "string"
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
],
|
|
186
|
+
"responses": {
|
|
187
|
+
"204": {
|
|
188
|
+
"description": "Revoked."
|
|
189
|
+
},
|
|
190
|
+
"default": {
|
|
191
|
+
"$ref": "#/components/responses/Error"
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
"/api/v1/logout": {
|
|
197
|
+
"post": {
|
|
198
|
+
"operationId": "logout",
|
|
199
|
+
"tags": ["account"],
|
|
200
|
+
"x-hub-access": "user",
|
|
201
|
+
"summary": "Sign this device out",
|
|
202
|
+
"description": "Removes the calling device: its cookie and token stop working, and the cookie is cleared (Set-Cookie). The request has no body.",
|
|
203
|
+
"responses": {
|
|
204
|
+
"204": {
|
|
205
|
+
"description": "Signed out."
|
|
206
|
+
},
|
|
207
|
+
"default": {
|
|
208
|
+
"$ref": "#/components/responses/Error"
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
},
|
|
214
|
+
"components": {
|
|
215
|
+
"schemas": {
|
|
216
|
+
"AuthInfo": {
|
|
217
|
+
"type": "object",
|
|
218
|
+
"required": ["mode", "signIn"],
|
|
219
|
+
"properties": {
|
|
220
|
+
"mode": {
|
|
221
|
+
"type": "string",
|
|
222
|
+
"description": "pairing: one owner, devices join with a pairing code. oidc: people sign in with the hub's identity provider.",
|
|
223
|
+
"x-hub-known": ["pairing", "oidc"]
|
|
224
|
+
},
|
|
225
|
+
"signIn": {
|
|
226
|
+
"type": ["string", "null"],
|
|
227
|
+
"description": "The path on this hub that starts a browser sign-in (oidc), or null (pairing)."
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
},
|
|
231
|
+
"PairRequest": {
|
|
232
|
+
"type": "object",
|
|
233
|
+
"required": ["code"],
|
|
234
|
+
"properties": {
|
|
235
|
+
"code": {
|
|
236
|
+
"type": "string",
|
|
237
|
+
"description": "The 6-digit pairing code. Spaces around it are ignored."
|
|
238
|
+
},
|
|
239
|
+
"deviceName": {
|
|
240
|
+
"type": "string",
|
|
241
|
+
"description": "A name for the device, 1 to 64 characters after trimming. \"Device\" when absent or empty."
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
},
|
|
245
|
+
"PairedDevice": {
|
|
246
|
+
"type": "object",
|
|
247
|
+
"required": ["device"],
|
|
248
|
+
"properties": {
|
|
249
|
+
"device": {
|
|
250
|
+
"$ref": "#/components/schemas/Device"
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
},
|
|
254
|
+
"RedeemLinkRequest": {
|
|
255
|
+
"type": "object",
|
|
256
|
+
"required": ["code"],
|
|
257
|
+
"properties": {
|
|
258
|
+
"code": {
|
|
259
|
+
"type": "string",
|
|
260
|
+
"description": "The link code, from the `code` parameter of the hubapp:// link."
|
|
261
|
+
},
|
|
262
|
+
"deviceName": {
|
|
263
|
+
"type": "string",
|
|
264
|
+
"description": "A name for the device. Control characters are dropped and it is cut to 64 characters. \"App\" when absent or empty."
|
|
265
|
+
},
|
|
266
|
+
"publicKey": {
|
|
267
|
+
"type": ["string", "null"],
|
|
268
|
+
"maxLength": 4096,
|
|
269
|
+
"description": "The public half of the device's signing key, PEM (BEGIN PUBLIC KEY) or its base64 body. Kept with the device for later strong approvals."
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
},
|
|
273
|
+
"LinkedDevice": {
|
|
274
|
+
"type": "object",
|
|
275
|
+
"required": ["device", "token"],
|
|
276
|
+
"properties": {
|
|
277
|
+
"device": {
|
|
278
|
+
"$ref": "#/components/schemas/Device"
|
|
279
|
+
},
|
|
280
|
+
"token": {
|
|
281
|
+
"type": "string",
|
|
282
|
+
"description": "The device token: the app's credential, sent as `Authorization: Bearer`."
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
},
|
|
286
|
+
"Device": {
|
|
287
|
+
"type": "object",
|
|
288
|
+
"required": ["id", "name", "created", "lastSeen"],
|
|
289
|
+
"properties": {
|
|
290
|
+
"id": {
|
|
291
|
+
"type": "string"
|
|
292
|
+
},
|
|
293
|
+
"name": {
|
|
294
|
+
"type": "string"
|
|
295
|
+
},
|
|
296
|
+
"created": {
|
|
297
|
+
"type": "integer",
|
|
298
|
+
"format": "int64",
|
|
299
|
+
"description": "When it was paired or linked, in epoch milliseconds."
|
|
300
|
+
},
|
|
301
|
+
"lastSeen": {
|
|
302
|
+
"type": "integer",
|
|
303
|
+
"format": "int64",
|
|
304
|
+
"description": "When the hub last saw it, in epoch milliseconds."
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
},
|
|
308
|
+
"User": {
|
|
309
|
+
"type": "object",
|
|
310
|
+
"required": ["id", "role"],
|
|
311
|
+
"properties": {
|
|
312
|
+
"id": {
|
|
313
|
+
"type": "string",
|
|
314
|
+
"description": "\"local\" for the owner of a pairing-mode hub."
|
|
315
|
+
},
|
|
316
|
+
"email": {
|
|
317
|
+
"type": "string",
|
|
318
|
+
"description": "Absent for the owner of a pairing-mode hub."
|
|
319
|
+
},
|
|
320
|
+
"name": {
|
|
321
|
+
"type": "string",
|
|
322
|
+
"description": "Absent when the identity provider gave none."
|
|
323
|
+
},
|
|
324
|
+
"role": {
|
|
325
|
+
"type": "string",
|
|
326
|
+
"x-hub-known": ["admin", "user"]
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
},
|
|
330
|
+
"Me": {
|
|
331
|
+
"type": "object",
|
|
332
|
+
"required": ["device", "user", "auth", "publicURL", "version"],
|
|
333
|
+
"properties": {
|
|
334
|
+
"device": {
|
|
335
|
+
"$ref": "#/components/schemas/Device"
|
|
336
|
+
},
|
|
337
|
+
"user": {
|
|
338
|
+
"$ref": "#/components/schemas/User"
|
|
339
|
+
},
|
|
340
|
+
"auth": {
|
|
341
|
+
"type": "string",
|
|
342
|
+
"description": "The hub's sign-in mode, as in AuthInfo.mode.",
|
|
343
|
+
"x-hub-known": ["pairing", "oidc"]
|
|
344
|
+
},
|
|
345
|
+
"publicURL": {
|
|
346
|
+
"type": "string",
|
|
347
|
+
"description": "The address the hub is reached at, without a trailing slash."
|
|
348
|
+
},
|
|
349
|
+
"version": {
|
|
350
|
+
"type": "string",
|
|
351
|
+
"description": "The hub's version."
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
},
|
|
355
|
+
"ListedDevice": {
|
|
356
|
+
"type": "object",
|
|
357
|
+
"description": "A device in the user's list: a Device, and whether it is the one asking.",
|
|
358
|
+
"required": ["id", "name", "created", "lastSeen", "current"],
|
|
359
|
+
"properties": {
|
|
360
|
+
"id": {
|
|
361
|
+
"type": "string"
|
|
362
|
+
},
|
|
363
|
+
"name": {
|
|
364
|
+
"type": "string"
|
|
365
|
+
},
|
|
366
|
+
"created": {
|
|
367
|
+
"type": "integer",
|
|
368
|
+
"format": "int64",
|
|
369
|
+
"description": "When it was paired or linked, in epoch milliseconds."
|
|
370
|
+
},
|
|
371
|
+
"lastSeen": {
|
|
372
|
+
"type": "integer",
|
|
373
|
+
"format": "int64",
|
|
374
|
+
"description": "When the hub last saw it, in epoch milliseconds."
|
|
375
|
+
},
|
|
376
|
+
"current": {
|
|
377
|
+
"type": "boolean",
|
|
378
|
+
"description": "True for the device that made this request."
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
},
|
|
382
|
+
"DeviceList": {
|
|
383
|
+
"type": "object",
|
|
384
|
+
"required": ["devices"],
|
|
385
|
+
"properties": {
|
|
386
|
+
"devices": {
|
|
387
|
+
"type": "array",
|
|
388
|
+
"items": {
|
|
389
|
+
"$ref": "#/components/schemas/ListedDevice"
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
},
|
|
394
|
+
"DeviceLink": {
|
|
395
|
+
"type": "object",
|
|
396
|
+
"required": ["code", "expiresAt", "hub", "url"],
|
|
397
|
+
"properties": {
|
|
398
|
+
"code": {
|
|
399
|
+
"type": "string",
|
|
400
|
+
"description": "The single-use link code."
|
|
401
|
+
},
|
|
402
|
+
"expiresAt": {
|
|
403
|
+
"type": "integer",
|
|
404
|
+
"format": "int64",
|
|
405
|
+
"description": "When the code stops working, in epoch milliseconds (5 minutes after it was issued)."
|
|
406
|
+
},
|
|
407
|
+
"hub": {
|
|
408
|
+
"type": "string",
|
|
409
|
+
"description": "The hub's public address, where the app redeems the code."
|
|
410
|
+
},
|
|
411
|
+
"url": {
|
|
412
|
+
"type": "string",
|
|
413
|
+
"description": "The deep link to show as a QR code: hubapp://link?hub=<hub>&code=<code>."
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
}
|