@company-semantics/contracts 2.18.0 → 4.0.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.18.0",
3
+ "version": "4.0.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 = '3d5da96bdeb1' as const;
3
- export const SPEC_HASH_FULL = '3d5da96bdeb12a1223f19d67956bfa0a481abc37813c181c0897a10c7e8f9b80' as const;
2
+ export const SPEC_HASH = '30c4d8eb9dce' as const;
3
+ export const SPEC_HASH_FULL = '30c4d8eb9dcefed99d44a531c27a9e5a25eb4842c578e8933f64678a13816d07' as const;
@@ -3590,10 +3590,6 @@ export interface components {
3590
3590
  id: string;
3591
3591
  name: string;
3592
3592
  } | null;
3593
- coOwners: {
3594
- id: string;
3595
- name: string;
3596
- }[];
3597
3593
  canEdit: boolean;
3598
3594
  inheritsFrom: string | null;
3599
3595
  sources: {
@@ -66,7 +66,6 @@ export const CompanyMdDocResponseSchema = z.object({
66
66
  parentId: z.string().nullable(),
67
67
  owningUnitId: z.string().nullable(),
68
68
  owner: CompanyMdPersonSchema.nullable(),
69
- coOwners: z.array(CompanyMdPersonSchema),
70
69
  canEdit: z.boolean(),
71
70
  inheritsFrom: z.string().nullable(),
72
71
  sources: z.array(CompanyMdSourceSchema),
@@ -50,6 +50,7 @@ export const openApiRoutes = {
50
50
  '/api/internal-admin/impersonate/session': ['GET'],
51
51
  '/api/internal-admin/impersonate/start': ['POST'],
52
52
  '/api/me': ['GET'],
53
+ '/api/me/access-list': ['GET'],
53
54
  '/api/me/meetings/recordings/start': ['POST'],
54
55
  '/api/me/meetings/recordings/{id}': ['DELETE'],
55
56
  '/api/me/meetings/recordings/{id}/complete': ['POST'],
@@ -75,6 +76,7 @@ export const openApiRoutes = {
75
76
  '/api/org-units/{unitId}/memberships': ['GET', 'POST'],
76
77
  '/api/org-units/{unitId}/memberships/{userId}': ['DELETE'],
77
78
  '/api/org-units/{unitId}/memberships/{userId}/role': ['PUT'],
79
+ '/api/org-units/{unitId}/my-authority': ['GET'],
78
80
  '/api/org-units/{unitId}/owners': ['GET'],
79
81
  '/api/org-units/{unitId}/permissions': ['GET'],
80
82
  '/api/org-units/{unitId}/relationships': ['GET', 'POST'],
@@ -143,8 +145,10 @@ export const openApiRoutes = {
143
145
  '/api/{entityType}/{id}/acl': ['GET'],
144
146
  '/api/{entityType}/{id}/acl/{principalType}/{principalId}': ['DELETE', 'PUT'],
145
147
  '/api/{entityType}/{id}/effective-access': ['POST'],
148
+ '/api/{entityType}/{id}/recent-decisions': ['GET'],
146
149
  '/api/{entityType}/{id}/transfer-ownership': ['POST'],
147
150
  '/api/{entityType}/{id}/visibility': ['PATCH'],
151
+ '/api/{entityType}/{id}/who-can-access': ['GET'],
148
152
  '/auth/logout': ['POST'],
149
153
  '/auth/me': ['GET'],
150
154
  '/auth/sso/callback': ['GET', 'POST'],
package/src/index.ts CHANGED
@@ -263,7 +263,6 @@ export type {
263
263
  OwnershipTransferStatus,
264
264
  // Workspace visibility DTOs (Phase 2)
265
265
  // @see ADR-CONT-030 for design rationale
266
- WorkspaceRole,
267
266
  WorkspaceOverview,
268
267
  WorkspaceMember,
269
268
  AuthMethodConfig,
@@ -342,7 +341,7 @@ export type {
342
341
  PermissionAuditEntry,
343
342
  } from './org/index'
344
343
 
345
- export { ROLE_DISPLAY_MAP, VIEW_SCOPE_MAP, getViewScope, TRANSFER_RESPONSIBILITIES, IDENTITY_TRUST_LEVEL_LABELS } from './org/index'
344
+ export { VIEW_SCOPE_MAP, getViewScope, TRANSFER_RESPONSIBILITIES, IDENTITY_TRUST_LEVEL_LABELS } from './org/index'
346
345
 
347
346
  // View authorization types (Phase 5 - ADR-APP-013)
348
347
  export type { AuthorizableView } from './org/index'
@@ -123,10 +123,6 @@ export interface CompanyMdDocCore extends CompanyMdNodeIdentity {
123
123
 
124
124
  export interface CompanyMdDocCollaborators {
125
125
  readonly owner: { readonly id: string; readonly name: string } | null;
126
- readonly coOwners: ReadonlyArray<{
127
- readonly id: string;
128
- readonly name: string;
129
- }>;
130
126
  readonly canEdit: boolean;
131
127
  readonly members: ReadonlyArray<{
132
128
  readonly id: string;
package/src/org/index.ts CHANGED
@@ -12,7 +12,6 @@ export type {
12
12
  OwnershipTransferRequest,
13
13
  OwnershipTransferStatus,
14
14
  // Workspace visibility DTOs (Phase 2)
15
- WorkspaceRole,
16
15
  WorkspaceOverview,
17
16
  WorkspaceMember,
18
17
  WorkspaceMemberUnitSummary,
@@ -71,7 +70,7 @@ export type {
71
70
  TransferMemberEligibility,
72
71
  } from './types';
73
72
 
74
- export { ROLE_DISPLAY_MAP, TRANSFER_RESPONSIBILITIES, IDENTITY_TRUST_LEVEL_LABELS } from './types';
73
+ export { TRANSFER_RESPONSIBILITIES, IDENTITY_TRUST_LEVEL_LABELS } from './types';
75
74
 
76
75
  // Domain types (Phase 4)
77
76
  export type {
@@ -209,7 +208,6 @@ export type {
209
208
  OrgUnitVisibility,
210
209
  OrgUnitRelationshipType,
211
210
  OrgUnitRelationshipRole,
212
- OrgUnitMembershipRole,
213
211
  OrgUnitMembershipStatus,
214
212
  OrgUnitMembershipSource,
215
213
  OrgUnitErrorCode,
@@ -222,7 +220,7 @@ export {
222
220
  OrgUnitVisibilitySchema,
223
221
  OrgUnitRelationshipTypeSchema,
224
222
  OrgUnitRelationshipRoleSchema,
225
- OrgUnitMembershipRoleSchema,
223
+ UnitMembershipRoleSchema,
226
224
  OrgUnitMembershipStatusSchema,
227
225
  OrgUnitMembershipSourceSchema,
228
226
  OrgUnitErrorCodeSchema,
@@ -248,6 +246,7 @@ export {
248
246
  UpdateOrgUnitResponseSchema,
249
247
  } from './schemas';
250
248
  export type {
249
+ UnitMembershipRole,
251
250
  OrgUnit,
252
251
  OrgUnitTreeNode,
253
252
  OrgUnitMembership,
@@ -36,9 +36,6 @@ export type OrgUnitRelationshipType = 'collaborates_with' | 'reports_to' | 'depe
36
36
  /** Edge role — refines the collaboration nature on a graph edge. */
37
37
  export type OrgUnitRelationshipRole = 'owner' | 'participant' | 'supporting';
38
38
 
39
- /** Per-unit user role. Privilege order: owner > manager > member. */
40
- export type OrgUnitMembershipRole = 'member' | 'manager' | 'owner';
41
-
42
39
  /** Active/pending/removed lifecycle for a unit membership. */
43
40
  export type OrgUnitMembershipStatus = 'active' | 'pending' | 'removed';
44
41
 
@@ -12,6 +12,7 @@
12
12
  */
13
13
  import { z } from 'zod';
14
14
  import { CursorPageSchema } from '../api/primitives';
15
+ import { OrgChartRoleSchema } from '../permissions/orgchart-roles';
15
16
 
16
17
  // ---------------------------------------------------------------------------
17
18
  // Sub-schemas
@@ -29,7 +30,7 @@ const WorkspaceMemberSchema = z.object({
29
30
  name: z.string(),
30
31
  email: z.string(),
31
32
  jobTitle: z.string().nullable(),
32
- role: z.enum(['owner', 'admin', 'member', 'auditor']),
33
+ role: OrgChartRoleSchema.nullable(),
33
34
  roleNames: z.array(z.string()),
34
35
  joinedAt: z.string(),
35
36
  lastActiveAt: z.string().nullable(),
@@ -357,7 +358,7 @@ const UserOrgMembershipSchema = z.object({
357
358
  orgId: z.string(),
358
359
  orgName: z.string(),
359
360
  orgSlug: z.string(),
360
- role: z.enum(['owner', 'admin', 'member', 'auditor']),
361
+ role: OrgChartRoleSchema.nullable(),
361
362
  joinedAt: z.string(),
362
363
  isActive: z.boolean(),
363
364
  orgType: z.enum(['personal', 'shared']),
@@ -419,7 +420,7 @@ const OrgInviteSchema = z.object({
419
420
  id: z.string(),
420
421
  orgId: z.string(),
421
422
  email: z.string(),
422
- role: z.enum(['owner', 'admin', 'member', 'auditor']),
423
+ role: z.enum(['admin', 'member']),
423
424
  invitedBy: z.object({ id: z.string(), name: z.string() }),
424
425
  status: z.enum(['pending', 'accepted', 'expired', 'revoked']),
425
426
  createdAt: z.string(),
@@ -676,7 +677,12 @@ export const OrgUnitRelationshipTypeSchema = z.enum([
676
677
 
677
678
  export const OrgUnitRelationshipRoleSchema = z.enum(['owner', 'participant', 'supporting']);
678
679
 
679
- export const OrgUnitMembershipRoleSchema = z.enum([
680
+ /**
681
+ * Positional slot a member holds in the org-unit tree. ORTHOGONAL to the
682
+ * `OrgChartRole` policy vocabulary (this is an INPUT to authority resolution,
683
+ * not the derived policy role). Level is encoded in the value (l1…l5).
684
+ */
685
+ export const UnitMembershipRoleSchema = z.enum([
680
686
  'member',
681
687
  'l1_unit_owner',
682
688
  'l2_unit_owner',
@@ -685,6 +691,8 @@ export const OrgUnitMembershipRoleSchema = z.enum([
685
691
  'l5_unit_owner',
686
692
  ]);
687
693
 
694
+ export type UnitMembershipRole = z.infer<typeof UnitMembershipRoleSchema>;
695
+
688
696
  export const OrgUnitMembershipStatusSchema = z.enum(['active', 'pending', 'removed']);
689
697
 
690
698
  export const OrgUnitMembershipSourceSchema = z.enum([
@@ -750,7 +758,7 @@ export const OrgUnitMembershipSchema = z.object({
750
758
  orgId: z.string().uuid(),
751
759
  unitId: z.string().uuid(),
752
760
  userId: z.string().uuid(),
753
- membershipRole: OrgUnitMembershipRoleSchema,
761
+ membershipRole: UnitMembershipRoleSchema,
754
762
  status: OrgUnitMembershipStatusSchema,
755
763
  source: OrgUnitMembershipSourceSchema,
756
764
  sourceRef: z.string().nullable(),
@@ -1012,7 +1020,7 @@ export const OrgUnitMembershipListResponseSchema = z.object({
1012
1020
  */
1013
1021
  export const OrgUnitPermissionsEntrySchema = z.object({
1014
1022
  userId: z.string().uuid(),
1015
- membershipRole: OrgUnitMembershipRoleSchema,
1023
+ membershipRole: UnitMembershipRoleSchema,
1016
1024
  inheritedFromUnitId: z.string().uuid(),
1017
1025
  inheritedFromUnitName: z.string().min(1),
1018
1026
  });
package/src/org/types.ts CHANGED
@@ -5,6 +5,8 @@
5
5
  * @see ADR-BE-XXX (Personal vs Shared Organization Model)
6
6
  */
7
7
 
8
+ import type { OrgChartRole } from '../permissions/orgchart-roles';
9
+
8
10
  /**
9
11
  * Organization type distinguishes personal workspaces from shared organizations.
10
12
  * - 'personal': Single-user workspace, owned by creator, claimable
@@ -53,22 +55,6 @@ export interface OwnershipTransferStatus {
53
55
  // @see ADR-CONT-030 for design rationale
54
56
  // =============================================================================
55
57
 
56
- /**
57
- * Display role for workspace members.
58
- * Presentation-layer simplification of the internal RBAC roles.
59
- */
60
- export type WorkspaceRole = 'owner' | 'admin' | 'member' | 'auditor';
61
-
62
- /**
63
- * RBAC → UI role mapping (presentation only).
64
- * Maps internal system roles to user-facing display roles.
65
- */
66
- export const ROLE_DISPLAY_MAP = {
67
- org_owner: 'owner',
68
- org_admin: 'admin',
69
- org_auditor: 'auditor',
70
- // All other roles → 'member'
71
- } as const satisfies Partial<Record<string, WorkspaceRole>>;
72
58
 
73
59
  /**
74
60
  * Workspace overview for the control plane UI.
@@ -120,9 +106,12 @@ export interface WorkspaceMember {
120
106
  email: string;
121
107
  /** Free-text job title (`users.job_title`). Null when unset. */
122
108
  jobTitle: string | null;
123
- /** Display role — derived collapse of RBAC into {owner,admin,member,auditor}. */
124
- role: WorkspaceRole;
125
- /** Raw RBAC role names (e.g. 'org_owner', 'org_admin', 'auditor'). Superset of `role`. */
109
+ /**
110
+ * Display role — the member's highest org-chart standing, or `null` for a
111
+ * plain member with no org-chart authority. Render via `orgChartRoleLabel`.
112
+ */
113
+ role: OrgChartRole | null;
114
+ /** Raw RBAC role names (e.g. 'ceo', 'admin', 'delegate'). Superset of `role`. */
126
115
  roleNames: string[];
127
116
  joinedAt: string;
128
117
  /** ISO timestamp of last activity; null if never recorded. */
@@ -424,7 +413,8 @@ export interface OrgInvite {
424
413
  id: string;
425
414
  orgId: string;
426
415
  email: string;
427
- role: WorkspaceRole;
416
+ /** Invite role — invites only grant the restricted {admin, member} domain. */
417
+ role: 'admin' | 'member';
428
418
  invitedBy: {
429
419
  id: string;
430
420
  name: string;
@@ -555,8 +545,11 @@ export interface UserOrgMembership {
555
545
  orgId: string;
556
546
  orgName: string;
557
547
  orgSlug: string;
558
- /** Display role derived from RBAC - presentation only, not for auth decisions. */
559
- role: WorkspaceRole;
548
+ /**
549
+ * Display role — highest org-chart standing, or `null` for a plain member.
550
+ * Presentation only, not for auth decisions. Render via `orgChartRoleLabel`.
551
+ */
552
+ role: OrgChartRole | null;
560
553
  /** ISO8601 timestamp when user joined the organization. */
561
554
  joinedAt: string;
562
555
  /** Whether this membership is currently active. */
@@ -11,10 +11,14 @@
11
11
  *
12
12
  * Consumers: AUTH-006 policy registry (PRD-00674),
13
13
  * AUTH-009 org-chart member CRUD UI (PRD-00677),
14
- * AUTH-011C strict-guard flip (PRD-00681).
14
+ * AUTH-011C convergence (PRD-00681) — the single role vocabulary after the
15
+ * legacy workspace display-role and per-unit membership-role enums were removed.
15
16
  *
16
- * The legacy `WorkspaceRole` and `OrgUnitMembershipRole` enums coexist with
17
- * this enum until AUTH-011C deletes them.
17
+ * The org-level display badge collapses onto this vocabulary: an actor's
18
+ * highest org-chart standing, or `null` for a plain member with no authority.
19
+ * The positional slot (`UnitMembershipRole`, `member | l1_unit_owner | …`)
20
+ * remains a separate, orthogonal axis — it is an INPUT to authority
21
+ * resolution, not the derived policy role.
18
22
  */
19
23
  import { z } from 'zod';
20
24
 
@@ -22,3 +26,19 @@ export const ORG_CHART_ROLES = ['ceo', 'leader', 'delegate', 'admin'] as const;
22
26
  export type OrgChartRole = (typeof ORG_CHART_ROLES)[number];
23
27
 
24
28
  export const OrgChartRoleSchema = z.enum(ORG_CHART_ROLES);
29
+
30
+ /**
31
+ * Human-readable labels for the org-chart role display badge. `null` (no
32
+ * org-chart standing) renders as "Member" via {@link orgChartRoleLabel}.
33
+ */
34
+ export const ORG_CHART_ROLE_LABELS: Record<OrgChartRole, string> = {
35
+ ceo: 'CEO',
36
+ leader: 'Leader',
37
+ delegate: 'Delegate',
38
+ admin: 'Admin',
39
+ };
40
+
41
+ /** Display label for a (possibly null) org-chart role; `null` = plain member. */
42
+ export function orgChartRoleLabel(role: OrgChartRole | null): string {
43
+ return role === null ? 'Member' : ORG_CHART_ROLE_LABELS[role];
44
+ }