@serviceai/api-spec 1.2.434 → 1.6.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.
Files changed (4) hide show
  1. package/openapi.json +1915 -51
  2. package/openapi.yaml +1279 -11
  3. package/package.json +1 -1
  4. package/types.d.ts +696 -1
package/openapi.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "openapi": "3.1.0",
3
3
  "info": {
4
4
  "title": "ServiceAi API",
5
- "version": "1.2.434",
5
+ "version": "1.6.1",
6
6
  "description": "Source-of-truth API contract for ServiceAi. Generated from `shared/schema.ts` Zod schemas by `scripts/build-api-spec.ts`. Versioning policy: see `docs/api-versioning.md`. The hand-written docs/ios-contract.md and docs/lidar-mobile-upload-contract.md are human-readable design notes only — this spec is the canonical wire contract.",
7
7
  "license": {
8
8
  "name": "Proprietary",
@@ -52,6 +52,10 @@
52
52
  "name": "chatty",
53
53
  "description": "Realtime voice-enabled AI assistant."
54
54
  },
55
+ {
56
+ "name": "checklists",
57
+ "description": "Job checklists: the voice walk-through draft."
58
+ },
55
59
  {
56
60
  "name": "time-tracking",
57
61
  "description": "The clock. A work day is the master clock and the payroll number; time entries sit inside it and say where the time went. Automatic clock-in/out is solved SERVER-side from reported fence crossings — a client reports what it saw and reads the outcome back."
@@ -66,6 +70,22 @@
66
70
  }
67
71
  ],
68
72
  "components": {
73
+ "securitySchemes": {
74
+ "UserBearer": {
75
+ "type": "http",
76
+ "scheme": "bearer"
77
+ },
78
+ "BrowserSession": {
79
+ "type": "apiKey",
80
+ "in": "cookie",
81
+ "name": "connect.sid"
82
+ },
83
+ "BrowserAuthCookie": {
84
+ "type": "apiKey",
85
+ "in": "cookie",
86
+ "name": "auth_token"
87
+ }
88
+ },
69
89
  "schemas": {
70
90
  "ErrorEnvelope": {
71
91
  "type": "object",
@@ -126,7 +146,7 @@
126
146
  "properties": {
127
147
  "apiVersion": {
128
148
  "type": "string",
129
- "example": "1.2.434"
149
+ "example": "1.6.1"
130
150
  },
131
151
  "minClientVersion": {
132
152
  "type": "string",
@@ -2748,6 +2768,39 @@
2748
2768
  "roomConnections"
2749
2769
  ]
2750
2770
  },
2771
+ "EventStreamTicketResponse": {
2772
+ "type": "object",
2773
+ "properties": {
2774
+ "ticket": {
2775
+ "type": "string",
2776
+ "minLength": 1,
2777
+ "maxLength": 8192
2778
+ }
2779
+ },
2780
+ "required": [
2781
+ "ticket"
2782
+ ],
2783
+ "additionalProperties": false
2784
+ },
2785
+ "StreamAuthenticationError": {
2786
+ "type": "object",
2787
+ "properties": {
2788
+ "message": {
2789
+ "type": "string"
2790
+ },
2791
+ "code": {
2792
+ "type": "string",
2793
+ "enum": [
2794
+ "IMPERSONATION_UNAVAILABLE",
2795
+ "SUPPORT_IMPERSONATION_UNAVAILABLE",
2796
+ "auth_unavailable"
2797
+ ]
2798
+ }
2799
+ },
2800
+ "required": [
2801
+ "message"
2802
+ ]
2803
+ },
2751
2804
  "JobSummary": {
2752
2805
  "type": "object",
2753
2806
  "properties": {
@@ -5026,24 +5079,1591 @@
5026
5079
  "token",
5027
5080
  "roomIds"
5028
5081
  ]
5029
- }
5030
- },
5031
- "parameters": {}
5032
- },
5033
- "paths": {
5034
- "/api/version": {
5035
- "get": {
5036
- "summary": "Cross-platform version handshake manifest.",
5037
- "tags": [
5038
- "version"
5039
- ],
5040
- "responses": {
5041
- "200": {
5042
- "description": "Always returned. Body is the canonical handshake manifest.",
5082
+ },
5083
+ "WalkthroughDraftRequest": {
5084
+ "type": "object",
5085
+ "properties": {
5086
+ "transcript": {
5087
+ "type": "array",
5088
+ "items": {
5089
+ "type": "object",
5090
+ "properties": {
5091
+ "text": {
5092
+ "type": "string",
5093
+ "minLength": 1,
5094
+ "maxLength": 1000
5095
+ },
5096
+ "startedAt": {
5097
+ "type": "string",
5098
+ "format": "date-time"
5099
+ },
5100
+ "endedAt": {
5101
+ "type": "string",
5102
+ "format": "date-time"
5103
+ }
5104
+ },
5105
+ "required": [
5106
+ "text",
5107
+ "startedAt",
5108
+ "endedAt"
5109
+ ]
5110
+ },
5111
+ "minItems": 1,
5112
+ "maxItems": 400
5113
+ },
5114
+ "photos": {
5115
+ "type": "array",
5116
+ "items": {
5117
+ "type": "object",
5118
+ "properties": {
5119
+ "assetId": {
5120
+ "type": "string",
5121
+ "minLength": 1,
5122
+ "maxLength": 64
5123
+ },
5124
+ "capturedAt": {
5125
+ "type": "string",
5126
+ "format": "date-time"
5127
+ },
5128
+ "roomHint": {
5129
+ "type": [
5130
+ "string",
5131
+ "null"
5132
+ ],
5133
+ "maxLength": 200
5134
+ },
5135
+ "sketchRoomId": {
5136
+ "type": [
5137
+ "integer",
5138
+ "null"
5139
+ ],
5140
+ "exclusiveMinimum": 0
5141
+ },
5142
+ "capturePose": {
5143
+ "type": [
5144
+ "object",
5145
+ "null"
5146
+ ],
5147
+ "properties": {
5148
+ "x": {
5149
+ "type": "number"
5150
+ },
5151
+ "y": {
5152
+ "type": "number"
5153
+ },
5154
+ "z": {
5155
+ "type": "number"
5156
+ },
5157
+ "floorId": {
5158
+ "type": [
5159
+ "integer",
5160
+ "null"
5161
+ ],
5162
+ "exclusiveMinimum": 0
5163
+ },
5164
+ "sketchId": {
5165
+ "type": [
5166
+ "integer",
5167
+ "null"
5168
+ ],
5169
+ "exclusiveMinimum": 0
5170
+ },
5171
+ "scanSessionId": {
5172
+ "type": "string",
5173
+ "maxLength": 64
5174
+ },
5175
+ "scanRoomLocalId": {
5176
+ "type": "string",
5177
+ "maxLength": 128
5178
+ },
5179
+ "scanRoomName": {
5180
+ "type": "string",
5181
+ "maxLength": 200
5182
+ }
5183
+ }
5184
+ }
5185
+ },
5186
+ "required": [
5187
+ "assetId",
5188
+ "capturedAt"
5189
+ ]
5190
+ },
5191
+ "maxItems": 200
5192
+ },
5193
+ "sections": {
5194
+ "type": "array",
5195
+ "items": {
5196
+ "type": "object",
5197
+ "properties": {
5198
+ "name": {
5199
+ "type": "string",
5200
+ "minLength": 1,
5201
+ "maxLength": 200
5202
+ },
5203
+ "startedAt": {
5204
+ "type": "string",
5205
+ "format": "date-time"
5206
+ },
5207
+ "sketchRoomId": {
5208
+ "type": [
5209
+ "integer",
5210
+ "null"
5211
+ ],
5212
+ "exclusiveMinimum": 0
5213
+ }
5214
+ },
5215
+ "required": [
5216
+ "name",
5217
+ "startedAt"
5218
+ ]
5219
+ },
5220
+ "maxItems": 100
5221
+ },
5222
+ "roomsFrom": {
5223
+ "type": "string",
5224
+ "enum": [
5225
+ "speech",
5226
+ "scan"
5227
+ ]
5228
+ }
5229
+ },
5230
+ "required": [
5231
+ "transcript"
5232
+ ]
5233
+ },
5234
+ "ChecklistDraft": {
5235
+ "type": "object",
5236
+ "properties": {
5237
+ "name": {
5238
+ "type": "string"
5239
+ },
5240
+ "sections": {
5241
+ "type": "array",
5242
+ "items": {
5243
+ "type": "object",
5244
+ "properties": {
5245
+ "key": {
5246
+ "type": "string"
5247
+ },
5248
+ "title": {
5249
+ "type": "string"
5250
+ },
5251
+ "sketchRoomId": {
5252
+ "type": [
5253
+ "integer",
5254
+ "null"
5255
+ ]
5256
+ },
5257
+ "kind": {
5258
+ "type": "string",
5259
+ "enum": [
5260
+ "room",
5261
+ "custom",
5262
+ "not_sure"
5263
+ ]
5264
+ },
5265
+ "items": {
5266
+ "type": "array",
5267
+ "items": {
5268
+ "type": "object",
5269
+ "properties": {
5270
+ "key": {
5271
+ "type": "string"
5272
+ },
5273
+ "itemText": {
5274
+ "type": "string"
5275
+ },
5276
+ "description": {
5277
+ "type": [
5278
+ "string",
5279
+ "null"
5280
+ ]
5281
+ },
5282
+ "itemType": {
5283
+ "type": "string",
5284
+ "enum": [
5285
+ "checkbox",
5286
+ "yes/no",
5287
+ "text",
5288
+ "number",
5289
+ "date",
5290
+ "dropdown",
5291
+ "multi-select",
5292
+ "photo",
5293
+ "signature"
5294
+ ]
5295
+ },
5296
+ "required": {
5297
+ "type": "boolean"
5298
+ },
5299
+ "options": {
5300
+ "type": [
5301
+ "object",
5302
+ "null"
5303
+ ],
5304
+ "additionalProperties": {}
5305
+ },
5306
+ "referenceMedia": {
5307
+ "type": "array",
5308
+ "items": {
5309
+ "type": "object",
5310
+ "properties": {
5311
+ "assetId": {
5312
+ "type": "string",
5313
+ "minLength": 1,
5314
+ "maxLength": 64
5315
+ },
5316
+ "caption": {
5317
+ "type": [
5318
+ "string",
5319
+ "null"
5320
+ ],
5321
+ "maxLength": 300
5322
+ },
5323
+ "order": {
5324
+ "type": "integer",
5325
+ "minimum": 0
5326
+ }
5327
+ },
5328
+ "required": [
5329
+ "assetId"
5330
+ ]
5331
+ },
5332
+ "maxItems": 10
5333
+ },
5334
+ "hints": {
5335
+ "type": "array",
5336
+ "items": {
5337
+ "type": "string",
5338
+ "enum": [
5339
+ "photo_required",
5340
+ "yes_no",
5341
+ "required",
5342
+ "reading"
5343
+ ]
5344
+ }
5345
+ },
5346
+ "roomSource": {
5347
+ "type": "string",
5348
+ "enum": [
5349
+ "pose",
5350
+ "named",
5351
+ "vision",
5352
+ "time",
5353
+ "none"
5354
+ ]
5355
+ },
5356
+ "spokenAt": {
5357
+ "type": "string"
5358
+ },
5359
+ "quote": {
5360
+ "type": [
5361
+ "string",
5362
+ "null"
5363
+ ]
5364
+ }
5365
+ },
5366
+ "required": [
5367
+ "key",
5368
+ "itemText",
5369
+ "description",
5370
+ "itemType",
5371
+ "required",
5372
+ "options",
5373
+ "referenceMedia",
5374
+ "hints",
5375
+ "roomSource",
5376
+ "spokenAt",
5377
+ "quote"
5378
+ ]
5379
+ }
5380
+ }
5381
+ },
5382
+ "required": [
5383
+ "key",
5384
+ "title",
5385
+ "sketchRoomId",
5386
+ "kind",
5387
+ "items"
5388
+ ]
5389
+ }
5390
+ },
5391
+ "photos": {
5392
+ "type": "array",
5393
+ "items": {
5394
+ "type": "object",
5395
+ "properties": {
5396
+ "assetId": {
5397
+ "type": "string"
5398
+ },
5399
+ "capturedAt": {
5400
+ "type": "string"
5401
+ },
5402
+ "sectionKey": {
5403
+ "type": [
5404
+ "string",
5405
+ "null"
5406
+ ]
5407
+ },
5408
+ "roomSource": {
5409
+ "type": "string",
5410
+ "enum": [
5411
+ "pose",
5412
+ "named",
5413
+ "vision",
5414
+ "time",
5415
+ "none"
5416
+ ]
5417
+ },
5418
+ "itemKeys": {
5419
+ "type": "array",
5420
+ "items": {
5421
+ "type": "string"
5422
+ }
5423
+ }
5424
+ },
5425
+ "required": [
5426
+ "assetId",
5427
+ "capturedAt",
5428
+ "sectionKey",
5429
+ "roomSource",
5430
+ "itemKeys"
5431
+ ]
5432
+ }
5433
+ },
5434
+ "visionUsed": {
5435
+ "type": "boolean"
5436
+ },
5437
+ "model": {
5438
+ "type": [
5439
+ "string",
5440
+ "null"
5441
+ ]
5442
+ },
5443
+ "promptVersion": {
5444
+ "type": "string"
5445
+ }
5446
+ },
5447
+ "required": [
5448
+ "name",
5449
+ "sections",
5450
+ "photos",
5451
+ "visionUsed",
5452
+ "model",
5453
+ "promptVersion"
5454
+ ]
5455
+ },
5456
+ "WalkthroughDraftResponse": {
5457
+ "type": "object",
5458
+ "properties": {
5459
+ "status": {
5460
+ "type": "string",
5461
+ "enum": [
5462
+ "completed",
5463
+ "running",
5464
+ "failed"
5465
+ ]
5466
+ },
5467
+ "runId": {
5468
+ "type": [
5469
+ "integer",
5470
+ "null"
5471
+ ]
5472
+ },
5473
+ "draft": {
5474
+ "type": [
5475
+ "object",
5476
+ "null"
5477
+ ],
5478
+ "properties": {
5479
+ "name": {
5480
+ "type": "string"
5481
+ },
5482
+ "sections": {
5483
+ "type": "array",
5484
+ "items": {
5485
+ "type": "object",
5486
+ "properties": {
5487
+ "key": {
5488
+ "type": "string"
5489
+ },
5490
+ "title": {
5491
+ "type": "string"
5492
+ },
5493
+ "sketchRoomId": {
5494
+ "type": [
5495
+ "integer",
5496
+ "null"
5497
+ ]
5498
+ },
5499
+ "kind": {
5500
+ "type": "string",
5501
+ "enum": [
5502
+ "room",
5503
+ "custom",
5504
+ "not_sure"
5505
+ ]
5506
+ },
5507
+ "items": {
5508
+ "type": "array",
5509
+ "items": {
5510
+ "type": "object",
5511
+ "properties": {
5512
+ "key": {
5513
+ "type": "string"
5514
+ },
5515
+ "itemText": {
5516
+ "type": "string"
5517
+ },
5518
+ "description": {
5519
+ "type": [
5520
+ "string",
5521
+ "null"
5522
+ ]
5523
+ },
5524
+ "itemType": {
5525
+ "type": "string",
5526
+ "enum": [
5527
+ "checkbox",
5528
+ "yes/no",
5529
+ "text",
5530
+ "number",
5531
+ "date",
5532
+ "dropdown",
5533
+ "multi-select",
5534
+ "photo",
5535
+ "signature"
5536
+ ]
5537
+ },
5538
+ "required": {
5539
+ "type": "boolean"
5540
+ },
5541
+ "options": {
5542
+ "type": [
5543
+ "object",
5544
+ "null"
5545
+ ],
5546
+ "additionalProperties": {}
5547
+ },
5548
+ "referenceMedia": {
5549
+ "type": "array",
5550
+ "items": {
5551
+ "type": "object",
5552
+ "properties": {
5553
+ "assetId": {
5554
+ "type": "string",
5555
+ "minLength": 1,
5556
+ "maxLength": 64
5557
+ },
5558
+ "caption": {
5559
+ "type": [
5560
+ "string",
5561
+ "null"
5562
+ ],
5563
+ "maxLength": 300
5564
+ },
5565
+ "order": {
5566
+ "type": "integer",
5567
+ "minimum": 0
5568
+ }
5569
+ },
5570
+ "required": [
5571
+ "assetId"
5572
+ ]
5573
+ },
5574
+ "maxItems": 10
5575
+ },
5576
+ "hints": {
5577
+ "type": "array",
5578
+ "items": {
5579
+ "type": "string",
5580
+ "enum": [
5581
+ "photo_required",
5582
+ "yes_no",
5583
+ "required",
5584
+ "reading"
5585
+ ]
5586
+ }
5587
+ },
5588
+ "roomSource": {
5589
+ "type": "string",
5590
+ "enum": [
5591
+ "pose",
5592
+ "named",
5593
+ "vision",
5594
+ "time",
5595
+ "none"
5596
+ ]
5597
+ },
5598
+ "spokenAt": {
5599
+ "type": "string"
5600
+ },
5601
+ "quote": {
5602
+ "type": [
5603
+ "string",
5604
+ "null"
5605
+ ]
5606
+ }
5607
+ },
5608
+ "required": [
5609
+ "key",
5610
+ "itemText",
5611
+ "description",
5612
+ "itemType",
5613
+ "required",
5614
+ "options",
5615
+ "referenceMedia",
5616
+ "hints",
5617
+ "roomSource",
5618
+ "spokenAt",
5619
+ "quote"
5620
+ ]
5621
+ }
5622
+ }
5623
+ },
5624
+ "required": [
5625
+ "key",
5626
+ "title",
5627
+ "sketchRoomId",
5628
+ "kind",
5629
+ "items"
5630
+ ]
5631
+ }
5632
+ },
5633
+ "photos": {
5634
+ "type": "array",
5635
+ "items": {
5636
+ "type": "object",
5637
+ "properties": {
5638
+ "assetId": {
5639
+ "type": "string"
5640
+ },
5641
+ "capturedAt": {
5642
+ "type": "string"
5643
+ },
5644
+ "sectionKey": {
5645
+ "type": [
5646
+ "string",
5647
+ "null"
5648
+ ]
5649
+ },
5650
+ "roomSource": {
5651
+ "type": "string",
5652
+ "enum": [
5653
+ "pose",
5654
+ "named",
5655
+ "vision",
5656
+ "time",
5657
+ "none"
5658
+ ]
5659
+ },
5660
+ "itemKeys": {
5661
+ "type": "array",
5662
+ "items": {
5663
+ "type": "string"
5664
+ }
5665
+ }
5666
+ },
5667
+ "required": [
5668
+ "assetId",
5669
+ "capturedAt",
5670
+ "sectionKey",
5671
+ "roomSource",
5672
+ "itemKeys"
5673
+ ]
5674
+ }
5675
+ },
5676
+ "visionUsed": {
5677
+ "type": "boolean"
5678
+ },
5679
+ "model": {
5680
+ "type": [
5681
+ "string",
5682
+ "null"
5683
+ ]
5684
+ },
5685
+ "promptVersion": {
5686
+ "type": "string"
5687
+ }
5688
+ },
5689
+ "required": [
5690
+ "name",
5691
+ "sections",
5692
+ "photos",
5693
+ "visionUsed",
5694
+ "model",
5695
+ "promptVersion"
5696
+ ]
5697
+ },
5698
+ "sortRun": {
5699
+ "type": [
5700
+ "object",
5701
+ "null"
5702
+ ],
5703
+ "properties": {
5704
+ "status": {
5705
+ "type": "string",
5706
+ "enum": [
5707
+ "running",
5708
+ "completed",
5709
+ "failed"
5710
+ ]
5711
+ },
5712
+ "total": {
5713
+ "type": "integer"
5714
+ },
5715
+ "done": {
5716
+ "type": "integer"
5717
+ }
5718
+ },
5719
+ "required": [
5720
+ "status",
5721
+ "total",
5722
+ "done"
5723
+ ]
5724
+ },
5725
+ "message": {
5726
+ "type": [
5727
+ "string",
5728
+ "null"
5729
+ ]
5730
+ }
5731
+ },
5732
+ "required": [
5733
+ "status",
5734
+ "runId",
5735
+ "draft",
5736
+ "sortRun",
5737
+ "message"
5738
+ ]
5739
+ },
5740
+ "ChattyListJobChecklistsArguments": {
5741
+ "type": "object",
5742
+ "properties": {
5743
+ "jobId": {
5744
+ "anyOf": [
5745
+ {
5746
+ "type": "integer",
5747
+ "exclusiveMinimum": 0
5748
+ },
5749
+ {
5750
+ "type": "string",
5751
+ "pattern": "^\\d+$"
5752
+ }
5753
+ ]
5754
+ }
5755
+ },
5756
+ "description": "`arguments` of the Chatty tool `list_job_checklists` (POST /api/chatty-voice/tools/execute)."
5757
+ },
5758
+ "ChattyListJobChecklistsData": {
5759
+ "type": "array",
5760
+ "items": {
5761
+ "type": "object",
5762
+ "properties": {
5763
+ "id": {
5764
+ "type": "integer"
5765
+ },
5766
+ "name": {
5767
+ "type": "string"
5768
+ },
5769
+ "status": {
5770
+ "type": [
5771
+ "string",
5772
+ "null"
5773
+ ]
5774
+ },
5775
+ "completionPercentage": {
5776
+ "type": "number"
5777
+ },
5778
+ "templateId": {
5779
+ "type": [
5780
+ "integer",
5781
+ "null"
5782
+ ]
5783
+ }
5784
+ },
5785
+ "required": [
5786
+ "id",
5787
+ "name",
5788
+ "status",
5789
+ "completionPercentage",
5790
+ "templateId"
5791
+ ]
5792
+ },
5793
+ "description": "`data` of a successful `list_job_checklists` call (`success: true`)."
5794
+ },
5795
+ "ChattyGetChecklistArguments": {
5796
+ "type": "object",
5797
+ "properties": {
5798
+ "checklistId": {
5799
+ "anyOf": [
5800
+ {
5801
+ "type": "integer",
5802
+ "exclusiveMinimum": 0
5803
+ },
5804
+ {
5805
+ "type": "string",
5806
+ "pattern": "^\\d+$"
5807
+ }
5808
+ ]
5809
+ },
5810
+ "checklistName": {
5811
+ "type": "string"
5812
+ },
5813
+ "jobId": {
5814
+ "anyOf": [
5815
+ {
5816
+ "type": "integer",
5817
+ "exclusiveMinimum": 0
5818
+ },
5819
+ {
5820
+ "type": "string",
5821
+ "pattern": "^\\d+$"
5822
+ }
5823
+ ]
5824
+ }
5825
+ },
5826
+ "description": "`arguments` of the Chatty tool `get_checklist` (POST /api/chatty-voice/tools/execute)."
5827
+ },
5828
+ "ChattyGetChecklistData": {
5829
+ "type": "object",
5830
+ "properties": {
5831
+ "id": {
5832
+ "type": "integer"
5833
+ },
5834
+ "name": {
5835
+ "type": "string"
5836
+ },
5837
+ "status": {
5838
+ "type": [
5839
+ "string",
5840
+ "null"
5841
+ ]
5842
+ },
5843
+ "completionPercentage": {
5844
+ "type": "number"
5845
+ },
5846
+ "jobId": {
5847
+ "type": [
5848
+ "integer",
5849
+ "null"
5850
+ ]
5851
+ },
5852
+ "items": {
5853
+ "type": "array",
5854
+ "items": {
5855
+ "type": "object",
5856
+ "properties": {
5857
+ "id": {
5858
+ "type": "integer"
5859
+ },
5860
+ "itemText": {
5861
+ "type": "string"
5862
+ },
5863
+ "itemType": {
5864
+ "type": "string"
5865
+ },
5866
+ "required": {
5867
+ "type": "boolean"
5868
+ },
5869
+ "done": {
5870
+ "type": "boolean"
5871
+ },
5872
+ "value": {
5873
+ "type": [
5874
+ "string",
5875
+ "null"
5876
+ ]
5877
+ },
5878
+ "section": {
5879
+ "type": [
5880
+ "string",
5881
+ "null"
5882
+ ]
5883
+ },
5884
+ "referencePhotos": {
5885
+ "type": "integer"
5886
+ }
5887
+ },
5888
+ "required": [
5889
+ "id",
5890
+ "itemText",
5891
+ "itemType",
5892
+ "required",
5893
+ "done",
5894
+ "value",
5895
+ "section",
5896
+ "referencePhotos"
5897
+ ]
5898
+ }
5899
+ }
5900
+ },
5901
+ "required": [
5902
+ "id",
5903
+ "name",
5904
+ "status",
5905
+ "completionPercentage",
5906
+ "jobId",
5907
+ "items"
5908
+ ],
5909
+ "description": "`data` of a successful `get_checklist` call (`success: true`)."
5910
+ },
5911
+ "ChattyCreateChecklistArguments": {
5912
+ "type": "object",
5913
+ "properties": {
5914
+ "jobId": {
5915
+ "anyOf": [
5916
+ {
5917
+ "type": "integer",
5918
+ "exclusiveMinimum": 0
5919
+ },
5920
+ {
5921
+ "type": "string",
5922
+ "pattern": "^\\d+$"
5923
+ }
5924
+ ]
5925
+ },
5926
+ "name": {
5927
+ "type": "string"
5928
+ },
5929
+ "templateId": {
5930
+ "anyOf": [
5931
+ {
5932
+ "type": "integer",
5933
+ "exclusiveMinimum": 0
5934
+ },
5935
+ {
5936
+ "type": "string",
5937
+ "pattern": "^\\d+$"
5938
+ }
5939
+ ]
5940
+ },
5941
+ "templateName": {
5942
+ "type": "string"
5943
+ },
5944
+ "notes": {
5945
+ "type": "string"
5946
+ },
5947
+ "items": {
5948
+ "type": "array",
5949
+ "items": {
5950
+ "type": "string"
5951
+ }
5952
+ }
5953
+ },
5954
+ "description": "`arguments` of the Chatty tool `create_checklist` (POST /api/chatty-voice/tools/execute)."
5955
+ },
5956
+ "ChattyCreateChecklistData": {
5957
+ "type": "object",
5958
+ "properties": {
5959
+ "id": {
5960
+ "type": "integer"
5961
+ },
5962
+ "name": {
5963
+ "type": "string"
5964
+ },
5965
+ "jobId": {
5966
+ "type": "integer"
5967
+ },
5968
+ "itemCount": {
5969
+ "type": "integer"
5970
+ },
5971
+ "templateId": {
5972
+ "type": "integer"
5973
+ },
5974
+ "sections": {
5975
+ "type": "array",
5976
+ "items": {
5977
+ "type": "object",
5978
+ "properties": {
5979
+ "title": {
5980
+ "type": "string"
5981
+ },
5982
+ "items": {
5983
+ "type": "array",
5984
+ "items": {
5985
+ "type": "object",
5986
+ "properties": {
5987
+ "itemText": {
5988
+ "type": "string"
5989
+ },
5990
+ "itemType": {
5991
+ "type": "string",
5992
+ "enum": [
5993
+ "checkbox",
5994
+ "yes/no",
5995
+ "text",
5996
+ "number",
5997
+ "date",
5998
+ "dropdown",
5999
+ "multi-select",
6000
+ "photo",
6001
+ "signature"
6002
+ ]
6003
+ },
6004
+ "required": {
6005
+ "type": "boolean"
6006
+ }
6007
+ },
6008
+ "required": [
6009
+ "itemText",
6010
+ "itemType",
6011
+ "required"
6012
+ ]
6013
+ }
6014
+ }
6015
+ },
6016
+ "required": [
6017
+ "title",
6018
+ "items"
6019
+ ]
6020
+ }
6021
+ }
6022
+ },
6023
+ "required": [
6024
+ "id",
6025
+ "name",
6026
+ "jobId",
6027
+ "itemCount"
6028
+ ],
6029
+ "description": "`data` of a successful `create_checklist` call (`success: true`)."
6030
+ },
6031
+ "ChattyAddChecklistItemArguments": {
6032
+ "type": "object",
6033
+ "properties": {
6034
+ "checklistId": {
6035
+ "anyOf": [
6036
+ {
6037
+ "type": "integer",
6038
+ "exclusiveMinimum": 0
6039
+ },
6040
+ {
6041
+ "type": "string",
6042
+ "pattern": "^\\d+$"
6043
+ }
6044
+ ]
6045
+ },
6046
+ "checklistName": {
6047
+ "type": "string"
6048
+ },
6049
+ "jobId": {
6050
+ "anyOf": [
6051
+ {
6052
+ "type": "integer",
6053
+ "exclusiveMinimum": 0
6054
+ },
6055
+ {
6056
+ "type": "string",
6057
+ "pattern": "^\\d+$"
6058
+ }
6059
+ ]
6060
+ },
6061
+ "itemText": {
6062
+ "type": "string"
6063
+ },
6064
+ "itemType": {
6065
+ "type": "string",
6066
+ "enum": [
6067
+ "checkbox",
6068
+ "yes/no",
6069
+ "text",
6070
+ "number",
6071
+ "date",
6072
+ "dropdown",
6073
+ "multi-select",
6074
+ "photo",
6075
+ "signature"
6076
+ ]
6077
+ },
6078
+ "required": {
6079
+ "type": "boolean"
6080
+ },
6081
+ "description": {
6082
+ "type": "string"
6083
+ },
6084
+ "sectionName": {
6085
+ "type": "string"
6086
+ }
6087
+ },
6088
+ "required": [
6089
+ "itemText"
6090
+ ],
6091
+ "description": "`arguments` of the Chatty tool `add_checklist_item` (POST /api/chatty-voice/tools/execute)."
6092
+ },
6093
+ "ChattyAddChecklistItemData": {
6094
+ "type": "object",
6095
+ "properties": {
6096
+ "id": {
6097
+ "type": "integer"
6098
+ },
6099
+ "checklistId": {
6100
+ "type": "integer"
6101
+ },
6102
+ "itemText": {
6103
+ "type": "string"
6104
+ },
6105
+ "itemType": {
6106
+ "type": "string",
6107
+ "enum": [
6108
+ "checkbox",
6109
+ "yes/no",
6110
+ "text",
6111
+ "number",
6112
+ "date",
6113
+ "dropdown",
6114
+ "multi-select",
6115
+ "photo",
6116
+ "signature"
6117
+ ]
6118
+ },
6119
+ "required": {
6120
+ "type": "boolean"
6121
+ },
6122
+ "section": {
6123
+ "type": [
6124
+ "string",
6125
+ "null"
6126
+ ]
6127
+ }
6128
+ },
6129
+ "required": [
6130
+ "id",
6131
+ "checklistId",
6132
+ "itemText",
6133
+ "itemType",
6134
+ "required",
6135
+ "section"
6136
+ ],
6137
+ "description": "`data` of a successful `add_checklist_item` call (`success: true`)."
6138
+ },
6139
+ "ChattyCompleteChecklistItemArguments": {
6140
+ "type": "object",
6141
+ "properties": {
6142
+ "checklistId": {
6143
+ "anyOf": [
6144
+ {
6145
+ "type": "integer",
6146
+ "exclusiveMinimum": 0
6147
+ },
6148
+ {
6149
+ "type": "string",
6150
+ "pattern": "^\\d+$"
6151
+ }
6152
+ ]
6153
+ },
6154
+ "checklistName": {
6155
+ "type": "string"
6156
+ },
6157
+ "jobId": {
6158
+ "anyOf": [
6159
+ {
6160
+ "type": "integer",
6161
+ "exclusiveMinimum": 0
6162
+ },
6163
+ {
6164
+ "type": "string",
6165
+ "pattern": "^\\d+$"
6166
+ }
6167
+ ]
6168
+ },
6169
+ "itemId": {
6170
+ "anyOf": [
6171
+ {
6172
+ "type": "integer",
6173
+ "exclusiveMinimum": 0
6174
+ },
6175
+ {
6176
+ "type": "string",
6177
+ "pattern": "^\\d+$"
6178
+ }
6179
+ ]
6180
+ },
6181
+ "itemText": {
6182
+ "type": "string"
6183
+ },
6184
+ "completed": {
6185
+ "type": "boolean"
6186
+ }
6187
+ },
6188
+ "description": "`arguments` of the Chatty tool `complete_checklist_item` (POST /api/chatty-voice/tools/execute)."
6189
+ },
6190
+ "ChattyCompleteChecklistItemData": {
6191
+ "type": "object",
6192
+ "properties": {
6193
+ "checklistId": {
6194
+ "type": "integer"
6195
+ },
6196
+ "itemId": {
6197
+ "type": "integer"
6198
+ },
6199
+ "completed": {
6200
+ "type": "boolean"
6201
+ }
6202
+ },
6203
+ "required": [
6204
+ "checklistId",
6205
+ "itemId",
6206
+ "completed"
6207
+ ],
6208
+ "description": "`data` of a successful `complete_checklist_item` call (`success: true`)."
6209
+ },
6210
+ "ChattySetChecklistItemAnswerArguments": {
6211
+ "type": "object",
6212
+ "properties": {
6213
+ "checklistId": {
6214
+ "anyOf": [
6215
+ {
6216
+ "type": "integer",
6217
+ "exclusiveMinimum": 0
6218
+ },
6219
+ {
6220
+ "type": "string",
6221
+ "pattern": "^\\d+$"
6222
+ }
6223
+ ]
6224
+ },
6225
+ "checklistName": {
6226
+ "type": "string"
6227
+ },
6228
+ "jobId": {
6229
+ "anyOf": [
6230
+ {
6231
+ "type": "integer",
6232
+ "exclusiveMinimum": 0
6233
+ },
6234
+ {
6235
+ "type": "string",
6236
+ "pattern": "^\\d+$"
6237
+ }
6238
+ ]
6239
+ },
6240
+ "itemId": {
6241
+ "anyOf": [
6242
+ {
6243
+ "type": "integer",
6244
+ "exclusiveMinimum": 0
6245
+ },
6246
+ {
6247
+ "type": "string",
6248
+ "pattern": "^\\d+$"
6249
+ }
6250
+ ]
6251
+ },
6252
+ "itemText": {
6253
+ "type": "string"
6254
+ },
6255
+ "value": {
6256
+ "type": "string"
6257
+ }
6258
+ },
6259
+ "required": [
6260
+ "value"
6261
+ ],
6262
+ "description": "`arguments` of the Chatty tool `set_checklist_item_answer` (POST /api/chatty-voice/tools/execute)."
6263
+ },
6264
+ "ChattySetChecklistItemAnswerData": {
6265
+ "type": "object",
6266
+ "properties": {
6267
+ "checklistId": {
6268
+ "type": "integer"
6269
+ },
6270
+ "itemId": {
6271
+ "type": "integer"
6272
+ },
6273
+ "value": {
6274
+ "type": "string"
6275
+ }
6276
+ },
6277
+ "required": [
6278
+ "checklistId",
6279
+ "itemId",
6280
+ "value"
6281
+ ],
6282
+ "description": "`data` of a successful `set_checklist_item_answer` call (`success: true`)."
6283
+ },
6284
+ "ChattyAttachReferencePhotoToItemArguments": {
6285
+ "type": "object",
6286
+ "properties": {
6287
+ "checklistId": {
6288
+ "anyOf": [
6289
+ {
6290
+ "type": "integer",
6291
+ "exclusiveMinimum": 0
6292
+ },
6293
+ {
6294
+ "type": "string",
6295
+ "pattern": "^\\d+$"
6296
+ }
6297
+ ]
6298
+ },
6299
+ "checklistName": {
6300
+ "type": "string"
6301
+ },
6302
+ "jobId": {
6303
+ "anyOf": [
6304
+ {
6305
+ "type": "integer",
6306
+ "exclusiveMinimum": 0
6307
+ },
6308
+ {
6309
+ "type": "string",
6310
+ "pattern": "^\\d+$"
6311
+ }
6312
+ ]
6313
+ },
6314
+ "itemId": {
6315
+ "anyOf": [
6316
+ {
6317
+ "type": "integer",
6318
+ "exclusiveMinimum": 0
6319
+ },
6320
+ {
6321
+ "type": "string",
6322
+ "pattern": "^\\d+$"
6323
+ }
6324
+ ]
6325
+ },
6326
+ "itemText": {
6327
+ "type": "string"
6328
+ },
6329
+ "photoId": {
6330
+ "anyOf": [
6331
+ {
6332
+ "type": "integer",
6333
+ "exclusiveMinimum": 0
6334
+ },
6335
+ {
6336
+ "type": "string",
6337
+ "pattern": "^\\d+$"
6338
+ }
6339
+ ]
6340
+ },
6341
+ "caption": {
6342
+ "type": "string"
6343
+ }
6344
+ },
6345
+ "required": [
6346
+ "photoId"
6347
+ ],
6348
+ "description": "`arguments` of the Chatty tool `attach_reference_photo_to_item` (POST /api/chatty-voice/tools/execute)."
6349
+ },
6350
+ "ChattyAttachReferencePhotoToItemData": {
6351
+ "type": "object",
6352
+ "properties": {
6353
+ "checklistId": {
6354
+ "type": "integer"
6355
+ },
6356
+ "itemId": {
6357
+ "type": "integer"
6358
+ },
6359
+ "referenceMedia": {
6360
+ "type": "array",
6361
+ "items": {
6362
+ "type": "object",
6363
+ "properties": {
6364
+ "assetId": {
6365
+ "type": "string",
6366
+ "minLength": 1,
6367
+ "maxLength": 64
6368
+ },
6369
+ "caption": {
6370
+ "type": [
6371
+ "string",
6372
+ "null"
6373
+ ],
6374
+ "maxLength": 300
6375
+ },
6376
+ "order": {
6377
+ "type": "integer",
6378
+ "minimum": 0
6379
+ }
6380
+ },
6381
+ "required": [
6382
+ "assetId"
6383
+ ]
6384
+ }
6385
+ }
6386
+ },
6387
+ "required": [
6388
+ "checklistId",
6389
+ "itemId",
6390
+ "referenceMedia"
6391
+ ],
6392
+ "description": "`data` of a successful `attach_reference_photo_to_item` call (`success: true`)."
6393
+ },
6394
+ "ChattyDraftChecklistFromJobPhotosArguments": {
6395
+ "type": "object",
6396
+ "properties": {
6397
+ "jobId": {
6398
+ "anyOf": [
6399
+ {
6400
+ "type": "integer",
6401
+ "exclusiveMinimum": 0
6402
+ },
6403
+ {
6404
+ "type": "string",
6405
+ "pattern": "^\\d+$"
6406
+ }
6407
+ ]
6408
+ },
6409
+ "name": {
6410
+ "type": "string"
6411
+ },
6412
+ "create": {
6413
+ "type": "boolean"
6414
+ }
6415
+ },
6416
+ "description": "`arguments` of the Chatty tool `draft_checklist_from_job_photos` (POST /api/chatty-voice/tools/execute)."
6417
+ },
6418
+ "ChattyDraftChecklistFromJobPhotosData": {
6419
+ "type": "object",
6420
+ "properties": {
6421
+ "id": {
6422
+ "type": "integer"
6423
+ },
6424
+ "jobId": {
6425
+ "type": "integer"
6426
+ },
6427
+ "name": {
6428
+ "type": "string"
6429
+ },
6430
+ "items": {
6431
+ "type": "array",
6432
+ "items": {
6433
+ "type": "object",
6434
+ "properties": {
6435
+ "itemText": {
6436
+ "type": "string"
6437
+ },
6438
+ "photos": {
6439
+ "type": "integer"
6440
+ }
6441
+ },
6442
+ "required": [
6443
+ "itemText",
6444
+ "photos"
6445
+ ]
6446
+ }
6447
+ },
6448
+ "unsortedPhotos": {
6449
+ "type": "integer"
6450
+ },
6451
+ "created": {
6452
+ "type": "boolean"
6453
+ }
6454
+ },
6455
+ "required": [
6456
+ "name",
6457
+ "items",
6458
+ "unsortedPhotos",
6459
+ "created"
6460
+ ],
6461
+ "description": "`data` of a successful `draft_checklist_from_job_photos` call (`success: true`)."
6462
+ }
6463
+ },
6464
+ "parameters": {}
6465
+ },
6466
+ "paths": {
6467
+ "/api/version": {
6468
+ "get": {
6469
+ "summary": "Cross-platform version handshake manifest.",
6470
+ "tags": [
6471
+ "version"
6472
+ ],
6473
+ "responses": {
6474
+ "200": {
6475
+ "description": "Always returned. Body is the canonical handshake manifest.",
6476
+ "content": {
6477
+ "application/json": {
6478
+ "schema": {
6479
+ "$ref": "#/components/schemas/VersionManifest"
6480
+ }
6481
+ }
6482
+ }
6483
+ }
6484
+ }
6485
+ }
6486
+ },
6487
+ "/api/ping": {
6488
+ "get": {
6489
+ "summary": "Liveness probe. Bypasses the version handshake.",
6490
+ "tags": [
6491
+ "version"
6492
+ ],
6493
+ "responses": {
6494
+ "200": {
6495
+ "description": "Static OK envelope.",
6496
+ "content": {
6497
+ "application/json": {
6498
+ "schema": {
6499
+ "type": "object",
6500
+ "properties": {
6501
+ "status": {
6502
+ "type": "string",
6503
+ "enum": [
6504
+ "ok"
6505
+ ]
6506
+ },
6507
+ "timestamp": {
6508
+ "type": "string"
6509
+ },
6510
+ "env": {
6511
+ "type": [
6512
+ "string",
6513
+ "null"
6514
+ ]
6515
+ }
6516
+ },
6517
+ "required": [
6518
+ "status",
6519
+ "timestamp",
6520
+ "env"
6521
+ ]
6522
+ }
6523
+ }
6524
+ }
6525
+ }
6526
+ }
6527
+ }
6528
+ },
6529
+ "/api/me/features": {
6530
+ "get": {
6531
+ "summary": "Capability discovery — iOS calls on launch to gate UI affordances.",
6532
+ "tags": [
6533
+ "auth",
6534
+ "features"
6535
+ ],
6536
+ "parameters": [
6537
+ {
6538
+ "name": "X-Client-Version",
6539
+ "in": "header",
6540
+ "required": false,
6541
+ "schema": {
6542
+ "type": "string",
6543
+ "example": "1.0.0"
6544
+ },
6545
+ "description": "Semver of the calling app build. Drives the 426 / soft-upgrade handshake."
6546
+ }
6547
+ ],
6548
+ "responses": {
6549
+ "200": {
6550
+ "description": "Flat feature map. Unknown / missing flags must be treated as false by the client.",
6551
+ "content": {
6552
+ "application/json": {
6553
+ "schema": {
6554
+ "$ref": "#/components/schemas/FeatureFlags"
6555
+ }
6556
+ }
6557
+ }
6558
+ },
6559
+ "426": {
6560
+ "description": "Client major below minClientVersion.",
6561
+ "content": {
6562
+ "application/json": {
6563
+ "schema": {
6564
+ "$ref": "#/components/schemas/UpgradeRequiredEnvelope"
6565
+ }
6566
+ }
6567
+ }
6568
+ }
6569
+ }
6570
+ }
6571
+ },
6572
+ "/api/impersonate/native-read-ticket": {
6573
+ "post": {
6574
+ "tags": [
6575
+ "auth"
6576
+ ],
6577
+ "summary": "Authorize an exact browser-native download URL for the current support session.",
6578
+ "description": "Requires the current typed support session and X-Support-Impersonation: 1. A narrow fixed GET allowlist only; record permissions still run on every GET. Admission lasts at most 15 minutes and never outlives the original one-hour support grant. The same browser session is required; URL alone is insufficient. GET/Range retries recheck current authority. Response is no-store with no-referrer. No user bearer is issued.",
6579
+ "security": [
6580
+ {
6581
+ "BrowserSession": []
6582
+ }
6583
+ ],
6584
+ "parameters": [
6585
+ {
6586
+ "schema": {
6587
+ "type": "string",
6588
+ "enum": [
6589
+ "1"
6590
+ ]
6591
+ },
6592
+ "required": true,
6593
+ "name": "X-Support-Impersonation",
6594
+ "in": "header"
6595
+ }
6596
+ ],
6597
+ "requestBody": {
6598
+ "required": true,
6599
+ "content": {
6600
+ "application/json": {
6601
+ "schema": {
6602
+ "type": "object",
6603
+ "properties": {
6604
+ "url": {
6605
+ "type": "string",
6606
+ "minLength": 1,
6607
+ "maxLength": 1024
6608
+ }
6609
+ },
6610
+ "required": [
6611
+ "url"
6612
+ ],
6613
+ "additionalProperties": false
6614
+ }
6615
+ }
6616
+ }
6617
+ },
6618
+ "responses": {
6619
+ "200": {
6620
+ "description": "Exact relative URL and terminal admission deadline.",
6621
+ "content": {
6622
+ "application/json": {
6623
+ "schema": {
6624
+ "type": "object",
6625
+ "properties": {
6626
+ "url": {
6627
+ "type": "string",
6628
+ "minLength": 1,
6629
+ "maxLength": 8192
6630
+ },
6631
+ "expiresAt": {
6632
+ "type": "integer",
6633
+ "exclusiveMinimum": 0
6634
+ }
6635
+ },
6636
+ "required": [
6637
+ "url",
6638
+ "expiresAt"
6639
+ ],
6640
+ "additionalProperties": false
6641
+ }
6642
+ }
6643
+ }
6644
+ },
6645
+ "400": {
6646
+ "description": "Unsupported destination or malformed request."
6647
+ },
6648
+ "401": {
6649
+ "description": "No authenticated session."
6650
+ },
6651
+ "403": {
6652
+ "description": "Support authority unavailable; explicit exit required.",
5043
6653
  "content": {
5044
6654
  "application/json": {
5045
6655
  "schema": {
5046
- "$ref": "#/components/schemas/VersionManifest"
6656
+ "$ref": "#/components/schemas/StreamAuthenticationError"
6657
+ }
6658
+ }
6659
+ }
6660
+ },
6661
+ "503": {
6662
+ "description": "Authentication lookup temporarily unavailable.",
6663
+ "content": {
6664
+ "application/json": {
6665
+ "schema": {
6666
+ "$ref": "#/components/schemas/StreamAuthenticationError"
5047
6667
  }
5048
6668
  }
5049
6669
  }
@@ -5051,84 +6671,159 @@
5051
6671
  }
5052
6672
  }
5053
6673
  },
5054
- "/api/ping": {
5055
- "get": {
5056
- "summary": "Liveness probe. Bypasses the version handshake.",
6674
+ "/api/events/ticket": {
6675
+ "post": {
5057
6676
  "tags": [
5058
- "version"
6677
+ "auth"
6678
+ ],
6679
+ "summary": "Create a short-lived stream-only admission ticket from the current authenticated actor.",
6680
+ "description": "Connect within at most 60 seconds using GET /api/events?ticket=.... The ticket preserves the real principal, effective target and original login/impersonation deadlines; it cannot authenticate ordinary API requests. It is never a target-user bearer token. Response Cache-Control is no-store. An invalid temporary context returns 403 and must be explicitly exited, without dropping the real login.",
6681
+ "security": [
6682
+ {
6683
+ "UserBearer": []
6684
+ },
6685
+ {
6686
+ "BrowserSession": []
6687
+ },
6688
+ {
6689
+ "BrowserAuthCookie": []
6690
+ }
5059
6691
  ],
6692
+ "requestBody": {
6693
+ "required": false,
6694
+ "content": {
6695
+ "application/json": {
6696
+ "schema": {
6697
+ "type": "object",
6698
+ "properties": {},
6699
+ "additionalProperties": false
6700
+ }
6701
+ }
6702
+ }
6703
+ },
5060
6704
  "responses": {
5061
6705
  "200": {
5062
- "description": "Static OK envelope.",
6706
+ "description": "Opaque ticket, usable only for short-lived stream admission.",
6707
+ "content": {
6708
+ "application/json": {
6709
+ "schema": {
6710
+ "$ref": "#/components/schemas/EventStreamTicketResponse"
6711
+ }
6712
+ }
6713
+ }
6714
+ },
6715
+ "400": {
6716
+ "description": "Unexpected request fields.",
5063
6717
  "content": {
5064
6718
  "application/json": {
5065
6719
  "schema": {
5066
6720
  "type": "object",
5067
6721
  "properties": {
5068
- "status": {
5069
- "type": "string",
5070
- "enum": [
5071
- "ok"
5072
- ]
5073
- },
5074
- "timestamp": {
6722
+ "message": {
5075
6723
  "type": "string"
5076
6724
  },
5077
- "env": {
5078
- "type": [
5079
- "string",
5080
- "null"
5081
- ]
6725
+ "errors": {
6726
+ "type": "array",
6727
+ "items": {}
5082
6728
  }
5083
6729
  },
5084
6730
  "required": [
5085
- "status",
5086
- "timestamp",
5087
- "env"
6731
+ "message",
6732
+ "errors"
5088
6733
  ]
5089
6734
  }
5090
6735
  }
5091
6736
  }
6737
+ },
6738
+ "401": {
6739
+ "description": "Real principal is missing, deleted, revoked or expired.",
6740
+ "content": {
6741
+ "application/json": {
6742
+ "schema": {
6743
+ "$ref": "#/components/schemas/StreamAuthenticationError"
6744
+ }
6745
+ }
6746
+ }
6747
+ },
6748
+ "403": {
6749
+ "description": "Impersonation is unavailable; explicitly exit before continuing as the real principal.",
6750
+ "content": {
6751
+ "application/json": {
6752
+ "schema": {
6753
+ "$ref": "#/components/schemas/StreamAuthenticationError"
6754
+ }
6755
+ }
6756
+ }
6757
+ },
6758
+ "503": {
6759
+ "description": "Authentication lookup unavailable; retry without discarding credentials.",
6760
+ "content": {
6761
+ "application/json": {
6762
+ "schema": {
6763
+ "$ref": "#/components/schemas/StreamAuthenticationError"
6764
+ }
6765
+ }
6766
+ }
5092
6767
  }
5093
6768
  }
5094
6769
  }
5095
6770
  },
5096
- "/api/me/features": {
6771
+ "/api/events": {
5097
6772
  "get": {
5098
- "summary": "Capability discovery — iOS calls on launch to gate UI affordances.",
5099
6773
  "tags": [
5100
- "auth",
5101
- "features"
6774
+ "auth"
5102
6775
  ],
6776
+ "summary": "Open the authenticated server-sent event stream.",
6777
+ "description": "New clients use a stream-only ticket in the ticket query parameter. Legacy authenticated connections remain supported. A supplied invalid ticket never falls back to another credential. Current user, session and revocation state is rechecked before admission and each delivery batch/heartbeat. Original authority deadlines also close idle or blocked sockets. A stream:resync hint means refresh authorized snapshots; this stream is not a replay log.",
5103
6778
  "parameters": [
5104
6779
  {
5105
- "name": "X-Client-Version",
5106
- "in": "header",
5107
- "required": false,
5108
6780
  "schema": {
5109
6781
  "type": "string",
5110
- "example": "1.0.0"
6782
+ "minLength": 1,
6783
+ "maxLength": 8192
5111
6784
  },
5112
- "description": "Semver of the calling app build. Drives the 426 / soft-upgrade handshake."
6785
+ "required": false,
6786
+ "name": "ticket",
6787
+ "in": "query"
5113
6788
  }
5114
6789
  ],
5115
6790
  "responses": {
5116
6791
  "200": {
5117
- "description": "Flat feature map. Unknown / missing flags must be treated as false by the client.",
6792
+ "description": "Bounded SSE hints and heartbeat comments until disconnect or authority expiry.",
6793
+ "content": {
6794
+ "text/event-stream": {
6795
+ "schema": {
6796
+ "type": "string"
6797
+ }
6798
+ }
6799
+ }
6800
+ },
6801
+ "401": {
6802
+ "description": "Ticket/source authentication expired, revoked or invalid.",
5118
6803
  "content": {
5119
6804
  "application/json": {
5120
6805
  "schema": {
5121
- "$ref": "#/components/schemas/FeatureFlags"
6806
+ "$ref": "#/components/schemas/StreamAuthenticationError"
5122
6807
  }
5123
6808
  }
5124
6809
  }
5125
6810
  },
5126
- "426": {
5127
- "description": "Client major below minClientVersion.",
6811
+ "403": {
6812
+ "description": "Legacy temporary context is unavailable.",
5128
6813
  "content": {
5129
6814
  "application/json": {
5130
6815
  "schema": {
5131
- "$ref": "#/components/schemas/UpgradeRequiredEnvelope"
6816
+ "$ref": "#/components/schemas/StreamAuthenticationError"
6817
+ }
6818
+ }
6819
+ }
6820
+ },
6821
+ "503": {
6822
+ "description": "Authorization temporarily unavailable; retry with backoff.",
6823
+ "content": {
6824
+ "application/json": {
6825
+ "schema": {
6826
+ "$ref": "#/components/schemas/StreamAuthenticationError"
5132
6827
  }
5133
6828
  }
5134
6829
  }
@@ -11150,6 +12845,175 @@
11150
12845
  }
11151
12846
  }
11152
12847
  }
12848
+ },
12849
+ "/api/projects/{projectId}/documents/draft-from-walkthrough": {
12850
+ "post": {
12851
+ "tags": [
12852
+ "checklists"
12853
+ ],
12854
+ "summary": "Turn a voice walk-through (timed transcript + photos) into a checklist draft.",
12855
+ "description": "Returns a DRAFT only; nothing is saved to the job. The phone's review screen creates the checklist with POST /api/projects/{projectId}/documents (custom `items`, carrying `referenceMedia`). Sections come from, in order: the camera pose of a scan, the room the tech named (the item's words, the photo's room chip, a section opened), the AI Image Sort's room for the item's photo (add-on), then the last room mentioned; items with no signal go to Not sure. GPS is never used. Item types come from spoken hints only (checkbox unless \"photo required\", \"yes or no\" or a reading; \"required\" sets the flag). Reference photos are the shots taken from 10 s before a sentence to 20 s after it. 200 when the draft is ready at once; 202 with `runId` while the photos go through an AI vision sort (poll the runs route). Requires the job (404 otherwise) and the Create Checklists permission (403). Photos that are not the organization's assets are left out.",
12856
+ "parameters": [
12857
+ {
12858
+ "name": "projectId",
12859
+ "in": "path",
12860
+ "required": true,
12861
+ "schema": {
12862
+ "type": "integer",
12863
+ "minimum": 1
12864
+ }
12865
+ }
12866
+ ],
12867
+ "requestBody": {
12868
+ "required": true,
12869
+ "content": {
12870
+ "application/json": {
12871
+ "schema": {
12872
+ "$ref": "#/components/schemas/WalkthroughDraftRequest"
12873
+ }
12874
+ }
12875
+ }
12876
+ },
12877
+ "responses": {
12878
+ "200": {
12879
+ "description": "The draft (status completed).",
12880
+ "content": {
12881
+ "application/json": {
12882
+ "schema": {
12883
+ "$ref": "#/components/schemas/WalkthroughDraftResponse"
12884
+ }
12885
+ }
12886
+ }
12887
+ },
12888
+ "202": {
12889
+ "description": "A vision sort runs first (status running); poll GET …/draft-from-walkthrough/runs/{runId}.",
12890
+ "content": {
12891
+ "application/json": {
12892
+ "schema": {
12893
+ "$ref": "#/components/schemas/WalkthroughDraftResponse"
12894
+ }
12895
+ }
12896
+ }
12897
+ },
12898
+ "400": {
12899
+ "description": "No transcript, or a wrong shape.",
12900
+ "content": {
12901
+ "application/json": {
12902
+ "schema": {
12903
+ "$ref": "#/components/schemas/ErrorEnvelope"
12904
+ }
12905
+ }
12906
+ }
12907
+ },
12908
+ "401": {
12909
+ "description": "Authentication required."
12910
+ },
12911
+ "403": {
12912
+ "description": "The role cannot create checklists.",
12913
+ "content": {
12914
+ "application/json": {
12915
+ "schema": {
12916
+ "$ref": "#/components/schemas/ErrorEnvelope"
12917
+ }
12918
+ }
12919
+ }
12920
+ },
12921
+ "404": {
12922
+ "description": "Job not found.",
12923
+ "content": {
12924
+ "application/json": {
12925
+ "schema": {
12926
+ "$ref": "#/components/schemas/ErrorEnvelope"
12927
+ }
12928
+ }
12929
+ }
12930
+ },
12931
+ "502": {
12932
+ "description": "The AI's answer could not be used.",
12933
+ "content": {
12934
+ "application/json": {
12935
+ "schema": {
12936
+ "$ref": "#/components/schemas/ErrorEnvelope"
12937
+ }
12938
+ }
12939
+ }
12940
+ },
12941
+ "503": {
12942
+ "description": "AI is not configured.",
12943
+ "content": {
12944
+ "application/json": {
12945
+ "schema": {
12946
+ "$ref": "#/components/schemas/ErrorEnvelope"
12947
+ }
12948
+ }
12949
+ }
12950
+ }
12951
+ }
12952
+ }
12953
+ },
12954
+ "/api/projects/{projectId}/documents/draft-from-walkthrough/runs/{runId}": {
12955
+ "get": {
12956
+ "tags": [
12957
+ "checklists"
12958
+ ],
12959
+ "summary": "Poll a walk-through draft that waits for an AI vision sort.",
12960
+ "description": "Status `running` (with the sort's progress in `sortRun`) until the draft is ready, then `completed` with `draft`, or `failed` with `message`. A run that stops making progress is marked failed on the next poll and never re-run.",
12961
+ "parameters": [
12962
+ {
12963
+ "name": "projectId",
12964
+ "in": "path",
12965
+ "required": true,
12966
+ "schema": {
12967
+ "type": "integer",
12968
+ "minimum": 1
12969
+ }
12970
+ },
12971
+ {
12972
+ "name": "runId",
12973
+ "in": "path",
12974
+ "required": true,
12975
+ "schema": {
12976
+ "type": "integer",
12977
+ "minimum": 1
12978
+ }
12979
+ }
12980
+ ],
12981
+ "responses": {
12982
+ "200": {
12983
+ "description": "The run's envelope.",
12984
+ "content": {
12985
+ "application/json": {
12986
+ "schema": {
12987
+ "$ref": "#/components/schemas/WalkthroughDraftResponse"
12988
+ }
12989
+ }
12990
+ }
12991
+ },
12992
+ "401": {
12993
+ "description": "Authentication required."
12994
+ },
12995
+ "403": {
12996
+ "description": "The role cannot create checklists.",
12997
+ "content": {
12998
+ "application/json": {
12999
+ "schema": {
13000
+ "$ref": "#/components/schemas/ErrorEnvelope"
13001
+ }
13002
+ }
13003
+ }
13004
+ },
13005
+ "404": {
13006
+ "description": "Job or run not found.",
13007
+ "content": {
13008
+ "application/json": {
13009
+ "schema": {
13010
+ "$ref": "#/components/schemas/ErrorEnvelope"
13011
+ }
13012
+ }
13013
+ }
13014
+ }
13015
+ }
13016
+ }
11153
13017
  }
11154
13018
  },
11155
13019
  "webhooks": {}