@astrale-os/shell-react 0.2.9 → 0.2.10-beta.3

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 (335) hide show
  1. package/dist/application/apps/app-host.d.ts +4 -15
  2. package/dist/application/apps/app-host.d.ts.map +1 -1
  3. package/dist/application/apps/app-host.js +1 -1
  4. package/dist/application/apps/apps.hook.d.ts +7 -4
  5. package/dist/application/apps/apps.hook.d.ts.map +1 -1
  6. package/dist/application/apps/apps.hook.js +10 -2
  7. package/dist/application/apps/domains.hook.d.ts +1 -1
  8. package/dist/application/apps/domains.hook.d.ts.map +1 -1
  9. package/dist/application/apps/domains.hook.js +1 -1
  10. package/dist/application/apps/open-app.hook.d.ts +2 -3
  11. package/dist/application/apps/open-app.hook.d.ts.map +1 -1
  12. package/dist/application/index.d.ts +2 -4
  13. package/dist/application/index.d.ts.map +1 -1
  14. package/dist/application/index.js +2 -3
  15. package/dist/application/spaces/space.hook.d.ts +2 -2
  16. package/dist/application/spaces/space.hook.d.ts.map +1 -1
  17. package/dist/application/spaces/space.hook.js +2 -2
  18. package/dist/application/spaces/spaces.hook.d.ts +2 -3
  19. package/dist/application/spaces/spaces.hook.d.ts.map +1 -1
  20. package/dist/application/spaces/spaces.hook.js +10 -3
  21. package/dist/auth/act-as.context.d.ts +15 -32
  22. package/dist/auth/act-as.context.d.ts.map +1 -1
  23. package/dist/auth/act-as.context.js +22 -66
  24. package/dist/auth/auth.hook.d.ts +1 -0
  25. package/dist/auth/auth.hook.d.ts.map +1 -1
  26. package/dist/auth/auth.hook.js +2 -22
  27. package/dist/auth/can.hook.d.ts +10 -38
  28. package/dist/auth/can.hook.d.ts.map +1 -1
  29. package/dist/auth/can.hook.js +35 -110
  30. package/dist/auth/index.d.ts +1 -0
  31. package/dist/auth/index.d.ts.map +1 -1
  32. package/dist/auth/self.hook.d.ts +2 -2
  33. package/dist/auth/self.hook.d.ts.map +1 -1
  34. package/dist/auth/self.hook.js +0 -7
  35. package/dist/auth/session-kernel.d.ts +2 -3
  36. package/dist/auth/session-kernel.d.ts.map +1 -1
  37. package/dist/auth/session-kernel.js +4 -13
  38. package/dist/components/astrale.d.ts +14 -0
  39. package/dist/components/astrale.d.ts.map +1 -0
  40. package/dist/components/astrale.js +12 -0
  41. package/dist/components/boundaries.d.ts +47 -0
  42. package/dist/components/boundaries.d.ts.map +1 -0
  43. package/dist/components/boundaries.js +55 -0
  44. package/dist/components/can.d.ts +11 -0
  45. package/dist/components/can.d.ts.map +1 -0
  46. package/dist/components/can.js +5 -0
  47. package/dist/components/index.d.ts +6 -0
  48. package/dist/components/index.d.ts.map +1 -0
  49. package/dist/components/index.js +3 -0
  50. package/dist/graph/call/call.hook.d.ts +8 -18
  51. package/dist/graph/call/call.hook.d.ts.map +1 -1
  52. package/dist/graph/call/call.hook.js +7 -13
  53. package/dist/graph/call/stream.hook.d.ts +12 -20
  54. package/dist/graph/call/stream.hook.d.ts.map +1 -1
  55. package/dist/graph/call/stream.hook.js +55 -111
  56. package/dist/graph/graph.context.d.ts +4 -3
  57. package/dist/graph/graph.context.d.ts.map +1 -1
  58. package/dist/graph/graph.context.js +2 -8
  59. package/dist/graph/guards.error.d.ts +7 -8
  60. package/dist/graph/guards.error.d.ts.map +1 -1
  61. package/dist/graph/guards.error.js +11 -7
  62. package/dist/graph/index.d.ts +8 -16
  63. package/dist/graph/index.d.ts.map +1 -1
  64. package/dist/graph/index.js +3 -7
  65. package/dist/graph/memory/read/envelope.d.ts +22 -54
  66. package/dist/graph/memory/read/envelope.d.ts.map +1 -1
  67. package/dist/graph/memory/read/envelope.js +26 -20
  68. package/dist/graph/memory/read/idle.d.ts +1 -15
  69. package/dist/graph/memory/read/idle.d.ts.map +1 -1
  70. package/dist/graph/memory/read/idle.js +4 -13
  71. package/dist/graph/query-definition.hook.d.ts +11 -0
  72. package/dist/graph/query-definition.hook.d.ts.map +1 -0
  73. package/dist/graph/query-definition.hook.js +205 -0
  74. package/dist/graph/resource.d.ts +34 -0
  75. package/dist/graph/resource.d.ts.map +1 -0
  76. package/dist/graph/resource.js +244 -0
  77. package/dist/graph/store.d.ts +25 -0
  78. package/dist/graph/store.d.ts.map +1 -0
  79. package/dist/graph/store.js +69 -0
  80. package/dist/host/actions.hook.d.ts +34 -0
  81. package/dist/host/actions.hook.d.ts.map +1 -0
  82. package/dist/host/actions.hook.js +125 -0
  83. package/dist/host/components.d.ts +15 -0
  84. package/dist/host/components.d.ts.map +1 -0
  85. package/dist/host/components.js +14 -0
  86. package/dist/host/index.d.ts +5 -0
  87. package/dist/host/index.d.ts.map +1 -0
  88. package/dist/host/index.js +3 -0
  89. package/dist/index.d.ts +26 -37
  90. package/dist/index.d.ts.map +1 -1
  91. package/dist/index.js +20 -31
  92. package/dist/intents/envelope.d.ts +7 -19
  93. package/dist/intents/envelope.d.ts.map +1 -1
  94. package/dist/intents/envelope.js +2 -3
  95. package/dist/intents/send-intent.hook.d.ts +5 -7
  96. package/dist/intents/send-intent.hook.d.ts.map +1 -1
  97. package/dist/intents/send-intent.hook.js +17 -75
  98. package/dist/navigation/adapters/adapter.d.ts +5 -0
  99. package/dist/navigation/adapters/adapter.d.ts.map +1 -1
  100. package/dist/navigation/adapters/memory.adapter.d.ts.map +1 -1
  101. package/dist/navigation/adapters/memory.adapter.js +4 -0
  102. package/dist/navigation/adapters/url.adapter.d.ts.map +1 -1
  103. package/dist/navigation/adapters/url.adapter.js +57 -10
  104. package/dist/navigation/codec.d.ts +60 -0
  105. package/dist/navigation/codec.d.ts.map +1 -0
  106. package/dist/navigation/codec.js +121 -0
  107. package/dist/navigation/history.d.ts +11 -9
  108. package/dist/navigation/history.d.ts.map +1 -1
  109. package/dist/navigation/history.js +6 -8
  110. package/dist/navigation/hooks/ancestors.hook.d.ts +5 -7
  111. package/dist/navigation/hooks/ancestors.hook.d.ts.map +1 -1
  112. package/dist/navigation/hooks/ancestors.hook.js +7 -51
  113. package/dist/navigation/hooks/location.hook.d.ts.map +1 -1
  114. package/dist/navigation/hooks/location.hook.js +4 -6
  115. package/dist/navigation/hooks/scope.hook.d.ts.map +1 -1
  116. package/dist/navigation/hooks/scope.hook.js +4 -6
  117. package/dist/navigation/index.d.ts +4 -2
  118. package/dist/navigation/index.d.ts.map +1 -1
  119. package/dist/navigation/index.js +2 -1
  120. package/dist/navigation/link.d.ts +12 -0
  121. package/dist/navigation/link.d.ts.map +1 -1
  122. package/dist/navigation/link.js +13 -2
  123. package/dist/navigation/location.d.ts +13 -40
  124. package/dist/navigation/location.d.ts.map +1 -1
  125. package/dist/navigation/location.js +14 -76
  126. package/dist/navigation/scope.context.d.ts +17 -26
  127. package/dist/navigation/scope.context.d.ts.map +1 -1
  128. package/dist/navigation/scope.context.js +140 -108
  129. package/dist/navigation/snapshot.d.ts +14 -19
  130. package/dist/navigation/snapshot.d.ts.map +1 -1
  131. package/dist/navigation/snapshot.js +48 -44
  132. package/dist/schema/action.hook.d.ts +44 -0
  133. package/dist/schema/action.hook.d.ts.map +1 -0
  134. package/dist/schema/action.hook.js +72 -0
  135. package/dist/schema/domain.hook.d.ts +12 -7
  136. package/dist/schema/domain.hook.d.ts.map +1 -1
  137. package/dist/schema/domain.hook.js +101 -4
  138. package/dist/schema/index.d.ts +9 -8
  139. package/dist/schema/index.d.ts.map +1 -1
  140. package/dist/schema/index.js +5 -7
  141. package/dist/schema/kernel.hook.d.ts +4 -9
  142. package/dist/schema/kernel.hook.d.ts.map +1 -1
  143. package/dist/schema/kernel.hook.js +4 -6
  144. package/dist/schema/mutation.hook.d.ts +9 -0
  145. package/dist/schema/mutation.hook.d.ts.map +1 -0
  146. package/dist/schema/mutation.hook.js +41 -0
  147. package/dist/schema/object.hook.d.ts +16 -0
  148. package/dist/schema/object.hook.d.ts.map +1 -0
  149. package/dist/schema/object.hook.js +46 -0
  150. package/dist/schema/relation.hook.d.ts +46 -0
  151. package/dist/schema/relation.hook.d.ts.map +1 -0
  152. package/dist/schema/relation.hook.js +136 -0
  153. package/dist/selection/live.d.ts +9 -17
  154. package/dist/selection/live.d.ts.map +1 -1
  155. package/dist/selection/live.js +65 -112
  156. package/dist/selection/scope.context.js +5 -4
  157. package/dist/session/boot/boot.d.ts +1 -13
  158. package/dist/session/boot/boot.d.ts.map +1 -1
  159. package/dist/session/boot/boot.js +9 -27
  160. package/dist/session/index.d.ts +1 -0
  161. package/dist/session/index.d.ts.map +1 -1
  162. package/dist/session/kernel-instance.hook.d.ts +1 -4
  163. package/dist/session/kernel-instance.hook.d.ts.map +1 -1
  164. package/dist/session/kernel-instance.hook.js +1 -5
  165. package/dist/session/provider.d.ts +9 -23
  166. package/dist/session/provider.d.ts.map +1 -1
  167. package/dist/session/provider.js +29 -75
  168. package/dist/session/session.context.d.ts +5 -0
  169. package/dist/session/session.context.d.ts.map +1 -1
  170. package/dist/window/adopt.d.ts +0 -1
  171. package/dist/window/adopt.d.ts.map +1 -1
  172. package/dist/window/hooks/target-node.hook.d.ts +10 -6
  173. package/dist/window/hooks/target-node.hook.d.ts.map +1 -1
  174. package/dist/window/hooks/target-node.hook.js +14 -72
  175. package/dist/window/hooks/views-for.hook.d.ts +4 -3
  176. package/dist/window/hooks/views-for.hook.d.ts.map +1 -1
  177. package/dist/window/hooks/views-for.hook.js +6 -22
  178. package/dist/window/hooks/windows.hook.d.ts.map +1 -1
  179. package/dist/window/hooks/windows.hook.js +3 -4
  180. package/dist/window/host.d.ts +9 -11
  181. package/dist/window/host.d.ts.map +1 -1
  182. package/dist/window/host.js +26 -62
  183. package/dist/window/hub.d.ts +2 -0
  184. package/dist/window/hub.d.ts.map +1 -1
  185. package/dist/window/hub.js +33 -0
  186. package/dist/window/index.d.ts +2 -2
  187. package/dist/window/index.d.ts.map +1 -1
  188. package/dist/window/index.js +2 -2
  189. package/dist/window/lifecycle/mount.d.ts +5 -44
  190. package/dist/window/lifecycle/mount.d.ts.map +1 -1
  191. package/dist/window/lifecycle/mount.js +14 -120
  192. package/dist/window/lifecycle/states.d.ts +0 -5
  193. package/dist/window/lifecycle/states.d.ts.map +1 -1
  194. package/package.json +20 -8
  195. package/src/application/apps/app-host.tsx +11 -15
  196. package/src/application/apps/apps.hook.ts +13 -6
  197. package/src/application/apps/domains.hook.ts +1 -1
  198. package/src/application/apps/open-app.hook.ts +3 -4
  199. package/src/application/index.ts +4 -6
  200. package/src/application/spaces/space.hook.ts +5 -6
  201. package/src/application/spaces/spaces.hook.ts +14 -9
  202. package/src/auth/act-as.context.tsx +37 -91
  203. package/src/auth/auth.hook.ts +2 -30
  204. package/src/auth/can.hook.ts +44 -135
  205. package/src/auth/index.ts +1 -0
  206. package/src/auth/self.hook.ts +2 -9
  207. package/src/auth/session-kernel.ts +6 -16
  208. package/src/components/astrale.tsx +40 -0
  209. package/src/components/boundaries.tsx +113 -0
  210. package/src/components/can.tsx +16 -0
  211. package/src/components/index.ts +13 -0
  212. package/src/graph/call/call.hook.ts +22 -27
  213. package/src/graph/call/stream.hook.ts +66 -143
  214. package/src/graph/graph.context.ts +6 -11
  215. package/src/graph/guards.error.ts +17 -55
  216. package/src/graph/index.ts +23 -17
  217. package/src/graph/memory/read/envelope.ts +40 -65
  218. package/src/graph/memory/read/idle.ts +5 -18
  219. package/src/graph/query-definition.hook.ts +270 -0
  220. package/src/graph/resource.ts +358 -0
  221. package/src/graph/store.ts +97 -0
  222. package/src/host/actions.hook.ts +165 -0
  223. package/src/host/components.tsx +29 -0
  224. package/src/host/index.ts +17 -0
  225. package/src/index.ts +131 -124
  226. package/src/intents/envelope.ts +7 -23
  227. package/src/intents/send-intent.hook.ts +24 -79
  228. package/src/navigation/adapters/adapter.ts +3 -0
  229. package/src/navigation/adapters/memory.adapter.ts +4 -0
  230. package/src/navigation/adapters/url.adapter.ts +48 -8
  231. package/src/navigation/codec.ts +190 -0
  232. package/src/navigation/history.ts +20 -11
  233. package/src/navigation/hooks/ancestors.hook.ts +10 -60
  234. package/src/navigation/hooks/location.hook.ts +4 -6
  235. package/src/navigation/hooks/scope.hook.ts +4 -6
  236. package/src/navigation/index.ts +18 -2
  237. package/src/navigation/link.tsx +27 -2
  238. package/src/navigation/location.ts +26 -93
  239. package/src/navigation/scope.context.tsx +151 -136
  240. package/src/navigation/snapshot.ts +69 -50
  241. package/src/schema/action.hook.ts +146 -0
  242. package/src/schema/domain.hook.ts +127 -11
  243. package/src/schema/index.ts +9 -30
  244. package/src/schema/kernel.hook.ts +6 -13
  245. package/src/schema/mutation.hook.ts +63 -0
  246. package/src/schema/object.hook.ts +85 -0
  247. package/src/schema/relation.hook.ts +253 -0
  248. package/src/selection/live.ts +75 -125
  249. package/src/selection/scope.context.tsx +4 -4
  250. package/src/session/boot/boot.ts +8 -33
  251. package/src/session/index.ts +1 -0
  252. package/src/session/kernel-instance.hook.ts +2 -11
  253. package/src/session/provider.tsx +34 -103
  254. package/src/session/session.context.ts +6 -0
  255. package/src/window/adopt.ts +0 -1
  256. package/src/window/hooks/target-node.hook.ts +20 -85
  257. package/src/window/hooks/views-for.hook.ts +12 -25
  258. package/src/window/hooks/windows.hook.ts +3 -4
  259. package/src/window/host.tsx +35 -77
  260. package/src/window/hub.ts +33 -0
  261. package/src/window/index.ts +3 -3
  262. package/src/window/lifecycle/mount.ts +15 -160
  263. package/src/window/lifecycle/states.ts +1 -5
  264. package/dist/application/roles.hook.d.ts +0 -7
  265. package/dist/application/roles.hook.d.ts.map +0 -1
  266. package/dist/application/roles.hook.js +0 -23
  267. package/dist/graph/memory/base.d.ts +0 -21
  268. package/dist/graph/memory/base.d.ts.map +0 -1
  269. package/dist/graph/memory/base.js +0 -33
  270. package/dist/graph/memory/read/read.d.ts +0 -9
  271. package/dist/graph/memory/read/read.d.ts.map +0 -1
  272. package/dist/graph/memory/read/read.js +0 -87
  273. package/dist/graph/memory/scope.d.ts +0 -7
  274. package/dist/graph/memory/scope.d.ts.map +0 -1
  275. package/dist/graph/memory/scope.js +0 -25
  276. package/dist/graph/mutate/move.hook.d.ts +0 -7
  277. package/dist/graph/mutate/move.hook.d.ts.map +0 -1
  278. package/dist/graph/mutate/move.hook.js +0 -49
  279. package/dist/graph/mutate/mutate.hook.d.ts +0 -17
  280. package/dist/graph/mutate/mutate.hook.d.ts.map +0 -1
  281. package/dist/graph/mutate/mutate.hook.js +0 -45
  282. package/dist/graph/query/children.hook.d.ts +0 -29
  283. package/dist/graph/query/children.hook.d.ts.map +0 -1
  284. package/dist/graph/query/children.hook.js +0 -64
  285. package/dist/graph/query/graph.hook.d.ts +0 -9
  286. package/dist/graph/query/graph.hook.d.ts.map +0 -1
  287. package/dist/graph/query/graph.hook.js +0 -5
  288. package/dist/graph/query/neighbors.hook.d.ts +0 -7
  289. package/dist/graph/query/neighbors.hook.d.ts.map +0 -1
  290. package/dist/graph/query/neighbors.hook.js +0 -104
  291. package/dist/graph/query/node.hook.d.ts +0 -14
  292. package/dist/graph/query/node.hook.d.ts.map +0 -1
  293. package/dist/graph/query/node.hook.js +0 -43
  294. package/dist/graph/query/query.hook.d.ts +0 -14
  295. package/dist/graph/query/query.hook.d.ts.map +0 -1
  296. package/dist/graph/query/query.hook.js +0 -23
  297. package/dist/schema/bind-read.d.ts +0 -37
  298. package/dist/schema/bind-read.d.ts.map +0 -1
  299. package/dist/schema/bind-read.js +0 -205
  300. package/dist/schema/binding.d.ts +0 -21
  301. package/dist/schema/binding.d.ts.map +0 -1
  302. package/dist/schema/binding.js +0 -99
  303. package/dist/schema/function.hook.d.ts +0 -9
  304. package/dist/schema/function.hook.d.ts.map +0 -1
  305. package/dist/schema/function.hook.js +0 -40
  306. package/dist/schema/method.hook.d.ts +0 -14
  307. package/dist/schema/method.hook.d.ts.map +0 -1
  308. package/dist/schema/method.hook.js +0 -49
  309. package/dist/schema/tag.d.ts +0 -11
  310. package/dist/schema/tag.d.ts.map +0 -1
  311. package/dist/schema/tag.js +0 -11
  312. package/dist/schema/types.d.ts +0 -73
  313. package/dist/schema/types.d.ts.map +0 -1
  314. package/dist/schema/types.js +0 -1
  315. package/dist/schema/write.d.ts +0 -16
  316. package/dist/schema/write.d.ts.map +0 -1
  317. package/dist/schema/write.js +0 -56
  318. package/src/application/roles.hook.ts +0 -41
  319. package/src/graph/memory/base.ts +0 -50
  320. package/src/graph/memory/read/read.ts +0 -103
  321. package/src/graph/memory/scope.ts +0 -29
  322. package/src/graph/mutate/move.hook.ts +0 -70
  323. package/src/graph/mutate/mutate.hook.ts +0 -69
  324. package/src/graph/query/children.hook.ts +0 -136
  325. package/src/graph/query/graph.hook.ts +0 -13
  326. package/src/graph/query/neighbors.hook.ts +0 -159
  327. package/src/graph/query/node.hook.ts +0 -83
  328. package/src/graph/query/query.hook.ts +0 -42
  329. package/src/schema/bind-read.ts +0 -319
  330. package/src/schema/binding.ts +0 -146
  331. package/src/schema/function.hook.ts +0 -68
  332. package/src/schema/method.hook.ts +0 -103
  333. package/src/schema/tag.ts +0 -19
  334. package/src/schema/types.ts +0 -150
  335. package/src/schema/write.ts +0 -96
@@ -1,7 +1,7 @@
1
- import type { NodeRefInput } from '@astrale-os/kernel-client'
2
- import type { ApplicationNode, SpaceNode } from '@astrale-os/shell'
1
+ import type { PathLike } from '@astrale-os/sdk/graph/path'
2
+ import type { ApplicationNode, NodeTarget, SpaceNode } from '@astrale-os/shell'
3
3
 
4
- import { normalizeRef } from '@astrale-os/kernel-client'
4
+ import { Path } from '@astrale-os/sdk/graph/path'
5
5
  /**
6
6
  * useApps(space?) (API §12.2) — the apps installed in a space (`installed_in`
7
7
  * in-edges). No arg targets the CURRENT space (shared store, so a switch anywhere
@@ -26,7 +26,7 @@ export interface AppsResult extends ReadState {
26
26
  readonly apps: readonly ApplicationNode[]
27
27
  }
28
28
 
29
- export function useApps(space?: SpaceNode | NodeRefInput | null): AppsResult {
29
+ export function useApps(space?: SpaceNode | NodeTarget | null): AppsResult {
30
30
  const shell = useShell()
31
31
  const available = isOsPlaneAvailable(shell)
32
32
 
@@ -76,6 +76,13 @@ function hasId(x: unknown): x is { readonly id: string } {
76
76
  }
77
77
 
78
78
  /** An `@id` ref for a bound node, else the normalized ref of a raw subject. */
79
- export function toRef(x: NodeRefInput | { readonly id: string }): string {
80
- return hasId(x) ? `@${x.id}` : normalizeRef(x)
79
+ export function toRef(x: NodeTarget | { readonly id: string }): NodeTarget {
80
+ return hasId(x) ? x.id : x
81
+ }
82
+
83
+ /** Stable dependency identity for one Shell node target. */
84
+ export function targetKey(x: NodeTarget | { readonly id: string }): string {
85
+ if (hasId(x)) return `id:${x.id}`
86
+ if (typeof x === 'string') return `text:${x}`
87
+ return `path:${Path.from(x as PathLike).raw}`
81
88
  }
@@ -14,7 +14,7 @@ export interface DomainsResult extends ReadState {
14
14
  readonly domains: readonly DomainSearchResult[]
15
15
  }
16
16
 
17
- export function useDomains(): DomainsResult {
17
+ export function useInstalledDomains(): DomainsResult {
18
18
  const shell = useShell()
19
19
  const available = isOsPlaneAvailable(shell)
20
20
  const result = useAsyncResource<readonly DomainSearchResult[]>(
@@ -3,8 +3,7 @@
3
3
  * app-open protocol lives in the shell package). Resolves to the session; disposal
4
4
  * is the caller's (AppHost disposes it with the window).
5
5
  */
6
- import type { NodeRefInput } from '@astrale-os/kernel-client'
7
- import type { ApplicationNode, AppSession } from '@astrale-os/shell'
6
+ import type { ApplicationNode, AppSession, NodeTarget } from '@astrale-os/shell'
8
7
 
9
8
  import type { Action } from '../../graph/action.js'
10
9
 
@@ -12,7 +11,7 @@ import { useAction } from '../../graph/action.js'
12
11
  import { useShell } from '../../session/shell.hook.js'
13
12
  import { toRef } from './apps.hook.js'
14
13
 
15
- export function useOpenApp(): Action<[ApplicationNode | NodeRefInput], AppSession> {
14
+ export function useOpenApp(): Action<[ApplicationNode | NodeTarget], AppSession> {
16
15
  const shell = useShell()
17
- return useAction((app: ApplicationNode | NodeRefInput) => shell.apps.open(toRef(app)))
16
+ return useAction((app: ApplicationNode | NodeTarget) => shell.apps.open(toRef(app)))
18
17
  }
@@ -1,6 +1,6 @@
1
1
  // application — API §12.2. The OS-plane hooks over the shell package's
2
2
  // `shell.user/spaces/apps` namespaces + the window module: useUser, useSpaces,
3
- // useCurrentSpace, useSpace, useApps, useDomains, useRoles, useOpenApp,
3
+ // useCurrentSpace, useSpace, useApps, useInstalledDomains, useOpenApp,
4
4
  // AppHost, AppLogo.
5
5
  export { useUser } from './user/user.hook.js'
6
6
  export { useSpaces } from './spaces/spaces.hook.js'
@@ -11,22 +11,20 @@ export { useSpace } from './spaces/space.hook.js'
11
11
  export type { SpaceResult } from './spaces/space.hook.js'
12
12
  export { useApps } from './apps/apps.hook.js'
13
13
  export type { AppsResult } from './apps/apps.hook.js'
14
- export { useDomains } from './apps/domains.hook.js'
14
+ export { useInstalledDomains } from './apps/domains.hook.js'
15
15
  export type { DomainsResult } from './apps/domains.hook.js'
16
16
  export { useOpenApp } from './apps/open-app.hook.js'
17
17
  export { AppHost } from './apps/app-host.js'
18
18
  export type { AppHostFallbackState, AppHostProps } from './apps/app-host.js'
19
19
  export { AppLogo } from './apps/app-logo.js'
20
20
  export type { AppLogoProps } from './apps/app-logo.js'
21
- export { useRoles } from './roles.hook.js'
22
- export type { RolesResult } from './roles.hook.js'
23
-
24
21
  // The OS node/session types (from the shell package, single import surface).
25
22
  export type {
26
23
  ApplicationNode,
27
24
  AppSession,
28
25
  DomainSearchResult,
29
- RoleNode,
26
+ NodeTarget,
27
+ ResolvedView,
30
28
  SpaceNode,
31
29
  UserNode,
32
30
  } from '@astrale-os/shell'
@@ -1,7 +1,5 @@
1
- import type { NodeRefInput } from '@astrale-os/kernel-client'
2
- import type { SpaceNode } from '@astrale-os/shell'
1
+ import type { NodeTarget, SpaceNode } from '@astrale-os/shell'
3
2
 
4
- import { normalizeRef } from '@astrale-os/kernel-client'
5
3
  /**
6
4
  * useSpace(ref) (API §12.2) — a single space by ref; `null`/`undefined` (or an
7
5
  * unavailable OS plane) is idle (§1.3). One-shot today (§12 flag).
@@ -13,17 +11,18 @@ import type { CurrentSpaceResult } from './current-space.hook.js'
13
11
  import { useAsyncResource } from '../../graph/async.js'
14
12
  import { isIdleInput } from '../../graph/memory/read/idle.js'
15
13
  import { useShell } from '../../session/shell.hook.js'
14
+ import { targetKey } from '../apps/apps.hook.js'
16
15
  import { isOsPlaneAvailable } from '../user/user.store.js'
17
16
 
18
17
  export type SpaceResult = CurrentSpaceResult
19
18
 
20
- export function useSpace(ref: NodeRefInput | null | undefined): SpaceResult {
19
+ export function useSpace(ref: NodeTarget | null | undefined): SpaceResult {
21
20
  const shell = useShell()
22
21
  const idle = isIdleInput(ref) || !isOsPlaneAvailable(shell)
23
22
  // The inline guard (not the stored `idle`) narrows `ref` to non-null below.
24
- const key = idle ? null : normalizeRef(ref as NodeRefInput)
23
+ const key = idle ? null : targetKey(ref as NodeTarget)
25
24
  const res = useAsyncResource<SpaceNode | null>(
26
- idle ? null : () => shell.spaces.get(ref as NodeRefInput),
25
+ idle ? null : () => shell.spaces.get(ref as NodeTarget),
27
26
  null,
28
27
  [shell, key],
29
28
  )
@@ -1,7 +1,7 @@
1
- import type { NodeRefInput } from '@astrale-os/kernel-client'
2
- import type { SpaceNode } from '@astrale-os/shell'
1
+ import type { PathLike } from '@astrale-os/sdk/graph/path'
2
+ import type { NodeTarget, SpaceNode } from '@astrale-os/shell'
3
3
 
4
- import { normalizeRef } from '@astrale-os/kernel-client'
4
+ import { Path } from '@astrale-os/sdk/graph/path'
5
5
  /**
6
6
  * useSpaces (API §12.2) — the spaces list, the selected space, and a `switch`
7
7
  * Action that repoints the `selected_space` edge. Reads the SAME per-Shell
@@ -28,7 +28,7 @@ export interface SpacesResult extends ReadState {
28
28
  /** The `selected_space` target — optimistically ahead during a `switch`. */
29
29
  readonly selected: SpaceNode | null
30
30
  /** `user::switchSpace` with a manual optimistic overlay (§1.6). */
31
- readonly switch: Action<[NodeRefInput], void>
31
+ readonly switch: Action<[NodeTarget], void>
32
32
  }
33
33
 
34
34
  export function useSpaces(): SpacesResult {
@@ -52,7 +52,7 @@ export function useSpaces(): SpacesResult {
52
52
 
53
53
  const spaces = spacesRes.data
54
54
 
55
- const switchAction = useAction(async (ref: NodeRefInput): Promise<void> => {
55
+ const switchAction = useAction(async (ref: NodeTarget): Promise<void> => {
56
56
  // Optimistic override on the SHARED store, so useCurrentSpace / useApps ahead
57
57
  // of the round-trip too (§12.2). Only overlay a known target (a path ref that
58
58
  // matches nothing in the list simply skips the preview).
@@ -94,7 +94,7 @@ export function useSpaces(): SpacesResult {
94
94
  }
95
95
 
96
96
  /** The space in `spaces` denoted by `ref`, or `null` (path refs don't match by id). */
97
- function findSpace(spaces: readonly SpaceNode[], ref: NodeRefInput): SpaceNode | null {
97
+ function findSpace(spaces: readonly SpaceNode[], ref: NodeTarget): SpaceNode | null {
98
98
  const id = refIdOf(ref)
99
99
  if (id === null) return null
100
100
  return spaces.find((s) => s.id === id) ?? null
@@ -106,8 +106,13 @@ function hasId(x: unknown): x is { readonly id: string } {
106
106
  }
107
107
 
108
108
  /** The graph id a subject denotes, or `null` when it is a path (no id to match). */
109
- function refIdOf(x: NodeRefInput | { readonly id: string }): string | null {
109
+ function refIdOf(x: NodeTarget | { readonly id: string }): string | null {
110
110
  if (hasId(x)) return x.id
111
- const raw = normalizeRef(x)
112
- return raw.startsWith('@') ? raw.slice(1) : null
111
+ if (typeof x === 'string' && !x.startsWith('@') && !x.startsWith('/')) return x
112
+ try {
113
+ const path = Path.from(x as PathLike)
114
+ return path.ast.anchor.kind === 'id' && path.ast.steps.length === 0 ? path.ast.anchor.id : null
115
+ } catch {
116
+ return null
117
+ }
113
118
  }
@@ -1,124 +1,70 @@
1
- import type { CredentialInput, FnMap } from '@astrale-os/kernel-client'
2
- import type { BoundClientSessionView } from '@astrale-os/kernel-client/session'
1
+ import type { Identity } from '@astrale-os/kernel-client/auth'
2
+ import type { KernelClient } from '@astrale-os/shell'
3
3
  import type { ReactElement, ReactNode } from 'react'
4
4
 
5
- /**
6
- * The acting-principal binding (API §4). `IdentityContext` seats the effective
7
- * principal a subtree dispatches as — its bound kernel view + whoami + memory
8
- * scope; `useIdentityBinding` resolves it (an `<ActAs>` override, else the root
9
- * off ShellContext). `<ActAs>` rebinds a subtree to another principal with a
10
- * DISTINCT memory scope so results never leak across principals (§5.4).
11
- */
12
5
  import { createContext, useContext, useEffect, useMemo, useState } from 'react'
13
6
 
14
- import type { SelfNode } from '../session/session.context.js'
15
-
16
7
  import { ShellContext } from '../session/session.context.js'
17
8
 
18
- /** A bound session view — the kernel surface `session.as(cred)` yields. */
19
- export type SessionView = BoundClientSessionView<FnMap>
20
-
21
- /** A whoami-shaped identity/graph node (kernel-client does not yet re-export `Node` — G8). */
22
- export type NodeValue = SelfNode
23
-
24
- /** The root scope key — the memory's own default scope (`createMemory` default). */
25
- export const ROOT_SCOPE = 'default'
9
+ export type NodeValue = Identity
10
+ export type SessionView = KernelClient
26
11
 
27
- /**
28
- * The principal a subtree acts as (API §4). `scope` is the memory isolation key
29
- * (§5.4): the graph plane scopes its memory by `memory.forScope(scope)` so an
30
- * <ActAs> subtree never shares cached results with another principal.
31
- */
32
12
  export interface IdentityBinding {
33
- readonly kernel: SessionView
34
- readonly self: SelfNode
35
- readonly scope: string
13
+ readonly kernel: KernelClient
14
+ readonly self: Identity
36
15
  }
16
+
37
17
  export const IdentityContext = createContext<IdentityBinding | null>(null)
38
18
  IdentityContext.displayName = 'AstraleIdentityContext'
39
19
 
40
- /**
41
- * The principal this subtree dispatches as. An <ActAs> value wins; otherwise the
42
- * root binding off ShellContext. Throws outside a provider, or when the bound
43
- * kernel resolved no identity (a bare prebuilt Shell with no auth surface).
44
- */
45
20
  export function useIdentityBinding(): IdentityBinding {
46
21
  const override = useContext(IdentityContext)
47
22
  if (override !== null) return override
48
-
49
23
  const runtime = useContext(ShellContext)
50
- if (runtime === null) {
51
- throw new Error('identity hooks must be used within a <ShellProvider>')
52
- }
53
- if (runtime.self === null) {
54
- throw new Error(
55
- 'identity hooks require an identity: this shell exposed no auth surface, so whoami ' +
56
- 'resolved nothing at boot',
57
- )
58
- }
59
- // The root binding reads stable fields (self, shell.kernel), so a fresh object
60
- // per render is inert — consumers key off `kernel`/`self`, both stable.
61
- return { kernel: runtime.shell.kernel, self: runtime.self, scope: ROOT_SCOPE }
24
+ if (runtime === null) throw new Error('identity hooks must be used within a <ShellProvider>')
25
+ if (runtime.self === null) throw new Error('the active Shell has no authenticated identity')
26
+ return { kernel: runtime.shell.kernel, self: runtime.self }
62
27
  }
63
28
 
64
29
  export interface ActAsProps {
65
- /** The principal to act as. A thunk is resolved by the kernel per dispatch. */
66
- credential: CredentialInput | (() => CredentialInput)
67
- children: ReactNode
30
+ /**
31
+ * A separately authenticated Kernel capability. Raw credentials are deliberately not accepted;
32
+ * construct the delegated Client Session at the trust boundary that owns credential resolution.
33
+ */
34
+ readonly client: KernelClient
35
+ readonly fallback?: ReactNode
36
+ readonly children: ReactNode
68
37
  }
69
38
 
70
- /**
71
- * A subtree that dispatches as another principal: rebinds the kernel (session.as),
72
- * resolves whoami, and provides a fresh identity binding with a DISTINCT memory
73
- * scope (`as:<id>`). Nestable — it rebinds from the current effective principal. A
74
- * brief nested boot holds the subtree (renders null) until whoami resolves.
75
- */
76
- export function ActAs({ credential, children }: ActAsProps): ReactElement | null {
77
- const parent = useIdentityBinding()
78
- // Key the rebind on a STABLE credential identity (like `configIdentity` does),
79
- // so an inline object credential (`credential={{ … }}`) does not re-mint the
80
- // session view — and re-run whoami, unmounting the subtree — every parent
81
- // render. A thunk still keys by reference: pass a stable thunk to avoid churn.
82
- const credKey = credentialIdentity(credential)
83
- // eslint-disable-next-line react-hooks/exhaustive-deps
84
- const kernel = useMemo(() => parent.kernel.as(credential), [parent.kernel, credKey])
39
+ /** Bind a subtree to an explicitly supplied authenticated Kernel capability. */
40
+ export function ActAs({ client, fallback, children }: ActAsProps): ReactElement | null {
41
+ const [state, setState] = useState<
42
+ | { readonly status: 'pending' }
43
+ | { readonly status: 'ready'; readonly self: Identity }
44
+ | { readonly status: 'failed'; readonly error: unknown }
45
+ >({ status: 'pending' })
85
46
 
86
- const [self, setSelf] = useState<SelfNode | null>(null)
87
47
  useEffect(() => {
88
- let alive = true
89
- setSelf(null)
90
- void kernel.auth.whoami().then(
91
- (node) => {
92
- if (alive) setSelf(node)
48
+ let active = true
49
+ setState({ status: 'pending' })
50
+ void client.auth.whoami().then(
51
+ (self) => {
52
+ if (active) setState({ status: 'ready', self })
93
53
  },
94
- () => {
95
- /* held (null) subtree on resolve failure — transport errors surface via the provider */
54
+ (error: unknown) => {
55
+ if (active) setState({ status: 'failed', error })
96
56
  },
97
57
  )
98
58
  return () => {
99
- alive = false
59
+ active = false
100
60
  }
101
- }, [kernel])
61
+ }, [client])
102
62
 
103
63
  const value = useMemo<IdentityBinding | null>(
104
- () => (self === null ? null : { kernel, self, scope: `as:${self.id}` }),
105
- [kernel, self],
64
+ () => (state.status === 'ready' ? { kernel: client, self: state.self } : null),
65
+ [client, state],
106
66
  )
107
-
108
- if (value === null) return null
67
+ if (state.status === 'failed') throw state.error
68
+ if (value === null) return fallback === undefined ? null : <>{fallback}</>
109
69
  return <IdentityContext.Provider value={value}>{children}</IdentityContext.Provider>
110
70
  }
111
-
112
- /**
113
- * A stable identity for a credential: the thunk by reference, a string as itself,
114
- * and an object by a serialized form — so an equal inline object does not churn
115
- * the memo (worst case a serialize failure falls back to reference identity).
116
- */
117
- function credentialIdentity(credential: CredentialInput | (() => CredentialInput)): unknown {
118
- if (typeof credential === 'function' || typeof credential === 'string') return credential
119
- try {
120
- return `cred:${JSON.stringify(credential)}`
121
- } catch {
122
- return credential
123
- }
124
- }
@@ -1,36 +1,8 @@
1
1
  import type { AuthApi } from '@astrale-os/kernel-client/auth'
2
2
 
3
- /**
4
- * useAuth (API §4) — the imperative AuthApi of the effective principal
5
- * (whoami/credential/mint/delegate/check/grant/revoke/bind/unbind). Grant and
6
- * revoke additionally nudge the principal's useCan ledger on success, delivering
7
- * the Tier-0 local re-check (SPEC §11.3). DEVIATION: API §4 describes a pure
8
- * passthrough; the wrap is the only way to surface a local grant/revoke today,
9
- * since permissions dispatch as identity methods rather than graph patches.
10
- * Cross-client liveness still awaits the watch tiers (G7).
11
- */
12
- import { useMemo } from 'react'
13
-
14
- import type { SessionView } from './act-as.context.js'
15
-
16
3
  import { useIdentityBinding } from './act-as.context.js'
17
- import { ledgerFor } from './can.hook.js'
18
4
 
5
+ /** The exact Client Auth capability for the effective subtree principal. */
19
6
  export function useAuth(): AuthApi {
20
- const { kernel } = useIdentityBinding()
21
- return useMemo(() => withLedgerNudge(kernel), [kernel])
22
- }
23
-
24
- /** Wrap grant/revoke so a successful local change re-checks the principal's cells. */
25
- function withLedgerNudge(kernel: SessionView): AuthApi {
26
- const auth = kernel.auth
27
- const ledger = ledgerFor(kernel)
28
- const invalidate = (): void => ledger.invalidateAll()
29
-
30
- const grant = ((arg: never) =>
31
- Promise.resolve(auth.grant(arg)).then(invalidate)) as AuthApi['grant']
32
- const revoke = ((arg: never) =>
33
- Promise.resolve(auth.revoke(arg)).then(invalidate)) as AuthApi['revoke']
34
-
35
- return { ...auth, grant, revoke }
7
+ return useIdentityBinding().kernel.auth
36
8
  }
@@ -1,149 +1,58 @@
1
- import type { AuthApi, Perms } from '@astrale-os/kernel-client/auth'
2
- import type { PathLike, Ref } from '@astrale-os/kernel-client/graph'
1
+ import type { NodeId } from '@astrale-os/sdk/graph/node'
2
+ import type { PathLike } from '@astrale-os/sdk/graph/path'
3
+ import type { schema } from '@astrale-os/sdk/schema'
3
4
 
4
- import { rawOf } from '@astrale-os/kernel-client/graph'
5
- /**
6
- * useCan (API §4) — deduped standing-grant permission checks. `auth.check`-backed:
7
- * `undefined` while the first check is in flight (or `on` is idle), then a boolean.
8
- * Deduped per (principal, perms, nodeId) across the whole tree via the principal's
9
- * check ledger (folded in here as the dedup substrate). Standing-grant semantics:
10
- * the dispatched call remains the gatekeeper — this is a UI affordance, not the
11
- * enforcement point (SPEC §6.2). A local grant/revoke invalidates the ledger.
12
- */
13
- import { useCallback, useMemo, useSyncExternalStore } from 'react'
5
+ import { Path } from '@astrale-os/sdk/graph/path'
6
+ import { useEffect, useState } from 'react'
14
7
 
15
- import type { NodeValue, SessionView } from './act-as.context.js'
16
-
17
- import { isIdleInput } from '../graph/memory/read/idle.js'
18
8
  import { useIdentityBinding } from './act-as.context.js'
19
9
 
20
- const NOOP_UNSUB = (): void => undefined
21
-
22
- /** A node value carries the id/class/path triple (mirrors the memory's `isNodeValue`). */
23
- export function isNodeValue(x: unknown): x is NodeValue {
24
- return typeof x === 'object' && x !== null && 'id' in x && 'class' in x && 'path' in x
25
- }
26
-
27
- /** Normalize a `useCan` subject to a dispatchable `Ref` plus a stable dedup key. */
28
- export function toRef(on: NodeValue | PathLike): { ref: Ref; key: string } {
29
- if (isNodeValue(on)) return { ref: on.path as Ref, key: `@${on.id}` }
30
- return { ref: on, key: rawOf(on) }
31
- }
32
-
33
- // ── check ledger (the dedup substrate) ───────────────────────────────────────
10
+ export type PolicyObject = NodeId | { readonly id: NodeId }
34
11
 
35
- /** One deduped check — its last-known value plus the subscribers watching it. */
36
- class CheckCell {
37
- value: boolean | undefined = undefined
38
- private inFlight = false
39
- private readonly listeners = new Set<() => void>()
40
-
41
- constructor(
42
- private readonly auth: AuthApi,
43
- private readonly perms: Perms,
44
- private readonly on: Ref,
45
- ) {}
46
-
47
- subscribe = (onChange: () => void): (() => void) => {
48
- this.listeners.add(onChange)
49
- this.ensure()
50
- return () => this.listeners.delete(onChange)
51
- }
52
-
53
- getSnapshot = (): boolean | undefined => this.value
54
-
55
- /** Run the check once when the value is unknown and nothing is in flight. */
56
- ensure(): void {
57
- if (this.value !== undefined || this.inFlight) return
58
- this.run()
59
- }
60
-
61
- /** Force a re-check (local grant/revoke on this principal). */
62
- invalidate(): void {
63
- if (this.listeners.size === 0) {
64
- this.value = undefined // recompute lazily on the next subscribe
12
+ /**
13
+ * Evaluate one declared Kernel policy for one exact graph object. This is a UI affordance; the
14
+ * invoked callable remains the authorization enforcement point.
15
+ */
16
+ export function useCan(
17
+ policy: PathLike | schema.PolicyRef | null | undefined,
18
+ object: PolicyObject | null | undefined,
19
+ ): boolean | undefined {
20
+ const { kernel } = useIdentityBinding()
21
+ const objectId = objectIdOf(object)
22
+ const policyTarget = policyPath(policy)
23
+ const [decision, setDecision] = useState<boolean | undefined>(undefined)
24
+
25
+ useEffect(() => {
26
+ if (policyTarget === null || objectId === null) {
27
+ setDecision(undefined)
65
28
  return
66
29
  }
67
- this.run()
68
- }
69
-
70
- private run(): void {
71
- this.inFlight = true
72
- void this.auth
73
- .check({ on: this.on, perms: this.perms })
74
- .then(
75
- (ok) => {
76
- this.value = ok
77
- },
78
- () => {
79
- // A failed check leaves the value unknown (undefined) — never a false grant.
80
- this.value = undefined
81
- },
82
- )
83
- .finally(() => {
84
- this.inFlight = false
85
- for (const l of this.listeners) l()
86
- })
87
- }
88
- }
89
-
90
- /** Per-principal cell registry — dedup across the whole tree for one kernel handle. */
91
- export class CheckLedger {
92
- private readonly cells = new Map<string, CheckCell>()
93
-
94
- constructor(private readonly auth: AuthApi) {}
95
-
96
- cell(key: string, perms: Perms, on: Ref): CheckCell {
97
- let cell = this.cells.get(key)
98
- if (cell === undefined) {
99
- cell = new CheckCell(this.auth, perms, on)
100
- this.cells.set(key, cell)
30
+ let active = true
31
+ setDecision(undefined)
32
+ void kernel.auth.can({ policy: policyTarget, object: objectId }).then(
33
+ (allowed) => {
34
+ if (active) setDecision(allowed)
35
+ },
36
+ () => {
37
+ if (active) setDecision(undefined)
38
+ },
39
+ )
40
+ return () => {
41
+ active = false
101
42
  }
102
- return cell
103
- }
43
+ }, [kernel, policyTarget, objectId])
104
44
 
105
- /** Re-check every observed cell — conservative Tier-0 sweep after a local grant/revoke. */
106
- invalidateAll(): void {
107
- for (const cell of this.cells.values()) cell.invalidate()
108
- }
45
+ return decision
109
46
  }
110
47
 
111
- // One ledger per bound kernel object → per principal. `session.as(cred)` mints a
112
- // fresh view per ActAs, so acted-as principals never share a ledger with the root.
113
- const ledgers = new WeakMap<SessionView, CheckLedger>()
114
-
115
- export function ledgerFor(kernel: SessionView): CheckLedger {
116
- let ledger = ledgers.get(kernel)
117
- if (ledger === undefined) {
118
- ledger = new CheckLedger(kernel.auth)
119
- ledgers.set(kernel, ledger)
120
- }
121
- return ledger
48
+ function policyPath(policy: PathLike | schema.PolicyRef | null | undefined) {
49
+ if (policy === null || policy === undefined) return null
50
+ return policy instanceof Path || typeof policy === 'string'
51
+ ? Path.from(policy).raw
52
+ : Path.project(policy).raw
122
53
  }
123
54
 
124
- // ── useCan ────────────────────────────────────────────────────────────────────
125
-
126
- export function useCan(
127
- perms: Perms,
128
- on: NodeValue | PathLike | null | undefined,
129
- ): boolean | undefined {
130
- const binding = useIdentityBinding()
131
- const ref = isIdleInput(on) ? null : toRef(on)
132
-
133
- // The shared cell for (principal, perms, nodeId): identical to every other
134
- // useCan reading the same triple, so one check serves the whole tree.
135
- const cell = useMemo(
136
- () =>
137
- ref === null ? null : ledgerFor(binding.kernel).cell(`${perms}\0${ref.key}`, perms, ref.ref),
138
- // ref is rebuilt per render; its `key` string is the stable identity.
139
- [binding.kernel, perms, ref?.key],
140
- )
141
-
142
- const subscribe = useCallback(
143
- (onChange: () => void) => (cell === null ? NOOP_UNSUB : cell.subscribe(onChange)),
144
- [cell],
145
- )
146
- const getSnapshot = useCallback((): boolean | undefined => cell?.getSnapshot(), [cell])
147
-
148
- return useSyncExternalStore(subscribe, getSnapshot, getSnapshot)
55
+ function objectIdOf(value: PolicyObject | null | undefined): NodeId | null {
56
+ if (value === null || value === undefined) return null
57
+ return typeof value === 'object' ? value.id : value
149
58
  }
package/src/auth/index.ts CHANGED
@@ -3,4 +3,5 @@ export { ActAs } from './act-as.context.js'
3
3
  export type { ActAsProps } from './act-as.context.js'
4
4
  export { useAuth } from './auth.hook.js'
5
5
  export { useCan } from './can.hook.js'
6
+ export type { PolicyObject } from './can.hook.js'
6
7
  export { useSelf } from './self.hook.js'
@@ -1,14 +1,7 @@
1
- import type { NodeValue } from './act-as.context.js'
1
+ import type { Identity } from '@astrale-os/kernel-client/auth'
2
2
 
3
- /**
4
- * useSelf (API §4) — the caller's identity node, resolved at boot and read
5
- * synchronously (never suspends). An <ActAs> subtree returns the acted-as
6
- * identity. FLAG: today this is the boot-resolved whoami snapshot; it becomes a
7
- * live memory shape once the graph plane subscribes the self node — no signature
8
- * change.
9
- */
10
3
  import { useIdentityBinding } from './act-as.context.js'
11
4
 
12
- export function useSelf(): NodeValue {
5
+ export function useSelf(): Identity {
13
6
  return useIdentityBinding().self
14
7
  }
@@ -1,24 +1,14 @@
1
- /**
2
- * useSessionKernel (API §4) — the dispatch-floor resolver. Inside an `<ActAs>` it
3
- * is the acted-as principal's bound session view; otherwise the root
4
- * `shell.kernel`. Every dispatch floor (schema bindings, useCall/useStream, useMove,
5
- * typed method dispatch) routes through this so a call runs as the subtree's
6
- * principal — not the root — and its scoped memory.
7
- */
8
- import { useContext } from 'react'
1
+ import type { KernelClient } from '@astrale-os/shell'
9
2
 
10
- import type { SessionView } from './act-as.context.js'
3
+ import { useContext } from 'react'
11
4
 
12
5
  import { ShellContext } from '../session/session.context.js'
13
6
  import { IdentityContext } from './act-as.context.js'
14
7
 
15
- /** The EFFECTIVE dispatch kernel for this subtree. Throws outside a provider. */
16
- export function useSessionKernel(): SessionView {
17
- const binding = useContext(IdentityContext)
8
+ export function useSessionKernel(): KernelClient {
9
+ const identity = useContext(IdentityContext)
18
10
  const runtime = useContext(ShellContext)
19
- if (binding !== null) return binding.kernel
20
- if (runtime === null) {
21
- throw new Error('session hooks must be used within a <ShellProvider>')
22
- }
11
+ if (identity !== null) return identity.kernel
12
+ if (runtime === null) throw new Error('session hooks must be used within a <ShellProvider>')
23
13
  return runtime.shell.kernel
24
14
  }