@company-semantics/contracts 0.116.0 → 0.118.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.116.0",
3
+ "version": "0.118.0",
4
4
  "private": false,
5
5
  "repository": {
6
6
  "type": "git",
@@ -1893,6 +1893,70 @@ export interface paths {
1893
1893
  patch?: never;
1894
1894
  trace?: never;
1895
1895
  };
1896
+ "/api/company-md/context-bank": {
1897
+ parameters: {
1898
+ query?: never;
1899
+ header?: never;
1900
+ path?: never;
1901
+ cookie?: never;
1902
+ };
1903
+ get?: never;
1904
+ put?: never;
1905
+ /**
1906
+ * Create a new context bank doc and associate with parent
1907
+ * @description Creates a new context doc (level=context) and associates it with the
1908
+ * given parent doc. Requires org.view_company_md capability.
1909
+ */
1910
+ post: operations["createCompanyMdContextDoc"];
1911
+ delete?: never;
1912
+ options?: never;
1913
+ head?: never;
1914
+ patch?: never;
1915
+ trace?: never;
1916
+ };
1917
+ "/api/company-md/docs/{slug}/context-bank/associate": {
1918
+ parameters: {
1919
+ query?: never;
1920
+ header?: never;
1921
+ path?: never;
1922
+ cookie?: never;
1923
+ };
1924
+ get?: never;
1925
+ put?: never;
1926
+ /**
1927
+ * Associate an existing context doc with a parent doc
1928
+ * @description Associates an existing context doc with the given parent doc.
1929
+ * Returns 409 if the association already exists.
1930
+ * Requires org.view_company_md capability.
1931
+ */
1932
+ post: operations["associateCompanyMdContextDoc"];
1933
+ delete?: never;
1934
+ options?: never;
1935
+ head?: never;
1936
+ patch?: never;
1937
+ trace?: never;
1938
+ };
1939
+ "/api/company-md/docs/{slug}/context-bank/{contextDocSlug}": {
1940
+ parameters: {
1941
+ query?: never;
1942
+ header?: never;
1943
+ path?: never;
1944
+ cookie?: never;
1945
+ };
1946
+ get?: never;
1947
+ put?: never;
1948
+ post?: never;
1949
+ /**
1950
+ * Remove a context bank association
1951
+ * @description Removes the association between a context doc and its parent doc.
1952
+ * Requires org.view_company_md capability.
1953
+ */
1954
+ delete: operations["removeCompanyMdContextAssociation"];
1955
+ options?: never;
1956
+ head?: never;
1957
+ patch?: never;
1958
+ trace?: never;
1959
+ };
1896
1960
  "/api/company-md/docs/{slug}/sharing": {
1897
1961
  parameters: {
1898
1962
  query?: never;
@@ -2006,6 +2070,50 @@ export interface paths {
2006
2070
  patch?: never;
2007
2071
  trace?: never;
2008
2072
  };
2073
+ "/api/company-md/settings": {
2074
+ parameters: {
2075
+ query?: never;
2076
+ header?: never;
2077
+ path?: never;
2078
+ cookie?: never;
2079
+ };
2080
+ /**
2081
+ * Get company.md settings for the authenticated org
2082
+ * @description Returns CompanyMdSettings with merged defaults. The root label defaults
2083
+ * to the org name; department and team use system defaults if not customized.
2084
+ * Requires org.view_company_md capability.
2085
+ */
2086
+ get: operations["getCompanyMdSettings"];
2087
+ put?: never;
2088
+ post?: never;
2089
+ delete?: never;
2090
+ options?: never;
2091
+ head?: never;
2092
+ patch?: never;
2093
+ trace?: never;
2094
+ };
2095
+ "/api/company-md/settings/level-labels": {
2096
+ parameters: {
2097
+ query?: never;
2098
+ header?: never;
2099
+ path?: never;
2100
+ cookie?: never;
2101
+ };
2102
+ get?: never;
2103
+ /**
2104
+ * Update company.md level labels for the authenticated org
2105
+ * @description Accepts a partial CompanyMdLevelLabels object. Only provided fields are updated;
2106
+ * unspecified fields retain their current values. Returns the full updated
2107
+ * CompanyMdSettings. Requires org.manage_company_md capability (org owner/admin).
2108
+ */
2109
+ put: operations["updateCompanyMdLevelLabels"];
2110
+ post?: never;
2111
+ delete?: never;
2112
+ options?: never;
2113
+ head?: never;
2114
+ patch?: never;
2115
+ trace?: never;
2116
+ };
2009
2117
  "/api/teams": {
2010
2118
  parameters: {
2011
2119
  query?: never;
@@ -2387,6 +2495,25 @@ export interface components {
2387
2495
  /** @enum {string} */
2388
2496
  visibility: "standard" | "admin";
2389
2497
  };
2498
+ CompanyMdLevelLabels: {
2499
+ /** @description Label for the root level (defaults to org name) */
2500
+ root: string;
2501
+ /** @description Label for the department level */
2502
+ department: string;
2503
+ /** @description Label for the team level */
2504
+ team: string;
2505
+ };
2506
+ CompanyMdSettings: {
2507
+ levelLabels: components["schemas"]["CompanyMdLevelLabels"];
2508
+ };
2509
+ UpdateCompanyMdLevelLabelsRequest: {
2510
+ /** @description Label for the root level */
2511
+ root?: string;
2512
+ /** @description Label for the department level */
2513
+ department?: string;
2514
+ /** @description Label for the team level */
2515
+ team?: string;
2516
+ };
2390
2517
  ChatRequest: {
2391
2518
  messages: Record<string, never>[];
2392
2519
  };
@@ -7473,6 +7600,155 @@ export interface operations {
7473
7600
  };
7474
7601
  };
7475
7602
  };
7603
+ createCompanyMdContextDoc: {
7604
+ parameters: {
7605
+ query?: never;
7606
+ header?: never;
7607
+ path?: never;
7608
+ cookie?: never;
7609
+ };
7610
+ requestBody: {
7611
+ content: {
7612
+ "application/json": {
7613
+ title: string;
7614
+ parentDocSlug: string;
7615
+ };
7616
+ };
7617
+ };
7618
+ responses: {
7619
+ /** @description Created context doc */
7620
+ 201: {
7621
+ headers: {
7622
+ [name: string]: unknown;
7623
+ };
7624
+ content: {
7625
+ "application/json": {
7626
+ /** Format: uuid */
7627
+ id: string;
7628
+ slug: string;
7629
+ title: string;
7630
+ };
7631
+ };
7632
+ };
7633
+ /** @description No org.view_company_md capability */
7634
+ 403: {
7635
+ headers: {
7636
+ [name: string]: unknown;
7637
+ };
7638
+ content: {
7639
+ "application/json": components["schemas"]["ErrorResponse"];
7640
+ };
7641
+ };
7642
+ /** @description Parent doc not found */
7643
+ 404: {
7644
+ headers: {
7645
+ [name: string]: unknown;
7646
+ };
7647
+ content: {
7648
+ "application/json": components["schemas"]["ErrorResponse"];
7649
+ };
7650
+ };
7651
+ };
7652
+ };
7653
+ associateCompanyMdContextDoc: {
7654
+ parameters: {
7655
+ query?: never;
7656
+ header?: never;
7657
+ path: {
7658
+ /** @description Parent doc slug */
7659
+ slug: string;
7660
+ };
7661
+ cookie?: never;
7662
+ };
7663
+ requestBody: {
7664
+ content: {
7665
+ "application/json": {
7666
+ contextDocSlug: string;
7667
+ };
7668
+ };
7669
+ };
7670
+ responses: {
7671
+ /** @description Association created */
7672
+ 200: {
7673
+ headers: {
7674
+ [name: string]: unknown;
7675
+ };
7676
+ content: {
7677
+ "application/json": {
7678
+ ok?: boolean;
7679
+ };
7680
+ };
7681
+ };
7682
+ /** @description No org.view_company_md capability */
7683
+ 403: {
7684
+ headers: {
7685
+ [name: string]: unknown;
7686
+ };
7687
+ content: {
7688
+ "application/json": components["schemas"]["ErrorResponse"];
7689
+ };
7690
+ };
7691
+ /** @description Doc not found */
7692
+ 404: {
7693
+ headers: {
7694
+ [name: string]: unknown;
7695
+ };
7696
+ content: {
7697
+ "application/json": components["schemas"]["ErrorResponse"];
7698
+ };
7699
+ };
7700
+ /** @description Association already exists */
7701
+ 409: {
7702
+ headers: {
7703
+ [name: string]: unknown;
7704
+ };
7705
+ content: {
7706
+ "application/json": components["schemas"]["ErrorResponse"];
7707
+ };
7708
+ };
7709
+ };
7710
+ };
7711
+ removeCompanyMdContextAssociation: {
7712
+ parameters: {
7713
+ query?: never;
7714
+ header?: never;
7715
+ path: {
7716
+ /** @description Parent doc slug */
7717
+ slug: string;
7718
+ /** @description Context doc slug */
7719
+ contextDocSlug: string;
7720
+ };
7721
+ cookie?: never;
7722
+ };
7723
+ requestBody?: never;
7724
+ responses: {
7725
+ /** @description Association removed */
7726
+ 204: {
7727
+ headers: {
7728
+ [name: string]: unknown;
7729
+ };
7730
+ content?: never;
7731
+ };
7732
+ /** @description No org.view_company_md capability */
7733
+ 403: {
7734
+ headers: {
7735
+ [name: string]: unknown;
7736
+ };
7737
+ content: {
7738
+ "application/json": components["schemas"]["ErrorResponse"];
7739
+ };
7740
+ };
7741
+ /** @description Doc not found */
7742
+ 404: {
7743
+ headers: {
7744
+ [name: string]: unknown;
7745
+ };
7746
+ content: {
7747
+ "application/json": components["schemas"]["ErrorResponse"];
7748
+ };
7749
+ };
7750
+ };
7751
+ };
7476
7752
  getCompanyMdDocSharing: {
7477
7753
  parameters: {
7478
7754
  query?: never;
@@ -7785,6 +8061,77 @@ export interface operations {
7785
8061
  };
7786
8062
  };
7787
8063
  };
8064
+ getCompanyMdSettings: {
8065
+ parameters: {
8066
+ query?: never;
8067
+ header?: never;
8068
+ path?: never;
8069
+ cookie?: never;
8070
+ };
8071
+ requestBody?: never;
8072
+ responses: {
8073
+ /** @description Company.md settings with merged defaults */
8074
+ 200: {
8075
+ headers: {
8076
+ [name: string]: unknown;
8077
+ };
8078
+ content: {
8079
+ "application/json": components["schemas"]["CompanyMdSettings"];
8080
+ };
8081
+ };
8082
+ /** @description No org.view_company_md capability */
8083
+ 403: {
8084
+ headers: {
8085
+ [name: string]: unknown;
8086
+ };
8087
+ content: {
8088
+ "application/json": components["schemas"]["ErrorResponse"];
8089
+ };
8090
+ };
8091
+ };
8092
+ };
8093
+ updateCompanyMdLevelLabels: {
8094
+ parameters: {
8095
+ query?: never;
8096
+ header?: never;
8097
+ path?: never;
8098
+ cookie?: never;
8099
+ };
8100
+ requestBody: {
8101
+ content: {
8102
+ "application/json": components["schemas"]["UpdateCompanyMdLevelLabelsRequest"];
8103
+ };
8104
+ };
8105
+ responses: {
8106
+ /** @description Updated company.md settings */
8107
+ 200: {
8108
+ headers: {
8109
+ [name: string]: unknown;
8110
+ };
8111
+ content: {
8112
+ "application/json": components["schemas"]["CompanyMdSettings"];
8113
+ };
8114
+ };
8115
+ /** @description Invalid label values (empty or exceeds 50 characters) */
8116
+ 400: {
8117
+ headers: {
8118
+ [name: string]: unknown;
8119
+ };
8120
+ content: {
8121
+ "application/json": components["schemas"]["ErrorResponse"];
8122
+ };
8123
+ };
8124
+ /** @description No org.manage_company_md capability */
8125
+ 403: {
8126
+ headers: {
8127
+ [name: string]: unknown;
8128
+ };
8129
+ content: {
8130
+ "application/json": components["schemas"]["ErrorResponse"];
8131
+ };
8132
+ };
8133
+ };
8134
+ };
7788
8135
  listTeams: {
7789
8136
  parameters: {
7790
8137
  query?: never;
@@ -28,3 +28,7 @@ export type { AvatarSource, ResolvedAvatar } from './avatar';
28
28
 
29
29
  // Functions - Avatar
30
30
  export { generateInitials, resolveAvatar } from './avatar';
31
+
32
+ // Response Schemas (Zod) - canonical location per ADR-CONT-044
33
+ export { MeResponseSchema, AuthStartResponseSchema, AuthVerifyResponseSchema, SsoConfigResponseSchema, ProfileResponseSchema } from './schemas';
34
+ export type { MeResponse, AuthStartResponse, AuthVerifyResponse, SsoConfigResponse, ProfileResponse } from './schemas';
@@ -0,0 +1,139 @@
1
+ /**
2
+ * Identity Response Schemas
3
+ *
4
+ * Zod response schemas for auth and identity endpoints.
5
+ * Canonical location for runtime validation of identity API responses.
6
+ *
7
+ * Deviation note (AuthStartResponseSchema): The PRD reference suggested
8
+ * z.object({ sent: boolean }), but the actual POST /auth/start route returns
9
+ * a discriminated union on `mode` (otp | sso | hybrid). Schema matches reality.
10
+ */
11
+ import { z } from 'zod';
12
+
13
+ // ---------------------------------------------------------------------------
14
+ // Shared sub-schemas
15
+ // ---------------------------------------------------------------------------
16
+
17
+ const ResolvedAvatarSchema = z.object({
18
+ source: z.enum(['slack', 'initials']),
19
+ url: z.string().optional(),
20
+ initials: z.string(),
21
+ });
22
+
23
+ // ---------------------------------------------------------------------------
24
+ // GET /api/me
25
+ // ---------------------------------------------------------------------------
26
+
27
+ /**
28
+ * Full identity context returned by GET /api/me.
29
+ * Canonical location: moved from backend contract-surfaces.ts per ADR-CONT-044.
30
+ */
31
+ export const MeResponseSchema = z.object({
32
+ userId: z.string().uuid(),
33
+ email: z.string(),
34
+ fullName: z.string(),
35
+ preferredName: z.string().nullable(),
36
+ displayName: z.string(),
37
+ nameSource: z.enum(['self', 'sso']),
38
+ nameEditable: z.boolean(),
39
+ primaryDepartmentId: z.string().nullable(),
40
+ slackUserId: z.string().nullable(),
41
+ avatar: ResolvedAvatarSchema,
42
+ orgId: z.string().uuid(),
43
+ orgName: z.string().nullable(),
44
+ orgSlug: z.string(),
45
+ plan: z.string(),
46
+ hasMultipleOrgs: z.boolean(),
47
+ isInternalAdmin: z.boolean(),
48
+ });
49
+
50
+ export type MeResponse = z.infer<typeof MeResponseSchema>;
51
+
52
+ // ---------------------------------------------------------------------------
53
+ // POST /auth/start
54
+ // Discriminated union on mode: otp | sso | hybrid
55
+ // ---------------------------------------------------------------------------
56
+
57
+ export const AuthStartResponseSchema = z.discriminatedUnion('mode', [
58
+ z.object({
59
+ mode: z.literal('otp'),
60
+ devOtp: z.string().optional(),
61
+ }),
62
+ z.object({
63
+ mode: z.literal('sso'),
64
+ providers: z.array(z.string()),
65
+ redirectUrl: z.string(),
66
+ }),
67
+ z.object({
68
+ mode: z.literal('hybrid'),
69
+ providers: z.array(z.string()),
70
+ redirectUrl: z.string(),
71
+ otpAllowed: z.literal(true),
72
+ devOtp: z.string().optional(),
73
+ }),
74
+ ]);
75
+
76
+ export type AuthStartResponse = z.infer<typeof AuthStartResponseSchema>;
77
+
78
+ // ---------------------------------------------------------------------------
79
+ // POST /auth/verify
80
+ // Sets session cookie on success; body is minimal.
81
+ // ---------------------------------------------------------------------------
82
+
83
+ export const AuthVerifyResponseSchema = z.union([
84
+ z.object({
85
+ success: z.literal(true),
86
+ ok: z.literal(true),
87
+ }),
88
+ z.object({
89
+ success: z.literal(true),
90
+ ok: z.literal(true),
91
+ acceptedInvite: z.literal(true),
92
+ orgId: z.string(),
93
+ role: z.string(),
94
+ }),
95
+ ]);
96
+
97
+ export type AuthVerifyResponse = z.infer<typeof AuthVerifyResponseSchema>;
98
+
99
+ // ---------------------------------------------------------------------------
100
+ // GET /api/workspace/auth (SSO configuration)
101
+ // Matches WorkspaceAuthConfig from org/types.ts
102
+ // ---------------------------------------------------------------------------
103
+
104
+ const AuthMethodConfigSchema = z.object({
105
+ enabled: z.boolean(),
106
+ provider: z.string().optional(),
107
+ });
108
+
109
+ export const SsoConfigResponseSchema = z.object({
110
+ emailOtp: AuthMethodConfigSchema,
111
+ googleSso: AuthMethodConfigSchema,
112
+ microsoftSso: AuthMethodConfigSchema,
113
+ okta: AuthMethodConfigSchema,
114
+ policy: z.object({
115
+ requireSSO: z.boolean(),
116
+ allowedProviders: z.array(z.string()),
117
+ }),
118
+ });
119
+
120
+ export type SsoConfigResponse = z.infer<typeof SsoConfigResponseSchema>;
121
+
122
+ // ---------------------------------------------------------------------------
123
+ // PATCH /api/user/profile
124
+ // Profile shape returned after a successful profile update.
125
+ // ---------------------------------------------------------------------------
126
+
127
+ export const ProfileResponseSchema = z.object({
128
+ success: z.literal(true),
129
+ user: z.object({
130
+ id: z.string(),
131
+ fullName: z.string(),
132
+ preferredName: z.string().nullable(),
133
+ displayName: z.string(),
134
+ nameSource: z.enum(['self', 'sso']),
135
+ primaryDepartmentId: z.string().nullable(),
136
+ }),
137
+ });
138
+
139
+ export type ProfileResponse = z.infer<typeof ProfileResponseSchema>;
package/src/index.ts CHANGED
@@ -120,6 +120,21 @@ export { extractFirstWord, resolveDisplayName, deriveFullName } from './identity
120
120
  export type { AvatarSource, ResolvedAvatar } from './identity/index'
121
121
  export { generateInitials, resolveAvatar } from './identity/index'
122
122
 
123
+ // Identity response schemas (Zod) - canonical location per ADR-CONT-044
124
+ export {
125
+ MeResponseSchema,
126
+ AuthStartResponseSchema,
127
+ AuthVerifyResponseSchema,
128
+ SsoConfigResponseSchema,
129
+ ProfileResponseSchema,
130
+ } from './identity/index'
131
+ export type {
132
+ MeResponse,
133
+ AuthVerifyResponse,
134
+ SsoConfigResponse,
135
+ ProfileResponse,
136
+ } from './identity/index'
137
+
123
138
  // Auth domain types
124
139
  export type { AuthStartMode, AuthStartResponse } from './auth/index'
125
140
  export { OTPErrorCode } from './auth/index'
@@ -76,6 +76,25 @@ export interface CompanyMdDocRelations {
76
76
 
77
77
  export type CompanyMdDoc = CompanyMdDocCore & CompanyMdDocCollaborators & CompanyMdDocRelations;
78
78
 
79
+ export interface CompanyMdLevelLabels {
80
+ /** L1 label — defaults to org name */
81
+ readonly root: string;
82
+ /** L2 label — defaults to 'Department' */
83
+ readonly department: string;
84
+ /** L3 label — defaults to 'Team' */
85
+ readonly team: string;
86
+ }
87
+
88
+ export interface CompanyMdSettings {
89
+ readonly levelLabels: CompanyMdLevelLabels;
90
+ }
91
+
92
+ /** System defaults for level labels. L1 (root) is set per-org at read time. */
93
+ export const DEFAULT_LEVEL_LABELS: Omit<CompanyMdLevelLabels, 'root'> = {
94
+ department: 'Department',
95
+ team: 'Team',
96
+ } as const;
97
+
79
98
  /**
80
99
  * A context bank item — a company.md doc associated with one or more parent nodes.
81
100
  * Context bank files can belong to company, department, or team levels.
package/src/org/index.ts CHANGED
@@ -96,8 +96,13 @@ export type {
96
96
  CompanyMdContextBankItem,
97
97
  TeamDepartmentRole,
98
98
  TeamDepartmentMembership,
99
+ // Level labels settings types (PRD-00453)
100
+ CompanyMdLevelLabels,
101
+ CompanyMdSettings,
99
102
  } from './company-md';
100
103
 
104
+ export { DEFAULT_LEVEL_LABELS } from './company-md';
105
+
101
106
  // Team types (PRD-00306)
102
107
  export type {
103
108
  TeamMembershipRole,