@company-semantics/contracts 27.7.0 → 27.8.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": "27.7.0",
3
+ "version": "27.8.0",
4
4
  "private": false,
5
5
  "repository": {
6
6
  "type": "git",
@@ -1,3 +1,3 @@
1
1
  // AUTO-GENERATED — do not edit. Run pnpm generate:spec-hash to regenerate.
2
- export const SPEC_HASH = '628fe99ff916' as const;
3
- export const SPEC_HASH_FULL = '628fe99ff9166b9eb6c0b2bab2794f4e730ceabff0785b7b54b8015897e9551d' as const;
2
+ export const SPEC_HASH = '1c5dcd23d461' as const;
3
+ export const SPEC_HASH_FULL = '1c5dcd23d46109024a008dea6440892f9a1ccd0b725fc6e0ed0bb3abe28bf78d' as const;
@@ -3962,6 +3962,12 @@ export interface components {
3962
3962
  /** Format: uuid */
3963
3963
  positionId: string;
3964
3964
  title: string;
3965
+ } | {
3966
+ /** @constant */
3967
+ kind: "reporting.setManagerBulk";
3968
+ reportPositionIds: string[];
3969
+ /** Format: uuid */
3970
+ managerPositionId: string;
3965
3971
  };
3966
3972
  MoveApplyRequest: {
3967
3973
  mutations: ({
@@ -62,6 +62,24 @@ describe("EMAIL_KINDS golden snapshot", () => {
62
62
  plainTextRequired: true,
63
63
  htmlSupported: true,
64
64
  },
65
+ "companyMd.access_requested": {
66
+ kind: "companyMd.access_requested",
67
+ subject: "Someone requested access to a document",
68
+ plainTextRequired: true,
69
+ htmlSupported: true,
70
+ },
71
+ "companyMd.access_request_approved": {
72
+ kind: "companyMd.access_request_approved",
73
+ subject: "Your access request was approved",
74
+ plainTextRequired: true,
75
+ htmlSupported: true,
76
+ },
77
+ "companyMd.access_request_denied": {
78
+ kind: "companyMd.access_request_denied",
79
+ subject: "Your access request was reviewed",
80
+ plainTextRequired: true,
81
+ htmlSupported: true,
82
+ },
65
83
  });
66
84
  });
67
85
  });
@@ -106,6 +106,55 @@ describe("OrgIntentSchema", () => {
106
106
  }).success,
107
107
  ).toBe(false);
108
108
  });
109
+
110
+ it("accepts a reporting.setManagerBulk intent (N seats -> one manager)", () => {
111
+ const intent = {
112
+ kind: "reporting.setManagerBulk" as const,
113
+ reportPositionIds: [REPORT, POSITION],
114
+ managerPositionId: MANAGER,
115
+ };
116
+ expect(OrgIntentSchema.parse(intent)).toEqual(intent);
117
+ });
118
+
119
+ it("rejects an empty bulk reportPositionIds array", () => {
120
+ expect(
121
+ OrgIntentSchema.safeParse({
122
+ kind: "reporting.setManagerBulk",
123
+ reportPositionIds: [],
124
+ managerPositionId: MANAGER,
125
+ }).success,
126
+ ).toBe(false);
127
+ });
128
+
129
+ it("rejects a bulk array beyond the 500-seat transport cap", () => {
130
+ expect(
131
+ OrgIntentSchema.safeParse({
132
+ kind: "reporting.setManagerBulk",
133
+ reportPositionIds: Array.from({ length: 501 }, () => REPORT),
134
+ managerPositionId: MANAGER,
135
+ }).success,
136
+ ).toBe(false);
137
+ });
138
+
139
+ it("rejects a non-uuid entry in the bulk report set", () => {
140
+ expect(
141
+ OrgIntentSchema.safeParse({
142
+ kind: "reporting.setManagerBulk",
143
+ reportPositionIds: [REPORT, "x"],
144
+ managerPositionId: MANAGER,
145
+ }).success,
146
+ ).toBe(false);
147
+ });
148
+
149
+ it("rejects a null bulk managerPositionId (intents always set a manager)", () => {
150
+ expect(
151
+ OrgIntentSchema.safeParse({
152
+ kind: "reporting.setManagerBulk",
153
+ reportPositionIds: [REPORT],
154
+ managerPositionId: null,
155
+ }).success,
156
+ ).toBe(false);
157
+ });
109
158
  });
110
159
 
111
160
  describe("FactMutationSchema", () => {
@@ -436,4 +485,23 @@ describe("TransformationPreviewSchema", () => {
436
485
  false,
437
486
  );
438
487
  });
488
+
489
+ it("accepts a multi-headline preview carrying primaryMutations (bulk intent)", () => {
490
+ const second = { ...setManagerMutation, reportPositionId: POSITION };
491
+ expect(
492
+ TransformationPreviewSchema.safeParse({
493
+ ...preview,
494
+ primaryMutations: [setManagerMutation, second],
495
+ }).success,
496
+ ).toBe(true);
497
+ });
498
+
499
+ it("rejects a single-element primaryMutations (single moves omit the field)", () => {
500
+ expect(
501
+ TransformationPreviewSchema.safeParse({
502
+ ...preview,
503
+ primaryMutations: [setManagerMutation],
504
+ }).success,
505
+ ).toBe(false);
506
+ });
439
507
  });
@@ -95,6 +95,25 @@ export const OrgIntentSchema = z.discriminatedUnion("kind", [
95
95
  /** The new human-facing title for the seat (non-empty, matching PositionSchema.title). */
96
96
  title: z.string().min(1),
97
97
  }),
98
+ // reporting.setManagerBulk — N reporting seats re-pointed at ONE manager as a
99
+ // single atomic intent (the org-chart cluster-pill drop). The engine expands
100
+ // it into N `reporting.setManager` FactMutations — the existing
101
+ // Intent-vs-Mutation asymmetry; no bulk mutation kind exists or is needed.
102
+ // Cross-field rules (manager ∉ reports, dedupe) are enforced at the route: a
103
+ // discriminatedUnion member cannot carry a ZodEffects refinement.
104
+ z.object({
105
+ kind: z.literal("reporting.setManagerBulk"),
106
+ /**
107
+ * The reporting seats being re-pointed together (e.g. a unit cluster's
108
+ * direct members; their subtrees follow implicitly). Order-insensitive;
109
+ * the engine treats the set as one atomic intent. The cap mirrors the
110
+ * bulk-reparent transport bound (ADR-BE-318).
111
+ */
112
+ reportPositionIds: z.array(z.string().uuid()).min(1).max(500),
113
+ /** The ONE manager seat every report re-points to. Non-null on an intent
114
+ * (un-setting is a mutation concern, exactly as on `reporting.setManager`). */
115
+ managerPositionId: z.string().uuid(),
116
+ }),
98
117
  ]);
99
118
  export type OrgIntent = z.infer<typeof OrgIntentSchema>;
100
119
 
@@ -336,6 +355,15 @@ export const TransformationPreviewSchema = z.object({
336
355
  intentLabel: z.string().min(1),
337
356
  /** The headline fact change the preview is centered on. */
338
357
  primary: FactMutationSchema,
358
+ /**
359
+ * Present only when the intent expands into MORE THAN ONE headline mutation
360
+ * (e.g. `reporting.setManagerBulk`): the full primary bundle, of which
361
+ * `primary` is the first element. Absent on single-mutation previews so
362
+ * existing consumers and goldens see byte-identical output. These are the
363
+ * INTENT's own edges — engine repair splices stay in the strategies'
364
+ * recommendations, never here.
365
+ */
366
+ primaryMutations: z.array(FactMutationSchema).min(2).optional(),
339
367
  /** The strategy the engine recommends by default. */
340
368
  defaultStrategy: TransformStrategySchema,
341
369
  /** Other viable strategies the operator may pick instead. */