@thinkai/tai-api-contract 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2277 @@
1
+ openapi: 3.0.3
2
+ info:
3
+ title: ThinkAI API
4
+ version: 0.16.0
5
+ description: >
6
+ Contract surface for the Performance Intelligence Platform backend used by ThinkAI.
7
+ Tenant-scoped routes use `/tenants/{tenantId}/...` and require membership.
8
+ Admin routes use `/admin/...` and require role `admin`.
9
+ Legacy HTTP routes that exist on the server but are not listed here (for example
10
+ `PUT /tenants/{tenantId}/dashboard-settings`) remain supported for existing PIP clients;
11
+ prefer OpenAPI-documented equivalents where available. Removal will be coordinated with ThinkAI releases.
12
+ security:
13
+ - bearerAuth: []
14
+ tags:
15
+ - name: Tenant
16
+ description: Workspace bootstrap (§13)
17
+ - name: CompanyProfile
18
+ description: Company profile (§1)
19
+ - name: AIReadiness
20
+ description: AI readiness assessment (§2)
21
+ - name: TechStack
22
+ description: Tech stack (§3)
23
+ - name: NDA
24
+ description: NDA flows (§4, §14 storagePath)
25
+ - name: RepositoryReadiness
26
+ description: Repository readiness (§5)
27
+ - name: SquadProjects
28
+ description: Squad and projects (§6)
29
+ - name: Notifications
30
+ description: Notifications (§7)
31
+ - name: AdminReviewer
32
+ description: Admin review queue (§8)
33
+ - name: AIStrategy
34
+ description: AI strategy recommendations (§9)
35
+ - name: Journey
36
+ description: Journey progress (§10)
37
+ - name: Me
38
+ description: Authenticated user profile (§11)
39
+ - name: Preferences
40
+ description: Per-user per-tenant preferences (§12)
41
+ - name: OrgChartImport
42
+ description: Org chart import via storage path (§14)
43
+
44
+ paths:
45
+ /tenants:
46
+ post:
47
+ tags: [Tenant]
48
+ summary: Create tenant
49
+ operationId: createTenant
50
+ requestBody:
51
+ required: true
52
+ content:
53
+ application/json:
54
+ schema:
55
+ $ref: "#/components/schemas/CreateTenantBodyDto"
56
+ responses:
57
+ "201":
58
+ description: Tenant created or acknowledged (idempotent; same body if already existed)
59
+ content:
60
+ application/json:
61
+ schema:
62
+ $ref: "#/components/schemas/CreateTenantResponseDto"
63
+ "401":
64
+ $ref: "#/components/responses/Unauthorized"
65
+
66
+ /me:
67
+ get:
68
+ tags: [Me]
69
+ summary: Current user profile
70
+ operationId: getMe
71
+ responses:
72
+ "200":
73
+ description: Profile
74
+ content:
75
+ application/json:
76
+ schema:
77
+ $ref: "#/components/schemas/MeProfileDto"
78
+ "401":
79
+ $ref: "#/components/responses/Unauthorized"
80
+ put:
81
+ tags: [Me]
82
+ summary: Update current user profile
83
+ operationId: updateMe
84
+ requestBody:
85
+ required: true
86
+ content:
87
+ application/json:
88
+ schema:
89
+ $ref: "#/components/schemas/UpdateMeBodyDto"
90
+ responses:
91
+ "204":
92
+ description: Updated
93
+ "401":
94
+ $ref: "#/components/responses/Unauthorized"
95
+
96
+ /me/workspaces:
97
+ get:
98
+ tags: [Me]
99
+ summary: Workspaces visible to the authenticated user
100
+ operationId: listMyWorkspaces
101
+ responses:
102
+ "200":
103
+ description: Workspace list for switcher
104
+ content:
105
+ application/json:
106
+ schema:
107
+ $ref: "#/components/schemas/WorkspacesForUserDto"
108
+ "401":
109
+ $ref: "#/components/responses/Unauthorized"
110
+
111
+ /workspaces:
112
+ post:
113
+ tags: [Tenant]
114
+ summary: Create workspace
115
+ operationId: createWorkspace
116
+ requestBody:
117
+ required: true
118
+ content:
119
+ application/json:
120
+ schema:
121
+ $ref: "#/components/schemas/CreateWorkspaceBodyDto"
122
+ responses:
123
+ "201":
124
+ description: Workspace created
125
+ content:
126
+ application/json:
127
+ schema:
128
+ $ref: "#/components/schemas/WorkspaceSummaryDto"
129
+ "401":
130
+ $ref: "#/components/responses/Unauthorized"
131
+
132
+ /workspaces/{workspaceId}/organization:
133
+ get:
134
+ tags: [CompanyProfile]
135
+ summary: Get workspace organization profile
136
+ operationId: getWorkspaceOrganization
137
+ parameters:
138
+ - name: workspaceId
139
+ in: path
140
+ required: true
141
+ schema: { type: string }
142
+ responses:
143
+ "200":
144
+ description: Organization profile or null if unset
145
+ content:
146
+ application/json:
147
+ schema:
148
+ $ref: "#/components/schemas/OrganizationDto"
149
+ "401":
150
+ $ref: "#/components/responses/Unauthorized"
151
+ put:
152
+ tags: [CompanyProfile]
153
+ summary: Upsert workspace organization profile
154
+ operationId: putWorkspaceOrganization
155
+ parameters:
156
+ - name: workspaceId
157
+ in: path
158
+ required: true
159
+ schema: { type: string }
160
+ requestBody:
161
+ required: true
162
+ content:
163
+ application/json:
164
+ schema:
165
+ $ref: "#/components/schemas/OrganizationDto"
166
+ responses:
167
+ "204":
168
+ description: Updated
169
+ "401":
170
+ $ref: "#/components/responses/Unauthorized"
171
+
172
+ /tenants/{tenantId}/members:
173
+ get:
174
+ tags: [Tenant]
175
+ summary: List tenant team members
176
+ operationId: listTenantMembers
177
+ parameters:
178
+ - $ref: "#/components/parameters/TenantId"
179
+ responses:
180
+ "200":
181
+ description: Team members for tenant
182
+ content:
183
+ application/json:
184
+ schema:
185
+ $ref: "#/components/schemas/TeamMemberListDto"
186
+ "401":
187
+ $ref: "#/components/responses/Unauthorized"
188
+ "403":
189
+ $ref: "#/components/responses/Forbidden"
190
+
191
+ /tenants/{tenantId}/members/invite:
192
+ post:
193
+ tags: [Tenant]
194
+ summary: Invite member to tenant
195
+ operationId: inviteTenantMember
196
+ parameters:
197
+ - $ref: "#/components/parameters/TenantId"
198
+ requestBody:
199
+ required: true
200
+ content:
201
+ application/json:
202
+ schema:
203
+ $ref: "#/components/schemas/InviteTeamMemberBodyDto"
204
+ responses:
205
+ "201":
206
+ description: Invited member row
207
+ content:
208
+ application/json:
209
+ schema:
210
+ $ref: "#/components/schemas/TeamMemberDto"
211
+ "401":
212
+ $ref: "#/components/responses/Unauthorized"
213
+ "403":
214
+ $ref: "#/components/responses/Forbidden"
215
+
216
+ /tenants/{tenantId}/members/{memberId}:
217
+ patch:
218
+ tags: [Tenant]
219
+ summary: Update tenant member role
220
+ operationId: updateTenantMemberRole
221
+ parameters:
222
+ - $ref: "#/components/parameters/TenantId"
223
+ - name: memberId
224
+ in: path
225
+ required: true
226
+ schema: { type: string }
227
+ requestBody:
228
+ required: true
229
+ content:
230
+ application/json:
231
+ schema:
232
+ $ref: "#/components/schemas/UpdateTeamMemberRoleBodyDto"
233
+ responses:
234
+ "200":
235
+ description: Updated member row
236
+ content:
237
+ application/json:
238
+ schema:
239
+ $ref: "#/components/schemas/TeamMemberDto"
240
+ "401":
241
+ $ref: "#/components/responses/Unauthorized"
242
+ "403":
243
+ $ref: "#/components/responses/Forbidden"
244
+ "404":
245
+ description: Member not found
246
+ delete:
247
+ tags: [Tenant]
248
+ summary: Remove member from tenant
249
+ operationId: removeTenantMember
250
+ parameters:
251
+ - $ref: "#/components/parameters/TenantId"
252
+ - name: memberId
253
+ in: path
254
+ required: true
255
+ schema: { type: string }
256
+ responses:
257
+ "204":
258
+ description: Removed
259
+ "401":
260
+ $ref: "#/components/responses/Unauthorized"
261
+ "403":
262
+ $ref: "#/components/responses/Forbidden"
263
+ "404":
264
+ description: Member not found
265
+
266
+ /tenants/{tenantId}/org-chart:
267
+ get:
268
+ tags: [Tenant]
269
+ summary: Get org chart tree
270
+ operationId: getTenantOrgChart
271
+ parameters:
272
+ - $ref: "#/components/parameters/TenantId"
273
+ - name: withScores
274
+ in: query
275
+ schema: { type: boolean }
276
+ responses:
277
+ "200":
278
+ description: Org chart (optionally with per-node scores)
279
+ content:
280
+ application/json:
281
+ schema:
282
+ $ref: "#/components/schemas/OrgChartDto"
283
+ "401":
284
+ $ref: "#/components/responses/Unauthorized"
285
+ "404":
286
+ description: Tenant not found
287
+ post:
288
+ tags: [Tenant]
289
+ summary: Save org chart tree
290
+ operationId: postTenantOrgChart
291
+ parameters:
292
+ - $ref: "#/components/parameters/TenantId"
293
+ requestBody:
294
+ required: true
295
+ content:
296
+ application/json:
297
+ schema:
298
+ $ref: "#/components/schemas/OrgChartDto"
299
+ responses:
300
+ "200":
301
+ description: Saved
302
+ content:
303
+ application/json:
304
+ schema:
305
+ type: object
306
+ required: [ok, tenantId]
307
+ properties:
308
+ ok: { type: boolean }
309
+ tenantId: { type: string }
310
+ "401":
311
+ $ref: "#/components/responses/Unauthorized"
312
+
313
+ /tenants/{tenantId}/sources:
314
+ put:
315
+ tags: [Tenant]
316
+ summary: Replace tenant data sources
317
+ operationId: putTenantSources
318
+ parameters:
319
+ - $ref: "#/components/parameters/TenantId"
320
+ requestBody:
321
+ required: true
322
+ content:
323
+ application/json:
324
+ schema:
325
+ type: object
326
+ required: [sources]
327
+ properties:
328
+ sources:
329
+ type: array
330
+ items:
331
+ $ref: "#/components/schemas/TenantSourceEntryDto"
332
+ responses:
333
+ "200":
334
+ description: Saved
335
+ content:
336
+ application/json:
337
+ schema:
338
+ type: object
339
+ required: [ok, tenantId]
340
+ properties:
341
+ ok: { type: boolean }
342
+ tenantId: { type: string }
343
+ "401":
344
+ $ref: "#/components/responses/Unauthorized"
345
+
346
+ /tenants/{tenantId}/sources/test:
347
+ post:
348
+ tags: [Tenant]
349
+ summary: Test one source connection (does not persist)
350
+ operationId: postTenantSourceTest
351
+ parameters:
352
+ - $ref: "#/components/parameters/TenantId"
353
+ requestBody:
354
+ required: true
355
+ content:
356
+ application/json:
357
+ schema:
358
+ $ref: "#/components/schemas/TenantSourceEntryDto"
359
+ responses:
360
+ "200":
361
+ description: Connection test result
362
+ content:
363
+ application/json:
364
+ schema:
365
+ $ref: "#/components/schemas/TestConnectionResponseDto"
366
+ "400":
367
+ description: Invalid body or missing env for token refs
368
+ "401":
369
+ $ref: "#/components/responses/Unauthorized"
370
+
371
+ /tenants/{tenantId}/dashboard/productivity:
372
+ get:
373
+ tags: [Tenant]
374
+ summary: CTO dashboard productivity snapshot
375
+ operationId: getDashboardProductivity
376
+ parameters:
377
+ - $ref: "#/components/parameters/TenantId"
378
+ - name: scope
379
+ in: query
380
+ schema:
381
+ type: string
382
+ enum: [org, team, person]
383
+ - name: teamId
384
+ in: query
385
+ schema: { type: string }
386
+ - name: personId
387
+ in: query
388
+ schema: { type: string }
389
+ - name: windowEnd
390
+ in: query
391
+ schema: { type: string, format: date-time }
392
+ responses:
393
+ "200":
394
+ description: Productivity metrics
395
+ content:
396
+ application/json:
397
+ schema:
398
+ $ref: "#/components/schemas/DashboardProductivityDto"
399
+ "401":
400
+ $ref: "#/components/responses/Unauthorized"
401
+
402
+ /tenants/{tenantId}/dashboard/productivity/history:
403
+ get:
404
+ tags: [Tenant]
405
+ summary: CTO dashboard productivity time series
406
+ operationId: getDashboardProductivityHistory
407
+ parameters:
408
+ - $ref: "#/components/parameters/TenantId"
409
+ - name: bucket
410
+ in: query
411
+ schema: { type: string, enum: [day, week, month] }
412
+ - name: limit
413
+ in: query
414
+ schema: { type: integer, minimum: 1 }
415
+ - name: scope
416
+ in: query
417
+ schema:
418
+ type: string
419
+ enum: [org, team, person]
420
+ - name: teamId
421
+ in: query
422
+ schema: { type: string }
423
+ - name: personId
424
+ in: query
425
+ schema: { type: string }
426
+ - name: windowEnd
427
+ in: query
428
+ schema: { type: string, format: date-time }
429
+ responses:
430
+ "200":
431
+ description: Bucketed history
432
+ content:
433
+ application/json:
434
+ schema:
435
+ $ref: "#/components/schemas/DashboardProductivityHistoryDto"
436
+ "401":
437
+ $ref: "#/components/responses/Unauthorized"
438
+
439
+ /admin/reviews:
440
+ get:
441
+ tags: [AdminReviewer]
442
+ summary: Admin review queue
443
+ operationId: listAdminReviews
444
+ parameters:
445
+ - name: status
446
+ in: query
447
+ schema: { type: string }
448
+ - name: priority
449
+ in: query
450
+ schema: { type: string }
451
+ - name: reviewer
452
+ in: query
453
+ schema: { type: string }
454
+ responses:
455
+ "200":
456
+ description: Queue and reviewer list
457
+ content:
458
+ application/json:
459
+ schema:
460
+ $ref: "#/components/schemas/AdminDashboardDto"
461
+ "401":
462
+ $ref: "#/components/responses/Unauthorized"
463
+ "403":
464
+ $ref: "#/components/responses/Forbidden"
465
+
466
+ /admin/reviews/{id}:
467
+ get:
468
+ tags: [AdminReviewer]
469
+ summary: Single review submission
470
+ operationId: getAdminReview
471
+ parameters:
472
+ - $ref: "#/components/parameters/ReviewId"
473
+ responses:
474
+ "200":
475
+ description: Review detail
476
+ content:
477
+ application/json:
478
+ schema:
479
+ $ref: "#/components/schemas/ReviewSubmissionDto"
480
+ "401":
481
+ $ref: "#/components/responses/Unauthorized"
482
+ "403":
483
+ $ref: "#/components/responses/Forbidden"
484
+ patch:
485
+ tags: [AdminReviewer]
486
+ summary: Update review metadata
487
+ operationId: patchAdminReview
488
+ parameters:
489
+ - $ref: "#/components/parameters/ReviewId"
490
+ requestBody:
491
+ required: true
492
+ content:
493
+ application/json:
494
+ schema:
495
+ $ref: "#/components/schemas/PatchAdminReviewBodyDto"
496
+ responses:
497
+ "200":
498
+ description: Updated review
499
+ content:
500
+ application/json:
501
+ schema:
502
+ $ref: "#/components/schemas/ReviewSubmissionDto"
503
+ "401":
504
+ $ref: "#/components/responses/Unauthorized"
505
+ "403":
506
+ $ref: "#/components/responses/Forbidden"
507
+
508
+ /admin/reviews/{id}/sections/{sectionId}/comments:
509
+ post:
510
+ tags: [AdminReviewer]
511
+ summary: Add section comment
512
+ operationId: postAdminReviewComment
513
+ parameters:
514
+ - $ref: "#/components/parameters/ReviewId"
515
+ - $ref: "#/components/parameters/SectionId"
516
+ requestBody:
517
+ required: true
518
+ content:
519
+ application/json:
520
+ schema:
521
+ $ref: "#/components/schemas/AdminCommentBodyDto"
522
+ responses:
523
+ "200":
524
+ description: Created comment
525
+ content:
526
+ application/json:
527
+ schema:
528
+ $ref: "#/components/schemas/CommentDto"
529
+ "401":
530
+ $ref: "#/components/responses/Unauthorized"
531
+ "403":
532
+ $ref: "#/components/responses/Forbidden"
533
+
534
+ /admin/reviews/{id}/sections/{sectionId}/decision:
535
+ put:
536
+ tags: [AdminReviewer]
537
+ summary: Set section decision
538
+ operationId: putAdminReviewSectionDecision
539
+ parameters:
540
+ - $ref: "#/components/parameters/ReviewId"
541
+ - $ref: "#/components/parameters/SectionId"
542
+ requestBody:
543
+ required: true
544
+ content:
545
+ application/json:
546
+ schema:
547
+ $ref: "#/components/schemas/SectionDecisionBodyDto"
548
+ responses:
549
+ "204":
550
+ description: Saved
551
+ "401":
552
+ $ref: "#/components/responses/Unauthorized"
553
+ "403":
554
+ $ref: "#/components/responses/Forbidden"
555
+
556
+ /admin/reviews/{id}/pricing:
557
+ put:
558
+ tags: [AdminReviewer]
559
+ summary: Update pricing lines
560
+ operationId: putAdminReviewPricing
561
+ parameters:
562
+ - $ref: "#/components/parameters/ReviewId"
563
+ requestBody:
564
+ required: true
565
+ content:
566
+ application/json:
567
+ schema:
568
+ $ref: "#/components/schemas/PricingUpdateBodyDto"
569
+ responses:
570
+ "204":
571
+ description: Saved
572
+ "401":
573
+ $ref: "#/components/responses/Unauthorized"
574
+ "403":
575
+ $ref: "#/components/responses/Forbidden"
576
+
577
+ /admin/reviews/{id}/deployment:
578
+ put:
579
+ tags: [AdminReviewer]
580
+ summary: Update deployment plan
581
+ operationId: putAdminReviewDeployment
582
+ parameters:
583
+ - $ref: "#/components/parameters/ReviewId"
584
+ requestBody:
585
+ required: true
586
+ content:
587
+ application/json:
588
+ schema:
589
+ $ref: "#/components/schemas/DeploymentPlanDto"
590
+ responses:
591
+ "204":
592
+ description: Saved
593
+ "401":
594
+ $ref: "#/components/responses/Unauthorized"
595
+ "403":
596
+ $ref: "#/components/responses/Forbidden"
597
+
598
+ /tenants/{tenantId}/company-profile:
599
+ get:
600
+ tags: [CompanyProfile]
601
+ summary: Get company profile
602
+ operationId: getCompanyProfile
603
+ parameters:
604
+ - $ref: "#/components/parameters/TenantId"
605
+ responses:
606
+ "200":
607
+ description: Profile or JSON null if unset
608
+ content:
609
+ application/json:
610
+ schema:
611
+ $ref: "#/components/schemas/CompanyProfileDto"
612
+ examples:
613
+ sample:
614
+ value:
615
+ companyName: Acme
616
+ industry: software
617
+ companySize: "51-200"
618
+ engineeringHC: "42"
619
+ headquarters: "Austin, TX"
620
+ "401":
621
+ $ref: "#/components/responses/Unauthorized"
622
+ put:
623
+ tags: [CompanyProfile]
624
+ summary: Upsert company profile
625
+ operationId: putCompanyProfile
626
+ parameters:
627
+ - $ref: "#/components/parameters/TenantId"
628
+ requestBody:
629
+ required: true
630
+ content:
631
+ application/json:
632
+ schema:
633
+ $ref: "#/components/schemas/CompanyProfileDto"
634
+ responses:
635
+ "204":
636
+ description: Saved
637
+ "401":
638
+ $ref: "#/components/responses/Unauthorized"
639
+
640
+ /tenants/{tenantId}/ai-readiness:
641
+ get:
642
+ tags: [AIReadiness]
643
+ summary: Get AI readiness
644
+ operationId: getAiReadiness
645
+ parameters:
646
+ - $ref: "#/components/parameters/TenantId"
647
+ responses:
648
+ "200":
649
+ description: State or JSON null
650
+ content:
651
+ application/json:
652
+ schema:
653
+ $ref: "#/components/schemas/AIReadinessDto"
654
+ "401":
655
+ $ref: "#/components/responses/Unauthorized"
656
+ put:
657
+ tags: [AIReadiness]
658
+ summary: Upsert AI readiness
659
+ operationId: putAiReadiness
660
+ parameters:
661
+ - $ref: "#/components/parameters/TenantId"
662
+ requestBody:
663
+ required: true
664
+ content:
665
+ application/json:
666
+ schema:
667
+ $ref: "#/components/schemas/AIReadinessDto"
668
+ responses:
669
+ "204":
670
+ description: Saved
671
+ "401":
672
+ $ref: "#/components/responses/Unauthorized"
673
+
674
+ /tenants/{tenantId}/ai-readiness/maturity:
675
+ post:
676
+ tags: [AIReadiness]
677
+ summary: Compute maturity level
678
+ operationId: postAiReadinessMaturity
679
+ parameters:
680
+ - $ref: "#/components/parameters/TenantId"
681
+ requestBody:
682
+ required: true
683
+ content:
684
+ application/json:
685
+ schema:
686
+ $ref: "#/components/schemas/AIReadinessDto"
687
+ responses:
688
+ "200":
689
+ description: Derived level
690
+ content:
691
+ application/json:
692
+ schema:
693
+ $ref: "#/components/schemas/AiMaturityResultDto"
694
+ "401":
695
+ $ref: "#/components/responses/Unauthorized"
696
+
697
+ /tenants/{tenantId}/tech-stack:
698
+ get:
699
+ tags: [TechStack]
700
+ summary: Get tech stack
701
+ operationId: getTechStack
702
+ parameters:
703
+ - $ref: "#/components/parameters/TenantId"
704
+ responses:
705
+ "200":
706
+ description: Stack or JSON null
707
+ content:
708
+ application/json:
709
+ schema:
710
+ $ref: "#/components/schemas/TechStackDto"
711
+ "401":
712
+ $ref: "#/components/responses/Unauthorized"
713
+ put:
714
+ tags: [TechStack]
715
+ summary: Upsert tech stack
716
+ operationId: putTechStack
717
+ parameters:
718
+ - $ref: "#/components/parameters/TenantId"
719
+ requestBody:
720
+ required: true
721
+ content:
722
+ application/json:
723
+ schema:
724
+ $ref: "#/components/schemas/TechStackDto"
725
+ responses:
726
+ "204":
727
+ description: Saved
728
+ "401":
729
+ $ref: "#/components/responses/Unauthorized"
730
+
731
+ /tenants/{tenantId}/nda:
732
+ get:
733
+ tags: [NDA]
734
+ summary: Get NDA completion state
735
+ operationId: getNda
736
+ parameters:
737
+ - $ref: "#/components/parameters/TenantId"
738
+ responses:
739
+ "200":
740
+ description: Completion or JSON null
741
+ content:
742
+ application/json:
743
+ schema:
744
+ $ref: "#/components/schemas/NdaCompletionDto"
745
+ "401":
746
+ $ref: "#/components/responses/Unauthorized"
747
+
748
+ /tenants/{tenantId}/nda/template:
749
+ get:
750
+ tags: [NDA]
751
+ summary: NDA template for display
752
+ operationId: getNdaTemplate
753
+ parameters:
754
+ - $ref: "#/components/parameters/TenantId"
755
+ responses:
756
+ "200":
757
+ description: Template
758
+ content:
759
+ application/json:
760
+ schema:
761
+ $ref: "#/components/schemas/NdaTemplateDto"
762
+ "401":
763
+ $ref: "#/components/responses/Unauthorized"
764
+
765
+ /tenants/{tenantId}/nda/sign:
766
+ post:
767
+ tags: [NDA]
768
+ summary: Electronic NDA signature
769
+ operationId: postNdaSign
770
+ parameters:
771
+ - $ref: "#/components/parameters/TenantId"
772
+ requestBody:
773
+ required: true
774
+ content:
775
+ application/json:
776
+ schema:
777
+ $ref: "#/components/schemas/NdaSignatureDto"
778
+ responses:
779
+ "200":
780
+ description: Completion record
781
+ content:
782
+ application/json:
783
+ schema:
784
+ $ref: "#/components/schemas/NdaCompletionDto"
785
+ "401":
786
+ $ref: "#/components/responses/Unauthorized"
787
+
788
+ /tenants/{tenantId}/nda/external:
789
+ post:
790
+ tags: [NDA]
791
+ summary: External NDA path (after Supabase upload)
792
+ description: >
793
+ Preferred body uses `storagePath` after client upload to the `nda-documents` bucket (§14).
794
+ Multipart variant may be supported by the server as an alternative.
795
+ operationId: postNdaExternal
796
+ parameters:
797
+ - $ref: "#/components/parameters/TenantId"
798
+ requestBody:
799
+ required: true
800
+ content:
801
+ application/json:
802
+ schema:
803
+ $ref: "#/components/schemas/NdaExternalBodyDto"
804
+ responses:
805
+ "200":
806
+ description: Completion record
807
+ content:
808
+ application/json:
809
+ schema:
810
+ $ref: "#/components/schemas/NdaCompletionDto"
811
+ "401":
812
+ $ref: "#/components/responses/Unauthorized"
813
+
814
+ /tenants/{tenantId}/readiness/repos:
815
+ get:
816
+ tags: [RepositoryReadiness]
817
+ summary: List repo readiness scores
818
+ operationId: listReadinessRepos
819
+ parameters:
820
+ - $ref: "#/components/parameters/TenantId"
821
+ responses:
822
+ "200":
823
+ description: Repositories analyzed
824
+ content:
825
+ application/json:
826
+ schema:
827
+ type: array
828
+ items:
829
+ $ref: "#/components/schemas/RepoReadinessScoreDto"
830
+ "401":
831
+ $ref: "#/components/responses/Unauthorized"
832
+
833
+ /tenants/{tenantId}/readiness/repos/{repoId}:
834
+ get:
835
+ tags: [RepositoryReadiness]
836
+ summary: Single repo readiness
837
+ operationId: getReadinessRepo
838
+ parameters:
839
+ - $ref: "#/components/parameters/TenantId"
840
+ - $ref: "#/components/parameters/RepoId"
841
+ responses:
842
+ "200":
843
+ description: Repo score
844
+ content:
845
+ application/json:
846
+ schema:
847
+ $ref: "#/components/schemas/RepoReadinessScoreDto"
848
+ "401":
849
+ $ref: "#/components/responses/Unauthorized"
850
+
851
+ /tenants/{tenantId}/readiness/dimensions:
852
+ get:
853
+ tags: [RepositoryReadiness]
854
+ summary: Readiness dimensions catalog
855
+ operationId: listReadinessDimensions
856
+ parameters:
857
+ - $ref: "#/components/parameters/TenantId"
858
+ responses:
859
+ "200":
860
+ description: Dimensions
861
+ content:
862
+ application/json:
863
+ schema:
864
+ type: array
865
+ items:
866
+ $ref: "#/components/schemas/ReadinessDimensionDto"
867
+ "401":
868
+ $ref: "#/components/responses/Unauthorized"
869
+
870
+ /tenants/{tenantId}/readiness/fixes:
871
+ get:
872
+ tags: [RepositoryReadiness]
873
+ summary: List fix requests
874
+ operationId: listReadinessFixes
875
+ parameters:
876
+ - $ref: "#/components/parameters/TenantId"
877
+ responses:
878
+ "200":
879
+ description: Fix queue
880
+ content:
881
+ application/json:
882
+ schema:
883
+ type: array
884
+ items:
885
+ $ref: "#/components/schemas/FixRequestDto"
886
+ "401":
887
+ $ref: "#/components/responses/Unauthorized"
888
+ post:
889
+ tags: [RepositoryReadiness]
890
+ summary: Enqueue fix for an issue
891
+ operationId: postReadinessFix
892
+ parameters:
893
+ - $ref: "#/components/parameters/TenantId"
894
+ requestBody:
895
+ required: true
896
+ content:
897
+ application/json:
898
+ schema:
899
+ $ref: "#/components/schemas/CreateFixRequestBodyDto"
900
+ responses:
901
+ "200":
902
+ description: Fix request created
903
+ content:
904
+ application/json:
905
+ schema:
906
+ $ref: "#/components/schemas/FixRequestDto"
907
+ "401":
908
+ $ref: "#/components/responses/Unauthorized"
909
+
910
+ /tenants/{tenantId}/squad:
911
+ get:
912
+ tags: [SquadProjects]
913
+ summary: Get squad configuration
914
+ operationId: getSquad
915
+ parameters:
916
+ - $ref: "#/components/parameters/TenantId"
917
+ responses:
918
+ "200":
919
+ description: Squad
920
+ content:
921
+ application/json:
922
+ schema:
923
+ $ref: "#/components/schemas/SquadDto"
924
+ "401":
925
+ $ref: "#/components/responses/Unauthorized"
926
+ put:
927
+ tags: [SquadProjects]
928
+ summary: Upsert squad
929
+ operationId: putSquad
930
+ parameters:
931
+ - $ref: "#/components/parameters/TenantId"
932
+ requestBody:
933
+ required: true
934
+ content:
935
+ application/json:
936
+ schema:
937
+ $ref: "#/components/schemas/SquadDto"
938
+ responses:
939
+ "204":
940
+ description: Saved
941
+ "401":
942
+ $ref: "#/components/responses/Unauthorized"
943
+
944
+ /tenants/{tenantId}/projects:
945
+ get:
946
+ tags: [SquadProjects]
947
+ summary: List projects
948
+ operationId: listProjects
949
+ parameters:
950
+ - $ref: "#/components/parameters/TenantId"
951
+ responses:
952
+ "200":
953
+ description: Projects
954
+ content:
955
+ application/json:
956
+ schema:
957
+ type: array
958
+ items:
959
+ $ref: "#/components/schemas/ProjectDto"
960
+ "401":
961
+ $ref: "#/components/responses/Unauthorized"
962
+ post:
963
+ tags: [SquadProjects]
964
+ summary: Create project
965
+ operationId: createProject
966
+ parameters:
967
+ - $ref: "#/components/parameters/TenantId"
968
+ requestBody:
969
+ required: true
970
+ content:
971
+ application/json:
972
+ schema:
973
+ $ref: "#/components/schemas/ProjectDto"
974
+ responses:
975
+ "200":
976
+ description: Created project
977
+ content:
978
+ application/json:
979
+ schema:
980
+ $ref: "#/components/schemas/ProjectDto"
981
+ "401":
982
+ $ref: "#/components/responses/Unauthorized"
983
+
984
+ /tenants/{tenantId}/projects/{projectId}:
985
+ patch:
986
+ tags: [SquadProjects]
987
+ summary: Update project
988
+ operationId: patchProject
989
+ parameters:
990
+ - $ref: "#/components/parameters/TenantId"
991
+ - $ref: "#/components/parameters/ProjectId"
992
+ requestBody:
993
+ required: true
994
+ content:
995
+ application/json:
996
+ schema:
997
+ $ref: "#/components/schemas/ProjectPatchDto"
998
+ responses:
999
+ "200":
1000
+ description: Updated project
1001
+ content:
1002
+ application/json:
1003
+ schema:
1004
+ $ref: "#/components/schemas/ProjectDto"
1005
+ "401":
1006
+ $ref: "#/components/responses/Unauthorized"
1007
+
1008
+ /tenants/{tenantId}/notifications:
1009
+ get:
1010
+ tags: [Notifications]
1011
+ summary: Paginated notifications
1012
+ operationId: listNotifications
1013
+ parameters:
1014
+ - $ref: "#/components/parameters/TenantId"
1015
+ - name: limit
1016
+ in: query
1017
+ schema: { type: integer, minimum: 1 }
1018
+ - name: offset
1019
+ in: query
1020
+ schema: { type: integer, minimum: 0 }
1021
+ responses:
1022
+ "200":
1023
+ description: Page of notifications
1024
+ content:
1025
+ application/json:
1026
+ schema:
1027
+ $ref: "#/components/schemas/NotificationListDto"
1028
+ "401":
1029
+ $ref: "#/components/responses/Unauthorized"
1030
+
1031
+ /tenants/{tenantId}/notifications/{id}/read:
1032
+ post:
1033
+ tags: [Notifications]
1034
+ summary: Mark notification read
1035
+ operationId: postNotificationRead
1036
+ parameters:
1037
+ - $ref: "#/components/parameters/TenantId"
1038
+ - $ref: "#/components/parameters/NotificationId"
1039
+ responses:
1040
+ "204":
1041
+ description: Updated
1042
+ "401":
1043
+ $ref: "#/components/responses/Unauthorized"
1044
+
1045
+ /tenants/{tenantId}/notifications/read-all:
1046
+ post:
1047
+ tags: [Notifications]
1048
+ summary: Mark all notifications read
1049
+ operationId: postNotificationsReadAll
1050
+ parameters:
1051
+ - $ref: "#/components/parameters/TenantId"
1052
+ responses:
1053
+ "204":
1054
+ description: Updated
1055
+ "401":
1056
+ $ref: "#/components/responses/Unauthorized"
1057
+
1058
+ /tenants/{tenantId}/ai-strategy/recommend:
1059
+ post:
1060
+ tags: [AIStrategy]
1061
+ summary: Generate AI strategy recommendations
1062
+ operationId: postAiStrategyRecommend
1063
+ parameters:
1064
+ - $ref: "#/components/parameters/TenantId"
1065
+ requestBody:
1066
+ required: true
1067
+ content:
1068
+ application/json:
1069
+ schema:
1070
+ $ref: "#/components/schemas/AiStrategyRecommendBodyDto"
1071
+ responses:
1072
+ "200":
1073
+ description: Plan
1074
+ content:
1075
+ application/json:
1076
+ schema:
1077
+ $ref: "#/components/schemas/AiStrategyPlanDto"
1078
+ "401":
1079
+ $ref: "#/components/responses/Unauthorized"
1080
+
1081
+ /tenants/{tenantId}/journey/progress:
1082
+ get:
1083
+ tags: [Journey]
1084
+ summary: Journey step completion
1085
+ operationId: getJourneyProgress
1086
+ parameters:
1087
+ - $ref: "#/components/parameters/TenantId"
1088
+ responses:
1089
+ "200":
1090
+ description: Progress
1091
+ content:
1092
+ application/json:
1093
+ schema:
1094
+ $ref: "#/components/schemas/JourneyProgressDto"
1095
+ "401":
1096
+ $ref: "#/components/responses/Unauthorized"
1097
+ put:
1098
+ tags: [Journey]
1099
+ summary: Replace completed steps
1100
+ operationId: putJourneyProgress
1101
+ parameters:
1102
+ - $ref: "#/components/parameters/TenantId"
1103
+ requestBody:
1104
+ required: true
1105
+ content:
1106
+ application/json:
1107
+ schema:
1108
+ $ref: "#/components/schemas/JourneyProgressUpdateDto"
1109
+ responses:
1110
+ "204":
1111
+ description: Saved
1112
+ "401":
1113
+ $ref: "#/components/responses/Unauthorized"
1114
+
1115
+ /tenants/{tenantId}/me/preferences:
1116
+ get:
1117
+ tags: [Preferences]
1118
+ summary: Get preferences for current user in tenant
1119
+ operationId: getMyPreferences
1120
+ parameters:
1121
+ - $ref: "#/components/parameters/TenantId"
1122
+ responses:
1123
+ "200":
1124
+ description: Preferences
1125
+ content:
1126
+ application/json:
1127
+ schema:
1128
+ $ref: "#/components/schemas/PreferencesDto"
1129
+ "401":
1130
+ $ref: "#/components/responses/Unauthorized"
1131
+ put:
1132
+ tags: [Preferences]
1133
+ summary: Upsert preferences
1134
+ operationId: putMyPreferences
1135
+ parameters:
1136
+ - $ref: "#/components/parameters/TenantId"
1137
+ requestBody:
1138
+ required: true
1139
+ content:
1140
+ application/json:
1141
+ schema:
1142
+ $ref: "#/components/schemas/PreferencesDto"
1143
+ responses:
1144
+ "204":
1145
+ description: Saved
1146
+ "401":
1147
+ $ref: "#/components/responses/Unauthorized"
1148
+
1149
+ /tenants/{tenantId}/org-chart/import:
1150
+ post:
1151
+ tags: [OrgChartImport]
1152
+ summary: Import org chart from Supabase storage path
1153
+ operationId: postOrgChartImport
1154
+ parameters:
1155
+ - $ref: "#/components/parameters/TenantId"
1156
+ requestBody:
1157
+ required: true
1158
+ content:
1159
+ application/json:
1160
+ schema:
1161
+ $ref: "#/components/schemas/OrgChartImportBodyDto"
1162
+ responses:
1163
+ "200":
1164
+ description: Parsed persons (shape TBD; align with backend)
1165
+ content:
1166
+ application/json:
1167
+ schema:
1168
+ type: object
1169
+ additionalProperties: true
1170
+ "401":
1171
+ $ref: "#/components/responses/Unauthorized"
1172
+
1173
+ components:
1174
+ securitySchemes:
1175
+ bearerAuth:
1176
+ type: http
1177
+ scheme: bearer
1178
+ bearerFormat: JWT
1179
+ description: Supabase access token (`Authorization` header).
1180
+
1181
+ parameters:
1182
+ TenantId:
1183
+ name: tenantId
1184
+ in: path
1185
+ required: true
1186
+ schema:
1187
+ type: string
1188
+ RepoId:
1189
+ name: repoId
1190
+ in: path
1191
+ required: true
1192
+ schema:
1193
+ type: string
1194
+ ProjectId:
1195
+ name: projectId
1196
+ in: path
1197
+ required: true
1198
+ schema:
1199
+ type: string
1200
+ ReviewId:
1201
+ name: id
1202
+ in: path
1203
+ required: true
1204
+ schema:
1205
+ type: string
1206
+ SectionId:
1207
+ name: sectionId
1208
+ in: path
1209
+ required: true
1210
+ schema:
1211
+ type: string
1212
+ NotificationId:
1213
+ name: id
1214
+ in: path
1215
+ required: true
1216
+ schema:
1217
+ type: string
1218
+
1219
+ responses:
1220
+ Unauthorized:
1221
+ description: Missing or invalid bearer token
1222
+ content:
1223
+ application/json:
1224
+ schema:
1225
+ $ref: "#/components/schemas/ErrorMessageDto"
1226
+ Forbidden:
1227
+ description: Authenticated but not allowed
1228
+ content:
1229
+ application/json:
1230
+ schema:
1231
+ $ref: "#/components/schemas/ErrorMessageDto"
1232
+
1233
+ schemas:
1234
+ ErrorMessageDto:
1235
+ type: object
1236
+ required: [error]
1237
+ properties:
1238
+ error:
1239
+ type: string
1240
+
1241
+ CreateTenantBodyDto:
1242
+ type: object
1243
+ required: [tenantId]
1244
+ properties:
1245
+ tenantId:
1246
+ type: string
1247
+
1248
+ CreateTenantResponseDto:
1249
+ type: object
1250
+ required: [tenantId, ok]
1251
+ properties:
1252
+ tenantId:
1253
+ type: string
1254
+ ok:
1255
+ type: boolean
1256
+
1257
+ TeamMemberRoleDto:
1258
+ type: string
1259
+ enum: [admin, editor, viewer]
1260
+
1261
+ TeamMemberDto:
1262
+ type: object
1263
+ required: [id, name, email, role]
1264
+ properties:
1265
+ id:
1266
+ type: string
1267
+ name:
1268
+ type: string
1269
+ email:
1270
+ type: string
1271
+ role:
1272
+ $ref: "#/components/schemas/TeamMemberRoleDto"
1273
+
1274
+ TeamMemberListDto:
1275
+ type: object
1276
+ required: [members]
1277
+ properties:
1278
+ members:
1279
+ type: array
1280
+ items:
1281
+ $ref: "#/components/schemas/TeamMemberDto"
1282
+
1283
+ InviteTeamMemberBodyDto:
1284
+ type: object
1285
+ required: [email, role]
1286
+ properties:
1287
+ email:
1288
+ type: string
1289
+ role:
1290
+ $ref: "#/components/schemas/TeamMemberRoleDto"
1291
+
1292
+ UpdateTeamMemberRoleBodyDto:
1293
+ type: object
1294
+ required: [role]
1295
+ properties:
1296
+ role:
1297
+ $ref: "#/components/schemas/TeamMemberRoleDto"
1298
+
1299
+ OrgChartTreeNodeDto:
1300
+ type: object
1301
+ required: [id]
1302
+ properties:
1303
+ id:
1304
+ type: string
1305
+ name:
1306
+ type: string
1307
+ type:
1308
+ type: string
1309
+ person_id:
1310
+ type: string
1311
+ team:
1312
+ type: string
1313
+ role:
1314
+ type: string
1315
+ level:
1316
+ type: string
1317
+ external_ids:
1318
+ type: object
1319
+ additionalProperties: { type: string }
1320
+ children:
1321
+ type: array
1322
+ items:
1323
+ $ref: "#/components/schemas/OrgChartTreeNodeDto"
1324
+
1325
+ OrgChartDto:
1326
+ type: object
1327
+ required: [root]
1328
+ properties:
1329
+ root:
1330
+ $ref: "#/components/schemas/OrgChartTreeNodeDto"
1331
+
1332
+ TenantSourceEntryDto:
1333
+ type: object
1334
+ required: [type]
1335
+ properties:
1336
+ type:
1337
+ type: string
1338
+ additionalProperties: true
1339
+
1340
+ TestConnectionResponseDto:
1341
+ type: object
1342
+ required: [success]
1343
+ properties:
1344
+ success:
1345
+ type: boolean
1346
+ error:
1347
+ type: string
1348
+
1349
+ DashboardProductivityMetricsDto:
1350
+ type: object
1351
+ description: Nested metric groups; see TypeScript `DashboardProductivityMetricsDto` in @thinkai/tai-api-contract.
1352
+ additionalProperties: true
1353
+
1354
+ DashboardProductivityDto:
1355
+ type: object
1356
+ required: [tenantId, windowStart, windowEnd, scope, metrics]
1357
+ properties:
1358
+ tenantId:
1359
+ type: string
1360
+ windowStart:
1361
+ type: string
1362
+ format: date-time
1363
+ windowEnd:
1364
+ type: string
1365
+ format: date-time
1366
+ scope:
1367
+ type: string
1368
+ enum: [org, team, person]
1369
+ metrics:
1370
+ $ref: "#/components/schemas/DashboardProductivityMetricsDto"
1371
+ meta:
1372
+ type: object
1373
+ additionalProperties: true
1374
+
1375
+ DashboardProductivityHistoryDto:
1376
+ type: object
1377
+ required: [buckets]
1378
+ properties:
1379
+ buckets:
1380
+ type: array
1381
+ items:
1382
+ type: object
1383
+ required: [bucketStart, bucketEnd, metrics]
1384
+ properties:
1385
+ bucketStart:
1386
+ type: string
1387
+ format: date-time
1388
+ bucketEnd:
1389
+ type: string
1390
+ format: date-time
1391
+ metrics:
1392
+ $ref: "#/components/schemas/DashboardProductivityMetricsDto"
1393
+
1394
+ MeProfileDto:
1395
+ type: object
1396
+ required: [id, email, name, roles]
1397
+ properties:
1398
+ id:
1399
+ type: string
1400
+ email:
1401
+ type: string
1402
+ name:
1403
+ type: string
1404
+ roles:
1405
+ type: array
1406
+ items:
1407
+ type: string
1408
+ defaultWorkspaceId:
1409
+ type: string
1410
+ nullable: true
1411
+
1412
+ UpdateMeBodyDto:
1413
+ type: object
1414
+ properties:
1415
+ name:
1416
+ type: string
1417
+ email:
1418
+ type: string
1419
+ defaultWorkspaceId:
1420
+ type: string
1421
+ nullable: true
1422
+
1423
+ WorkspaceSummaryDto:
1424
+ type: object
1425
+ required: [id, slug, name, status]
1426
+ properties:
1427
+ id:
1428
+ type: string
1429
+ slug:
1430
+ type: string
1431
+ name:
1432
+ type: string
1433
+ status:
1434
+ type: string
1435
+
1436
+ WorkspacesForUserDto:
1437
+ type: object
1438
+ required: [workspaces]
1439
+ properties:
1440
+ workspaces:
1441
+ type: array
1442
+ items:
1443
+ $ref: "#/components/schemas/WorkspaceSummaryDto"
1444
+
1445
+ CreateWorkspaceBodyDto:
1446
+ type: object
1447
+ required: [slug, name]
1448
+ properties:
1449
+ slug:
1450
+ type: string
1451
+ name:
1452
+ type: string
1453
+
1454
+ OrganizationDto:
1455
+ type: object
1456
+ required: [workspaceId, legalName]
1457
+ properties:
1458
+ workspaceId:
1459
+ type: string
1460
+ legalName:
1461
+ type: string
1462
+ industry:
1463
+ type: string
1464
+ companySize:
1465
+ type: string
1466
+ engineeringHeadcount:
1467
+ type: integer
1468
+ nullable: true
1469
+ headquarters:
1470
+ type: string
1471
+ metadata:
1472
+ type: object
1473
+ additionalProperties: true
1474
+
1475
+ CompanyProfileDto:
1476
+ type: object
1477
+ required: [companyName, industry, companySize, engineeringHC, headquarters]
1478
+ properties:
1479
+ companyName:
1480
+ type: string
1481
+ industry:
1482
+ type: string
1483
+ industryOther:
1484
+ type: string
1485
+ companySize:
1486
+ type: string
1487
+ description: "One of 1-50 | 51-200 | 201-500 | 501-1000 | 1000+"
1488
+ engineeringHC:
1489
+ type: string
1490
+ headquarters:
1491
+ type: string
1492
+
1493
+ AIReadinessDto:
1494
+ type: object
1495
+ required:
1496
+ - currentUsage
1497
+ - tools
1498
+ - satisfaction
1499
+ - painPointPhases
1500
+ - maturityLevel
1501
+ - maturityConfirmed
1502
+ properties:
1503
+ currentUsage:
1504
+ type: string
1505
+ tools:
1506
+ type: array
1507
+ items:
1508
+ type: string
1509
+ customTools:
1510
+ type: string
1511
+ models:
1512
+ type: string
1513
+ spend:
1514
+ type: string
1515
+ satisfaction:
1516
+ type: integer
1517
+ minimum: 0
1518
+ maximum: 5
1519
+ painPointPhases:
1520
+ type: array
1521
+ items:
1522
+ type: string
1523
+ maturityLevel:
1524
+ type: integer
1525
+ minimum: -1
1526
+ maximum: 4
1527
+ maturityConfirmed:
1528
+ type: boolean
1529
+ nullable: true
1530
+ challenges:
1531
+ type: string
1532
+ goals:
1533
+ type: string
1534
+
1535
+ AiMaturityResultDto:
1536
+ type: object
1537
+ required: [level, needsConfirmation]
1538
+ properties:
1539
+ level:
1540
+ type: integer
1541
+ minimum: 0
1542
+ maximum: 4
1543
+ needsConfirmation:
1544
+ type: boolean
1545
+
1546
+ TechCategoryDto:
1547
+ type: object
1548
+ required: [items]
1549
+ properties:
1550
+ items:
1551
+ type: array
1552
+ items:
1553
+ type: string
1554
+
1555
+ TechStackDto:
1556
+ type: object
1557
+ required: [sourceControl, cicd, pm, monitoring, knowledgeDocs, hrPeople]
1558
+ properties:
1559
+ sourceControl:
1560
+ $ref: "#/components/schemas/TechCategoryDto"
1561
+ cicd:
1562
+ $ref: "#/components/schemas/TechCategoryDto"
1563
+ pm:
1564
+ type: object
1565
+ required: [items, methodology, sprintLength]
1566
+ properties:
1567
+ items:
1568
+ type: array
1569
+ items:
1570
+ type: string
1571
+ methodology:
1572
+ type: string
1573
+ sprintLength:
1574
+ type: string
1575
+ monitoring:
1576
+ $ref: "#/components/schemas/TechCategoryDto"
1577
+ knowledgeDocs:
1578
+ $ref: "#/components/schemas/TechCategoryDto"
1579
+ hrPeople:
1580
+ $ref: "#/components/schemas/TechCategoryDto"
1581
+
1582
+ NdaTemplateDto:
1583
+ type: object
1584
+ required: [title, body]
1585
+ properties:
1586
+ title:
1587
+ type: string
1588
+ body:
1589
+ type: array
1590
+ items:
1591
+ type: string
1592
+
1593
+ NdaSignatureDto:
1594
+ type: object
1595
+ required: [fullName, date, ipAddress, signed]
1596
+ properties:
1597
+ fullName:
1598
+ type: string
1599
+ date:
1600
+ type: string
1601
+ ipAddress:
1602
+ type: string
1603
+ signed:
1604
+ type: boolean
1605
+ electronicAcknowledgements:
1606
+ type: object
1607
+ additionalProperties:
1608
+ type: boolean
1609
+
1610
+ NdaUploadedDocumentDto:
1611
+ type: object
1612
+ required: [fileName, mimeType, size, uploadedAt]
1613
+ properties:
1614
+ fileName:
1615
+ type: string
1616
+ mimeType:
1617
+ type: string
1618
+ size:
1619
+ type: integer
1620
+ uploadedAt:
1621
+ type: string
1622
+ dataUrl:
1623
+ type: string
1624
+
1625
+ NdaCompletionDto:
1626
+ oneOf:
1627
+ - $ref: "#/components/schemas/NdaCompletionElectronicDto"
1628
+ - $ref: "#/components/schemas/NdaCompletionExternalDto"
1629
+ discriminator:
1630
+ propertyName: mode
1631
+ mapping:
1632
+ electronic: "#/components/schemas/NdaCompletionElectronicDto"
1633
+ external: "#/components/schemas/NdaCompletionExternalDto"
1634
+
1635
+ NdaCompletionElectronicDto:
1636
+ type: object
1637
+ required: [mode, signature]
1638
+ properties:
1639
+ mode:
1640
+ type: string
1641
+ enum: [electronic]
1642
+ signature:
1643
+ $ref: "#/components/schemas/NdaSignatureDto"
1644
+
1645
+ NdaCompletionExternalDto:
1646
+ type: object
1647
+ required: [mode, attestedAt, confirmedBy, confirmed, personalDataDpaAck, uploadedDocument]
1648
+ properties:
1649
+ mode:
1650
+ type: string
1651
+ enum: [external]
1652
+ attestedAt:
1653
+ type: string
1654
+ confirmedBy:
1655
+ type: string
1656
+ confirmed:
1657
+ type: boolean
1658
+ enum: [true]
1659
+ personalDataDpaAck:
1660
+ type: boolean
1661
+ enum: [true]
1662
+ uploadedDocument:
1663
+ $ref: "#/components/schemas/NdaUploadedDocumentDto"
1664
+
1665
+ NdaExternalBodyDto:
1666
+ type: object
1667
+ required: [confirmedBy, personalDataDpaAck, storagePath]
1668
+ properties:
1669
+ confirmedBy:
1670
+ type: string
1671
+ personalDataDpaAck:
1672
+ type: boolean
1673
+ storagePath:
1674
+ type: string
1675
+ description: Path in `nda-documents` bucket after Supabase upload
1676
+
1677
+ ReadinessDimensionDto:
1678
+ type: object
1679
+ required: [id, name, description, maxScore]
1680
+ properties:
1681
+ id:
1682
+ type: string
1683
+ name:
1684
+ type: string
1685
+ description:
1686
+ type: string
1687
+ maxScore:
1688
+ type: number
1689
+
1690
+ ReadinessIssueDto:
1691
+ type: object
1692
+ required: [id, dimensionId, severity, title, description, fixStatus]
1693
+ properties:
1694
+ id:
1695
+ type: string
1696
+ dimensionId:
1697
+ type: string
1698
+ severity:
1699
+ type: string
1700
+ enum: [critical, high, medium, low]
1701
+ title:
1702
+ type: string
1703
+ description:
1704
+ type: string
1705
+ filePath:
1706
+ type: string
1707
+ fixStatus:
1708
+ type: string
1709
+ enum: [open, pr-pending, fixed]
1710
+
1711
+ DimensionScoreDto:
1712
+ type: object
1713
+ required: [dimensionId, score, maxScore, issues]
1714
+ properties:
1715
+ dimensionId:
1716
+ type: string
1717
+ score:
1718
+ type: number
1719
+ maxScore:
1720
+ type: number
1721
+ issues:
1722
+ type: array
1723
+ items:
1724
+ $ref: "#/components/schemas/ReadinessIssueDto"
1725
+
1726
+ RepoReadinessScoreDto:
1727
+ type: object
1728
+ required: [repoId, repoName, language, overallScore, dimensions, lastAnalyzed]
1729
+ properties:
1730
+ repoId:
1731
+ type: string
1732
+ repoName:
1733
+ type: string
1734
+ language:
1735
+ type: string
1736
+ overallScore:
1737
+ type: number
1738
+ dimensions:
1739
+ type: array
1740
+ items:
1741
+ $ref: "#/components/schemas/DimensionScoreDto"
1742
+ lastAnalyzed:
1743
+ type: string
1744
+ format: date-time
1745
+ teamId:
1746
+ type: string
1747
+
1748
+ FixRequestDto:
1749
+ type: object
1750
+ required: [id, issueId, repoId, repoName, issueTitle, dimensionId, severity, status, createdAt]
1751
+ properties:
1752
+ id:
1753
+ type: string
1754
+ issueId:
1755
+ type: string
1756
+ repoId:
1757
+ type: string
1758
+ repoName:
1759
+ type: string
1760
+ issueTitle:
1761
+ type: string
1762
+ dimensionId:
1763
+ type: string
1764
+ severity:
1765
+ type: string
1766
+ enum: [critical, high, medium, low]
1767
+ status:
1768
+ type: string
1769
+ enum: [queued, generating, pr-created, merged]
1770
+ prUrl:
1771
+ type: string
1772
+ createdAt:
1773
+ type: string
1774
+ format: date-time
1775
+
1776
+ CreateFixRequestBodyDto:
1777
+ type: object
1778
+ required: [issueId, repoId]
1779
+ properties:
1780
+ issueId:
1781
+ type: string
1782
+ repoId:
1783
+ type: string
1784
+
1785
+ PhaseRoleDto:
1786
+ type: object
1787
+ required: [phase, assignment]
1788
+ properties:
1789
+ phase:
1790
+ type: string
1791
+ assignment:
1792
+ type: string
1793
+ enum: [orchestrate, review, both, none]
1794
+
1795
+ SquadMemberDto:
1796
+ type: object
1797
+ required: [id, role, roleLabel, description, count, phases]
1798
+ properties:
1799
+ id:
1800
+ type: string
1801
+ role:
1802
+ type: string
1803
+ roleLabel:
1804
+ type: string
1805
+ name:
1806
+ type: string
1807
+ description:
1808
+ type: string
1809
+ count:
1810
+ type: integer
1811
+ phases:
1812
+ type: array
1813
+ items:
1814
+ $ref: "#/components/schemas/PhaseRoleDto"
1815
+ custom:
1816
+ type: boolean
1817
+
1818
+ CustomWorkStreamTaskDto:
1819
+ type: object
1820
+ required: [id, name, summary]
1821
+ properties:
1822
+ id:
1823
+ type: string
1824
+ name:
1825
+ type: string
1826
+ summary:
1827
+ type: string
1828
+
1829
+ PhaseWorkStreamConfigDto:
1830
+ type: object
1831
+ properties:
1832
+ deselectedCatalogIds:
1833
+ type: array
1834
+ items:
1835
+ type: string
1836
+ customTasks:
1837
+ type: array
1838
+ items:
1839
+ $ref: "#/components/schemas/CustomWorkStreamTaskDto"
1840
+
1841
+ SquadDto:
1842
+ type: object
1843
+ required: [members, hrConnected]
1844
+ properties:
1845
+ members:
1846
+ type: array
1847
+ items:
1848
+ $ref: "#/components/schemas/SquadMemberDto"
1849
+ hrConnected:
1850
+ type: boolean
1851
+ selectedPhases:
1852
+ type: array
1853
+ items:
1854
+ type: string
1855
+ phaseWorkStreams:
1856
+ type: object
1857
+ additionalProperties:
1858
+ $ref: "#/components/schemas/PhaseWorkStreamConfigDto"
1859
+
1860
+ WorkflowDto:
1861
+ type: object
1862
+ required: [id, name, kinds, typeDescription, roles]
1863
+ properties:
1864
+ id:
1865
+ type: string
1866
+ name:
1867
+ type: string
1868
+ kinds:
1869
+ type: array
1870
+ items:
1871
+ type: string
1872
+ enum: [greenfield, brownfield]
1873
+ typeDescription:
1874
+ type: string
1875
+ roles:
1876
+ type: array
1877
+ items:
1878
+ type: string
1879
+
1880
+ ProjectDto:
1881
+ type: object
1882
+ required: [id, name, description, startDate, workflows, createdAt]
1883
+ properties:
1884
+ id:
1885
+ type: string
1886
+ name:
1887
+ type: string
1888
+ description:
1889
+ type: string
1890
+ startDate:
1891
+ type: string
1892
+ workflows:
1893
+ type: array
1894
+ items:
1895
+ $ref: "#/components/schemas/WorkflowDto"
1896
+ createdAt:
1897
+ type: string
1898
+ format: date-time
1899
+
1900
+ ProjectPatchDto:
1901
+ type: object
1902
+ description: Partial update; all properties optional
1903
+ properties:
1904
+ id:
1905
+ type: string
1906
+ name:
1907
+ type: string
1908
+ description:
1909
+ type: string
1910
+ startDate:
1911
+ type: string
1912
+ workflows:
1913
+ type: array
1914
+ items:
1915
+ $ref: "#/components/schemas/WorkflowDto"
1916
+ createdAt:
1917
+ type: string
1918
+ format: date-time
1919
+
1920
+ NotificationDto:
1921
+ type: object
1922
+ required: [id, type, title, message, read, createdAt]
1923
+ properties:
1924
+ id:
1925
+ type: string
1926
+ type:
1927
+ type: string
1928
+ enum: [status, comment, activity, integration, system]
1929
+ title:
1930
+ type: string
1931
+ message:
1932
+ type: string
1933
+ read:
1934
+ type: boolean
1935
+ createdAt:
1936
+ type: string
1937
+ format: date-time
1938
+ route:
1939
+ type: string
1940
+
1941
+ NotificationListDto:
1942
+ type: object
1943
+ required: [items, total]
1944
+ properties:
1945
+ items:
1946
+ type: array
1947
+ items:
1948
+ $ref: "#/components/schemas/NotificationDto"
1949
+ total:
1950
+ type: integer
1951
+
1952
+ ReviewQueueItemDto:
1953
+ type: object
1954
+ required: [id, client, project, workflows, submittedAt, reviewer, status, priority]
1955
+ properties:
1956
+ id:
1957
+ type: string
1958
+ client:
1959
+ type: string
1960
+ project:
1961
+ type: string
1962
+ workflows:
1963
+ type: array
1964
+ items:
1965
+ type: string
1966
+ enum: [greenfield, brownfield]
1967
+ submittedAt:
1968
+ type: string
1969
+ format: date-time
1970
+ reviewer:
1971
+ type: string
1972
+ nullable: true
1973
+ status:
1974
+ type: string
1975
+ enum: [pending, in_review, approved, changes_requested]
1976
+ priority:
1977
+ type: string
1978
+ enum: [high, medium, low]
1979
+
1980
+ AdminDashboardDto:
1981
+ type: object
1982
+ required: [queue, reviewers]
1983
+ properties:
1984
+ queue:
1985
+ type: array
1986
+ items:
1987
+ $ref: "#/components/schemas/ReviewQueueItemDto"
1988
+ reviewers:
1989
+ type: array
1990
+ items:
1991
+ type: string
1992
+
1993
+ PatchAdminReviewBodyDto:
1994
+ type: object
1995
+ properties:
1996
+ status:
1997
+ type: string
1998
+ enum: [pending, in_review, approved, changes_requested]
1999
+ reviewer:
2000
+ type: string
2001
+ priority:
2002
+ type: string
2003
+ enum: [high, medium, low]
2004
+
2005
+ CommentDto:
2006
+ type: object
2007
+ required: [id, sectionId, author, text, timestamp]
2008
+ properties:
2009
+ id:
2010
+ type: string
2011
+ sectionId:
2012
+ type: string
2013
+ author:
2014
+ type: string
2015
+ text:
2016
+ type: string
2017
+ timestamp:
2018
+ type: string
2019
+ format: date-time
2020
+
2021
+ AdminCommentBodyDto:
2022
+ type: object
2023
+ required: [text]
2024
+ properties:
2025
+ text:
2026
+ type: string
2027
+
2028
+ SectionDecisionBodyDto:
2029
+ type: object
2030
+ required: [decision]
2031
+ properties:
2032
+ decision:
2033
+ type: string
2034
+ enum: [pending, approved, changes_requested, rejected]
2035
+
2036
+ PricingLineDto:
2037
+ type: object
2038
+ required: [id, label, rate, hours]
2039
+ properties:
2040
+ id:
2041
+ type: string
2042
+ label:
2043
+ type: string
2044
+ rate:
2045
+ type: number
2046
+ hours:
2047
+ type: number
2048
+
2049
+ PricingUpdateBodyDto:
2050
+ type: object
2051
+ required: [items]
2052
+ properties:
2053
+ items:
2054
+ type: array
2055
+ items:
2056
+ type: object
2057
+ required: [id, rate, hours]
2058
+ properties:
2059
+ id:
2060
+ type: string
2061
+ rate:
2062
+ type: number
2063
+ hours:
2064
+ type: number
2065
+
2066
+ DeploymentPlanDto:
2067
+ type: object
2068
+ required: [startDate, endDate, milestones]
2069
+ properties:
2070
+ startDate:
2071
+ type: string
2072
+ endDate:
2073
+ type: string
2074
+ milestones:
2075
+ type: array
2076
+ items:
2077
+ type: string
2078
+
2079
+ ReviewSectionDto:
2080
+ type: object
2081
+ required: [id, label, detail, decision, comments]
2082
+ properties:
2083
+ id:
2084
+ type: string
2085
+ label:
2086
+ type: string
2087
+ detail:
2088
+ type: string
2089
+ decision:
2090
+ type: string
2091
+ enum: [pending, approved, changes_requested, rejected]
2092
+ comments:
2093
+ type: array
2094
+ items:
2095
+ $ref: "#/components/schemas/CommentDto"
2096
+
2097
+ ReviewSubmissionDto:
2098
+ type: object
2099
+ required:
2100
+ - id
2101
+ - client
2102
+ - project
2103
+ - workflows
2104
+ - status
2105
+ - isResubmission
2106
+ - context
2107
+ - sections
2108
+ - pricing
2109
+ - deployment
2110
+ properties:
2111
+ id:
2112
+ type: string
2113
+ client:
2114
+ type: string
2115
+ project:
2116
+ type: string
2117
+ workflows:
2118
+ type: array
2119
+ items:
2120
+ type: string
2121
+ enum: [greenfield, brownfield]
2122
+ status:
2123
+ type: string
2124
+ enum: [pending, in_review, approved, changes_requested]
2125
+ isResubmission:
2126
+ type: boolean
2127
+ context:
2128
+ type: array
2129
+ items:
2130
+ type: object
2131
+ required: [text]
2132
+ properties:
2133
+ text:
2134
+ type: string
2135
+ sections:
2136
+ type: array
2137
+ items:
2138
+ $ref: "#/components/schemas/ReviewSectionDto"
2139
+ pricing:
2140
+ type: array
2141
+ items:
2142
+ $ref: "#/components/schemas/PricingLineDto"
2143
+ deployment:
2144
+ $ref: "#/components/schemas/DeploymentPlanDto"
2145
+
2146
+ EffectiveTaskRowDto:
2147
+ type: object
2148
+ required: [id, name, summary, source]
2149
+ properties:
2150
+ id:
2151
+ type: string
2152
+ name:
2153
+ type: string
2154
+ summary:
2155
+ type: string
2156
+ source:
2157
+ type: string
2158
+ enum: [catalog, custom]
2159
+
2160
+ EffectivePhaseTasksBlockDto:
2161
+ type: object
2162
+ required: [phaseName, icon, tasks]
2163
+ properties:
2164
+ phaseName:
2165
+ type: string
2166
+ icon:
2167
+ type: string
2168
+ tasks:
2169
+ type: array
2170
+ items:
2171
+ $ref: "#/components/schemas/EffectiveTaskRowDto"
2172
+
2173
+ AiStrategyRecommendBodyDto:
2174
+ type: object
2175
+ required: [phases]
2176
+ properties:
2177
+ phases:
2178
+ type: array
2179
+ items:
2180
+ $ref: "#/components/schemas/EffectivePhaseTasksBlockDto"
2181
+
2182
+ AiStrategyTaskRecommendationDto:
2183
+ type: object
2184
+ required: [taskId, taskName, summary, source, tool, engagement]
2185
+ properties:
2186
+ taskId:
2187
+ type: string
2188
+ taskName:
2189
+ type: string
2190
+ summary:
2191
+ type: string
2192
+ source:
2193
+ type: string
2194
+ enum: [catalog, custom]
2195
+ tool:
2196
+ type: string
2197
+ engagement:
2198
+ type: string
2199
+ enum: [AI assisted, AI delegated]
2200
+ rationale:
2201
+ type: string
2202
+
2203
+ AiStrategyPhaseBlockDto:
2204
+ type: object
2205
+ required: [phaseName, icon, tasks]
2206
+ properties:
2207
+ phaseName:
2208
+ type: string
2209
+ icon:
2210
+ type: string
2211
+ tasks:
2212
+ type: array
2213
+ items:
2214
+ $ref: "#/components/schemas/AiStrategyTaskRecommendationDto"
2215
+
2216
+ AiStrategyPlanDto:
2217
+ type: object
2218
+ required: [phases]
2219
+ properties:
2220
+ phases:
2221
+ type: array
2222
+ items:
2223
+ $ref: "#/components/schemas/AiStrategyPhaseBlockDto"
2224
+
2225
+ JourneyProgressDto:
2226
+ type: object
2227
+ required: [completedSteps, updatedAt]
2228
+ properties:
2229
+ completedSteps:
2230
+ type: array
2231
+ items:
2232
+ type: string
2233
+ updatedAt:
2234
+ type: string
2235
+ format: date-time
2236
+
2237
+ JourneyProgressUpdateDto:
2238
+ type: object
2239
+ required: [completedSteps]
2240
+ properties:
2241
+ completedSteps:
2242
+ type: array
2243
+ items:
2244
+ type: string
2245
+
2246
+ PreferencesDto:
2247
+ type: object
2248
+ required: [theme, sidebarCollapsed, timezone, notifications]
2249
+ properties:
2250
+ theme:
2251
+ type: string
2252
+ enum: [light, dark, system]
2253
+ sidebarCollapsed:
2254
+ type: boolean
2255
+ timezone:
2256
+ type: string
2257
+ description: IANA timezone name
2258
+ notifications:
2259
+ type: object
2260
+ required: [status, comment, activity, system]
2261
+ properties:
2262
+ status:
2263
+ type: boolean
2264
+ comment:
2265
+ type: boolean
2266
+ activity:
2267
+ type: boolean
2268
+ system:
2269
+ type: boolean
2270
+
2271
+ OrgChartImportBodyDto:
2272
+ type: object
2273
+ required: [storagePath]
2274
+ properties:
2275
+ storagePath:
2276
+ type: string
2277
+ description: Path in `org-charts` bucket after Supabase upload