@thinkai/tai-api-contract 2.70.0 → 2.72.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.
@@ -1,7 +1,7 @@
1
1
  openapi: 3.0.3
2
2
  info:
3
3
  title: ThinkAI API
4
- version: 2.70.0
4
+ version: 2.72.0
5
5
  description: >
6
6
  Contract surface for the AI Driven SDLC backend used by ThinkAI.
7
7
  Workspace-scoped routes use `/workspaces/{workspaceId}/...`.
@@ -968,11 +968,15 @@ paths:
968
968
  tags: [Workspace]
969
969
  summary: Invite member to workspace
970
970
  description: >
971
- Workspace admin only. Upserts `tai_users` by email and adds or reactivates
972
- `tai_workspace_members`. Idempotent when the email is already an active member:
973
- returns **201** with the existing row and **does not change** their role if the
974
- request body role differs. Does not send email; optional `tai_workspace_invitations`
975
- row may be recorded (no accept/link flow yet).
971
+ Workspace admin only. Creates or refreshes a **pending**
972
+ `tai_workspace_invitations` row and emails an accept link; it does **not** create
973
+ `tai_workspace_members`. Membership is granted only by
974
+ `POST /invitations/{token}/accept`. Applies to new and existing platform users
975
+ alike. Idempotent when the email is already an active member: returns **201** with
976
+ `outcome: "already_member"` and the existing row, **does not change** their role if
977
+ the request body role differs, and sends no email. Re-inviting a pending email
978
+ refreshes the token and 7-day expiry (the previous link stops working). When SMTP
979
+ is not configured the invitation is still created and a warning is logged.
976
980
  operationId: inviteTenantMember
977
981
  parameters:
978
982
  - $ref: "#/components/parameters/WorkspaceId"
@@ -987,11 +991,33 @@ paths:
987
991
  role: editor
988
992
  responses:
989
993
  "201":
990
- description: Invited member row
994
+ description: Pending invitation, or the existing member row when already a member
991
995
  content:
992
996
  application/json:
993
997
  schema:
994
- $ref: "#/components/schemas/TeamMemberDto"
998
+ $ref: "#/components/schemas/InviteTeamMemberResultDto"
999
+ examples:
1000
+ invited:
1001
+ value:
1002
+ outcome: invited
1003
+ invitation:
1004
+ id: 6f1d9c0e-4d0b-4a0f-9a3e-2c1b8f4a7d55
1005
+ workspaceId: 9a2b7c1d-3e4f-4a5b-8c9d-0e1f2a3b4c5d
1006
+ workspaceName: Acme Engineering
1007
+ email: new.member@example.com
1008
+ role: editor
1009
+ status: pending
1010
+ invitedByName: Dana Admin
1011
+ expiresAt: "2026-08-01T12:00:00.000Z"
1012
+ createdAt: "2026-07-25T12:00:00.000Z"
1013
+ alreadyMember:
1014
+ value:
1015
+ outcome: already_member
1016
+ member:
1017
+ id: 1b2c3d4e-5f60-4718-8293-a4b5c6d7e8f9
1018
+ name: Existing Member
1019
+ email: new.member@example.com
1020
+ role: admin
995
1021
  "400":
996
1022
  description: Invalid email or role
997
1023
  content:
@@ -1099,6 +1125,175 @@ paths:
1099
1125
  error: Cannot remove the workspace owner
1100
1126
  code: workspace_owner
1101
1127
 
1128
+ /workspaces/{workspaceId}/invitations:
1129
+ get:
1130
+ tags: [Workspace]
1131
+ summary: List pending workspace invitations
1132
+ description: >
1133
+ Workspace admin only. Returns invitations still awaiting a decision so the team
1134
+ settings page can show "pending" alongside active members. Rows whose `expiresAt`
1135
+ has passed are flipped to `expired` on read and omitted.
1136
+ operationId: listWorkspaceInvitations
1137
+ parameters:
1138
+ - $ref: "#/components/parameters/WorkspaceId"
1139
+ responses:
1140
+ "200":
1141
+ description: Pending invitations
1142
+ content:
1143
+ application/json:
1144
+ schema:
1145
+ $ref: "#/components/schemas/WorkspaceInvitationListDto"
1146
+ "401":
1147
+ $ref: "#/components/responses/Unauthorized"
1148
+ "403":
1149
+ $ref: "#/components/responses/Forbidden"
1150
+ "404":
1151
+ description: Workspace does not exist or malformed workspaceId
1152
+ content:
1153
+ application/json:
1154
+ schema:
1155
+ $ref: "#/components/schemas/ErrorMessageDto"
1156
+
1157
+ /invitations/{token}:
1158
+ get:
1159
+ tags: [Workspace]
1160
+ summary: Preview a workspace invitation (public)
1161
+ description: >
1162
+ **Unauthenticated.** Lets the SPA render the invite landing page before the invitee
1163
+ has signed in. The invited email is **masked** (`j••••e@example.com`) so a leaked
1164
+ link does not disclose an address. Returns `404` with a generic message for unknown,
1165
+ revoked, or rejected tokens; a past-due `pending` invitation is flipped to `expired`
1166
+ and returned with that status so the SPA can show a stable message.
1167
+ operationId: getWorkspaceInvitationPreview
1168
+ security: []
1169
+ parameters:
1170
+ - $ref: "#/components/parameters/WorkspaceInvitationToken"
1171
+ responses:
1172
+ "200":
1173
+ description: Invitation preview
1174
+ content:
1175
+ application/json:
1176
+ schema:
1177
+ $ref: "#/components/schemas/WorkspaceInvitationPreviewDto"
1178
+ "404":
1179
+ description: Unknown or no longer available invitation
1180
+ content:
1181
+ application/json:
1182
+ schema:
1183
+ $ref: "#/components/schemas/ErrorMessageDto"
1184
+ examples:
1185
+ notFound:
1186
+ value:
1187
+ error: This invitation link is not valid.
1188
+ code: invitation_not_found
1189
+
1190
+ /invitations/{token}/accept:
1191
+ post:
1192
+ tags: [Workspace]
1193
+ summary: Accept a workspace invitation
1194
+ description: >
1195
+ Requires a Supabase JWT whose email matches the invited email. Creates the
1196
+ `tai_workspace_members` row with the invited role and closes the invitation as
1197
+ `accepted`. This is the **only** path that grants workspace membership — signing up
1198
+ alone never does. Idempotent: re-accepting your own accepted invitation returns
1199
+ `200` unchanged.
1200
+ operationId: acceptWorkspaceInvitation
1201
+ parameters:
1202
+ - $ref: "#/components/parameters/WorkspaceInvitationToken"
1203
+ responses:
1204
+ "200":
1205
+ description: Invitation accepted; caller is now a workspace member
1206
+ content:
1207
+ application/json:
1208
+ schema:
1209
+ $ref: "#/components/schemas/WorkspaceInvitationDto"
1210
+ "401":
1211
+ $ref: "#/components/responses/Unauthorized"
1212
+ "403":
1213
+ description: Signed-in email does not match the invited email
1214
+ content:
1215
+ application/json:
1216
+ schema:
1217
+ $ref: "#/components/schemas/ErrorMessageDto"
1218
+ examples:
1219
+ emailMismatch:
1220
+ value:
1221
+ error: This invitation was sent to a different email address.
1222
+ code: invitation_email_mismatch
1223
+ "404":
1224
+ description: Unknown invitation token
1225
+ content:
1226
+ application/json:
1227
+ schema:
1228
+ $ref: "#/components/schemas/ErrorMessageDto"
1229
+ "409":
1230
+ description: Invitation is no longer actionable
1231
+ content:
1232
+ application/json:
1233
+ schema:
1234
+ $ref: "#/components/schemas/ErrorMessageDto"
1235
+ examples:
1236
+ notPending:
1237
+ value:
1238
+ error: This invitation is no longer available.
1239
+ code: invitation_not_pending
1240
+ "410":
1241
+ description: Invitation expired
1242
+ content:
1243
+ application/json:
1244
+ schema:
1245
+ $ref: "#/components/schemas/ErrorMessageDto"
1246
+ examples:
1247
+ expired:
1248
+ value:
1249
+ error: This invitation has expired. Ask an admin to send a new one.
1250
+ code: invitation_expired
1251
+
1252
+ /invitations/{token}/reject:
1253
+ post:
1254
+ tags: [Workspace]
1255
+ summary: Decline a workspace invitation
1256
+ description: >
1257
+ Requires a Supabase JWT whose email matches the invited email — anonymous decline
1258
+ with only the token is not allowed. Closes the invitation as `rejected` and creates
1259
+ no member row. Idempotent for an already-rejected invitation.
1260
+ operationId: rejectWorkspaceInvitation
1261
+ parameters:
1262
+ - $ref: "#/components/parameters/WorkspaceInvitationToken"
1263
+ responses:
1264
+ "200":
1265
+ description: Invitation declined
1266
+ content:
1267
+ application/json:
1268
+ schema:
1269
+ $ref: "#/components/schemas/WorkspaceInvitationDto"
1270
+ "401":
1271
+ $ref: "#/components/responses/Unauthorized"
1272
+ "403":
1273
+ description: Signed-in email does not match the invited email
1274
+ content:
1275
+ application/json:
1276
+ schema:
1277
+ $ref: "#/components/schemas/ErrorMessageDto"
1278
+ "404":
1279
+ description: Unknown invitation token
1280
+ content:
1281
+ application/json:
1282
+ schema:
1283
+ $ref: "#/components/schemas/ErrorMessageDto"
1284
+ "409":
1285
+ description: Invitation was already accepted
1286
+ content:
1287
+ application/json:
1288
+ schema:
1289
+ $ref: "#/components/schemas/ErrorMessageDto"
1290
+ "410":
1291
+ description: Invitation expired
1292
+ content:
1293
+ application/json:
1294
+ schema:
1295
+ $ref: "#/components/schemas/ErrorMessageDto"
1296
+
1102
1297
  /workspaces/{workspaceId}/org-chart/status:
1103
1298
  get:
1104
1299
  tags: [Workspace]
@@ -1327,6 +1522,7 @@ paths:
1327
1522
  - $ref: "#/components/schemas/PrometheusSourceDto"
1328
1523
  - $ref: "#/components/schemas/GrafanaSourceDto"
1329
1524
  - $ref: "#/components/schemas/SonarQubeSourceDto"
1525
+ - $ref: "#/components/schemas/PagerDutySourceDto"
1330
1526
  - $ref: "#/components/schemas/TenantSourceEntryDto"
1331
1527
  examples:
1332
1528
  cursorAndJira:
@@ -1443,6 +1639,7 @@ paths:
1443
1639
  - $ref: "#/components/schemas/PrometheusSourceDto"
1444
1640
  - $ref: "#/components/schemas/GrafanaSourceDto"
1445
1641
  - $ref: "#/components/schemas/SonarQubeSourceDto"
1642
+ - $ref: "#/components/schemas/PagerDutySourceDto"
1446
1643
  - $ref: "#/components/schemas/TenantSourceEntryDto"
1447
1644
  examples:
1448
1645
  cursorValid:
@@ -7700,6 +7897,16 @@ components:
7700
7897
  type: string
7701
7898
  format: uuid
7702
7899
  description: Workspace member user id (`tai_users.id`).
7900
+ WorkspaceInvitationToken:
7901
+ name: token
7902
+ in: path
7903
+ required: true
7904
+ schema:
7905
+ type: string
7906
+ minLength: 32
7907
+ description: >
7908
+ Opaque workspace invitation token from the emailed accept link. Only its SHA-256
7909
+ hash is stored server-side; the plaintext is shown exactly once, in the email.
7703
7910
  PrivacyRequestId:
7704
7911
  name: requestId
7705
7912
  in: path
@@ -8029,6 +8236,100 @@ components:
8029
8236
  type: string
8030
8237
  enum: [admin, editor, viewer]
8031
8238
 
8239
+ WorkspaceInvitationStatusDto:
8240
+ type: string
8241
+ description: >
8242
+ `revoked` is an admin cancelling the invitation; `rejected` is the invitee
8243
+ declining it. Both leave the invitee outside the workspace.
8244
+ enum: [pending, accepted, expired, revoked, rejected]
8245
+
8246
+ WorkspaceInvitationDto:
8247
+ type: object
8248
+ description: Workspace invitation as seen by an authenticated admin or invitee.
8249
+ required:
8250
+ [id, workspaceId, workspaceName, email, role, status, expiresAt, createdAt]
8251
+ properties:
8252
+ id:
8253
+ type: string
8254
+ format: uuid
8255
+ workspaceId:
8256
+ type: string
8257
+ format: uuid
8258
+ workspaceName:
8259
+ type: string
8260
+ email:
8261
+ type: string
8262
+ description: Invited email address.
8263
+ role:
8264
+ type: string
8265
+ enum: [admin, editor, viewer]
8266
+ status:
8267
+ $ref: "#/components/schemas/WorkspaceInvitationStatusDto"
8268
+ invitedByName:
8269
+ type: string
8270
+ nullable: true
8271
+ invitedByEmail:
8272
+ type: string
8273
+ nullable: true
8274
+ expiresAt:
8275
+ type: string
8276
+ format: date-time
8277
+ createdAt:
8278
+ type: string
8279
+ format: date-time
8280
+ acceptedAt:
8281
+ type: string
8282
+ format: date-time
8283
+ nullable: true
8284
+
8285
+ WorkspaceInvitationPreviewDto:
8286
+ type: object
8287
+ description: >
8288
+ Unauthenticated invitation preview. `maskedEmail` is the only view of the invited
8289
+ address; compare it to the signed-in account client-side before calling accept.
8290
+ required: [workspaceName, role, status, maskedEmail, expiresAt]
8291
+ properties:
8292
+ workspaceName:
8293
+ type: string
8294
+ role:
8295
+ type: string
8296
+ enum: [admin, editor, viewer]
8297
+ status:
8298
+ $ref: "#/components/schemas/WorkspaceInvitationStatusDto"
8299
+ maskedEmail:
8300
+ type: string
8301
+ example: j••••e@example.com
8302
+ invitedByName:
8303
+ type: string
8304
+ nullable: true
8305
+ expiresAt:
8306
+ type: string
8307
+ format: date-time
8308
+
8309
+ WorkspaceInvitationListDto:
8310
+ type: object
8311
+ required: [invitations]
8312
+ properties:
8313
+ invitations:
8314
+ type: array
8315
+ items:
8316
+ $ref: "#/components/schemas/WorkspaceInvitationDto"
8317
+
8318
+ InviteTeamMemberResultDto:
8319
+ type: object
8320
+ description: >
8321
+ Discriminated on `outcome`. `invited` carries the new pending invitation;
8322
+ `already_member` carries the existing membership row unchanged.
8323
+ required: [outcome]
8324
+ properties:
8325
+ outcome:
8326
+ type: string
8327
+ enum: [invited, already_member]
8328
+ invitation:
8329
+ $ref: "#/components/schemas/WorkspaceInvitationDto"
8330
+ member:
8331
+ $ref: "#/components/schemas/TeamMemberDto"
8332
+
8032
8333
  EraseInsightsPersonBodyDto:
8033
8334
  type: object
8034
8335
  description: >
@@ -8747,6 +9048,57 @@ components:
8747
9048
  branch:
8748
9049
  type: string
8749
9050
 
9051
+ PagerDutySourceDto:
9052
+ type: object
9053
+ description: >
9054
+ PagerDuty incident monitoring source for `PUT /workspaces/{workspaceId}/sources` and
9055
+ `POST /workspaces/{workspaceId}/sources/test`. Requires a REST API v2 token
9056
+ (an "API Access Key" from PagerDuty → **Integrations → API Access Keys**).
9057
+ required: [type, token]
9058
+ additionalProperties: false
9059
+ properties:
9060
+ type:
9061
+ type: string
9062
+ enum: [pagerduty]
9063
+ token:
9064
+ type: string
9065
+ minLength: 1
9066
+ maxLength: 512
9067
+ description: PagerDuty REST API v2 token (API Access Key, write-only on PUT).
9068
+ baseUrl:
9069
+ type: string
9070
+ description: Optional API base URL override. Default `https://api.pagerduty.com`.
9071
+ userName:
9072
+ type: string
9073
+ description: Optional display name from a successful connection test (echo-after-test).
9074
+ userEmail:
9075
+ type: string
9076
+ description: Optional email from a successful connection test (echo-after-test).
9077
+
9078
+ PagerDutySourceConfigDto:
9079
+ type: object
9080
+ description: >
9081
+ Redacted PagerDuty source returned by `GET /workspaces/{workspaceId}/config`.
9082
+ Raw token is never returned.
9083
+ required: [type, hasToken]
9084
+ additionalProperties: false
9085
+ properties:
9086
+ type:
9087
+ type: string
9088
+ enum: [pagerduty]
9089
+ hasToken:
9090
+ type: boolean
9091
+ description: Whether an API token is stored for this workspace.
9092
+ baseUrl:
9093
+ type: string
9094
+ description: Configured API base URL override, when set.
9095
+ userName:
9096
+ type: string
9097
+ description: PagerDuty user name when known from the last successful verify.
9098
+ userEmail:
9099
+ type: string
9100
+ description: PagerDuty user email when known from the last successful verify.
9101
+
8750
9102
  AgentExecutionProviderDto:
8751
9103
  type: string
8752
9104
  description: >
@@ -8774,6 +9126,7 @@ components:
8774
9126
  - $ref: "#/components/schemas/PrometheusSourceConfigDto"
8775
9127
  - $ref: "#/components/schemas/GrafanaSourceConfigDto"
8776
9128
  - $ref: "#/components/schemas/SonarQubeSourceConfigDto"
9129
+ - $ref: "#/components/schemas/PagerDutySourceConfigDto"
8777
9130
  - $ref: "#/components/schemas/TenantSourceEntryDto"
8778
9131
  orgChart:
8779
9132
  nullable: true
@@ -14644,6 +14997,8 @@ components:
14644
14997
  - integrations.cursor.platform_key_enabled
14645
14998
  - integrations.cursor.platform_key_disabled
14646
14999
  - member.invited
15000
+ - member.invite_accepted
15001
+ - member.invite_rejected
14647
15002
  - member.role_changed
14648
15003
  - member.removed
14649
15004
  - hris.personio.sync_started
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thinkai/tai-api-contract",
3
- "version": "2.70.0",
3
+ "version": "2.72.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "dist/index.js",