@thinkai/tai-api-contract 2.5.16 → 2.5.17

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.
@@ -1,7 +1,7 @@
1
1
  openapi: 3.0.3
2
2
  info:
3
3
  title: ThinkAI API
4
- version: 2.5.16
4
+ version: 2.5.17
5
5
  description: >
6
6
  Contract surface for the AI Driven SDLC backend used by ThinkAI.
7
7
  Workspace-scoped routes use `/workspaces/{workspaceId}/...`.
@@ -138,6 +138,9 @@ paths:
138
138
  get:
139
139
  tags: [Workspace]
140
140
  summary: List workspace team members
141
+ description: >
142
+ Returns active workspace members (`tai_workspace_members` with `deleted_at` null).
143
+ Any workspace member may list; invite and role changes require admin.
141
144
  operationId: listTenantMembers
142
145
  parameters:
143
146
  - $ref: "#/components/parameters/WorkspaceId"
@@ -148,15 +151,33 @@ paths:
148
151
  application/json:
149
152
  schema:
150
153
  $ref: "#/components/schemas/TeamMemberListDto"
154
+ example:
155
+ members:
156
+ - id: "11111111-1111-4111-8111-111111111111"
157
+ name: "Alex Admin"
158
+ email: "alex@example.com"
159
+ role: admin
151
160
  "401":
152
161
  $ref: "#/components/responses/Unauthorized"
153
162
  "403":
154
163
  $ref: "#/components/responses/Forbidden"
164
+ "404":
165
+ description: Workspace does not exist or malformed workspaceId
166
+ content:
167
+ application/json:
168
+ schema:
169
+ $ref: "#/components/schemas/ErrorMessageDto"
155
170
 
156
171
  /workspaces/{workspaceId}/members/invite:
157
172
  post:
158
173
  tags: [Workspace]
159
174
  summary: Invite member to workspace
175
+ description: >
176
+ Workspace admin only. Upserts `tai_users` by email and adds or reactivates
177
+ `tai_workspace_members`. Idempotent when the email is already an active member:
178
+ returns **201** with the existing row and **does not change** their role if the
179
+ request body role differs. Does not send email; optional `tai_workspace_invitations`
180
+ row may be recorded (no accept/link flow yet).
160
181
  operationId: inviteTenantMember
161
182
  parameters:
162
183
  - $ref: "#/components/parameters/WorkspaceId"
@@ -166,6 +187,9 @@ paths:
166
187
  application/json:
167
188
  schema:
168
189
  $ref: "#/components/schemas/InviteTeamMemberBodyDto"
190
+ example:
191
+ email: new.member@example.com
192
+ role: editor
169
193
  responses:
170
194
  "201":
171
195
  description: Invited member row
@@ -173,28 +197,40 @@ paths:
173
197
  application/json:
174
198
  schema:
175
199
  $ref: "#/components/schemas/TeamMemberDto"
200
+ "400":
201
+ description: Invalid email or role
202
+ content:
203
+ application/json:
204
+ schema:
205
+ $ref: "#/components/schemas/ErrorMessageDto"
176
206
  "401":
177
207
  $ref: "#/components/responses/Unauthorized"
178
208
  "403":
179
209
  $ref: "#/components/responses/Forbidden"
210
+ "404":
211
+ description: Workspace does not exist or malformed workspaceId
212
+ content:
213
+ application/json:
214
+ schema:
215
+ $ref: "#/components/schemas/ErrorMessageDto"
180
216
 
181
217
  /workspaces/{workspaceId}/members/{memberId}:
182
218
  patch:
183
219
  tags: [Workspace]
184
220
  summary: Update workspace member role
221
+ description: Workspace admin only. `memberId` is `tai_users.id` (UUID), not the auth subject.
185
222
  operationId: updateTenantMemberRole
186
223
  parameters:
187
224
  - $ref: "#/components/parameters/WorkspaceId"
188
- - name: memberId
189
- in: path
190
- required: true
191
- schema: { type: string }
225
+ - $ref: "#/components/parameters/WorkspaceMemberId"
192
226
  requestBody:
193
227
  required: true
194
228
  content:
195
229
  application/json:
196
230
  schema:
197
231
  $ref: "#/components/schemas/UpdateTeamMemberRoleBodyDto"
232
+ example:
233
+ role: viewer
198
234
  responses:
199
235
  "200":
200
236
  description: Updated member row
@@ -202,22 +238,43 @@ paths:
202
238
  application/json:
203
239
  schema:
204
240
  $ref: "#/components/schemas/TeamMemberDto"
241
+ "400":
242
+ description: Invalid role payload
243
+ content:
244
+ application/json:
245
+ schema:
246
+ $ref: "#/components/schemas/ErrorMessageDto"
205
247
  "401":
206
248
  $ref: "#/components/responses/Unauthorized"
207
249
  "403":
208
250
  $ref: "#/components/responses/Forbidden"
209
251
  "404":
210
- description: Member not found
252
+ description: Member not found or invalid memberId
253
+ content:
254
+ application/json:
255
+ schema:
256
+ $ref: "#/components/schemas/ErrorMessageDto"
257
+ "409":
258
+ description: Cannot demote the last workspace admin
259
+ content:
260
+ application/json:
261
+ schema:
262
+ $ref: "#/components/schemas/ErrorMessageDto"
263
+ examples:
264
+ lastAdmin:
265
+ value:
266
+ error: Cannot change role of the last workspace admin
267
+ code: last_admin
211
268
  delete:
212
269
  tags: [Workspace]
213
270
  summary: Remove member from workspace
271
+ description: >
272
+ Workspace admin only. Soft-deletes the membership (`deleted_at` set).
273
+ Cannot remove the workspace owner or the last admin.
214
274
  operationId: removeTenantMember
215
275
  parameters:
216
276
  - $ref: "#/components/parameters/WorkspaceId"
217
- - name: memberId
218
- in: path
219
- required: true
220
- schema: { type: string }
277
+ - $ref: "#/components/parameters/WorkspaceMemberId"
221
278
  responses:
222
279
  "204":
223
280
  description: Removed
@@ -226,7 +283,26 @@ paths:
226
283
  "403":
227
284
  $ref: "#/components/responses/Forbidden"
228
285
  "404":
229
- description: Member not found
286
+ description: Member not found or invalid memberId
287
+ content:
288
+ application/json:
289
+ schema:
290
+ $ref: "#/components/schemas/ErrorMessageDto"
291
+ "409":
292
+ description: Cannot remove workspace owner or last admin
293
+ content:
294
+ application/json:
295
+ schema:
296
+ $ref: "#/components/schemas/ErrorMessageDto"
297
+ examples:
298
+ lastAdmin:
299
+ value:
300
+ error: Cannot remove the last workspace admin
301
+ code: last_admin
302
+ workspaceOwner:
303
+ value:
304
+ error: Cannot remove the workspace owner
305
+ code: workspace_owner
230
306
 
231
307
  /workspaces/{workspaceId}/org-chart:
232
308
  get:
@@ -3020,6 +3096,14 @@ components:
3020
3096
  required: true
3021
3097
  schema:
3022
3098
  type: string
3099
+ WorkspaceMemberId:
3100
+ name: memberId
3101
+ in: path
3102
+ required: true
3103
+ schema:
3104
+ type: string
3105
+ format: uuid
3106
+ description: Workspace member user id (`tai_users.id`).
3023
3107
  FixId:
3024
3108
  name: fixId
3025
3109
  in: path
@@ -3061,6 +3145,9 @@ components:
3061
3145
  properties:
3062
3146
  error:
3063
3147
  type: string
3148
+ code:
3149
+ type: string
3150
+ description: Machine-readable error code when present (for example `last_admin`).
3064
3151
 
3065
3152
  TeamMemberDto:
3066
3153
  type: object
@@ -3068,6 +3155,7 @@ components:
3068
3155
  properties:
3069
3156
  id:
3070
3157
  type: string
3158
+ format: uuid
3071
3159
  name:
3072
3160
  type: string
3073
3161
  email:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thinkai/tai-api-contract",
3
- "version": "2.5.16",
3
+ "version": "2.5.17",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -69,7 +69,10 @@ export interface paths {
69
69
  path?: never;
70
70
  cookie?: never;
71
71
  };
72
- /** List workspace team members */
72
+ /**
73
+ * List workspace team members
74
+ * @description Returns active workspace members (`tai_workspace_members` with `deleted_at` null). Any workspace member may list; invite and role changes require admin.
75
+ */
73
76
  get: operations["listTenantMembers"];
74
77
  put?: never;
75
78
  post?: never;
@@ -88,7 +91,10 @@ export interface paths {
88
91
  };
89
92
  get?: never;
90
93
  put?: never;
91
- /** Invite member to workspace */
94
+ /**
95
+ * Invite member to workspace
96
+ * @description Workspace admin only. Upserts `tai_users` by email and adds or reactivates `tai_workspace_members`. Idempotent when the email is already an active member: returns **201** with the existing row and **does not change** their role if the request body role differs. Does not send email; optional `tai_workspace_invitations` row may be recorded (no accept/link flow yet).
97
+ */
92
98
  post: operations["inviteTenantMember"];
93
99
  delete?: never;
94
100
  options?: never;
@@ -106,11 +112,17 @@ export interface paths {
106
112
  get?: never;
107
113
  put?: never;
108
114
  post?: never;
109
- /** Remove member from workspace */
115
+ /**
116
+ * Remove member from workspace
117
+ * @description Workspace admin only. Soft-deletes the membership (`deleted_at` set). Cannot remove the workspace owner or the last admin.
118
+ */
110
119
  delete: operations["removeTenantMember"];
111
120
  options?: never;
112
121
  head?: never;
113
- /** Update workspace member role */
122
+ /**
123
+ * Update workspace member role
124
+ * @description Workspace admin only. `memberId` is `tai_users.id` (UUID), not the auth subject.
125
+ */
114
126
  patch: operations["updateTenantMemberRole"];
115
127
  trace?: never;
116
128
  };
@@ -1329,8 +1341,11 @@ export interface components {
1329
1341
  schemas: {
1330
1342
  ErrorMessageDto: {
1331
1343
  error: string;
1344
+ /** @description Machine-readable error code when present (for example `last_admin`). */
1345
+ code?: string;
1332
1346
  };
1333
1347
  TeamMemberDto: {
1348
+ /** Format: uuid */
1334
1349
  id: string;
1335
1350
  name: string;
1336
1351
  email: string;
@@ -2449,6 +2464,8 @@ export interface components {
2449
2464
  RepoId: string;
2450
2465
  ProjectId: string;
2451
2466
  NotificationId: string;
2467
+ /** @description Workspace member user id (`tai_users.id`). */
2468
+ WorkspaceMemberId: string;
2452
2469
  FixId: string;
2453
2470
  /** @description Department filter; send `All departments` to include every department. Scoped using imported `thinkai_org_structure` members when present, otherwise SPA org chart `department` nodes and their descendant teams. When neither source defines the requested department, insights return no scoped teams or contributors (not org-wide data). */
2454
2471
  InsightsDepartmentFilter: string;
@@ -2589,6 +2606,7 @@ export type ParameterWorkspaceId = components['parameters']['WorkspaceId'];
2589
2606
  export type ParameterRepoId = components['parameters']['RepoId'];
2590
2607
  export type ParameterProjectId = components['parameters']['ProjectId'];
2591
2608
  export type ParameterNotificationId = components['parameters']['NotificationId'];
2609
+ export type ParameterWorkspaceMemberId = components['parameters']['WorkspaceMemberId'];
2592
2610
  export type ParameterFixId = components['parameters']['FixId'];
2593
2611
  export type ParameterInsightsDepartmentFilter = components['parameters']['InsightsDepartmentFilter'];
2594
2612
  export type $defs = Record<string, never>;
@@ -2718,11 +2736,32 @@ export interface operations {
2718
2736
  [name: string]: unknown;
2719
2737
  };
2720
2738
  content: {
2739
+ /**
2740
+ * @example {
2741
+ * "members": [
2742
+ * {
2743
+ * "id": "11111111-1111-4111-8111-111111111111",
2744
+ * "name": "Alex Admin",
2745
+ * "email": "alex@example.com",
2746
+ * "role": "admin"
2747
+ * }
2748
+ * ]
2749
+ * }
2750
+ */
2721
2751
  "application/json": components["schemas"]["TeamMemberListDto"];
2722
2752
  };
2723
2753
  };
2724
2754
  401: components["responses"]["Unauthorized"];
2725
2755
  403: components["responses"]["Forbidden"];
2756
+ /** @description Workspace does not exist or malformed workspaceId */
2757
+ 404: {
2758
+ headers: {
2759
+ [name: string]: unknown;
2760
+ };
2761
+ content: {
2762
+ "application/json": components["schemas"]["ErrorMessageDto"];
2763
+ };
2764
+ };
2726
2765
  };
2727
2766
  };
2728
2767
  inviteTenantMember: {
@@ -2736,6 +2775,12 @@ export interface operations {
2736
2775
  };
2737
2776
  requestBody: {
2738
2777
  content: {
2778
+ /**
2779
+ * @example {
2780
+ * "email": "new.member@example.com",
2781
+ * "role": "editor"
2782
+ * }
2783
+ */
2739
2784
  "application/json": components["schemas"]["InviteTeamMemberBodyDto"];
2740
2785
  };
2741
2786
  };
@@ -2749,8 +2794,26 @@ export interface operations {
2749
2794
  "application/json": components["schemas"]["TeamMemberDto"];
2750
2795
  };
2751
2796
  };
2797
+ /** @description Invalid email or role */
2798
+ 400: {
2799
+ headers: {
2800
+ [name: string]: unknown;
2801
+ };
2802
+ content: {
2803
+ "application/json": components["schemas"]["ErrorMessageDto"];
2804
+ };
2805
+ };
2752
2806
  401: components["responses"]["Unauthorized"];
2753
2807
  403: components["responses"]["Forbidden"];
2808
+ /** @description Workspace does not exist or malformed workspaceId */
2809
+ 404: {
2810
+ headers: {
2811
+ [name: string]: unknown;
2812
+ };
2813
+ content: {
2814
+ "application/json": components["schemas"]["ErrorMessageDto"];
2815
+ };
2816
+ };
2754
2817
  };
2755
2818
  };
2756
2819
  removeTenantMember: {
@@ -2759,7 +2822,8 @@ export interface operations {
2759
2822
  header?: never;
2760
2823
  path: {
2761
2824
  workspaceId: components["parameters"]["WorkspaceId"];
2762
- memberId: string;
2825
+ /** @description Workspace member user id (`tai_users.id`). */
2826
+ memberId: components["parameters"]["WorkspaceMemberId"];
2763
2827
  };
2764
2828
  cookie?: never;
2765
2829
  };
@@ -2774,12 +2838,23 @@ export interface operations {
2774
2838
  };
2775
2839
  401: components["responses"]["Unauthorized"];
2776
2840
  403: components["responses"]["Forbidden"];
2777
- /** @description Member not found */
2841
+ /** @description Member not found or invalid memberId */
2778
2842
  404: {
2779
2843
  headers: {
2780
2844
  [name: string]: unknown;
2781
2845
  };
2782
- content?: never;
2846
+ content: {
2847
+ "application/json": components["schemas"]["ErrorMessageDto"];
2848
+ };
2849
+ };
2850
+ /** @description Cannot remove workspace owner or last admin */
2851
+ 409: {
2852
+ headers: {
2853
+ [name: string]: unknown;
2854
+ };
2855
+ content: {
2856
+ "application/json": components["schemas"]["ErrorMessageDto"];
2857
+ };
2783
2858
  };
2784
2859
  };
2785
2860
  };
@@ -2789,12 +2864,18 @@ export interface operations {
2789
2864
  header?: never;
2790
2865
  path: {
2791
2866
  workspaceId: components["parameters"]["WorkspaceId"];
2792
- memberId: string;
2867
+ /** @description Workspace member user id (`tai_users.id`). */
2868
+ memberId: components["parameters"]["WorkspaceMemberId"];
2793
2869
  };
2794
2870
  cookie?: never;
2795
2871
  };
2796
2872
  requestBody: {
2797
2873
  content: {
2874
+ /**
2875
+ * @example {
2876
+ * "role": "viewer"
2877
+ * }
2878
+ */
2798
2879
  "application/json": components["schemas"]["UpdateTeamMemberRoleBodyDto"];
2799
2880
  };
2800
2881
  };
@@ -2808,14 +2889,34 @@ export interface operations {
2808
2889
  "application/json": components["schemas"]["TeamMemberDto"];
2809
2890
  };
2810
2891
  };
2892
+ /** @description Invalid role payload */
2893
+ 400: {
2894
+ headers: {
2895
+ [name: string]: unknown;
2896
+ };
2897
+ content: {
2898
+ "application/json": components["schemas"]["ErrorMessageDto"];
2899
+ };
2900
+ };
2811
2901
  401: components["responses"]["Unauthorized"];
2812
2902
  403: components["responses"]["Forbidden"];
2813
- /** @description Member not found */
2903
+ /** @description Member not found or invalid memberId */
2814
2904
  404: {
2815
2905
  headers: {
2816
2906
  [name: string]: unknown;
2817
2907
  };
2818
- content?: never;
2908
+ content: {
2909
+ "application/json": components["schemas"]["ErrorMessageDto"];
2910
+ };
2911
+ };
2912
+ /** @description Cannot demote the last workspace admin */
2913
+ 409: {
2914
+ headers: {
2915
+ [name: string]: unknown;
2916
+ };
2917
+ content: {
2918
+ "application/json": components["schemas"]["ErrorMessageDto"];
2919
+ };
2819
2920
  };
2820
2921
  };
2821
2922
  };