@company-semantics/contracts 0.38.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.38.0",
3
+ "version": "0.39.0",
4
4
  "private": false,
5
5
  "repository": {
6
6
  "type": "git",
package/src/index.ts CHANGED
@@ -152,9 +152,15 @@ export type {
152
152
  OrgDomain,
153
153
  Phase4AuditAction,
154
154
  UserOrgMembership,
155
+ // Authorization context types (Phase 5)
156
+ // @see ADR-CTRL-010 for design rationale
157
+ OrgScopedContext,
155
158
  } from './org/index'
156
159
 
157
- 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'
158
164
 
159
165
  // MCP tool discovery types
160
166
  // @see company-semantics-backend/src/interfaces/mcp/ for implementation
package/src/org/index.ts CHANGED
@@ -34,6 +34,8 @@ export type {
34
34
  Phase3AuditAction,
35
35
  // Multi-org membership types (Phase 4)
36
36
  UserOrgMembership,
37
+ // Authorization context types (Phase 5 - ADR-CTRL-010)
38
+ OrgScopedContext,
37
39
  } from './types';
38
40
 
39
41
  export { ROLE_DISPLAY_MAP } from './types';
@@ -49,3 +51,7 @@ export type {
49
51
  OrgDomain,
50
52
  Phase4AuditAction,
51
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
@@ -329,3 +329,49 @@ export interface UserOrgMembership {
329
329
  /** Whether this membership is currently active. */
330
330
  isActive: boolean;
331
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
+ }