@company-semantics/contracts 1.13.0 → 1.15.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": "1.13.0",
3
+ "version": "1.15.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 = '3c2104cecec4' as const;
3
- export const SPEC_HASH_FULL = '3c2104cecec403986da31a11310ce09d3dd773fd095b7416c0cf6f4e30d64f6c' as const;
2
+ export const SPEC_HASH = 'b15100bf7771' as const;
3
+ export const SPEC_HASH_FULL = 'b15100bf7771682644b63942432a672ffee7d4fdb1237201f491b4d8d3c6b238' as const;
@@ -636,7 +636,8 @@ export interface paths {
636
636
  path?: never;
637
637
  cookie?: never;
638
638
  };
639
- get?: never;
639
+ /** Get workspace member detail (roles, units, effective scopes, recent actions) */
640
+ get: operations["getWorkspaceMemberDetail"];
640
641
  put?: never;
641
642
  post?: never;
642
643
  /** Remove workspace member */
@@ -646,6 +647,23 @@ export interface paths {
646
647
  patch?: never;
647
648
  trace?: never;
648
649
  };
650
+ "/api/rbac/roles": {
651
+ parameters: {
652
+ query?: never;
653
+ header?: never;
654
+ path?: never;
655
+ cookie?: never;
656
+ };
657
+ /** List RBAC roles catalog (system + custom) with scopes and member counts */
658
+ get: operations["getRbacRoles"];
659
+ put?: never;
660
+ post?: never;
661
+ delete?: never;
662
+ options?: never;
663
+ head?: never;
664
+ patch?: never;
665
+ trace?: never;
666
+ };
649
667
  "/api/workspace/members/{id}/role": {
650
668
  parameters: {
651
669
  query?: never;
@@ -1430,7 +1448,8 @@ export interface paths {
1430
1448
  delete?: never;
1431
1449
  options?: never;
1432
1450
  head?: never;
1433
- patch?: never;
1451
+ /** Update an org unit (name and/or description) */
1452
+ patch: operations["updateOrgUnit"];
1434
1453
  trace?: never;
1435
1454
  };
1436
1455
  "/api/org-units/{unitId}/children": {
@@ -2336,15 +2355,49 @@ export interface components {
2336
2355
  WorkspaceHandleRequest: {
2337
2356
  handle: string;
2338
2357
  };
2358
+ WorkspaceMemberUnitSummary: {
2359
+ unitId: string;
2360
+ unitName: string;
2361
+ unitPath: string;
2362
+ /** @enum {string} */
2363
+ role: "owner" | "manager" | "member";
2364
+ };
2365
+ WorkspaceMember: {
2366
+ id: string;
2367
+ name: string;
2368
+ email: string;
2369
+ /** @enum {string} */
2370
+ role: "owner" | "admin" | "member" | "auditor";
2371
+ roleNames: string[];
2372
+ joinedAt: string;
2373
+ lastActiveAt: string | null;
2374
+ unitMemberships: components["schemas"]["WorkspaceMemberUnitSummary"][];
2375
+ unitMembershipsTruncated: boolean;
2376
+ inviteStatus: ("active" | "pending" | "expired") | null;
2377
+ };
2378
+ MemberRecentAction: {
2379
+ id: string;
2380
+ timestamp: string;
2381
+ action: string;
2382
+ summary: string;
2383
+ };
2384
+ WorkspaceMemberDetail: components["schemas"]["WorkspaceMember"] & {
2385
+ effectiveScopes: string[];
2386
+ recentActions: components["schemas"]["MemberRecentAction"][];
2387
+ };
2388
+ RoleCatalogEntry: {
2389
+ name: string;
2390
+ /** @enum {string} */
2391
+ type: "system" | "custom";
2392
+ description: string;
2393
+ scopes: string[];
2394
+ memberCount: number;
2395
+ };
2396
+ RoleCatalogResponse: {
2397
+ roles: components["schemas"]["RoleCatalogEntry"][];
2398
+ };
2339
2399
  WorkspaceMembersResponse: {
2340
- items: {
2341
- id: string;
2342
- name: string;
2343
- email: string;
2344
- /** @enum {string} */
2345
- role: "owner" | "admin" | "member" | "auditor";
2346
- joinedAt: string;
2347
- }[];
2400
+ items: components["schemas"]["WorkspaceMember"][];
2348
2401
  nextCursor: string | null;
2349
2402
  hasMore: boolean;
2350
2403
  };
@@ -2936,6 +2989,31 @@ export interface components {
2936
2989
  updatedAt: string;
2937
2990
  };
2938
2991
  };
2992
+ UpdateOrgUnitResponse: {
2993
+ unit: {
2994
+ /** Format: uuid */
2995
+ id: string;
2996
+ /** Format: uuid */
2997
+ orgId: string;
2998
+ parentId: string | null;
2999
+ slug: string;
3000
+ name: string;
3001
+ description: string | null;
3002
+ typeTag: string;
3003
+ classification: ("execution_unit" | "org_container" | "custom") | null;
3004
+ orderKey: string;
3005
+ path: string;
3006
+ /** @enum {string} */
3007
+ syncMode: "manual_only" | "synced_readonly" | "synced_with_overrides";
3008
+ visibilityDefault: ("public" | "private" | "restricted") | null;
3009
+ metadata: {
3010
+ [key: string]: unknown;
3011
+ };
3012
+ archivedAt: string | null;
3013
+ createdAt: string;
3014
+ updatedAt: string;
3015
+ };
3016
+ };
2939
3017
  OrgUnitChildrenResponse: {
2940
3018
  /** Format: uuid */
2941
3019
  parentId: string;
@@ -4345,6 +4423,28 @@ export interface operations {
4345
4423
  };
4346
4424
  };
4347
4425
  };
4426
+ getWorkspaceMemberDetail: {
4427
+ parameters: {
4428
+ query?: never;
4429
+ header?: never;
4430
+ path: {
4431
+ id: string;
4432
+ };
4433
+ cookie?: never;
4434
+ };
4435
+ requestBody?: never;
4436
+ responses: {
4437
+ /** @description Workspace member detail */
4438
+ 200: {
4439
+ headers: {
4440
+ [name: string]: unknown;
4441
+ };
4442
+ content: {
4443
+ "application/json": components["schemas"]["WorkspaceMemberDetail"];
4444
+ };
4445
+ };
4446
+ };
4447
+ };
4348
4448
  removeMember: {
4349
4449
  parameters: {
4350
4450
  query?: never;
@@ -4367,6 +4467,26 @@ export interface operations {
4367
4467
  };
4368
4468
  };
4369
4469
  };
4470
+ getRbacRoles: {
4471
+ parameters: {
4472
+ query?: never;
4473
+ header?: never;
4474
+ path?: never;
4475
+ cookie?: never;
4476
+ };
4477
+ requestBody?: never;
4478
+ responses: {
4479
+ /** @description Role catalog */
4480
+ 200: {
4481
+ headers: {
4482
+ [name: string]: unknown;
4483
+ };
4484
+ content: {
4485
+ "application/json": components["schemas"]["RoleCatalogResponse"];
4486
+ };
4487
+ };
4488
+ };
4489
+ };
4370
4490
  changeMemberRole: {
4371
4491
  parameters: {
4372
4492
  query?: never;
@@ -5522,6 +5642,35 @@ export interface operations {
5522
5642
  };
5523
5643
  };
5524
5644
  };
5645
+ updateOrgUnit: {
5646
+ parameters: {
5647
+ query?: never;
5648
+ header?: never;
5649
+ path: {
5650
+ unitId: string;
5651
+ };
5652
+ cookie?: never;
5653
+ };
5654
+ requestBody: {
5655
+ content: {
5656
+ "application/json": {
5657
+ name?: string;
5658
+ description?: string | null;
5659
+ };
5660
+ };
5661
+ };
5662
+ responses: {
5663
+ /** @description Updated org unit */
5664
+ 200: {
5665
+ headers: {
5666
+ [name: string]: unknown;
5667
+ };
5668
+ content: {
5669
+ "application/json": components["schemas"]["UpdateOrgUnitResponse"];
5670
+ };
5671
+ };
5672
+ };
5673
+ };
5525
5674
  listOrgUnitChildren: {
5526
5675
  parameters: {
5527
5676
  query?: never;
package/src/org/index.ts CHANGED
@@ -15,6 +15,11 @@ export type {
15
15
  WorkspaceRole,
16
16
  WorkspaceOverview,
17
17
  WorkspaceMember,
18
+ WorkspaceMemberUnitSummary,
19
+ WorkspaceMemberInviteStatus,
20
+ WorkspaceMemberDetail,
21
+ MemberRecentAction,
22
+ RoleCatalogEntry,
18
23
  AuthMethodConfig,
19
24
  WorkspaceAuthConfig,
20
25
  // SSO self-service setup types (PRD-00193)
@@ -120,6 +125,9 @@ export {
120
125
  WorkspaceAccessResponseSchema,
121
126
  WorkspaceOverviewSchema,
122
127
  WorkspaceMembersResponseSchema,
128
+ WorkspaceMemberDetailSchema,
129
+ RoleCatalogEntrySchema,
130
+ RoleCatalogResponseSchema,
123
131
  WorkspaceAuthConfigSchema,
124
132
  WorkspaceAuditEventSchema,
125
133
  WorkspaceAuditResponseSchema,
@@ -17,12 +17,48 @@ import { CursorPageSchema } from '../api/primitives';
17
17
  // Sub-schemas
18
18
  // ---------------------------------------------------------------------------
19
19
 
20
+ const WorkspaceMemberUnitSummarySchema = z.object({
21
+ unitId: z.string(),
22
+ unitName: z.string(),
23
+ unitPath: z.string(),
24
+ role: z.enum(['owner', 'manager', 'member']),
25
+ });
26
+
20
27
  const WorkspaceMemberSchema = z.object({
21
28
  id: z.string(),
22
29
  name: z.string(),
23
30
  email: z.string(),
24
31
  role: z.enum(['owner', 'admin', 'member', 'auditor']),
32
+ roleNames: z.array(z.string()),
25
33
  joinedAt: z.string(),
34
+ lastActiveAt: z.string().nullable(),
35
+ unitMemberships: z.array(WorkspaceMemberUnitSummarySchema),
36
+ unitMembershipsTruncated: z.boolean(),
37
+ inviteStatus: z.enum(['active', 'pending', 'expired']).nullable(),
38
+ });
39
+
40
+ const MemberRecentActionSchema = z.object({
41
+ id: z.string(),
42
+ timestamp: z.string(),
43
+ action: z.string(),
44
+ summary: z.string(),
45
+ });
46
+
47
+ export const WorkspaceMemberDetailSchema = WorkspaceMemberSchema.extend({
48
+ effectiveScopes: z.array(z.string()),
49
+ recentActions: z.array(MemberRecentActionSchema),
50
+ });
51
+
52
+ export const RoleCatalogEntrySchema = z.object({
53
+ name: z.string(),
54
+ type: z.enum(['system', 'custom']),
55
+ description: z.string(),
56
+ scopes: z.array(z.string()),
57
+ memberCount: z.number().int().nonnegative(),
58
+ });
59
+
60
+ export const RoleCatalogResponseSchema = z.object({
61
+ roles: z.array(RoleCatalogEntrySchema),
26
62
  });
27
63
 
28
64
  const WorkspaceOwnerSchema = z.object({
package/src/org/types.ts CHANGED
@@ -92,6 +92,24 @@ export interface WorkspaceOverview {
92
92
  claimable: boolean;
93
93
  }
94
94
 
95
+ /**
96
+ * Single OrgUnit membership summary attached to a WorkspaceMember row.
97
+ * See ADR-BE-120 for the canonical OrgUnit tree model.
98
+ */
99
+ export interface WorkspaceMemberUnitSummary {
100
+ unitId: string;
101
+ unitName: string;
102
+ /** Human-readable path from the OrgUnit tree (e.g. "Sales / Enterprise"). */
103
+ unitPath: string;
104
+ role: 'owner' | 'manager' | 'member';
105
+ }
106
+
107
+ /**
108
+ * Invite status for a workspace member row. `null` for members that have no
109
+ * associated invite record (joined pre-invite system).
110
+ */
111
+ export type WorkspaceMemberInviteStatus = 'active' | 'pending' | 'expired';
112
+
95
113
  /**
96
114
  * Workspace member for the members list.
97
115
  * Human users only (no agent actors).
@@ -100,8 +118,56 @@ export interface WorkspaceMember {
100
118
  id: string;
101
119
  name: string;
102
120
  email: string;
121
+ /** Display role — derived collapse of RBAC into {owner,admin,member,auditor}. */
103
122
  role: WorkspaceRole;
123
+ /** Raw RBAC role names (e.g. 'org_owner', 'org_admin', 'auditor'). Superset of `role`. */
124
+ roleNames: string[];
104
125
  joinedAt: string;
126
+ /** ISO timestamp of last activity; null if never recorded. */
127
+ lastActiveAt: string | null;
128
+ /** OrgUnit memberships for this member, capped at a small number server-side. */
129
+ unitMemberships: WorkspaceMemberUnitSummary[];
130
+ /** True when server truncated `unitMemberships`; detail endpoint returns the full list. */
131
+ unitMembershipsTruncated: boolean;
132
+ /** Invite lifecycle status. `null` for members without an invite record. */
133
+ inviteStatus: WorkspaceMemberInviteStatus | null;
134
+ }
135
+
136
+ /**
137
+ * Recent audit action attached to a member-detail response.
138
+ * Lighter projection than WorkspaceAuditEvent — no actor block (implied by caller).
139
+ */
140
+ export interface MemberRecentAction {
141
+ id: string;
142
+ timestamp: string;
143
+ action: string;
144
+ summary: string;
145
+ }
146
+
147
+ /**
148
+ * Full member detail, returned by GET /api/workspace/members/:userId and also
149
+ * the shape projected from /api/me for self-view.
150
+ */
151
+ export interface WorkspaceMemberDetail extends WorkspaceMember {
152
+ /** Full resolved scope patterns — union of grants from all assigned roles. */
153
+ effectiveScopes: string[];
154
+ /** Up to N most recent audit actions attributed to this member. */
155
+ recentActions: MemberRecentAction[];
156
+ }
157
+
158
+ /**
159
+ * Entry in the RBAC roles catalog (GET /api/rbac/roles).
160
+ */
161
+ export interface RoleCatalogEntry {
162
+ /** Canonical role name, e.g. 'org_owner'. */
163
+ name: string;
164
+ type: 'system' | 'custom';
165
+ /** One-line description sourced from system-roles.ts (or org-provided for custom). */
166
+ description: string;
167
+ /** Scope patterns granted by this role. May contain wildcards (e.g. 'org.view_*'). */
168
+ scopes: string[];
169
+ /** Number of active assignments in the current org. */
170
+ memberCount: number;
105
171
  }
106
172
 
107
173
  /**