@company-semantics/contracts 21.1.0 → 21.3.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 +30 -0
- package/src/org/README.md +4 -0
- package/src/org/__tests__/invite-schemas.test.ts +104 -0
- package/src/org/index.ts +4 -0
- package/src/org/schemas.ts +94 -7
- package/src/org/types.ts +44 -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 = '16094a4fcda0' as const;
|
|
3
|
+
export const SPEC_HASH_FULL = '16094a4fcda0647e96289cdc0e104eab13d9539c043207cdda1ad8c8bf5a4dcb' as const;
|
package/src/api/generated.ts
CHANGED
|
@@ -3449,6 +3449,8 @@ export interface components {
|
|
|
3449
3449
|
unitName: string;
|
|
3450
3450
|
/** @enum {string} */
|
|
3451
3451
|
designation: "whole_org" | "admin" | "unit_owner" | "delegate" | "member";
|
|
3452
|
+
/** @enum {string} */
|
|
3453
|
+
mutability: "derived" | "user_managed";
|
|
3452
3454
|
}[];
|
|
3453
3455
|
unitMembershipsTruncated: boolean;
|
|
3454
3456
|
inviteStatus: ("active" | "pending" | "expired") | null;
|
|
@@ -3644,6 +3646,8 @@ export interface components {
|
|
|
3644
3646
|
unitName: string;
|
|
3645
3647
|
/** @enum {string} */
|
|
3646
3648
|
designation: "whole_org" | "admin" | "unit_owner" | "delegate" | "member";
|
|
3649
|
+
/** @enum {string} */
|
|
3650
|
+
mutability: "derived" | "user_managed";
|
|
3647
3651
|
}[];
|
|
3648
3652
|
unitMembershipsTruncated: boolean;
|
|
3649
3653
|
inviteStatus: ("active" | "pending" | "expired") | null;
|
|
@@ -3774,6 +3778,19 @@ export interface components {
|
|
|
3774
3778
|
homeUnitId?: string;
|
|
3775
3779
|
/** @enum {string} */
|
|
3776
3780
|
homeUnitRole?: "member" | "unit_owner";
|
|
3781
|
+
stagedPlacement?: {
|
|
3782
|
+
title?: string;
|
|
3783
|
+
/** Format: uuid */
|
|
3784
|
+
managerUserId?: string;
|
|
3785
|
+
/** Format: uuid */
|
|
3786
|
+
homeUnitId?: string;
|
|
3787
|
+
/** @enum {string} */
|
|
3788
|
+
homeUnitRole?: "member" | "unit_owner";
|
|
3789
|
+
/** @default [] */
|
|
3790
|
+
unitOwnerOf: string[];
|
|
3791
|
+
/** @default [] */
|
|
3792
|
+
contributesTo: string[];
|
|
3793
|
+
};
|
|
3777
3794
|
createdAt: string;
|
|
3778
3795
|
expiresAt: string;
|
|
3779
3796
|
acceptedAt?: string;
|
|
@@ -3805,6 +3822,19 @@ export interface components {
|
|
|
3805
3822
|
homeUnitId?: string;
|
|
3806
3823
|
/** @enum {string} */
|
|
3807
3824
|
homeUnitRole?: "member" | "unit_owner";
|
|
3825
|
+
stagedPlacement?: {
|
|
3826
|
+
title?: string;
|
|
3827
|
+
/** Format: uuid */
|
|
3828
|
+
managerUserId?: string;
|
|
3829
|
+
/** Format: uuid */
|
|
3830
|
+
homeUnitId?: string;
|
|
3831
|
+
/** @enum {string} */
|
|
3832
|
+
homeUnitRole?: "member" | "unit_owner";
|
|
3833
|
+
/** @default [] */
|
|
3834
|
+
unitOwnerOf: string[];
|
|
3835
|
+
/** @default [] */
|
|
3836
|
+
contributesTo: string[];
|
|
3837
|
+
};
|
|
3808
3838
|
createdAt: string;
|
|
3809
3839
|
expiresAt: string;
|
|
3810
3840
|
acceptedAt?: string;
|
package/src/org/README.md
CHANGED
|
@@ -75,6 +75,8 @@ Shared type vocabulary for organization ownership, type classification, and tran
|
|
|
75
75
|
- `CreateDelegationRequest` _(type)_
|
|
76
76
|
- `CreateDelegationRequestSchema`
|
|
77
77
|
- `CreateInviteRequest` _(type)_ — Request payload for creating an organization invite.
|
|
78
|
+
- `CreateInviteRequestPayload` _(type)_
|
|
79
|
+
- `CreateInviteRequestSchema`
|
|
78
80
|
- `CreateOpenRoleRequest` _(type)_
|
|
79
81
|
- `CreateOpenRoleRequestSchema`
|
|
80
82
|
- `Delegation` _(type)_
|
|
@@ -258,6 +260,8 @@ Shared type vocabulary for organization ownership, type classification, and tran
|
|
|
258
260
|
- `SsoReadinessCheck` _(type)_ — Individual readiness check for SSO activation.
|
|
259
261
|
- `SsoSetupInfo` _(type)_ — SSO setup information for admin configuration UI.
|
|
260
262
|
- `SsoStepperStep` _(type)_ — Backend-authoritative stepper step.
|
|
263
|
+
- `StagedPlacement` _(type)_ — Staged member placement: the fuller org position an invitee is slotted into, applied as deferred grants when…
|
|
264
|
+
- `StagedPlacementSchema` — Staged member placement: the fuller org position an invitee is slotted into, applied as deferred grants when…
|
|
261
265
|
- `SubmitInteractiveTaskResponse` _(type)_
|
|
262
266
|
- `SubmitInteractiveTaskResponseSchema` — Response for submitting a filled-in interactive chat task surface (e.g. the editable "change reporting…
|
|
263
267
|
- `SyncRunSummary` _(type)_
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import {
|
|
3
|
+
StagedPlacementSchema,
|
|
4
|
+
CreateInviteRequestSchema,
|
|
5
|
+
InviteResponseSchema,
|
|
6
|
+
} from "../schemas.js";
|
|
7
|
+
|
|
8
|
+
const UUID_A = "11111111-1111-4111-8111-111111111111";
|
|
9
|
+
const UUID_B = "22222222-2222-4222-8222-222222222222";
|
|
10
|
+
const UUID_C = "33333333-3333-4333-8333-333333333333";
|
|
11
|
+
|
|
12
|
+
const makeInvite = (overrides: Record<string, unknown> = {}) => ({
|
|
13
|
+
id: UUID_A,
|
|
14
|
+
orgId: UUID_B,
|
|
15
|
+
email: "new.hire@example.com",
|
|
16
|
+
role: "member",
|
|
17
|
+
invitedBy: { id: UUID_C, name: "Inviter" },
|
|
18
|
+
status: "pending",
|
|
19
|
+
createdAt: "2026-06-24T00:00:00Z",
|
|
20
|
+
expiresAt: "2026-07-01T00:00:00Z",
|
|
21
|
+
...overrides,
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
describe("CreateInviteRequestSchema", () => {
|
|
25
|
+
it("parses a minimal payload without stagedPlacement", () => {
|
|
26
|
+
const parsed = CreateInviteRequestSchema.parse({
|
|
27
|
+
email: "new.hire@example.com",
|
|
28
|
+
role: "admin",
|
|
29
|
+
});
|
|
30
|
+
expect(parsed.stagedPlacement).toBeUndefined();
|
|
31
|
+
expect(parsed.homeUnitId).toBeUndefined();
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("parses a full stagedPlacement with arrays defaulting to []", () => {
|
|
35
|
+
const parsed = CreateInviteRequestSchema.parse({
|
|
36
|
+
email: "new.hire@example.com",
|
|
37
|
+
role: "member",
|
|
38
|
+
homeUnitId: UUID_A,
|
|
39
|
+
homeUnitRole: "unit_owner",
|
|
40
|
+
stagedPlacement: {
|
|
41
|
+
title: "Staff Engineer",
|
|
42
|
+
managerUserId: UUID_B,
|
|
43
|
+
homeUnitId: UUID_A,
|
|
44
|
+
homeUnitRole: "unit_owner",
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
expect(parsed.stagedPlacement?.title).toBe("Staff Engineer");
|
|
48
|
+
// unitOwnerOf/contributesTo default to [] when omitted.
|
|
49
|
+
expect(parsed.stagedPlacement?.unitOwnerOf).toEqual([]);
|
|
50
|
+
expect(parsed.stagedPlacement?.contributesTo).toEqual([]);
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
describe("StagedPlacementSchema", () => {
|
|
55
|
+
it("defaults unitOwnerOf and contributesTo to []", () => {
|
|
56
|
+
const parsed = StagedPlacementSchema.parse({});
|
|
57
|
+
expect(parsed.unitOwnerOf).toEqual([]);
|
|
58
|
+
expect(parsed.contributesTo).toEqual([]);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("retains provided unit arrays", () => {
|
|
62
|
+
const parsed = StagedPlacementSchema.parse({
|
|
63
|
+
unitOwnerOf: [UUID_A],
|
|
64
|
+
contributesTo: [UUID_B, UUID_C],
|
|
65
|
+
});
|
|
66
|
+
expect(parsed.unitOwnerOf).toEqual([UUID_A]);
|
|
67
|
+
expect(parsed.contributesTo).toEqual([UUID_B, UUID_C]);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it("trims the title", () => {
|
|
71
|
+
const parsed = StagedPlacementSchema.parse({ title: " Lead " });
|
|
72
|
+
expect(parsed.title).toBe("Lead");
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it("rejects a non-uuid managerUserId", () => {
|
|
76
|
+
expect(() =>
|
|
77
|
+
StagedPlacementSchema.parse({ managerUserId: "not-a-uuid" }),
|
|
78
|
+
).toThrow();
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
describe("OrgInviteSchema (via InviteResponseSchema)", () => {
|
|
83
|
+
it("parses an invite without stagedPlacement (back-compat)", () => {
|
|
84
|
+
const parsed = InviteResponseSchema.parse({ invite: makeInvite() });
|
|
85
|
+
expect(parsed.invite.stagedPlacement).toBeUndefined();
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it("parses an invite carrying a stagedPlacement", () => {
|
|
89
|
+
const parsed = InviteResponseSchema.parse({
|
|
90
|
+
invite: makeInvite({
|
|
91
|
+
homeUnitId: UUID_A,
|
|
92
|
+
homeUnitRole: "member",
|
|
93
|
+
stagedPlacement: {
|
|
94
|
+
title: "Engineer",
|
|
95
|
+
unitOwnerOf: [UUID_A],
|
|
96
|
+
},
|
|
97
|
+
}),
|
|
98
|
+
});
|
|
99
|
+
expect(parsed.invite.stagedPlacement?.title).toBe("Engineer");
|
|
100
|
+
expect(parsed.invite.stagedPlacement?.unitOwnerOf).toEqual([UUID_A]);
|
|
101
|
+
// Omitted contributesTo still defaults to [].
|
|
102
|
+
expect(parsed.invite.stagedPlacement?.contributesTo).toEqual([]);
|
|
103
|
+
});
|
|
104
|
+
});
|
package/src/org/index.ts
CHANGED
|
@@ -249,6 +249,8 @@ export type {
|
|
|
249
249
|
|
|
250
250
|
// Org lifecycle response schemas (PRD-00446)
|
|
251
251
|
export {
|
|
252
|
+
StagedPlacementSchema,
|
|
253
|
+
CreateInviteRequestSchema,
|
|
252
254
|
InviteResponseSchema,
|
|
253
255
|
InviteListResponseSchema,
|
|
254
256
|
DomainResponseSchema,
|
|
@@ -259,6 +261,8 @@ export {
|
|
|
259
261
|
OwnershipTransferPreviewSchema,
|
|
260
262
|
} from "./schemas";
|
|
261
263
|
export type {
|
|
264
|
+
StagedPlacement,
|
|
265
|
+
CreateInviteRequestPayload,
|
|
262
266
|
InviteResponse,
|
|
263
267
|
InviteListResponse,
|
|
264
268
|
DomainResponse,
|
package/src/org/schemas.ts
CHANGED
|
@@ -43,10 +43,31 @@ export const OrgUnitDesignationSchema = z.enum([
|
|
|
43
43
|
]);
|
|
44
44
|
export type OrgUnitDesignation = z.infer<typeof OrgUnitDesignationSchema>;
|
|
45
45
|
|
|
46
|
+
/**
|
|
47
|
+
* Whether the user can change this authority from this surface.
|
|
48
|
+
* - `derived`: change the upstream source instead (the org chart, RBAC roles).
|
|
49
|
+
* - `user_managed`: removable from this UI.
|
|
50
|
+
*
|
|
51
|
+
* Hoisted above {@link WorkspaceMemberUnitDesignationEntrySchema} so the
|
|
52
|
+
* per-unit designation can carry it; also consumed by {@link OwnerAuthoritySchema}.
|
|
53
|
+
*/
|
|
54
|
+
export const AuthorityMutabilitySchema = z.enum(["derived", "user_managed"]);
|
|
55
|
+
export type AuthorityMutability = z.infer<typeof AuthorityMutabilitySchema>;
|
|
56
|
+
|
|
46
57
|
export const WorkspaceMemberUnitDesignationEntrySchema = z.object({
|
|
47
58
|
unitId: z.string(),
|
|
48
59
|
unitName: z.string(),
|
|
49
60
|
designation: OrgUnitDesignationSchema,
|
|
61
|
+
/**
|
|
62
|
+
* Whether this designation is REMOVABLE in place (`user_managed` — an explicit
|
|
63
|
+
* overlay grant or `l{N}_unit_owner` membership) or DERIVED from reporting
|
|
64
|
+
* topology (`derived` — the senior person homed in a unit with no manager
|
|
65
|
+
* inside it, ADR-BE-267/294). A `derived` owner can't be revoked: the holder
|
|
66
|
+
* must relinquish it (recorded as a higher-provenance suppression that the
|
|
67
|
+
* structural projection honors) or the upstream chart must change. Display +
|
|
68
|
+
* affordance gating only; never an authorization input.
|
|
69
|
+
*/
|
|
70
|
+
mutability: AuthorityMutabilitySchema,
|
|
50
71
|
});
|
|
51
72
|
export type WorkspaceMemberUnitDesignationEntry = z.infer<
|
|
52
73
|
typeof WorkspaceMemberUnitDesignationEntrySchema
|
|
@@ -606,6 +627,46 @@ export type ScopeCheckBatchResponse = z.infer<
|
|
|
606
627
|
export const HomeUnitRoleSchema = z.enum(["member", "unit_owner"]);
|
|
607
628
|
export type HomeUnitRole = z.infer<typeof HomeUnitRoleSchema>;
|
|
608
629
|
|
|
630
|
+
/** Established title cap shared with org-unit/open-role titles. */
|
|
631
|
+
const STAGED_PLACEMENT_TITLE_MAX = 255;
|
|
632
|
+
/**
|
|
633
|
+
* Upper bound on the number of units an invitee can be staged into as owner or
|
|
634
|
+
* contributor. Bounds the replay cost of applying a staged placement at accept
|
|
635
|
+
* time (each entry is a deferred membership grant). A generous-but-finite cap.
|
|
636
|
+
*/
|
|
637
|
+
const STAGED_PLACEMENT_UNITS_MAX = 64;
|
|
638
|
+
|
|
639
|
+
/**
|
|
640
|
+
* Staged member placement: the fuller org position an invitee is slotted into,
|
|
641
|
+
* applied as deferred grants when the invite is accepted. A superset of the
|
|
642
|
+
* legacy top-level `homeUnitId`/`homeUnitRole` fields, carrying the (optional)
|
|
643
|
+
* intended title, manager, and the units the invitee will own or contribute to.
|
|
644
|
+
*
|
|
645
|
+
* Every field is optional or defaulted so a placement can be partially
|
|
646
|
+
* specified at invite time. The array caps bound downstream replay cost.
|
|
647
|
+
*/
|
|
648
|
+
export const StagedPlacementSchema = z.object({
|
|
649
|
+
// Intended job/role title for the invitee. Trimmed; non-empty when present.
|
|
650
|
+
title: z.string().trim().min(1).max(STAGED_PLACEMENT_TITLE_MAX).optional(),
|
|
651
|
+
// The invitee's manager on acceptance (a `manages` designation).
|
|
652
|
+
managerUserId: z.string().uuid().optional(),
|
|
653
|
+
// Home unit the invitee is placed in (their `users.primary_unit_id`).
|
|
654
|
+
homeUnitId: z.string().uuid().optional(),
|
|
655
|
+
// Role the invitee takes in `homeUnitId` ('unit_owner' = deferred grant).
|
|
656
|
+
homeUnitRole: HomeUnitRoleSchema.optional(),
|
|
657
|
+
// Additional units the invitee becomes a unit owner of on acceptance.
|
|
658
|
+
unitOwnerOf: z
|
|
659
|
+
.array(z.string().uuid())
|
|
660
|
+
.max(STAGED_PLACEMENT_UNITS_MAX)
|
|
661
|
+
.default([]),
|
|
662
|
+
// Units the invitee contributes to (non-owner membership) on acceptance.
|
|
663
|
+
contributesTo: z
|
|
664
|
+
.array(z.string().uuid())
|
|
665
|
+
.max(STAGED_PLACEMENT_UNITS_MAX)
|
|
666
|
+
.default([]),
|
|
667
|
+
});
|
|
668
|
+
export type StagedPlacement = z.infer<typeof StagedPlacementSchema>;
|
|
669
|
+
|
|
609
670
|
const OrgInviteSchema = z.object({
|
|
610
671
|
id: z.string(),
|
|
611
672
|
orgId: z.string(),
|
|
@@ -620,6 +681,10 @@ const OrgInviteSchema = z.object({
|
|
|
620
681
|
// deferred unit-ownership grant). Optional/'member' for legacy +
|
|
621
682
|
// unit-less invites.
|
|
622
683
|
homeUnitRole: HomeUnitRoleSchema.optional(),
|
|
684
|
+
// Fuller staged placement applied as deferred grants on acceptance. A
|
|
685
|
+
// superset of the top-level homeUnitId/homeUnitRole, kept additive/optional
|
|
686
|
+
// so legacy invites and unit-less invites parse unchanged.
|
|
687
|
+
stagedPlacement: StagedPlacementSchema.optional(),
|
|
623
688
|
createdAt: z.string(),
|
|
624
689
|
expiresAt: z.string(),
|
|
625
690
|
acceptedAt: z.string().optional(),
|
|
@@ -643,6 +708,33 @@ export const InviteListResponseSchema = z.array(OrgInviteSchema);
|
|
|
643
708
|
|
|
644
709
|
export type InviteListResponse = z.infer<typeof InviteListResponseSchema>;
|
|
645
710
|
|
|
711
|
+
// ---------------------------------------------------------------------------
|
|
712
|
+
// POST /api/workspace/invites — request body
|
|
713
|
+
// Request schema colocated with the response schema (narrow deviation from
|
|
714
|
+
// ADR-CONT-044, per the CreateOpenRoleRequestSchema precedent) because the
|
|
715
|
+
// staged-placement shape is the published promise consumers must satisfy.
|
|
716
|
+
// Mirrors the hand-written `CreateInviteRequest` interface in org/types.ts and
|
|
717
|
+
// extends it with the optional `stagedPlacement` superset.
|
|
718
|
+
// ---------------------------------------------------------------------------
|
|
719
|
+
|
|
720
|
+
export const CreateInviteRequestSchema = z.object({
|
|
721
|
+
email: z.string().email(),
|
|
722
|
+
// Invites only grant the restricted {admin, member} domain.
|
|
723
|
+
role: z.enum(["admin", "member"]),
|
|
724
|
+
// Home unit the invitee is placed in on acceptance. Optional in the contract
|
|
725
|
+
// so the field can roll out without breaking older callers.
|
|
726
|
+
homeUnitId: z.string().uuid().optional(),
|
|
727
|
+
// Role the invitee takes in homeUnitId — only meaningful with a home unit.
|
|
728
|
+
homeUnitRole: HomeUnitRoleSchema.optional(),
|
|
729
|
+
// Fuller staged placement (title, manager, owned/contributed units) applied
|
|
730
|
+
// as deferred grants on acceptance. Optional/additive for back-compat.
|
|
731
|
+
stagedPlacement: StagedPlacementSchema.optional(),
|
|
732
|
+
});
|
|
733
|
+
|
|
734
|
+
export type CreateInviteRequestPayload = z.infer<
|
|
735
|
+
typeof CreateInviteRequestSchema
|
|
736
|
+
>;
|
|
737
|
+
|
|
646
738
|
// ---------------------------------------------------------------------------
|
|
647
739
|
// OrgDomain sub-schema
|
|
648
740
|
// ---------------------------------------------------------------------------
|
|
@@ -1070,13 +1162,8 @@ export type AuthorityMechanism = z.infer<typeof AuthorityMechanismSchema>;
|
|
|
1070
1162
|
export const AuthorityLocalitySchema = z.enum(["local", "inherited"]);
|
|
1071
1163
|
export type AuthorityLocality = z.infer<typeof AuthorityLocalitySchema>;
|
|
1072
1164
|
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
* - `derived`: change the upstream source instead (the org chart, RBAC roles).
|
|
1076
|
-
* - `user_managed`: removable from this UI.
|
|
1077
|
-
*/
|
|
1078
|
-
export const AuthorityMutabilitySchema = z.enum(["derived", "user_managed"]);
|
|
1079
|
-
export type AuthorityMutability = z.infer<typeof AuthorityMutabilitySchema>;
|
|
1165
|
+
// AuthorityMutabilitySchema is defined above (hoisted next to
|
|
1166
|
+
// WorkspaceMemberUnitDesignationEntrySchema, which also carries it).
|
|
1080
1167
|
|
|
1081
1168
|
export const OwnerAuthoritySchema = z.object({
|
|
1082
1169
|
mechanism: AuthorityMechanismSchema,
|
package/src/org/types.ts
CHANGED
|
@@ -397,6 +397,37 @@ export interface WorkspaceAuditEvent {
|
|
|
397
397
|
*/
|
|
398
398
|
export type OrgInviteStatus = "pending" | "accepted" | "expired" | "revoked";
|
|
399
399
|
|
|
400
|
+
/**
|
|
401
|
+
* Staged member placement: the fuller org position an invitee is slotted into,
|
|
402
|
+
* applied as deferred grants when the invite is accepted. A superset of the
|
|
403
|
+
* top-level `homeUnitId`/`homeUnitRole` fields, carrying the (optional) intended
|
|
404
|
+
* title, manager, and the units the invitee will own or contribute to.
|
|
405
|
+
*
|
|
406
|
+
* Hand-written mirror of `StagedPlacementSchema` in `org/schemas.ts` — keep in
|
|
407
|
+
* lockstep. Because the schema defaults `unitOwnerOf`/`contributesTo` to `[]`,
|
|
408
|
+
* their inferred OUTPUT type is a required `string[]`; the other four fields are
|
|
409
|
+
* optional. The `homeUnitRole` union is re-typed inline (not imported) to match
|
|
410
|
+
* the `OrgInvite`/`CreateInviteRequest` convention.
|
|
411
|
+
*
|
|
412
|
+
* NOTE: the canonical `StagedPlacement` name is exported package-root from
|
|
413
|
+
* `org/schemas.ts` (the `z.infer`). This interface is intentionally NOT added to
|
|
414
|
+
* the `./types` re-export block in `org/index.ts` to avoid a name collision.
|
|
415
|
+
*/
|
|
416
|
+
export interface StagedPlacement {
|
|
417
|
+
/** Intended job/role title for the invitee. Trimmed; non-empty when present. */
|
|
418
|
+
title?: string;
|
|
419
|
+
/** The invitee's manager on acceptance (a `manages` designation) — a member id. */
|
|
420
|
+
managerUserId?: string;
|
|
421
|
+
/** Home unit the invitee is placed in (their `users.primary_unit_id`). */
|
|
422
|
+
homeUnitId?: string;
|
|
423
|
+
/** Role the invitee takes in `homeUnitId` (`unit_owner` = deferred grant). */
|
|
424
|
+
homeUnitRole?: "member" | "unit_owner";
|
|
425
|
+
/** Additional units the invitee becomes a unit owner of on acceptance. */
|
|
426
|
+
unitOwnerOf: string[];
|
|
427
|
+
/** Units the invitee contributes to (non-owner membership) on acceptance. */
|
|
428
|
+
contributesTo: string[];
|
|
429
|
+
}
|
|
430
|
+
|
|
400
431
|
/**
|
|
401
432
|
* Organization invite for the workspace invites list.
|
|
402
433
|
* Represents a pending or historical invitation.
|
|
@@ -425,6 +456,13 @@ export interface OrgInvite {
|
|
|
425
456
|
* legacy invites and unit-less invites have none (treated as `member`).
|
|
426
457
|
*/
|
|
427
458
|
homeUnitRole?: "member" | "unit_owner";
|
|
459
|
+
/**
|
|
460
|
+
* Fuller staged placement applied as deferred grants on acceptance. A superset
|
|
461
|
+
* of the top-level `homeUnitId`/`homeUnitRole`, kept additive/optional so
|
|
462
|
+
* legacy and unit-less invites parse unchanged. Mirrors
|
|
463
|
+
* `OrgInviteSchema.stagedPlacement` in `org/schemas.ts`.
|
|
464
|
+
*/
|
|
465
|
+
stagedPlacement?: StagedPlacement;
|
|
428
466
|
createdAt: string;
|
|
429
467
|
expiresAt: string;
|
|
430
468
|
acceptedAt?: string;
|
|
@@ -450,6 +488,12 @@ export interface CreateInviteRequest {
|
|
|
450
488
|
* rejects `unit_owner` without a home unit. Optional/`member` for older callers.
|
|
451
489
|
*/
|
|
452
490
|
homeUnitRole?: "member" | "unit_owner";
|
|
491
|
+
/**
|
|
492
|
+
* Fuller staged placement (title, manager, owned/contributed units) applied as
|
|
493
|
+
* deferred grants on acceptance. Optional/additive for back-compat. Mirrors
|
|
494
|
+
* `CreateInviteRequestSchema.stagedPlacement` in `org/schemas.ts`.
|
|
495
|
+
*/
|
|
496
|
+
stagedPlacement?: StagedPlacement;
|
|
453
497
|
}
|
|
454
498
|
|
|
455
499
|
/**
|