@company-semantics/contracts 13.19.0 → 13.20.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": "13.19.0",
3
+ "version": "13.20.0",
4
4
  "private": false,
5
5
  "repository": {
6
6
  "type": "git",
@@ -119,15 +119,15 @@
119
119
  "zod": "^4.4.3"
120
120
  },
121
121
  "devDependencies": {
122
- "@types/node": "^22.19.20",
122
+ "@types/node": "^25.9.3",
123
123
  "husky": "^9.1.7",
124
124
  "lint-staged": "^17.0.7",
125
125
  "markdownlint-cli2": "^0.22.1",
126
126
  "openapi-typescript": "^7.13.0",
127
- "prettier": "^3.8.3",
127
+ "prettier": "^3.8.4",
128
128
  "tsx": "^4.22.4",
129
129
  "typescript": "^5.8.3",
130
- "vitest": "^4.1.8",
130
+ "vitest": "^4.1.9",
131
131
  "yaml": "^2.9.0"
132
132
  },
133
133
  "pnpm": {
@@ -1,3 +1,3 @@
1
1
  // AUTO-GENERATED — do not edit. Run pnpm generate:spec-hash to regenerate.
2
- export const SPEC_HASH = 'b4c6a72ecef5' as const;
3
- export const SPEC_HASH_FULL = 'b4c6a72ecef5397ac7bffd8e6d1638ffa91d8e917e683ca31b1b71a356cd080e' as const;
2
+ export const SPEC_HASH = '255ee9f997af' as const;
3
+ export const SPEC_HASH_FULL = '255ee9f997afb36f3e96cdcffb8aa30a97e5c14f8c21b884974c75f9d126d596' as const;
@@ -3376,7 +3376,7 @@ export interface components {
3376
3376
  };
3377
3377
  ownerTitle: string;
3378
3378
  /** @enum {string} */
3379
- ownerIcon: "crown" | "crown-cross" | "person" | "medal-military" | "dog" | "cat";
3379
+ ownerIcon: "crown" | "crown-cross" | "person-simple-run" | "person" | "medal-military" | "dog" | "cat" | "linux-logo";
3380
3380
  createdAt: string;
3381
3381
  memberCount: number;
3382
3382
  claimable: boolean;
@@ -3390,7 +3390,7 @@ export interface components {
3390
3390
  OrgRenameRequest: {
3391
3391
  name?: string;
3392
3392
  ownerTitle?: string | null;
3393
- ownerIcon?: ("crown" | "crown-cross" | "person" | "medal-military" | "dog" | "cat") | null;
3393
+ ownerIcon?: ("crown" | "crown-cross" | "person-simple-run" | "person" | "medal-military" | "dog" | "cat" | "linux-logo") | null;
3394
3394
  };
3395
3395
  WorkspaceMembersResponse: {
3396
3396
  items: {
@@ -4051,6 +4051,11 @@ export interface components {
4051
4051
  state: "allowed" | "blocked";
4052
4052
  requiredScope?: string;
4053
4053
  };
4054
+ manageSharing: {
4055
+ /** @enum {string} */
4056
+ state: "allowed" | "blocked";
4057
+ requiredScope?: string;
4058
+ };
4054
4059
  };
4055
4060
  workItem?: {
4056
4061
  transferOwnership: {
@@ -4058,6 +4063,18 @@ export interface components {
4058
4063
  state: "allowed" | "blocked";
4059
4064
  requiredScope?: string;
4060
4065
  };
4066
+ manageSharing: {
4067
+ /** @enum {string} */
4068
+ state: "allowed" | "blocked";
4069
+ requiredScope?: string;
4070
+ };
4071
+ };
4072
+ meetingRecording?: {
4073
+ manageSharing: {
4074
+ /** @enum {string} */
4075
+ state: "allowed" | "blocked";
4076
+ requiredScope?: string;
4077
+ };
4061
4078
  };
4062
4079
  };
4063
4080
  };
@@ -82,6 +82,7 @@ export const openApiRoutes = {
82
82
  '/api/org-units/{unitId}/delegations': ['POST'],
83
83
  '/api/org-units/{unitId}/delegations/{id}': ['DELETE', 'PATCH'],
84
84
  '/api/org-units/{unitId}/descendants': ['GET'],
85
+ '/api/org-units/{unitId}/head': ['DELETE', 'PUT'],
85
86
  '/api/org-units/{unitId}/memberships': ['GET', 'POST'],
86
87
  '/api/org-units/{unitId}/memberships/{userId}': ['DELETE'],
87
88
  '/api/org-units/{unitId}/memberships/{userId}/role': ['PUT'],
package/src/index.ts CHANGED
@@ -358,6 +358,19 @@ export {
358
358
  // View authorization types (Phase 5 - ADR-APP-013)
359
359
  export type { AuthorizableView } from "./org/index";
360
360
 
361
+ // Org structure facts: provenance + home/membership separation (ADR-CONTRACTS-066)
362
+ export {
363
+ FactSourceTierSchema,
364
+ FACT_SOURCE_TIER_PRECEDENCE,
365
+ FactProvenanceSchema,
366
+ HomeAssignmentSchema,
367
+ } from "./org/index";
368
+ export type {
369
+ FactSourceTier,
370
+ FactProvenance,
371
+ HomeAssignment,
372
+ } from "./org/index";
373
+
361
374
  // Authority & Delegation vocabulary
362
375
  export {
363
376
  AuthoritySourceSchema,
package/src/org/index.ts CHANGED
@@ -87,6 +87,19 @@ export type {
87
87
  export type { AuthorizableView } from "./view-scopes";
88
88
  export { VIEW_SCOPE_MAP, getViewScope } from "./view-scopes";
89
89
 
90
+ // Org structure facts: provenance + home/membership separation (ADR-CONTRACTS-066)
91
+ export {
92
+ FactSourceTierSchema,
93
+ FACT_SOURCE_TIER_PRECEDENCE,
94
+ FactProvenanceSchema,
95
+ HomeAssignmentSchema,
96
+ } from "./structure-facts";
97
+ export type {
98
+ FactSourceTier,
99
+ FactProvenance,
100
+ HomeAssignment,
101
+ } from "./structure-facts";
102
+
90
103
  // Canonical OrgUnit tree ordering (PRD-00506)
91
104
  export type { TreeOrderableNode } from "./tree-ordering";
92
105
  export { orderTreeNodes } from "./tree-ordering";
@@ -1438,16 +1438,25 @@ export const CapabilitiesResponseSchema = z.object({
1438
1438
  orgUnit: z.object({
1439
1439
  manage: ActionCapabilitySchema,
1440
1440
  }),
1441
- // Entity ownership-transfer overrides (backend ADR-BE-259). Optional so
1442
- // older backends that don't derive them still validate.
1441
+ // Entity ownership-transfer overrides (backend ADR-BE-259) +
1442
+ // sharing-management custody (backend ADR-BE-288). Optional so older
1443
+ // backends that don't derive them still validate. manageSharing gates the
1444
+ // admin Share affordance on content the admin may not be able to view.
1443
1445
  companyMd: z
1444
1446
  .object({
1445
1447
  transferOwnership: ActionCapabilitySchema,
1448
+ manageSharing: ActionCapabilitySchema,
1446
1449
  })
1447
1450
  .optional(),
1448
1451
  workItem: z
1449
1452
  .object({
1450
1453
  transferOwnership: ActionCapabilitySchema,
1454
+ manageSharing: ActionCapabilitySchema,
1455
+ })
1456
+ .optional(),
1457
+ meetingRecording: z
1458
+ .object({
1459
+ manageSharing: ActionCapabilitySchema,
1451
1460
  })
1452
1461
  .optional(),
1453
1462
  })
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Org structure facts: provenance envelope + the home/membership separation.
3
+ *
4
+ * The org model is several INDEPENDENT graphs — the org-unit tree, the reporting
5
+ * graph, the home assignment, and the membership graph (and, later, positions).
6
+ * This module is the shared vocabulary for two cross-cutting ideas in that model
7
+ * (see ADR-CONTRACTS-066 and control ADR-CTRL-159):
8
+ *
9
+ * 1. Every structural fact carries provenance ({@link FactProvenanceSchema}).
10
+ * 2. "Home" is a dedicated ≤1-per-person relation ({@link HomeAssignmentSchema}),
11
+ * kept SEPARATE from `org_unit_memberships` — not a `kind` flag on memberships.
12
+ *
13
+ * Principles encoded here (do not drift from these):
14
+ * - Membership / home is an INPUT to authority derivation, NOT authority itself.
15
+ * `home member of unit` does not mean `owns unit`.
16
+ * - Facts are immutable; corrections SUPERSEDE prior facts (`supersedesFactId`)
17
+ * rather than mutating in place. This leaves room for event-sourcing later
18
+ * without forcing it now.
19
+ * - A truth hierarchy decides which fact wins: user > sync > import > inferred.
20
+ * - `source` is an OPEN string so new origins (scim, workday, csv, org_chart,
21
+ * google, slack, …) need no schema change; `tier` is the closed precedence axis.
22
+ */
23
+ import { z } from "zod";
24
+
25
+ // ---------------------------------------------------------------------------
26
+ // Provenance
27
+ // ---------------------------------------------------------------------------
28
+
29
+ /**
30
+ * The precedence axis for a fact. Closed set, ordered highest-precedence first
31
+ * (see {@link FACT_SOURCE_TIER_PRECEDENCE}). The specific origin lives in the
32
+ * open `source` string; this enum is what comparison / "who wins" reasons over.
33
+ */
34
+ export const FactSourceTierSchema = z.enum([
35
+ "user",
36
+ "sync",
37
+ "import",
38
+ "inferred",
39
+ ]);
40
+ export type FactSourceTier = z.infer<typeof FactSourceTierSchema>;
41
+
42
+ /**
43
+ * Truth hierarchy, highest precedence first. A writer at a lower tier must never
44
+ * supersede a fact recorded at a higher tier (e.g. an org-chart import must not
45
+ * overwrite a `user`-entered reporting edge).
46
+ */
47
+ export const FACT_SOURCE_TIER_PRECEDENCE = [
48
+ "user",
49
+ "sync",
50
+ "import",
51
+ "inferred",
52
+ ] as const satisfies ReadonlyArray<FactSourceTier>;
53
+
54
+ /**
55
+ * Provenance envelope attached to a structural fact (reporting edge, org unit,
56
+ * membership, home assignment). The live value of any fact is the
57
+ * highest-precedence, non-superseded record.
58
+ */
59
+ export const FactProvenanceSchema = z.object({
60
+ /** Precedence axis used by the truth hierarchy. */
61
+ tier: FactSourceTierSchema,
62
+ /**
63
+ * Specific origin — OPEN set, e.g. `manual` | `org_chart` | `scim` | `hris` |
64
+ * `csv` | `google` | `slack`. New origins slot in without a schema change.
65
+ */
66
+ source: z.string().min(1),
67
+ /** Extractor/matcher certainty in [0,1]; `null` for human-entered facts. */
68
+ confidence: z.number().min(0).max(1).nullable(),
69
+ /**
70
+ * True once a human has corrected/confirmed the fact. A locked fact is sticky:
71
+ * lower-tier writers (imports, inference) must not supersede it.
72
+ */
73
+ locked: z.boolean(),
74
+ /**
75
+ * The fact this record supersedes (immutable correction history); `null`/absent
76
+ * for an original. Enables append+supersede without destructive updates.
77
+ */
78
+ supersedesFactId: z.string().uuid().nullable().optional(),
79
+ });
80
+ export type FactProvenance = z.infer<typeof FactProvenanceSchema>;
81
+
82
+ // ---------------------------------------------------------------------------
83
+ // HomeAssignment (separate from membership)
84
+ // ---------------------------------------------------------------------------
85
+
86
+ /**
87
+ * A person's single structural home unit — at most one per person per org.
88
+ *
89
+ * SEPARATE relation from `org_unit_memberships` (NOT a `kind`/role flag on a
90
+ * shared table): the cardinalities differ on purpose — exactly one home, many
91
+ * memberships — which is the tell that they are different concepts. A shared
92
+ * `Membership(kind='home'|'member')` would inevitably grow
93
+ * `acting-home`/`temporary-home`/`future-home` flags.
94
+ *
95
+ * Home is an INPUT to authority derivation, sets `department`/`org` scope, and
96
+ * filters chart inclusion. It is NOT authority by itself (see Principles above).
97
+ * Supersedes the legacy `users.primary_unit_id` pointer (ADR-BE-120).
98
+ */
99
+ export const HomeAssignmentSchema = z.object({
100
+ personId: z.string().uuid(),
101
+ orgUnitId: z.string().uuid(),
102
+ /** Provenance of this home assignment. Optional on lightweight projections. */
103
+ provenance: FactProvenanceSchema.optional(),
104
+ });
105
+ export type HomeAssignment = z.infer<typeof HomeAssignmentSchema>;