@stapel/workspaces-react 0.8.0 → 0.9.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 (45) hide show
  1. package/dist/api/generated/schema.d.ts +107 -2
  2. package/dist/api/generated/schema.d.ts.map +1 -1
  3. package/dist/api/types.d.ts +7 -0
  4. package/dist/api/types.d.ts.map +1 -1
  5. package/dist/api/workspacesApi.d.ts +3 -1
  6. package/dist/api/workspacesApi.d.ts.map +1 -1
  7. package/dist/api/workspacesApi.js +1 -0
  8. package/dist/api/workspacesApi.js.map +1 -1
  9. package/dist/default/MembersManager.js +2 -2
  10. package/dist/i18n/generated/errors.gen.d.ts +6 -0
  11. package/dist/i18n/generated/errors.gen.d.ts.map +1 -1
  12. package/dist/i18n/generated/errors.gen.js +3 -0
  13. package/dist/i18n/generated/errors.gen.js.map +1 -1
  14. package/dist/i18n/generated/errors.ru.gen.d.ts.map +1 -1
  15. package/dist/i18n/generated/errors.ru.gen.js +1 -0
  16. package/dist/i18n/generated/errors.ru.gen.js.map +1 -1
  17. package/dist/index.d.ts +1 -1
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +1 -1
  20. package/dist/index.js.map +1 -1
  21. package/dist/model/mutations.d.ts +1 -1
  22. package/dist/model/mutations.js +1 -1
  23. package/dist/model/queries.d.ts +19 -1
  24. package/dist/model/queries.d.ts.map +1 -1
  25. package/dist/model/queries.js +25 -0
  26. package/dist/model/queries.js.map +1 -1
  27. package/dist/model/queryKeys.d.ts +1 -0
  28. package/dist/model/queryKeys.d.ts.map +1 -1
  29. package/dist/model/queryKeys.js +2 -1
  30. package/dist/model/queryKeys.js.map +1 -1
  31. package/llms.txt +6 -3
  32. package/manifest.json +26 -2
  33. package/package.json +2 -2
  34. package/src/analytics/generated/events.json +1 -1
  35. package/src/api/generated/schema.ts +107 -2
  36. package/src/api/types.ts +8 -0
  37. package/src/api/workspacesApi.ts +6 -0
  38. package/src/default/MembersManager.tsx +2 -2
  39. package/src/i18n/generated/errors.gen.ts +3 -0
  40. package/src/i18n/generated/errors.json +9 -0
  41. package/src/i18n/generated/errors.ru.gen.ts +1 -0
  42. package/src/index.ts +1 -0
  43. package/src/model/mutations.ts +1 -1
  44. package/src/model/queries.ts +30 -0
  45. package/src/model/queryKeys.ts +3 -1
@@ -1,6 +1,6 @@
1
1
  import type { InfiniteData, UseInfiniteQueryResult, UseQueryResult } from "@tanstack/react-query";
2
2
  import type { StapelApiError } from "@stapel/core";
3
- import type { InvitationPage, InvitationPreview, InvitationsParams, MemberPage, MembersParams, RoleInfo, Workspace, WorkspaceList } from "../api/types.js";
3
+ import type { InvitationPage, InvitationPreview, InstanceShape, InvitationsParams, MemberPage, MembersParams, RoleInfo, Workspace, WorkspaceList } from "../api/types.js";
4
4
  import type { CapabilityLevel } from "./stepUp.js";
5
5
  /**
6
6
  * Read hooks over the workspaces API. Staleness follows core's query defaults;
@@ -70,6 +70,24 @@ export declare function useInfiniteInvitations(workspaceId: string | null, filte
70
70
  * {@link useWorkspaces} (IsAuthenticated endpoint, mounts at screen top).
71
71
  */
72
72
  export declare function useRoles(): UseQueryResult<readonly RoleInfo[], StapelApiError>;
73
+ /**
74
+ * Deployment shape (GET /instance, unauthenticated).
75
+ *
76
+ * Answers the question a screen must ask BEFORE deciding what to show
77
+ * someone with no workspace: is this a closed deployment (`landing:
78
+ * "none"` — no workspace exists and none can be created) or a public cloud
79
+ * (`"personal"` — one exists and the screen can lead there)?
80
+ *
81
+ * Why a hook instead of a profile field: the reader is exactly the person
82
+ * who has no access — kicked out of their workspace, or having left it. So
83
+ * the request deliberately does NOT wait for a session, unlike {@link
84
+ * useRoles}: waiting would mean never answering the one person it exists for.
85
+ *
86
+ * The data is static per deployment — it only changes alongside the
87
+ * deployment itself, so the cache lives until page reload and is never
88
+ * refetched.
89
+ */
90
+ export declare function useInstanceShape(): UseQueryResult<InstanceShape, StapelApiError>;
73
91
  /**
74
92
  * Public invitation preview (GET /invitations/{token}, AllowAny — org-program
75
93
  * §B2): what the `/invite/{token}` page renders BEFORE any auth decision.
@@ -1 +1 @@
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
+ {"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../../src/model/queries.ts"],"names":[],"mappings":"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"}
@@ -129,6 +129,31 @@ export function useRoles() {
129
129
  enabled: sessionReady,
130
130
  });
131
131
  }
132
+ /**
133
+ * Deployment shape (GET /instance, unauthenticated).
134
+ *
135
+ * Answers the question a screen must ask BEFORE deciding what to show
136
+ * someone with no workspace: is this a closed deployment (`landing:
137
+ * "none"` — no workspace exists and none can be created) or a public cloud
138
+ * (`"personal"` — one exists and the screen can lead there)?
139
+ *
140
+ * Why a hook instead of a profile field: the reader is exactly the person
141
+ * who has no access — kicked out of their workspace, or having left it. So
142
+ * the request deliberately does NOT wait for a session, unlike {@link
143
+ * useRoles}: waiting would mean never answering the one person it exists for.
144
+ *
145
+ * The data is static per deployment — it only changes alongside the
146
+ * deployment itself, so the cache lives until page reload and is never
147
+ * refetched.
148
+ */
149
+ export function useInstanceShape() {
150
+ const api = useWorkspacesApi();
151
+ return useQuery({
152
+ queryKey: workspacesQueryKeys.instance(),
153
+ queryFn: () => api.getInstanceShape(),
154
+ staleTime: Infinity,
155
+ });
156
+ }
132
157
  /**
133
158
  * Public invitation preview (GET /invitations/{token}, AllowAny — org-program
134
159
  * §B2): what the `/invite/{token}` page renders BEFORE any auth decision.
@@ -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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"}
@@ -15,6 +15,7 @@ export declare const workspacesQueryKeys: {
15
15
  InvitationsParams
16
16
  ];
17
17
  roles(): readonly ["workspaces", "roles"];
18
+ instance(): readonly ["workspaces", "instance"];
18
19
  invitationPreview(token: string): readonly ["workspaces", "invitation-preview", string];
19
20
  };
20
21
  //# sourceMappingURL=queryKeys.d.ts.map
@@ -1 +1 @@
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"}
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,QAAQ,IAAI,SAAS,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;IAChD,iBAAiB,CACf,KAAK,EAAE,MAAM,GACZ,SAAS,CAAC,YAAY,EAAE,oBAAoB,EAAE,MAAM,CAAC,CAAC;CAmC1D,CAAC"}
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Namespaced TanStack Query keys (frontend-standard §2 — "ключи неймспейснуты").
2
+ * Namespaced TanStack Query keys (frontend-standard §2 — namespaced keys).
3
3
  * Everything under the `"workspaces"` root so a host can invalidate the whole
4
4
  * module or match a single resource. Persist scope is per-user via core's query
5
5
  * runtime (`setPersistUser`). Explicit tuple return types satisfy
@@ -34,6 +34,7 @@ export const workspacesQueryKeys = {
34
34
  filters,
35
35
  ],
36
36
  roles: () => [ROOT, "roles"],
37
+ instance: () => [ROOT, "instance"],
37
38
  // NOTE: the key carries the invite TOKEN (a secret). Core's query persist
38
39
  // scope is per-user and the preview response is already public-by-design
39
40
  // (masked email only) — but hosts logging query keys should treat this one
@@ -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,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"}
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,GA6B5B;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,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC,IAAI,EAAE,UAAU,CAAC;IAClC,0EAA0E;IAC1E,yEAAyE;IACzE,2EAA2E;IAC3E,gBAAgB;IAChB,iBAAiB,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,oBAAoB,EAAE,KAAK,CAAC;CAClE,CAAC"}
package/llms.txt CHANGED
@@ -1,6 +1,6 @@
1
- # @stapel/workspaces-react 0.8.0
1
+ # @stapel/workspaces-react 0.9.0
2
2
 
3
- Headless React flow pair for stapel-workspaces (contract >=0.14 <0.15) — business + state, zero visual opinion.
3
+ Headless React flow pair for stapel-workspaces (contract >=0.18 <0.19) — 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
 
@@ -26,6 +26,7 @@ Request/response schema names are in manifest.json + the generated types.
26
26
  Paths are relative to `/workspaces/api/v1/`.
27
27
  - workspaces_api_v1_create: POST /
28
28
  - workspaces_api_v1_destroy: DELETE /{workspace_id}
29
+ - workspaces_api_v1_instance_retrieve: GET /instance
29
30
  - workspaces_api_v1_internal_members_retrieve: GET /internal/{workspace_id}/members/{user_id}
30
31
  - workspaces_api_v1_internal_users_personal_create: POST /internal/users/{user_id}/personal
31
32
  - workspaces_api_v1_invitations_accept_create: POST /invitations/accept
@@ -52,6 +53,7 @@ Paths are relative to `/workspaces/api/v1/`.
52
53
  - useCreateWorkspace (mutation) → createWorkspace
53
54
  - useDeclineInvitation (mutation) → declineInvitation
54
55
  - useDeleteWorkspace (mutation) → deleteWorkspace
56
+ - useInstanceShape (query) → getInstanceShape
55
57
  - useInvitationPreview (query) → getInvitationPreview
56
58
  - useInvitations (query) → listInvitations
57
59
  - useInviteMembers (mutation) → inviteMembers
@@ -68,7 +70,7 @@ Paths are relative to `/workspaces/api/v1/`.
68
70
  - useWorkspaces (query) → listWorkspaces
69
71
 
70
72
  ## Errors (render t(code, params); UX from remediation)
71
- 60 keys (full catalog: manifest.json §errors). By remediation: fix_input 28 · retry 12 · contact_support 7 · wait_and_retry 6 · verify 5 · reauthenticate 2.
73
+ 61 keys (full catalog: manifest.json §errors). By remediation: fix_input 29 · retry 12 · contact_support 7 · wait_and_retry 6 · verify 5 · reauthenticate 2.
72
74
  Param-bearing keys (interpolation slots matter):
73
75
  - error.400.field.blank [400] → fix_input {field}
74
76
  - error.400.field.does_not_exist [400] → fix_input {field}
@@ -84,6 +86,7 @@ Param-bearing keys (interpolation slots matter):
84
86
  - error.402.member_limit_reached [402] → fix_input {limit}
85
87
  - error.403.membership_suspended [403] → fix_input {reason}
86
88
  - error.403.missing_capability [403] → contact_support {capability}
89
+ - error.403.role_exceeds_inviter_rank [403] → fix_input {role}
87
90
  - error.429.rate_limit [429] → wait_and_retry {retry_after_minutes}
88
91
 
89
92
  ## Analytics events (typed; defineEvent → events.json, drift-gated)
package/manifest.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "$generated": "by scripts/gen-manifest.mjs — do not edit; drift-gated (pnpm gen:manifest:check)",
3
3
  "package": "@stapel/workspaces-react",
4
- "version": "0.8.0",
4
+ "version": "0.9.0",
5
5
  "backend": {
6
6
  "module": "stapel-workspaces",
7
- "contract": ">=0.14 <0.15"
7
+ "contract": ">=0.18 <0.19"
8
8
  },
9
9
  "layers": [
10
10
  "api",
@@ -32,6 +32,13 @@
32
32
  "request": null,
33
33
  "response": null
34
34
  },
35
+ "workspaces_api_v1_instance_retrieve": {
36
+ "method": "GET",
37
+ "path": "/workspaces/api/v1/instance",
38
+ "tag": "Workspaces",
39
+ "request": null,
40
+ "response": "InstanceShapeResponse"
41
+ },
35
42
  "workspaces_api_v1_internal_members_retrieve": {
36
43
  "method": "GET",
37
44
  "path": "/workspaces/api/v1/internal/{workspace_id}/members/{user_id}",
@@ -222,6 +229,14 @@
222
229
  ]
223
230
  ]
224
231
  },
232
+ "useInstanceShape": {
233
+ "kind": "query",
234
+ "operation": "getInstanceShape",
235
+ "queryKey": [
236
+ "workspaces",
237
+ "instance"
238
+ ]
239
+ },
225
240
  "useInvitationPreview": {
226
241
  "kind": "query",
227
242
  "operation": "getInvitationPreview",
@@ -604,6 +619,13 @@
604
619
  "params": [],
605
620
  "remediation": "contact_support"
606
621
  },
622
+ "error.403.role_exceeds_inviter_rank": {
623
+ "status": 403,
624
+ "params": [
625
+ "role"
626
+ ],
627
+ "remediation": "fix_input"
628
+ },
607
629
  "error.403.verification_enrollment_required": {
608
630
  "status": 403,
609
631
  "params": [],
@@ -863,6 +885,7 @@
863
885
  "error.403.membership_suspended",
864
886
  "error.403.missing_capability",
865
887
  "error.403.network_blocked",
888
+ "error.403.role_exceeds_inviter_rank",
866
889
  "error.403.verification_enrollment_required",
867
890
  "error.403.verification_required",
868
891
  "error.404.ad_not_found",
@@ -989,6 +1012,7 @@
989
1012
  "useDeleteWorkspace",
990
1013
  "useFlow",
991
1014
  "useInfiniteInvitations",
1015
+ "useInstanceShape",
992
1016
  "useInvitationPreview",
993
1017
  "useInvitations",
994
1018
  "useInviteMembers",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stapel/workspaces-react",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "Headless React flow pair for stapel-workspaces: typed API client, TanStack Query hooks, flow machines, headless components, and i18n keys. Zero visual opinion.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -82,8 +82,8 @@
82
82
  "size-limit": "^11.2.0",
83
83
  "typescript": "^5.8.3",
84
84
  "vitest": "^3.2.4",
85
+ "@stapel/core": "^0.10.0",
85
86
  "@stapel/showcase": "^0.2.0",
86
- "@stapel/core": "^0.9.0",
87
87
  "@stapel/tokens": "^0.5.0"
88
88
  },
89
89
  "engines": {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$generated": "by scripts/gen-events.mjs — do not edit; drift-gated (pnpm gen:events:check)",
3
3
  "package": "@stapel/workspaces-react",
4
- "version": "0.8.0",
4
+ "version": "0.9.0",
5
5
  "defined": [],
6
6
  "flows": []
7
7
  }
@@ -403,6 +403,27 @@ export interface paths {
403
403
  patch?: never;
404
404
  trace?: never;
405
405
  };
406
+ "/workspaces/api/v1/instance": {
407
+ parameters: {
408
+ query?: never;
409
+ header?: never;
410
+ path?: never;
411
+ cookie?: never;
412
+ };
413
+ /**
414
+ * @description Instance shape: how a street signup lands (personal | none) and whether self-serve registration is open. Public, unauthenticated — the screen a kicked/left member sees depends on it.
415
+ *
416
+ * **Permissions:** `AllowAny`
417
+ */
418
+ get: operations["workspaces_api_v1_instance_retrieve"];
419
+ put?: never;
420
+ post?: never;
421
+ delete?: never;
422
+ options?: never;
423
+ head?: never;
424
+ patch?: never;
425
+ trace?: never;
426
+ };
406
427
  "/workspaces/api/v1/internal/{workspace_id}/members/{user_id}": {
407
428
  parameters: {
408
429
  query?: never;
@@ -585,6 +606,38 @@ export interface paths {
585
606
  export type webhooks = Record<string, never>;
586
607
  export interface components {
587
608
  schemas: {
609
+ /**
610
+ * @description Как развёрнут ЭТОТ инстанс — то, что клиенту нужно знать ДО того, как
611
+ * он решит, что показать человеку без пространства.
612
+ *
613
+ * Ось ``landing`` (``STREET_LANDING_MODE``) существовала с 03.08.2026, но
614
+ * жила только в окружении бэкенда: наружу не отдавалась ничем, и отличить
615
+ * закрытый контур от публичного облака на клиенте было НЕЧЕМ.
616
+ *
617
+ * Почему это не косметика. Экран, который видит человек, выброшенный из
618
+ * Спейса (или вышедший сам), в этих двух мирах разный по существу:
619
+ *
620
+ * * ``none`` — закрытый контур: своего пространства у человека нет и
621
+ * взяться неоткуда. Честный экран говорит «вы не участник, попросите
622
+ * приглашение» и никуда не зовёт;
623
+ * * ``personal`` — публичное облако: у него есть собственное
624
+ * пространство, и туда можно вести.
625
+ *
626
+ * Показать «создайте встречу» тому, кому инстанс её создать не даст, —
627
+ * это тупик, нарисованный кнопкой.
628
+ */
629
+ InstanceShapeResponse: {
630
+ /**
631
+ * @description С чем приземляется человек «с улицы»
632
+ * @example personal
633
+ */
634
+ landing: string;
635
+ /**
636
+ * @description Можно ли завести учётку самому
637
+ * @example True
638
+ */
639
+ registration_open: boolean;
640
+ };
588
641
  /** @description Get-or-create result for a user's personal workspace (service-to-service). */
589
642
  InternalPersonalWorkspaceResponse: {
590
643
  /**
@@ -692,9 +745,19 @@ export interface components {
692
745
  * @example 0192a...
693
746
  */
694
747
  invited_by_id?: string | null;
748
+ /**
749
+ * @description Name hint typed for this invitee at invite time, if any; null otherwise
750
+ * @example Ada Lovelace
751
+ */
752
+ display_name?: string | null;
695
753
  };
696
754
  /** @description Invite payload. */
697
755
  MemberInviteRequest: {
756
+ /**
757
+ * @description Name hint for the invitee (this invite's "Имя" field), applied to every email in this request. Optional — an invite without one behaves exactly as before. NOT written into stapel-profiles directly (that store is the invitee's own): held on the invitation, copied onto the member at accept time, and shown only until stapel-profiles has a real name for the person
758
+ * @example Ada Lovelace
759
+ */
760
+ display_name?: string | null;
698
761
  /**
699
762
  * @description One or more emails to invite
700
763
  * @example [
@@ -793,6 +856,11 @@ export interface components {
793
856
  suspended_at?: string | null;
794
857
  /** @description Why the membership is suspended (canonical value no_mfa); null while active */
795
858
  suspension_reason?: string | null;
859
+ /**
860
+ * @description Best-effort display name — a live lookup in stapel-profiles when it is installed and has one, else the name typed at invite/provision time (never both, never invented when neither exists). Null when nobody has one yet
861
+ * @example Ada Lovelace
862
+ */
863
+ display_name?: string | null;
796
864
  };
797
865
  PaginatedInvitationResponseList: {
798
866
  items: components["schemas"]["InvitationResponse"][];
@@ -874,9 +942,19 @@ export interface components {
874
942
  /** @description Server-generated initial password — returned exactly ONCE, only when the request omitted password. Store it or hand it to the user now; it cannot be re-fetched. A credential: never log it */
875
943
  generated_password?: string | null;
876
944
  };
877
- /** @description RoleListResponse(roles: List[stapel_workspaces.dto.RoleResponse] = <factory>) */
945
+ /** @description The effective role registry (builtin four + STAPEL_WORKSPACES overlay). */
878
946
  RoleListResponse: {
947
+ /** @description One entry per effective role, descending rank */
879
948
  roles?: components["schemas"]["RoleResponse"][];
949
+ /**
950
+ * @description Step-up level per namespaced capability string, builtin ``members.provision`` / ``members.password.reset`` / ``workspace.security.manage`` plus the deployment's ``STAPEL_WORKSPACES["CAPABILITY_LEVELS"]`` overlay. A capability absent from this map is ``"standard"`` — the client-side default. Lets a frontend stop hardcoding its own copy of this registry
951
+ * @example {
952
+ * "members.provision": "high"
953
+ * }
954
+ */
955
+ capability_levels?: {
956
+ [key: string]: string;
957
+ };
880
958
  };
881
959
  /** @description One role of the effective registry (builtin + STAPEL_WORKSPACES overlay). */
882
960
  RoleResponse: {
@@ -943,9 +1021,17 @@ export interface components {
943
1021
  */
944
1022
  type?: string;
945
1023
  };
946
- /** @description WorkspaceListResponse(workspaces: List[stapel_workspaces.dto.WorkspaceResponse] = <factory>) */
1024
+ /** @description The caller's own workspace list. */
947
1025
  WorkspaceListResponse: {
1026
+ /** @description The caller's active memberships (empty for a guest — see is_guest) */
948
1027
  workspaces?: components["schemas"]["WorkspaceResponse"][];
1028
+ /** @description True when the caller holds NO active mandate anywhere (permissions.is_guest) — the wire form of the mandate-model vardict's guest predicate (2026-08-03), so a frontend can render the "incomplete dashboard" without re-deriving it from workspaces == [] */
1029
+ is_guest?: boolean;
1030
+ /**
1031
+ * @description Which workspace a client should open when the person has expressed no choice — the instance's STAPEL_WORKSPACES["DEFAULT_WORKSPACE_ID"], echoed back ONLY when the caller actually holds an active membership in it, else "". Exists because clients that had to guess guessed badly: meettoday took `workspaces[0]` off a list ordered by last access, so a person in two spaces landed wherever they happened to have been last (measured 2026-08-06 as "the owner cannot see his own invitations" — they were in the OTHER space). A default, not a cage: an explicit choice still wins
1032
+ * @example a8bba7ae-5d2e-43e5-9911-0553e7df50b3
1033
+ */
1034
+ default_workspace_id?: string;
949
1035
  };
950
1036
  /** @description Workspace details. */
951
1037
  WorkspaceResponse: {
@@ -1368,6 +1454,25 @@ export interface operations {
1368
1454
  };
1369
1455
  };
1370
1456
  };
1457
+ workspaces_api_v1_instance_retrieve: {
1458
+ parameters: {
1459
+ query?: never;
1460
+ header?: never;
1461
+ path?: never;
1462
+ cookie?: never;
1463
+ };
1464
+ requestBody?: never;
1465
+ responses: {
1466
+ 200: {
1467
+ headers: {
1468
+ [name: string]: unknown;
1469
+ };
1470
+ content: {
1471
+ "application/json": components["schemas"]["InstanceShapeResponse"];
1472
+ };
1473
+ };
1474
+ };
1475
+ };
1371
1476
  workspaces_api_v1_internal_members_retrieve: {
1372
1477
  parameters: {
1373
1478
  query?: never;
package/src/api/types.ts CHANGED
@@ -68,6 +68,14 @@ export type RoleInfo = Schemas["RoleResponse"];
68
68
  /** GET /roles 200 body — the effective role registry, rank-descending. */
69
69
  export type RoleList = Schemas["RoleListResponse"];
70
70
 
71
+ /**
72
+ * Deployment shape: what a person landing "off the street" gets, and
73
+ * whether self-serve signup is open. A property of the INSTANCE, not of a
74
+ * workspace — and not a setting the customer can toggle: it's fixed at
75
+ * deployment time.
76
+ */
77
+ export type InstanceShape = Schemas["InstanceShapeResponse"];
78
+
71
79
  // ── documented corrections (drf-spectacular under-describes) ──────────────────
72
80
 
73
81
  /**
@@ -14,6 +14,7 @@ import type {
14
14
  InvitationAccept,
15
15
  InvitationClaim,
16
16
  InvitationPreview,
17
+ InstanceShape,
17
18
  RoleList,
18
19
  Workspace,
19
20
  WorkspaceCreate,
@@ -171,6 +172,9 @@ export interface WorkspacesApi {
171
172
  /** The effective role registry (builtin + deployment overlay), for
172
173
  * RoleSelect-class UI — capability strings verbatim, rank-descending. */
173
174
  listRoles(): Promise<RoleList>;
175
+
176
+ /** Instance shape (GET /instance, unauthenticated). */
177
+ getInstanceShape(): Promise<InstanceShape>;
174
178
  }
175
179
 
176
180
  export function createWorkspacesApi(client: StapelClient): WorkspacesApi {
@@ -284,5 +288,7 @@ export function createWorkspacesApi(client: StapelClient): WorkspacesApi {
284
288
  ),
285
289
 
286
290
  listRoles: () => client.get("/roles"),
291
+
292
+ getInstanceShape: () => client.get("/instance"),
287
293
  };
288
294
  }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * `<MembersManager/>` — default skin for the "members & roles" settings
3
- * screen (owner directive: "настройки воркспейса (имя/участники/роли/
4
- * инвайты)"). Built entirely on this pair's EXISTING `Members` headless
3
+ * screen (owner directive: workspace settings — name/members/roles/
4
+ * invites). Built entirely on this pair's EXISTING `Members` headless
5
5
  * wrapper (`useMembers`/`useInviteMembers`/`useUpdateMemberRole`/
6
6
  * `useRemoveMember`) — no new backend surface.
7
7
  *
@@ -72,6 +72,7 @@ export const WORKSPACES_ERRORS = {
72
72
  "error.403.membership_suspended": { status: 403, params: ["reason"], remediation: "fix_input", en: "Your membership in this workspace is suspended ({reason})" },
73
73
  "error.403.missing_capability": { status: 403, params: ["capability"], remediation: "contact_support", en: "Your role does not include the {capability} capability in this workspace" },
74
74
  "error.403.network_blocked": { status: 403, params: [], remediation: "contact_support", en: "Requests from this network are not allowed" },
75
+ "error.403.role_exceeds_inviter_rank": { status: 403, params: ["role"], remediation: "fix_input", en: "You cannot grant a role that outranks your own ({role})" },
75
76
  "error.403.verification_enrollment_required": { status: 403, params: [], remediation: "verify", en: "Verification factor enrollment required" },
76
77
  "error.403.verification_required": { status: 403, params: [], remediation: "verify", en: "Additional verification required" },
77
78
  "error.404.ad_not_found": { status: 404, params: [], remediation: "retry", en: "Listing not found" },
@@ -138,6 +139,7 @@ export const WORKSPACES_ERROR_CODES: readonly WorkspacesErrorCode[] = [
138
139
  "error.403.membership_suspended",
139
140
  "error.403.missing_capability",
140
141
  "error.403.network_blocked",
142
+ "error.403.role_exceeds_inviter_rank",
141
143
  "error.403.verification_enrollment_required",
142
144
  "error.403.verification_required",
143
145
  "error.404.ad_not_found",
@@ -206,6 +208,7 @@ export const workspacesErrorBundleEn: Record<WorkspacesErrorCode, string> = {
206
208
  "error.403.membership_suspended": "Your membership in this workspace is suspended ({reason})",
207
209
  "error.403.missing_capability": "Your role does not include the {capability} capability in this workspace",
208
210
  "error.403.network_blocked": "Requests from this network are not allowed",
211
+ "error.403.role_exceeds_inviter_rank": "You cannot grant a role that outranks your own ({role})",
209
212
  "error.403.verification_enrollment_required": "Verification factor enrollment required",
210
213
  "error.403.verification_required": "Additional verification required",
211
214
  "error.404.ad_not_found": "Listing not found",
@@ -290,6 +290,15 @@
290
290
  "remediation": "contact_support",
291
291
  "en": "Requests from this network are not allowed"
292
292
  },
293
+ {
294
+ "code": "error.403.role_exceeds_inviter_rank",
295
+ "status": 403,
296
+ "params": [
297
+ "role"
298
+ ],
299
+ "remediation": "fix_input",
300
+ "en": "You cannot grant a role that outranks your own ({role})"
301
+ },
293
302
  {
294
303
  "code": "error.403.verification_enrollment_required",
295
304
  "status": 403,
@@ -49,6 +49,7 @@ export const workspacesErrorBundleRu: Record<WorkspacesErrorCode, string> = {
49
49
  "error.403.membership_suspended": "Ваше членство в этом рабочем пространстве приостановлено ({reason})",
50
50
  "error.403.missing_capability": "Ваша роль не включает право {capability} в этом рабочем пространстве",
51
51
  "error.403.network_blocked": "Запросы из этой сети не разрешены.",
52
+ "error.403.role_exceeds_inviter_rank": "Вы не можете выдать роль, которая превышает вашу собственную ({role})",
52
53
  "error.403.verification_enrollment_required": "Требуется регистрация фактора подтверждения.",
53
54
  "error.403.verification_required": "Требуется дополнительная проверка",
54
55
  "error.404.ad_not_found": "Объявление не найдено",
package/src/index.ts CHANGED
@@ -60,6 +60,7 @@ export {
60
60
  useInvitations,
61
61
  useInfiniteInvitations,
62
62
  useRoles,
63
+ useInstanceShape,
63
64
  useInvitationPreview,
64
65
  useCapabilities,
65
66
  useCapabilityGate,
@@ -22,7 +22,7 @@ import { useWorkspacesApi } from "./context.js";
22
22
  import { workspacesQueryKeys } from "./queryKeys.js";
23
23
 
24
24
  /**
25
- * Write hooks (frontend-standard §2 — "мутации с инвалидацией"). Each mutation
25
+ * Write hooks (frontend-standard §2 — mutations invalidate on success). Each mutation
26
26
  * invalidates exactly the server state it can move. Membership and ownership are
27
27
  * server truth (roles gate access in other services via the membership cache),
28
28
  * so NONE of these are optimistic (frontend-core-architecture §2.6: optimistic
@@ -9,6 +9,7 @@ import type { StapelApiError } from "@stapel/core";
9
9
  import type {
10
10
  InvitationPage,
11
11
  InvitationPreview,
12
+ InstanceShape,
12
13
  InvitationsParams,
13
14
  MemberPage,
14
15
  MembersParams,
@@ -173,6 +174,35 @@ export function useRoles(): UseQueryResult<
173
174
  });
174
175
  }
175
176
 
177
+ /**
178
+ * Deployment shape (GET /instance, unauthenticated).
179
+ *
180
+ * Answers the question a screen must ask BEFORE deciding what to show
181
+ * someone with no workspace: is this a closed deployment (`landing:
182
+ * "none"` — no workspace exists and none can be created) or a public cloud
183
+ * (`"personal"` — one exists and the screen can lead there)?
184
+ *
185
+ * Why a hook instead of a profile field: the reader is exactly the person
186
+ * who has no access — kicked out of their workspace, or having left it. So
187
+ * the request deliberately does NOT wait for a session, unlike {@link
188
+ * useRoles}: waiting would mean never answering the one person it exists for.
189
+ *
190
+ * The data is static per deployment — it only changes alongside the
191
+ * deployment itself, so the cache lives until page reload and is never
192
+ * refetched.
193
+ */
194
+ export function useInstanceShape(): UseQueryResult<
195
+ InstanceShape,
196
+ StapelApiError
197
+ > {
198
+ const api = useWorkspacesApi();
199
+ return useQuery({
200
+ queryKey: workspacesQueryKeys.instance(),
201
+ queryFn: () => api.getInstanceShape(),
202
+ staleTime: Infinity,
203
+ });
204
+ }
205
+
176
206
  /**
177
207
  * Public invitation preview (GET /invitations/{token}, AllowAny — org-program
178
208
  * §B2): what the `/invite/{token}` page renders BEFORE any auth decision.
@@ -1,7 +1,7 @@
1
1
  import type { InvitationsParams, MembersParams } from "../api/types.js";
2
2
 
3
3
  /**
4
- * Namespaced TanStack Query keys (frontend-standard §2 — "ключи неймспейснуты").
4
+ * Namespaced TanStack Query keys (frontend-standard §2 — namespaced keys).
5
5
  * Everything under the `"workspaces"` root so a host can invalidate the whole
6
6
  * module or match a single resource. Persist scope is per-user via core's query
7
7
  * runtime (`setPersistUser`). Explicit tuple return types satisfy
@@ -34,6 +34,7 @@ export const workspacesQueryKeys: {
34
34
  InvitationsParams,
35
35
  ];
36
36
  roles(): readonly ["workspaces", "roles"];
37
+ instance(): readonly ["workspaces", "instance"];
37
38
  invitationPreview(
38
39
  token: string
39
40
  ): readonly ["workspaces", "invitation-preview", string];
@@ -65,6 +66,7 @@ export const workspacesQueryKeys: {
65
66
  filters,
66
67
  ],
67
68
  roles: () => [ROOT, "roles"],
69
+ instance: () => [ROOT, "instance"],
68
70
  // NOTE: the key carries the invite TOKEN (a secret). Core's query persist
69
71
  // scope is per-user and the preview response is already public-by-design
70
72
  // (masked email only) — but hosts logging query keys should treat this one