@astrale-domains/shell 0.1.6 → 0.1.8

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 (309) hide show
  1. package/README.md +73 -173
  2. package/dist/domain.d.ts +499 -31
  3. package/dist/domain.js +99 -78
  4. package/dist/functions/application/index.js +2 -1
  5. package/dist/functions/application/legacy/index.js +1 -0
  6. package/dist/functions/application/legacy/list-entrypoints.js +8 -0
  7. package/dist/functions/authority/capabilities.js +1 -0
  8. package/dist/functions/authority/composition.js +47 -0
  9. package/dist/functions/authority/index.js +2 -0
  10. package/dist/functions/authority/roles.js +113 -0
  11. package/dist/functions/directory/disconnect-directory.js +35 -0
  12. package/dist/functions/directory/index.js +1 -0
  13. package/dist/functions/group/assign-member.js +7 -0
  14. package/dist/functions/group/change-group-membership.js +101 -20
  15. package/dist/functions/group/create-group.js +23 -0
  16. package/dist/functions/group/delete-group.js +33 -0
  17. package/dist/functions/group/deprovision-group.js +27 -0
  18. package/dist/functions/group/group-errors.js +43 -0
  19. package/dist/functions/group/group-membership-errors.js +3 -1
  20. package/dist/functions/group/group.js +51 -0
  21. package/dist/functions/group/index.js +8 -2
  22. package/dist/functions/group/legacy/index.js +1 -0
  23. package/dist/functions/group/legacy/membership.js +64 -0
  24. package/dist/functions/group/membership-laws.js +37 -0
  25. package/dist/functions/group/provision-group.js +33 -0
  26. package/dist/functions/group/unassign-member.js +7 -0
  27. package/dist/functions/group/update-group.js +55 -0
  28. package/dist/functions/invitation/index.js +2 -0
  29. package/dist/functions/invitation/invitation-errors.js +13 -0
  30. package/dist/functions/invitation/invitation-methods.js +41 -0
  31. package/dist/functions/invitation/send-invitation.js +131 -0
  32. package/dist/functions/user/account.js +35 -0
  33. package/dist/functions/user/create-user.js +45 -0
  34. package/dist/functions/user/deactivate-user.js +19 -0
  35. package/dist/functions/user/delete-user.js +34 -0
  36. package/dist/functions/user/deprovision-user.js +21 -0
  37. package/dist/functions/user/index.js +15 -1
  38. package/dist/functions/user/invite-errors.js +18 -0
  39. package/dist/functions/user/invite-user.js +42 -34
  40. package/dist/functions/user/legacy/claimed-account.js +11 -0
  41. package/dist/functions/user/legacy/index.js +4 -0
  42. package/dist/functions/user/legacy/invite.js +20 -0
  43. package/dist/functions/user/legacy/migrate-accounts.js +98 -0
  44. package/dist/functions/user/legacy/record-profile.js +19 -0
  45. package/dist/functions/user/protect-administrators.js +16 -0
  46. package/dist/functions/user/provision-user.js +70 -0
  47. package/dist/functions/user/reactivate-user.js +19 -0
  48. package/dist/functions/user/read-account.js +12 -0
  49. package/dist/functions/user/request-invitation.js +17 -0
  50. package/dist/functions/user/update-profile.js +22 -0
  51. package/dist/functions/user/update-user.js +68 -0
  52. package/dist/functions/user/user-errors.js +69 -0
  53. package/dist/functions/user/write-account.js +57 -0
  54. package/dist/functions/view-access/index.js +2 -1
  55. package/dist/functions/view-access/{assign-views.js → legacy/assign-views.js} +11 -7
  56. package/dist/functions/view-access/legacy/index.js +1 -0
  57. package/dist/functions/view-access/{view-access-errors.js → legacy/view-access-errors.js} +5 -1
  58. package/dist/index.d.ts +1 -1
  59. package/dist/index.js +3 -1
  60. package/dist/integrations/user-invitation/invite-user-request.d.ts +6 -0
  61. package/dist/legacy/index.js +1 -0
  62. package/dist/legacy/release.js +33 -0
  63. package/dist/mutations/composition/grant-role.js +13 -0
  64. package/dist/mutations/composition/index.js +1 -0
  65. package/dist/mutations/group/index.js +1 -1
  66. package/dist/mutations/group/legacy/index.js +1 -0
  67. package/dist/mutations/group/legacy/membership-class.js +7 -0
  68. package/dist/mutations/group/set-group-membership.js +60 -19
  69. package/dist/mutations/identity/create-profile.js +37 -0
  70. package/dist/mutations/identity/delete-identity.js +28 -0
  71. package/dist/mutations/identity/index.js +4 -0
  72. package/dist/mutations/identity/write-account.js +109 -0
  73. package/dist/mutations/identity/write-group.js +72 -0
  74. package/dist/mutations/invitation/index.js +1 -0
  75. package/dist/mutations/invitation/write-invitation.js +79 -0
  76. package/dist/mutations/user/legacy/index.js +1 -0
  77. package/dist/mutations/user/{record-user-profile.js → legacy/record-user-profile.js} +5 -2
  78. package/dist/providers/admin-enrollment/create-admin-enrollment-provider.js +6 -3
  79. package/dist/providers/admin-enrollment/legacy/index.js +1 -0
  80. package/dist/providers/admin-enrollment/legacy/send-without-profile.js +16 -0
  81. package/dist/queries/application/legacy/index.js +1 -0
  82. package/dist/queries/application/legacy/read-installed-entrypoints.js +47 -0
  83. package/dist/queries/composition/index.js +2 -0
  84. package/dist/queries/composition/read-extensions.js +34 -0
  85. package/dist/queries/composition/read-role-nodes.js +76 -0
  86. package/dist/queries/group/index.js +2 -1
  87. package/dist/queries/group/legacy/index.js +3 -0
  88. package/dist/queries/group/legacy/read-core-groups.js +46 -0
  89. package/dist/queries/group/legacy/read-member-of-group.js +24 -0
  90. package/dist/queries/group/legacy/read-members-of-group.js +27 -0
  91. package/dist/queries/group/read-group-members.js +73 -0
  92. package/dist/queries/group/read-group-membership-endpoints.js +11 -0
  93. package/dist/queries/group/read-group-membership.js +6 -21
  94. package/dist/queries/identity/index.js +1 -0
  95. package/dist/queries/identity/read-identities.js +29 -0
  96. package/dist/queries/invitation/index.js +1 -0
  97. package/dist/queries/invitation/read-invitation.js +50 -0
  98. package/dist/queries/profile/index.js +1 -0
  99. package/dist/queries/profile/read-profile.js +15 -0
  100. package/dist/queries/role/index.js +1 -0
  101. package/dist/queries/role/read-role-node.js +21 -0
  102. package/dist/queries/user/legacy/index.js +1 -0
  103. package/dist/queries/user/legacy/read-user-profile.js +27 -0
  104. package/dist/runtime.d.ts +20147 -466
  105. package/dist/runtime.js +34 -7
  106. package/dist/schema/index.d.ts +7 -4
  107. package/dist/schema/index.js +8 -4
  108. package/dist/schema/legacy/index.js +1 -0
  109. package/dist/schema/legacy/schema.js +32 -0
  110. package/dist/schema/modules/application/legacy/entrypoint-entry.js +11 -0
  111. package/dist/schema/modules/application/legacy/functions/index.js +1 -0
  112. package/dist/schema/modules/application/legacy/functions/list-entrypoints.js +22 -0
  113. package/dist/schema/modules/application/legacy/index.js +2 -0
  114. package/dist/schema/modules/directory/functions/disconnect-directory.d.ts +13 -0
  115. package/dist/schema/modules/directory/functions/disconnect-directory.js +15 -0
  116. package/dist/schema/modules/directory/functions/index.d.ts +1 -0
  117. package/dist/schema/modules/directory/functions/index.js +1 -0
  118. package/dist/schema/modules/directory/index.d.ts +1 -0
  119. package/dist/schema/modules/directory/index.js +1 -0
  120. package/dist/schema/modules/group/classes/group-profile-link.d.ts +34 -0
  121. package/dist/schema/modules/group/classes/group-profile-link.js +21 -0
  122. package/dist/schema/modules/group/classes/group-profile.d.ts +15 -0
  123. package/dist/schema/modules/group/classes/group-profile.js +20 -0
  124. package/dist/schema/modules/group/classes/group.d.ts +87 -1
  125. package/dist/schema/modules/group/classes/group.js +38 -7
  126. package/dist/schema/modules/group/classes/index.d.ts +2 -1
  127. package/dist/schema/modules/group/classes/index.js +3 -1
  128. package/dist/schema/modules/group/functions/assign-member.js +17 -0
  129. package/dist/schema/modules/group/functions/assign-members.js +17 -0
  130. package/dist/schema/modules/group/functions/create-group.js +20 -0
  131. package/dist/schema/modules/group/functions/delete-group.js +12 -0
  132. package/dist/schema/modules/group/functions/deprovision-group.js +14 -0
  133. package/dist/schema/modules/group/functions/index.js +9 -2
  134. package/dist/schema/modules/group/functions/provision-group.js +14 -0
  135. package/dist/schema/modules/group/functions/unassign-member.js +17 -0
  136. package/dist/schema/modules/group/functions/unassign-members.js +17 -0
  137. package/dist/schema/modules/group/functions/update-group.js +20 -0
  138. package/dist/schema/modules/group/index.d.ts +3 -3
  139. package/dist/schema/modules/group/index.js +4 -3
  140. package/dist/schema/modules/group/legacy/admission.d.ts +9 -0
  141. package/dist/schema/modules/group/legacy/admission.js +9 -0
  142. package/dist/schema/modules/group/legacy/classes/index.d.ts +1 -0
  143. package/dist/schema/modules/group/legacy/classes/index.js +1 -0
  144. package/dist/schema/modules/group/{classes → legacy/classes}/member-of-group.d.ts +10 -1
  145. package/dist/schema/modules/group/legacy/classes/member-of-group.js +32 -0
  146. package/dist/schema/modules/group/legacy/core-groups.d.ts +22 -0
  147. package/dist/schema/modules/group/legacy/core-groups.js +28 -0
  148. package/dist/schema/modules/group/legacy/index.d.ts +5 -0
  149. package/dist/schema/modules/group/legacy/index.js +6 -0
  150. package/dist/schema/modules/group/legacy/policies/belongs-to-group.d.ts +5 -0
  151. package/dist/schema/modules/group/legacy/policies/belongs-to-group.js +9 -0
  152. package/dist/schema/modules/group/legacy/policies/index.d.ts +2 -0
  153. package/dist/schema/modules/group/legacy/policies/index.js +2 -0
  154. package/dist/schema/modules/group/legacy/policies/owns-membership-group.d.ts +6 -0
  155. package/dist/schema/modules/group/legacy/policies/owns-membership-group.js +12 -0
  156. package/dist/schema/modules/group/legacy/relaxations.d.ts +21 -0
  157. package/dist/schema/modules/group/legacy/relaxations.js +27 -0
  158. package/dist/schema/modules/group/policies/describes-group-of-subject.d.ts +2 -0
  159. package/dist/schema/modules/group/policies/describes-group-of-subject.js +7 -0
  160. package/dist/schema/modules/group/policies/index.d.ts +2 -1
  161. package/dist/schema/modules/group/policies/index.js +2 -1
  162. package/dist/schema/modules/group/policies/is-group-profile-source.d.ts +2 -0
  163. package/dist/schema/modules/group/policies/is-group-profile-source.js +6 -0
  164. package/dist/schema/modules/group/types/group-membership-input.js +8 -0
  165. package/dist/schema/modules/group/types/group.js +10 -0
  166. package/dist/schema/modules/group/types/index.js +2 -1
  167. package/dist/schema/modules/invitation/classes/index.js +2 -0
  168. package/dist/schema/modules/invitation/classes/invitation-user.js +17 -0
  169. package/dist/schema/modules/invitation/classes/invitation.js +32 -0
  170. package/dist/schema/modules/invitation/functions/accept.js +16 -0
  171. package/dist/schema/modules/invitation/functions/cancel.js +12 -0
  172. package/dist/schema/modules/invitation/functions/index.js +4 -0
  173. package/dist/schema/modules/invitation/functions/resend.js +12 -0
  174. package/dist/schema/modules/invitation/functions/send.js +20 -0
  175. package/dist/schema/modules/invitation/index.js +2 -0
  176. package/dist/schema/modules/invitation/types/index.js +1 -0
  177. package/dist/schema/modules/invitation/types/invitation-status.js +5 -0
  178. package/dist/schema/modules/namespace/classes/alias.d.ts +2 -1
  179. package/dist/schema/modules/namespace/classes/alias.js +11 -2
  180. package/dist/schema/modules/namespace/functions/link.js +3 -2
  181. package/dist/schema/modules/namespace/functions/rename.js +3 -2
  182. package/dist/schema/modules/namespace/functions/unlink.js +3 -2
  183. package/dist/schema/modules/role/classes/index.d.ts +1 -0
  184. package/dist/schema/modules/role/classes/index.js +1 -0
  185. package/dist/schema/modules/role/classes/role.d.ts +16 -0
  186. package/dist/schema/modules/role/classes/role.js +19 -0
  187. package/dist/schema/modules/role/core/index.d.ts +1 -0
  188. package/dist/schema/modules/role/core/index.js +1 -0
  189. package/dist/schema/modules/role/core/roles.d.ts +39 -0
  190. package/dist/schema/modules/role/core/roles.js +31 -0
  191. package/dist/schema/modules/role/index.d.ts +2 -0
  192. package/dist/schema/modules/role/index.js +2 -0
  193. package/dist/schema/modules/user/classes/index.d.ts +2 -0
  194. package/dist/schema/modules/user/classes/index.js +3 -0
  195. package/dist/schema/modules/user/classes/user-profile-link.d.ts +35 -0
  196. package/dist/schema/modules/user/classes/user-profile-link.js +22 -0
  197. package/dist/schema/modules/user/classes/user-profile.d.ts +41 -0
  198. package/dist/schema/modules/user/classes/user-profile.js +30 -0
  199. package/dist/schema/modules/user/classes/user.d.ts +133 -8
  200. package/dist/schema/modules/user/classes/user.js +46 -15
  201. package/dist/schema/modules/user/functions/create-user.js +21 -0
  202. package/dist/schema/modules/user/functions/deactivate-user.js +12 -0
  203. package/dist/schema/modules/user/functions/delete-user.js +12 -0
  204. package/dist/schema/modules/user/functions/deprovision-user.js +14 -0
  205. package/dist/schema/modules/user/functions/index.js +8 -1
  206. package/dist/schema/modules/user/functions/invite-user.js +23 -4
  207. package/dist/schema/modules/user/functions/provision-user.js +25 -0
  208. package/dist/schema/modules/user/functions/reactivate-user.js +12 -0
  209. package/dist/schema/modules/user/functions/update-profile.js +16 -0
  210. package/dist/schema/modules/user/functions/update-user.js +22 -0
  211. package/dist/schema/modules/user/index.d.ts +2 -1
  212. package/dist/schema/modules/user/index.js +2 -1
  213. package/dist/schema/modules/user/legacy/account-properties.js +24 -0
  214. package/dist/schema/modules/user/legacy/functions/index.js +2 -0
  215. package/dist/schema/modules/user/legacy/functions/migrate-accounts.js +23 -0
  216. package/dist/schema/modules/user/legacy/functions/record-profile.js +18 -0
  217. package/dist/schema/modules/user/legacy/index.js +5 -0
  218. package/dist/schema/modules/user/legacy/invite.js +15 -0
  219. package/dist/schema/modules/user/legacy/relaxations.js +37 -0
  220. package/dist/schema/modules/user/policies/describes-subject.d.ts +2 -0
  221. package/dist/schema/modules/user/policies/describes-subject.js +7 -0
  222. package/dist/schema/modules/user/policies/index.d.ts +2 -0
  223. package/dist/schema/modules/user/policies/index.js +2 -0
  224. package/dist/schema/modules/user/policies/is-profile-source.d.ts +2 -0
  225. package/dist/schema/modules/user/policies/is-profile-source.js +6 -0
  226. package/dist/schema/modules/user/types/account.d.ts +12 -0
  227. package/dist/schema/modules/user/types/account.js +12 -0
  228. package/dist/schema/modules/user/types/index.d.ts +1 -1
  229. package/dist/schema/modules/user/types/index.js +1 -1
  230. package/dist/schema/modules/view-access/classes/view-access.d.ts +7 -11
  231. package/dist/schema/modules/view-access/classes/view-access.js +17 -12
  232. package/dist/schema/modules/view-access/index.d.ts +1 -2
  233. package/dist/schema/modules/view-access/index.js +1 -2
  234. package/dist/schema/modules/view-access/legacy/functions/assign-views.js +22 -0
  235. package/dist/schema/modules/view-access/legacy/functions/index.js +1 -0
  236. package/dist/schema/modules/view-access/legacy/index.js +2 -0
  237. package/dist/schema/modules/view-access/legacy/view-assignment.js +24 -0
  238. package/dist/schema/modules/view-access/policies/holds-view-access.d.ts +2 -0
  239. package/dist/schema/modules/view-access/policies/holds-view-access.js +5 -0
  240. package/dist/schema/modules/view-access/policies/index.d.ts +1 -0
  241. package/dist/schema/modules/view-access/policies/index.js +1 -0
  242. package/dist/schema/policies/has-role.d.ts +6 -0
  243. package/dist/schema/policies/has-role.js +9 -0
  244. package/dist/schema/policies/index.d.ts +1 -0
  245. package/dist/schema/policies/index.js +1 -4
  246. package/dist/schema/policies/legacy/administers-shell-class.js +21 -0
  247. package/dist/schema/policies/legacy/index.js +4 -0
  248. package/dist/schema/policies/legacy/is-self.js +9 -0
  249. package/dist/schema/policies/legacy/owns-class.js +12 -0
  250. package/dist/schema/policies/legacy/uses-function.js +9 -0
  251. package/dist/schema/schema.d.ts +1937 -119
  252. package/dist/schema/schema.js +35 -15
  253. package/dist/schema/types/attributes.js +15 -0
  254. package/dist/schema/types/index.js +1 -0
  255. package/dist/utils/attributes/attributes.js +12 -0
  256. package/dist/utils/attributes/index.js +1 -0
  257. package/dist/utils/index.js +3 -0
  258. package/dist/utils/same-json/index.js +1 -0
  259. package/dist/utils/same-json/same-json.js +9 -0
  260. package/package.json +3 -3
  261. package/dist/functions/application/list-entrypoints.js +0 -6
  262. package/dist/functions/group/assign-member-to-group.js +0 -4
  263. package/dist/functions/group/unassign-member-from-group.js +0 -4
  264. package/dist/functions/user/record-profile.js +0 -18
  265. package/dist/mutations/user/index.js +0 -1
  266. package/dist/queries/application/index.js +0 -1
  267. package/dist/queries/application/read-installed-entrypoints.js +0 -28
  268. package/dist/queries/user/index.js +0 -1
  269. package/dist/queries/user/read-user-profile.js +0 -9
  270. package/dist/schema/modules/application/functions/index.d.ts +0 -1
  271. package/dist/schema/modules/application/functions/index.js +0 -1
  272. package/dist/schema/modules/application/functions/list-entrypoints.d.ts +0 -15
  273. package/dist/schema/modules/application/functions/list-entrypoints.js +0 -16
  274. package/dist/schema/modules/application/index.d.ts +0 -2
  275. package/dist/schema/modules/application/index.js +0 -2
  276. package/dist/schema/modules/application/types/entrypoint-entry.d.ts +0 -8
  277. package/dist/schema/modules/application/types/entrypoint-entry.js +0 -7
  278. package/dist/schema/modules/application/types/index.d.ts +0 -1
  279. package/dist/schema/modules/application/types/index.js +0 -1
  280. package/dist/schema/modules/group/classes/member-of-group.js +0 -12
  281. package/dist/schema/modules/group/core/administrators-group.d.ts +0 -1
  282. package/dist/schema/modules/group/core/administrators-group.js +0 -6
  283. package/dist/schema/modules/group/core/applications-group.d.ts +0 -1
  284. package/dist/schema/modules/group/core/applications-group.js +0 -6
  285. package/dist/schema/modules/group/core/index.d.ts +0 -3
  286. package/dist/schema/modules/group/core/index.js +0 -3
  287. package/dist/schema/modules/group/core/members-group.d.ts +0 -1
  288. package/dist/schema/modules/group/core/members-group.js +0 -6
  289. package/dist/schema/modules/group/functions/assign-member-to-group.js +0 -11
  290. package/dist/schema/modules/group/functions/unassign-member-from-group.js +0 -11
  291. package/dist/schema/modules/group/policies/belongs-to-group.d.ts +0 -1
  292. package/dist/schema/modules/group/policies/belongs-to-group.js +0 -5
  293. package/dist/schema/modules/user/functions/record-profile.js +0 -14
  294. package/dist/schema/modules/user/types/user-profile.d.ts +0 -7
  295. package/dist/schema/modules/user/types/user-profile.js +0 -7
  296. package/dist/schema/modules/view-access/core/index.d.ts +0 -1
  297. package/dist/schema/modules/view-access/core/index.js +0 -1
  298. package/dist/schema/modules/view-access/core/view-only-group.d.ts +0 -5
  299. package/dist/schema/modules/view-access/core/view-only-group.js +0 -10
  300. package/dist/schema/modules/view-access/functions/assign-views.d.ts +0 -16
  301. package/dist/schema/modules/view-access/functions/assign-views.js +0 -17
  302. package/dist/schema/modules/view-access/functions/index.d.ts +0 -1
  303. package/dist/schema/modules/view-access/functions/index.js +0 -1
  304. package/dist/schema/modules/view-access/types/index.js +0 -1
  305. package/dist/schema/modules/view-access/types/view-assignment.js +0 -16
  306. package/dist/schema/policies/administers-shell-class.js +0 -11
  307. package/dist/schema/policies/is-self.js +0 -5
  308. package/dist/schema/policies/owns-class.js +0 -7
  309. package/dist/schema/policies/uses-function.js +0 -5
@@ -1,8 +1,9 @@
1
1
  import { TransportError } from '@astrale-os/sdk/client';
2
2
  import { defineProvider } from '@astrale-os/sdk/integration';
3
3
  import { z } from 'zod';
4
- import { enrollment, InvitationRequestFailure } from '../../integrations/user-invitation/index.js';
4
+ import { enrollment, InvitationRequestFailure, } from '../../integrations/user-invitation/index.js';
5
5
  import { decodeAdminInvitationResponse } from './decode-admin-invitation-response.js';
6
+ import { legacySendWithoutProfile } from './legacy/index.js';
6
7
  import { readReply } from './read-enrollment-response.js';
7
8
  // Environment is a representation boundary, unlike already-admitted handler input.
8
9
  const configuration = z.object({ ENROLLMENT_INGRESS_URL: z.string().url() });
@@ -33,7 +34,7 @@ export function enrollmentProvider(environment) {
33
34
  }
34
35
  // No automatic HTTP retry. A timeout after send has an unknown effect.
35
36
  const signal = AbortSignal.any([execution.signal, AbortSignal.timeout(remaining)]);
36
- const response = await fetch(audience, {
37
+ const send = (body) => fetch(audience, {
37
38
  method: 'POST',
38
39
  // Workers reject redirect:error before sending. Manual preserves the refusal:
39
40
  // every 3xx is rejected below, without forwarding the proof to its Location.
@@ -44,7 +45,7 @@ export function enrollmentProvider(environment) {
44
45
  Accept: 'application/json',
45
46
  'Idempotency-Key': input.requestId,
46
47
  },
47
- body: JSON.stringify(input),
48
+ body: JSON.stringify(body),
48
49
  signal,
49
50
  }).catch((cause) => {
50
51
  if (!(cause instanceof TypeError) && !(cause instanceof DOMException))
@@ -54,6 +55,8 @@ export function enrollmentProvider(environment) {
54
55
  delivery: 'unknown',
55
56
  });
56
57
  });
58
+ // Seam L-SHELL-15: an Admin older than `profile` refuses the field; send it again without.
59
+ const response = await legacySendWithoutProfile(input, send);
57
60
  if (!response.ok) {
58
61
  await response.body?.cancel();
59
62
  if (response.status === 409)
@@ -0,0 +1 @@
1
+ export { legacySendWithoutProfile } from './send-without-profile.js';
@@ -0,0 +1,16 @@
1
+ /**
2
+ * @deprecated Admin before profiles validates its invitation request strictly and refuses the
3
+ * `profile` field with 400: the request is sent once more without it, which Admin then admits
4
+ * (L-SHELL-15). A first 400 has no effect, so resending under the same idempotency key is safe.
5
+ * Replaced by one request carrying `profile`. Removal: Shell major (delivery step 5), once every
6
+ * Admin deployment admits `profile` (Admin delivery step 2).
7
+ */
8
+ export async function legacySendWithoutProfile(request, send) {
9
+ const response = await send(request);
10
+ if (request.profile === undefined || (response.status !== 400 && response.status !== 422)) {
11
+ return response;
12
+ }
13
+ await response.body?.cancel();
14
+ const { profile: _profile, ...legacy } = request;
15
+ return send(legacy);
16
+ }
@@ -0,0 +1 @@
1
+ export { legacyReadInstalledEntrypoints } from './read-installed-entrypoints.js';
@@ -0,0 +1,47 @@
1
+ import { defineQuery, Query, queryResult, } from '@astrale-os/sdk/query';
2
+ const VIEW_MEMBER = /^view\.([A-Za-z][A-Za-z0-9_]*)$/u;
3
+ /**
4
+ * @deprecated The catalogue `listEntrypoints` answers (L-SHELL-11). Replaced by the visitor's own
5
+ * Query (V2). Removal: Shell major (delivery step 5) after 1Pact step 4.
6
+ *
7
+ * Every installed Domain entrypoint this authority can read, in origin order. The `of_domain`
8
+ * locator of a View that has an outgoing `entrypoint` Edge names that View (`view.<name>`), and its
9
+ * target is the Domain, whose Node carries the origin and the display name.
10
+ */
11
+ export const legacyReadInstalledEntrypoints = defineQuery()((domain) => {
12
+ const kernel = domain.dependencies.kernel.classes;
13
+ return {
14
+ id: 'shell.application.entrypoints',
15
+ page: { size: 200 },
16
+ pagination: { maximumPages: 50 },
17
+ build: () => {
18
+ const located = Query.from({ edges: [kernel.of_domain] });
19
+ return located
20
+ .expand({ from: located.source, via: [kernel.entrypoint], direction: 'outgoing' })
21
+ .select({
22
+ kind: 'edges',
23
+ binding: located.edge,
24
+ projection: { edge: 'value', source: 'reference', target: 'value' },
25
+ });
26
+ },
27
+ project(pages) {
28
+ const entries = [];
29
+ for (const page of pages) {
30
+ for (const item of queryResult.edgeItems(page, 'Installed entrypoints')) {
31
+ if (item.edge.kind !== 'value' || item.target.kind !== 'value') {
32
+ throw new TypeError('Installed entrypoint is not a complete value.');
33
+ }
34
+ const member = VIEW_MEMBER.exec(String(item.edge.value.props[kernel.of_domain.properties.member.key]));
35
+ const props = item.target.value.props;
36
+ const origin = props[kernel.Domain.properties.origin.key];
37
+ const name = props[kernel.Domain.properties.name.key];
38
+ if (member === null || typeof origin !== 'string' || typeof name !== 'string') {
39
+ throw new TypeError('Installed entrypoint has no View, origin, or name.');
40
+ }
41
+ entries.push({ origin, name, view: `${origin}:view.${member[1]}` });
42
+ }
43
+ }
44
+ return entries.sort((left, right) => left.origin.localeCompare(right.origin));
45
+ },
46
+ };
47
+ });
@@ -0,0 +1,2 @@
1
+ export { readExtensions } from './read-extensions.js';
2
+ export { readRoleKeys, readRoleNodes } from './read-role-nodes.js';
@@ -0,0 +1,34 @@
1
+ import { Path } from '@astrale-os/sdk/graph/path';
2
+ import { defineQuery, Query, queryResult, } from '@astrale-os/sdk/query';
3
+ /** The `extends_with` Edges at one frontier of a composition walk, read with Shell's authority. */
4
+ export const readExtensions = defineQuery()((domain) => ({
5
+ id: 'shell.composition.extensions',
6
+ page: { size: 256 },
7
+ pagination: { maximumPages: 16 },
8
+ build({ identities, direction }) {
9
+ const walk = Query.from({
10
+ nodes: [Path.id(identities[0]), ...identities.slice(1).map((id) => Path.id(id))],
11
+ }).expand({ via: [domain.dependencies.kernel.classes.extends_with], direction });
12
+ return walk.select({
13
+ kind: 'edges',
14
+ binding: walk.edge,
15
+ projection: { edge: 'reference', source: 'reference', target: 'reference' },
16
+ });
17
+ },
18
+ project(pages) {
19
+ const extensions = [];
20
+ for (const page of pages) {
21
+ for (const item of queryResult.edgeItems(page, 'Shell composition')) {
22
+ if (item.source.kind !== 'reference' || item.target.kind !== 'reference')
23
+ continue;
24
+ extensions.push({
25
+ source: item.source.value.id,
26
+ target: item.target.value.id,
27
+ sourceClass: item.source.value.class,
28
+ targetClass: item.target.value.class,
29
+ });
30
+ }
31
+ }
32
+ return extensions;
33
+ },
34
+ }));
@@ -0,0 +1,76 @@
1
+ import { Path } from '@astrale-os/sdk/graph/path';
2
+ import { defineQuery, Query, queryResult, } from '@astrale-os/sdk/query';
3
+ const CORE = 'core.';
4
+ /** Each Core Node of a Kernel Role Class, named by its `of_domain` locator. */
5
+ export const readRoleNodes = defineQuery()((domain) => {
6
+ const kernel = domain.dependencies.kernel.classes;
7
+ const member = kernel.of_domain.properties.member.key;
8
+ const origin = kernel.Domain.properties.origin.key;
9
+ return {
10
+ id: 'shell.composition.roles',
11
+ page: { size: 256 },
12
+ pagination: { maximumPages: 16 },
13
+ build: () => {
14
+ const locator = Query.from({ nodes: [kernel.Role] }).expand({
15
+ via: [kernel.of_domain],
16
+ direction: 'outgoing',
17
+ });
18
+ return locator.select({
19
+ kind: 'edges',
20
+ binding: locator.edge,
21
+ projection: { edge: 'value', source: 'reference', target: 'value' },
22
+ });
23
+ },
24
+ project(pages) {
25
+ const byKey = new Map();
26
+ for (const [id, key] of roleKeys(pages, member, origin))
27
+ byKey.set(key, id);
28
+ return { byKey, ids: new Set(byKey.values()) };
29
+ },
30
+ };
31
+ });
32
+ /** Each Core Role in pages of `of_domain` Edges: its Node, and `<origin>:<Core key>`. */
33
+ function roleKeys(pages, member, origin) {
34
+ const keys = new Map();
35
+ for (const page of pages) {
36
+ for (const item of queryResult.edgeItems(page, 'Shell Roles')) {
37
+ if (item.edge.kind !== 'value' || item.source.kind !== 'reference')
38
+ continue;
39
+ if (item.target.kind !== 'value')
40
+ continue;
41
+ const key = item.edge.value.props[member];
42
+ const owner = item.target.value.props[origin];
43
+ if (typeof key !== 'string' || !key.startsWith(CORE) || typeof owner !== 'string')
44
+ continue;
45
+ keys.set(item.source.value.id, `${owner}:${key.slice(CORE.length)}`);
46
+ }
47
+ }
48
+ return keys;
49
+ }
50
+ /**
51
+ * The Core Roles among some Identities, by `<origin>:<Core key>`: what one composition holds, read
52
+ * without the catalogue of every installed Role.
53
+ */
54
+ export const readRoleKeys = defineQuery()((domain) => {
55
+ const kernel = domain.dependencies.kernel.classes;
56
+ const member = kernel.of_domain.properties.member.key;
57
+ const origin = kernel.Domain.properties.origin.key;
58
+ return {
59
+ id: 'shell.composition.role-keys',
60
+ page: { size: 256 },
61
+ pagination: { maximumPages: 16 },
62
+ build: ({ identities }) => {
63
+ const locator = Query.from({
64
+ nodes: [Path.id(identities[0]), ...identities.slice(1).map((id) => Path.id(id))],
65
+ })
66
+ .filter({ class: kernel.Role })
67
+ .expand({ via: [kernel.of_domain], direction: 'outgoing' });
68
+ return locator.select({
69
+ kind: 'edges',
70
+ binding: locator.edge,
71
+ projection: { edge: 'value', source: 'reference', target: 'value' },
72
+ });
73
+ },
74
+ project: (pages) => roleKeys(pages, member, origin),
75
+ };
76
+ });
@@ -1,2 +1,3 @@
1
1
  export { readGroupMembership, } from './read-group-membership.js';
2
- export { readGroupMembershipEndpoints } from './read-group-membership-endpoints.js';
2
+ export { readGroupMembershipEndpoints, } from './read-group-membership-endpoints.js';
3
+ export { readGroupMembers, readGroupMembersEndpoints, } from './read-group-members.js';
@@ -0,0 +1,3 @@
1
+ export { legacyReadMemberOfGroup } from './read-member-of-group.js';
2
+ export { legacyReadCoreGroups } from './read-core-groups.js';
3
+ export { legacyReadMembersOfGroup } from './read-members-of-group.js';
@@ -0,0 +1,46 @@
1
+ import { defineQuery, Query, queryResult, } from '@astrale-os/sdk/query';
2
+ const CORE = 'core.';
3
+ /**
4
+ * @deprecated Shell's own Core groups, each named by its `of_domain` locator (`core.<name>`)
5
+ * (L-SHELL-7): the legacy groups a membership write keeps `member_of_group` for. Replaced by the
6
+ * profile Roles. Removal: Shell major (delivery step 5) after 1Pact step 4.
7
+ */
8
+ export const legacyReadCoreGroups = defineQuery()((domain) => {
9
+ const kernel = domain.dependencies.kernel.classes;
10
+ const member = kernel.of_domain.properties.member.key;
11
+ const origin = kernel.Domain.properties.origin.key;
12
+ return {
13
+ id: 'shell.access.core-groups',
14
+ page: { size: 256 },
15
+ pagination: { maximumPages: 8 },
16
+ build: () => {
17
+ const locator = Query.from({ nodes: [domain.classes.Group] }).expand({
18
+ via: [kernel.of_domain],
19
+ direction: 'outgoing',
20
+ });
21
+ return locator.select({
22
+ kind: 'edges',
23
+ binding: locator.edge,
24
+ projection: { edge: 'value', source: 'reference', target: 'value' },
25
+ });
26
+ },
27
+ project(pages) {
28
+ const groups = {};
29
+ for (const page of pages) {
30
+ for (const item of queryResult.edgeItems(page, 'Shell Core groups')) {
31
+ if (item.edge.kind !== 'value' || item.source.kind !== 'reference')
32
+ continue;
33
+ if (item.target.kind !== 'value')
34
+ continue;
35
+ if (item.target.value.props[origin] !== domain.origin)
36
+ continue;
37
+ const key = item.edge.value.props[member];
38
+ if (typeof key === 'string' && key.startsWith(CORE)) {
39
+ groups[key.slice(CORE.length)] = item.source.value.id;
40
+ }
41
+ }
42
+ }
43
+ return groups;
44
+ },
45
+ };
46
+ });
@@ -0,0 +1,24 @@
1
+ import { Query, defineQuery, queryResult } from '@astrale-os/sdk/query';
2
+ /**
3
+ * @deprecated The legacy `member_of_group` Edge from the member to the group, kept whole as a guard
4
+ * (L-SHELL-8). Replaced by `readGroupMembership` (`extends_with`). Removal: Shell major (delivery
5
+ * step 5) after 1Pact step 4.
6
+ */
7
+ export const legacyReadMemberOfGroup = defineQuery()((domain) => ({
8
+ id: 'shell.group.membership.legacy',
9
+ build({ member, group }) {
10
+ const edges = Query.from({ edges: [domain.classes.member_of_group] });
11
+ return edges
12
+ .filter({ binding: edges.source, predicate: { kind: 'identity.equal', identity: member } })
13
+ .filter({ binding: edges.target, predicate: { kind: 'identity.equal', identity: group } })
14
+ .select({
15
+ kind: 'edges',
16
+ projection: { edge: 'reference', source: 'reference', target: 'reference' },
17
+ });
18
+ },
19
+ pagination: { maximumPages: 2 },
20
+ project(pages, _input, { ast, complete }) {
21
+ const present = pages.some((page) => queryResult.edgeItems(page, 'Shell legacy membership').length > 0);
22
+ return { present, guard: { query: ast, equals: complete } };
23
+ },
24
+ }));
@@ -0,0 +1,27 @@
1
+ import { Path } from '@astrale-os/sdk/graph/path';
2
+ import { Query, defineQuery, } from '@astrale-os/sdk/query';
3
+ import { canonical, sources, } from '../read-group-members.js';
4
+ /**
5
+ * @deprecated The legacy `member_of_group` Edges from the members to the group, in one read and
6
+ * kept whole as one guard (L-SHELL-8). Replaced by `readGroupMembers` (`extends_with`). Removal:
7
+ * Shell major (delivery step 5) after 1Pact step 4.
8
+ */
9
+ export const legacyReadMembersOfGroup = defineQuery()((domain) => ({
10
+ id: 'shell.group.members.legacy',
11
+ page: { size: 256 },
12
+ pagination: { maximumPages: 2 },
13
+ build({ members, group }) {
14
+ const walk = Query.from({
15
+ nodes: [Path.id(members[0]), ...members.slice(1).map((id) => Path.id(id))],
16
+ }).expand({ via: [domain.classes.member_of_group], direction: 'outgoing' });
17
+ return walk.filter({ predicate: { kind: 'identity.equal', identity: group } }).select({
18
+ kind: 'edges',
19
+ binding: walk.edge,
20
+ projection: { edge: 'reference', source: 'reference', target: 'reference' },
21
+ });
22
+ },
23
+ project: (pages, _input, { ast, complete }) => ({
24
+ present: sources(pages, 'Shell legacy group members'),
25
+ guard: { query: ast, equals: canonical(complete) },
26
+ }),
27
+ }));
@@ -0,0 +1,73 @@
1
+ import { Path } from '@astrale-os/sdk/graph/path';
2
+ import { Query, defineQuery, queryResult, } from '@astrale-os/sdk/query';
3
+ const anchors = (ids) => [Path.id(ids[0]), ...ids.slice(1).map((id) => Path.id(id))];
4
+ /** Every member and the group, in one read whatever the number of members. */
5
+ export const readGroupMembersEndpoints = defineQuery()(() => ({
6
+ id: 'shell.group.members.endpoints',
7
+ page: { size: 256 },
8
+ pagination: { maximumPages: 2 },
9
+ build: ({ members, group }) => Query.from({ nodes: [...anchors(members), Path.id(group)] }).select({
10
+ kind: 'nodes',
11
+ projection: { kind: 'reference' },
12
+ }),
13
+ project(pages, input, { ast, complete }) {
14
+ const visible = new Set(queryResult.completeNodeIds(pages, 'Shell group members'));
15
+ let groupClass;
16
+ for (const page of pages) {
17
+ if (page.kind !== 'nodes')
18
+ continue;
19
+ for (const item of page.nodes) {
20
+ if (item.kind === 'reference' && item.value.id === input.group)
21
+ groupClass = item.value.class;
22
+ }
23
+ }
24
+ return {
25
+ visible,
26
+ ...(groupClass === undefined ? {} : { groupClass }),
27
+ // The Kernel takes a guard's Nodes in canonical order.
28
+ guard: { query: ast, equals: { ...complete, ids: [...complete.ids].sort(order) } },
29
+ };
30
+ },
31
+ }));
32
+ /** The `extends_with` Edges from the members to the group: their memberships (G1), in one read. */
33
+ export const readGroupMembers = defineQuery()((domain) => ({
34
+ id: 'shell.group.members.read',
35
+ page: { size: 256 },
36
+ pagination: { maximumPages: 2 },
37
+ build({ members, group }) {
38
+ const walk = Query.from({ nodes: anchors(members) }).expand({
39
+ via: [domain.dependencies.kernel.classes.extends_with],
40
+ direction: 'outgoing',
41
+ });
42
+ return walk.filter({ predicate: { kind: 'identity.equal', identity: group } }).select({
43
+ kind: 'edges',
44
+ binding: walk.edge,
45
+ projection: { edge: 'reference', source: 'reference', target: 'reference' },
46
+ });
47
+ },
48
+ project: (pages, _input, { ast, complete }) => ({
49
+ present: sources(pages, 'Shell group members'),
50
+ guard: { query: ast, equals: canonical(complete) },
51
+ }),
52
+ }));
53
+ /** The members an Edge read finds, by source. */
54
+ export function sources(pages, label) {
55
+ const found = new Set();
56
+ for (const page of pages) {
57
+ for (const item of queryResult.edgeItems(page, label)) {
58
+ if (item.source.kind === 'reference')
59
+ found.add(item.source.value.id);
60
+ }
61
+ }
62
+ return found;
63
+ }
64
+ const order = (left, right) => (left < right ? -1 : left > right ? 1 : 0);
65
+ /** A guard's Edges in the Kernel's canonical order: by source, then target, then Class. */
66
+ export function canonical(selection) {
67
+ if (selection.kind !== 'edge')
68
+ return selection;
69
+ const keys = [...selection.keys].sort((left, right) => order(left.source, right.source) ||
70
+ order(left.target, right.target) ||
71
+ order(left.class, right.class));
72
+ return { ...selection, keys };
73
+ }
@@ -1,5 +1,6 @@
1
1
  import { Path } from '@astrale-os/sdk/graph/path';
2
2
  import { defineQuery, Query, queryResult, } from '@astrale-os/sdk/query';
3
+ /** Both membership endpoints, kept whole as a guard: neither is replaced while Shell decides. */
3
4
  export const readGroupMembershipEndpoints = defineQuery()(() => ({
4
5
  id: 'shell.group.membership.endpoints',
5
6
  page: { size: 2 },
@@ -10,8 +11,18 @@ export const readGroupMembershipEndpoints = defineQuery()(() => ({
10
11
  }),
11
12
  project(pages, input, { ast, complete }) {
12
13
  const ids = queryResult.completeNodeIds(pages, 'Shell membership endpoints');
14
+ let groupClass;
15
+ for (const page of pages) {
16
+ if (page.kind !== 'nodes')
17
+ continue;
18
+ for (const item of page.nodes) {
19
+ if (item.kind === 'reference' && item.value.id === input.group)
20
+ groupClass = item.value.class;
21
+ }
22
+ }
13
23
  return {
14
24
  visible: ids.includes(input.member) && ids.includes(input.group),
25
+ ...(groupClass === undefined ? {} : { groupClass }),
15
26
  guard: { query: ast, equals: complete },
16
27
  };
17
28
  },
@@ -1,35 +1,20 @@
1
1
  import { Query, defineQuery, queryResult, } from '@astrale-os/sdk/query';
2
+ /** The `extends_with` Edge from the member to the group: the membership itself (G1). */
2
3
  export const readGroupMembership = defineQuery()((domain) => ({
3
4
  id: 'shell.group.membership.read',
4
5
  build({ member, group }) {
5
- const edges = Query.from({
6
- edges: [domain.classes.member_of_group, domain.dependencies.kernel.classes.extends_with],
7
- });
6
+ const edges = Query.from({ edges: [domain.dependencies.kernel.classes.extends_with] });
8
7
  return edges
9
8
  .filter({ binding: edges.source, predicate: { kind: 'identity.equal', identity: member } })
10
9
  .filter({ binding: edges.target, predicate: { kind: 'identity.equal', identity: group } })
11
10
  .select({
12
11
  kind: 'edges',
13
- projection: { edge: 'value', source: 'reference', target: 'reference' },
12
+ projection: { edge: 'reference', source: 'reference', target: 'reference' },
14
13
  });
15
14
  },
16
- pagination: { maximumPages: 4 },
15
+ pagination: { maximumPages: 2 },
17
16
  project(pages, _input, { ast, complete }) {
18
- let membership = false;
19
- let authority = false;
20
- for (const page of pages) {
21
- for (const item of queryResult.edgeItems(page, 'Shell group membership')) {
22
- if (item.edge.kind !== 'value')
23
- throw new TypeError('Expected an Edge value.');
24
- if (item.edge.value.class === domain.classes.member_of_group.key)
25
- membership = true;
26
- else if (item.edge.value.class === domain.dependencies.kernel.classes.extends_with.key) {
27
- authority = true;
28
- }
29
- else
30
- throw new TypeError('Unexpected Edge Class.');
31
- }
32
- }
33
- return { membership, authority, guard: { query: ast, equals: complete } };
17
+ const present = pages.some((page) => queryResult.edgeItems(page, 'Shell group membership').length > 0);
18
+ return { present, guard: { query: ast, equals: complete } };
34
19
  },
35
20
  }));
@@ -0,0 +1 @@
1
+ export { readIdentities } from './read-identities.js';
@@ -0,0 +1,29 @@
1
+ import { Path } from '@astrale-os/sdk/graph/path';
2
+ import { defineQuery, Query, queryResult, } from '@astrale-os/sdk/query';
3
+ /**
4
+ * The accounts or groups a selection names that Shell reads, as stored: a Class extent includes a
5
+ * foreign subclass, and a Node of another Class is left out.
6
+ */
7
+ export const readIdentities = defineQuery()((domain) => ({
8
+ id: 'shell.identities.read',
9
+ page: { size: 256 },
10
+ pagination: { maximumPages: 16 },
11
+ build(selection) {
12
+ const selected = domain.classes[selection.kind];
13
+ if ('ids' in selection) {
14
+ const [first, ...others] = selection.ids;
15
+ return Query.from({ nodes: [Path.id(first), ...others.map((id) => Path.id(id))] })
16
+ .filter({ class: selected })
17
+ .select({ kind: 'nodes', projection: { kind: 'value' } });
18
+ }
19
+ let query = Query.from({ nodes: [selected] });
20
+ for (const [name, value] of Object.entries(selection.where)) {
21
+ const property = selected.properties[name];
22
+ if (property === undefined)
23
+ throw new TypeError(`${selection.kind} has no ${name}.`);
24
+ query = query.filter({ predicate: { kind: 'property.equal', property: property.key, value } });
25
+ }
26
+ return query.select({ kind: 'nodes', projection: { kind: 'value' } });
27
+ },
28
+ project: (pages) => queryResult.completeNodeValues(pages, 'Shell identities'),
29
+ }));
@@ -0,0 +1 @@
1
+ export { readInvitation, readPendingInvitations } from './read-invitation.js';
@@ -0,0 +1,50 @@
1
+ import { Path } from '@astrale-os/sdk/graph/path';
2
+ import { defineQuery, Query, queryResult, } from '@astrale-os/sdk/query';
3
+ /** An invitation Node as the methods and the run read it. */
4
+ function toInvitation(node, keys) {
5
+ const props = node.props;
6
+ const email = props[keys.email.key];
7
+ return {
8
+ id: node.id,
9
+ status: String(props[keys.status.key]),
10
+ execution: String(props[keys.execution.key]),
11
+ round: Number(props[keys.round.key] ?? 0),
12
+ ...(typeof email === 'string' ? { email } : {}),
13
+ };
14
+ }
15
+ /** One invitation, or undefined when there is none the reader reads. */
16
+ export const readInvitation = defineQuery()((domain) => ({
17
+ id: 'shell.invitation.read',
18
+ page: { size: 1 },
19
+ pagination: { maximumPages: 1 },
20
+ build: ({ invitation }) => Query.from({ nodes: [Path.id(invitation)] }).select({
21
+ kind: 'nodes',
22
+ projection: { kind: 'value' },
23
+ }),
24
+ project: (pages) => {
25
+ const node = queryResult.completeNodeValues(pages, 'Shell invitation')[0];
26
+ if (node === undefined)
27
+ return undefined;
28
+ return toInvitation(node, domain.classes.Invitation.properties);
29
+ },
30
+ }));
31
+ /** The pending invitations of one account: at most one, unless recorded before that rule. */
32
+ export const readPendingInvitations = defineQuery()((domain) => ({
33
+ id: 'shell.invitation.pending',
34
+ page: { size: 64 },
35
+ pagination: { maximumPages: 1 },
36
+ build: ({ user }) => Query.from({ nodes: [Path.id(user)] })
37
+ .expand({ via: [domain.classes.invitation_user], direction: 'incoming' })
38
+ .filter({ class: domain.classes.Invitation })
39
+ .filter({
40
+ predicate: {
41
+ kind: 'property.equal',
42
+ property: domain.classes.Invitation.properties.status.key,
43
+ value: 'pending',
44
+ },
45
+ })
46
+ .select({ kind: 'nodes', projection: { kind: 'value' } }),
47
+ project: (pages) => queryResult
48
+ .completeNodeValues(pages, 'Shell pending invitations')
49
+ .map((node) => toInvitation(node, domain.classes.Invitation.properties)),
50
+ }));
@@ -0,0 +1 @@
1
+ export { readProfile } from './read-profile.js';
@@ -0,0 +1,15 @@
1
+ import { Path } from '@astrale-os/sdk/graph/path';
2
+ import { defineQuery, Query, queryResult, } from '@astrale-os/sdk/query';
3
+ /** The profile Node of one account or group, or undefined for one stored before profiles. */
4
+ export const readProfile = defineQuery()((domain) => ({
5
+ id: 'shell.profile.read',
6
+ page: { size: 1 },
7
+ pagination: { maximumPages: 1 },
8
+ build: ({ kind, node }) => Query.from({ nodes: [Path.id(node)] })
9
+ .expand({
10
+ via: [kind === 'User' ? domain.classes.user_profile : domain.classes.group_profile],
11
+ direction: 'outgoing',
12
+ })
13
+ .select({ kind: 'nodes', projection: { kind: 'value' } }),
14
+ project: (pages) => queryResult.completeNodeValues(pages, 'Shell profile')[0]?.id,
15
+ }));
@@ -0,0 +1 @@
1
+ export { readRoleId, readRoleNode } from './read-role-node.js';
@@ -0,0 +1,21 @@
1
+ import { defineQuery, Query, queryResult, } from '@astrale-os/sdk/query';
2
+ /**
3
+ * Whether the reader reads one Role Node. A Shell Role reads by its holders and by Kernel
4
+ * `authority.reader` (R7), so read under a caller's authority it tells whether the Kernel finds the
5
+ * Role in that caller's live composition, at any depth; Root reads every Role.
6
+ */
7
+ export const readRoleNode = defineQuery()(() => ({
8
+ id: 'shell.role.read',
9
+ page: { size: 1 },
10
+ pagination: { maximumPages: 1 },
11
+ build: ({ role }) => Query.from({ nodes: [role] }).select({ kind: 'nodes', projection: { kind: 'value' } }),
12
+ project: (pages) => queryResult.completeNodeValues(pages, 'Shell Role').length === 1,
13
+ }));
14
+ /** One Role's Node, read by its Core target; nothing when it is not installed. */
15
+ export const readRoleId = defineQuery()(() => ({
16
+ id: 'shell.role.id',
17
+ page: { size: 1 },
18
+ pagination: { maximumPages: 1 },
19
+ build: ({ role }) => Query.from({ nodes: [role] }).select({ kind: 'nodes', projection: { kind: 'reference' } }),
20
+ project: (pages) => queryResult.completeNodeIds(pages, 'Shell Role')[0],
21
+ }));
@@ -0,0 +1 @@
1
+ export { legacyReadUserProfile } from './read-user-profile.js';
@@ -0,0 +1,27 @@
1
+ import { Path } from '@astrale-os/sdk/graph/path';
2
+ import { defineQuery, Query, queryResult, } from '@astrale-os/sdk/query';
3
+ /**
4
+ * @deprecated The email and display name one account recorded about itself (L-SHELL-5). Replaced
5
+ * by the account's `email` and `name`. Removal: Shell major (delivery step 5) after 1Pact step 4.
6
+ */
7
+ export const legacyReadUserProfile = defineQuery()((domain) => {
8
+ const { claimedEmail: email, claimedName: displayName } = domain.classes.User.properties;
9
+ return {
10
+ id: 'shell.user.profile',
11
+ page: { size: 1 },
12
+ pagination: { maximumPages: 1 },
13
+ build: ({ user }) => Query.from({ nodes: [Path.id(user)] }).select({
14
+ kind: 'nodes',
15
+ projection: { kind: 'value' },
16
+ }),
17
+ project(pages) {
18
+ const [node] = queryResult.completeNodeValues(pages, 'Shell user profile');
19
+ const text = (value) => (typeof value === 'string' ? value : undefined);
20
+ const recorded = {
21
+ email: text(node?.props[email.key]),
22
+ displayName: text(node?.props[displayName.key]),
23
+ };
24
+ return Object.fromEntries(Object.entries(recorded).filter(([, value]) => value !== undefined));
25
+ },
26
+ };
27
+ });