@stapel/workspaces-react 0.7.0 → 0.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.
Files changed (41) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/dist/api/generated/schema.d.ts +390 -3
  3. package/dist/api/generated/schema.d.ts.map +1 -1
  4. package/dist/api/types.d.ts +84 -2
  5. package/dist/api/types.d.ts.map +1 -1
  6. package/dist/api/workspacesApi.d.ts +33 -1
  7. package/dist/api/workspacesApi.d.ts.map +1 -1
  8. package/dist/api/workspacesApi.js +19 -0
  9. package/dist/api/workspacesApi.js.map +1 -1
  10. package/dist/index.d.ts +7 -5
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +3 -2
  13. package/dist/index.js.map +1 -1
  14. package/dist/model/mutations.d.ts +85 -1
  15. package/dist/model/mutations.d.ts.map +1 -1
  16. package/dist/model/mutations.js +151 -0
  17. package/dist/model/mutations.js.map +1 -1
  18. package/dist/model/queries.d.ts +72 -2
  19. package/dist/model/queries.d.ts.map +1 -1
  20. package/dist/model/queries.js +90 -1
  21. package/dist/model/queries.js.map +1 -1
  22. package/dist/model/queryKeys.d.ts +10 -1
  23. package/dist/model/queryKeys.d.ts.map +1 -1
  24. package/dist/model/queryKeys.js +19 -0
  25. package/dist/model/queryKeys.js.map +1 -1
  26. package/dist/model/stepUp.d.ts +25 -0
  27. package/dist/model/stepUp.d.ts.map +1 -0
  28. package/dist/model/stepUp.js +79 -0
  29. package/dist/model/stepUp.js.map +1 -0
  30. package/llms.txt +11 -2
  31. package/manifest.json +123 -2
  32. package/package.json +4 -4
  33. package/src/analytics/generated/events.json +1 -1
  34. package/src/api/generated/schema.ts +390 -3
  35. package/src/api/types.ts +93 -2
  36. package/src/api/workspacesApi.ts +87 -0
  37. package/src/index.ts +29 -2
  38. package/src/model/mutations.ts +192 -0
  39. package/src/model/queries.ts +132 -2
  40. package/src/model/queryKeys.ts +35 -1
  41. package/src/model/stepUp.ts +96 -0
@@ -1,6 +1,7 @@
1
- import type { UseQueryResult } from "@tanstack/react-query";
1
+ import type { InfiniteData, UseInfiniteQueryResult, UseQueryResult } from "@tanstack/react-query";
2
2
  import type { StapelApiError } from "@stapel/core";
3
- import type { InvitationPreview, MemberPage, MembersParams, RoleInfo, Workspace, WorkspaceList } from "../api/types.js";
3
+ import type { InvitationPage, InvitationPreview, InvitationsParams, MemberPage, MembersParams, RoleInfo, Workspace, WorkspaceList } from "../api/types.js";
4
+ import type { CapabilityLevel } from "./stepUp.js";
4
5
  /**
5
6
  * Read hooks over the workspaces API. Staleness follows core's query defaults;
6
7
  * override per call site via a page that needs fresher data. Keys are
@@ -34,6 +35,33 @@ export declare function useWorkspace(workspaceId: string | null): UseQueryResult
34
35
  * to a specific page or filter; omit for the newest page (default limit 100).
35
36
  */
36
37
  export declare function useMembers(workspaceId: string | null, params?: MembersParams): UseQueryResult<MemberPage, StapelApiError>;
38
+ /**
39
+ * One page of a workspace's invitations (GET /{id}/invitations, #109) — the
40
+ * admin's "who has not accepted yet" table. Disabled until a `workspaceId` is
41
+ * given (and the session is ready — see {@link useWorkspace}).
42
+ *
43
+ * ANCHOR pagination, exactly like {@link useMembers}: pass a page's
44
+ * `next_anchor` as `anchor` to walk forward. There is no page NUMBER — an
45
+ * offset would skew the moment an invitation is revoked or accepted while the
46
+ * admin is reading, which on this screen is the normal case, not the edge one.
47
+ * For scroll-to-load-more use {@link useInfiniteInvitations}.
48
+ *
49
+ * `status` defaults to the backend's `pending` (live, seat-reserving
50
+ * invitations); pass `never_accepted` to include declined/revoked/expired, or
51
+ * `all` for the full history.
52
+ */
53
+ export declare function useInvitations(workspaceId: string | null, params?: InvitationsParams): UseQueryResult<InvitationPage, StapelApiError>;
54
+ /**
55
+ * A workspace's invitations as an infinite (load-more) list. Follows the
56
+ * backend's ANCHOR pagination and nothing else: the page param IS the
57
+ * previous page's `next_anchor`, and the walk stops when `has_next` goes
58
+ * false. `data.pages.flatMap(p => p.items)` is the flat row list.
59
+ *
60
+ * `filters` (`status` / `search` / `limit`) are part of the query key, so
61
+ * flipping the status tab starts a fresh anchor walk rather than appending
62
+ * rows of one filter to the pages of another.
63
+ */
64
+ export declare function useInfiniteInvitations(workspaceId: string | null, filters?: Omit<InvitationsParams, "anchor" | "direction">): UseInfiniteQueryResult<InfiniteData<InvitationPage, string | undefined>, StapelApiError>;
37
65
  /**
38
66
  * The effective role registry (GET /roles, org-program §A2): builtin four +
39
67
  * the deployment's `STAPEL_WORKSPACES["ROLES"]` overlay, capability strings
@@ -70,4 +98,46 @@ export interface CapabilitiesResult {
70
98
  * the backend predates the field.
71
99
  */
72
100
  export declare function useCapabilities(workspaceId: string | null): CapabilitiesResult;
101
+ /** What {@link useCapabilityGate} answers about ONE capability, BEFORE the
102
+ * operation is attempted. */
103
+ export interface CapabilityGate {
104
+ /** The capability asked about, verbatim. */
105
+ readonly capability: string;
106
+ /** Does the caller's role carry it? Deny-by-default while loading. */
107
+ readonly allowed: boolean;
108
+ /** Its declared step-up level (ported registry — see `./stepUp.js`). */
109
+ readonly level: CapabilityLevel;
110
+ /** True when `level === "high"`: the backend ALSO demands a fresh
111
+ * verification (scope {@link SENSITIVE_SCOPE}) on top of the capability. */
112
+ readonly requiresStepUp: boolean;
113
+ /** The verification scope of that demand, or `null` at `standard`. */
114
+ readonly stepUpScope: string | null;
115
+ readonly isLoading: boolean;
116
+ }
117
+ /**
118
+ * Ask about one capability BEFORE offering the operation (org-program §A3).
119
+ *
120
+ * Two different answers, both needed in front of the button rather than
121
+ * behind it:
122
+ *
123
+ * * `allowed` — the caller's role carries the mandate. UI convenience only,
124
+ * deny-by-default; the backend re-checks. This is what replaces guessing
125
+ * access from the ROLE NAME: a deployment role like `secretary` can hold
126
+ * `members.invite` and would still fail a `role === "admin"` test forever,
127
+ * no matter what the registry says.
128
+ * * `requiresStepUp` — the operation is declared `high`, so a fresh step-up
129
+ * verification is demanded on top. Knowing this up front is what lets a
130
+ * screen say "you'll be asked to confirm" (or pre-drive enrollment)
131
+ * instead of showing a button that answers 403.
132
+ *
133
+ * Example — the administrative password reset:
134
+ * ```tsx
135
+ * const gate = useCapabilityGate(workspaceId, "members.password.reset");
136
+ * // gate.allowed === false → do not render the button at all
137
+ * // gate.requiresStepUp → render it with the "we will ask you to
138
+ * // confirm" affordance, wired to the app's
139
+ * // verification controller
140
+ * ```
141
+ */
142
+ export declare function useCapabilityGate(workspaceId: string | null, capability: string): CapabilityGate;
73
143
  //# sourceMappingURL=queries.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../../src/model/queries.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EACV,iBAAiB,EACjB,UAAU,EACV,aAAa,EACb,QAAQ,EACR,SAAS,EACT,aAAa,EACd,MAAM,iBAAiB,CAAC;AAKzB;;;;GAIG;AAEH;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,IAAI,cAAc,CAAC,aAAa,EAAE,cAAc,CAAC,CAQ7E;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,WAAW,EAAE,MAAM,GAAG,IAAI,GACzB,cAAc,CAAC,SAAS,EAAE,cAAc,CAAC,CAQ3C;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CACxB,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,MAAM,CAAC,EAAE,aAAa,GACrB,cAAc,CAAC,UAAU,EAAE,cAAc,CAAC,CAS5C;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,IAAI,cAAc,CACxC,SAAS,QAAQ,EAAE,EACnB,cAAc,CACf,CAQA;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,GAAG,IAAI,GACnB,cAAc,CAAC,iBAAiB,EAAE,cAAc,CAAC,CAOnD;AAED;qEACqE;AACrE,MAAM,WAAW,kBAAkB;IACjC;iEAC6D;IAC7D,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC;wEACoE;IACpE,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC;IACjC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAAC;CACvC;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,kBAAkB,CAU9E"}
1
+ {"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../../src/model/queries.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,YAAY,EACZ,sBAAsB,EACtB,cAAc,EACf,MAAM,uBAAuB,CAAC;AAE/B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EACV,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,UAAU,EACV,aAAa,EACb,QAAQ,EACR,SAAS,EACT,aAAa,EACd,MAAM,iBAAiB,CAAC;AAKzB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD;;;;GAIG;AAEH;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,IAAI,cAAc,CAAC,aAAa,EAAE,cAAc,CAAC,CAQ7E;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,WAAW,EAAE,MAAM,GAAG,IAAI,GACzB,cAAc,CAAC,SAAS,EAAE,cAAc,CAAC,CAQ3C;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CACxB,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,MAAM,CAAC,EAAE,aAAa,GACrB,cAAc,CAAC,UAAU,EAAE,cAAc,CAAC,CAS5C;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAC5B,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,MAAM,CAAC,EAAE,iBAAiB,GACzB,cAAc,CAAC,cAAc,EAAE,cAAc,CAAC,CAShD;AAED;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,OAAO,CAAC,EAAE,IAAI,CAAC,iBAAiB,EAAE,QAAQ,GAAG,WAAW,CAAC,GACxD,sBAAsB,CACvB,YAAY,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC,EAChD,cAAc,CACf,CAiBA;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,IAAI,cAAc,CACxC,SAAS,QAAQ,EAAE,EACnB,cAAc,CACf,CAQA;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,GAAG,IAAI,GACnB,cAAc,CAAC,iBAAiB,EAAE,cAAc,CAAC,CAOnD;AAED;qEACqE;AACrE,MAAM,WAAW,kBAAkB;IACjC;iEAC6D;IAC7D,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC;wEACoE;IACpE,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC;IACjC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAAC;CACvC;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,kBAAkB,CAU9E;AAED;6BAC6B;AAC7B,MAAM,WAAW,cAAc;IAC7B,4CAA4C;IAC5C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,sEAAsE;IACtE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,wEAAwE;IACxE,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;IAChC;gFAC4E;IAC5E,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC,sEAAsE;IACtE,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,UAAU,EAAE,MAAM,GACjB,cAAc,CAWhB"}
@@ -1,8 +1,9 @@
1
- import { useQuery } from "@tanstack/react-query";
1
+ import { useInfiniteQuery, useQuery } from "@tanstack/react-query";
2
2
  import { useActiveSessionReady } from "@stapel/core";
3
3
  import { useWorkspacesApi } from "./context.js";
4
4
  import { workspacesQueryKeys } from "./queryKeys.js";
5
5
  import { hasCapability } from "./capabilities.js";
6
+ import { SENSITIVE_SCOPE, capabilityLevel } from "./stepUp.js";
6
7
  /**
7
8
  * Read hooks over the workspaces API. Staleness follows core's query defaults;
8
9
  * override per call site via a page that needs fresher data. Keys are
@@ -61,6 +62,57 @@ export function useMembers(workspaceId, params) {
61
62
  enabled: sessionReady && workspaceId !== null && workspaceId !== "",
62
63
  });
63
64
  }
65
+ /**
66
+ * One page of a workspace's invitations (GET /{id}/invitations, #109) — the
67
+ * admin's "who has not accepted yet" table. Disabled until a `workspaceId` is
68
+ * given (and the session is ready — see {@link useWorkspace}).
69
+ *
70
+ * ANCHOR pagination, exactly like {@link useMembers}: pass a page's
71
+ * `next_anchor` as `anchor` to walk forward. There is no page NUMBER — an
72
+ * offset would skew the moment an invitation is revoked or accepted while the
73
+ * admin is reading, which on this screen is the normal case, not the edge one.
74
+ * For scroll-to-load-more use {@link useInfiniteInvitations}.
75
+ *
76
+ * `status` defaults to the backend's `pending` (live, seat-reserving
77
+ * invitations); pass `never_accepted` to include declined/revoked/expired, or
78
+ * `all` for the full history.
79
+ */
80
+ export function useInvitations(workspaceId, params) {
81
+ const api = useWorkspacesApi();
82
+ const sessionReady = useActiveSessionReady();
83
+ const p = params ?? {};
84
+ return useQuery({
85
+ queryKey: workspacesQueryKeys.invitationsPage(workspaceId ?? "", p),
86
+ queryFn: () => api.listInvitations(workspaceId, p),
87
+ enabled: sessionReady && workspaceId !== null && workspaceId !== "",
88
+ });
89
+ }
90
+ /**
91
+ * A workspace's invitations as an infinite (load-more) list. Follows the
92
+ * backend's ANCHOR pagination and nothing else: the page param IS the
93
+ * previous page's `next_anchor`, and the walk stops when `has_next` goes
94
+ * false. `data.pages.flatMap(p => p.items)` is the flat row list.
95
+ *
96
+ * `filters` (`status` / `search` / `limit`) are part of the query key, so
97
+ * flipping the status tab starts a fresh anchor walk rather than appending
98
+ * rows of one filter to the pages of another.
99
+ */
100
+ export function useInfiniteInvitations(workspaceId, filters) {
101
+ const api = useWorkspacesApi();
102
+ const sessionReady = useActiveSessionReady();
103
+ const f = filters ?? {};
104
+ return useInfiniteQuery({
105
+ queryKey: workspacesQueryKeys.invitationsInfinite(workspaceId ?? "", f),
106
+ queryFn: ({ pageParam }) => api.listInvitations(workspaceId, {
107
+ ...f,
108
+ direction: "next",
109
+ ...(pageParam !== undefined ? { anchor: pageParam } : {}),
110
+ }),
111
+ initialPageParam: undefined,
112
+ getNextPageParam: (last) => last.has_next ? (last.next_anchor ?? undefined) : undefined,
113
+ enabled: sessionReady && workspaceId !== null && workspaceId !== "",
114
+ });
115
+ }
64
116
  /**
65
117
  * The effective role registry (GET /roles, org-program §A2): builtin four +
66
118
  * the deployment's `STAPEL_WORKSPACES["ROLES"]` overlay, capability strings
@@ -109,4 +161,41 @@ export function useCapabilities(workspaceId) {
109
161
  error: query.error ?? null,
110
162
  };
111
163
  }
164
+ /**
165
+ * Ask about one capability BEFORE offering the operation (org-program §A3).
166
+ *
167
+ * Two different answers, both needed in front of the button rather than
168
+ * behind it:
169
+ *
170
+ * * `allowed` — the caller's role carries the mandate. UI convenience only,
171
+ * deny-by-default; the backend re-checks. This is what replaces guessing
172
+ * access from the ROLE NAME: a deployment role like `secretary` can hold
173
+ * `members.invite` and would still fail a `role === "admin"` test forever,
174
+ * no matter what the registry says.
175
+ * * `requiresStepUp` — the operation is declared `high`, so a fresh step-up
176
+ * verification is demanded on top. Knowing this up front is what lets a
177
+ * screen say "you'll be asked to confirm" (or pre-drive enrollment)
178
+ * instead of showing a button that answers 403.
179
+ *
180
+ * Example — the administrative password reset:
181
+ * ```tsx
182
+ * const gate = useCapabilityGate(workspaceId, "members.password.reset");
183
+ * // gate.allowed === false → do not render the button at all
184
+ * // gate.requiresStepUp → render it with the "we will ask you to
185
+ * // confirm" affordance, wired to the app's
186
+ * // verification controller
187
+ * ```
188
+ */
189
+ export function useCapabilityGate(workspaceId, capability) {
190
+ const { can, isLoading } = useCapabilities(workspaceId);
191
+ const level = capabilityLevel(capability);
192
+ return {
193
+ capability,
194
+ allowed: can(capability),
195
+ level,
196
+ requiresStepUp: level === "high",
197
+ stepUpScope: level === "high" ? SENSITIVE_SCOPE : null,
198
+ isLoading,
199
+ };
200
+ }
112
201
  //# sourceMappingURL=queries.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"queries.js","sourceRoot":"","sources":["../../src/model/queries.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"queries.js","sourceRoot":"","sources":["../../src/model/queries.ts"],"names":[],"mappings":"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"}
@@ -1,10 +1,19 @@
1
- import type { MembersParams } from "../api/types.js";
1
+ import type { InvitationsParams, MembersParams } from "../api/types.js";
2
2
  export declare const workspacesQueryKeys: {
3
3
  readonly all: readonly ["workspaces"];
4
4
  list(): readonly ["workspaces", "list"];
5
5
  detail(workspaceId: string): readonly ["workspaces", "detail", string];
6
6
  members(workspaceId: string): readonly ["workspaces", "members", string];
7
7
  membersPage(workspaceId: string, params: MembersParams): readonly ["workspaces", "members", string, MembersParams];
8
+ invitations(workspaceId: string): readonly ["workspaces", "invitations", string];
9
+ invitationsPage(workspaceId: string, params: InvitationsParams): readonly ["workspaces", "invitations", string, InvitationsParams];
10
+ invitationsInfinite(workspaceId: string, filters: InvitationsParams): readonly [
11
+ "workspaces",
12
+ "invitations",
13
+ string,
14
+ "infinite",
15
+ InvitationsParams
16
+ ];
8
17
  roles(): readonly ["workspaces", "roles"];
9
18
  invitationPreview(token: string): readonly ["workspaces", "invitation-preview", string];
10
19
  };
@@ -1 +1 @@
1
- {"version":3,"file":"queryKeys.d.ts","sourceRoot":"","sources":["../../src/model/queryKeys.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAWrD,eAAO,MAAM,mBAAmB,EAAE;IAChC,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAC,YAAY,CAAC,CAAC;IACtC,IAAI,IAAI,SAAS,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IACxC,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC,YAAY,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;IACvE,OAAO,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC,YAAY,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;IACzE,WAAW,CACT,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,aAAa,GACpB,SAAS,CAAC,YAAY,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC;IAC7D,KAAK,IAAI,SAAS,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IAC1C,iBAAiB,CACf,KAAK,EAAE,MAAM,GACZ,SAAS,CAAC,YAAY,EAAE,oBAAoB,EAAE,MAAM,CAAC,CAAC;CAe1D,CAAC"}
1
+ {"version":3,"file":"queryKeys.d.ts","sourceRoot":"","sources":["../../src/model/queryKeys.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAWxE,eAAO,MAAM,mBAAmB,EAAE;IAChC,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAC,YAAY,CAAC,CAAC;IACtC,IAAI,IAAI,SAAS,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IACxC,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC,YAAY,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;IACvE,OAAO,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC,YAAY,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;IACzE,WAAW,CACT,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,aAAa,GACpB,SAAS,CAAC,YAAY,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC;IAC7D,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC,YAAY,EAAE,aAAa,EAAE,MAAM,CAAC,CAAC;IACjF,eAAe,CACb,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,iBAAiB,GACxB,SAAS,CAAC,YAAY,EAAE,aAAa,EAAE,MAAM,EAAE,iBAAiB,CAAC,CAAC;IACrE,mBAAmB,CACjB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,iBAAiB,GACzB,SAAS;QACV,YAAY;QACZ,aAAa;QACb,MAAM;QACN,UAAU;QACV,iBAAiB;KAClB,CAAC;IACF,KAAK,IAAI,SAAS,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IAC1C,iBAAiB,CACf,KAAK,EAAE,MAAM,GACZ,SAAS,CAAC,YAAY,EAAE,oBAAoB,EAAE,MAAM,CAAC,CAAC;CAkC1D,CAAC"}
@@ -14,6 +14,25 @@ export const workspacesQueryKeys = {
14
14
  // invalidating `members(workspaceId)` (mutations.ts) drops every page.
15
15
  members: (workspaceId) => [ROOT, "members", workspaceId],
16
16
  membersPage: (workspaceId, params) => [ROOT, "members", workspaceId, params],
17
+ // Same prefix trick as `members`: the bare 3-tuple invalidates every page
18
+ // (and the infinite list, which keys on it) after a revoke / resend.
19
+ invitations: (workspaceId) => [ROOT, "invitations", workspaceId],
20
+ invitationsPage: (workspaceId, params) => [
21
+ ROOT,
22
+ "invitations",
23
+ workspaceId,
24
+ params,
25
+ ],
26
+ // The infinite list carries its own marker segment: its cached value is an
27
+ // `InfiniteData` envelope, not a page, so it must never collide with a
28
+ // single-page key that happens to hold the same filters.
29
+ invitationsInfinite: (workspaceId, filters) => [
30
+ ROOT,
31
+ "invitations",
32
+ workspaceId,
33
+ "infinite",
34
+ filters,
35
+ ],
17
36
  roles: () => [ROOT, "roles"],
18
37
  // NOTE: the key carries the invite TOKEN (a secret). Core's query persist
19
38
  // scope is per-user and the preview response is already public-by-design
@@ -1 +1 @@
1
- {"version":3,"file":"queryKeys.js","sourceRoot":"","sources":["../../src/model/queryKeys.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,IAAI,GAAG,YAAqB,CAAC;AAEnC,MAAM,CAAC,MAAM,mBAAmB,GAa5B;IACF,GAAG,EAAE,CAAC,IAAI,CAAC;IACX,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC;IAC1B,MAAM,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,QAAQ,EAAE,WAAW,CAAC;IACtD,kEAAkE;IAClE,uEAAuE;IACvE,OAAO,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,SAAS,EAAE,WAAW,CAAC;IACxD,WAAW,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,CAAC;IAC5E,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC;IAC5B,0EAA0E;IAC1E,yEAAyE;IACzE,2EAA2E;IAC3E,gBAAgB;IAChB,iBAAiB,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,oBAAoB,EAAE,KAAK,CAAC;CAClE,CAAC"}
1
+ {"version":3,"file":"queryKeys.js","sourceRoot":"","sources":["../../src/model/queryKeys.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,IAAI,GAAG,YAAqB,CAAC;AAEnC,MAAM,CAAC,MAAM,mBAAmB,GA4B5B;IACF,GAAG,EAAE,CAAC,IAAI,CAAC;IACX,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC;IAC1B,MAAM,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,QAAQ,EAAE,WAAW,CAAC;IACtD,kEAAkE;IAClE,uEAAuE;IACvE,OAAO,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,SAAS,EAAE,WAAW,CAAC;IACxD,WAAW,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,CAAC;IAC5E,0EAA0E;IAC1E,qEAAqE;IACrE,WAAW,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,aAAa,EAAE,WAAW,CAAC;IAChE,eAAe,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,CAAC;QACxC,IAAI;QACJ,aAAa;QACb,WAAW;QACX,MAAM;KACP;IACD,2EAA2E;IAC3E,uEAAuE;IACvE,yDAAyD;IACzD,mBAAmB,EAAE,CAAC,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC;QAC7C,IAAI;QACJ,aAAa;QACb,WAAW;QACX,UAAU;QACV,OAAO;KACR;IACD,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC;IAC5B,0EAA0E;IAC1E,yEAAyE;IACzE,2EAA2E;IAC3E,gBAAgB;IAChB,iBAAiB,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,oBAAoB,EAAE,KAAK,CAAC;CAClE,CAAC"}
@@ -0,0 +1,25 @@
1
+ /** The verification scope every `high` workspace capability is gated under. */
2
+ export declare const SENSITIVE_SCOPE = "sensitive";
3
+ /** Step-up level of a capability. */
4
+ export type CapabilityLevel = "standard" | "high";
5
+ /** PORT of `BUILTIN_CAPABILITY_LEVELS` — everything unlisted is `standard`. */
6
+ export declare const BUILTIN_CAPABILITY_LEVELS: Readonly<Record<string, "high">>;
7
+ /** The declared step-up level of one capability string. */
8
+ export declare function capabilityLevel(capability: string): CapabilityLevel;
9
+ /**
10
+ * The 403 ENROLLMENT envelope: the caller must first enroll one of `factors`
11
+ * — there is no challenge to complete, so core cannot drive it.
12
+ */
13
+ export interface VerificationEnrollment {
14
+ /** What the demand protects — `"sensitive"` for every `high` capability. */
15
+ readonly scope: string;
16
+ /** Interchangeable factors, any ONE of which unblocks the operation. */
17
+ readonly factors: readonly string[];
18
+ }
19
+ /**
20
+ * Read the enrollment demand out of a rejected request, or `null` when the
21
+ * error is anything else (including a step-up CHALLENGE, which carries a
22
+ * `challenge_id` and is core's business, not the consumer's).
23
+ */
24
+ export declare function readVerificationEnrollment(error: unknown): VerificationEnrollment | null;
25
+ //# sourceMappingURL=stepUp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stepUp.d.ts","sourceRoot":"","sources":["../../src/model/stepUp.ts"],"names":[],"mappings":"AAiCA,+EAA+E;AAC/E,eAAO,MAAM,eAAe,cAAc,CAAC;AAE3C,qCAAqC;AACrC,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,MAAM,CAAC;AAElD,+EAA+E;AAC/E,eAAO,MAAM,yBAAyB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAItE,CAAC;AAEF,2DAA2D;AAC3D,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe,CAEnE;AAED;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACrC,4EAA4E;IAC5E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,wEAAwE;IACxE,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AAQD;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,OAAO,GACb,sBAAsB,GAAG,IAAI,CAoB/B"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Step-up ahead of the button, not behind it (org-program §A3).
3
+ *
4
+ * Some workspace operations are declared **high**: the backend gates them
5
+ * with `stapel_core`'s `@requires_verification(scope="sensitive")` on top of
6
+ * the capability check, so an ambient cookie is never enough. A client that
7
+ * only learns this from the 403 shows the admin a button, a spinner and a
8
+ * refusal; this module lets it know BEFORE the click.
9
+ *
10
+ * Two things travel from the backend, and they are not the same thing:
11
+ *
12
+ * 1. **A step-up CHALLENGE** — `verification.challenge_id` is present. This
13
+ * one nobody has to handle here: `@stapel/core`'s client intercepts it,
14
+ * hands it to the app's verification controller (auth-react's factor
15
+ * machines) and replays the original request with
16
+ * `X-Verification-Token`. It is a detour, not a failure.
17
+ * 2. **An ENROLLMENT demand** — `verification.enroll === true` and there is
18
+ * NO challenge id, because the user holds no factor that could be
19
+ * challenged. Core deliberately does not intercept this one (there is
20
+ * nothing to drive), so it surfaces as a plain 403 and the app must send
21
+ * the user to factor enrollment first. {@link readVerificationEnrollment}
22
+ * is how a hook says "this is that, and these are the factors".
23
+ *
24
+ * KEEP IN SYNC with stapel-workspaces `capabilities.BUILTIN_CAPABILITY_LEVELS`
25
+ * — a PORT for the same reason `capabilityMatches` is one: `GET /roles`
26
+ * publishes each role's capabilities but not their levels, so the level map
27
+ * cannot be read off the wire. A deployment may raise further capabilities via
28
+ * `STAPEL_WORKSPACES["CAPABILITY_LEVELS"]`; those are additive, so treating an
29
+ * unlisted capability as `standard` can only ever under-promise (the backend
30
+ * still challenges, and core still drives it).
31
+ */
32
+ import { isStapelApiError } from "@stapel/core";
33
+ /** The verification scope every `high` workspace capability is gated under. */
34
+ export const SENSITIVE_SCOPE = "sensitive";
35
+ /** PORT of `BUILTIN_CAPABILITY_LEVELS` — everything unlisted is `standard`. */
36
+ export const BUILTIN_CAPABILITY_LEVELS = {
37
+ "members.provision": "high",
38
+ "members.password.reset": "high",
39
+ "workspace.security.manage": "high",
40
+ };
41
+ /** The declared step-up level of one capability string. */
42
+ export function capabilityLevel(capability) {
43
+ return BUILTIN_CAPABILITY_LEVELS[capability] ?? "standard";
44
+ }
45
+ function asRecord(value) {
46
+ return typeof value === "object" && value !== null && !Array.isArray(value)
47
+ ? value
48
+ : null;
49
+ }
50
+ /**
51
+ * Read the enrollment demand out of a rejected request, or `null` when the
52
+ * error is anything else (including a step-up CHALLENGE, which carries a
53
+ * `challenge_id` and is core's business, not the consumer's).
54
+ */
55
+ export function readVerificationEnrollment(error) {
56
+ // Both dialects, narrowed through the imported predicate (never through a
57
+ // shape this call site invented): the typed error carries the parsed body,
58
+ // a rethrown raw envelope IS the body.
59
+ const body = asRecord(isStapelApiError(error) ? error.body : error);
60
+ if (body === null)
61
+ return null;
62
+ const verification = asRecord(body["verification"]);
63
+ if (verification === null)
64
+ return null;
65
+ if (verification["enroll"] !== true)
66
+ return null;
67
+ if (typeof verification["challenge_id"] === "string")
68
+ return null;
69
+ const factors = verification["factors"];
70
+ return {
71
+ scope: typeof verification["scope"] === "string"
72
+ ? verification["scope"]
73
+ : SENSITIVE_SCOPE,
74
+ factors: Array.isArray(factors)
75
+ ? factors.filter((f) => typeof f === "string")
76
+ : [],
77
+ };
78
+ }
79
+ //# sourceMappingURL=stepUp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stepUp.js","sourceRoot":"","sources":["../../src/model/stepUp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEhD,+EAA+E;AAC/E,MAAM,CAAC,MAAM,eAAe,GAAG,WAAW,CAAC;AAK3C,+EAA+E;AAC/E,MAAM,CAAC,MAAM,yBAAyB,GAAqC;IACzE,mBAAmB,EAAE,MAAM;IAC3B,wBAAwB,EAAE,MAAM;IAChC,2BAA2B,EAAE,MAAM;CACpC,CAAC;AAEF,2DAA2D;AAC3D,MAAM,UAAU,eAAe,CAAC,UAAkB;IAChD,OAAO,yBAAyB,CAAC,UAAU,CAAC,IAAI,UAAU,CAAC;AAC7D,CAAC;AAaD,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QACzE,CAAC,CAAE,KAAiC;QACpC,CAAC,CAAC,IAAI,CAAC;AACX,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,0BAA0B,CACxC,KAAc;IAEd,0EAA0E;IAC1E,2EAA2E;IAC3E,uCAAuC;IACvC,MAAM,IAAI,GAAG,QAAQ,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IACpE,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC/B,MAAM,YAAY,GAAG,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC;IACpD,IAAI,YAAY,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACvC,IAAI,YAAY,CAAC,QAAQ,CAAC,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACjD,IAAI,OAAO,YAAY,CAAC,cAAc,CAAC,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAClE,MAAM,OAAO,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;IACxC,OAAO;QACL,KAAK,EACH,OAAO,YAAY,CAAC,OAAO,CAAC,KAAK,QAAQ;YACvC,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC;YACvB,CAAC,CAAC,eAAe;QACrB,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;YAC7B,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC;YAC3D,CAAC,CAAC,EAAE;KACP,CAAC;AACJ,CAAC"}
package/llms.txt CHANGED
@@ -1,6 +1,6 @@
1
- # @stapel/workspaces-react 0.7.0
1
+ # @stapel/workspaces-react 0.8.0
2
2
 
3
- Headless React flow pair for stapel-workspaces (contract >=0.8 <0.9) — business + state, zero visual opinion.
3
+ Headless React flow pair for stapel-workspaces (contract >=0.14 <0.15) — business + state, zero visual opinion.
4
4
  Built on @stapel/core: typed client + StapelApiError envelope, auth token refresh,
5
5
  verification-403 interception, i18n engine, analytics facade, TanStack Query layer.
6
6
 
@@ -31,11 +31,15 @@ Paths are relative to `/workspaces/api/v1/`.
31
31
  - workspaces_api_v1_invitations_accept_create: POST /invitations/accept
32
32
  - workspaces_api_v1_invitations_claim_create: POST /invitations/{token}/claim
33
33
  - workspaces_api_v1_invitations_decline_create: POST /invitations/{token}/decline
34
+ - workspaces_api_v1_invitations_list: GET /{workspace_id}/invitations
35
+ - workspaces_api_v1_invitations_resend_create: POST /{workspace_id}/invitations/{invitation_id}/resend
34
36
  - workspaces_api_v1_invitations_retrieve: GET /invitations/{token}
37
+ - workspaces_api_v1_invitations_revoke_create: POST /{workspace_id}/invitations/{invitation_id}/revoke
35
38
  - workspaces_api_v1_members_destroy: DELETE /{workspace_id}/members/{user_id}
36
39
  - workspaces_api_v1_members_invite_create: POST /{workspace_id}/members/invite
37
40
  - workspaces_api_v1_members_list: GET /{workspace_id}/members
38
41
  - workspaces_api_v1_members_partial_update: PATCH /{workspace_id}/members/{user_id}
42
+ - workspaces_api_v1_members_password_reset_create: POST /{workspace_id}/members/{user_id}/password/reset
39
43
  - workspaces_api_v1_members_provision_create: POST /{workspace_id}/members/provision
40
44
  - workspaces_api_v1_partial_update: PATCH /{workspace_id}
41
45
  - workspaces_api_v1_retrieve: GET /
@@ -49,11 +53,16 @@ Paths are relative to `/workspaces/api/v1/`.
49
53
  - useDeclineInvitation (mutation) → declineInvitation
50
54
  - useDeleteWorkspace (mutation) → deleteWorkspace
51
55
  - useInvitationPreview (query) → getInvitationPreview
56
+ - useInvitations (query) → listInvitations
52
57
  - useInviteMembers (mutation) → inviteMembers
53
58
  - useMembers (query) → listMembers
54
59
  - useRemoveMember (mutation) → removeMember
60
+ - useResendInvitation (mutation) → resendInvitation
61
+ - useResetMemberPassword (mutation) → resetMemberPassword
62
+ - useRevokeInvitation (mutation) → revokeInvitation
55
63
  - useRoles (query) → listRoles
56
64
  - useUpdateMemberRole (mutation) → updateMemberRole
65
+ - useUpdateSecuritySettings (mutation) → getWorkspace+updateWorkspace
57
66
  - useUpdateWorkspace (mutation) → updateWorkspace
58
67
  - useWorkspace (query) → getWorkspace
59
68
  - useWorkspaces (query) → listWorkspaces