@company-semantics/contracts 0.50.0 → 0.52.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.50.0",
3
+ "version": "0.52.0",
4
4
  "private": false,
5
5
  "repository": {
6
6
  "type": "git",
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Company admin types — shared vocabulary for cross-org admin control plane.
3
+ *
4
+ * These types support the company admin MVP (read-only).
5
+ * @see PRD-00113 for design rationale.
6
+ */
7
+
8
+ /** Read-only capabilities for company admin MVP. */
9
+ export type CompanyCapability =
10
+ | 'company.view_orgs'
11
+ | 'company.view_audit'
12
+ | 'company.view_system';
13
+
14
+ /** Context attached to company-admin requests after auth middleware validation. */
15
+ export interface CompanyAdminContext {
16
+ readonly kind: 'company';
17
+ readonly adminEmail: string;
18
+ readonly capabilities: readonly CompanyCapability[];
19
+ }
20
+
21
+ /**
22
+ * Discriminated union for request contexts.
23
+ *
24
+ * Org-scoped requests carry OrgScopedContext (kind: 'org').
25
+ * Company admin requests carry CompanyAdminContext (kind: 'company').
26
+ */
27
+ export type RequestContext =
28
+ | (import('./org/types').OrgScopedContext & { readonly kind: 'org' })
29
+ | CompanyAdminContext;
@@ -6,7 +6,14 @@
6
6
  */
7
7
 
8
8
  // Types
9
- export type { ISODateString, NameSource, UserIdentity } from './types';
9
+ export type {
10
+ ISODateString,
11
+ NameSource,
12
+ UserIdentity,
13
+ UserLifecycleStatus,
14
+ DeletionBlocker,
15
+ AccountDeletionEligibility,
16
+ } from './types';
10
17
 
11
18
  // Functions - Display Name
12
19
  export {
@@ -94,3 +94,36 @@ export type UserIdentity = {
94
94
  */
95
95
  slackAvatarLastSyncedAt?: ISODateString;
96
96
  };
97
+
98
+ // =============================================================================
99
+ // User Lifecycle
100
+ // =============================================================================
101
+
102
+ /**
103
+ * User lifecycle status. Replaces the boolean `isActive` field.
104
+ *
105
+ * State transitions:
106
+ * active → pending_deletion (self-service deletion request)
107
+ * pending_deletion → active (cancel during grace period)
108
+ * pending_deletion → deleted (async purge after grace period)
109
+ * deleted → (terminal, no transitions)
110
+ * active → deleted (FORBIDDEN — must pass through pending_deletion)
111
+ */
112
+ export type UserLifecycleStatus = 'active' | 'pending_deletion' | 'deleted';
113
+
114
+ /**
115
+ * Conditions that block account deletion.
116
+ * Discriminated union — extend with new blocker types without breaking changes.
117
+ */
118
+ export type DeletionBlocker =
119
+ | { type: 'sole_workspace_owner'; workspaceId: string; workspaceName: string }
120
+ | { type: 'active_legal_hold'; holdId: string };
121
+
122
+ /**
123
+ * Result of an account deletion eligibility check.
124
+ * Invariant: eligible=true ↔ blockers.length === 0
125
+ */
126
+ export type AccountDeletionEligibility = {
127
+ eligible: boolean;
128
+ blockers: DeletionBlocker[];
129
+ };
package/src/index.ts CHANGED
@@ -106,7 +106,14 @@ export type { Compatibility, Deprecation } from './compatibility'
106
106
 
107
107
  // User identity types and functions
108
108
  // @see ADR-CONT-032 for design rationale
109
- export type { ISODateString, NameSource, UserIdentity } from './identity/index'
109
+ export type {
110
+ ISODateString,
111
+ NameSource,
112
+ UserIdentity,
113
+ UserLifecycleStatus,
114
+ DeletionBlocker,
115
+ AccountDeletionEligibility,
116
+ } from './identity/index'
110
117
  export { extractFirstWord, resolveDisplayName, deriveFullName } from './identity/index'
111
118
 
112
119
  // Avatar types and functions
@@ -175,6 +182,12 @@ export type {
175
182
  // Authorization context types (Phase 5)
176
183
  // @see ADR-CTRL-010 for design rationale
177
184
  OrgScopedContext,
185
+ // Workspace Info/Settings surface types (PRD-00133)
186
+ WorkspaceSurface,
187
+ WorkspaceInfoOverview,
188
+ WorkspaceSettingsOverview,
189
+ IntegrationRequestStatus,
190
+ IntegrationRequest,
178
191
  } from './org/index'
179
192
 
180
193
  export { ROLE_DISPLAY_MAP, WORKSPACE_CAPABILITIES, ROLE_CAPABILITY_MAP, VIEW_SCOPE_MAP, getViewScope } from './org/index'
@@ -337,6 +350,14 @@ export type {
337
350
  // Ralph constants (cross-repo support)
338
351
  export { REPO_PRECEDENCE } from './ralph/index'
339
352
 
353
+ // Company admin types (cross-org control plane)
354
+ // @see PRD-00113 for design rationale
355
+ export type {
356
+ CompanyCapability,
357
+ CompanyAdminContext,
358
+ RequestContext,
359
+ } from './company-admin'
360
+
340
361
  // Rate limit domain types
341
362
  // @see PRD-00013 for contracts integration
342
363
  export type { RateLimitConfig, RateLimitResult } from './rate-limit/index'
package/src/org/index.ts CHANGED
@@ -36,6 +36,12 @@ export type {
36
36
  UserOrgMembership,
37
37
  // Authorization context types (Phase 5 - ADR-CTRL-010)
38
38
  OrgScopedContext,
39
+ // Workspace Info/Settings surface types (PRD-00133)
40
+ WorkspaceSurface,
41
+ WorkspaceInfoOverview,
42
+ WorkspaceSettingsOverview,
43
+ IntegrationRequestStatus,
44
+ IntegrationRequest,
39
45
  } from './types';
40
46
 
41
47
  export { ROLE_DISPLAY_MAP } from './types';
package/src/org/types.ts CHANGED
@@ -328,6 +328,8 @@ export interface UserOrgMembership {
328
328
  joinedAt: string;
329
329
  /** Whether this membership is currently active. */
330
330
  isActive: boolean;
331
+ /** Organization type (personal vs shared). */
332
+ orgType: OrgType;
331
333
  }
332
334
 
333
335
  // ─────────────────────────────────────────────────────────────────────────────
@@ -375,3 +377,78 @@ export interface OrgScopedContext {
375
377
  */
376
378
  readonly _orgValidated: true;
377
379
  }
380
+
381
+ // =============================================================================
382
+ // Workspace Info/Settings Surface Types (PRD-00133)
383
+ // Capability naming invariant:
384
+ // Info surfaces use view-capabilities only (org.view_*)
385
+ // Settings surfaces use manage-capabilities only (org.manage_*)
386
+ // Consumers MUST NOT cross-wire: Info routes must never require org.manage_*
387
+ // capabilities, and Settings routes must never rely solely on org.view_*.
388
+ // =============================================================================
389
+
390
+ /**
391
+ * Discriminator for workspace surface routing.
392
+ * - 'info': Read-only surface, any member, org.view_* capabilities
393
+ * - 'settings': Admin surface, org.manage_* capabilities
394
+ */
395
+ export type WorkspaceSurface = 'info' | 'settings';
396
+
397
+ /**
398
+ * Read-only workspace overview for the Info surface.
399
+ * Visible to any workspace member with org.view_* capabilities.
400
+ *
401
+ * CAPABILITY INVARIANT: This type is served ONLY by Info routes
402
+ * which require org.view_* capabilities. Never use org.manage_*.
403
+ */
404
+ export interface WorkspaceInfoOverview {
405
+ /** Organization name. */
406
+ name: string;
407
+ /** Workspace owners (display-only). */
408
+ owners: Array<{ id: string; name: string }>;
409
+ /** Total member count. */
410
+ memberCount: number;
411
+ /** Human-readable management line (e.g., "Managed by Alice"). */
412
+ managedByLine: string;
413
+ }
414
+
415
+ /**
416
+ * Full workspace overview for the Settings surface.
417
+ * Extends Info with mutation-relevant fields.
418
+ * Visible only to admins with org.manage_* capabilities.
419
+ *
420
+ * CAPABILITY INVARIANT: This type is served ONLY by Settings routes
421
+ * which require org.manage_* capabilities. Never use org.view_* alone.
422
+ */
423
+ export interface WorkspaceSettingsOverview extends WorkspaceInfoOverview {
424
+ /** Organization slug (editable by admin). */
425
+ slug: string;
426
+ /** Metadata about who last edited settings and when. */
427
+ editMetadata: {
428
+ lastEditedBy: { id: string; name: string } | null;
429
+ lastEditedAt: string | null;
430
+ };
431
+ }
432
+
433
+ /**
434
+ * Status of an integration request from a member.
435
+ */
436
+ export type IntegrationRequestStatus = 'pending' | 'approved' | 'denied';
437
+
438
+ /**
439
+ * Advisory integration request created by a member.
440
+ * Members can request integration connections; admins see and action these.
441
+ * Creating a request does NOT guarantee approval.
442
+ */
443
+ export interface IntegrationRequest {
444
+ /** Unique request identifier. */
445
+ id: string;
446
+ /** Integration provider name (e.g., 'slack', 'github'). */
447
+ provider: string;
448
+ /** User who made the request. */
449
+ requestedBy: { id: string; name: string };
450
+ /** Current status of the request. */
451
+ status: IntegrationRequestStatus;
452
+ /** ISO8601 timestamp when the request was created. */
453
+ createdAt: string;
454
+ }