@company-semantics/contracts 0.37.0 → 0.39.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.37.0",
3
+ "version": "0.39.0",
4
4
  "private": false,
5
5
  "repository": {
6
6
  "type": "git",
package/src/index.ts CHANGED
@@ -145,9 +145,22 @@ export type {
145
145
  Phase3AuditAction,
146
146
  // Workspace capability types (Phase 3)
147
147
  WorkspaceCapability,
148
+ // Domain and multi-org types (Phase 4)
149
+ // @see ADR-CONT-032 for design rationale
150
+ DomainStatus,
151
+ DomainVerificationMethod,
152
+ OrgDomain,
153
+ Phase4AuditAction,
154
+ UserOrgMembership,
155
+ // Authorization context types (Phase 5)
156
+ // @see ADR-CTRL-010 for design rationale
157
+ OrgScopedContext,
148
158
  } from './org/index'
149
159
 
150
- export { ROLE_DISPLAY_MAP, WORKSPACE_CAPABILITIES, ROLE_CAPABILITY_MAP } from './org/index'
160
+ export { ROLE_DISPLAY_MAP, WORKSPACE_CAPABILITIES, ROLE_CAPABILITY_MAP, VIEW_SCOPE_MAP, getViewScope } from './org/index'
161
+
162
+ // View authorization types (Phase 5 - ADR-APP-013)
163
+ export type { AuthorizableView } from './org/index'
151
164
 
152
165
  // MCP tool discovery types
153
166
  // @see company-semantics-backend/src/interfaces/mcp/ for implementation
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Domain Types (Phase 4)
3
+ *
4
+ * Vocabulary types for enterprise domain verification and trust.
5
+ * @see ADR-CONT-032 (Phase 4: Enterprise Identity, Domain Trust, Multi-Org)
6
+ */
7
+
8
+ /**
9
+ * Status of a domain claim within an organization.
10
+ * - 'pending': Domain claimed but not yet verified
11
+ * - 'verified': Domain ownership confirmed via DNS TXT record
12
+ * - 'revoked': Domain claim revoked by org owner
13
+ *
14
+ * INVARIANT: Only ONE org may have status='verified' for any domain globally.
15
+ */
16
+ export type DomainStatus = 'pending' | 'verified' | 'revoked';
17
+
18
+ /**
19
+ * Method used to verify domain ownership.
20
+ * - 'dns_txt': DNS TXT record verification (primary method)
21
+ * - 'email': Email-based verification (reserved for future)
22
+ * - 'idp': IdP-based verification via SAML/OIDC (reserved for future)
23
+ */
24
+ export type DomainVerificationMethod = 'dns_txt' | 'email' | 'idp';
25
+
26
+ /**
27
+ * Organization domain claim and verification status.
28
+ * Represents a domain that an org has claimed or verified ownership of.
29
+ *
30
+ * INVARIANT: Domain verification does not grant access.
31
+ * INVARIANT: Only one org can have a verified claim on any email domain.
32
+ */
33
+ export interface OrgDomain {
34
+ id: string;
35
+ orgId: string;
36
+ domain: string;
37
+ status: DomainStatus;
38
+ verificationMethod: DomainVerificationMethod;
39
+ /** Verification token - only visible to org owner. */
40
+ verificationToken?: string;
41
+ /** ISO8601 timestamp when domain was verified, null if pending/revoked. */
42
+ verifiedAt: string | null;
43
+ /** ISO8601 timestamp when claim was created. */
44
+ createdAt: string;
45
+ }
46
+
47
+ // =============================================================================
48
+ // Phase 4 Audit Action Types
49
+ // =============================================================================
50
+
51
+ /**
52
+ * Audit actions for Phase 4 enterprise identity features.
53
+ * These actions are emitted by the backend when domain/auth state changes.
54
+ *
55
+ * INVARIANT: All domain and auth policy mutations must emit audit events.
56
+ */
57
+ export type Phase4AuditAction =
58
+ // Domain lifecycle
59
+ | 'org.domain.claimed'
60
+ | 'org.domain.verified'
61
+ | 'org.domain.revoked'
62
+ // Auth policy enforcement
63
+ | 'org.auth_policy.enforced'
64
+ | 'org.auth_policy.override_used' // Emergency SSO bypass succeeded
65
+ | 'org.auth_policy.override_attempted' // Emergency SSO bypass denied (incident review)
66
+ // Multi-org context
67
+ | 'user.active_org.switched';
package/src/org/index.ts CHANGED
@@ -32,6 +32,10 @@ export type {
32
32
  PromoteIntegrationRequest,
33
33
  DemoteIntegrationRequest,
34
34
  Phase3AuditAction,
35
+ // Multi-org membership types (Phase 4)
36
+ UserOrgMembership,
37
+ // Authorization context types (Phase 5 - ADR-CTRL-010)
38
+ OrgScopedContext,
35
39
  } from './types';
36
40
 
37
41
  export { ROLE_DISPLAY_MAP } from './types';
@@ -39,3 +43,15 @@ export { ROLE_DISPLAY_MAP } from './types';
39
43
  // Workspace capability types (Phase 3)
40
44
  export type { WorkspaceCapability } from './capabilities';
41
45
  export { WORKSPACE_CAPABILITIES, ROLE_CAPABILITY_MAP } from './capabilities';
46
+
47
+ // Domain types (Phase 4)
48
+ export type {
49
+ DomainStatus,
50
+ DomainVerificationMethod,
51
+ OrgDomain,
52
+ Phase4AuditAction,
53
+ } from './domain';
54
+
55
+ // View authorization scopes (Phase 5 - ADR-APP-013)
56
+ export type { AuthorizableView } from './view-scopes';
57
+ export { VIEW_SCOPE_MAP, getViewScope } from './view-scopes';
package/src/org/types.ts CHANGED
@@ -304,3 +304,74 @@ export type Phase3AuditAction =
304
304
  | 'integration.scope_demoted'
305
305
  // Auth policy
306
306
  | 'org.auth_policy.updated';
307
+
308
+ // =============================================================================
309
+ // Multi-Org Membership Types (Phase 4)
310
+ // @see ADR-CONT-032 for design rationale
311
+ // =============================================================================
312
+
313
+ /**
314
+ * User organization membership summary.
315
+ * Represents a user's membership in an organization for multi-org context switching.
316
+ *
317
+ * INVARIANT: role is DERIVED from RBAC at write-time (presentation only).
318
+ * INVARIANT: RBAC remains the authoritative source of truth for permissions.
319
+ */
320
+ export interface UserOrgMembership {
321
+ userId: string;
322
+ orgId: string;
323
+ orgName: string;
324
+ orgSlug: string;
325
+ /** Display role derived from RBAC - presentation only, not for auth decisions. */
326
+ role: WorkspaceRole;
327
+ /** ISO8601 timestamp when user joined the organization. */
328
+ joinedAt: string;
329
+ /** Whether this membership is currently active. */
330
+ isActive: boolean;
331
+ }
332
+
333
+ // ─────────────────────────────────────────────────────────────────────────────
334
+ // Authorization Context Types (Phase 5 - ADR-CTRL-010)
335
+ // ─────────────────────────────────────────────────────────────────────────────
336
+
337
+ /**
338
+ * Validated organization-scoped context for policy implementations.
339
+ *
340
+ * This type provides compile-time proof that org membership was validated
341
+ * upstream. Policy implementations MUST accept this type instead of raw
342
+ * `orgId: string` to prevent user-controlled org bypass attacks.
343
+ *
344
+ * @invariant orgId comes from validated session, never user input
345
+ * @invariant userId is the authenticated user from session
346
+ * @invariant _orgValidated is a type-level marker (not runtime)
347
+ *
348
+ * @see ADR-CTRL-010 Org-Scoped Context Type requirement
349
+ * @see ADR-BE-060 Policy Delegation Pattern
350
+ *
351
+ * @example
352
+ * ```typescript
353
+ * // Policy implementation - accepts context, not raw orgId
354
+ * export const DomainViewPolicyImpl = {
355
+ * async getDomainById(
356
+ * db: Db,
357
+ * ctx: OrgScopedContext,
358
+ * domainId: string
359
+ * ): Promise<OrgDomain | null> {
360
+ * return db.select().from(orgDomains)
361
+ * .where(and(eq(orgDomains.orgId, ctx.orgId), eq(orgDomains.id, domainId)));
362
+ * }
363
+ * };
364
+ * ```
365
+ */
366
+ export interface OrgScopedContext {
367
+ /** Organization ID from validated session. */
368
+ readonly orgId: string;
369
+ /** Authenticated user ID from session. */
370
+ readonly userId: string;
371
+ /**
372
+ * Type-level marker proving org validation occurred.
373
+ * This is a compile-time constraint, not a runtime value.
374
+ * Set to `true as const` when constructing from validated session.
375
+ */
376
+ readonly _orgValidated: true;
377
+ }
@@ -0,0 +1,42 @@
1
+ /**
2
+ * View Authorization Scope Mapping
3
+ *
4
+ * Maps frontend views to required RBAC scopes.
5
+ * Used by useViewAuthorization hook for centralized view access control.
6
+ *
7
+ * See: ADR-APP-013
8
+ *
9
+ * INVARIANT: VIEW_SCOPE_MAP must stay in sync with AppView type in app-state.ts
10
+ */
11
+
12
+ /**
13
+ * View-to-scope mapping for frontend authorization.
14
+ *
15
+ * - Views with string values require that scope for access
16
+ * - Views with null values are public (require only authentication)
17
+ */
18
+ export const VIEW_SCOPE_MAP = {
19
+ // Protected views (require specific scope)
20
+ workspace: 'org.view_workspace',
21
+ timeline: 'org.view_timeline',
22
+ dashboard: 'org.view_dashboard',
23
+ 'organization-strategy': 'org.view_strategy',
24
+ 'system-snapshot': 'org.view_system',
25
+ // Public views (require only authentication)
26
+ chat: null,
27
+ settings: null,
28
+ chats: null,
29
+ upgrade: null,
30
+ } as const;
31
+
32
+ /**
33
+ * Type for views that can be checked against VIEW_SCOPE_MAP.
34
+ */
35
+ export type AuthorizableView = keyof typeof VIEW_SCOPE_MAP;
36
+
37
+ /**
38
+ * Get the required scope for a view, or null if public.
39
+ */
40
+ export function getViewScope(view: string): string | null {
41
+ return VIEW_SCOPE_MAP[view as AuthorizableView] ?? null;
42
+ }