@company-semantics/contracts 0.122.0 → 0.123.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@company-semantics/contracts",
3
- "version": "0.122.0",
3
+ "version": "0.123.0",
4
4
  "private": false,
5
5
  "repository": {
6
6
  "type": "git",
@@ -56,6 +56,10 @@
56
56
  "types": "./src/org/index.ts",
57
57
  "default": "./src/org/index.ts"
58
58
  },
59
+ "./content": {
60
+ "types": "./src/content/index.ts",
61
+ "default": "./src/content/index.ts"
62
+ },
59
63
  "./schemas/guard-result.schema.json": "./schemas/guard-result.schema.json"
60
64
  },
61
65
  "types": "./src/index.ts",
@@ -356,12 +356,7 @@ export interface paths {
356
356
  path?: never;
357
357
  cookie?: never;
358
358
  };
359
- /**
360
- * Get execution timeline
361
- * @description Returns the timeline for an execution.
362
- * Timeline is a read-only projection over audit data.
363
- * Returns 404 for both non-existent and non-visible executions (prevents existence leaks).
364
- */
359
+ /** Get timeline events for an execution */
365
360
  get: operations["getExecutionTimeline"];
366
361
  put?: never;
367
362
  post?: never;
@@ -378,11 +373,7 @@ export interface paths {
378
373
  path?: never;
379
374
  cookie?: never;
380
375
  };
381
- /**
382
- * Get execution summary
383
- * @description Returns the ExecutionSummary projection for an execution.
384
- * Summary is a UI-facing projection derived from audit records.
385
- */
376
+ /** Get execution summary projection */
386
377
  get: operations["getExecutionSummary"];
387
378
  put?: never;
388
379
  post?: never;
@@ -399,16 +390,10 @@ export interface paths {
399
390
  path?: never;
400
391
  cookie?: never;
401
392
  };
402
- /**
403
- * List executions
404
- * @description Lists execution summaries with optional filtering.
405
- */
393
+ /** List executions with cursor pagination */
406
394
  get: operations["listExecutions"];
407
395
  put?: never;
408
- /**
409
- * Start a new execution
410
- * @description Start a new execution for an integration action.
411
- */
396
+ /** Start a new execution */
412
397
  post: operations["startExecution"];
413
398
  delete?: never;
414
399
  options?: never;
@@ -423,11 +408,7 @@ export interface paths {
423
408
  path?: never;
424
409
  cookie?: never;
425
410
  };
426
- /**
427
- * Get execution explanation
428
- * @description Returns the deterministic explanation for an execution.
429
- * Explanation is generated from audit records, NOT from LLM.
430
- */
411
+ /** Get deterministic explanation for an execution */
431
412
  get: operations["getExplanation"];
432
413
  put?: never;
433
414
  post?: never;
@@ -446,12 +427,7 @@ export interface paths {
446
427
  };
447
428
  get?: never;
448
429
  put?: never;
449
- /**
450
- * Undo a completed execution
451
- * @description Undoes a completed execution within its undo window.
452
- * The caller must be the same user who initiated the execution.
453
- * Idempotent: if undo was already performed, returns the existing result.
454
- */
430
+ /** Undo a completed execution within its undo window */
455
431
  post: operations["undoExecution"];
456
432
  delete?: never;
457
433
  options?: never;
@@ -468,11 +444,7 @@ export interface paths {
468
444
  };
469
445
  get?: never;
470
446
  put?: never;
471
- /**
472
- * Confirm a pending execution
473
- * @description Confirms a pending execution. Serialized via advisory lock.
474
- * The caller must be the same user who initiated the execution.
475
- */
447
+ /** Confirm pending execution */
476
448
  post: operations["confirmExecution"];
477
449
  delete?: never;
478
450
  options?: never;
@@ -489,11 +461,7 @@ export interface paths {
489
461
  };
490
462
  get?: never;
491
463
  put?: never;
492
- /**
493
- * Reject a pending execution
494
- * @description Rejects a pending execution. Serialized via advisory lock.
495
- * The caller must be the same user who initiated the execution.
496
- */
464
+ /** Reject pending execution */
497
465
  post: operations["rejectExecution"];
498
466
  delete?: never;
499
467
  options?: never;
@@ -508,11 +476,7 @@ export interface paths {
508
476
  path?: never;
509
477
  cookie?: never;
510
478
  };
511
- /**
512
- * Get timeline UI events
513
- * @description Returns timeline events in UI projection format.
514
- * This is the user-facing timeline with derived labels and icons.
515
- */
479
+ /** Get timeline events in UI projection format */
516
480
  get: operations["getTimelineUI"];
517
481
  put?: never;
518
482
  post?: never;
@@ -2504,11 +2468,9 @@ export interface components {
2504
2468
  status: "executing" | "blocked_pending_approval" | "already_confirmed" | "awaiting_approval";
2505
2469
  code?: string;
2506
2470
  executionId?: string;
2507
- /** @description ExecutionResultData when execution completes inline */
2508
- result?: Record<string, never>;
2509
2471
  };
2510
2472
  RejectExecutionResponse: {
2511
- /** @enum {string} */
2473
+ /** @constant */
2512
2474
  status: "cancelled";
2513
2475
  };
2514
2476
  ExecutionSummary: {
@@ -2529,21 +2491,30 @@ export interface components {
2529
2491
  summary: components["schemas"]["ExecutionSummary"];
2530
2492
  };
2531
2493
  ExecutionListResponse: {
2532
- executions: components["schemas"]["ExecutionSummary"][];
2533
- /** @description Cursor for next page, null if no more results */
2494
+ executions: {
2495
+ /** Format: uuid */
2496
+ executionId: string;
2497
+ kind: string;
2498
+ /** @enum {string} */
2499
+ status: "pending" | "succeeded" | "failed";
2500
+ /** Format: date-time */
2501
+ decidedAt: string;
2502
+ /** Format: date-time */
2503
+ completedAt?: string;
2504
+ target: {
2505
+ type: string;
2506
+ };
2507
+ }[];
2534
2508
  nextCursor?: string | null;
2535
- /** @description Whether more results are available */
2536
- hasMore: boolean;
2509
+ hasMore?: boolean;
2537
2510
  };
2538
2511
  ExecutionStartRequest: {
2539
2512
  kind: string;
2540
2513
  target: {
2541
- /** @enum {string} */
2542
- type: "slack";
2514
+ type: string;
2543
2515
  workspaceId?: string;
2544
2516
  };
2545
2517
  connectionId?: string;
2546
- /** Format: uri */
2547
2518
  returnUrl?: string;
2548
2519
  };
2549
2520
  ExecutionStartResponse: {
@@ -3565,6 +3536,28 @@ export interface components {
3565
3536
  PreviewTransferRequest: {
3566
3537
  token: string;
3567
3538
  };
3539
+ ExecutionTimelineResponse: {
3540
+ events: {
3541
+ eventId: string;
3542
+ /** Format: uuid */
3543
+ executionId: string;
3544
+ timestamp: string;
3545
+ createdAt: string;
3546
+ kind: string;
3547
+ summary: string;
3548
+ details?: {
3549
+ [key: string]: unknown;
3550
+ };
3551
+ relatedIds?: {
3552
+ decisionId?: string;
3553
+ artifactId?: string;
3554
+ rollbackId?: string;
3555
+ provenanceIds?: string[];
3556
+ };
3557
+ /** @enum {string} */
3558
+ visibilityLevel: "system" | "oversight" | "org_admin" | "user";
3559
+ }[];
3560
+ };
3568
3561
  };
3569
3562
  responses: never;
3570
3563
  parameters: never;
@@ -4038,39 +4031,18 @@ export interface operations {
4038
4031
  parameters: {
4039
4032
  query?: never;
4040
4033
  header?: never;
4041
- path: {
4042
- /** @description Execution ID (UUID v4) */
4043
- executionId: string;
4044
- };
4034
+ path?: never;
4045
4035
  cookie?: never;
4046
4036
  };
4047
4037
  requestBody?: never;
4048
4038
  responses: {
4049
- /** @description Timeline events for the execution */
4039
+ /** @description Execution timeline events */
4050
4040
  200: {
4051
4041
  headers: {
4052
4042
  [name: string]: unknown;
4053
4043
  };
4054
4044
  content: {
4055
- "application/json": components["schemas"]["TimelineResponse"];
4056
- };
4057
- };
4058
- /** @description Invalid execution ID format */
4059
- 400: {
4060
- headers: {
4061
- [name: string]: unknown;
4062
- };
4063
- content: {
4064
- "application/json": components["schemas"]["ErrorResponse"];
4065
- };
4066
- };
4067
- /** @description Execution not found or not visible */
4068
- 404: {
4069
- headers: {
4070
- [name: string]: unknown;
4071
- };
4072
- content: {
4073
- "application/json": components["schemas"]["ErrorResponse"];
4045
+ "application/json": components["schemas"]["ExecutionTimelineResponse"];
4074
4046
  };
4075
4047
  };
4076
4048
  };
@@ -4079,10 +4051,7 @@ export interface operations {
4079
4051
  parameters: {
4080
4052
  query?: never;
4081
4053
  header?: never;
4082
- path: {
4083
- /** @description Execution ID (UUID v4) */
4084
- executionId: string;
4085
- };
4054
+ path?: never;
4086
4055
  cookie?: never;
4087
4056
  };
4088
4057
  requestBody?: never;
@@ -4092,44 +4061,18 @@ export interface operations {
4092
4061
  headers: {
4093
4062
  [name: string]: unknown;
4094
4063
  };
4095
- content: {
4096
- "application/json": components["schemas"]["ExecutionSummaryResponse"];
4097
- };
4098
- };
4099
- /** @description Invalid execution ID format */
4100
- 400: {
4101
- headers: {
4102
- [name: string]: unknown;
4103
- };
4104
- content: {
4105
- "application/json": components["schemas"]["ErrorResponse"];
4106
- };
4107
- };
4108
- /** @description Execution not found or not visible */
4109
- 404: {
4110
- headers: {
4111
- [name: string]: unknown;
4112
- };
4113
- content: {
4114
- "application/json": components["schemas"]["ErrorResponse"];
4115
- };
4064
+ content?: never;
4116
4065
  };
4117
4066
  };
4118
4067
  };
4119
4068
  listExecutions: {
4120
4069
  parameters: {
4121
4070
  query?: {
4122
- /** @description Filter by ExecutionKind */
4123
- kind?: string;
4124
- /** @description Filter by target type */
4125
- targetType?: string;
4126
- /** @description Max results (default 100) */
4127
- limit?: number;
4128
- /** @description Cursor for pagination */
4129
4071
  cursor?: string;
4130
- /** @description Start of date range filter */
4072
+ limit?: number;
4073
+ kind?: "integration.connect" | "integration.disconnect" | "profile.update" | "slack.send" | "data.ingest" | "data.scope" | "system.cleanup";
4074
+ targetType?: string;
4131
4075
  periodStart?: string;
4132
- /** @description End of date range filter */
4133
4076
  periodEnd?: string;
4134
4077
  };
4135
4078
  header?: never;
@@ -4138,7 +4081,7 @@ export interface operations {
4138
4081
  };
4139
4082
  requestBody?: never;
4140
4083
  responses: {
4141
- /** @description List of execution summaries */
4084
+ /** @description Paginated execution list */
4142
4085
  200: {
4143
4086
  headers: {
4144
4087
  [name: string]: unknown;
@@ -4147,15 +4090,6 @@ export interface operations {
4147
4090
  "application/json": components["schemas"]["ExecutionListResponse"];
4148
4091
  };
4149
4092
  };
4150
- /** @description Invalid kind parameter */
4151
- 400: {
4152
- headers: {
4153
- [name: string]: unknown;
4154
- };
4155
- content: {
4156
- "application/json": components["schemas"]["ErrorResponse"];
4157
- };
4158
- };
4159
4093
  };
4160
4094
  };
4161
4095
  startExecution: {
@@ -4176,27 +4110,7 @@ export interface operations {
4176
4110
  headers: {
4177
4111
  [name: string]: unknown;
4178
4112
  };
4179
- content: {
4180
- "application/json": components["schemas"]["ExecutionStartResponse"];
4181
- };
4182
- };
4183
- /** @description Invalid execution kind or missing required fields */
4184
- 400: {
4185
- headers: {
4186
- [name: string]: unknown;
4187
- };
4188
- content: {
4189
- "application/json": components["schemas"]["ErrorResponse"];
4190
- };
4191
- };
4192
- /** @description User does not have required admin role */
4193
- 403: {
4194
- headers: {
4195
- [name: string]: unknown;
4196
- };
4197
- content: {
4198
- "application/json": components["schemas"]["ErrorResponse"];
4199
- };
4113
+ content?: never;
4200
4114
  };
4201
4115
  };
4202
4116
  };
@@ -4204,10 +4118,7 @@ export interface operations {
4204
4118
  parameters: {
4205
4119
  query?: never;
4206
4120
  header?: never;
4207
- path: {
4208
- /** @description Execution ID (UUID v4) */
4209
- executionId: string;
4210
- };
4121
+ path?: never;
4211
4122
  cookie?: never;
4212
4123
  };
4213
4124
  requestBody?: never;
@@ -4217,36 +4128,7 @@ export interface operations {
4217
4128
  headers: {
4218
4129
  [name: string]: unknown;
4219
4130
  };
4220
- content: {
4221
- "application/json": components["schemas"]["ExplanationResponse"];
4222
- };
4223
- };
4224
- /** @description Invalid execution ID format */
4225
- 400: {
4226
- headers: {
4227
- [name: string]: unknown;
4228
- };
4229
- content: {
4230
- "application/json": components["schemas"]["ErrorResponse"];
4231
- };
4232
- };
4233
- /** @description Execution not found or not visible */
4234
- 404: {
4235
- headers: {
4236
- [name: string]: unknown;
4237
- };
4238
- content: {
4239
- "application/json": components["schemas"]["ErrorResponse"];
4240
- };
4241
- };
4242
- /** @description Explanation service not available */
4243
- 501: {
4244
- headers: {
4245
- [name: string]: unknown;
4246
- };
4247
- content: {
4248
- "application/json": components["schemas"]["ErrorResponse"];
4249
- };
4131
+ content?: never;
4250
4132
  };
4251
4133
  };
4252
4134
  };
@@ -4254,10 +4136,7 @@ export interface operations {
4254
4136
  parameters: {
4255
4137
  query?: never;
4256
4138
  header?: never;
4257
- path: {
4258
- /** @description Execution ID (UUID v4) */
4259
- executionId: string;
4260
- };
4139
+ path?: never;
4261
4140
  cookie?: never;
4262
4141
  };
4263
4142
  requestBody?: never;
@@ -4267,45 +4146,7 @@ export interface operations {
4267
4146
  headers: {
4268
4147
  [name: string]: unknown;
4269
4148
  };
4270
- content: {
4271
- "application/json": components["schemas"]["UndoResultData"];
4272
- };
4273
- };
4274
- /** @description Invalid execution ID format or execution not in undoable state */
4275
- 400: {
4276
- headers: {
4277
- [name: string]: unknown;
4278
- };
4279
- content: {
4280
- "application/json": components["schemas"]["ErrorResponse"];
4281
- };
4282
- };
4283
- /** @description Insufficient permissions (not the initiating user) */
4284
- 403: {
4285
- headers: {
4286
- [name: string]: unknown;
4287
- };
4288
- content: {
4289
- "application/json": components["schemas"]["ExecutionLifecycleError"];
4290
- };
4291
- };
4292
- /** @description Execution not found */
4293
- 404: {
4294
- headers: {
4295
- [name: string]: unknown;
4296
- };
4297
- content: {
4298
- "application/json": components["schemas"]["ErrorResponse"];
4299
- };
4300
- };
4301
- /** @description Execution in wrong state (e.g. undo window expired) */
4302
- 409: {
4303
- headers: {
4304
- [name: string]: unknown;
4305
- };
4306
- content: {
4307
- "application/json": components["schemas"]["ExecutionLifecycleError"];
4308
- };
4149
+ content?: never;
4309
4150
  };
4310
4151
  };
4311
4152
  };
@@ -4313,15 +4154,12 @@ export interface operations {
4313
4154
  parameters: {
4314
4155
  query?: never;
4315
4156
  header?: never;
4316
- path: {
4317
- /** @description Execution ID (UUID v4) */
4318
- executionId: string;
4319
- };
4157
+ path?: never;
4320
4158
  cookie?: never;
4321
4159
  };
4322
4160
  requestBody?: never;
4323
4161
  responses: {
4324
- /** @description Confirmation result */
4162
+ /** @description Execution confirmed */
4325
4163
  200: {
4326
4164
  headers: {
4327
4165
  [name: string]: unknown;
@@ -4330,66 +4168,18 @@ export interface operations {
4330
4168
  "application/json": components["schemas"]["ConfirmExecutionResponse"];
4331
4169
  };
4332
4170
  };
4333
- /** @description Invalid execution ID format */
4334
- 400: {
4335
- headers: {
4336
- [name: string]: unknown;
4337
- };
4338
- content: {
4339
- "application/json": components["schemas"]["ErrorResponse"];
4340
- };
4341
- };
4342
- /** @description Insufficient permissions (not the initiating user) */
4343
- 403: {
4344
- headers: {
4345
- [name: string]: unknown;
4346
- };
4347
- content: {
4348
- "application/json": components["schemas"]["ExecutionLifecycleError"];
4349
- };
4350
- };
4351
- /** @description Execution not found */
4352
- 404: {
4353
- headers: {
4354
- [name: string]: unknown;
4355
- };
4356
- content: {
4357
- "application/json": components["schemas"]["ErrorResponse"];
4358
- };
4359
- };
4360
- /** @description Execution not in pending_confirmation state */
4361
- 409: {
4362
- headers: {
4363
- [name: string]: unknown;
4364
- };
4365
- content: {
4366
- "application/json": components["schemas"]["ExecutionLifecycleError"];
4367
- };
4368
- };
4369
- /** @description Confirmation has expired */
4370
- 410: {
4371
- headers: {
4372
- [name: string]: unknown;
4373
- };
4374
- content: {
4375
- "application/json": components["schemas"]["ExecutionLifecycleError"];
4376
- };
4377
- };
4378
4171
  };
4379
4172
  };
4380
4173
  rejectExecution: {
4381
4174
  parameters: {
4382
4175
  query?: never;
4383
4176
  header?: never;
4384
- path: {
4385
- /** @description Execution ID (UUID v4) */
4386
- executionId: string;
4387
- };
4177
+ path?: never;
4388
4178
  cookie?: never;
4389
4179
  };
4390
4180
  requestBody?: never;
4391
4181
  responses: {
4392
- /** @description Rejection result */
4182
+ /** @description Execution rejected */
4393
4183
  200: {
4394
4184
  headers: {
4395
4185
  [name: string]: unknown;
@@ -4398,55 +4188,15 @@ export interface operations {
4398
4188
  "application/json": components["schemas"]["RejectExecutionResponse"];
4399
4189
  };
4400
4190
  };
4401
- /** @description Invalid execution ID format */
4402
- 400: {
4403
- headers: {
4404
- [name: string]: unknown;
4405
- };
4406
- content: {
4407
- "application/json": components["schemas"]["ErrorResponse"];
4408
- };
4409
- };
4410
- /** @description Insufficient permissions (not the initiating user) */
4411
- 403: {
4412
- headers: {
4413
- [name: string]: unknown;
4414
- };
4415
- content: {
4416
- "application/json": components["schemas"]["ExecutionLifecycleError"];
4417
- };
4418
- };
4419
- /** @description Execution not found */
4420
- 404: {
4421
- headers: {
4422
- [name: string]: unknown;
4423
- };
4424
- content: {
4425
- "application/json": components["schemas"]["ErrorResponse"];
4426
- };
4427
- };
4428
- /** @description Execution not in pending_confirmation state */
4429
- 409: {
4430
- headers: {
4431
- [name: string]: unknown;
4432
- };
4433
- content: {
4434
- "application/json": components["schemas"]["ExecutionLifecycleError"];
4435
- };
4436
- };
4437
4191
  };
4438
4192
  };
4439
4193
  getTimelineUI: {
4440
4194
  parameters: {
4441
4195
  query?: {
4442
- /** @description Filter by ExecutionKind */
4443
- kind?: string;
4444
- /** @description Filter by kind prefix */
4445
- kindPrefix?: string;
4446
- /** @description Max results (default 100) */
4447
4196
  limit?: number;
4448
- /** @description Pagination offset (default 0) */
4449
4197
  offset?: number;
4198
+ kind?: "integration.connect" | "integration.disconnect" | "profile.update" | "slack.send" | "data.ingest" | "data.scope" | "system.cleanup";
4199
+ kindPrefix?: string;
4450
4200
  };
4451
4201
  header?: never;
4452
4202
  path?: never;
@@ -4454,23 +4204,12 @@ export interface operations {
4454
4204
  };
4455
4205
  requestBody?: never;
4456
4206
  responses: {
4457
- /** @description Timeline UI events */
4207
+ /** @description UI timeline events */
4458
4208
  200: {
4459
4209
  headers: {
4460
4210
  [name: string]: unknown;
4461
4211
  };
4462
- content: {
4463
- "application/json": components["schemas"]["TimelineUIResponse"];
4464
- };
4465
- };
4466
- /** @description Invalid kind parameter */
4467
- 400: {
4468
- headers: {
4469
- [name: string]: unknown;
4470
- };
4471
- content: {
4472
- "application/json": components["schemas"]["ErrorResponse"];
4473
- };
4212
+ content?: never;
4474
4213
  };
4475
4214
  };
4476
4215
  };
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Content Domain Barrel
3
+ *
4
+ * Re-exports content response schemas for company-md, teams, departments, and drive.
5
+ * Import from '@company-semantics/contracts/content'.
6
+ */
7
+
8
+ // Company.md response schemas (PRD-00448)
9
+ export {
10
+ CompanyMdListResponseSchema,
11
+ CompanyMdDocResponseSchema,
12
+ CompanyMdShareResponseSchema,
13
+ CompanyMdContextBankResponseSchema,
14
+ CompanyMdSettingsResponseSchema,
15
+ } from './schemas';
16
+ export type {
17
+ CompanyMdListResponse,
18
+ CompanyMdDocResponse,
19
+ CompanyMdShareResponse,
20
+ CompanyMdContextBankResponse,
21
+ CompanyMdSettingsResponse,
22
+ } from './schemas';
23
+
24
+ // Team response schemas (PRD-00448)
25
+ export { TeamListResponseSchema, TeamResponseSchema } from './schemas';
26
+ export type { TeamListResponse, TeamResponse } from './schemas';
27
+
28
+ // Department response schemas (PRD-00448)
29
+ export { DepartmentListResponseSchema, DepartmentResponseSchema } from './schemas';
30
+ export type { DepartmentListResponse, DepartmentResponse } from './schemas';
31
+
32
+ // Drive response schemas (PRD-00448)
33
+ export { DriveFileListResponseSchema, DriveFileContentResponseSchema } from './schemas';
34
+ export type { DriveFileListResponse, DriveFileContentResponse } from './schemas';
@@ -0,0 +1,286 @@
1
+ /**
2
+ * Content Domain Response Schemas
3
+ *
4
+ * Zod response schemas for content and org structure endpoints.
5
+ * Canonical location for runtime validation of company-md, team,
6
+ * department, and drive API responses.
7
+ *
8
+ * Covers:
9
+ * - company-md.ts (GET /api/company-md/tree, GET /api/company-md/docs/:slug, etc.)
10
+ * - company-md-sharing.ts (GET /api/company-md/docs/:slug/sharing)
11
+ * - teams.ts (GET /api/teams, GET /api/teams/:teamId, etc.)
12
+ * - departments.ts (GET /api/departments, GET /api/departments/:id, etc.)
13
+ * - drive.ts (GET /api/drive/files, GET /api/drive/files/recent, etc.)
14
+ */
15
+ import { z } from 'zod';
16
+ import { CursorPageSchema } from '../api/primitives';
17
+
18
+ // ---------------------------------------------------------------------------
19
+ // Company.md Sub-schemas
20
+ // ---------------------------------------------------------------------------
21
+
22
+ const CompanyMdOwningTeamSchema = z.object({
23
+ id: z.string(),
24
+ name: z.string(),
25
+ });
26
+
27
+ const CompanyMdPersonSchema = z.object({
28
+ id: z.string(),
29
+ name: z.string(),
30
+ });
31
+
32
+ const CompanyMdSourceSchema = z.object({
33
+ label: z.string(),
34
+ sourceType: z.enum(['meeting', 'document', 'conversation', 'manual']),
35
+ referencedAt: z.string(),
36
+ });
37
+
38
+ const CompanyMdDependencySchema = z.object({
39
+ targetSlug: z.string(),
40
+ description: z.string(),
41
+ });
42
+
43
+ const CompanyMdTreeNodeSchema = z.object({
44
+ id: z.string(),
45
+ slug: z.string(),
46
+ title: z.string(),
47
+ level: z.enum(['root', 'department', 'team', 'context']),
48
+ parentId: z.string().nullable(),
49
+ department: z.string().nullable(),
50
+ departmentId: z.string().nullable(),
51
+ visibility: z.enum(['public', 'private']),
52
+ owningTeam: CompanyMdOwningTeamSchema.nullable(),
53
+ type: z.enum(['company', 'department', 'team', 'cross_team', 'doc', 'goal', 'source', 'map', 'context_bank']),
54
+ canEdit: z.boolean(),
55
+ memberCount: z.number().int(),
56
+ description: z.string().optional(),
57
+ departmentIds: z.array(z.string()).optional(),
58
+ });
59
+
60
+ // ---------------------------------------------------------------------------
61
+ // Company.md HTTP Response Schemas
62
+ // ---------------------------------------------------------------------------
63
+
64
+ /** Response for GET /api/company-md/tree */
65
+ export const CompanyMdListResponseSchema = CursorPageSchema(CompanyMdTreeNodeSchema);
66
+
67
+ /** Response for GET /api/company-md/docs/:slug */
68
+ export const CompanyMdDocResponseSchema = z.object({
69
+ id: z.string(),
70
+ slug: z.string(),
71
+ title: z.string(),
72
+ level: z.enum(['root', 'department', 'team', 'context']),
73
+ department: z.string().nullable(),
74
+ departmentId: z.string().nullable(),
75
+ content: z.string(),
76
+ visibility: z.enum(['public', 'private']),
77
+ parentId: z.string().nullable(),
78
+ owningTeam: CompanyMdOwningTeamSchema.nullable(),
79
+ owner: CompanyMdPersonSchema.nullable(),
80
+ coOwners: z.array(CompanyMdPersonSchema),
81
+ canEdit: z.boolean(),
82
+ inheritsFrom: z.string().nullable(),
83
+ sources: z.array(CompanyMdSourceSchema),
84
+ dependencies: z.array(CompanyMdDependencySchema),
85
+ members: z.array(CompanyMdPersonSchema),
86
+ extractionStatus: z.enum(['pending', 'extracting', 'complete', 'failed']),
87
+ createdAt: z.string(),
88
+ updatedAt: z.string(),
89
+ });
90
+
91
+ // ---------------------------------------------------------------------------
92
+ // Company.md Sharing Sub-schemas
93
+ // ---------------------------------------------------------------------------
94
+
95
+ const AclEntrySchema = z.object({
96
+ principalType: z.enum(['user', 'team']),
97
+ principalId: z.string(),
98
+ principalName: z.string(),
99
+ accessLevel: z.enum(['viewer', 'commenter', 'editor']),
100
+ grantedBy: z.object({ id: z.string(), name: z.string() }).nullable(),
101
+ grantedAt: z.string(),
102
+ });
103
+
104
+ const AccessReasonSchema = z.object({
105
+ source: z.enum(['org_rbac', 'sharing_policy', 'team_baseline', 'acl_grant', 'doc_ownership']),
106
+ detail: z.string(),
107
+ });
108
+
109
+ const EffectiveAccessSchema = z.object({
110
+ level: z.enum(['none', 'viewer', 'commenter', 'editor']),
111
+ reasons: z.array(AccessReasonSchema),
112
+ canShare: z.boolean(),
113
+ });
114
+
115
+ /** Response for GET /api/company-md/docs/:slug/sharing */
116
+ export const CompanyMdShareResponseSchema = z.object({
117
+ sharingPolicy: z.enum(['restricted', 'org_read', 'org_comment', 'org_edit']),
118
+ acl: z.array(AclEntrySchema),
119
+ effectiveAccess: EffectiveAccessSchema,
120
+ });
121
+
122
+ // ---------------------------------------------------------------------------
123
+ // Company.md Context Bank + Settings Response Schemas
124
+ // ---------------------------------------------------------------------------
125
+
126
+ const CompanyMdContextBankItemSchema = z.object({
127
+ id: z.string(),
128
+ slug: z.string(),
129
+ title: z.string(),
130
+ visibility: z.enum(['public', 'private']),
131
+ updatedAt: z.string(),
132
+ });
133
+
134
+ /** Response for GET /api/company-md/docs/:slug/context-bank */
135
+ export const CompanyMdContextBankResponseSchema = z.object({
136
+ items: z.array(CompanyMdContextBankItemSchema),
137
+ });
138
+
139
+ const CompanyMdLevelLabelsSchema = z.object({
140
+ root: z.string(),
141
+ department: z.string(),
142
+ team: z.string(),
143
+ });
144
+
145
+ /** Response for GET /api/company-md/settings */
146
+ export const CompanyMdSettingsResponseSchema = z.object({
147
+ levelLabels: CompanyMdLevelLabelsSchema,
148
+ });
149
+
150
+ // ---------------------------------------------------------------------------
151
+ // Team Sub-schemas
152
+ // ---------------------------------------------------------------------------
153
+
154
+ const TeamMemberSchema = z.object({
155
+ userId: z.string(),
156
+ name: z.string(),
157
+ email: z.string(),
158
+ role: z.enum(['member', 'manager', 'owner']),
159
+ joinedAt: z.string(),
160
+ });
161
+
162
+ const TeamSummarySchema = z.object({
163
+ id: z.string(),
164
+ name: z.string(),
165
+ slug: z.string(),
166
+ description: z.string().nullable(),
167
+ memberCount: z.number().int(),
168
+ scope: z.enum(['department', 'cross_department', 'org']),
169
+ department: z.object({ id: z.string(), name: z.string(), slug: z.string() }).nullable(),
170
+ homeDepartment: z.object({ id: z.string(), name: z.string(), slug: z.string() }).nullable(),
171
+ });
172
+
173
+ // ---------------------------------------------------------------------------
174
+ // Team HTTP Response Schemas
175
+ // ---------------------------------------------------------------------------
176
+
177
+ /** Response for GET /api/teams */
178
+ export const TeamListResponseSchema = z.object({
179
+ teams: z.array(TeamSummarySchema),
180
+ });
181
+
182
+ /** Response for GET /api/teams/:teamId */
183
+ export const TeamResponseSchema = z.object({
184
+ id: z.string(),
185
+ name: z.string(),
186
+ slug: z.string(),
187
+ description: z.string().nullable(),
188
+ syncMode: z.enum(['manual_only', 'synced_readonly', 'synced_with_overrides']),
189
+ members: z.array(TeamMemberSchema),
190
+ });
191
+
192
+ // ---------------------------------------------------------------------------
193
+ // Department Sub-schemas
194
+ // ---------------------------------------------------------------------------
195
+
196
+ const DepartmentMemberSchema = z.object({
197
+ userId: z.string(),
198
+ name: z.string(),
199
+ email: z.string(),
200
+ role: z.enum(['member', 'manager', 'owner']),
201
+ joinedAt: z.string(),
202
+ });
203
+
204
+ const DepartmentSummarySchema = z.object({
205
+ id: z.string(),
206
+ name: z.string(),
207
+ slug: z.string(),
208
+ description: z.string().nullable(),
209
+ memberCount: z.number().int(),
210
+ position: z.number().int(),
211
+ });
212
+
213
+ // ---------------------------------------------------------------------------
214
+ // Department HTTP Response Schemas
215
+ // ---------------------------------------------------------------------------
216
+
217
+ /** Response for GET /api/departments */
218
+ export const DepartmentListResponseSchema = z.object({
219
+ departments: z.array(DepartmentSummarySchema),
220
+ });
221
+
222
+ /** Response for GET /api/departments/:id */
223
+ export const DepartmentResponseSchema = z.object({
224
+ id: z.string(),
225
+ name: z.string(),
226
+ slug: z.string(),
227
+ description: z.string().nullable(),
228
+ position: z.number().int(),
229
+ syncMode: z.enum(['manual_only', 'scim', 'hris']),
230
+ memberCount: z.number().int(),
231
+ members: z.array(DepartmentMemberSchema),
232
+ });
233
+
234
+ // ---------------------------------------------------------------------------
235
+ // Drive Sub-schemas
236
+ // ---------------------------------------------------------------------------
237
+
238
+ const DriveFileOwnerSchema = z.object({
239
+ displayName: z.string().optional(),
240
+ emailAddress: z.string().optional(),
241
+ });
242
+
243
+ const DriveFileSchema = z.object({
244
+ id: z.string(),
245
+ name: z.string(),
246
+ mimeType: z.string(),
247
+ createdTime: z.string().optional(),
248
+ modifiedTime: z.string().optional(),
249
+ owners: z.array(DriveFileOwnerSchema).optional(),
250
+ webViewLink: z.string().optional(),
251
+ iconLink: z.string().optional(),
252
+ size: z.string().optional(),
253
+ });
254
+
255
+ // ---------------------------------------------------------------------------
256
+ // Drive HTTP Response Schemas
257
+ // ---------------------------------------------------------------------------
258
+
259
+ /** Response for GET /api/drive/files and GET /api/drive/files/recent */
260
+ export const DriveFileListResponseSchema = z.object({
261
+ files: z.array(DriveFileSchema),
262
+ nextPageToken: z.string().optional(),
263
+ });
264
+
265
+ /** Response for GET /api/drive/files/:fileId/content */
266
+ export const DriveFileContentResponseSchema = z.object({
267
+ content: z.string(),
268
+ exportedAs: z.string(),
269
+ truncated: z.boolean(),
270
+ });
271
+
272
+ // ---------------------------------------------------------------------------
273
+ // Inferred Types
274
+ // ---------------------------------------------------------------------------
275
+
276
+ export type CompanyMdListResponse = z.infer<typeof CompanyMdListResponseSchema>;
277
+ export type CompanyMdDocResponse = z.infer<typeof CompanyMdDocResponseSchema>;
278
+ export type CompanyMdShareResponse = z.infer<typeof CompanyMdShareResponseSchema>;
279
+ export type CompanyMdContextBankResponse = z.infer<typeof CompanyMdContextBankResponseSchema>;
280
+ export type CompanyMdSettingsResponse = z.infer<typeof CompanyMdSettingsResponseSchema>;
281
+ export type TeamListResponse = z.infer<typeof TeamListResponseSchema>;
282
+ export type TeamResponse = z.infer<typeof TeamResponseSchema>;
283
+ export type DepartmentListResponse = z.infer<typeof DepartmentListResponseSchema>;
284
+ export type DepartmentResponse = z.infer<typeof DepartmentResponseSchema>;
285
+ export type DriveFileListResponse = z.infer<typeof DriveFileListResponseSchema>;
286
+ export type DriveFileContentResponse = z.infer<typeof DriveFileContentResponseSchema>;