@allocator-one/harness-cli 1.15.0 → 1.15.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/spec/openapi.json CHANGED
@@ -8,7 +8,7 @@
8
8
  }
9
9
  },
10
10
  "info": {
11
- "description": "Internal JSON API for the Harness issue tracker.\n\nAuthenticate with a bearer credential:\n\n Authorization: Bearer <token>\n\nThree kinds are accepted. The first two require an active admin:\n\n- `aone_…` API tokens (admin → API tokens) carrying the\n `harness:read` and/or `harness:write` scope. Writes are attributed\n to the token's creator, displayed as the `actor`/token name.\n- User login tokens from the platform sign-in flow, as used by the\n browser extension and the Harness Drop app. Note: sign-in lives on\n the venture host (`POST https://venture.infra.one/api/v1/sign-in`),\n not on this API's host. These tokens act as the signed-in admin:\n both harness scopes, writes attributed and displayed as that user\n unless an `actor` is given.\n- `pxc_…` credentials of an outside expert invited to a plan, minted\n by the expert with a fresh TOTP code and valid for at most 30 days.\n They carry only the `harness:expert` scope, which no other route\n accepts, and reach only the expert's own assignments\n (`/api/v1/expert/assignments`), and on a step assigned to them its\n gate conditions, filtered to the gates they own, and a tick or\n untick of those gates. A step not assigned to them is 404, every\n other route 403 (`expert_bound_credential`). The expert's seat is\n re-read on every request: a revoked or expired seat, or a removed\n TOTP enrolment, answers 401.\n\nThe Operator endpoints (`/api/v1/operator/…`) admit every admin and\nmember of the credential's organization rather than staff alone, and\nneed the `operator:read` scope to read and `operator:write` for\nanything else. Login tokens carry both; `aone_…` tokens must be\nminted with them, bound to the organization.\n\nRequests are rate limited per client IP.\n",
11
+ "description": "Internal JSON API for the Harness issue tracker.\n\nAuthenticate with a bearer credential:\n\n Authorization: Bearer <token>\n\nThree kinds are accepted. The first two require an active admin:\n\n- `aone_…` API tokens (admin → API tokens) carrying the\n `harness:read` and/or `harness:write` scope. Writes are attributed\n to the token's creator, displayed as the `actor`/token name.\n- User login tokens from the platform sign-in flow, as used by the\n browser extension and the Harness Drop app. Note: sign-in lives on\n the venture host (`POST https://venture.infra.one/api/v1/sign-in`),\n not on this API's host. These tokens act as the signed-in admin:\n both harness scopes, writes attributed and displayed as that user\n unless an `actor` is given.\n- `pxc_…` credentials of an outside expert invited to a plan, minted\n by the expert with a fresh TOTP code and valid for at most 30 days.\n They carry only the `harness:expert` scope, which no other route\n accepts, and reach only the expert's own assignments\n (`/api/v1/expert/assignments`), and on a step assigned to them its\n gate conditions, filtered to the gates they own, and a tick or\n untick of those gates. A step not assigned to them is 404, every\n other route 403 (`expert_bound_credential`). The expert's seat is\n re-read on every request: a revoked or expired seat, or a removed\n TOTP enrolment, answers 401.\n\nThe Operator endpoints (`/api/v1/operator/…`) admit every admin and\nmember of the credential's organization rather than staff alone, and\nneed the `operator:read` scope to read and `operator:write` for\nanything else. Login tokens carry both; `aone_…` tokens must be\nminted with them, bound to the organization.\n\n`harness login` mints one of two login credentials, chosen by the\nserver from the person's standing in the organization they pick:\nHarness staff get the full credential (`harness-cli`), and any other\nadmin or member Operator serves gets an Operator-only one\n(`operator-cli`) carrying `operator:read` and `operator:write`\nalone. The Operator-only credential reaches the Operator endpoints\nand `/api/v1/session` and is refused (403) everywhere else.\n\nRequests are rate limited per client IP.\n",
12
12
  "title": "Harness API",
13
13
  "version": "1.0"
14
14
  },
@@ -194,7 +194,7 @@
194
194
  "get": {
195
195
  "callbacks": {},
196
196
  "deprecated": false,
197
- "description": "Requires the `harness:read` scope.",
197
+ "description": "Requires the `harness:read` scope. Comments are returned oldest-first within each page. Follow before=<oldest comment id> while meta.has_more is true to read older pages. Timestamp ties are ordered by comment id.",
198
198
  "parameters": [
199
199
  {
200
200
  "description": "Issue identifier, e.g. ALL-4901 or CLI-12 (issues minted before team-prefixed numbering carry IO-)",
@@ -204,6 +204,26 @@
204
204
  "schema": {
205
205
  "type": "string"
206
206
  }
207
+ },
208
+ {
209
+ "description": "Number of comments in each page (default 50, maximum 200).",
210
+ "in": "query",
211
+ "name": "limit",
212
+ "required": false,
213
+ "schema": {
214
+ "type": "integer",
215
+ "minimum": 1,
216
+ "maximum": 200
217
+ }
218
+ },
219
+ {
220
+ "description": "Oldest comment id from the preceding page; returns comments before its timestamp/id cursor.",
221
+ "in": "query",
222
+ "name": "before",
223
+ "required": false,
224
+ "schema": {
225
+ "type": "string"
226
+ }
207
227
  }
208
228
  ],
209
229
  "responses": {
@@ -4909,7 +4929,7 @@
4909
4929
  "post": {
4910
4930
  "callbacks": {},
4911
4931
  "deprecated": false,
4912
- "description": "Requires the `none (the code is the credential)` scope. Unauthenticated, tightly IP-rate-limited. Redeems the 60-second single-use code from the /cli/login browser handoff for a 30-day login token; the PKCE code_verifier must hash to the challenge the code was minted with.",
4932
+ "description": "Requires the `none (the code is the credential)` scope. Unauthenticated, tightly IP-rate-limited. Redeems the 60-second single-use code from the /cli/login browser handoff for a 30-day login token; the PKCE code_verifier must hash to the challenge the code was minted with. `kind` is the credential the server minted: `harness-cli` for Harness staff, `operator-cli` (Operator only) for any other admin or member Operator serves in the chosen organization. The person's standing is checked again here, so a code whose holder lost it is refused.",
4913
4933
  "parameters": [],
4914
4934
  "requestBody": {
4915
4935
  "content": {
@@ -4933,13 +4953,57 @@
4933
4953
  },
4934
4954
  "responses": {
4935
4955
  "200": {
4936
- "description": "Success"
4956
+ "description": "Success",
4957
+ "content": {
4958
+ "application/json": {
4959
+ "schema": {
4960
+ "properties": {
4961
+ "data": {
4962
+ "properties": {
4963
+ "email": {
4964
+ "type": "string"
4965
+ },
4966
+ "kind": {
4967
+ "description": "`harness-cli`, the full login credential, or `operator-cli`, the Operator-only one",
4968
+ "enum": [
4969
+ "harness-cli",
4970
+ "operator-cli"
4971
+ ],
4972
+ "type": "string"
4973
+ },
4974
+ "token": {
4975
+ "description": "The login credential; shown once",
4976
+ "type": "string"
4977
+ },
4978
+ "token_type": {
4979
+ "enum": [
4980
+ "bearer"
4981
+ ],
4982
+ "type": "string"
4983
+ }
4984
+ },
4985
+ "required": [
4986
+ "token",
4987
+ "token_type",
4988
+ "email",
4989
+ "kind"
4990
+ ],
4991
+ "type": "object"
4992
+ }
4993
+ },
4994
+ "required": [
4995
+ "data"
4996
+ ],
4997
+ "type": "object"
4998
+ }
4999
+ }
5000
+ }
4937
5001
  },
4938
5002
  "400": {
4939
5003
  "description": "Bad request"
4940
5004
  },
4941
5005
  "401": {
4942
- "description": "Invalid, expired, used, or verifier-mismatched code"
5006
+ "description": "Invalid, expired, used, or verifier-mismatched code, or the person's access changed"
4943
5007
  },
4944
5008
  "403": {
4945
5009
  "description": "Token not permitted (org-scoped, non-admin, or missing scope)"
@@ -5062,11 +5126,39 @@
5062
5126
  "delete": {
5063
5127
  "callbacks": {},
5064
5128
  "deprecated": false,
5065
- "description": "Requires the `harness:read` scope. Logout for the harness CLI: revokes the bearer login token making the request. aone_ API tokens are refused (400) — manage those in the admin UI.",
5129
+ "description": "Requires a login credential of either kind — the full one carries `harness:read`, the Operator-only one `operator:read` — held by someone with standing in its organization; an `aone_` token needs `harness:read` and staff standing. Logout for the harness CLI: revokes the login credential making the request, either kind. aone_ API tokens are refused (400) — manage those in the admin UI.",
5066
5130
  "parameters": [],
5067
5131
  "responses": {
5068
5132
  "200": {
5069
- "description": "Success"
5133
+ "description": "Success",
5134
+ "content": {
5135
+ "application/json": {
5136
+ "schema": {
5137
+ "additionalProperties": false,
5138
+ "properties": {
5139
+ "data": {
5140
+ "additionalProperties": false,
5141
+ "properties": {
5142
+ "revoked": {
5143
+ "enum": [
5144
+ true
5145
+ ],
5146
+ "type": "boolean"
5147
+ }
5148
+ },
5149
+ "required": [
5150
+ "revoked"
5151
+ ],
5152
+ "type": "object"
5153
+ }
5154
+ },
5155
+ "required": [
5156
+ "data"
5157
+ ],
5158
+ "type": "object"
5159
+ }
5160
+ }
5161
+ }
5070
5162
  },
5071
5163
  "400": {
5072
5164
  "description": "Bad request"
@@ -5086,6 +5178,121 @@
5086
5178
  },
5087
5179
  "summary": "Revoke the presented login token",
5088
5180
  "tags": []
5181
+ },
5182
+ "get": {
5183
+ "callbacks": {},
5184
+ "deprecated": false,
5185
+ "description": "Requires a login credential of either kind — the full one carries `harness:read`, the Operator-only one `operator:read` — held by someone with standing in its organization; an `aone_` token needs `harness:read` and staff standing. whoami for the harness CLI: the login credential making the request — the user it acts as, the organization it is bound to, its kind, its scopes, and when it expires. aone_ API tokens are refused (400) — manage those in the admin UI.",
5186
+ "parameters": [],
5187
+ "responses": {
5188
+ "200": {
5189
+ "content": {
5190
+ "application/json": {
5191
+ "schema": {
5192
+ "additionalProperties": false,
5193
+ "properties": {
5194
+ "data": {
5195
+ "additionalProperties": false,
5196
+ "properties": {
5197
+ "expires_at": {
5198
+ "format": "date-time",
5199
+ "type": "string"
5200
+ },
5201
+ "kind": {
5202
+ "description": "`harness-cli`, the full login credential, or `operator-cli`, the Operator-only one",
5203
+ "enum": [
5204
+ "harness-cli",
5205
+ "operator-cli"
5206
+ ],
5207
+ "type": "string"
5208
+ },
5209
+ "org": {
5210
+ "additionalProperties": false,
5211
+ "properties": {
5212
+ "id": {
5213
+ "format": "uuid",
5214
+ "type": "string"
5215
+ },
5216
+ "name": {
5217
+ "type": "string"
5218
+ },
5219
+ "slug": {
5220
+ "type": "string"
5221
+ }
5222
+ },
5223
+ "required": [
5224
+ "id",
5225
+ "slug",
5226
+ "name"
5227
+ ],
5228
+ "type": "object"
5229
+ },
5230
+ "scopes": {
5231
+ "items": {
5232
+ "type": "string"
5233
+ },
5234
+ "type": "array"
5235
+ },
5236
+ "user": {
5237
+ "additionalProperties": false,
5238
+ "properties": {
5239
+ "email": {
5240
+ "type": "string"
5241
+ },
5242
+ "id": {
5243
+ "format": "uuid",
5244
+ "type": "string"
5245
+ },
5246
+ "name": {
5247
+ "nullable": true,
5248
+ "type": "string"
5249
+ }
5250
+ },
5251
+ "required": [
5252
+ "id",
5253
+ "name",
5254
+ "email"
5255
+ ],
5256
+ "type": "object"
5257
+ }
5258
+ },
5259
+ "required": [
5260
+ "kind",
5261
+ "scopes",
5262
+ "expires_at",
5263
+ "user",
5264
+ "org"
5265
+ ],
5266
+ "type": "object"
5267
+ }
5268
+ },
5269
+ "required": [
5270
+ "data"
5271
+ ],
5272
+ "type": "object"
5273
+ }
5274
+ }
5275
+ },
5276
+ "description": "Success"
5277
+ },
5278
+ "400": {
5279
+ "description": "Bad request"
5280
+ },
5281
+ "401": {
5282
+ "description": "Missing or invalid token"
5283
+ },
5284
+ "403": {
5285
+ "description": "Token not permitted (org-scoped, non-admin, or missing scope)"
5286
+ },
5287
+ "404": {
5288
+ "description": "Not found"
5289
+ },
5290
+ "422": {
5291
+ "description": "Validation error"
5292
+ }
5293
+ },
5294
+ "summary": "Describe the presented login token",
5295
+ "tags": []
5089
5296
  }
5090
5297
  },
5091
5298
  "/api/v1/issues/{identifier}/conditions": {
@@ -5112,180 +5319,294 @@
5112
5319
  "properties": {
5113
5320
  "data": {
5114
5321
  "items": {
5115
- "additionalProperties": false,
5116
- "properties": {
5117
- "id": {
5118
- "format": "uuid",
5119
- "type": "string"
5120
- },
5121
- "inserted_at": {
5122
- "format": "date-time",
5123
- "type": "string"
5124
- },
5125
- "issue_id": {
5126
- "format": "uuid",
5127
- "type": "string"
5128
- },
5129
- "key": {
5130
- "description": "A gate's key; null without one or for other kinds",
5131
- "nullable": true,
5132
- "type": "string"
5133
- },
5134
- "kind": {
5135
- "enum": [
5136
- "not_before",
5137
- "gate",
5138
- "event"
5139
- ],
5140
- "type": "string"
5141
- },
5142
- "label": {
5143
- "description": "A gate's label; null for other kinds",
5144
- "nullable": true,
5145
- "type": "string"
5146
- },
5147
- "not_before": {
5148
- "description": "A `not_before` condition's instant; null for other kinds",
5149
- "format": "date-time",
5150
- "nullable": true,
5151
- "type": "string"
5152
- },
5153
- "owner": {
5322
+ "oneOf": [
5323
+ {
5154
5324
  "additionalProperties": false,
5155
- "description": "Who ticks the gate; null for an unowned gate or another kind",
5156
- "nullable": true,
5157
5325
  "properties": {
5158
- "email": {
5159
- "description": "For `expert`",
5160
- "nullable": true,
5326
+ "id": {
5327
+ "format": "uuid",
5161
5328
  "type": "string"
5162
5329
  },
5163
- "kind": {
5164
- "enum": [
5165
- "role",
5166
- "user",
5167
- "expert"
5168
- ],
5330
+ "inserted_at": {
5331
+ "format": "date-time",
5169
5332
  "type": "string"
5170
5333
  },
5171
- "label": {
5172
- "description": "The role's name, the member's name or the expert's email",
5334
+ "issue_id": {
5335
+ "format": "uuid",
5173
5336
  "type": "string"
5174
5337
  },
5175
- "ref": {
5176
- "description": "The owner as a plan document names it; null once a member owner's account is deleted",
5338
+ "key": {
5339
+ "description": "A gate's key; null without one or for other kinds",
5177
5340
  "nullable": true,
5178
5341
  "type": "string"
5179
5342
  },
5180
- "role": {
5181
- "description": "For `role`",
5343
+ "kind": {
5182
5344
  "enum": [
5183
- "gp",
5184
- "compliance_officer",
5185
- "valuer",
5186
- "accountant",
5187
- "auditor",
5188
- "counsel"
5345
+ "not_before",
5346
+ "gate",
5347
+ "event"
5189
5348
  ],
5349
+ "type": "string"
5350
+ },
5351
+ "label": {
5352
+ "description": "A gate's label; null for other kinds",
5190
5353
  "nullable": true,
5191
5354
  "type": "string"
5192
5355
  },
5193
- "user_id": {
5194
- "description": "For `user`; null once the account is deleted",
5195
- "format": "uuid",
5356
+ "not_before": {
5357
+ "description": "A `not_before` condition's instant; null for other kinds",
5358
+ "format": "date-time",
5196
5359
  "nullable": true,
5197
5360
  "type": "string"
5198
- }
5199
- },
5200
- "required": [
5201
- "kind",
5202
- "ref",
5203
- "role",
5204
- "user_id",
5205
- "email",
5206
- "label"
5207
- ],
5208
- "type": "object"
5209
- },
5210
- "satisfied": {
5211
- "type": "boolean"
5212
- },
5213
- "satisfied_as_role": {
5214
- "description": "The fund-team role an owned gate was ticked as",
5215
- "enum": [
5216
- "gp",
5217
- "compliance_officer",
5218
- "valuer",
5219
- "accountant",
5220
- "auditor",
5221
- "counsel"
5222
- ],
5223
- "nullable": true,
5224
- "type": "string"
5225
- },
5226
- "satisfied_at": {
5227
- "format": "date-time",
5228
- "nullable": true,
5229
- "type": "string"
5230
- },
5231
- "satisfied_by": {
5232
- "description": "Who ticked a gate; null otherwise",
5233
- "nullable": true,
5234
- "properties": {
5235
- "email": {
5361
+ },
5362
+ "owner": {
5363
+ "additionalProperties": false,
5364
+ "description": "Who ticks the gate; null for an unowned gate or another kind",
5365
+ "nullable": true,
5366
+ "properties": {
5367
+ "email": {
5368
+ "description": "For `expert`",
5369
+ "nullable": true,
5370
+ "type": "string"
5371
+ },
5372
+ "kind": {
5373
+ "enum": [
5374
+ "role",
5375
+ "user",
5376
+ "expert"
5377
+ ],
5378
+ "type": "string"
5379
+ },
5380
+ "label": {
5381
+ "description": "The role's name, the member's name or the expert's email",
5382
+ "type": "string"
5383
+ },
5384
+ "ref": {
5385
+ "description": "The owner as a plan document names it; null once a member owner's account is deleted",
5386
+ "nullable": true,
5387
+ "type": "string"
5388
+ },
5389
+ "role": {
5390
+ "description": "For `role`",
5391
+ "enum": [
5392
+ "gp",
5393
+ "compliance_officer",
5394
+ "valuer",
5395
+ "accountant",
5396
+ "auditor",
5397
+ "counsel"
5398
+ ],
5399
+ "nullable": true,
5400
+ "type": "string"
5401
+ },
5402
+ "user_id": {
5403
+ "description": "For `user`; null once the account is deleted",
5404
+ "format": "uuid",
5405
+ "nullable": true,
5406
+ "type": "string"
5407
+ }
5408
+ },
5409
+ "required": [
5410
+ "kind",
5411
+ "ref",
5412
+ "role",
5413
+ "user_id",
5414
+ "email",
5415
+ "label"
5416
+ ],
5417
+ "type": "object"
5418
+ },
5419
+ "satisfied": {
5420
+ "type": "boolean"
5421
+ },
5422
+ "satisfied_as_role": {
5423
+ "description": "The fund-team role an owned gate was ticked as",
5424
+ "enum": [
5425
+ "gp",
5426
+ "compliance_officer",
5427
+ "valuer",
5428
+ "accountant",
5429
+ "auditor",
5430
+ "counsel"
5431
+ ],
5236
5432
  "nullable": true,
5237
5433
  "type": "string"
5238
5434
  },
5239
- "id": {
5240
- "format": "uuid",
5435
+ "satisfied_at": {
5436
+ "format": "date-time",
5241
5437
  "nullable": true,
5242
5438
  "type": "string"
5243
5439
  },
5244
- "name": {
5440
+ "satisfied_by": {
5441
+ "description": "Who ticked a gate; null otherwise",
5442
+ "nullable": true,
5443
+ "properties": {
5444
+ "email": {
5445
+ "nullable": true,
5446
+ "type": "string"
5447
+ },
5448
+ "id": {
5449
+ "format": "uuid",
5450
+ "nullable": true,
5451
+ "type": "string"
5452
+ },
5453
+ "name": {
5454
+ "nullable": true,
5455
+ "type": "string"
5456
+ }
5457
+ },
5458
+ "required": [
5459
+ "id",
5460
+ "name",
5461
+ "email"
5462
+ ],
5463
+ "type": "object"
5464
+ },
5465
+ "satisfied_by_kind": {
5466
+ "description": "What satisfied it: a gate's person (`user`) or outside expert (`expert`), an event condition's system event (`event`), a not-before instant's clock (`system`); null while unsatisfied, or for a gate whose record of who ticked it is gone",
5467
+ "enum": [
5468
+ "user",
5469
+ "expert",
5470
+ "event",
5471
+ "system"
5472
+ ],
5245
5473
  "nullable": true,
5246
5474
  "type": "string"
5475
+ },
5476
+ "updated_at": {
5477
+ "format": "date-time",
5478
+ "type": "string"
5247
5479
  }
5248
5480
  },
5249
5481
  "required": [
5250
5482
  "id",
5251
- "name",
5252
- "email"
5483
+ "issue_id",
5484
+ "kind",
5485
+ "key",
5486
+ "label",
5487
+ "not_before",
5488
+ "owner",
5489
+ "satisfied",
5490
+ "satisfied_at",
5491
+ "satisfied_by",
5492
+ "satisfied_by_kind",
5493
+ "satisfied_as_role",
5494
+ "inserted_at",
5495
+ "updated_at"
5253
5496
  ],
5254
5497
  "type": "object"
5255
5498
  },
5256
- "satisfied_by_kind": {
5257
- "description": "What satisfied it: a gate's person (`user`) or outside expert (`expert`), an event condition's system event (`event`), a not-before instant's clock (`system`); null while unsatisfied, or for a gate whose record of who ticked it is gone",
5258
- "enum": [
5259
- "user",
5260
- "expert",
5261
- "event",
5262
- "system"
5499
+ {
5500
+ "additionalProperties": false,
5501
+ "properties": {
5502
+ "id": {
5503
+ "format": "uuid",
5504
+ "type": "string"
5505
+ },
5506
+ "issue_id": {
5507
+ "format": "uuid",
5508
+ "type": "string"
5509
+ },
5510
+ "key": {
5511
+ "description": "The gate's key; null without one",
5512
+ "nullable": true,
5513
+ "type": "string"
5514
+ },
5515
+ "kind": {
5516
+ "enum": [
5517
+ "gate"
5518
+ ],
5519
+ "type": "string"
5520
+ },
5521
+ "label": {
5522
+ "nullable": true,
5523
+ "type": "string"
5524
+ },
5525
+ "owner": {
5526
+ "additionalProperties": false,
5527
+ "description": "A role the expert holds, or the expert themselves",
5528
+ "nullable": true,
5529
+ "properties": {
5530
+ "kind": {
5531
+ "enum": [
5532
+ "role",
5533
+ "expert"
5534
+ ],
5535
+ "type": "string"
5536
+ },
5537
+ "role": {
5538
+ "description": "For `role`",
5539
+ "enum": [
5540
+ "gp",
5541
+ "compliance_officer",
5542
+ "valuer",
5543
+ "accountant",
5544
+ "auditor",
5545
+ "counsel"
5546
+ ],
5547
+ "type": "string"
5548
+ }
5549
+ },
5550
+ "required": [
5551
+ "kind"
5552
+ ],
5553
+ "type": "object"
5554
+ },
5555
+ "satisfied": {
5556
+ "type": "boolean"
5557
+ },
5558
+ "satisfied_at": {
5559
+ "format": "date-time",
5560
+ "nullable": true,
5561
+ "type": "string"
5562
+ },
5563
+ "satisfied_by": {
5564
+ "additionalProperties": false,
5565
+ "description": "Who ticked it, never by name: `you`, the `role` it was ticked as, or for a tick without a role only `expert` or `member`; null while unsatisfied",
5566
+ "nullable": true,
5567
+ "properties": {
5568
+ "kind": {
5569
+ "enum": [
5570
+ "you",
5571
+ "role",
5572
+ "expert",
5573
+ "member"
5574
+ ],
5575
+ "type": "string"
5576
+ },
5577
+ "role": {
5578
+ "description": "For `role`: the role it was ticked as",
5579
+ "enum": [
5580
+ "gp",
5581
+ "compliance_officer",
5582
+ "valuer",
5583
+ "accountant",
5584
+ "auditor",
5585
+ "counsel"
5586
+ ],
5587
+ "type": "string"
5588
+ }
5589
+ },
5590
+ "required": [
5591
+ "kind"
5592
+ ],
5593
+ "type": "object"
5594
+ }
5595
+ },
5596
+ "required": [
5597
+ "id",
5598
+ "issue_id",
5599
+ "kind",
5600
+ "key",
5601
+ "label",
5602
+ "owner",
5603
+ "satisfied",
5604
+ "satisfied_at",
5605
+ "satisfied_by"
5263
5606
  ],
5264
- "nullable": true,
5265
- "type": "string"
5266
- },
5267
- "updated_at": {
5268
- "format": "date-time",
5269
- "type": "string"
5607
+ "type": "object"
5270
5608
  }
5271
- },
5272
- "required": [
5273
- "id",
5274
- "issue_id",
5275
- "kind",
5276
- "key",
5277
- "label",
5278
- "not_before",
5279
- "owner",
5280
- "satisfied",
5281
- "satisfied_at",
5282
- "satisfied_by",
5283
- "satisfied_by_kind",
5284
- "satisfied_as_role",
5285
- "inserted_at",
5286
- "updated_at"
5287
- ],
5288
- "type": "object"
5609
+ ]
5289
5610
  },
5290
5611
  "type": "array"
5291
5612
  }
@@ -5293,7 +5614,8 @@
5293
5614
  "required": [
5294
5615
  "data"
5295
5616
  ],
5296
- "type": "object"
5617
+ "type": "object",
5618
+ "additionalProperties": false
5297
5619
  }
5298
5620
  }
5299
5621
  },
@@ -6101,73 +6423,108 @@
6101
6423
  "schema": {
6102
6424
  "properties": {
6103
6425
  "data": {
6104
- "additionalProperties": false,
6105
- "properties": {
6106
- "id": {
6107
- "format": "uuid",
6108
- "type": "string"
6109
- },
6110
- "inserted_at": {
6111
- "format": "date-time",
6112
- "type": "string"
6113
- },
6114
- "issue_id": {
6115
- "format": "uuid",
6116
- "type": "string"
6117
- },
6118
- "key": {
6119
- "description": "A gate's key; null without one or for other kinds",
6120
- "nullable": true,
6121
- "type": "string"
6122
- },
6123
- "kind": {
6124
- "enum": [
6125
- "not_before",
6126
- "gate",
6127
- "event"
6128
- ],
6129
- "type": "string"
6130
- },
6131
- "label": {
6132
- "description": "A gate's label; null for other kinds",
6133
- "nullable": true,
6134
- "type": "string"
6135
- },
6136
- "not_before": {
6137
- "description": "A `not_before` condition's instant; null for other kinds",
6138
- "format": "date-time",
6139
- "nullable": true,
6140
- "type": "string"
6141
- },
6142
- "owner": {
6426
+ "oneOf": [
6427
+ {
6143
6428
  "additionalProperties": false,
6144
- "description": "Who ticks the gate; null for an unowned gate or another kind",
6145
- "nullable": true,
6146
6429
  "properties": {
6147
- "email": {
6148
- "description": "For `expert`",
6430
+ "id": {
6431
+ "format": "uuid",
6432
+ "type": "string"
6433
+ },
6434
+ "inserted_at": {
6435
+ "format": "date-time",
6436
+ "type": "string"
6437
+ },
6438
+ "issue_id": {
6439
+ "format": "uuid",
6440
+ "type": "string"
6441
+ },
6442
+ "key": {
6443
+ "description": "A gate's key; null without one or for other kinds",
6149
6444
  "nullable": true,
6150
6445
  "type": "string"
6151
6446
  },
6152
6447
  "kind": {
6153
6448
  "enum": [
6449
+ "not_before",
6450
+ "gate",
6451
+ "event"
6452
+ ],
6453
+ "type": "string"
6454
+ },
6455
+ "label": {
6456
+ "description": "A gate's label; null for other kinds",
6457
+ "nullable": true,
6458
+ "type": "string"
6459
+ },
6460
+ "not_before": {
6461
+ "description": "A `not_before` condition's instant; null for other kinds",
6462
+ "format": "date-time",
6463
+ "nullable": true,
6464
+ "type": "string"
6465
+ },
6466
+ "owner": {
6467
+ "additionalProperties": false,
6468
+ "description": "Who ticks the gate; null for an unowned gate or another kind",
6469
+ "nullable": true,
6470
+ "properties": {
6471
+ "email": {
6472
+ "description": "For `expert`",
6473
+ "nullable": true,
6474
+ "type": "string"
6475
+ },
6476
+ "kind": {
6477
+ "enum": [
6478
+ "role",
6479
+ "user",
6480
+ "expert"
6481
+ ],
6482
+ "type": "string"
6483
+ },
6484
+ "label": {
6485
+ "description": "The role's name, the member's name or the expert's email",
6486
+ "type": "string"
6487
+ },
6488
+ "ref": {
6489
+ "description": "The owner as a plan document names it; null once a member owner's account is deleted",
6490
+ "nullable": true,
6491
+ "type": "string"
6492
+ },
6493
+ "role": {
6494
+ "description": "For `role`",
6495
+ "enum": [
6496
+ "gp",
6497
+ "compliance_officer",
6498
+ "valuer",
6499
+ "accountant",
6500
+ "auditor",
6501
+ "counsel"
6502
+ ],
6503
+ "nullable": true,
6504
+ "type": "string"
6505
+ },
6506
+ "user_id": {
6507
+ "description": "For `user`; null once the account is deleted",
6508
+ "format": "uuid",
6509
+ "nullable": true,
6510
+ "type": "string"
6511
+ }
6512
+ },
6513
+ "required": [
6514
+ "kind",
6515
+ "ref",
6154
6516
  "role",
6155
- "user",
6156
- "expert"
6517
+ "user_id",
6518
+ "email",
6519
+ "label"
6157
6520
  ],
6158
- "type": "string"
6159
- },
6160
- "label": {
6161
- "description": "The role's name, the member's name or the expert's email",
6162
- "type": "string"
6521
+ "type": "object"
6163
6522
  },
6164
- "ref": {
6165
- "description": "The owner as a plan document names it; null once a member owner's account is deleted",
6166
- "nullable": true,
6167
- "type": "string"
6523
+ "satisfied": {
6524
+ "type": "boolean"
6168
6525
  },
6169
- "role": {
6170
- "description": "For `role`",
6526
+ "satisfied_as_role": {
6527
+ "description": "The fund-team role an owned gate was ticked as",
6171
6528
  "enum": [
6172
6529
  "gp",
6173
6530
  "compliance_officer",
@@ -6179,108 +6536,188 @@
6179
6536
  "nullable": true,
6180
6537
  "type": "string"
6181
6538
  },
6182
- "user_id": {
6183
- "description": "For `user`; null once the account is deleted",
6184
- "format": "uuid",
6539
+ "satisfied_at": {
6540
+ "format": "date-time",
6541
+ "nullable": true,
6542
+ "type": "string"
6543
+ },
6544
+ "satisfied_by": {
6545
+ "description": "Who ticked a gate; null otherwise",
6546
+ "nullable": true,
6547
+ "properties": {
6548
+ "email": {
6549
+ "nullable": true,
6550
+ "type": "string"
6551
+ },
6552
+ "id": {
6553
+ "format": "uuid",
6554
+ "nullable": true,
6555
+ "type": "string"
6556
+ },
6557
+ "name": {
6558
+ "nullable": true,
6559
+ "type": "string"
6560
+ }
6561
+ },
6562
+ "required": [
6563
+ "id",
6564
+ "name",
6565
+ "email"
6566
+ ],
6567
+ "type": "object"
6568
+ },
6569
+ "satisfied_by_kind": {
6570
+ "description": "What satisfied it: a gate's person (`user`) or outside expert (`expert`), an event condition's system event (`event`), a not-before instant's clock (`system`); null while unsatisfied, or for a gate whose record of who ticked it is gone",
6571
+ "enum": [
6572
+ "user",
6573
+ "expert",
6574
+ "event",
6575
+ "system"
6576
+ ],
6185
6577
  "nullable": true,
6186
6578
  "type": "string"
6579
+ },
6580
+ "updated_at": {
6581
+ "format": "date-time",
6582
+ "type": "string"
6187
6583
  }
6188
6584
  },
6189
6585
  "required": [
6586
+ "id",
6587
+ "issue_id",
6190
6588
  "kind",
6191
- "ref",
6192
- "role",
6193
- "user_id",
6194
- "email",
6195
- "label"
6589
+ "key",
6590
+ "label",
6591
+ "not_before",
6592
+ "owner",
6593
+ "satisfied",
6594
+ "satisfied_at",
6595
+ "satisfied_by",
6596
+ "satisfied_by_kind",
6597
+ "satisfied_as_role",
6598
+ "inserted_at",
6599
+ "updated_at"
6196
6600
  ],
6197
6601
  "type": "object"
6198
6602
  },
6199
- "satisfied": {
6200
- "type": "boolean"
6201
- },
6202
- "satisfied_as_role": {
6203
- "description": "The fund-team role an owned gate was ticked as",
6204
- "enum": [
6205
- "gp",
6206
- "compliance_officer",
6207
- "valuer",
6208
- "accountant",
6209
- "auditor",
6210
- "counsel"
6211
- ],
6212
- "nullable": true,
6213
- "type": "string"
6214
- },
6215
- "satisfied_at": {
6216
- "format": "date-time",
6217
- "nullable": true,
6218
- "type": "string"
6219
- },
6220
- "satisfied_by": {
6221
- "description": "Who ticked a gate; null otherwise",
6222
- "nullable": true,
6603
+ {
6604
+ "additionalProperties": false,
6223
6605
  "properties": {
6224
- "email": {
6225
- "nullable": true,
6606
+ "id": {
6607
+ "format": "uuid",
6226
6608
  "type": "string"
6227
6609
  },
6228
- "id": {
6610
+ "issue_id": {
6229
6611
  "format": "uuid",
6612
+ "type": "string"
6613
+ },
6614
+ "key": {
6615
+ "description": "The gate's key; null without one",
6230
6616
  "nullable": true,
6231
6617
  "type": "string"
6232
6618
  },
6233
- "name": {
6619
+ "kind": {
6620
+ "enum": [
6621
+ "gate"
6622
+ ],
6623
+ "type": "string"
6624
+ },
6625
+ "label": {
6626
+ "nullable": true,
6627
+ "type": "string"
6628
+ },
6629
+ "owner": {
6630
+ "additionalProperties": false,
6631
+ "description": "A role the expert holds, or the expert themselves",
6632
+ "nullable": true,
6633
+ "properties": {
6634
+ "kind": {
6635
+ "enum": [
6636
+ "role",
6637
+ "expert"
6638
+ ],
6639
+ "type": "string"
6640
+ },
6641
+ "role": {
6642
+ "description": "For `role`",
6643
+ "enum": [
6644
+ "gp",
6645
+ "compliance_officer",
6646
+ "valuer",
6647
+ "accountant",
6648
+ "auditor",
6649
+ "counsel"
6650
+ ],
6651
+ "type": "string"
6652
+ }
6653
+ },
6654
+ "required": [
6655
+ "kind"
6656
+ ],
6657
+ "type": "object"
6658
+ },
6659
+ "satisfied": {
6660
+ "type": "boolean"
6661
+ },
6662
+ "satisfied_at": {
6663
+ "format": "date-time",
6234
6664
  "nullable": true,
6235
6665
  "type": "string"
6666
+ },
6667
+ "satisfied_by": {
6668
+ "additionalProperties": false,
6669
+ "description": "Who ticked it, never by name: `you`, the `role` it was ticked as, or for a tick without a role only `expert` or `member`; null while unsatisfied",
6670
+ "nullable": true,
6671
+ "properties": {
6672
+ "kind": {
6673
+ "enum": [
6674
+ "you",
6675
+ "role",
6676
+ "expert",
6677
+ "member"
6678
+ ],
6679
+ "type": "string"
6680
+ },
6681
+ "role": {
6682
+ "description": "For `role`: the role it was ticked as",
6683
+ "enum": [
6684
+ "gp",
6685
+ "compliance_officer",
6686
+ "valuer",
6687
+ "accountant",
6688
+ "auditor",
6689
+ "counsel"
6690
+ ],
6691
+ "type": "string"
6692
+ }
6693
+ },
6694
+ "required": [
6695
+ "kind"
6696
+ ],
6697
+ "type": "object"
6236
6698
  }
6237
6699
  },
6238
6700
  "required": [
6239
6701
  "id",
6240
- "name",
6241
- "email"
6702
+ "issue_id",
6703
+ "kind",
6704
+ "key",
6705
+ "label",
6706
+ "owner",
6707
+ "satisfied",
6708
+ "satisfied_at",
6709
+ "satisfied_by"
6242
6710
  ],
6243
6711
  "type": "object"
6244
- },
6245
- "satisfied_by_kind": {
6246
- "description": "What satisfied it: a gate's person (`user`) or outside expert (`expert`), an event condition's system event (`event`), a not-before instant's clock (`system`); null while unsatisfied, or for a gate whose record of who ticked it is gone",
6247
- "enum": [
6248
- "user",
6249
- "expert",
6250
- "event",
6251
- "system"
6252
- ],
6253
- "nullable": true,
6254
- "type": "string"
6255
- },
6256
- "updated_at": {
6257
- "format": "date-time",
6258
- "type": "string"
6259
6712
  }
6260
- },
6261
- "required": [
6262
- "id",
6263
- "issue_id",
6264
- "kind",
6265
- "key",
6266
- "label",
6267
- "not_before",
6268
- "owner",
6269
- "satisfied",
6270
- "satisfied_at",
6271
- "satisfied_by",
6272
- "satisfied_by_kind",
6273
- "satisfied_as_role",
6274
- "inserted_at",
6275
- "updated_at"
6276
- ],
6277
- "type": "object"
6713
+ ]
6278
6714
  }
6279
6715
  },
6280
6716
  "required": [
6281
6717
  "data"
6282
6718
  ],
6283
- "type": "object"
6719
+ "type": "object",
6720
+ "additionalProperties": false
6284
6721
  }
6285
6722
  }
6286
6723
  },
@@ -11331,28 +11768,152 @@
11331
11768
  "meta": {
11332
11769
  "additionalProperties": false,
11333
11770
  "properties": {
11334
- "has_more": {
11335
- "type": "boolean"
11336
- },
11337
- "next_cursor": {
11338
- "description": "Pass as `before`; null on the last page",
11771
+ "has_more": {
11772
+ "type": "boolean"
11773
+ },
11774
+ "next_cursor": {
11775
+ "description": "Pass as `before`; null on the last page",
11776
+ "nullable": true,
11777
+ "type": "string"
11778
+ }
11779
+ },
11780
+ "required": [
11781
+ "has_more",
11782
+ "next_cursor"
11783
+ ],
11784
+ "title": "OperatorJobListMeta",
11785
+ "type": "object"
11786
+ }
11787
+ },
11788
+ "required": [
11789
+ "data",
11790
+ "meta"
11791
+ ],
11792
+ "title": "OperatorJobList",
11793
+ "type": "object"
11794
+ }
11795
+ }
11796
+ },
11797
+ "description": "Success"
11798
+ },
11799
+ "400": {
11800
+ "description": "`invalid_cursor` for a cursor that is invalid, expired, or minted for other filters or another caller; `bad_request` for an unknown state or alias, a bad `mine` or `limit`"
11801
+ },
11802
+ "401": {
11803
+ "description": "Missing or invalid token"
11804
+ },
11805
+ "403": {
11806
+ "description": "Not permitted: a guest or outsider, or a missing scope (`forbidden`), a run-bound credential (`run_bound_credential`), no person acting (`actor_required`), no admin or member role in the organization (`operator_not_permitted`), or Operator switched off (`operator_disabled`)"
11807
+ },
11808
+ "404": {
11809
+ "description": "Not found"
11810
+ },
11811
+ "422": {
11812
+ "description": "Validation error"
11813
+ }
11814
+ },
11815
+ "summary": "List Operator jobs",
11816
+ "tags": []
11817
+ },
11818
+ "post": {
11819
+ "callbacks": {},
11820
+ "deprecated": false,
11821
+ "description": "Requires the `operator:write` scope and an admin or member role in the organization the credential is bound to, with Operator switched on there. Starts a job for the caller as the Chat Mode composer does when a person sends a request with Run as job on: the request is posted, attributed to the caller, as a job turn in a new org chat of theirs in the credential's organization, named after it, and Operator takes it from there under the caller's own current rights, checking them again. The caller requests, owns and runs the job. A request that starts with one of the organization's Operator skills (`/name …`) runs that skill, as in the composer. Spend counts against the organization's monthly Operator budget, as for any job started in the app. Approving its change set stays in the workbench, at the job's `approval_url`, which is set only while a change set waits for approval. The room, the request and the job are written together: a refused start leaves nothing behind. No response carries the outcome. A person starts at most 30 jobs an hour this way, across their credentials. Not idempotent: every request starts another job in another room, so a client must not retry it on its own; after a lost response, find the job with `GET /api/v1/operator/jobs?mine=true`. Refusals of this operation's own name their code in both `error` and `reason`.",
11822
+ "parameters": [],
11823
+ "requestBody": {
11824
+ "content": {
11825
+ "application/json": {
11826
+ "schema": {
11827
+ "additionalProperties": false,
11828
+ "properties": {
11829
+ "budget": {
11830
+ "description": "US dollars, at most two decimals: the job starts only while the organization's monthly Operator budget has at least this much left this month. Only for those who manage that budget (the organization's admins), as the app shows it only to them. A check before the start, not a cap: the job spends against the monthly budget like any job started in the app.",
11831
+ "exclusiveMinimum": true,
11832
+ "maximum": 1000000,
11833
+ "minimum": 0,
11834
+ "nullable": true,
11835
+ "type": "number"
11836
+ },
11837
+ "outcome": {
11838
+ "description": "What the job should achieve, as the person would write it in the composer; trimmed, and not blank. It becomes the job's request, never part of a response.",
11839
+ "maxLength": 10000,
11840
+ "minLength": 1,
11841
+ "type": "string"
11842
+ },
11843
+ "skill": {
11844
+ "description": "The invocation name of one of the organization's Operator skills the caller may run (see `GET /api/v1/operator/skills`), with or without the composer's leading slash. The request then starts with the invocation, as in the composer.",
11845
+ "maxLength": 65,
11846
+ "nullable": true,
11847
+ "pattern": "^/?[a-z0-9]+(-[a-z0-9]+)*$",
11848
+ "type": "string"
11849
+ }
11850
+ },
11851
+ "required": [
11852
+ "outcome"
11853
+ ],
11854
+ "title": "OperatorJobStartRequest",
11855
+ "type": "object"
11856
+ }
11857
+ }
11858
+ },
11859
+ "required": true
11860
+ },
11861
+ "responses": {
11862
+ "201": {
11863
+ "content": {
11864
+ "application/json": {
11865
+ "schema": {
11866
+ "additionalProperties": false,
11867
+ "properties": {
11868
+ "data": {
11869
+ "additionalProperties": false,
11870
+ "properties": {
11871
+ "approval_url": {
11872
+ "description": "Opens the review drawer on the exact change set waiting for approval; null while none waits",
11873
+ "format": "uri",
11339
11874
  "nullable": true,
11340
11875
  "type": "string"
11876
+ },
11877
+ "job_id": {
11878
+ "format": "uuid",
11879
+ "type": "string"
11880
+ },
11881
+ "state": {
11882
+ "enum": [
11883
+ "draft",
11884
+ "planning",
11885
+ "ready",
11886
+ "running",
11887
+ "waiting_for_approval",
11888
+ "waiting_for_human",
11889
+ "paused",
11890
+ "failed",
11891
+ "needs_reconciliation",
11892
+ "completed",
11893
+ "cancelled"
11894
+ ],
11895
+ "type": "string"
11896
+ },
11897
+ "workbench_url": {
11898
+ "description": "Opens the job's review drawer in its room",
11899
+ "format": "uri",
11900
+ "type": "string"
11341
11901
  }
11342
11902
  },
11343
11903
  "required": [
11344
- "has_more",
11345
- "next_cursor"
11904
+ "approval_url",
11905
+ "job_id",
11906
+ "state",
11907
+ "workbench_url"
11346
11908
  ],
11347
- "title": "OperatorJobListMeta",
11909
+ "title": "OperatorJobStart",
11348
11910
  "type": "object"
11349
11911
  }
11350
11912
  },
11351
11913
  "required": [
11352
- "data",
11353
- "meta"
11914
+ "data"
11354
11915
  ],
11355
- "title": "OperatorJobList",
11916
+ "title": "OperatorJobStartResponse",
11356
11917
  "type": "object"
11357
11918
  }
11358
11919
  }
@@ -11360,22 +11921,28 @@
11360
11921
  "description": "Success"
11361
11922
  },
11362
11923
  "400": {
11363
- "description": "`invalid_cursor` for a cursor that is invalid, expired, or minted for other filters or another caller; `bad_request` for an unknown state or alias, a bad `mine` or `limit`"
11924
+ "description": "A field the request does not take (`bad_request`)"
11364
11925
  },
11365
11926
  "401": {
11366
11927
  "description": "Missing or invalid token"
11367
11928
  },
11368
11929
  "403": {
11369
- "description": "Not permitted: a guest or outsider, or a missing scope (`forbidden`), a run-bound credential (`run_bound_credential`), no person acting (`actor_required`), no admin or member role in the organization (`operator_not_permitted`), or Operator switched off (`operator_disabled`)"
11930
+ "description": "Not permitted: a guest or outsider, or a missing `operator:write` scope (`forbidden`), a run-bound credential (`run_bound_credential`), no person acting (`actor_required`), no admin or member role in the organization (`operator_not_permitted`), Operator switched off (`operator_disabled`), or a `budget` from someone who doesn't manage the organization's Operator budget (`budget_not_permitted`)"
11370
11931
  },
11371
- "404": {
11372
- "description": "Not found"
11932
+ "409": {
11933
+ "description": "The organization's monthly Operator budget has less than `budget` left this month (`budget_exceeded`), or Operator or the caller's access changed while the job started (`concurrent_change`); nothing was posted"
11373
11934
  },
11374
11935
  "422": {
11375
- "description": "Validation error"
11936
+ "description": "An `outcome` that is missing, not text, blank, longer than 10000 characters, holds control characters (C0 other than tab, line feed and carriage return, DEL, or C1), or is a confirmation marker (`invalid_outcome`); a `budget` that is not a positive amount with at most two decimals up to 1000000 (`invalid_budget`); a `skill` that names no Operator skill the caller may run in the organization (`unknown_skill`)"
11937
+ },
11938
+ "429": {
11939
+ "description": "The caller started 30 jobs this way in the last hour (`rate_limited`, with `retry-after`)"
11940
+ },
11941
+ "503": {
11942
+ "description": "Operator's operational profile or capabilities are unavailable (`service_unavailable`)"
11376
11943
  }
11377
11944
  },
11378
- "summary": "List Operator jobs",
11945
+ "summary": "Start an Operator job",
11379
11946
  "tags": []
11380
11947
  }
11381
11948
  },
@@ -16208,7 +16775,245 @@
16208
16775
  "schema": {
16209
16776
  "properties": {
16210
16777
  "data": {
16211
- "type": "object"
16778
+ "type": "object",
16779
+ "additionalProperties": false,
16780
+ "properties": {
16781
+ "assignments": {
16782
+ "description": "The steps assigned to the expert that they still hold, in identifier order",
16783
+ "items": {
16784
+ "additionalProperties": false,
16785
+ "properties": {
16786
+ "description": {
16787
+ "description": "Null when Operator runs the step or the step has none",
16788
+ "nullable": true,
16789
+ "type": "string"
16790
+ },
16791
+ "due_date": {
16792
+ "format": "date",
16793
+ "nullable": true,
16794
+ "type": "string"
16795
+ },
16796
+ "gates": {
16797
+ "description": "Only the gates the expert owns",
16798
+ "items": {
16799
+ "additionalProperties": false,
16800
+ "properties": {
16801
+ "id": {
16802
+ "format": "uuid",
16803
+ "type": "string"
16804
+ },
16805
+ "issue_id": {
16806
+ "format": "uuid",
16807
+ "type": "string"
16808
+ },
16809
+ "key": {
16810
+ "description": "The gate's key; null without one",
16811
+ "nullable": true,
16812
+ "type": "string"
16813
+ },
16814
+ "kind": {
16815
+ "enum": [
16816
+ "gate"
16817
+ ],
16818
+ "type": "string"
16819
+ },
16820
+ "label": {
16821
+ "nullable": true,
16822
+ "type": "string"
16823
+ },
16824
+ "owner": {
16825
+ "additionalProperties": false,
16826
+ "description": "A role the expert holds, or the expert themselves",
16827
+ "nullable": true,
16828
+ "properties": {
16829
+ "kind": {
16830
+ "enum": [
16831
+ "role",
16832
+ "expert"
16833
+ ],
16834
+ "type": "string"
16835
+ },
16836
+ "role": {
16837
+ "description": "For `role`",
16838
+ "enum": [
16839
+ "gp",
16840
+ "compliance_officer",
16841
+ "valuer",
16842
+ "accountant",
16843
+ "auditor",
16844
+ "counsel"
16845
+ ],
16846
+ "type": "string"
16847
+ }
16848
+ },
16849
+ "required": [
16850
+ "kind"
16851
+ ],
16852
+ "type": "object"
16853
+ },
16854
+ "satisfied": {
16855
+ "type": "boolean"
16856
+ },
16857
+ "satisfied_at": {
16858
+ "format": "date-time",
16859
+ "nullable": true,
16860
+ "type": "string"
16861
+ },
16862
+ "satisfied_by": {
16863
+ "additionalProperties": false,
16864
+ "description": "Who ticked it, never by name: `you`, the `role` it was ticked as, or for a tick without a role only `expert` or `member`; null while unsatisfied",
16865
+ "nullable": true,
16866
+ "properties": {
16867
+ "kind": {
16868
+ "enum": [
16869
+ "you",
16870
+ "role",
16871
+ "expert",
16872
+ "member"
16873
+ ],
16874
+ "type": "string"
16875
+ },
16876
+ "role": {
16877
+ "description": "For `role`: the role it was ticked as",
16878
+ "enum": [
16879
+ "gp",
16880
+ "compliance_officer",
16881
+ "valuer",
16882
+ "accountant",
16883
+ "auditor",
16884
+ "counsel"
16885
+ ],
16886
+ "type": "string"
16887
+ }
16888
+ },
16889
+ "required": [
16890
+ "kind"
16891
+ ],
16892
+ "type": "object"
16893
+ }
16894
+ },
16895
+ "required": [
16896
+ "id",
16897
+ "issue_id",
16898
+ "kind",
16899
+ "key",
16900
+ "label",
16901
+ "owner",
16902
+ "satisfied",
16903
+ "satisfied_at",
16904
+ "satisfied_by"
16905
+ ],
16906
+ "type": "object"
16907
+ },
16908
+ "type": "array"
16909
+ },
16910
+ "identifier": {
16911
+ "type": "string"
16912
+ },
16913
+ "open_blockers": {
16914
+ "description": "How many of its blockers are still open",
16915
+ "minimum": 0,
16916
+ "type": "integer"
16917
+ },
16918
+ "state": {
16919
+ "additionalProperties": false,
16920
+ "nullable": true,
16921
+ "properties": {
16922
+ "name": {
16923
+ "type": "string"
16924
+ },
16925
+ "type": {
16926
+ "enum": [
16927
+ "backlog",
16928
+ "unstarted",
16929
+ "started",
16930
+ "completed",
16931
+ "canceled"
16932
+ ],
16933
+ "type": "string"
16934
+ }
16935
+ },
16936
+ "required": [
16937
+ "name",
16938
+ "type"
16939
+ ],
16940
+ "type": "object"
16941
+ },
16942
+ "title": {
16943
+ "type": "string"
16944
+ }
16945
+ },
16946
+ "required": [
16947
+ "identifier",
16948
+ "title",
16949
+ "description",
16950
+ "state",
16951
+ "due_date",
16952
+ "open_blockers",
16953
+ "gates"
16954
+ ],
16955
+ "type": "object"
16956
+ },
16957
+ "type": "array"
16958
+ },
16959
+ "expert": {
16960
+ "additionalProperties": false,
16961
+ "properties": {
16962
+ "id": {
16963
+ "format": "uuid",
16964
+ "type": "string"
16965
+ },
16966
+ "role": {
16967
+ "description": "The expert's role on the plan",
16968
+ "enum": [
16969
+ "gp",
16970
+ "compliance_officer",
16971
+ "valuer",
16972
+ "accountant",
16973
+ "auditor",
16974
+ "counsel"
16975
+ ],
16976
+ "type": "string"
16977
+ }
16978
+ },
16979
+ "required": [
16980
+ "id",
16981
+ "role"
16982
+ ],
16983
+ "type": "object"
16984
+ },
16985
+ "plan": {
16986
+ "additionalProperties": false,
16987
+ "description": "The plan the expert was invited to; null once it is gone",
16988
+ "nullable": true,
16989
+ "properties": {
16990
+ "id": {
16991
+ "format": "uuid",
16992
+ "type": "string"
16993
+ },
16994
+ "status": {
16995
+ "enum": [
16996
+ "held",
16997
+ "released",
16998
+ "running",
16999
+ "completed",
17000
+ "needs_attention"
17001
+ ],
17002
+ "type": "string"
17003
+ }
17004
+ },
17005
+ "required": [
17006
+ "id",
17007
+ "status"
17008
+ ],
17009
+ "type": "object"
17010
+ }
17011
+ },
17012
+ "required": [
17013
+ "expert",
17014
+ "plan",
17015
+ "assignments"
17016
+ ]
16212
17017
  }
16213
17018
  },
16214
17019
  "required": [