@company-semantics/contracts 58.5.1 → 59.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 +8 -3
- package/src/api/generated-spec-hash.ts +2 -2
- package/src/api/generated.ts +3 -3
- package/src/decisions/README.md +41 -0
- package/src/decisions/__tests__/README.md +37 -0
- package/src/decisions/__tests__/schemas.test.ts +146 -0
- package/src/decisions/index.ts +32 -0
- package/src/decisions/schemas.ts +107 -0
- package/src/decisions/types.ts +192 -0
- package/src/execution/__tests__/registry.test.ts +21 -0
- package/src/execution/kinds.ts +4 -0
- package/src/execution/registry.ts +23 -0
- package/src/index.ts +6 -0
- package/src/integrations/README.md +2 -0
- package/src/integrations/index.ts +10 -2
- package/src/integrations/schemas.ts +87 -0
- package/src/message-parts/__tests__/confirmation.test.ts +1 -0
- package/src/message-parts/confirmation.ts +1 -0
- package/src/org/README.md +3 -1
- package/src/org/__tests__/structure-inference.test.ts +70 -2
- package/src/org/index.ts +1 -0
- package/src/org/structure-inference.ts +36 -16
- package/src/resource-key-tables.ts +191 -0
- package/src/resource-keys.ts +12 -176
package/src/resource-keys.ts
CHANGED
|
@@ -25,184 +25,20 @@ export function resolveScope(context: {
|
|
|
25
25
|
return { orgId: context.impersonatedOrgId ?? context.orgId };
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
/*
|
|
29
|
-
* ---------------------------------------------------------------------------
|
|
30
|
-
* fromQueryKey's routing tables, and the drift detector over them.
|
|
31
|
-
* ---------------------------------------------------------------------------
|
|
32
|
-
*
|
|
33
|
-
* `toQueryKey` has always been safe: its switch is exhaustive and its `never`
|
|
34
|
-
* guard makes a new union member a compile error. `fromQueryKey` was not. Its
|
|
35
|
-
* five lookup tables are hand-maintained, and a member missing from all of them
|
|
36
|
-
* fell through to a RUNTIME `throw` — which `matchesResourceKey` catches and
|
|
37
|
-
* turns into "matches nothing", and which `useResource` turns into a query that
|
|
38
|
-
* never fetches. Silent in both directions (ADR-CONTRACTS-119).
|
|
39
|
-
*
|
|
40
|
-
* Two mechanisms, and BOTH are needed:
|
|
41
|
-
*
|
|
42
|
-
* `satisfies` on each table catches a WRONG entry — a typo, or a literal
|
|
43
|
-
* parked under the wrong scope. It cannot catch an entry that is simply
|
|
44
|
-
* absent, because an array is free to be a subset of its element type.
|
|
45
|
-
*
|
|
46
|
-
* `_EveryResourceKeyIsRouted` below catches the ABSENT entry, which is the
|
|
47
|
-
* failure that actually shipped. It is the half that closes the hole.
|
|
48
|
-
*/
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* The identity segments a member carries — every field that is neither the type
|
|
52
|
-
* tag nor a scope discriminator. `member` → `"memberId"`; `commentThreads` →
|
|
53
|
-
* `"subjectType" | "subjectId"`; a scope-only key → `never`.
|
|
54
|
-
*/
|
|
55
|
-
type IdentityFieldsOf<T extends ResourceKey["type"]> = Exclude<
|
|
56
|
-
keyof Extract<ResourceKey, { type: T }>,
|
|
57
|
-
"type" | "orgId" | "userId" | "scope"
|
|
58
|
-
>;
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Type literals whose whole shape is the tag plus one scope discriminator —
|
|
62
|
-
* i.e. the members that belong in a scope ARRAY rather than an identity MAP.
|
|
63
|
-
* Distributes over the union (`K` is a naked type parameter).
|
|
64
|
-
*/
|
|
65
|
-
type ScopeOnlyType<K = ResourceKey> = K extends {
|
|
66
|
-
type: infer T extends ResourceKey["type"];
|
|
67
|
-
}
|
|
68
|
-
? [IdentityFieldsOf<T>] extends [never]
|
|
69
|
-
? T
|
|
70
|
-
: never
|
|
71
|
-
: never;
|
|
72
|
-
|
|
73
|
-
type OrgScopedType = Extract<
|
|
74
|
-
ScopeOnlyType,
|
|
75
|
-
Extract<ResourceKey, { orgId: string }>["type"]
|
|
76
|
-
>;
|
|
77
|
-
type UserScopedType = Extract<
|
|
78
|
-
ScopeOnlyType,
|
|
79
|
-
Extract<ResourceKey, { userId: string }>["type"]
|
|
80
|
-
>;
|
|
81
|
-
type SystemScopedType = Extract<
|
|
82
|
-
ScopeOnlyType,
|
|
83
|
-
Extract<ResourceKey, { scope: "system" }>["type"]
|
|
84
|
-
>;
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Identities with a single extra segment. The `satisfies` checks the FIELD NAME
|
|
88
|
-
* against that member's own keys, so renaming `memberId` in the union — or
|
|
89
|
-
* pointing a key at a field it does not have — fails to compile here.
|
|
90
|
-
*/
|
|
91
|
-
const IDENTITY_FIELDS = {
|
|
92
|
-
member: "memberId",
|
|
93
|
-
team: "teamId",
|
|
94
|
-
department: "departmentId",
|
|
95
|
-
chat: "chatId",
|
|
96
|
-
companyMdDoc: "slug",
|
|
97
|
-
companyMdContextBank: "slug",
|
|
98
|
-
companyMdAccessRequests: "docId",
|
|
99
|
-
companyMdDocHistory: "docId",
|
|
100
|
-
orgUnit: "unitId",
|
|
101
|
-
orgUnitChildren: "unitId",
|
|
102
|
-
orgUnitAncestors: "unitId",
|
|
103
|
-
orgUnitMemberships: "unitId",
|
|
104
|
-
orgUnitPermissions: "unitId",
|
|
105
|
-
orgUnitOpenRoles: "unitId",
|
|
106
|
-
orgUnitMyAuthority: "unitId",
|
|
107
|
-
} as const satisfies { [T in ResourceKey["type"]]?: IdentityFieldsOf<T> };
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Identities with a COMPOSITE (multi-segment) identity. Checked before
|
|
111
|
-
* {@link IDENTITY_FIELDS}, which hard-asserts a two-element `rest` and would
|
|
112
|
-
* otherwise reject these.
|
|
113
|
-
*
|
|
114
|
-
* A map of its own rather than widening `IDENTITY_FIELDS` to `string | string[]`:
|
|
115
|
-
* the single-segment case is every other key in the union, and making it pay for
|
|
116
|
-
* this one would put a branch in the hot path for no reader's benefit.
|
|
117
|
-
*/
|
|
118
|
-
const COMPOSITE_IDENTITY_FIELDS = {
|
|
119
|
-
commentThreads: ["subjectType", "subjectId"],
|
|
120
|
-
companyMdDocVersion: ["docId", "versionId"],
|
|
121
|
-
} as const satisfies {
|
|
122
|
-
[T in ResourceKey["type"]]?: readonly IdentityFieldsOf<T>[];
|
|
123
|
-
};
|
|
124
|
-
|
|
125
|
-
const ORG_SCOPED_TYPES = [
|
|
126
|
-
"members",
|
|
127
|
-
"departments",
|
|
128
|
-
"chats",
|
|
129
|
-
"teams",
|
|
130
|
-
"integrations",
|
|
131
|
-
"invites",
|
|
132
|
-
"orgDirectory",
|
|
133
|
-
"auditEvents",
|
|
134
|
-
"timeline",
|
|
135
|
-
"workspace",
|
|
136
|
-
"workspaceDomains",
|
|
137
|
-
"authSettings",
|
|
138
|
-
"billing",
|
|
139
|
-
"aiUsage",
|
|
140
|
-
"deletionEligibility",
|
|
141
|
-
"transferOwnership",
|
|
142
|
-
"companyMdDocs",
|
|
143
|
-
"directGrants",
|
|
144
|
-
"orgTree",
|
|
145
|
-
"orgLevelConfig",
|
|
146
|
-
"peopleOrgChart",
|
|
147
|
-
"orgUnitOwners",
|
|
148
|
-
"actionItems",
|
|
149
|
-
"feed",
|
|
150
|
-
"orgSystemEvents",
|
|
151
|
-
] as const satisfies readonly OrgScopedType[];
|
|
152
|
-
|
|
153
|
-
const USER_SCOPED_TYPES = [
|
|
154
|
-
"dismissedBanners",
|
|
155
|
-
"userOrgs",
|
|
156
|
-
"sessions",
|
|
157
|
-
"userMd",
|
|
158
|
-
"viewer",
|
|
159
|
-
] as const satisfies readonly UserScopedType[];
|
|
160
|
-
|
|
161
28
|
/**
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
|
|
166
|
-
const SYSTEM_SCOPED_TYPES = [
|
|
167
|
-
"internalAdminAiProviders",
|
|
168
|
-
"internalAdminPrompts",
|
|
169
|
-
"internalAdminAiRuntimeDefaults",
|
|
170
|
-
"factoryFloor",
|
|
171
|
-
"factorySnapshot",
|
|
172
|
-
"factoryKpis",
|
|
173
|
-
] as const satisfies readonly SystemScopedType[];
|
|
174
|
-
|
|
175
|
-
/** Every literal `fromQueryKey` can route, across all five tables. */
|
|
176
|
-
type RoutedType =
|
|
177
|
-
| keyof typeof IDENTITY_FIELDS
|
|
178
|
-
| keyof typeof COMPOSITE_IDENTITY_FIELDS
|
|
179
|
-
| (typeof ORG_SCOPED_TYPES)[number]
|
|
180
|
-
| (typeof USER_SCOPED_TYPES)[number]
|
|
181
|
-
| (typeof SYSTEM_SCOPED_TYPES)[number];
|
|
182
|
-
|
|
183
|
-
type Assert<T extends true> = T;
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* THE DRIFT DETECTOR. Register a union member and forget its routing table and
|
|
187
|
-
* this fails to compile — instead of shipping a key that parses nowhere,
|
|
188
|
-
* matches nothing, and disables the query that reads it.
|
|
189
|
-
*
|
|
190
|
-
* The false branch resolves to the UNROUTED LITERALS rather than to `false`, so
|
|
191
|
-
* the diagnostic names the culprit:
|
|
192
|
-
* `Type '"directGrants"' does not satisfy the constraint 'true'`.
|
|
193
|
-
*
|
|
194
|
-
* EXPORTED, though nothing consumes it. This package ships `src`, so every
|
|
195
|
-
* consumer typechecks this file under ITS OWN compiler options — and the
|
|
196
|
-
* backend sets `noUnusedLocals`, which rejects an unexported type alias that
|
|
197
|
-
* nothing references. Keeping it private broke `tsc` in a consumer while
|
|
198
|
-
* passing here, so the export is what makes the assertion portable, not a
|
|
199
|
-
* widening of the public vocabulary. Do not "tidy" it away.
|
|
29
|
+
* The routing tables `fromQueryKey` reads, and the drift detector over them,
|
|
30
|
+
* live in `resource-key-tables.ts`. `RoutingExhaustivenessWitness` is
|
|
31
|
+
* re-exported so its import path is unchanged — see the note on its definition
|
|
32
|
+
* for why it is exported at all.
|
|
200
33
|
*/
|
|
201
|
-
export type RoutingExhaustivenessWitness
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
34
|
+
export type { RoutingExhaustivenessWitness } from "./resource-key-tables";
|
|
35
|
+
import {
|
|
36
|
+
IDENTITY_FIELDS,
|
|
37
|
+
COMPOSITE_IDENTITY_FIELDS,
|
|
38
|
+
ORG_SCOPED_TYPES,
|
|
39
|
+
USER_SCOPED_TYPES,
|
|
40
|
+
SYSTEM_SCOPED_TYPES,
|
|
41
|
+
} from "./resource-key-tables";
|
|
206
42
|
|
|
207
43
|
/**
|
|
208
44
|
* Canonical ResourceKey → query key conversion.
|