@company-semantics/contracts 0.145.0 → 0.147.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 +1 -1
- package/src/api/generated-spec-hash.ts +2 -2
- package/src/api/generated.ts +709 -1
- package/src/org/__tests__/org-units.test.ts +202 -0
- package/src/org/index.ts +50 -0
- package/src/org/org-units.ts +66 -0
- package/src/org/schemas.ts +152 -0
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 = '390e7649da58' as const;
|
|
3
|
+
export const SPEC_HASH_FULL = '390e7649da58e32271a1ad703703bc9d71ef0ec0c66c0918fc6fbd65a385d0d0' as const;
|
package/src/api/generated.ts
CHANGED
|
@@ -1627,6 +1627,178 @@ export interface paths {
|
|
|
1627
1627
|
patch?: never;
|
|
1628
1628
|
trace?: never;
|
|
1629
1629
|
};
|
|
1630
|
+
"/api/org-units": {
|
|
1631
|
+
parameters: {
|
|
1632
|
+
query?: never;
|
|
1633
|
+
header?: never;
|
|
1634
|
+
path?: never;
|
|
1635
|
+
cookie?: never;
|
|
1636
|
+
};
|
|
1637
|
+
get?: never;
|
|
1638
|
+
put?: never;
|
|
1639
|
+
/** Create an org unit */
|
|
1640
|
+
post: operations["createOrgUnit"];
|
|
1641
|
+
delete?: never;
|
|
1642
|
+
options?: never;
|
|
1643
|
+
head?: never;
|
|
1644
|
+
patch?: never;
|
|
1645
|
+
trace?: never;
|
|
1646
|
+
};
|
|
1647
|
+
"/api/org-units/{unitId}": {
|
|
1648
|
+
parameters: {
|
|
1649
|
+
query?: never;
|
|
1650
|
+
header?: never;
|
|
1651
|
+
path?: never;
|
|
1652
|
+
cookie?: never;
|
|
1653
|
+
};
|
|
1654
|
+
/** Get an org unit */
|
|
1655
|
+
get: operations["getOrgUnit"];
|
|
1656
|
+
put?: never;
|
|
1657
|
+
post?: never;
|
|
1658
|
+
delete?: never;
|
|
1659
|
+
options?: never;
|
|
1660
|
+
head?: never;
|
|
1661
|
+
patch?: never;
|
|
1662
|
+
trace?: never;
|
|
1663
|
+
};
|
|
1664
|
+
"/api/org-units/{unitId}/children": {
|
|
1665
|
+
parameters: {
|
|
1666
|
+
query?: never;
|
|
1667
|
+
header?: never;
|
|
1668
|
+
path?: never;
|
|
1669
|
+
cookie?: never;
|
|
1670
|
+
};
|
|
1671
|
+
/** List direct children of an org unit */
|
|
1672
|
+
get: operations["listOrgUnitChildren"];
|
|
1673
|
+
put?: never;
|
|
1674
|
+
post?: never;
|
|
1675
|
+
delete?: never;
|
|
1676
|
+
options?: never;
|
|
1677
|
+
head?: never;
|
|
1678
|
+
patch?: never;
|
|
1679
|
+
trace?: never;
|
|
1680
|
+
};
|
|
1681
|
+
"/api/org-units/{unitId}/descendants": {
|
|
1682
|
+
parameters: {
|
|
1683
|
+
query?: never;
|
|
1684
|
+
header?: never;
|
|
1685
|
+
path?: never;
|
|
1686
|
+
cookie?: never;
|
|
1687
|
+
};
|
|
1688
|
+
/** List descendants of an org unit (subtree) */
|
|
1689
|
+
get: operations["listOrgUnitDescendants"];
|
|
1690
|
+
put?: never;
|
|
1691
|
+
post?: never;
|
|
1692
|
+
delete?: never;
|
|
1693
|
+
options?: never;
|
|
1694
|
+
head?: never;
|
|
1695
|
+
patch?: never;
|
|
1696
|
+
trace?: never;
|
|
1697
|
+
};
|
|
1698
|
+
"/api/org-units/{unitId}/ancestors": {
|
|
1699
|
+
parameters: {
|
|
1700
|
+
query?: never;
|
|
1701
|
+
header?: never;
|
|
1702
|
+
path?: never;
|
|
1703
|
+
cookie?: never;
|
|
1704
|
+
};
|
|
1705
|
+
/** List ancestors of an org unit */
|
|
1706
|
+
get: operations["listOrgUnitAncestors"];
|
|
1707
|
+
put?: never;
|
|
1708
|
+
post?: never;
|
|
1709
|
+
delete?: never;
|
|
1710
|
+
options?: never;
|
|
1711
|
+
head?: never;
|
|
1712
|
+
patch?: never;
|
|
1713
|
+
trace?: never;
|
|
1714
|
+
};
|
|
1715
|
+
"/api/org-units/{unitId}/reparent": {
|
|
1716
|
+
parameters: {
|
|
1717
|
+
query?: never;
|
|
1718
|
+
header?: never;
|
|
1719
|
+
path?: never;
|
|
1720
|
+
cookie?: never;
|
|
1721
|
+
};
|
|
1722
|
+
get?: never;
|
|
1723
|
+
put?: never;
|
|
1724
|
+
/** Reparent an org unit (moves the whole subtree) */
|
|
1725
|
+
post: operations["reparentOrgUnit"];
|
|
1726
|
+
delete?: never;
|
|
1727
|
+
options?: never;
|
|
1728
|
+
head?: never;
|
|
1729
|
+
patch?: never;
|
|
1730
|
+
trace?: never;
|
|
1731
|
+
};
|
|
1732
|
+
"/api/org-units/{unitId}/archive": {
|
|
1733
|
+
parameters: {
|
|
1734
|
+
query?: never;
|
|
1735
|
+
header?: never;
|
|
1736
|
+
path?: never;
|
|
1737
|
+
cookie?: never;
|
|
1738
|
+
};
|
|
1739
|
+
get?: never;
|
|
1740
|
+
put?: never;
|
|
1741
|
+
/** Archive an org unit (soft-delete) */
|
|
1742
|
+
post: operations["archiveOrgUnit"];
|
|
1743
|
+
delete?: never;
|
|
1744
|
+
options?: never;
|
|
1745
|
+
head?: never;
|
|
1746
|
+
patch?: never;
|
|
1747
|
+
trace?: never;
|
|
1748
|
+
};
|
|
1749
|
+
"/api/org-units/{unitId}/relationships": {
|
|
1750
|
+
parameters: {
|
|
1751
|
+
query?: never;
|
|
1752
|
+
header?: never;
|
|
1753
|
+
path?: never;
|
|
1754
|
+
cookie?: never;
|
|
1755
|
+
};
|
|
1756
|
+
/** List incoming + outgoing graph edges for an org unit */
|
|
1757
|
+
get: operations["listOrgUnitRelationships"];
|
|
1758
|
+
put?: never;
|
|
1759
|
+
/** Create a graph edge from this unit */
|
|
1760
|
+
post: operations["createOrgUnitRelationship"];
|
|
1761
|
+
delete?: never;
|
|
1762
|
+
options?: never;
|
|
1763
|
+
head?: never;
|
|
1764
|
+
patch?: never;
|
|
1765
|
+
trace?: never;
|
|
1766
|
+
};
|
|
1767
|
+
"/api/orgs/{orgId}/tree": {
|
|
1768
|
+
parameters: {
|
|
1769
|
+
query?: never;
|
|
1770
|
+
header?: never;
|
|
1771
|
+
path?: never;
|
|
1772
|
+
cookie?: never;
|
|
1773
|
+
};
|
|
1774
|
+
/** Get the org tree (path-ordered snapshot) with level labels */
|
|
1775
|
+
get: operations["getOrgTree"];
|
|
1776
|
+
put?: never;
|
|
1777
|
+
post?: never;
|
|
1778
|
+
delete?: never;
|
|
1779
|
+
options?: never;
|
|
1780
|
+
head?: never;
|
|
1781
|
+
patch?: never;
|
|
1782
|
+
trace?: never;
|
|
1783
|
+
};
|
|
1784
|
+
"/api/orgs/{orgId}/level-config": {
|
|
1785
|
+
parameters: {
|
|
1786
|
+
query?: never;
|
|
1787
|
+
header?: never;
|
|
1788
|
+
path?: never;
|
|
1789
|
+
cookie?: never;
|
|
1790
|
+
};
|
|
1791
|
+
/** List per-depth labels + allow_doc policy */
|
|
1792
|
+
get: operations["listOrgLevelConfig"];
|
|
1793
|
+
/** Replace per-depth labels + allow_doc policy */
|
|
1794
|
+
put: operations["upsertOrgLevelConfig"];
|
|
1795
|
+
post?: never;
|
|
1796
|
+
delete?: never;
|
|
1797
|
+
options?: never;
|
|
1798
|
+
head?: never;
|
|
1799
|
+
patch?: never;
|
|
1800
|
+
trace?: never;
|
|
1801
|
+
};
|
|
1630
1802
|
"/api/drive/files": {
|
|
1631
1803
|
parameters: {
|
|
1632
1804
|
query?: never;
|
|
@@ -2982,7 +3154,225 @@ export interface components {
|
|
|
2982
3154
|
role: "member" | "manager" | "owner";
|
|
2983
3155
|
joinedAt: string;
|
|
2984
3156
|
}[];
|
|
2985
|
-
orderKey: string;
|
|
3157
|
+
orderKey: string;
|
|
3158
|
+
};
|
|
3159
|
+
OrgUnitResponse: {
|
|
3160
|
+
unit: {
|
|
3161
|
+
/** Format: uuid */
|
|
3162
|
+
id: string;
|
|
3163
|
+
/** Format: uuid */
|
|
3164
|
+
orgId: string;
|
|
3165
|
+
parentId: string | null;
|
|
3166
|
+
slug: string;
|
|
3167
|
+
name: string;
|
|
3168
|
+
description: string | null;
|
|
3169
|
+
typeTag: string;
|
|
3170
|
+
classification: ("execution_unit" | "org_container" | "custom") | null;
|
|
3171
|
+
orderKey: string;
|
|
3172
|
+
path: string;
|
|
3173
|
+
/** @enum {string} */
|
|
3174
|
+
syncMode: "manual_only" | "synced_readonly" | "synced_with_overrides";
|
|
3175
|
+
visibilityDefault: ("public" | "private" | "restricted") | null;
|
|
3176
|
+
metadata: {
|
|
3177
|
+
[key: string]: unknown;
|
|
3178
|
+
};
|
|
3179
|
+
archivedAt: string | null;
|
|
3180
|
+
createdAt: string;
|
|
3181
|
+
updatedAt: string;
|
|
3182
|
+
};
|
|
3183
|
+
};
|
|
3184
|
+
OrgUnitChildrenResponse: {
|
|
3185
|
+
/** Format: uuid */
|
|
3186
|
+
parentId: string;
|
|
3187
|
+
children: {
|
|
3188
|
+
/** Format: uuid */
|
|
3189
|
+
id: string;
|
|
3190
|
+
/** Format: uuid */
|
|
3191
|
+
orgId: string;
|
|
3192
|
+
parentId: string | null;
|
|
3193
|
+
slug: string;
|
|
3194
|
+
name: string;
|
|
3195
|
+
description: string | null;
|
|
3196
|
+
typeTag: string;
|
|
3197
|
+
classification: ("execution_unit" | "org_container" | "custom") | null;
|
|
3198
|
+
orderKey: string;
|
|
3199
|
+
path: string;
|
|
3200
|
+
/** @enum {string} */
|
|
3201
|
+
syncMode: "manual_only" | "synced_readonly" | "synced_with_overrides";
|
|
3202
|
+
visibilityDefault: ("public" | "private" | "restricted") | null;
|
|
3203
|
+
metadata: {
|
|
3204
|
+
[key: string]: unknown;
|
|
3205
|
+
};
|
|
3206
|
+
archivedAt: string | null;
|
|
3207
|
+
createdAt: string;
|
|
3208
|
+
updatedAt: string;
|
|
3209
|
+
depth: number;
|
|
3210
|
+
hasChildren: boolean;
|
|
3211
|
+
memberCount: number;
|
|
3212
|
+
}[];
|
|
3213
|
+
};
|
|
3214
|
+
OrgUnitDescendantsResponse: {
|
|
3215
|
+
/** Format: uuid */
|
|
3216
|
+
rootId: string;
|
|
3217
|
+
descendants: {
|
|
3218
|
+
/** Format: uuid */
|
|
3219
|
+
id: string;
|
|
3220
|
+
/** Format: uuid */
|
|
3221
|
+
orgId: string;
|
|
3222
|
+
parentId: string | null;
|
|
3223
|
+
slug: string;
|
|
3224
|
+
name: string;
|
|
3225
|
+
description: string | null;
|
|
3226
|
+
typeTag: string;
|
|
3227
|
+
classification: ("execution_unit" | "org_container" | "custom") | null;
|
|
3228
|
+
orderKey: string;
|
|
3229
|
+
path: string;
|
|
3230
|
+
/** @enum {string} */
|
|
3231
|
+
syncMode: "manual_only" | "synced_readonly" | "synced_with_overrides";
|
|
3232
|
+
visibilityDefault: ("public" | "private" | "restricted") | null;
|
|
3233
|
+
metadata: {
|
|
3234
|
+
[key: string]: unknown;
|
|
3235
|
+
};
|
|
3236
|
+
archivedAt: string | null;
|
|
3237
|
+
createdAt: string;
|
|
3238
|
+
updatedAt: string;
|
|
3239
|
+
}[];
|
|
3240
|
+
};
|
|
3241
|
+
OrgUnitAncestorsResponse: {
|
|
3242
|
+
/** Format: uuid */
|
|
3243
|
+
unitId: string;
|
|
3244
|
+
ancestors: {
|
|
3245
|
+
/** Format: uuid */
|
|
3246
|
+
id: string;
|
|
3247
|
+
/** Format: uuid */
|
|
3248
|
+
orgId: string;
|
|
3249
|
+
parentId: string | null;
|
|
3250
|
+
slug: string;
|
|
3251
|
+
name: string;
|
|
3252
|
+
description: string | null;
|
|
3253
|
+
typeTag: string;
|
|
3254
|
+
classification: ("execution_unit" | "org_container" | "custom") | null;
|
|
3255
|
+
orderKey: string;
|
|
3256
|
+
path: string;
|
|
3257
|
+
/** @enum {string} */
|
|
3258
|
+
syncMode: "manual_only" | "synced_readonly" | "synced_with_overrides";
|
|
3259
|
+
visibilityDefault: ("public" | "private" | "restricted") | null;
|
|
3260
|
+
metadata: {
|
|
3261
|
+
[key: string]: unknown;
|
|
3262
|
+
};
|
|
3263
|
+
archivedAt: string | null;
|
|
3264
|
+
createdAt: string;
|
|
3265
|
+
updatedAt: string;
|
|
3266
|
+
}[];
|
|
3267
|
+
};
|
|
3268
|
+
OrgUnitRelationshipsResponse: {
|
|
3269
|
+
/** Format: uuid */
|
|
3270
|
+
unitId: string;
|
|
3271
|
+
incoming: {
|
|
3272
|
+
/** Format: uuid */
|
|
3273
|
+
id: string;
|
|
3274
|
+
/** Format: uuid */
|
|
3275
|
+
orgId: string;
|
|
3276
|
+
/** Format: uuid */
|
|
3277
|
+
fromUnit: string;
|
|
3278
|
+
/** Format: uuid */
|
|
3279
|
+
toUnit: string;
|
|
3280
|
+
/** @enum {string} */
|
|
3281
|
+
type: "collaborates_with" | "reports_to" | "depends_on" | "custom";
|
|
3282
|
+
/** @enum {string} */
|
|
3283
|
+
role: "owner" | "participant" | "supporting";
|
|
3284
|
+
contextKey: string | null;
|
|
3285
|
+
metadata: {
|
|
3286
|
+
[key: string]: unknown;
|
|
3287
|
+
};
|
|
3288
|
+
createdAt: string;
|
|
3289
|
+
}[];
|
|
3290
|
+
outgoing: {
|
|
3291
|
+
/** Format: uuid */
|
|
3292
|
+
id: string;
|
|
3293
|
+
/** Format: uuid */
|
|
3294
|
+
orgId: string;
|
|
3295
|
+
/** Format: uuid */
|
|
3296
|
+
fromUnit: string;
|
|
3297
|
+
/** Format: uuid */
|
|
3298
|
+
toUnit: string;
|
|
3299
|
+
/** @enum {string} */
|
|
3300
|
+
type: "collaborates_with" | "reports_to" | "depends_on" | "custom";
|
|
3301
|
+
/** @enum {string} */
|
|
3302
|
+
role: "owner" | "participant" | "supporting";
|
|
3303
|
+
contextKey: string | null;
|
|
3304
|
+
metadata: {
|
|
3305
|
+
[key: string]: unknown;
|
|
3306
|
+
};
|
|
3307
|
+
createdAt: string;
|
|
3308
|
+
}[];
|
|
3309
|
+
};
|
|
3310
|
+
OrgUnitRelationship: {
|
|
3311
|
+
/** Format: uuid */
|
|
3312
|
+
id: string;
|
|
3313
|
+
/** Format: uuid */
|
|
3314
|
+
orgId: string;
|
|
3315
|
+
/** Format: uuid */
|
|
3316
|
+
fromUnit: string;
|
|
3317
|
+
/** Format: uuid */
|
|
3318
|
+
toUnit: string;
|
|
3319
|
+
/** @enum {string} */
|
|
3320
|
+
type: "collaborates_with" | "reports_to" | "depends_on" | "custom";
|
|
3321
|
+
/** @enum {string} */
|
|
3322
|
+
role: "owner" | "participant" | "supporting";
|
|
3323
|
+
contextKey: string | null;
|
|
3324
|
+
metadata: {
|
|
3325
|
+
[key: string]: unknown;
|
|
3326
|
+
};
|
|
3327
|
+
createdAt: string;
|
|
3328
|
+
};
|
|
3329
|
+
OrgUnitTreeResponse: {
|
|
3330
|
+
nodes: {
|
|
3331
|
+
/** Format: uuid */
|
|
3332
|
+
id: string;
|
|
3333
|
+
/** Format: uuid */
|
|
3334
|
+
orgId: string;
|
|
3335
|
+
parentId: string | null;
|
|
3336
|
+
slug: string;
|
|
3337
|
+
name: string;
|
|
3338
|
+
description: string | null;
|
|
3339
|
+
typeTag: string;
|
|
3340
|
+
classification: ("execution_unit" | "org_container" | "custom") | null;
|
|
3341
|
+
orderKey: string;
|
|
3342
|
+
path: string;
|
|
3343
|
+
/** @enum {string} */
|
|
3344
|
+
syncMode: "manual_only" | "synced_readonly" | "synced_with_overrides";
|
|
3345
|
+
visibilityDefault: ("public" | "private" | "restricted") | null;
|
|
3346
|
+
metadata: {
|
|
3347
|
+
[key: string]: unknown;
|
|
3348
|
+
};
|
|
3349
|
+
archivedAt: string | null;
|
|
3350
|
+
createdAt: string;
|
|
3351
|
+
updatedAt: string;
|
|
3352
|
+
depth: number;
|
|
3353
|
+
hasChildren: boolean;
|
|
3354
|
+
memberCount: number;
|
|
3355
|
+
}[];
|
|
3356
|
+
levelConfig: {
|
|
3357
|
+
/** Format: uuid */
|
|
3358
|
+
orgId: string;
|
|
3359
|
+
depth: number;
|
|
3360
|
+
label: string;
|
|
3361
|
+
allowDoc: boolean;
|
|
3362
|
+
createdAt: string;
|
|
3363
|
+
updatedAt: string;
|
|
3364
|
+
}[];
|
|
3365
|
+
};
|
|
3366
|
+
OrgLevelConfigResponse: {
|
|
3367
|
+
entries: {
|
|
3368
|
+
/** Format: uuid */
|
|
3369
|
+
orgId: string;
|
|
3370
|
+
depth: number;
|
|
3371
|
+
label: string;
|
|
3372
|
+
allowDoc: boolean;
|
|
3373
|
+
createdAt: string;
|
|
3374
|
+
updatedAt: string;
|
|
3375
|
+
}[];
|
|
2986
3376
|
};
|
|
2987
3377
|
DriveFileListResponse: {
|
|
2988
3378
|
files: {
|
|
@@ -5736,6 +6126,324 @@ export interface operations {
|
|
|
5736
6126
|
};
|
|
5737
6127
|
};
|
|
5738
6128
|
};
|
|
6129
|
+
createOrgUnit: {
|
|
6130
|
+
parameters: {
|
|
6131
|
+
query?: never;
|
|
6132
|
+
header?: never;
|
|
6133
|
+
path?: never;
|
|
6134
|
+
cookie?: never;
|
|
6135
|
+
};
|
|
6136
|
+
requestBody: {
|
|
6137
|
+
content: {
|
|
6138
|
+
"application/json": {
|
|
6139
|
+
/** Format: uuid */
|
|
6140
|
+
parentId: string;
|
|
6141
|
+
slug: string;
|
|
6142
|
+
name: string;
|
|
6143
|
+
description?: string | null;
|
|
6144
|
+
typeTag: string;
|
|
6145
|
+
/** @enum {string} */
|
|
6146
|
+
classification?: "execution_unit" | "org_container" | "custom";
|
|
6147
|
+
/** @enum {string} */
|
|
6148
|
+
syncMode?: "manual_only" | "synced_readonly" | "synced_with_overrides";
|
|
6149
|
+
/** @enum {string} */
|
|
6150
|
+
visibilityDefault?: "public" | "private" | "restricted";
|
|
6151
|
+
metadata?: {
|
|
6152
|
+
[key: string]: unknown;
|
|
6153
|
+
};
|
|
6154
|
+
};
|
|
6155
|
+
};
|
|
6156
|
+
};
|
|
6157
|
+
responses: {
|
|
6158
|
+
/** @description Created org unit */
|
|
6159
|
+
201: {
|
|
6160
|
+
headers: {
|
|
6161
|
+
[name: string]: unknown;
|
|
6162
|
+
};
|
|
6163
|
+
content: {
|
|
6164
|
+
"application/json": components["schemas"]["OrgUnitResponse"];
|
|
6165
|
+
};
|
|
6166
|
+
};
|
|
6167
|
+
};
|
|
6168
|
+
};
|
|
6169
|
+
getOrgUnit: {
|
|
6170
|
+
parameters: {
|
|
6171
|
+
query?: never;
|
|
6172
|
+
header?: never;
|
|
6173
|
+
path: {
|
|
6174
|
+
unitId: string;
|
|
6175
|
+
};
|
|
6176
|
+
cookie?: never;
|
|
6177
|
+
};
|
|
6178
|
+
requestBody?: never;
|
|
6179
|
+
responses: {
|
|
6180
|
+
/** @description Org unit */
|
|
6181
|
+
200: {
|
|
6182
|
+
headers: {
|
|
6183
|
+
[name: string]: unknown;
|
|
6184
|
+
};
|
|
6185
|
+
content: {
|
|
6186
|
+
"application/json": components["schemas"]["OrgUnitResponse"];
|
|
6187
|
+
};
|
|
6188
|
+
};
|
|
6189
|
+
};
|
|
6190
|
+
};
|
|
6191
|
+
listOrgUnitChildren: {
|
|
6192
|
+
parameters: {
|
|
6193
|
+
query?: never;
|
|
6194
|
+
header?: never;
|
|
6195
|
+
path: {
|
|
6196
|
+
unitId: string;
|
|
6197
|
+
};
|
|
6198
|
+
cookie?: never;
|
|
6199
|
+
};
|
|
6200
|
+
requestBody?: never;
|
|
6201
|
+
responses: {
|
|
6202
|
+
/** @description Children of the unit */
|
|
6203
|
+
200: {
|
|
6204
|
+
headers: {
|
|
6205
|
+
[name: string]: unknown;
|
|
6206
|
+
};
|
|
6207
|
+
content: {
|
|
6208
|
+
"application/json": components["schemas"]["OrgUnitChildrenResponse"];
|
|
6209
|
+
};
|
|
6210
|
+
};
|
|
6211
|
+
};
|
|
6212
|
+
};
|
|
6213
|
+
listOrgUnitDescendants: {
|
|
6214
|
+
parameters: {
|
|
6215
|
+
query?: never;
|
|
6216
|
+
header?: never;
|
|
6217
|
+
path: {
|
|
6218
|
+
unitId: string;
|
|
6219
|
+
};
|
|
6220
|
+
cookie?: never;
|
|
6221
|
+
};
|
|
6222
|
+
requestBody?: never;
|
|
6223
|
+
responses: {
|
|
6224
|
+
/** @description Descendants of the unit */
|
|
6225
|
+
200: {
|
|
6226
|
+
headers: {
|
|
6227
|
+
[name: string]: unknown;
|
|
6228
|
+
};
|
|
6229
|
+
content: {
|
|
6230
|
+
"application/json": components["schemas"]["OrgUnitDescendantsResponse"];
|
|
6231
|
+
};
|
|
6232
|
+
};
|
|
6233
|
+
};
|
|
6234
|
+
};
|
|
6235
|
+
listOrgUnitAncestors: {
|
|
6236
|
+
parameters: {
|
|
6237
|
+
query?: never;
|
|
6238
|
+
header?: never;
|
|
6239
|
+
path: {
|
|
6240
|
+
unitId: string;
|
|
6241
|
+
};
|
|
6242
|
+
cookie?: never;
|
|
6243
|
+
};
|
|
6244
|
+
requestBody?: never;
|
|
6245
|
+
responses: {
|
|
6246
|
+
/** @description Ancestors of the unit */
|
|
6247
|
+
200: {
|
|
6248
|
+
headers: {
|
|
6249
|
+
[name: string]: unknown;
|
|
6250
|
+
};
|
|
6251
|
+
content: {
|
|
6252
|
+
"application/json": components["schemas"]["OrgUnitAncestorsResponse"];
|
|
6253
|
+
};
|
|
6254
|
+
};
|
|
6255
|
+
};
|
|
6256
|
+
};
|
|
6257
|
+
reparentOrgUnit: {
|
|
6258
|
+
parameters: {
|
|
6259
|
+
query?: never;
|
|
6260
|
+
header?: never;
|
|
6261
|
+
path: {
|
|
6262
|
+
unitId: string;
|
|
6263
|
+
};
|
|
6264
|
+
cookie?: never;
|
|
6265
|
+
};
|
|
6266
|
+
requestBody: {
|
|
6267
|
+
content: {
|
|
6268
|
+
"application/json": {
|
|
6269
|
+
/** Format: uuid */
|
|
6270
|
+
newParentId: string;
|
|
6271
|
+
};
|
|
6272
|
+
};
|
|
6273
|
+
};
|
|
6274
|
+
responses: {
|
|
6275
|
+
/** @description Reparented unit */
|
|
6276
|
+
200: {
|
|
6277
|
+
headers: {
|
|
6278
|
+
[name: string]: unknown;
|
|
6279
|
+
};
|
|
6280
|
+
content: {
|
|
6281
|
+
"application/json": components["schemas"]["OrgUnitResponse"];
|
|
6282
|
+
};
|
|
6283
|
+
};
|
|
6284
|
+
};
|
|
6285
|
+
};
|
|
6286
|
+
archiveOrgUnit: {
|
|
6287
|
+
parameters: {
|
|
6288
|
+
query?: never;
|
|
6289
|
+
header?: never;
|
|
6290
|
+
path: {
|
|
6291
|
+
unitId: string;
|
|
6292
|
+
};
|
|
6293
|
+
cookie?: never;
|
|
6294
|
+
};
|
|
6295
|
+
requestBody: {
|
|
6296
|
+
content: {
|
|
6297
|
+
"application/json": Record<string, never>;
|
|
6298
|
+
};
|
|
6299
|
+
};
|
|
6300
|
+
responses: {
|
|
6301
|
+
/** @description Archived unit */
|
|
6302
|
+
200: {
|
|
6303
|
+
headers: {
|
|
6304
|
+
[name: string]: unknown;
|
|
6305
|
+
};
|
|
6306
|
+
content: {
|
|
6307
|
+
"application/json": components["schemas"]["OrgUnitResponse"];
|
|
6308
|
+
};
|
|
6309
|
+
};
|
|
6310
|
+
};
|
|
6311
|
+
};
|
|
6312
|
+
listOrgUnitRelationships: {
|
|
6313
|
+
parameters: {
|
|
6314
|
+
query?: never;
|
|
6315
|
+
header?: never;
|
|
6316
|
+
path: {
|
|
6317
|
+
unitId: string;
|
|
6318
|
+
};
|
|
6319
|
+
cookie?: never;
|
|
6320
|
+
};
|
|
6321
|
+
requestBody?: never;
|
|
6322
|
+
responses: {
|
|
6323
|
+
/** @description Graph edges */
|
|
6324
|
+
200: {
|
|
6325
|
+
headers: {
|
|
6326
|
+
[name: string]: unknown;
|
|
6327
|
+
};
|
|
6328
|
+
content: {
|
|
6329
|
+
"application/json": components["schemas"]["OrgUnitRelationshipsResponse"];
|
|
6330
|
+
};
|
|
6331
|
+
};
|
|
6332
|
+
};
|
|
6333
|
+
};
|
|
6334
|
+
createOrgUnitRelationship: {
|
|
6335
|
+
parameters: {
|
|
6336
|
+
query?: never;
|
|
6337
|
+
header?: never;
|
|
6338
|
+
path: {
|
|
6339
|
+
unitId: string;
|
|
6340
|
+
};
|
|
6341
|
+
cookie?: never;
|
|
6342
|
+
};
|
|
6343
|
+
requestBody: {
|
|
6344
|
+
content: {
|
|
6345
|
+
"application/json": {
|
|
6346
|
+
/** Format: uuid */
|
|
6347
|
+
toUnit: string;
|
|
6348
|
+
/** @enum {string} */
|
|
6349
|
+
type?: "collaborates_with" | "reports_to" | "depends_on" | "custom";
|
|
6350
|
+
/** @enum {string} */
|
|
6351
|
+
role?: "owner" | "participant" | "supporting";
|
|
6352
|
+
contextKey?: string | null;
|
|
6353
|
+
metadata?: {
|
|
6354
|
+
[key: string]: unknown;
|
|
6355
|
+
};
|
|
6356
|
+
};
|
|
6357
|
+
};
|
|
6358
|
+
};
|
|
6359
|
+
responses: {
|
|
6360
|
+
/** @description Created relationship */
|
|
6361
|
+
201: {
|
|
6362
|
+
headers: {
|
|
6363
|
+
[name: string]: unknown;
|
|
6364
|
+
};
|
|
6365
|
+
content: {
|
|
6366
|
+
"application/json": components["schemas"]["OrgUnitRelationship"];
|
|
6367
|
+
};
|
|
6368
|
+
};
|
|
6369
|
+
};
|
|
6370
|
+
};
|
|
6371
|
+
getOrgTree: {
|
|
6372
|
+
parameters: {
|
|
6373
|
+
query?: never;
|
|
6374
|
+
header?: never;
|
|
6375
|
+
path: {
|
|
6376
|
+
orgId: string;
|
|
6377
|
+
};
|
|
6378
|
+
cookie?: never;
|
|
6379
|
+
};
|
|
6380
|
+
requestBody?: never;
|
|
6381
|
+
responses: {
|
|
6382
|
+
/** @description Org tree snapshot */
|
|
6383
|
+
200: {
|
|
6384
|
+
headers: {
|
|
6385
|
+
[name: string]: unknown;
|
|
6386
|
+
};
|
|
6387
|
+
content: {
|
|
6388
|
+
"application/json": components["schemas"]["OrgUnitTreeResponse"];
|
|
6389
|
+
};
|
|
6390
|
+
};
|
|
6391
|
+
};
|
|
6392
|
+
};
|
|
6393
|
+
listOrgLevelConfig: {
|
|
6394
|
+
parameters: {
|
|
6395
|
+
query?: never;
|
|
6396
|
+
header?: never;
|
|
6397
|
+
path: {
|
|
6398
|
+
orgId: string;
|
|
6399
|
+
};
|
|
6400
|
+
cookie?: never;
|
|
6401
|
+
};
|
|
6402
|
+
requestBody?: never;
|
|
6403
|
+
responses: {
|
|
6404
|
+
/** @description Level config entries */
|
|
6405
|
+
200: {
|
|
6406
|
+
headers: {
|
|
6407
|
+
[name: string]: unknown;
|
|
6408
|
+
};
|
|
6409
|
+
content: {
|
|
6410
|
+
"application/json": components["schemas"]["OrgLevelConfigResponse"];
|
|
6411
|
+
};
|
|
6412
|
+
};
|
|
6413
|
+
};
|
|
6414
|
+
};
|
|
6415
|
+
upsertOrgLevelConfig: {
|
|
6416
|
+
parameters: {
|
|
6417
|
+
query?: never;
|
|
6418
|
+
header?: never;
|
|
6419
|
+
path: {
|
|
6420
|
+
orgId: string;
|
|
6421
|
+
};
|
|
6422
|
+
cookie?: never;
|
|
6423
|
+
};
|
|
6424
|
+
requestBody: {
|
|
6425
|
+
content: {
|
|
6426
|
+
"application/json": {
|
|
6427
|
+
entries: {
|
|
6428
|
+
depth: number;
|
|
6429
|
+
label: string;
|
|
6430
|
+
allowDoc: boolean;
|
|
6431
|
+
}[];
|
|
6432
|
+
};
|
|
6433
|
+
};
|
|
6434
|
+
};
|
|
6435
|
+
responses: {
|
|
6436
|
+
/** @description Updated level config entries */
|
|
6437
|
+
200: {
|
|
6438
|
+
headers: {
|
|
6439
|
+
[name: string]: unknown;
|
|
6440
|
+
};
|
|
6441
|
+
content: {
|
|
6442
|
+
"application/json": components["schemas"]["OrgLevelConfigResponse"];
|
|
6443
|
+
};
|
|
6444
|
+
};
|
|
6445
|
+
};
|
|
6446
|
+
};
|
|
5739
6447
|
listDriveFiles: {
|
|
5740
6448
|
parameters: {
|
|
5741
6449
|
query?: never;
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import {
|
|
3
|
+
OrgUnitSchema,
|
|
4
|
+
OrgUnitTreeNodeSchema,
|
|
5
|
+
OrgUnitMembershipSchema,
|
|
6
|
+
OrgUnitRelationshipSchema,
|
|
7
|
+
OrgLevelConfigSchema,
|
|
8
|
+
OrgUnitTreeResponseSchema,
|
|
9
|
+
OrgUnitChildrenResponseSchema,
|
|
10
|
+
OrgUnitRelationshipsResponseSchema,
|
|
11
|
+
OrgUnitErrorCodeSchema,
|
|
12
|
+
OrgUnitClassificationSchema,
|
|
13
|
+
OrgUnitRelationshipTypeSchema,
|
|
14
|
+
OrgUnitMembershipSourceSchema,
|
|
15
|
+
} from '../schemas.js';
|
|
16
|
+
|
|
17
|
+
const UUID_A = '11111111-1111-4111-8111-111111111111';
|
|
18
|
+
const UUID_B = '22222222-2222-4222-8222-222222222222';
|
|
19
|
+
const UUID_C = '33333333-3333-4333-8333-333333333333';
|
|
20
|
+
|
|
21
|
+
const makeUnit = (overrides: Record<string, unknown> = {}) => ({
|
|
22
|
+
id: UUID_A,
|
|
23
|
+
orgId: UUID_B,
|
|
24
|
+
parentId: UUID_C,
|
|
25
|
+
slug: 'engineering',
|
|
26
|
+
name: 'Engineering',
|
|
27
|
+
description: null,
|
|
28
|
+
typeTag: 'department',
|
|
29
|
+
classification: 'org_container',
|
|
30
|
+
orderKey: 'a0',
|
|
31
|
+
path: `${UUID_B.replace(/-/g, '_')}.${UUID_A.replace(/-/g, '_')}`,
|
|
32
|
+
syncMode: 'manual_only',
|
|
33
|
+
visibilityDefault: null,
|
|
34
|
+
metadata: {},
|
|
35
|
+
archivedAt: null,
|
|
36
|
+
createdAt: '2026-04-17T00:00:00Z',
|
|
37
|
+
updatedAt: '2026-04-17T00:00:00Z',
|
|
38
|
+
...overrides,
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
describe('OrgUnitSchema', () => {
|
|
42
|
+
it('accepts a complete unit', () => {
|
|
43
|
+
const parsed = OrgUnitSchema.parse(makeUnit());
|
|
44
|
+
expect(parsed.id).toBe(UUID_A);
|
|
45
|
+
expect(parsed.typeTag).toBe('department');
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('accepts a root unit with null parentId', () => {
|
|
49
|
+
const root = makeUnit({ parentId: null, slug: 'company', name: 'Company', typeTag: 'company' });
|
|
50
|
+
expect(() => OrgUnitSchema.parse(root)).not.toThrow();
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('accepts archived unit (archivedAt non-null)', () => {
|
|
54
|
+
const archived = makeUnit({ archivedAt: '2026-04-17T12:00:00Z' });
|
|
55
|
+
expect(() => OrgUnitSchema.parse(archived)).not.toThrow();
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('rejects invalid UUID for id', () => {
|
|
59
|
+
expect(() => OrgUnitSchema.parse(makeUnit({ id: 'not-a-uuid' }))).toThrow();
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('rejects invalid classification', () => {
|
|
63
|
+
expect(() => OrgUnitSchema.parse(makeUnit({ classification: 'bogus' }))).toThrow();
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('rejects missing required fields', () => {
|
|
67
|
+
const { name: _name, ...missingName } = makeUnit();
|
|
68
|
+
expect(() => OrgUnitSchema.parse(missingName)).toThrow();
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('round-trips unknown metadata fields verbatim', () => {
|
|
72
|
+
const parsed = OrgUnitSchema.parse(makeUnit({ metadata: { legacy_team_id: UUID_C } }));
|
|
73
|
+
expect(parsed.metadata).toEqual({ legacy_team_id: UUID_C });
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
describe('OrgUnitTreeNodeSchema', () => {
|
|
78
|
+
it('requires depth 1..5', () => {
|
|
79
|
+
const base = { ...makeUnit(), depth: 3, hasChildren: true, memberCount: 5 };
|
|
80
|
+
expect(() => OrgUnitTreeNodeSchema.parse(base)).not.toThrow();
|
|
81
|
+
expect(() => OrgUnitTreeNodeSchema.parse({ ...base, depth: 0 })).toThrow();
|
|
82
|
+
expect(() => OrgUnitTreeNodeSchema.parse({ ...base, depth: 6 })).toThrow();
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
describe('OrgUnitMembershipSchema', () => {
|
|
87
|
+
it('enforces role + status + source enums', () => {
|
|
88
|
+
const membership = {
|
|
89
|
+
id: UUID_A,
|
|
90
|
+
orgId: UUID_B,
|
|
91
|
+
unitId: UUID_C,
|
|
92
|
+
userId: UUID_A,
|
|
93
|
+
membershipRole: 'manager',
|
|
94
|
+
status: 'active',
|
|
95
|
+
source: 'google_groups',
|
|
96
|
+
sourceRef: 'eng@example.com',
|
|
97
|
+
createdAt: '2026-04-17T00:00:00Z',
|
|
98
|
+
updatedAt: '2026-04-17T00:00:00Z',
|
|
99
|
+
};
|
|
100
|
+
expect(() => OrgUnitMembershipSchema.parse(membership)).not.toThrow();
|
|
101
|
+
expect(() =>
|
|
102
|
+
OrgUnitMembershipSchema.parse({ ...membership, membershipRole: 'root' })
|
|
103
|
+
).toThrow();
|
|
104
|
+
expect(() => OrgUnitMembershipSchema.parse({ ...membership, status: 'terminated' })).toThrow();
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
describe('OrgUnitRelationshipSchema', () => {
|
|
109
|
+
it('accepts graph edge with nullable contextKey', () => {
|
|
110
|
+
const edge = {
|
|
111
|
+
id: UUID_A,
|
|
112
|
+
orgId: UUID_B,
|
|
113
|
+
fromUnit: UUID_C,
|
|
114
|
+
toUnit: UUID_A,
|
|
115
|
+
type: 'collaborates_with' as const,
|
|
116
|
+
role: 'participant' as const,
|
|
117
|
+
contextKey: null,
|
|
118
|
+
metadata: {},
|
|
119
|
+
createdAt: '2026-04-17T00:00:00Z',
|
|
120
|
+
};
|
|
121
|
+
expect(() => OrgUnitRelationshipSchema.parse(edge)).not.toThrow();
|
|
122
|
+
expect(() =>
|
|
123
|
+
OrgUnitRelationshipSchema.parse({ ...edge, contextKey: 'infra-context' })
|
|
124
|
+
).not.toThrow();
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
describe('OrgLevelConfigSchema', () => {
|
|
129
|
+
it('enforces depth 1..5 and non-empty label', () => {
|
|
130
|
+
const entry = {
|
|
131
|
+
orgId: UUID_B,
|
|
132
|
+
depth: 2,
|
|
133
|
+
label: 'Department',
|
|
134
|
+
allowDoc: true,
|
|
135
|
+
createdAt: '2026-04-17T00:00:00Z',
|
|
136
|
+
updatedAt: '2026-04-17T00:00:00Z',
|
|
137
|
+
};
|
|
138
|
+
expect(() => OrgLevelConfigSchema.parse(entry)).not.toThrow();
|
|
139
|
+
expect(() => OrgLevelConfigSchema.parse({ ...entry, depth: 6 })).toThrow();
|
|
140
|
+
expect(() => OrgLevelConfigSchema.parse({ ...entry, label: '' })).toThrow();
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
describe('Response schemas', () => {
|
|
145
|
+
it('OrgUnitTreeResponseSchema accepts empty tree', () => {
|
|
146
|
+
expect(() =>
|
|
147
|
+
OrgUnitTreeResponseSchema.parse({ nodes: [], levelConfig: [] })
|
|
148
|
+
).not.toThrow();
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it('OrgUnitChildrenResponseSchema wraps parentId + children array', () => {
|
|
152
|
+
expect(() =>
|
|
153
|
+
OrgUnitChildrenResponseSchema.parse({ parentId: UUID_A, children: [] })
|
|
154
|
+
).not.toThrow();
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it('OrgUnitRelationshipsResponseSchema has incoming + outgoing arrays', () => {
|
|
158
|
+
expect(() =>
|
|
159
|
+
OrgUnitRelationshipsResponseSchema.parse({
|
|
160
|
+
unitId: UUID_A,
|
|
161
|
+
incoming: [],
|
|
162
|
+
outgoing: [],
|
|
163
|
+
})
|
|
164
|
+
).not.toThrow();
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
describe('Enum exhaustiveness', () => {
|
|
169
|
+
it('OrgUnitErrorCodeSchema enumerates all 7 known codes', () => {
|
|
170
|
+
const codes = [
|
|
171
|
+
'CYCLE_BLOCKED',
|
|
172
|
+
'DEPTH_EXCEEDED',
|
|
173
|
+
'TARGET_ARCHIVED',
|
|
174
|
+
'ROOT_HAS_NO_PARENT',
|
|
175
|
+
'PARENT_ARCHIVED',
|
|
176
|
+
'SLUG_TAKEN',
|
|
177
|
+
'CROSS_ORG_REPARENT',
|
|
178
|
+
];
|
|
179
|
+
for (const code of codes) {
|
|
180
|
+
expect(() => OrgUnitErrorCodeSchema.parse(code)).not.toThrow();
|
|
181
|
+
}
|
|
182
|
+
expect(() => OrgUnitErrorCodeSchema.parse('OTHER')).toThrow();
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it('classification enum matches backend _enums.ts', () => {
|
|
186
|
+
for (const v of ['execution_unit', 'org_container', 'custom']) {
|
|
187
|
+
expect(() => OrgUnitClassificationSchema.parse(v)).not.toThrow();
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
it('relationship type enum matches backend', () => {
|
|
192
|
+
for (const v of ['collaborates_with', 'reports_to', 'depends_on', 'custom']) {
|
|
193
|
+
expect(() => OrgUnitRelationshipTypeSchema.parse(v)).not.toThrow();
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
it('membership source enum matches backend', () => {
|
|
198
|
+
for (const v of ['manual', 'google_groups', 'scim', 'hris']) {
|
|
199
|
+
expect(() => OrgUnitMembershipSourceSchema.parse(v)).not.toThrow();
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
});
|
package/src/org/index.ts
CHANGED
|
@@ -214,3 +214,53 @@ export type {
|
|
|
214
214
|
OrgBudgetConfig,
|
|
215
215
|
OrgUsageResponse,
|
|
216
216
|
} from './schemas';
|
|
217
|
+
|
|
218
|
+
// OrgUnit canonical model (ADR-BE-120)
|
|
219
|
+
export type {
|
|
220
|
+
OrgUnitClassification,
|
|
221
|
+
OrgUnitSyncMode,
|
|
222
|
+
OrgUnitVisibility,
|
|
223
|
+
OrgUnitRelationshipType,
|
|
224
|
+
OrgUnitRelationshipRole,
|
|
225
|
+
OrgUnitMembershipRole,
|
|
226
|
+
OrgUnitMembershipStatus,
|
|
227
|
+
OrgUnitMembershipSource,
|
|
228
|
+
OrgUnitErrorCode,
|
|
229
|
+
} from './org-units';
|
|
230
|
+
export {
|
|
231
|
+
OrgUnitClassificationSchema,
|
|
232
|
+
OrgUnitSyncModeSchema,
|
|
233
|
+
OrgUnitVisibilitySchema,
|
|
234
|
+
OrgUnitRelationshipTypeSchema,
|
|
235
|
+
OrgUnitRelationshipRoleSchema,
|
|
236
|
+
OrgUnitMembershipRoleSchema,
|
|
237
|
+
OrgUnitMembershipStatusSchema,
|
|
238
|
+
OrgUnitMembershipSourceSchema,
|
|
239
|
+
OrgUnitErrorCodeSchema,
|
|
240
|
+
OrgUnitSchema,
|
|
241
|
+
OrgUnitTreeNodeSchema,
|
|
242
|
+
OrgUnitMembershipSchema,
|
|
243
|
+
OrgUnitRelationshipSchema,
|
|
244
|
+
OrgLevelConfigSchema,
|
|
245
|
+
OrgUnitResponseSchema,
|
|
246
|
+
OrgUnitTreeResponseSchema,
|
|
247
|
+
OrgUnitChildrenResponseSchema,
|
|
248
|
+
OrgUnitAncestorsResponseSchema,
|
|
249
|
+
OrgUnitDescendantsResponseSchema,
|
|
250
|
+
OrgUnitRelationshipsResponseSchema,
|
|
251
|
+
OrgLevelConfigResponseSchema,
|
|
252
|
+
} from './schemas';
|
|
253
|
+
export type {
|
|
254
|
+
OrgUnit,
|
|
255
|
+
OrgUnitTreeNode,
|
|
256
|
+
OrgUnitMembership,
|
|
257
|
+
OrgUnitRelationship,
|
|
258
|
+
OrgLevelConfig,
|
|
259
|
+
OrgUnitResponse,
|
|
260
|
+
OrgUnitTreeResponse,
|
|
261
|
+
OrgUnitChildrenResponse,
|
|
262
|
+
OrgUnitAncestorsResponse,
|
|
263
|
+
OrgUnitDescendantsResponse,
|
|
264
|
+
OrgUnitRelationshipsResponse,
|
|
265
|
+
OrgLevelConfigResponse,
|
|
266
|
+
} from './schemas';
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Org Unit Canonical Model Types
|
|
3
|
+
*
|
|
4
|
+
* Vocabulary enums for the canonical `org_units` tree + `org_unit_relationships`
|
|
5
|
+
* graph overlay. Object shapes (OrgUnit, OrgUnitMembership, ...) are owned by
|
|
6
|
+
* the Zod schemas in `./schemas` and inferred from them — see
|
|
7
|
+
* `OrgUnitSchema`, `OrgUnitMembershipSchema`, etc.
|
|
8
|
+
*
|
|
9
|
+
* Authoritative decision: ADR-BE-120. Structural invariants: INVARIANTS.md §Org Structure.
|
|
10
|
+
*
|
|
11
|
+
* Key facts a reader needs:
|
|
12
|
+
* - The tree (`OrgUnit.parentId` / `path`) is the only structural source.
|
|
13
|
+
* The graph (`OrgUnitRelationship`) is structure-inert; never traverse
|
|
14
|
+
* parent/child through it.
|
|
15
|
+
* - `typeTag` and `classification` are projection-only — never use for tree
|
|
16
|
+
* traversal. Enforced by CI guards (Phase 2).
|
|
17
|
+
* - `id` is the immutable identity. `slug` is mutable presentation.
|
|
18
|
+
* - `path` is an ltree string maintained by a DB trigger; never written from
|
|
19
|
+
* application code.
|
|
20
|
+
* - Depth is derived from `path`. `OrgLevelConfig.depth` is only a key for
|
|
21
|
+
* per-depth labels and policy — not authoritative structure.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/** Semantic classification — projection-only, never drives traversal. */
|
|
25
|
+
export type OrgUnitClassification = 'execution_unit' | 'org_container' | 'custom';
|
|
26
|
+
|
|
27
|
+
/** External directory reconciliation policy for a unit. */
|
|
28
|
+
export type OrgUnitSyncMode = 'manual_only' | 'synced_readonly' | 'synced_with_overrides';
|
|
29
|
+
|
|
30
|
+
/** Default visibility inherited by new docs under this unit. */
|
|
31
|
+
export type OrgUnitVisibility = 'public' | 'private' | 'restricted';
|
|
32
|
+
|
|
33
|
+
/** Edge classification for `org_unit_relationships`. Graph-only; never structural. */
|
|
34
|
+
export type OrgUnitRelationshipType = 'collaborates_with' | 'reports_to' | 'depends_on' | 'custom';
|
|
35
|
+
|
|
36
|
+
/** Edge role — refines the collaboration nature on a graph edge. */
|
|
37
|
+
export type OrgUnitRelationshipRole = 'owner' | 'participant' | 'supporting';
|
|
38
|
+
|
|
39
|
+
/** Per-unit user role. Privilege order: owner > manager > member. */
|
|
40
|
+
export type OrgUnitMembershipRole = 'member' | 'manager' | 'owner';
|
|
41
|
+
|
|
42
|
+
/** Active/pending/removed lifecycle for a unit membership. */
|
|
43
|
+
export type OrgUnitMembershipStatus = 'active' | 'pending' | 'removed';
|
|
44
|
+
|
|
45
|
+
/** External directory origin of a membership row. */
|
|
46
|
+
export type OrgUnitMembershipSource = 'manual' | 'google_groups' | 'scim' | 'hris';
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Error codes returned by `POST /api/org-units/:id/reparent` and related
|
|
50
|
+
* mutation endpoints. Clients must handle these explicitly.
|
|
51
|
+
*/
|
|
52
|
+
export type OrgUnitErrorCode =
|
|
53
|
+
/** newParent.path contains unit.path — would create a cycle. */
|
|
54
|
+
| 'CYCLE_BLOCKED'
|
|
55
|
+
/** Reparent would push subtree above depth 5. */
|
|
56
|
+
| 'DEPTH_EXCEEDED'
|
|
57
|
+
/** Target parent is archived; reparenting into archived subtrees is forbidden. */
|
|
58
|
+
| 'TARGET_ARCHIVED'
|
|
59
|
+
/** Attempted to set `parent_id` on a level-1 root unit. */
|
|
60
|
+
| 'ROOT_HAS_NO_PARENT'
|
|
61
|
+
/** Parent is archived on create. */
|
|
62
|
+
| 'PARENT_ARCHIVED'
|
|
63
|
+
/** Slug already taken under the target parent. */
|
|
64
|
+
| 'SLUG_TAKEN'
|
|
65
|
+
/** Attempted to reparent across orgs (or create with mismatched orgId). */
|
|
66
|
+
| 'CROSS_ORG_REPARENT';
|
package/src/org/schemas.ts
CHANGED
|
@@ -609,3 +609,155 @@ export const OrgUsageResponseSchema = z.object({
|
|
|
609
609
|
});
|
|
610
610
|
|
|
611
611
|
export type OrgUsageResponse = z.infer<typeof OrgUsageResponseSchema>;
|
|
612
|
+
|
|
613
|
+
// ---------------------------------------------------------------------------
|
|
614
|
+
// OrgUnit canonical model (ADR-BE-120)
|
|
615
|
+
// ---------------------------------------------------------------------------
|
|
616
|
+
|
|
617
|
+
export const OrgUnitClassificationSchema = z.enum(['execution_unit', 'org_container', 'custom']);
|
|
618
|
+
|
|
619
|
+
export const OrgUnitSyncModeSchema = z.enum([
|
|
620
|
+
'manual_only',
|
|
621
|
+
'synced_readonly',
|
|
622
|
+
'synced_with_overrides',
|
|
623
|
+
]);
|
|
624
|
+
|
|
625
|
+
export const OrgUnitVisibilitySchema = z.enum(['public', 'private', 'restricted']);
|
|
626
|
+
|
|
627
|
+
export const OrgUnitRelationshipTypeSchema = z.enum([
|
|
628
|
+
'collaborates_with',
|
|
629
|
+
'reports_to',
|
|
630
|
+
'depends_on',
|
|
631
|
+
'custom',
|
|
632
|
+
]);
|
|
633
|
+
|
|
634
|
+
export const OrgUnitRelationshipRoleSchema = z.enum(['owner', 'participant', 'supporting']);
|
|
635
|
+
|
|
636
|
+
export const OrgUnitMembershipRoleSchema = z.enum(['member', 'manager', 'owner']);
|
|
637
|
+
|
|
638
|
+
export const OrgUnitMembershipStatusSchema = z.enum(['active', 'pending', 'removed']);
|
|
639
|
+
|
|
640
|
+
export const OrgUnitMembershipSourceSchema = z.enum([
|
|
641
|
+
'manual',
|
|
642
|
+
'google_groups',
|
|
643
|
+
'scim',
|
|
644
|
+
'hris',
|
|
645
|
+
]);
|
|
646
|
+
|
|
647
|
+
export const OrgUnitErrorCodeSchema = z.enum([
|
|
648
|
+
'CYCLE_BLOCKED',
|
|
649
|
+
'DEPTH_EXCEEDED',
|
|
650
|
+
'TARGET_ARCHIVED',
|
|
651
|
+
'ROOT_HAS_NO_PARENT',
|
|
652
|
+
'PARENT_ARCHIVED',
|
|
653
|
+
'SLUG_TAKEN',
|
|
654
|
+
'CROSS_ORG_REPARENT',
|
|
655
|
+
]);
|
|
656
|
+
|
|
657
|
+
export const OrgUnitSchema = z.object({
|
|
658
|
+
id: z.string().uuid(),
|
|
659
|
+
orgId: z.string().uuid(),
|
|
660
|
+
parentId: z.string().uuid().nullable(),
|
|
661
|
+
slug: z.string().min(1),
|
|
662
|
+
name: z.string().min(1),
|
|
663
|
+
description: z.string().nullable(),
|
|
664
|
+
typeTag: z.string().min(1),
|
|
665
|
+
classification: OrgUnitClassificationSchema.nullable(),
|
|
666
|
+
orderKey: z.string().min(1),
|
|
667
|
+
path: z.string().min(1),
|
|
668
|
+
syncMode: OrgUnitSyncModeSchema,
|
|
669
|
+
visibilityDefault: OrgUnitVisibilitySchema.nullable(),
|
|
670
|
+
metadata: z.record(z.string(), z.unknown()),
|
|
671
|
+
archivedAt: z.string().nullable(),
|
|
672
|
+
createdAt: z.string(),
|
|
673
|
+
updatedAt: z.string(),
|
|
674
|
+
});
|
|
675
|
+
|
|
676
|
+
export const OrgUnitTreeNodeSchema = OrgUnitSchema.extend({
|
|
677
|
+
depth: z.number().int().min(1).max(5),
|
|
678
|
+
hasChildren: z.boolean(),
|
|
679
|
+
memberCount: z.number().int().min(0),
|
|
680
|
+
});
|
|
681
|
+
|
|
682
|
+
export const OrgUnitMembershipSchema = z.object({
|
|
683
|
+
id: z.string().uuid(),
|
|
684
|
+
orgId: z.string().uuid(),
|
|
685
|
+
unitId: z.string().uuid(),
|
|
686
|
+
userId: z.string().uuid(),
|
|
687
|
+
membershipRole: OrgUnitMembershipRoleSchema,
|
|
688
|
+
status: OrgUnitMembershipStatusSchema,
|
|
689
|
+
source: OrgUnitMembershipSourceSchema,
|
|
690
|
+
sourceRef: z.string().nullable(),
|
|
691
|
+
createdAt: z.string(),
|
|
692
|
+
updatedAt: z.string(),
|
|
693
|
+
});
|
|
694
|
+
|
|
695
|
+
export const OrgUnitRelationshipSchema = z.object({
|
|
696
|
+
id: z.string().uuid(),
|
|
697
|
+
orgId: z.string().uuid(),
|
|
698
|
+
fromUnit: z.string().uuid(),
|
|
699
|
+
toUnit: z.string().uuid(),
|
|
700
|
+
type: OrgUnitRelationshipTypeSchema,
|
|
701
|
+
role: OrgUnitRelationshipRoleSchema,
|
|
702
|
+
contextKey: z.string().nullable(),
|
|
703
|
+
metadata: z.record(z.string(), z.unknown()),
|
|
704
|
+
createdAt: z.string(),
|
|
705
|
+
});
|
|
706
|
+
|
|
707
|
+
export const OrgLevelConfigSchema = z.object({
|
|
708
|
+
orgId: z.string().uuid(),
|
|
709
|
+
depth: z.number().int().min(1).max(5),
|
|
710
|
+
label: z.string().min(1),
|
|
711
|
+
allowDoc: z.boolean(),
|
|
712
|
+
createdAt: z.string(),
|
|
713
|
+
updatedAt: z.string(),
|
|
714
|
+
});
|
|
715
|
+
|
|
716
|
+
// --- Response schemas (request schemas live in backend per ADR-CONT-044) ---
|
|
717
|
+
|
|
718
|
+
export const OrgUnitResponseSchema = z.object({ unit: OrgUnitSchema });
|
|
719
|
+
|
|
720
|
+
export const OrgUnitTreeResponseSchema = z.object({
|
|
721
|
+
nodes: z.array(OrgUnitTreeNodeSchema),
|
|
722
|
+
levelConfig: z.array(OrgLevelConfigSchema),
|
|
723
|
+
});
|
|
724
|
+
|
|
725
|
+
export const OrgUnitChildrenResponseSchema = z.object({
|
|
726
|
+
parentId: z.string().uuid(),
|
|
727
|
+
children: z.array(OrgUnitTreeNodeSchema),
|
|
728
|
+
});
|
|
729
|
+
|
|
730
|
+
export const OrgUnitAncestorsResponseSchema = z.object({
|
|
731
|
+
unitId: z.string().uuid(),
|
|
732
|
+
ancestors: z.array(OrgUnitSchema),
|
|
733
|
+
});
|
|
734
|
+
|
|
735
|
+
export const OrgUnitDescendantsResponseSchema = z.object({
|
|
736
|
+
rootId: z.string().uuid(),
|
|
737
|
+
descendants: z.array(OrgUnitSchema),
|
|
738
|
+
});
|
|
739
|
+
|
|
740
|
+
export const OrgUnitRelationshipsResponseSchema = z.object({
|
|
741
|
+
unitId: z.string().uuid(),
|
|
742
|
+
incoming: z.array(OrgUnitRelationshipSchema),
|
|
743
|
+
outgoing: z.array(OrgUnitRelationshipSchema),
|
|
744
|
+
});
|
|
745
|
+
|
|
746
|
+
export const OrgLevelConfigResponseSchema = z.object({
|
|
747
|
+
entries: z.array(OrgLevelConfigSchema),
|
|
748
|
+
});
|
|
749
|
+
|
|
750
|
+
// --- Inferred types ---
|
|
751
|
+
|
|
752
|
+
export type OrgUnit = z.infer<typeof OrgUnitSchema>;
|
|
753
|
+
export type OrgUnitTreeNode = z.infer<typeof OrgUnitTreeNodeSchema>;
|
|
754
|
+
export type OrgUnitMembership = z.infer<typeof OrgUnitMembershipSchema>;
|
|
755
|
+
export type OrgUnitRelationship = z.infer<typeof OrgUnitRelationshipSchema>;
|
|
756
|
+
export type OrgLevelConfig = z.infer<typeof OrgLevelConfigSchema>;
|
|
757
|
+
export type OrgUnitResponse = z.infer<typeof OrgUnitResponseSchema>;
|
|
758
|
+
export type OrgUnitTreeResponse = z.infer<typeof OrgUnitTreeResponseSchema>;
|
|
759
|
+
export type OrgUnitChildrenResponse = z.infer<typeof OrgUnitChildrenResponseSchema>;
|
|
760
|
+
export type OrgUnitAncestorsResponse = z.infer<typeof OrgUnitAncestorsResponseSchema>;
|
|
761
|
+
export type OrgUnitDescendantsResponse = z.infer<typeof OrgUnitDescendantsResponseSchema>;
|
|
762
|
+
export type OrgUnitRelationshipsResponse = z.infer<typeof OrgUnitRelationshipsResponseSchema>;
|
|
763
|
+
export type OrgLevelConfigResponse = z.infer<typeof OrgLevelConfigResponseSchema>;
|