@company-semantics/contracts 7.1.0 → 7.1.1

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": "7.1.0",
3
+ "version": "7.1.1",
4
4
  "private": false,
5
5
  "repository": {
6
6
  "type": "git",
@@ -3132,6 +3132,12 @@ export interface components {
3132
3132
  /** @enum {string} */
3133
3133
  role: "owner" | "manager" | "member";
3134
3134
  }[];
3135
+ manages: {
3136
+ unitId: string;
3137
+ unitName: string;
3138
+ /** @enum {string} */
3139
+ designation: "whole_org" | "admin" | "leader" | "delegate" | "member";
3140
+ }[];
3135
3141
  unitMembershipsTruncated: boolean;
3136
3142
  inviteStatus: ("active" | "pending" | "expired") | null;
3137
3143
  }[];
@@ -3320,6 +3326,12 @@ export interface components {
3320
3326
  /** @enum {string} */
3321
3327
  role: "owner" | "manager" | "member";
3322
3328
  }[];
3329
+ manages: {
3330
+ unitId: string;
3331
+ unitName: string;
3332
+ /** @enum {string} */
3333
+ designation: "whole_org" | "admin" | "leader" | "delegate" | "member";
3334
+ }[];
3323
3335
  unitMembershipsTruncated: boolean;
3324
3336
  inviteStatus: ("active" | "pending" | "expired") | null;
3325
3337
  effectiveScopes: string[];
@@ -54,15 +54,45 @@ const WorkspaceMemberSchema = z.object({
54
54
  id: z.string(),
55
55
  name: z.string(),
56
56
  email: z.string(),
57
+ /**
58
+ * Resolved avatar photo URL for the member, or `null`/absent when none is
59
+ * stored. SOURCE-AGNOSTIC: today the backend resolves this from the Slack
60
+ * profile photo cached on the user record, but the field name deliberately
61
+ * does not encode the origin so future sources (in-app upload, etc.) slot in
62
+ * behind the backend avatar resolver without a contract change. UI MUST fall
63
+ * back to initials when this is absent. Optional because it is an additive
64
+ * display-only enrichment (see ADR-CONTRACTS-055).
65
+ */
66
+ avatarUrl: z.string().nullable().optional(),
67
+ /** Free-text job title (`users.job_title`). Null when unset. */
57
68
  jobTitle: z.string().nullable(),
69
+ /**
70
+ * Display role — the member's highest org-chart standing, or `null` for a
71
+ * plain member with no org-chart authority. Render via `orgChartRoleLabel`.
72
+ */
58
73
  role: OrgChartRoleSchema.nullable(),
74
+ /** Raw RBAC role names (e.g. 'ceo', 'admin', 'delegate'). Superset of `role`. */
59
75
  roleNames: z.array(z.string()),
60
76
  joinedAt: z.string(),
77
+ /** ISO timestamp of last activity; null if never recorded. */
61
78
  lastActiveAt: z.string().nullable(),
79
+ /**
80
+ * Home org-unit (`users.primary_unit_id`). Null for org-scoped users
81
+ * (no level-2 home assignment). Used by the unit-detail Members table to
82
+ * roll up "people in this org-unit" across the subtree.
83
+ */
62
84
  primaryUnitId: z.string().uuid().nullable(),
85
+ /** OrgUnit memberships for this member, capped at a small number server-side. */
63
86
  unitMemberships: z.array(WorkspaceMemberUnitSummarySchema),
87
+ /**
88
+ * Per-unit org-chart designations the member holds where they manage
89
+ * (ADR-CTRL-112). Display-only summary of management reach; never an
90
+ * authorization input. Empty array when the member manages nothing.
91
+ */
64
92
  manages: z.array(WorkspaceMemberManagesEntrySchema),
93
+ /** True when server truncated `unitMemberships`; detail endpoint returns the full list. */
65
94
  unitMembershipsTruncated: z.boolean(),
95
+ /** Invite lifecycle status. `null` for members without an invite record. */
66
96
  inviteStatus: z.enum(['active', 'pending', 'expired']).nullable(),
67
97
  });
68
98
 
@@ -78,6 +108,19 @@ export const WorkspaceMemberDetailSchema = WorkspaceMemberSchema.extend({
78
108
  recentActions: z.array(MemberRecentActionSchema),
79
109
  });
80
110
 
111
+ /**
112
+ * Workspace member for the members list. Human users only (no agent actors).
113
+ * Canonical type — inferred from {@link WorkspaceMemberSchema} so the runtime
114
+ * schema is the single source of truth (no parallel hand-written interface).
115
+ */
116
+ export type WorkspaceMember = z.infer<typeof WorkspaceMemberSchema>;
117
+
118
+ /**
119
+ * Full member detail (GET /api/workspace/members/:userId and /api/me self-view).
120
+ * Inferred from {@link WorkspaceMemberDetailSchema}.
121
+ */
122
+ export type WorkspaceMemberDetail = z.infer<typeof WorkspaceMemberDetailSchema>;
123
+
81
124
  export const RoleCatalogEntrySchema = z.object({
82
125
  name: z.string(),
83
126
  type: z.enum(['system', 'custom']),
package/src/org/types.ts CHANGED
@@ -97,48 +97,13 @@ export interface WorkspaceMemberUnitSummary {
97
97
  export type WorkspaceMemberInviteStatus = 'active' | 'pending' | 'expired';
98
98
 
99
99
  /**
100
- * Workspace member for the members list.
101
- * Human users only (no agent actors).
100
+ * Workspace member types. Inferred from their Zod schemas in `./schemas`
101
+ * (the single source of truth) and re-exported here so existing import paths
102
+ * (`from '@company-semantics/contracts/org'`) stay stable. The schema carries
103
+ * the field-level documentation; do not reintroduce a parallel interface (it
104
+ * was the cause of the `manages`/`avatarUrl` drift — see ADR-CTRL-112).
102
105
  */
103
- export interface WorkspaceMember {
104
- id: string;
105
- name: string;
106
- email: string;
107
- /**
108
- * Resolved avatar photo URL for the member, or `null`/absent when none is
109
- * stored. SOURCE-AGNOSTIC: today the backend resolves this from the Slack
110
- * profile photo cached on the user record, but the field name deliberately
111
- * does not encode the origin so future sources (in-app upload, etc.) slot in
112
- * behind the backend avatar resolver without a contract change. UI MUST fall
113
- * back to initials when this is absent. Optional because it is an additive
114
- * display-only enrichment (see ADR-CONTRACTS-055).
115
- */
116
- avatarUrl?: string | null;
117
- /** Free-text job title (`users.job_title`). Null when unset. */
118
- jobTitle: string | null;
119
- /**
120
- * Display role — the member's highest org-chart standing, or `null` for a
121
- * plain member with no org-chart authority. Render via `orgChartRoleLabel`.
122
- */
123
- role: OrgChartRole | null;
124
- /** Raw RBAC role names (e.g. 'ceo', 'admin', 'delegate'). Superset of `role`. */
125
- roleNames: string[];
126
- joinedAt: string;
127
- /** ISO timestamp of last activity; null if never recorded. */
128
- lastActiveAt: string | null;
129
- /**
130
- * Home org-unit (`users.primary_unit_id`). Null for org-scoped users
131
- * (no level-2 home assignment). Used by the unit-detail Members table to
132
- * roll up "people in this org-unit" across the subtree.
133
- */
134
- primaryUnitId: string | null;
135
- /** OrgUnit memberships for this member, capped at a small number server-side. */
136
- unitMemberships: WorkspaceMemberUnitSummary[];
137
- /** True when server truncated `unitMemberships`; detail endpoint returns the full list. */
138
- unitMembershipsTruncated: boolean;
139
- /** Invite lifecycle status. `null` for members without an invite record. */
140
- inviteStatus: WorkspaceMemberInviteStatus | null;
141
- }
106
+ export type { WorkspaceMember, WorkspaceMemberDetail } from './schemas';
142
107
 
143
108
  /**
144
109
  * Recent audit action attached to a member-detail response.
@@ -151,16 +116,6 @@ export interface MemberRecentAction {
151
116
  summary: string;
152
117
  }
153
118
 
154
- /**
155
- * Full member detail, returned by GET /api/workspace/members/:userId and also
156
- * the shape projected from /api/me for self-view.
157
- */
158
- export interface WorkspaceMemberDetail extends WorkspaceMember {
159
- /** Full resolved scope patterns — union of grants from all assigned roles. */
160
- effectiveScopes: string[];
161
- /** Up to N most recent audit actions attributed to this member. */
162
- recentActions: MemberRecentAction[];
163
- }
164
119
 
165
120
  /**
166
121
  * Entry in the RBAC roles catalog (GET /api/rbac/roles).