@company-semantics/contracts 2.7.0 → 2.10.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": "2.7.0",
3
+ "version": "2.10.0",
4
4
  "private": false,
5
5
  "repository": {
6
6
  "type": "git",
@@ -1,3 +1,3 @@
1
1
  // AUTO-GENERATED — do not edit. Run pnpm generate:spec-hash to regenerate.
2
- export const SPEC_HASH = 'dfd003162bb3' as const;
3
- export const SPEC_HASH_FULL = 'dfd003162bb3d11c451864139ca8ba09e494cfd652b177f8b5ee8611c0f54e2a' as const;
2
+ export const SPEC_HASH = 'b33671a6612a' as const;
3
+ export const SPEC_HASH_FULL = 'b33671a6612a405a566dcdcc0f0bd2fc4017f84c43a46177e4db59fcb9f21709' as const;
@@ -2262,7 +2262,7 @@ export interface paths {
2262
2262
  patch?: never;
2263
2263
  trace?: never;
2264
2264
  };
2265
- "/api/me/meetings/recordings": {
2265
+ "/api/me/meetings/recordings/start": {
2266
2266
  parameters: {
2267
2267
  query?: never;
2268
2268
  header?: never;
@@ -2271,8 +2271,127 @@ export interface paths {
2271
2271
  };
2272
2272
  get?: never;
2273
2273
  put?: never;
2274
- /** Mint a transcription session grant for a new recording */
2275
- post: operations["issueMeetingRecordingGrant"];
2274
+ /** Start a recording: create draft rows and mint a transcription grant */
2275
+ post: operations["startMeetingRecording"];
2276
+ delete?: never;
2277
+ options?: never;
2278
+ head?: never;
2279
+ patch?: never;
2280
+ trace?: never;
2281
+ };
2282
+ "/api/me/meetings/recordings/{id}/events": {
2283
+ parameters: {
2284
+ query?: never;
2285
+ header?: never;
2286
+ path?: never;
2287
+ cookie?: never;
2288
+ };
2289
+ get?: never;
2290
+ put?: never;
2291
+ /** Apply a batch of recording events (v1 envelope) */
2292
+ post: operations["appendMeetingRecordingEvents"];
2293
+ delete?: never;
2294
+ options?: never;
2295
+ head?: never;
2296
+ patch?: never;
2297
+ trace?: never;
2298
+ };
2299
+ "/api/me/meetings/recordings/{id}/complete": {
2300
+ parameters: {
2301
+ query?: never;
2302
+ header?: never;
2303
+ path?: never;
2304
+ cookie?: never;
2305
+ };
2306
+ get?: never;
2307
+ put?: never;
2308
+ /** Finalize (or cancel) a recording; idempotent on checksum */
2309
+ post: operations["completeMeetingRecording"];
2310
+ delete?: never;
2311
+ options?: never;
2312
+ head?: never;
2313
+ patch?: never;
2314
+ trace?: never;
2315
+ };
2316
+ "/api/me/meetings/recordings/{id}/export": {
2317
+ parameters: {
2318
+ query?: never;
2319
+ header?: never;
2320
+ path?: never;
2321
+ cookie?: never;
2322
+ };
2323
+ get?: never;
2324
+ put?: never;
2325
+ /** Export a transcript as markdown/JSON (sync) or PDF (async job) */
2326
+ post: operations["exportMeetingRecording"];
2327
+ delete?: never;
2328
+ options?: never;
2329
+ head?: never;
2330
+ patch?: never;
2331
+ trace?: never;
2332
+ };
2333
+ "/api/me/meetings/recordings/{id}/export/{jobId}": {
2334
+ parameters: {
2335
+ query?: never;
2336
+ header?: never;
2337
+ path?: never;
2338
+ cookie?: never;
2339
+ };
2340
+ /** Download a rendered PDF export, or poll its job status */
2341
+ get: operations["downloadMeetingRecordingExport"];
2342
+ put?: never;
2343
+ post?: never;
2344
+ delete?: never;
2345
+ options?: never;
2346
+ head?: never;
2347
+ patch?: never;
2348
+ trace?: never;
2349
+ };
2350
+ "/api/me/meetings/recordings/{id}": {
2351
+ parameters: {
2352
+ query?: never;
2353
+ header?: never;
2354
+ path?: never;
2355
+ cookie?: never;
2356
+ };
2357
+ get?: never;
2358
+ put?: never;
2359
+ post?: never;
2360
+ /** Soft-delete a recording (30-day hard-delete grace; idempotent) */
2361
+ delete: operations["softDeleteMeetingRecording"];
2362
+ options?: never;
2363
+ head?: never;
2364
+ patch?: never;
2365
+ trace?: never;
2366
+ };
2367
+ "/api/me/meetings/recordings/{id}/restore": {
2368
+ parameters: {
2369
+ query?: never;
2370
+ header?: never;
2371
+ path?: never;
2372
+ cookie?: never;
2373
+ };
2374
+ get?: never;
2375
+ put?: never;
2376
+ /** Restore a soft-deleted recording within its 30-day window */
2377
+ post: operations["restoreMeetingRecording"];
2378
+ delete?: never;
2379
+ options?: never;
2380
+ head?: never;
2381
+ patch?: never;
2382
+ trace?: never;
2383
+ };
2384
+ "/api/me/meetings/recordings/{id}/visibility": {
2385
+ parameters: {
2386
+ query?: never;
2387
+ header?: never;
2388
+ path?: never;
2389
+ cookie?: never;
2390
+ };
2391
+ get?: never;
2392
+ put?: never;
2393
+ /** Change recording visibility (post-finalize only) */
2394
+ post: operations["changeMeetingRecordingVisibility"];
2276
2395
  delete?: never;
2277
2396
  options?: never;
2278
2397
  head?: never;
@@ -3921,42 +4040,224 @@ export interface components {
3921
4040
  UpdateWorkItemTitleRequest: {
3922
4041
  title: string;
3923
4042
  };
3924
- /** @description Provider-agnostic grant the mac shell consumes. Mac never sees provider name (INV-MTG-15). */
3925
- TranscriptionSessionGrant: {
4043
+ /** @description Recording + work_item ids and the transcription session grant. */
4044
+ StartMeetingRecordingResponse: {
3926
4045
  /** @description ULID; unified trace key for the recording (INV-MTG-7). */
3927
- sessionId: string;
3928
- /** Format: uri */
3929
- connectUrl: string;
3930
- authHeaders: {
3931
- [key: string]: string;
4046
+ recordingId: string;
4047
+ /** Format: uuid */
4048
+ workItemId: string;
4049
+ /** @description Provider-agnostic grant the mac shell consumes. Mac never sees provider name (INV-MTG-15). */
4050
+ grant: {
4051
+ /** @description ULID; unified trace key for the recording (INV-MTG-7). */
4052
+ sessionId: string;
4053
+ /** Format: uri */
4054
+ connectUrl: string;
4055
+ authHeaders: {
4056
+ [key: string]: string;
4057
+ };
4058
+ /** Format: date-time */
4059
+ expiresAt: string;
4060
+ audioConfig: {
4061
+ /** @constant */
4062
+ sampleRateHz: 16000;
4063
+ /** @constant */
4064
+ channels: 2;
4065
+ /** @constant */
4066
+ encoding: "linear16";
4067
+ /** @constant */
4068
+ chunkMs: 200;
4069
+ };
4070
+ capabilities: {
4071
+ interimResults: boolean;
4072
+ multichannelDiarization: boolean;
4073
+ reconnectionTokens: boolean;
4074
+ };
3932
4075
  };
3933
- /** Format: date-time */
3934
- expiresAt: string;
3935
- audioConfig: {
4076
+ };
4077
+ /** @description Start a recording: create draft rows and mint a grant. */
4078
+ StartMeetingRecordingRequest: {
4079
+ /** @description ULID; unified trace key for the recording (INV-MTG-7). */
4080
+ clientRecordingId: string;
4081
+ /**
4082
+ * @description Auto-detected meeting app that owns the system audio stream.
4083
+ * @enum {string}
4084
+ */
4085
+ detectedApp: "zoom" | "teams" | "meet-browser" | "slack-huddle" | "manual";
4086
+ };
4087
+ /** @description Result of applying an event batch. */
4088
+ AppendMeetingRecordingEventsResponse: {
4089
+ /** @description ULID; unified trace key for the recording (INV-MTG-7). */
4090
+ recordingId: string;
4091
+ status: string;
4092
+ chunksAccepted: number;
4093
+ };
4094
+ /** @description A batch of recording events (v1 envelope). */
4095
+ AppendMeetingRecordingEventsRequest: {
4096
+ eventSchemaVersion: number;
4097
+ events: ({
3936
4098
  /** @constant */
3937
- sampleRateHz: 16000;
4099
+ kind: "session_opened";
4100
+ /** @description ULID; unified trace key for the recording (INV-MTG-7). */
4101
+ recordingId: string;
4102
+ atMs: number;
4103
+ } | {
3938
4104
  /** @constant */
3939
- channels: 2;
4105
+ kind: "chunk_batch";
4106
+ /** @description ULID; unified trace key for the recording (INV-MTG-7). */
4107
+ recordingId: string;
4108
+ chunks: {
4109
+ /** @description ULID; unified trace key for the recording (INV-MTG-7). */
4110
+ recordingId: string;
4111
+ /**
4112
+ * @description Capture stream identity. Mic = channel 0, system audio = channel 1.
4113
+ * @enum {string}
4114
+ */
4115
+ source: "mic" | "system";
4116
+ sequence: number;
4117
+ startedAtMs: number;
4118
+ endedAtMs: number;
4119
+ text: string;
4120
+ final: boolean;
4121
+ speakerLabel?: string | null;
4122
+ confidence?: number;
4123
+ }[];
4124
+ } | {
3940
4125
  /** @constant */
3941
- encoding: "linear16";
4126
+ kind: "quality_degraded";
4127
+ /** @description ULID; unified trace key for the recording (INV-MTG-7). */
4128
+ recordingId: string;
4129
+ reason: string;
4130
+ atMs: number;
4131
+ } | {
3942
4132
  /** @constant */
3943
- chunkMs: 200;
3944
- };
3945
- capabilities: {
3946
- interimResults: boolean;
3947
- multichannelDiarization: boolean;
3948
- reconnectionTokens: boolean;
4133
+ kind: "session_stopped";
4134
+ /** @description ULID; unified trace key for the recording (INV-MTG-7). */
4135
+ recordingId: string;
4136
+ atMs: number;
4137
+ expectedLastSequence: number;
4138
+ })[];
4139
+ };
4140
+ /** @description Result of finalizing or cancelling a recording. */
4141
+ CompleteMeetingRecordingResponse: {
4142
+ /** @description ULID; unified trace key for the recording (INV-MTG-7). */
4143
+ recordingId: string;
4144
+ status: string;
4145
+ workItemId: string | null;
4146
+ transcriptDocumentId: string | null;
4147
+ idempotent: boolean;
4148
+ };
4149
+ /** @description Finalize (or cancel) a recording. Idempotent on checksum. */
4150
+ CompleteMeetingRecordingRequest: {
4151
+ expectedLastSequence: number;
4152
+ totalDurationMs: number;
4153
+ checksum: string;
4154
+ cancelled?: boolean;
4155
+ };
4156
+ /** @description Synchronous markdown/JSON content, or a queued PDF job id. */
4157
+ ExportMeetingRecordingResponse: {
4158
+ /** @constant */
4159
+ format: "markdown";
4160
+ content: string;
4161
+ } | {
4162
+ /** @constant */
4163
+ format: "json";
4164
+ /** @description Finalized read projection for a recording (excludes drafts). */
4165
+ metadata: {
4166
+ /** @description ULID; unified trace key for the recording (INV-MTG-7). */
4167
+ recordingId: string;
4168
+ /** Format: uuid */
4169
+ ownerUserId: string;
4170
+ /** Format: uuid */
4171
+ orgId: string;
4172
+ title: string | null;
4173
+ /**
4174
+ * @description Auto-detected meeting app that owns the system audio stream.
4175
+ * @enum {string}
4176
+ */
4177
+ detectedApp: "zoom" | "teams" | "meet-browser" | "slack-huddle" | "manual";
4178
+ /**
4179
+ * @description Visibility band for the finalized meeting projection. Default `meeting_only`.
4180
+ * @enum {string}
4181
+ */
4182
+ visibility: "meeting_only" | "shared" | "org" | "finalized_private";
4183
+ /**
4184
+ * @description Coarse lifecycle state for a recording entity.
4185
+ * @enum {string}
4186
+ */
4187
+ status: "draft" | "recording" | "processing" | "finalized" | "failed" | "partial-transcript-network" | "cancelled";
4188
+ /**
4189
+ * @description Capture-runtime quality signal. `degraded` triggers a UI hint.
4190
+ * @enum {string}
4191
+ */
4192
+ quality: "clean" | "degraded";
4193
+ /** Format: date-time */
4194
+ startedAt: string;
4195
+ endedAt: string | null;
4196
+ durationMs: number;
4197
+ participantUserIds: string[];
4198
+ transcriptAvailable: boolean;
3949
4199
  };
4200
+ segments: {
4201
+ startMs: number;
4202
+ endMs: number;
4203
+ /** @enum {string} */
4204
+ source: "mic" | "remote" | "unknown";
4205
+ speakerLabel: string | null;
4206
+ text: string;
4207
+ confidence: number | null;
4208
+ }[];
4209
+ } | {
4210
+ /** @constant */
4211
+ format: "pdf";
4212
+ /** Format: uuid */
4213
+ jobId: string;
4214
+ /** @constant */
4215
+ status: "queued";
4216
+ };
4217
+ /** @description Export a recording transcript as markdown, JSON, or PDF. */
4218
+ ExportMeetingRecordingRequest: {
4219
+ /** @enum {string} */
4220
+ format: "markdown" | "json" | "pdf";
4221
+ };
4222
+ /** @description PDF export job not yet ready (pending) or failed. */
4223
+ MeetingRecordingExportJobStatus: {
4224
+ /** Format: uuid */
4225
+ jobId: string;
4226
+ /** @enum {string} */
4227
+ status: "pending" | "failed";
3950
4228
  };
3951
- /** @description Request a transcription session grant for a new recording. */
3952
- IssueMeetingRecordingGrantRequest: {
4229
+ /** @description Recording soft-deleted; hard-delete scheduled 30 days out. */
4230
+ SoftDeleteMeetingRecordingResponse: {
3953
4231
  /** @description ULID; unified trace key for the recording (INV-MTG-7). */
3954
- clientRecordingId: string;
4232
+ recordingId: string;
4233
+ /** @constant */
4234
+ deleted: true;
4235
+ hardDeleteScheduledAt: string | null;
4236
+ };
4237
+ /** @description Restore a soft-deleted recording within its grace window. */
4238
+ RestoreMeetingRecordingResponse: {
4239
+ /** @description ULID; unified trace key for the recording (INV-MTG-7). */
4240
+ recordingId: string;
4241
+ restored: boolean;
4242
+ status: string;
4243
+ };
4244
+ /** @description Result of a visibility change. */
4245
+ ChangeMeetingRecordingVisibilityResponse: {
4246
+ /** @description ULID; unified trace key for the recording (INV-MTG-7). */
4247
+ recordingId: string;
3955
4248
  /**
3956
- * @description Auto-detected meeting app that owns the system audio stream.
4249
+ * @description Visibility band for the finalized meeting projection. Default `meeting_only`.
3957
4250
  * @enum {string}
3958
4251
  */
3959
- detectedApp: "zoom" | "teams" | "meet-browser" | "slack-huddle" | "manual";
4252
+ visibility: "meeting_only" | "shared" | "org" | "finalized_private";
4253
+ };
4254
+ /** @description Change a recording visibility (post-finalize only). */
4255
+ ChangeMeetingRecordingVisibilityRequest: {
4256
+ /**
4257
+ * @description Visibility band for the finalized meeting projection. Default `meeting_only`.
4258
+ * @enum {string}
4259
+ */
4260
+ visibility: "meeting_only" | "shared" | "org" | "finalized_private";
3960
4261
  };
3961
4262
  ImpersonationSessionResponse: {
3962
4263
  session: {
@@ -7541,7 +7842,7 @@ export interface operations {
7541
7842
  };
7542
7843
  };
7543
7844
  };
7544
- issueMeetingRecordingGrant: {
7845
+ startMeetingRecording: {
7545
7846
  parameters: {
7546
7847
  query?: never;
7547
7848
  header?: never;
@@ -7550,20 +7851,27 @@ export interface operations {
7550
7851
  };
7551
7852
  requestBody: {
7552
7853
  content: {
7553
- "application/json": components["schemas"]["IssueMeetingRecordingGrantRequest"];
7854
+ "application/json": components["schemas"]["StartMeetingRecordingRequest"];
7554
7855
  };
7555
7856
  };
7556
7857
  responses: {
7557
- /** @description Provider-agnostic transcription session grant */
7858
+ /** @description Recording + work_item ids and the provider-agnostic grant */
7558
7859
  200: {
7559
7860
  headers: {
7560
7861
  [name: string]: unknown;
7561
7862
  };
7562
7863
  content: {
7563
- "application/json": components["schemas"]["TranscriptionSessionGrant"];
7864
+ "application/json": components["schemas"]["StartMeetingRecordingResponse"];
7865
+ };
7866
+ };
7867
+ /** @description A recording is already in progress for this user */
7868
+ 409: {
7869
+ headers: {
7870
+ [name: string]: unknown;
7564
7871
  };
7872
+ content?: never;
7565
7873
  };
7566
- /** @description Rate limit exceeded (10 issuances/user/hour) */
7874
+ /** @description Rate limit exceeded (10 starts/user/hour) */
7567
7875
  429: {
7568
7876
  headers: {
7569
7877
  [name: string]: unknown;
@@ -7579,6 +7887,261 @@ export interface operations {
7579
7887
  };
7580
7888
  };
7581
7889
  };
7890
+ appendMeetingRecordingEvents: {
7891
+ parameters: {
7892
+ query?: never;
7893
+ header?: never;
7894
+ path: {
7895
+ id: string;
7896
+ };
7897
+ cookie?: never;
7898
+ };
7899
+ requestBody: {
7900
+ content: {
7901
+ "application/json": components["schemas"]["AppendMeetingRecordingEventsRequest"];
7902
+ };
7903
+ };
7904
+ responses: {
7905
+ /** @description Event batch applied */
7906
+ 200: {
7907
+ headers: {
7908
+ [name: string]: unknown;
7909
+ };
7910
+ content: {
7911
+ "application/json": components["schemas"]["AppendMeetingRecordingEventsResponse"];
7912
+ };
7913
+ };
7914
+ /** @description Unknown eventSchemaVersion */
7915
+ 400: {
7916
+ headers: {
7917
+ [name: string]: unknown;
7918
+ };
7919
+ content?: never;
7920
+ };
7921
+ /** @description Recording not found or not owned by this user */
7922
+ 404: {
7923
+ headers: {
7924
+ [name: string]: unknown;
7925
+ };
7926
+ content?: never;
7927
+ };
7928
+ /** @description Illegal state transition */
7929
+ 409: {
7930
+ headers: {
7931
+ [name: string]: unknown;
7932
+ };
7933
+ content?: never;
7934
+ };
7935
+ };
7936
+ };
7937
+ completeMeetingRecording: {
7938
+ parameters: {
7939
+ query?: never;
7940
+ header?: never;
7941
+ path: {
7942
+ id: string;
7943
+ };
7944
+ cookie?: never;
7945
+ };
7946
+ requestBody: {
7947
+ content: {
7948
+ "application/json": components["schemas"]["CompleteMeetingRecordingRequest"];
7949
+ };
7950
+ };
7951
+ responses: {
7952
+ /** @description Recording finalized or cancelled */
7953
+ 200: {
7954
+ headers: {
7955
+ [name: string]: unknown;
7956
+ };
7957
+ content: {
7958
+ "application/json": components["schemas"]["CompleteMeetingRecordingResponse"];
7959
+ };
7960
+ };
7961
+ /** @description Recording not found or not owned by this user */
7962
+ 404: {
7963
+ headers: {
7964
+ [name: string]: unknown;
7965
+ };
7966
+ content?: never;
7967
+ };
7968
+ /** @description Conflicting checksum on an already-finalized recording */
7969
+ 409: {
7970
+ headers: {
7971
+ [name: string]: unknown;
7972
+ };
7973
+ content?: never;
7974
+ };
7975
+ };
7976
+ };
7977
+ exportMeetingRecording: {
7978
+ parameters: {
7979
+ query?: never;
7980
+ header?: never;
7981
+ path: {
7982
+ id: string;
7983
+ };
7984
+ cookie?: never;
7985
+ };
7986
+ requestBody: {
7987
+ content: {
7988
+ "application/json": components["schemas"]["ExportMeetingRecordingRequest"];
7989
+ };
7990
+ };
7991
+ responses: {
7992
+ /** @description Markdown/JSON content inline, or a queued PDF job id */
7993
+ 200: {
7994
+ headers: {
7995
+ [name: string]: unknown;
7996
+ };
7997
+ content: {
7998
+ "application/json": components["schemas"]["ExportMeetingRecordingResponse"];
7999
+ };
8000
+ };
8001
+ /** @description Recording not found or not owned by this user */
8002
+ 404: {
8003
+ headers: {
8004
+ [name: string]: unknown;
8005
+ };
8006
+ content?: never;
8007
+ };
8008
+ };
8009
+ };
8010
+ downloadMeetingRecordingExport: {
8011
+ parameters: {
8012
+ query?: never;
8013
+ header?: never;
8014
+ path: {
8015
+ id: string;
8016
+ jobId: string;
8017
+ };
8018
+ cookie?: never;
8019
+ };
8020
+ requestBody?: never;
8021
+ responses: {
8022
+ /** @description The rendered PDF */
8023
+ 200: {
8024
+ headers: {
8025
+ [name: string]: unknown;
8026
+ };
8027
+ content?: never;
8028
+ };
8029
+ /** @description PDF not yet ready (pending) or failed */
8030
+ 202: {
8031
+ headers: {
8032
+ [name: string]: unknown;
8033
+ };
8034
+ content: {
8035
+ "application/json": components["schemas"]["MeetingRecordingExportJobStatus"];
8036
+ };
8037
+ };
8038
+ /** @description Recording or export job not found / not owned by this user */
8039
+ 404: {
8040
+ headers: {
8041
+ [name: string]: unknown;
8042
+ };
8043
+ content?: never;
8044
+ };
8045
+ };
8046
+ };
8047
+ softDeleteMeetingRecording: {
8048
+ parameters: {
8049
+ query?: never;
8050
+ header?: never;
8051
+ path: {
8052
+ id: string;
8053
+ };
8054
+ cookie?: never;
8055
+ };
8056
+ requestBody?: never;
8057
+ responses: {
8058
+ /** @description Recording soft-deleted */
8059
+ 200: {
8060
+ headers: {
8061
+ [name: string]: unknown;
8062
+ };
8063
+ content: {
8064
+ "application/json": components["schemas"]["SoftDeleteMeetingRecordingResponse"];
8065
+ };
8066
+ };
8067
+ /** @description Recording not found or not owned by this user */
8068
+ 404: {
8069
+ headers: {
8070
+ [name: string]: unknown;
8071
+ };
8072
+ content?: never;
8073
+ };
8074
+ };
8075
+ };
8076
+ restoreMeetingRecording: {
8077
+ parameters: {
8078
+ query?: never;
8079
+ header?: never;
8080
+ path: {
8081
+ id: string;
8082
+ };
8083
+ cookie?: never;
8084
+ };
8085
+ requestBody?: never;
8086
+ responses: {
8087
+ /** @description Recording restored (or a no-op outside the window) */
8088
+ 200: {
8089
+ headers: {
8090
+ [name: string]: unknown;
8091
+ };
8092
+ content: {
8093
+ "application/json": components["schemas"]["RestoreMeetingRecordingResponse"];
8094
+ };
8095
+ };
8096
+ /** @description Recording not found or not owned by this user */
8097
+ 404: {
8098
+ headers: {
8099
+ [name: string]: unknown;
8100
+ };
8101
+ content?: never;
8102
+ };
8103
+ };
8104
+ };
8105
+ changeMeetingRecordingVisibility: {
8106
+ parameters: {
8107
+ query?: never;
8108
+ header?: never;
8109
+ path: {
8110
+ id: string;
8111
+ };
8112
+ cookie?: never;
8113
+ };
8114
+ requestBody: {
8115
+ content: {
8116
+ "application/json": components["schemas"]["ChangeMeetingRecordingVisibilityRequest"];
8117
+ };
8118
+ };
8119
+ responses: {
8120
+ /** @description Visibility changed */
8121
+ 200: {
8122
+ headers: {
8123
+ [name: string]: unknown;
8124
+ };
8125
+ content: {
8126
+ "application/json": components["schemas"]["ChangeMeetingRecordingVisibilityResponse"];
8127
+ };
8128
+ };
8129
+ /** @description Recording not found or not owned by this user */
8130
+ 404: {
8131
+ headers: {
8132
+ [name: string]: unknown;
8133
+ };
8134
+ content?: never;
8135
+ };
8136
+ /** @description Cannot change visibility while recording (pre-finalize) */
8137
+ 409: {
8138
+ headers: {
8139
+ [name: string]: unknown;
8140
+ };
8141
+ content?: never;
8142
+ };
8143
+ };
8144
+ };
7582
8145
  startImpersonation: {
7583
8146
  parameters: {
7584
8147
  query?: never;
package/src/index.ts CHANGED
@@ -747,3 +747,8 @@ export type {
747
747
  // Meeting recorder vocabulary (PRD-00651)
748
748
  // @see ./meetings/schemas.ts for invariants
749
749
  export * from './meetings'
750
+
751
+ // Permission model vocabulary (PRD-00669 AUTH-001)
752
+ // AccessLevel / OrgChartRole / AccessSource — see ADR-CTRL-084..088.
753
+ // No consumers in this PRD; cutover starts in AUTH-002 (PRD-00670).
754
+ export * from './permissions'
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Permission Access Levels
3
+ *
4
+ * Canonical four-level access vocabulary for object permissions across
5
+ * Company Semantics, modeled on the Google-Docs four-level scheme.
6
+ *
7
+ * Authority: ADR-CTRL-085 (Rights Table). See ADR-CTRL-084 for how these
8
+ * levels are materialized into `effective_acl_grants`, and ADR-CTRL-086 for
9
+ * the aggregation rule (most-permissive across sources).
10
+ *
11
+ * The commenter level is currently a stub — see ADR-CTRL-087.
12
+ */
13
+ import { z } from 'zod';
14
+
15
+ export const ACCESS_LEVELS = ['owner', 'editor', 'commenter', 'viewer'] as const;
16
+ export type AccessLevel = (typeof ACCESS_LEVELS)[number];
17
+
18
+ export const AccessLevelSchema = z.enum(ACCESS_LEVELS);
19
+
20
+ /**
21
+ * Ordered weakest → strongest. Index = ranking.
22
+ * Used by `highestGrant()` in AUTH-006 (PRD-00674) to aggregate across sources.
23
+ */
24
+ export const ACCESS_LEVEL_ORDER: Record<AccessLevel, number> = {
25
+ viewer: 0,
26
+ commenter: 1,
27
+ editor: 2,
28
+ owner: 3,
29
+ };
30
+
31
+ /**
32
+ * Returns true when `actual` is at least as strong as `required`.
33
+ * Examples:
34
+ * isAtLeast('editor', 'viewer') === true
35
+ * isAtLeast('viewer', 'editor') === false
36
+ * isAtLeast('owner', 'owner') === true
37
+ */
38
+ export function isAtLeast(actual: AccessLevel, required: AccessLevel): boolean {
39
+ return ACCESS_LEVEL_ORDER[actual] >= ACCESS_LEVEL_ORDER[required];
40
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Access Source
3
+ *
4
+ * Provenance tag on rows in `effective_acl_grants`. Each row is materialized
5
+ * from exactly one input source; multiple rows for the same
6
+ * (entity, principal) pair are allowed, one per source.
7
+ *
8
+ * Authority: ADR-CTRL-084 (Permission Resolution Architecture).
9
+ *
10
+ * Sources:
11
+ * - `explicit` — direct `acl_grants` row
12
+ * - `ownership` — entity.owner_user_id column projection
13
+ * - `visibility` — entity.visibility tier compiled to viewer rows
14
+ * - `inheritance` — org-chart-membership-based unit walk
15
+ * - `migration` — one-shot backfill from legacy systems (AUTH-004)
16
+ */
17
+ import { z } from 'zod';
18
+
19
+ export const ACCESS_SOURCES = [
20
+ 'explicit',
21
+ 'ownership',
22
+ 'visibility',
23
+ 'inheritance',
24
+ 'migration',
25
+ ] as const;
26
+ export type AccessSource = (typeof ACCESS_SOURCES)[number];
27
+
28
+ export const AccessSourceSchema = z.enum(ACCESS_SOURCES);
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Permissions Vocabulary Barrel
3
+ *
4
+ * Re-exports the three canonical enums introduced in AUTH-001 (PRD-00669).
5
+ * Import from '@company-semantics/contracts' (root).
6
+ */
7
+ export * from './access-levels';
8
+ export * from './orgchart-roles';
9
+ export * from './access-source';
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Org-Chart Roles
3
+ *
4
+ * Canonical four-role vocabulary for subtree-CRUD authority on org_units.
5
+ *
6
+ * Authority: ADR-CTRL-088 (Org-Chart Roles).
7
+ *
8
+ * These roles govern only member CRUD on a unit and its ltree descendants.
9
+ * They never grant object access — object access flows through ownership +
10
+ * ACL + visibility + inheritance per ADR-CTRL-084.
11
+ *
12
+ * Consumers: AUTH-006 policy registry (PRD-00674),
13
+ * AUTH-009 org-chart member CRUD UI (PRD-00677),
14
+ * AUTH-011C strict-guard flip (PRD-00681).
15
+ *
16
+ * The legacy `WorkspaceRole` and `OrgUnitMembershipRole` enums coexist with
17
+ * this enum until AUTH-011C deletes them.
18
+ */
19
+ import { z } from 'zod';
20
+
21
+ export const ORG_CHART_ROLES = ['ceo', 'leader', 'delegate', 'admin'] as const;
22
+ export type OrgChartRole = (typeof ORG_CHART_ROLES)[number];
23
+
24
+ export const OrgChartRoleSchema = z.enum(ORG_CHART_ROLES);