@astrale-os/shell-react 0.1.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 (378) hide show
  1. package/LICENSE +202 -0
  2. package/dist/application/apps/app-host.d.ts +31 -0
  3. package/dist/application/apps/app-host.d.ts.map +1 -0
  4. package/dist/application/apps/app-host.js +59 -0
  5. package/dist/application/apps/app-logo.d.ts +19 -0
  6. package/dist/application/apps/app-logo.d.ts.map +1 -0
  7. package/dist/application/apps/app-logo.js +31 -0
  8. package/dist/application/apps/apps.hook.d.ts +12 -0
  9. package/dist/application/apps/apps.hook.d.ts.map +1 -0
  10. package/dist/application/apps/apps.hook.js +51 -0
  11. package/dist/application/apps/open-app.hook.d.ts +10 -0
  12. package/dist/application/apps/open-app.hook.d.ts.map +1 -0
  13. package/dist/application/apps/open-app.hook.js +7 -0
  14. package/dist/application/index.d.ts +18 -0
  15. package/dist/application/index.d.ts.map +1 -0
  16. package/dist/application/index.js +12 -0
  17. package/dist/application/roles.hook.d.ts +7 -0
  18. package/dist/application/roles.hook.d.ts.map +1 -0
  19. package/dist/application/roles.hook.js +23 -0
  20. package/dist/application/spaces/current-space.hook.d.ts +7 -0
  21. package/dist/application/spaces/current-space.hook.d.ts.map +1 -0
  22. package/dist/application/spaces/current-space.hook.js +27 -0
  23. package/dist/application/spaces/current-space.store.d.ts +32 -0
  24. package/dist/application/spaces/current-space.store.d.ts.map +1 -0
  25. package/dist/application/spaces/current-space.store.js +79 -0
  26. package/dist/application/spaces/space.hook.d.ts +5 -0
  27. package/dist/application/spaces/space.hook.d.ts.map +1 -0
  28. package/dist/application/spaces/space.hook.js +25 -0
  29. package/dist/application/spaces/spaces.hook.d.ts +14 -0
  30. package/dist/application/spaces/spaces.hook.d.ts.map +1 -0
  31. package/dist/application/spaces/spaces.hook.js +82 -0
  32. package/dist/application/user/user.hook.d.ts +10 -0
  33. package/dist/application/user/user.hook.d.ts.map +1 -0
  34. package/dist/application/user/user.hook.js +19 -0
  35. package/dist/application/user/user.store.d.ts +35 -0
  36. package/dist/application/user/user.store.d.ts.map +1 -0
  37. package/dist/application/user/user.store.js +51 -0
  38. package/dist/auth/act-as.context.d.ts +40 -0
  39. package/dist/auth/act-as.context.d.ts.map +1 -0
  40. package/dist/auth/act-as.context.js +84 -0
  41. package/dist/auth/auth.hook.d.ts +3 -0
  42. package/dist/auth/auth.hook.d.ts.map +1 -0
  43. package/dist/auth/auth.hook.js +25 -0
  44. package/dist/auth/can.hook.d.ts +40 -0
  45. package/dist/auth/can.hook.d.ts.map +1 -0
  46. package/dist/auth/can.hook.js +119 -0
  47. package/dist/auth/index.d.ts +6 -0
  48. package/dist/auth/index.d.ts.map +1 -0
  49. package/dist/auth/index.js +5 -0
  50. package/dist/auth/self.hook.d.ts +3 -0
  51. package/dist/auth/self.hook.d.ts.map +1 -0
  52. package/dist/auth/self.hook.js +11 -0
  53. package/dist/auth/session-kernel.d.ts +4 -0
  54. package/dist/auth/session-kernel.d.ts.map +1 -0
  55. package/dist/auth/session-kernel.js +21 -0
  56. package/dist/graph/action.d.ts +22 -0
  57. package/dist/graph/action.d.ts.map +1 -0
  58. package/dist/graph/action.js +85 -0
  59. package/dist/graph/async.d.ts +11 -0
  60. package/dist/graph/async.d.ts.map +1 -0
  61. package/dist/graph/async.js +60 -0
  62. package/dist/graph/call/call.hook.d.ts +21 -0
  63. package/dist/graph/call/call.hook.d.ts.map +1 -0
  64. package/dist/graph/call/call.hook.js +23 -0
  65. package/dist/graph/call/stream.hook.d.ts +28 -0
  66. package/dist/graph/call/stream.hook.d.ts.map +1 -0
  67. package/dist/graph/call/stream.hook.js +137 -0
  68. package/dist/graph/graph.context.d.ts +4 -0
  69. package/dist/graph/graph.context.d.ts.map +1 -0
  70. package/dist/graph/graph.context.js +10 -0
  71. package/dist/graph/guards.error.d.ts +9 -0
  72. package/dist/graph/guards.error.d.ts.map +1 -0
  73. package/dist/graph/guards.error.js +7 -0
  74. package/dist/graph/index.d.ts +20 -0
  75. package/dist/graph/index.d.ts.map +1 -0
  76. package/dist/graph/index.js +9 -0
  77. package/dist/graph/memory/base.d.ts +21 -0
  78. package/dist/graph/memory/base.d.ts.map +1 -0
  79. package/dist/graph/memory/base.js +33 -0
  80. package/dist/graph/memory/read/envelope.d.ts +71 -0
  81. package/dist/graph/memory/read/envelope.d.ts.map +1 -0
  82. package/dist/graph/memory/read/envelope.js +29 -0
  83. package/dist/graph/memory/read/idle.d.ts +18 -0
  84. package/dist/graph/memory/read/idle.d.ts.map +1 -0
  85. package/dist/graph/memory/read/idle.js +16 -0
  86. package/dist/graph/memory/read/read.d.ts +9 -0
  87. package/dist/graph/memory/read/read.d.ts.map +1 -0
  88. package/dist/graph/memory/read/read.js +87 -0
  89. package/dist/graph/memory/scope.d.ts +7 -0
  90. package/dist/graph/memory/scope.d.ts.map +1 -0
  91. package/dist/graph/memory/scope.js +25 -0
  92. package/dist/graph/mutate/move.hook.d.ts +7 -0
  93. package/dist/graph/mutate/move.hook.d.ts.map +1 -0
  94. package/dist/graph/mutate/move.hook.js +49 -0
  95. package/dist/graph/mutate/mutate.hook.d.ts +17 -0
  96. package/dist/graph/mutate/mutate.hook.d.ts.map +1 -0
  97. package/dist/graph/mutate/mutate.hook.js +45 -0
  98. package/dist/graph/query/children.hook.d.ts +29 -0
  99. package/dist/graph/query/children.hook.d.ts.map +1 -0
  100. package/dist/graph/query/children.hook.js +64 -0
  101. package/dist/graph/query/graph.hook.d.ts +9 -0
  102. package/dist/graph/query/graph.hook.d.ts.map +1 -0
  103. package/dist/graph/query/graph.hook.js +5 -0
  104. package/dist/graph/query/neighbors.hook.d.ts +7 -0
  105. package/dist/graph/query/neighbors.hook.d.ts.map +1 -0
  106. package/dist/graph/query/neighbors.hook.js +79 -0
  107. package/dist/graph/query/node.hook.d.ts +14 -0
  108. package/dist/graph/query/node.hook.d.ts.map +1 -0
  109. package/dist/graph/query/node.hook.js +43 -0
  110. package/dist/graph/query/query.hook.d.ts +14 -0
  111. package/dist/graph/query/query.hook.d.ts.map +1 -0
  112. package/dist/graph/query/query.hook.js +23 -0
  113. package/dist/index.d.ts +43 -0
  114. package/dist/index.d.ts.map +1 -0
  115. package/dist/index.js +34 -0
  116. package/dist/intents/envelope.d.ts +33 -0
  117. package/dist/intents/envelope.d.ts.map +1 -0
  118. package/dist/intents/envelope.js +19 -0
  119. package/dist/intents/index.d.ts +6 -0
  120. package/dist/intents/index.d.ts.map +1 -0
  121. package/dist/intents/index.js +3 -0
  122. package/dist/intents/listen-intent.hook.d.ts +16 -0
  123. package/dist/intents/listen-intent.hook.d.ts.map +1 -0
  124. package/dist/intents/listen-intent.hook.js +75 -0
  125. package/dist/intents/reply.d.ts +9 -0
  126. package/dist/intents/reply.d.ts.map +1 -0
  127. package/dist/intents/reply.js +14 -0
  128. package/dist/intents/send-intent.hook.d.ts +12 -0
  129. package/dist/intents/send-intent.hook.d.ts.map +1 -0
  130. package/dist/intents/send-intent.hook.js +86 -0
  131. package/dist/navigation/adapters/adapter.d.ts +15 -0
  132. package/dist/navigation/adapters/adapter.d.ts.map +1 -0
  133. package/dist/navigation/adapters/adapter.js +1 -0
  134. package/dist/navigation/adapters/memory.adapter.d.ts +9 -0
  135. package/dist/navigation/adapters/memory.adapter.d.ts.map +1 -0
  136. package/dist/navigation/adapters/memory.adapter.js +15 -0
  137. package/dist/navigation/adapters/url.adapter.d.ts +6 -0
  138. package/dist/navigation/adapters/url.adapter.d.ts.map +1 -0
  139. package/dist/navigation/adapters/url.adapter.js +59 -0
  140. package/dist/navigation/history.d.ts +63 -0
  141. package/dist/navigation/history.d.ts.map +1 -0
  142. package/dist/navigation/history.js +144 -0
  143. package/dist/navigation/hooks/ancestors.hook.d.ts +13 -0
  144. package/dist/navigation/hooks/ancestors.hook.d.ts.map +1 -0
  145. package/dist/navigation/hooks/ancestors.hook.js +56 -0
  146. package/dist/navigation/hooks/location.hook.d.ts +4 -0
  147. package/dist/navigation/hooks/location.hook.d.ts.map +1 -0
  148. package/dist/navigation/hooks/location.hook.js +17 -0
  149. package/dist/navigation/hooks/navigate.hook.d.ts +12 -0
  150. package/dist/navigation/hooks/navigate.hook.d.ts.map +1 -0
  151. package/dist/navigation/hooks/navigate.hook.js +33 -0
  152. package/dist/navigation/hooks/scope.hook.d.ts +12 -0
  153. package/dist/navigation/hooks/scope.hook.d.ts.map +1 -0
  154. package/dist/navigation/hooks/scope.hook.js +21 -0
  155. package/dist/navigation/index.d.ts +16 -0
  156. package/dist/navigation/index.d.ts.map +1 -0
  157. package/dist/navigation/index.js +10 -0
  158. package/dist/navigation/link.d.ts +11 -0
  159. package/dist/navigation/link.d.ts.map +1 -0
  160. package/dist/navigation/link.js +62 -0
  161. package/dist/navigation/location.d.ts +48 -0
  162. package/dist/navigation/location.d.ts.map +1 -0
  163. package/dist/navigation/location.js +88 -0
  164. package/dist/navigation/scope.context.d.ts +64 -0
  165. package/dist/navigation/scope.context.d.ts.map +1 -0
  166. package/dist/navigation/scope.context.js +178 -0
  167. package/dist/navigation/snapshot.d.ts +22 -0
  168. package/dist/navigation/snapshot.d.ts.map +1 -0
  169. package/dist/navigation/snapshot.js +65 -0
  170. package/dist/schema/bind-read.d.ts +37 -0
  171. package/dist/schema/bind-read.d.ts.map +1 -0
  172. package/dist/schema/bind-read.js +205 -0
  173. package/dist/schema/binding.d.ts +21 -0
  174. package/dist/schema/binding.d.ts.map +1 -0
  175. package/dist/schema/binding.js +55 -0
  176. package/dist/schema/domain.hook.d.ts +10 -0
  177. package/dist/schema/domain.hook.d.ts.map +1 -0
  178. package/dist/schema/domain.hook.js +7 -0
  179. package/dist/schema/function.hook.d.ts +9 -0
  180. package/dist/schema/function.hook.d.ts.map +1 -0
  181. package/dist/schema/function.hook.js +40 -0
  182. package/dist/schema/index.d.ts +10 -0
  183. package/dist/schema/index.d.ts.map +1 -0
  184. package/dist/schema/index.js +8 -0
  185. package/dist/schema/kernel.hook.d.ts +10 -0
  186. package/dist/schema/kernel.hook.d.ts.map +1 -0
  187. package/dist/schema/kernel.hook.js +8 -0
  188. package/dist/schema/method.hook.d.ts +14 -0
  189. package/dist/schema/method.hook.d.ts.map +1 -0
  190. package/dist/schema/method.hook.js +49 -0
  191. package/dist/schema/tag.d.ts +11 -0
  192. package/dist/schema/tag.d.ts.map +1 -0
  193. package/dist/schema/tag.js +11 -0
  194. package/dist/schema/types.d.ts +73 -0
  195. package/dist/schema/types.d.ts.map +1 -0
  196. package/dist/schema/types.js +1 -0
  197. package/dist/schema/write.d.ts +15 -0
  198. package/dist/schema/write.d.ts.map +1 -0
  199. package/dist/schema/write.js +45 -0
  200. package/dist/selection/index.d.ts +4 -0
  201. package/dist/selection/index.d.ts.map +1 -0
  202. package/dist/selection/index.js +4 -0
  203. package/dist/selection/live.d.ts +21 -0
  204. package/dist/selection/live.d.ts.map +1 -0
  205. package/dist/selection/live.js +116 -0
  206. package/dist/selection/scope.context.d.ts +26 -0
  207. package/dist/selection/scope.context.d.ts.map +1 -0
  208. package/dist/selection/scope.context.js +100 -0
  209. package/dist/selection/selection.hook.d.ts +4 -0
  210. package/dist/selection/selection.hook.d.ts.map +1 -0
  211. package/dist/selection/selection.hook.js +14 -0
  212. package/dist/session/boot/boot.d.ts +19 -0
  213. package/dist/session/boot/boot.d.ts.map +1 -0
  214. package/dist/session/boot/boot.js +45 -0
  215. package/dist/session/boot/ownership.d.ts +18 -0
  216. package/dist/session/boot/ownership.d.ts.map +1 -0
  217. package/dist/session/boot/ownership.js +39 -0
  218. package/dist/session/boot/status.d.ts +24 -0
  219. package/dist/session/boot/status.d.ts.map +1 -0
  220. package/dist/session/boot/status.js +11 -0
  221. package/dist/session/connection/connection.hook.d.ts +3 -0
  222. package/dist/session/connection/connection.hook.d.ts.map +1 -0
  223. package/dist/session/connection/connection.hook.js +12 -0
  224. package/dist/session/connection/connection.store.d.ts +24 -0
  225. package/dist/session/connection/connection.store.d.ts.map +1 -0
  226. package/dist/session/connection/connection.store.js +31 -0
  227. package/dist/session/index.d.ts +8 -0
  228. package/dist/session/index.d.ts.map +1 -0
  229. package/dist/session/index.js +6 -0
  230. package/dist/session/kernel-client.hook.d.ts +9 -0
  231. package/dist/session/kernel-client.hook.d.ts.map +1 -0
  232. package/dist/session/kernel-client.hook.js +5 -0
  233. package/dist/session/kernel-instance.hook.d.ts +9 -0
  234. package/dist/session/kernel-instance.hook.d.ts.map +1 -0
  235. package/dist/session/kernel-instance.hook.js +10 -0
  236. package/dist/session/provider.d.ts +31 -0
  237. package/dist/session/provider.d.ts.map +1 -0
  238. package/dist/session/provider.js +165 -0
  239. package/dist/session/session.context.d.ts +18 -0
  240. package/dist/session/session.context.d.ts.map +1 -0
  241. package/dist/session/session.context.js +8 -0
  242. package/dist/session/shell.hook.d.ts +4 -0
  243. package/dist/session/shell.hook.d.ts.map +1 -0
  244. package/dist/session/shell.hook.js +15 -0
  245. package/dist/window/adopt.d.ts +27 -0
  246. package/dist/window/adopt.d.ts.map +1 -0
  247. package/dist/window/adopt.js +27 -0
  248. package/dist/window/hooks/close-guard.hook.d.ts +6 -0
  249. package/dist/window/hooks/close-guard.hook.d.ts.map +1 -0
  250. package/dist/window/hooks/close-guard.hook.js +90 -0
  251. package/dist/window/hooks/target-node.hook.d.ts +7 -0
  252. package/dist/window/hooks/target-node.hook.d.ts.map +1 -0
  253. package/dist/window/hooks/target-node.hook.js +77 -0
  254. package/dist/window/hooks/views-for.hook.d.ts +8 -0
  255. package/dist/window/hooks/views-for.hook.d.ts.map +1 -0
  256. package/dist/window/hooks/views-for.hook.js +51 -0
  257. package/dist/window/hooks/window.hook.d.ts +4 -0
  258. package/dist/window/hooks/window.hook.d.ts.map +1 -0
  259. package/dist/window/hooks/window.hook.js +14 -0
  260. package/dist/window/hooks/windows.hook.d.ts +15 -0
  261. package/dist/window/hooks/windows.hook.d.ts.map +1 -0
  262. package/dist/window/hooks/windows.hook.js +25 -0
  263. package/dist/window/host.d.ts +31 -0
  264. package/dist/window/host.d.ts.map +1 -0
  265. package/dist/window/host.js +270 -0
  266. package/dist/window/hub.d.ts +41 -0
  267. package/dist/window/hub.d.ts.map +1 -0
  268. package/dist/window/hub.js +100 -0
  269. package/dist/window/index.d.ts +15 -0
  270. package/dist/window/index.d.ts.map +1 -0
  271. package/dist/window/index.js +10 -0
  272. package/dist/window/lifecycle/mount.d.ts +47 -0
  273. package/dist/window/lifecycle/mount.d.ts.map +1 -0
  274. package/dist/window/lifecycle/mount.js +92 -0
  275. package/dist/window/lifecycle/states.d.ts +33 -0
  276. package/dist/window/lifecycle/states.d.ts.map +1 -0
  277. package/dist/window/lifecycle/states.js +7 -0
  278. package/dist/window/placement.d.ts +33 -0
  279. package/dist/window/placement.d.ts.map +1 -0
  280. package/dist/window/placement.js +57 -0
  281. package/dist/window/stage.d.ts +3 -0
  282. package/dist/window/stage.d.ts.map +1 -0
  283. package/dist/window/stage.js +41 -0
  284. package/package.json +59 -0
  285. package/src/application/apps/app-host.tsx +113 -0
  286. package/src/application/apps/app-logo.tsx +56 -0
  287. package/src/application/apps/apps.hook.ts +81 -0
  288. package/src/application/apps/open-app.hook.ts +18 -0
  289. package/src/application/index.ts +22 -0
  290. package/src/application/roles.hook.ts +41 -0
  291. package/src/application/spaces/current-space.hook.ts +43 -0
  292. package/src/application/spaces/current-space.store.ts +110 -0
  293. package/src/application/spaces/space.hook.ts +41 -0
  294. package/src/application/spaces/spaces.hook.ts +113 -0
  295. package/src/application/user/user.hook.ts +27 -0
  296. package/src/application/user/user.store.ts +85 -0
  297. package/src/auth/act-as.context.tsx +124 -0
  298. package/src/auth/auth.hook.ts +36 -0
  299. package/src/auth/can.hook.ts +149 -0
  300. package/src/auth/index.ts +6 -0
  301. package/src/auth/self.hook.ts +14 -0
  302. package/src/auth/session-kernel.ts +24 -0
  303. package/src/graph/action.ts +127 -0
  304. package/src/graph/async.ts +87 -0
  305. package/src/graph/call/call.hook.ts +42 -0
  306. package/src/graph/call/stream.hook.ts +200 -0
  307. package/src/graph/graph.context.ts +14 -0
  308. package/src/graph/guards.error.ts +58 -0
  309. package/src/graph/index.ts +20 -0
  310. package/src/graph/memory/base.ts +50 -0
  311. package/src/graph/memory/read/envelope.ts +98 -0
  312. package/src/graph/memory/read/idle.ts +24 -0
  313. package/src/graph/memory/read/read.ts +103 -0
  314. package/src/graph/memory/scope.ts +29 -0
  315. package/src/graph/mutate/move.hook.ts +70 -0
  316. package/src/graph/mutate/mutate.hook.ts +69 -0
  317. package/src/graph/query/children.hook.ts +136 -0
  318. package/src/graph/query/graph.hook.ts +13 -0
  319. package/src/graph/query/neighbors.hook.ts +124 -0
  320. package/src/graph/query/node.hook.ts +83 -0
  321. package/src/graph/query/query.hook.ts +42 -0
  322. package/src/index.ts +202 -0
  323. package/src/intents/envelope.ts +52 -0
  324. package/src/intents/index.ts +6 -0
  325. package/src/intents/listen-intent.hook.ts +92 -0
  326. package/src/intents/reply.ts +24 -0
  327. package/src/intents/send-intent.hook.ts +111 -0
  328. package/src/navigation/adapters/adapter.ts +13 -0
  329. package/src/navigation/adapters/memory.adapter.ts +22 -0
  330. package/src/navigation/adapters/url.adapter.ts +61 -0
  331. package/src/navigation/history.ts +170 -0
  332. package/src/navigation/hooks/ancestors.hook.ts +71 -0
  333. package/src/navigation/hooks/location.hook.ts +21 -0
  334. package/src/navigation/hooks/navigate.hook.ts +43 -0
  335. package/src/navigation/hooks/scope.hook.ts +34 -0
  336. package/src/navigation/index.ts +17 -0
  337. package/src/navigation/link.tsx +110 -0
  338. package/src/navigation/location.ts +122 -0
  339. package/src/navigation/scope.context.tsx +267 -0
  340. package/src/navigation/snapshot.ts +79 -0
  341. package/src/schema/bind-read.ts +319 -0
  342. package/src/schema/binding.ts +91 -0
  343. package/src/schema/domain.hook.ts +16 -0
  344. package/src/schema/function.hook.ts +68 -0
  345. package/src/schema/index.ts +25 -0
  346. package/src/schema/kernel.hook.ts +17 -0
  347. package/src/schema/method.hook.ts +103 -0
  348. package/src/schema/tag.ts +19 -0
  349. package/src/schema/types.ts +150 -0
  350. package/src/schema/write.ts +80 -0
  351. package/src/selection/index.ts +5 -0
  352. package/src/selection/live.ts +142 -0
  353. package/src/selection/scope.context.tsx +151 -0
  354. package/src/selection/selection.hook.ts +18 -0
  355. package/src/session/boot/boot.ts +57 -0
  356. package/src/session/boot/ownership.ts +54 -0
  357. package/src/session/boot/status.ts +32 -0
  358. package/src/session/connection/connection.hook.ts +16 -0
  359. package/src/session/connection/connection.store.ts +58 -0
  360. package/src/session/index.ts +8 -0
  361. package/src/session/kernel-client.hook.ts +13 -0
  362. package/src/session/kernel-instance.hook.ts +22 -0
  363. package/src/session/provider.tsx +205 -0
  364. package/src/session/session.context.ts +27 -0
  365. package/src/session/shell.hook.ts +19 -0
  366. package/src/window/adopt.ts +57 -0
  367. package/src/window/hooks/close-guard.hook.ts +100 -0
  368. package/src/window/hooks/target-node.hook.ts +94 -0
  369. package/src/window/hooks/views-for.hook.ts +82 -0
  370. package/src/window/hooks/window.hook.ts +18 -0
  371. package/src/window/hooks/windows.hook.ts +40 -0
  372. package/src/window/host.tsx +347 -0
  373. package/src/window/hub.ts +156 -0
  374. package/src/window/index.ts +17 -0
  375. package/src/window/lifecycle/mount.ts +134 -0
  376. package/src/window/lifecycle/states.ts +23 -0
  377. package/src/window/placement.ts +84 -0
  378. package/src/window/stage.tsx +46 -0
@@ -0,0 +1,79 @@
1
+ // Stable idles for when the OS plane is unavailable (§12.2) — a fixed snapshot
2
+ // and a no-op subscription keep `useSyncExternalStore` tear-free without touching
3
+ // (and re-triggering a fetch on) the real current-space store.
4
+ export const IDLE_SNAPSHOT = { space: null, pending: false, error: undefined };
5
+ export const idleSnapshot = () => IDLE_SNAPSHOT;
6
+ export const noopSubscribe = () => () => { };
7
+ function createStore(load) {
8
+ let confirmed = null;
9
+ let loaded = false;
10
+ let pending = false;
11
+ let error = undefined;
12
+ let override = null;
13
+ let seq = 0;
14
+ let snap = { space: null, pending: false, error: undefined };
15
+ const listeners = new Set();
16
+ /** Recompute the projection (override wins) and notify only on a real change. */
17
+ function rebuild() {
18
+ const space = override !== null ? override.space : confirmed;
19
+ if (space === snap.space && pending === snap.pending && error === snap.error)
20
+ return;
21
+ snap = { space, pending, error };
22
+ for (const l of listeners)
23
+ l();
24
+ }
25
+ function fetch() {
26
+ const my = ++seq;
27
+ pending = true;
28
+ rebuild();
29
+ return load().then((space) => {
30
+ if (my !== seq)
31
+ return;
32
+ confirmed = space;
33
+ loaded = true;
34
+ pending = false;
35
+ error = undefined;
36
+ rebuild();
37
+ }, (e) => {
38
+ if (my !== seq)
39
+ return;
40
+ pending = false;
41
+ error = e;
42
+ rebuild();
43
+ });
44
+ }
45
+ return {
46
+ subscribe(cb) {
47
+ listeners.add(cb);
48
+ if (!loaded && !pending)
49
+ void fetch();
50
+ return () => listeners.delete(cb);
51
+ },
52
+ getSnapshot: () => snap,
53
+ ensure() {
54
+ if (!loaded && !pending)
55
+ void fetch();
56
+ },
57
+ refresh: () => fetch(),
58
+ setOptimistic(space) {
59
+ override = { space };
60
+ rebuild();
61
+ },
62
+ clearOptimistic() {
63
+ if (override === null)
64
+ return;
65
+ override = null;
66
+ rebuild();
67
+ },
68
+ };
69
+ }
70
+ const stores = new WeakMap();
71
+ /** The one current-space store for a Shell (created on first touch). */
72
+ export function currentSpaceStore(shell) {
73
+ let s = stores.get(shell);
74
+ if (s === undefined) {
75
+ s = createStore(() => shell.user.currentSpace());
76
+ stores.set(shell, s);
77
+ }
78
+ return s;
79
+ }
@@ -0,0 +1,5 @@
1
+ import type { NodeRefInput } from '@astrale-os/kernel-client';
2
+ import type { CurrentSpaceResult } from './current-space.hook';
3
+ export type SpaceResult = CurrentSpaceResult;
4
+ export declare function useSpace(ref: NodeRefInput | null | undefined): SpaceResult;
5
+ //# sourceMappingURL=space.hook.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"space.hook.d.ts","sourceRoot":"","sources":["../../../src/application/spaces/space.hook.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAU7D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAO9D,MAAM,MAAM,WAAW,GAAG,kBAAkB,CAAA;AAE5C,wBAAgB,QAAQ,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI,GAAG,SAAS,GAAG,WAAW,CAqB1E"}
@@ -0,0 +1,25 @@
1
+ import { normalizeRef } from '@astrale-os/kernel-client';
2
+ /**
3
+ * useSpace(ref) (API §12.2) — a single space by ref; `null`/`undefined` (or an
4
+ * unavailable OS plane) is idle (§1.3). One-shot today (§12 flag).
5
+ */
6
+ import { useMemo } from 'react';
7
+ import { useAsyncResource } from '../../graph/async';
8
+ import { isIdleInput } from '../../graph/memory/read/idle';
9
+ import { useShell } from '../../session/shell.hook';
10
+ import { isOsPlaneAvailable } from '../user/user.store';
11
+ export function useSpace(ref) {
12
+ const shell = useShell();
13
+ const idle = isIdleInput(ref) || !isOsPlaneAvailable(shell);
14
+ // The inline guard (not the stored `idle`) narrows `ref` to non-null below.
15
+ const key = idle ? null : normalizeRef(ref);
16
+ const res = useAsyncResource(idle ? null : () => shell.spaces.get(ref), null, [shell, key]);
17
+ return useMemo(() => ({
18
+ space: idle ? null : res.data,
19
+ pending: idle ? false : res.pending,
20
+ error: idle ? undefined : res.error,
21
+ live: false,
22
+ seq: 0,
23
+ refetch: res.refetch,
24
+ }), [idle, res]);
25
+ }
@@ -0,0 +1,14 @@
1
+ import type { NodeRefInput } from '@astrale-os/kernel-client';
2
+ import type { SpaceNode } from '@astrale-os/shell';
3
+ import type { Action } from '../../graph/action';
4
+ import type { ReadState } from '../../graph/memory/read/envelope';
5
+ export interface SpacesResult extends ReadState {
6
+ /** Spaces-dir children, live (one-shot today), the caller's readable set. */
7
+ readonly spaces: readonly SpaceNode[];
8
+ /** The `selected_space` target — optimistically ahead during a `switch`. */
9
+ readonly selected: SpaceNode | null;
10
+ /** `user::switchSpace` with a manual optimistic overlay (§1.6). */
11
+ readonly switch: Action<[NodeRefInput], void>;
12
+ }
13
+ export declare function useSpaces(): SpacesResult;
14
+ //# sourceMappingURL=spaces.hook.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spaces.hook.d.ts","sourceRoot":"","sources":["../../../src/application/spaces/spaces.hook.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAC7D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAYlD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAA;AAUjE,MAAM,WAAW,YAAa,SAAQ,SAAS;IAC7C,6EAA6E;IAC7E,QAAQ,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,CAAA;IACrC,4EAA4E;IAC5E,QAAQ,CAAC,QAAQ,EAAE,SAAS,GAAG,IAAI,CAAA;IACnC,mEAAmE;IACnE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,YAAY,CAAC,EAAE,IAAI,CAAC,CAAA;CAC9C;AAED,wBAAgB,SAAS,IAAI,YAAY,CA4DxC"}
@@ -0,0 +1,82 @@
1
+ import { normalizeRef } from '@astrale-os/kernel-client';
2
+ /**
3
+ * useSpaces (API §12.2) — the spaces list, the selected space, and a `switch`
4
+ * Action that repoints the `selected_space` edge. Reads the SAME per-Shell
5
+ * current-space store as useCurrentSpace/useApps, so a switch re-themes every
6
+ * consumer in the window at once — optimistically ahead of the round-trip (§1.6),
7
+ * commit reconciles, failure rolls back. Reads are one-shot today (§12 flag).
8
+ */
9
+ import { useEffect, useMemo, useSyncExternalStore } from 'react';
10
+ import { useAction } from '../../graph/action';
11
+ import { useAsyncResource } from '../../graph/async';
12
+ import { useShell } from '../../session/shell.hook';
13
+ import { isOsPlaneAvailable } from '../user/user.store';
14
+ import { currentSpaceStore, idleSnapshot, noopSubscribe } from './current-space.store';
15
+ const NO_SPACES = [];
16
+ export function useSpaces() {
17
+ const shell = useShell();
18
+ const available = isOsPlaneAvailable(shell);
19
+ const store = currentSpaceStore(shell);
20
+ const spacesRes = useAsyncResource(available ? () => shell.spaces.list() : null, NO_SPACES, [shell, available]);
21
+ useEffect(() => {
22
+ if (available)
23
+ store.ensure();
24
+ }, [store, available]);
25
+ const selectedSnap = useSyncExternalStore(available ? store.subscribe : noopSubscribe, available ? store.getSnapshot : idleSnapshot, available ? store.getSnapshot : idleSnapshot);
26
+ const spaces = spacesRes.data;
27
+ const switchAction = useAction(async (ref) => {
28
+ // Optimistic override on the SHARED store, so useCurrentSpace / useApps ahead
29
+ // of the round-trip too (§12.2). Only overlay a known target (a path ref that
30
+ // matches nothing in the list simply skips the preview).
31
+ const target = findSpace(spaces, ref);
32
+ if (target !== null)
33
+ store.setOptimistic(target);
34
+ try {
35
+ await shell.user.switchSpace(ref);
36
+ await store.refresh(); // reconcile confirmed truth BEFORE dropping the preview
37
+ store.clearOptimistic();
38
+ }
39
+ catch (error) {
40
+ store.clearOptimistic(); // rollback: reveal the confirmed (previous) space
41
+ throw error;
42
+ }
43
+ });
44
+ return useMemo(() => ({
45
+ spaces,
46
+ selected: selectedSnap.space,
47
+ switch: switchAction,
48
+ pending: spacesRes.pending || selectedSnap.pending,
49
+ error: spacesRes.error ?? selectedSnap.error,
50
+ live: false,
51
+ seq: 0,
52
+ refetch: async () => {
53
+ await Promise.all([spacesRes.refetch(), store.refresh()]);
54
+ },
55
+ }), [
56
+ spaces,
57
+ selectedSnap,
58
+ switchAction,
59
+ spacesRes.pending,
60
+ spacesRes.error,
61
+ spacesRes.refetch,
62
+ store,
63
+ ]);
64
+ }
65
+ /** The space in `spaces` denoted by `ref`, or `null` (path refs don't match by id). */
66
+ function findSpace(spaces, ref) {
67
+ const id = refIdOf(ref);
68
+ if (id === null)
69
+ return null;
70
+ return spaces.find((s) => s.id === id) ?? null;
71
+ }
72
+ /** A bound-node-ish subject carries a graph id. */
73
+ function hasId(x) {
74
+ return typeof x === 'object' && x !== null && 'id' in x;
75
+ }
76
+ /** The graph id a subject denotes, or `null` when it is a path (no id to match). */
77
+ function refIdOf(x) {
78
+ if (hasId(x))
79
+ return x.id;
80
+ const raw = normalizeRef(x);
81
+ return raw.startsWith('@') ? raw.slice(1) : null;
82
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * useUser (API §12.2) — self as the shell-domain `User` (typed
3
+ * firstName/lastName/email). The provider PRE-RESOLVES it at boot (`primeUser`),
4
+ * so `useUser` is synchronous below the provider (API §2). OS-plane absent → throws
5
+ * descriptively to the nearest boundary; a never-primed shell suspends on first use
6
+ * (§1.4). FLAG: not yet re-rendered on rename — becomes live via a memory shape.
7
+ */
8
+ import type { UserNode } from '@astrale-os/shell';
9
+ export declare function useUser(): UserNode;
10
+ //# sourceMappingURL=user.hook.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user.hook.d.ts","sourceRoot":"","sources":["../../../src/application/user/user.hook.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAKjD,wBAAgB,OAAO,IAAI,QAAQ,CAclC"}
@@ -0,0 +1,19 @@
1
+ import { useShell } from '../../session/shell.hook';
2
+ import { loadUser, userCache } from './user.store';
3
+ export function useUser() {
4
+ const shell = useShell();
5
+ const entry = userCache.get(shell) ?? loadUser(shell);
6
+ if (entry.status === 'pending')
7
+ throw entry.promise;
8
+ // OS plane resolved absent at boot — throw to the nearest boundary; do NOT
9
+ // re-load (the plane is not coming back this session).
10
+ if (entry.status === 'unavailable')
11
+ throw entry.error;
12
+ if (entry.status === 'rejected') {
13
+ // Retryable transient: drop the poisoned cell so an error-boundary retry
14
+ // re-loads `me()` instead of re-throwing the same failure forever.
15
+ userCache.delete(shell);
16
+ throw entry.error;
17
+ }
18
+ return entry.value;
19
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * The OS-plane user store (API §2/§12.2). Provider-boot priming (`primeUser`) seeds
3
+ * the per-Shell user cache so `useUser` is synchronous, and tracks OS-plane
4
+ * availability: a missing/rejecting `shell.user.me` marks the plane down (the other
5
+ * OS hooks then read idle) without failing boot. A never-primed shell falls back to
6
+ * a lazy cold read that SUSPENDS on first use (§1.4).
7
+ */
8
+ import type { Shell, UserNode } from '@astrale-os/shell';
9
+ export type UserEntry = {
10
+ status: 'pending';
11
+ promise: Promise<void>;
12
+ } | {
13
+ status: 'resolved';
14
+ value: UserNode;
15
+ } | {
16
+ status: 'rejected';
17
+ error: unknown;
18
+ }
19
+ /** OS plane absent — throw descriptively, do NOT re-load (a reload just refails). */
20
+ | {
21
+ status: 'unavailable';
22
+ error: unknown;
23
+ };
24
+ export declare const userCache: WeakMap<Shell, UserEntry>;
25
+ /** Is the OS plane (shell.user/spaces/apps) usable for this shell? */
26
+ export declare function isOsPlaneAvailable(shell: Shell): boolean;
27
+ /**
28
+ * Provider-boot priming (API §2). Best-effort: seed the user cache so `useUser`
29
+ * is synchronous, or mark the OS plane down. NEVER throws — boot must not fail on
30
+ * a missing OS plane.
31
+ */
32
+ export declare function primeUser(shell: Shell): Promise<void>;
33
+ /** Kick off `me()` lazily (a shell that was never primed) and cache a suspense cell. */
34
+ export declare function loadUser(shell: Shell): UserEntry;
35
+ //# sourceMappingURL=user.store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user.store.d.ts","sourceRoot":"","sources":["../../../src/application/user/user.store.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAExD,MAAM,MAAM,SAAS,GACjB;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,GAC7C;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,QAAQ,CAAA;CAAE,GACvC;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE;AACxC,qFAAqF;GACnF;IAAE,MAAM,EAAE,aAAa,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAA;AAE7C,eAAO,MAAM,SAAS,2BAAkC,CAAA;AAKxD,sEAAsE;AACtE,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAExD;AAcD;;;;GAIG;AACH,wBAAsB,SAAS,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAkB3D;AAED,wFAAwF;AACxF,wBAAgB,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,SAAS,CAoBhD"}
@@ -0,0 +1,51 @@
1
+ export const userCache = new WeakMap();
2
+ /** Shells whose OS plane could not be resolved at boot — OS hooks read idle. */
3
+ const osPlaneDown = new WeakSet();
4
+ /** Is the OS plane (shell.user/spaces/apps) usable for this shell? */
5
+ export function isOsPlaneAvailable(shell) {
6
+ return !osPlaneDown.has(shell);
7
+ }
8
+ function osPlaneError(cause) {
9
+ const detail = cause instanceof Error ? cause.message : String(cause);
10
+ return new Error(`The OS plane is unavailable (useUser/useSpaces/useApps): shell.user.me() could not resolve ` +
11
+ `— the workspace/shell domain may not be installed for this identity. (${detail})`);
12
+ }
13
+ /**
14
+ * Provider-boot priming (API §2). Best-effort: seed the user cache so `useUser`
15
+ * is synchronous, or mark the OS plane down. NEVER throws — boot must not fail on
16
+ * a missing OS plane.
17
+ */
18
+ export async function primeUser(shell) {
19
+ const me = shell.user?.me;
20
+ if (typeof me !== 'function') {
21
+ osPlaneDown.add(shell);
22
+ userCache.set(shell, {
23
+ status: 'unavailable',
24
+ error: osPlaneError('shell.user.me is not a function'),
25
+ });
26
+ return;
27
+ }
28
+ try {
29
+ const value = await me.call(shell.user);
30
+ osPlaneDown.delete(shell);
31
+ userCache.set(shell, { status: 'resolved', value });
32
+ }
33
+ catch (error) {
34
+ osPlaneDown.add(shell);
35
+ userCache.set(shell, { status: 'unavailable', error: osPlaneError(error) });
36
+ }
37
+ }
38
+ /** Kick off `me()` lazily (a shell that was never primed) and cache a suspense cell. */
39
+ export function loadUser(shell) {
40
+ const cell = { status: 'pending' };
41
+ cell.promise = shell.user.me().then((value) => {
42
+ cell.status = 'resolved';
43
+ cell.value = value;
44
+ }, (error) => {
45
+ cell.status = 'rejected';
46
+ cell.error = error;
47
+ });
48
+ const entry = cell;
49
+ userCache.set(shell, entry);
50
+ return entry;
51
+ }
@@ -0,0 +1,40 @@
1
+ import type { CredentialInput, FnMap } from '@astrale-os/kernel-client';
2
+ import type { BoundClientSessionView } from '@astrale-os/kernel-client/session';
3
+ import type { ReactElement, ReactNode } from 'react';
4
+ import type { SelfNode } from '../session/session.context';
5
+ /** A bound session view — the kernel surface `session.as(cred)` yields. */
6
+ export type SessionView = BoundClientSessionView<FnMap>;
7
+ /** A whoami-shaped identity/graph node (kernel-client does not yet re-export `Node` — G8). */
8
+ export type NodeValue = SelfNode;
9
+ /** The root scope key — the memory's own default scope (`createMemory` default). */
10
+ export declare const ROOT_SCOPE = "default";
11
+ /**
12
+ * The principal a subtree acts as (API §4). `scope` is the memory isolation key
13
+ * (§5.4): the graph plane scopes its memory by `memory.forScope(scope)` so an
14
+ * <ActAs> subtree never shares cached results with another principal.
15
+ */
16
+ export interface IdentityBinding {
17
+ readonly kernel: SessionView;
18
+ readonly self: SelfNode;
19
+ readonly scope: string;
20
+ }
21
+ export declare const IdentityContext: import("react").Context<IdentityBinding | null>;
22
+ /**
23
+ * The principal this subtree dispatches as. An <ActAs> value wins; otherwise the
24
+ * root binding off ShellContext. Throws outside a provider, or when the bound
25
+ * kernel resolved no identity (a bare prebuilt Shell with no auth surface).
26
+ */
27
+ export declare function useIdentityBinding(): IdentityBinding;
28
+ export interface ActAsProps {
29
+ /** The principal to act as. A thunk is resolved by the kernel per dispatch. */
30
+ credential: CredentialInput | (() => CredentialInput);
31
+ children: ReactNode;
32
+ }
33
+ /**
34
+ * A subtree that dispatches as another principal: rebinds the kernel (session.as),
35
+ * resolves whoami, and provides a fresh identity binding with a DISTINCT memory
36
+ * scope (`as:<id>`). Nestable — it rebinds from the current effective principal. A
37
+ * brief nested boot holds the subtree (renders null) until whoami resolves.
38
+ */
39
+ export declare function ActAs({ credential, children }: ActAsProps): ReactElement | null;
40
+ //# sourceMappingURL=act-as.context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"act-as.context.d.ts","sourceRoot":"","sources":["../../src/auth/act-as.context.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAA;AACvE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAA;AAC/E,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAWpD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAA;AAI1D,2EAA2E;AAC3E,MAAM,MAAM,WAAW,GAAG,sBAAsB,CAAC,KAAK,CAAC,CAAA;AAEvD,8FAA8F;AAC9F,MAAM,MAAM,SAAS,GAAG,QAAQ,CAAA;AAEhC,oFAAoF;AACpF,eAAO,MAAM,UAAU,YAAY,CAAA;AAEnC;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;IAC5B,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB;AACD,eAAO,MAAM,eAAe,iDAA8C,CAAA;AAG1E;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,eAAe,CAiBpD;AAED,MAAM,WAAW,UAAU;IACzB,+EAA+E;IAC/E,UAAU,EAAE,eAAe,GAAG,CAAC,MAAM,eAAe,CAAC,CAAA;IACrD,QAAQ,EAAE,SAAS,CAAA;CACpB;AAED;;;;;GAKG;AACH,wBAAgB,KAAK,CAAC,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,UAAU,GAAG,YAAY,GAAG,IAAI,CAkC/E"}
@@ -0,0 +1,84 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /**
3
+ * The acting-principal binding (API §4). `IdentityContext` seats the effective
4
+ * principal a subtree dispatches as — its bound kernel view + whoami + memory
5
+ * scope; `useIdentityBinding` resolves it (an `<ActAs>` override, else the root
6
+ * off ShellContext). `<ActAs>` rebinds a subtree to another principal with a
7
+ * DISTINCT memory scope so results never leak across principals (§5.4).
8
+ */
9
+ import { createContext, useContext, useEffect, useMemo, useState } from 'react';
10
+ import { ShellContext } from '../session/session.context';
11
+ /** The root scope key — the memory's own default scope (`createMemory` default). */
12
+ export const ROOT_SCOPE = 'default';
13
+ export const IdentityContext = createContext(null);
14
+ IdentityContext.displayName = 'AstraleIdentityContext';
15
+ /**
16
+ * The principal this subtree dispatches as. An <ActAs> value wins; otherwise the
17
+ * root binding off ShellContext. Throws outside a provider, or when the bound
18
+ * kernel resolved no identity (a bare prebuilt Shell with no auth surface).
19
+ */
20
+ export function useIdentityBinding() {
21
+ const override = useContext(IdentityContext);
22
+ if (override !== null)
23
+ return override;
24
+ const runtime = useContext(ShellContext);
25
+ if (runtime === null) {
26
+ throw new Error('identity hooks must be used within a <ShellProvider>');
27
+ }
28
+ if (runtime.self === null) {
29
+ throw new Error('identity hooks require an identity: this shell exposed no auth surface, so whoami ' +
30
+ 'resolved nothing at boot');
31
+ }
32
+ // The root binding reads stable fields (self, shell.kernel), so a fresh object
33
+ // per render is inert — consumers key off `kernel`/`self`, both stable.
34
+ return { kernel: runtime.shell.kernel, self: runtime.self, scope: ROOT_SCOPE };
35
+ }
36
+ /**
37
+ * A subtree that dispatches as another principal: rebinds the kernel (session.as),
38
+ * resolves whoami, and provides a fresh identity binding with a DISTINCT memory
39
+ * scope (`as:<id>`). Nestable — it rebinds from the current effective principal. A
40
+ * brief nested boot holds the subtree (renders null) until whoami resolves.
41
+ */
42
+ export function ActAs({ credential, children }) {
43
+ const parent = useIdentityBinding();
44
+ // Key the rebind on a STABLE credential identity (like `configIdentity` does),
45
+ // so an inline object credential (`credential={{ … }}`) does not re-mint the
46
+ // session view — and re-run whoami, unmounting the subtree — every parent
47
+ // render. A thunk still keys by reference: pass a stable thunk to avoid churn.
48
+ const credKey = credentialIdentity(credential);
49
+ // eslint-disable-next-line react-hooks/exhaustive-deps
50
+ const kernel = useMemo(() => parent.kernel.as(credential), [parent.kernel, credKey]);
51
+ const [self, setSelf] = useState(null);
52
+ useEffect(() => {
53
+ let alive = true;
54
+ setSelf(null);
55
+ void kernel.auth.whoami().then((node) => {
56
+ if (alive)
57
+ setSelf(node);
58
+ }, () => {
59
+ /* held (null) subtree on resolve failure — transport errors surface via the provider */
60
+ });
61
+ return () => {
62
+ alive = false;
63
+ };
64
+ }, [kernel]);
65
+ const value = useMemo(() => (self === null ? null : { kernel, self, scope: `as:${self.id}` }), [kernel, self]);
66
+ if (value === null)
67
+ return null;
68
+ return _jsx(IdentityContext.Provider, { value: value, children: children });
69
+ }
70
+ /**
71
+ * A stable identity for a credential: the thunk by reference, a string as itself,
72
+ * and an object by a serialized form — so an equal inline object does not churn
73
+ * the memo (worst case a serialize failure falls back to reference identity).
74
+ */
75
+ function credentialIdentity(credential) {
76
+ if (typeof credential === 'function' || typeof credential === 'string')
77
+ return credential;
78
+ try {
79
+ return `cred:${JSON.stringify(credential)}`;
80
+ }
81
+ catch {
82
+ return credential;
83
+ }
84
+ }
@@ -0,0 +1,3 @@
1
+ import type { AuthApi } from '@astrale-os/kernel-client/auth';
2
+ export declare function useAuth(): AuthApi;
3
+ //# sourceMappingURL=auth.hook.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.hook.d.ts","sourceRoot":"","sources":["../../src/auth/auth.hook.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAA;AAkB7D,wBAAgB,OAAO,IAAI,OAAO,CAGjC"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * useAuth (API §4) — the imperative AuthApi of the effective principal
3
+ * (whoami/credential/mint/delegate/check/grant/revoke/bind/unbind). Grant and
4
+ * revoke additionally nudge the principal's useCan ledger on success, delivering
5
+ * the Tier-0 local re-check (SPEC §11.3). DEVIATION: API §4 describes a pure
6
+ * passthrough; the wrap is the only way to surface a local grant/revoke today,
7
+ * since permissions dispatch as identity methods rather than graph patches.
8
+ * Cross-client liveness still awaits the watch tiers (G7).
9
+ */
10
+ import { useMemo } from 'react';
11
+ import { useIdentityBinding } from './act-as.context';
12
+ import { ledgerFor } from './can.hook';
13
+ export function useAuth() {
14
+ const { kernel } = useIdentityBinding();
15
+ return useMemo(() => withLedgerNudge(kernel), [kernel]);
16
+ }
17
+ /** Wrap grant/revoke so a successful local change re-checks the principal's cells. */
18
+ function withLedgerNudge(kernel) {
19
+ const auth = kernel.auth;
20
+ const ledger = ledgerFor(kernel);
21
+ const invalidate = () => ledger.invalidateAll();
22
+ const grant = ((arg) => Promise.resolve(auth.grant(arg)).then(invalidate));
23
+ const revoke = ((arg) => Promise.resolve(auth.revoke(arg)).then(invalidate));
24
+ return { ...auth, grant, revoke };
25
+ }
@@ -0,0 +1,40 @@
1
+ import type { AuthApi, Perms } from '@astrale-os/kernel-client/auth';
2
+ import type { PathLike, Ref } from '@astrale-os/kernel-client/graph';
3
+ import type { NodeValue, SessionView } from './act-as.context';
4
+ /** A node value carries the id/class/path triple (mirrors the memory's `isNodeValue`). */
5
+ export declare function isNodeValue(x: unknown): x is NodeValue;
6
+ /** Normalize a `useCan` subject to a dispatchable `Ref` plus a stable dedup key. */
7
+ export declare function toRef(on: NodeValue | PathLike): {
8
+ ref: Ref;
9
+ key: string;
10
+ };
11
+ /** One deduped check — its last-known value plus the subscribers watching it. */
12
+ declare class CheckCell {
13
+ private readonly auth;
14
+ private readonly perms;
15
+ private readonly on;
16
+ value: boolean | undefined;
17
+ private inFlight;
18
+ private readonly listeners;
19
+ constructor(auth: AuthApi, perms: Perms, on: Ref);
20
+ subscribe: (onChange: () => void) => (() => void);
21
+ getSnapshot: () => boolean | undefined;
22
+ /** Run the check once when the value is unknown and nothing is in flight. */
23
+ ensure(): void;
24
+ /** Force a re-check (local grant/revoke on this principal). */
25
+ invalidate(): void;
26
+ private run;
27
+ }
28
+ /** Per-principal cell registry — dedup across the whole tree for one kernel handle. */
29
+ export declare class CheckLedger {
30
+ private readonly auth;
31
+ private readonly cells;
32
+ constructor(auth: AuthApi);
33
+ cell(key: string, perms: Perms, on: Ref): CheckCell;
34
+ /** Re-check every observed cell — conservative Tier-0 sweep after a local grant/revoke. */
35
+ invalidateAll(): void;
36
+ }
37
+ export declare function ledgerFor(kernel: SessionView): CheckLedger;
38
+ export declare function useCan(perms: Perms, on: NodeValue | PathLike | null | undefined): boolean | undefined;
39
+ export {};
40
+ //# sourceMappingURL=can.hook.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"can.hook.d.ts","sourceRoot":"","sources":["../../src/auth/can.hook.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,gCAAgC,CAAA;AACpE,OAAO,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,iCAAiC,CAAA;AAapE,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAO9D,0FAA0F;AAC1F,wBAAgB,WAAW,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,SAAS,CAEtD;AAED,oFAAoF;AACpF,wBAAgB,KAAK,CAAC,EAAE,EAAE,SAAS,GAAG,QAAQ,GAAG;IAAE,GAAG,EAAE,GAAG,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAGzE;AAID,iFAAiF;AACjF,cAAM,SAAS;IAMX,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,EAAE;IAPrB,KAAK,EAAE,OAAO,GAAG,SAAS,CAAY;IACtC,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAwB;IAElD,YACmB,IAAI,EAAE,OAAO,EACb,KAAK,EAAE,KAAK,EACZ,EAAE,EAAE,GAAG,EACtB;IAEJ,SAAS,aAAc,MAAM,IAAI,KAAG,CAAC,MAAM,IAAI,CAAC,CAI/C;IAED,WAAW,QAAO,OAAO,GAAG,SAAS,CAAc;IAEnD,6EAA6E;IAC7E,MAAM,IAAI,IAAI,CAGb;IAED,+DAA+D;IAC/D,UAAU,IAAI,IAAI,CAMjB;IAED,OAAO,CAAC,GAAG;CAkBZ;AAED,uFAAuF;AACvF,qBAAa,WAAW;IAGV,OAAO,CAAC,QAAQ,CAAC,IAAI;IAFjC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA+B;IAErD,YAA6B,IAAI,EAAE,OAAO,EAAI;IAE9C,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,GAAG,GAAG,SAAS,CAOlD;IAED,2FAA2F;IAC3F,aAAa,IAAI,IAAI,CAEpB;CACF;AAMD,wBAAgB,SAAS,CAAC,MAAM,EAAE,WAAW,GAAG,WAAW,CAO1D;AAID,wBAAgB,MAAM,CACpB,KAAK,EAAE,KAAK,EACZ,EAAE,EAAE,SAAS,GAAG,QAAQ,GAAG,IAAI,GAAG,SAAS,GAC1C,OAAO,GAAG,SAAS,CAoBrB"}