@company-semantics/contracts 51.2.0 → 52.0.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,3 +1,3 @@
|
|
|
1
1
|
// AUTO-GENERATED — do not edit. Run pnpm generate:spec-hash to regenerate.
|
|
2
|
-
export const SPEC_HASH = '
|
|
3
|
-
export const SPEC_HASH_FULL = '
|
|
2
|
+
export const SPEC_HASH = 'd0171aedf623' as const;
|
|
3
|
+
export const SPEC_HASH_FULL = 'd0171aedf623604dc721fb42b626ebc019afcc2fda9be59e1f06360cd6a4fcca' as const;
|
package/src/api/generated.ts
CHANGED
|
@@ -3616,6 +3616,23 @@ export interface paths {
|
|
|
3616
3616
|
patch?: never;
|
|
3617
3617
|
trace?: never;
|
|
3618
3618
|
};
|
|
3619
|
+
"/api/comments/threads/{threadId}/accept-apply": {
|
|
3620
|
+
parameters: {
|
|
3621
|
+
query?: never;
|
|
3622
|
+
header?: never;
|
|
3623
|
+
path?: never;
|
|
3624
|
+
cookie?: never;
|
|
3625
|
+
};
|
|
3626
|
+
get?: never;
|
|
3627
|
+
put?: never;
|
|
3628
|
+
/** Apply a claimed suggestion and record the accept, on one commit */
|
|
3629
|
+
post: operations["acceptSuggestionApply"];
|
|
3630
|
+
delete?: never;
|
|
3631
|
+
options?: never;
|
|
3632
|
+
head?: never;
|
|
3633
|
+
patch?: never;
|
|
3634
|
+
trace?: never;
|
|
3635
|
+
};
|
|
3619
3636
|
"/api/comments/threads/{threadId}/accept-release": {
|
|
3620
3637
|
parameters: {
|
|
3621
3638
|
query?: never;
|
|
@@ -6542,6 +6559,15 @@ export interface components {
|
|
|
6542
6559
|
SuggestionClaimRequest: {
|
|
6543
6560
|
claimToken: string;
|
|
6544
6561
|
};
|
|
6562
|
+
/** @description The accepted thread and the document mutation that landed with it, on one commit. */
|
|
6563
|
+
SuggestionAcceptAppliedResponse: {
|
|
6564
|
+
thread: components["schemas"]["CommentThreadSummary"];
|
|
6565
|
+
applied: components["schemas"]["SuggestionApplied"];
|
|
6566
|
+
};
|
|
6567
|
+
SuggestionApplyRequest: {
|
|
6568
|
+
claimToken: string;
|
|
6569
|
+
expectedRevision: string;
|
|
6570
|
+
};
|
|
6545
6571
|
/** @description Server-enforced collaboration size limits, published so clients can pre-check. */
|
|
6546
6572
|
CollabSyncLimits: {
|
|
6547
6573
|
maxUpdateBytes: number;
|
|
@@ -6712,6 +6738,17 @@ export interface components {
|
|
|
6712
6738
|
createdAt: string;
|
|
6713
6739
|
updatedAt: string;
|
|
6714
6740
|
};
|
|
6741
|
+
/** @description What the accept-apply did to the document: whether there was a CRDT to write into at all, and the canonical edit that was spliced. */
|
|
6742
|
+
SuggestionApplied: {
|
|
6743
|
+
bridged: boolean;
|
|
6744
|
+
edit: components["schemas"]["SuggestionPlannedEdit"];
|
|
6745
|
+
};
|
|
6746
|
+
/** @description The canonical mutation derived from the stored payload: splice out deleteLength UTF-16 code units at `at` and insert `insert`. */
|
|
6747
|
+
SuggestionPlannedEdit: {
|
|
6748
|
+
at: number;
|
|
6749
|
+
deleteLength: number;
|
|
6750
|
+
insert: string;
|
|
6751
|
+
};
|
|
6715
6752
|
};
|
|
6716
6753
|
responses: never;
|
|
6717
6754
|
parameters: never;
|
|
@@ -12979,6 +13016,53 @@ export interface operations {
|
|
|
12979
13016
|
};
|
|
12980
13017
|
};
|
|
12981
13018
|
};
|
|
13019
|
+
acceptSuggestionApply: {
|
|
13020
|
+
parameters: {
|
|
13021
|
+
query?: never;
|
|
13022
|
+
header?: never;
|
|
13023
|
+
path: {
|
|
13024
|
+
threadId: string;
|
|
13025
|
+
};
|
|
13026
|
+
cookie?: never;
|
|
13027
|
+
};
|
|
13028
|
+
requestBody: {
|
|
13029
|
+
content: {
|
|
13030
|
+
"application/json": components["schemas"]["SuggestionApplyRequest"];
|
|
13031
|
+
};
|
|
13032
|
+
};
|
|
13033
|
+
responses: {
|
|
13034
|
+
/** @description Suggestion applied and accepted: the canonical edit landed in the document and the thread was resolved on the SAME transaction */
|
|
13035
|
+
200: {
|
|
13036
|
+
headers: {
|
|
13037
|
+
[name: string]: unknown;
|
|
13038
|
+
};
|
|
13039
|
+
content: {
|
|
13040
|
+
"application/json": components["schemas"]["SuggestionAcceptAppliedResponse"];
|
|
13041
|
+
};
|
|
13042
|
+
};
|
|
13043
|
+
/** @description Malformed claim token or expectedRevision */
|
|
13044
|
+
400: {
|
|
13045
|
+
headers: {
|
|
13046
|
+
[name: string]: unknown;
|
|
13047
|
+
};
|
|
13048
|
+
content?: never;
|
|
13049
|
+
};
|
|
13050
|
+
/** @description Thread not found, or the caller may not read its subject */
|
|
13051
|
+
404: {
|
|
13052
|
+
headers: {
|
|
13053
|
+
[name: string]: unknown;
|
|
13054
|
+
};
|
|
13055
|
+
content?: never;
|
|
13056
|
+
};
|
|
13057
|
+
/** @description Terminal, never retry: not a suggestion thread, the token does not match a live claim, the document moved past expectedRevision, the anchor is orphaned or no longer reads, or the payload resolves to a no-op — re-read the document and decide again */
|
|
13058
|
+
409: {
|
|
13059
|
+
headers: {
|
|
13060
|
+
[name: string]: unknown;
|
|
13061
|
+
};
|
|
13062
|
+
content?: never;
|
|
13063
|
+
};
|
|
13064
|
+
};
|
|
13065
|
+
};
|
|
12982
13066
|
releaseSuggestionClaim: {
|
|
12983
13067
|
parameters: {
|
|
12984
13068
|
query?: never;
|
|
@@ -23,6 +23,7 @@ export const openApiRoutes = {
|
|
|
23
23
|
'/api/chats/{id}/pin': ['DELETE', 'POST'],
|
|
24
24
|
'/api/comments': ['GET'],
|
|
25
25
|
'/api/comments/threads': ['POST'],
|
|
26
|
+
'/api/comments/threads/{threadId}/accept-apply': ['POST'],
|
|
26
27
|
'/api/comments/threads/{threadId}/accept-complete': ['POST'],
|
|
27
28
|
'/api/comments/threads/{threadId}/accept-intent': ['POST'],
|
|
28
29
|
'/api/comments/threads/{threadId}/accept-release': ['POST'],
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
PeopleOrgChartSeatOccupantSchema,
|
|
5
|
+
PeopleOrgChartSeatSchema,
|
|
6
|
+
} from "../people-org-chart.js";
|
|
7
|
+
|
|
8
|
+
const PERSON_ID = "3f2504e0-4f89-41d3-9a0c-0305e82c3301";
|
|
9
|
+
const USER_ID = "9c5b94b1-35ad-49bb-b118-8e8fc24abf80";
|
|
10
|
+
const UNIT_ID = "6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b";
|
|
11
|
+
const POSITION_ID = "11111111-1111-4111-8111-111111111111";
|
|
12
|
+
|
|
13
|
+
describe("PeopleOrgChartSeatOccupantSchema", () => {
|
|
14
|
+
const accountless = {
|
|
15
|
+
personId: PERSON_ID,
|
|
16
|
+
userId: null,
|
|
17
|
+
fullName: "Ada Lovelace",
|
|
18
|
+
avatarUrl: null,
|
|
19
|
+
primaryUnitId: null,
|
|
20
|
+
ownedUnits: [],
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
it("parses an accountless occupant keyed by personId", () => {
|
|
24
|
+
const occupant = PeopleOrgChartSeatOccupantSchema.parse(accountless);
|
|
25
|
+
expect(occupant.personId).toBe(PERSON_ID);
|
|
26
|
+
expect(occupant.userId).toBeNull();
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("parses an account-linked occupant carrying a uuid userId", () => {
|
|
30
|
+
const occupant = PeopleOrgChartSeatOccupantSchema.parse({
|
|
31
|
+
...accountless,
|
|
32
|
+
userId: USER_ID,
|
|
33
|
+
});
|
|
34
|
+
expect(occupant.userId).toBe(USER_ID);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("requires personId", () => {
|
|
38
|
+
const { personId: _omitted, ...withoutPersonId } = accountless;
|
|
39
|
+
expect(() =>
|
|
40
|
+
PeopleOrgChartSeatOccupantSchema.parse(withoutPersonId),
|
|
41
|
+
).toThrow();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// userId is .nullable() WITHOUT .optional(): the server always emits the key,
|
|
45
|
+
// so an absent userId must be unrepresentable rather than silently null.
|
|
46
|
+
it("rejects an absent userId — nullable is not optional", () => {
|
|
47
|
+
const { userId: _omitted, ...withoutUserId } = accountless;
|
|
48
|
+
const result = PeopleOrgChartSeatOccupantSchema.safeParse(withoutUserId);
|
|
49
|
+
expect(result.success).toBe(false);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
describe("PeopleOrgChartSeatSchema", () => {
|
|
54
|
+
it("admits a filled seat whose only occupant is accountless", () => {
|
|
55
|
+
const seat = PeopleOrgChartSeatSchema.parse({
|
|
56
|
+
id: POSITION_ID,
|
|
57
|
+
unitId: UNIT_ID,
|
|
58
|
+
title: "Analyst",
|
|
59
|
+
status: "filled",
|
|
60
|
+
hiring: false,
|
|
61
|
+
occupants: [
|
|
62
|
+
{
|
|
63
|
+
personId: PERSON_ID,
|
|
64
|
+
userId: null,
|
|
65
|
+
fullName: "Ada Lovelace",
|
|
66
|
+
avatarUrl: null,
|
|
67
|
+
primaryUnitId: null,
|
|
68
|
+
ownedUnits: [],
|
|
69
|
+
},
|
|
70
|
+
],
|
|
71
|
+
});
|
|
72
|
+
expect(seat.occupants).toHaveLength(1);
|
|
73
|
+
expect(seat.occupants[0]?.userId).toBeNull();
|
|
74
|
+
});
|
|
75
|
+
});
|
|
@@ -88,11 +88,30 @@ export type PeopleOrgChartSeatStatus = z.infer<
|
|
|
88
88
|
typeof PeopleOrgChartSeatStatusSchema
|
|
89
89
|
>;
|
|
90
90
|
|
|
91
|
-
// Person-scoped attributes of a seat's holder —
|
|
92
|
-
//
|
|
93
|
-
//
|
|
91
|
+
// Person-scoped attributes of a seat's holder — they travel with the person
|
|
92
|
+
// across seats (ADR-BE-329: a vacant seat grants none of these by
|
|
93
|
+
// construction).
|
|
94
|
+
//
|
|
95
|
+
// KEYED BY personId. The org chart is a graph of POSITIONS with PEOPLE
|
|
96
|
+
// projected onto them; the account link is an attribute of the person, never
|
|
97
|
+
// their identity. `userId` is the 0..1 account link and is null for the many
|
|
98
|
+
// people who never sign in (an HRIS import is the normal case, not the edge).
|
|
99
|
+
//
|
|
100
|
+
// For an ACCOUNTLESS occupant each of the following is a FACT, not a fallback:
|
|
101
|
+
// avatarUrl always null -- `persons` carries no avatar column
|
|
102
|
+
// primaryUnitId always null -- `home_assignments` is user-keyed, so there is
|
|
103
|
+
// no representable home; null means "no home
|
|
104
|
+
// row", NOT "home unknown, substitute the seat"
|
|
105
|
+
// ownedUnits always [] -- the projection of "no grant row exists".
|
|
106
|
+
// Authority is account-keyed; an accountless
|
|
107
|
+
// person holds none. This is the authority
|
|
108
|
+
// boundary made visible.
|
|
94
109
|
export const PeopleOrgChartSeatOccupantSchema = z.object({
|
|
95
|
-
|
|
110
|
+
personId: z.string().uuid(),
|
|
111
|
+
// .nullable() WITHOUT .optional(): this is a server-generated response, so
|
|
112
|
+
// `undefined` must be unrepresentable. PersonSchema.userId is
|
|
113
|
+
// .nullable().optional() because it is an input-shaped vocabulary.
|
|
114
|
+
userId: z.string().uuid().nullable(),
|
|
96
115
|
fullName: z.string(),
|
|
97
116
|
avatarUrl: z.string().nullable(),
|
|
98
117
|
// Stable HOME unit (home_assignments), not the seat unit — mirrors the legacy
|
|
@@ -123,8 +142,8 @@ export const PeopleOrgChartSeatSchema = z.object({
|
|
|
123
142
|
// fulfillment row ⇒ false.
|
|
124
143
|
hiring: z.boolean(),
|
|
125
144
|
// The seat's current holders. [] ⇒ vacant (the old "open role"); >= 1 ⇒
|
|
126
|
-
// occupied (the old "member").
|
|
127
|
-
//
|
|
145
|
+
// occupied (the old "member"). Every canonical occupant appears, account or
|
|
146
|
+
// not — occupancy, not account linkage, is what admits a person here.
|
|
128
147
|
occupants: z.array(PeopleOrgChartSeatOccupantSchema),
|
|
129
148
|
});
|
|
130
149
|
|