@astrale-os/sdk 0.4.0 → 0.4.2

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 (101) hide show
  1. package/dist/auth/compose.d.ts +2 -2
  2. package/dist/auth/compose.d.ts.map +1 -1
  3. package/dist/auth/compose.js +2 -2
  4. package/dist/auth/compose.js.map +1 -1
  5. package/dist/auth/function-context.d.ts +28 -0
  6. package/dist/auth/function-context.d.ts.map +1 -0
  7. package/dist/auth/function-context.js +47 -0
  8. package/dist/auth/function-context.js.map +1 -0
  9. package/dist/auth/index.d.ts +5 -3
  10. package/dist/auth/index.d.ts.map +1 -1
  11. package/dist/auth/index.js +3 -2
  12. package/dist/auth/index.js.map +1 -1
  13. package/dist/auth/issuer-mint.d.ts +9 -9
  14. package/dist/auth/issuer-mint.d.ts.map +1 -1
  15. package/dist/auth/issuer-mint.js +3 -3
  16. package/dist/auth/issuer-mint.js.map +1 -1
  17. package/dist/auth/kernel-client.d.ts +5 -17
  18. package/dist/auth/kernel-client.d.ts.map +1 -1
  19. package/dist/auth/kernel-client.js +12 -34
  20. package/dist/auth/kernel-client.js.map +1 -1
  21. package/dist/cli/publish.js +1 -1
  22. package/dist/cli/publish.js.map +1 -1
  23. package/dist/config/define-domain.d.ts +1 -1
  24. package/dist/define/index.d.ts +1 -1
  25. package/dist/define/index.d.ts.map +1 -1
  26. package/dist/define/remote-function.d.ts +22 -30
  27. package/dist/define/remote-function.d.ts.map +1 -1
  28. package/dist/define/remote-function.js.map +1 -1
  29. package/dist/define/view.d.ts +6 -10
  30. package/dist/define/view.d.ts.map +1 -1
  31. package/dist/define/view.js.map +1 -1
  32. package/dist/dispatch/dispatcher.d.ts +1 -1
  33. package/dist/dispatch/dispatcher.d.ts.map +1 -1
  34. package/dist/dispatch/dispatcher.js +31 -7
  35. package/dist/dispatch/dispatcher.js.map +1 -1
  36. package/dist/dispatch/execute.d.ts +10 -6
  37. package/dist/dispatch/execute.d.ts.map +1 -1
  38. package/dist/dispatch/execute.js +5 -3
  39. package/dist/dispatch/execute.js.map +1 -1
  40. package/dist/dispatch/index.d.ts +0 -1
  41. package/dist/dispatch/index.d.ts.map +1 -1
  42. package/dist/dispatch/index.js +0 -1
  43. package/dist/dispatch/index.js.map +1 -1
  44. package/dist/index.d.ts +6 -5
  45. package/dist/index.d.ts.map +1 -1
  46. package/dist/index.js +1 -1
  47. package/dist/index.js.map +1 -1
  48. package/dist/method/context.d.ts +34 -28
  49. package/dist/method/context.d.ts.map +1 -1
  50. package/dist/method/context.js +2 -1
  51. package/dist/method/context.js.map +1 -1
  52. package/dist/method/index.d.ts +1 -1
  53. package/dist/method/index.d.ts.map +1 -1
  54. package/dist/method/index.js.map +1 -1
  55. package/dist/method/single.d.ts +2 -2
  56. package/dist/method/single.d.ts.map +1 -1
  57. package/dist/server/auxiliary-routes.d.ts.map +1 -1
  58. package/dist/server/auxiliary-routes.js +40 -21
  59. package/dist/server/auxiliary-routes.js.map +1 -1
  60. package/dist/server/create.js +1 -1
  61. package/dist/server/create.js.map +1 -1
  62. package/dist/step/index.d.ts +5 -0
  63. package/dist/step/index.d.ts.map +1 -0
  64. package/dist/step/index.js +3 -0
  65. package/dist/step/index.js.map +1 -0
  66. package/dist/step/inline.d.ts +8 -0
  67. package/dist/step/inline.d.ts.map +1 -0
  68. package/dist/step/inline.js +22 -0
  69. package/dist/step/inline.js.map +1 -0
  70. package/dist/step/step.d.ts +28 -0
  71. package/dist/step/step.d.ts.map +1 -0
  72. package/dist/step/step.js +53 -0
  73. package/dist/step/step.js.map +1 -0
  74. package/package.json +5 -1
  75. package/src/auth/compose.ts +2 -2
  76. package/src/auth/function-context.ts +108 -0
  77. package/src/auth/index.ts +9 -3
  78. package/src/auth/issuer-mint.ts +10 -9
  79. package/src/auth/kernel-client.ts +19 -44
  80. package/src/cli/publish.ts +1 -1
  81. package/src/config/define-domain.ts +1 -1
  82. package/src/define/index.ts +1 -0
  83. package/src/define/remote-function.ts +34 -30
  84. package/src/define/view.ts +6 -10
  85. package/src/dispatch/dispatcher.ts +34 -8
  86. package/src/dispatch/execute.ts +15 -9
  87. package/src/dispatch/index.ts +0 -1
  88. package/src/index.ts +20 -5
  89. package/src/method/context.ts +50 -28
  90. package/src/method/index.ts +8 -1
  91. package/src/method/single.ts +2 -2
  92. package/src/server/auxiliary-routes.ts +41 -23
  93. package/src/server/create.ts +1 -1
  94. package/src/step/index.ts +4 -0
  95. package/src/step/inline.ts +38 -0
  96. package/src/step/step.ts +95 -0
  97. package/dist/dispatch/call-remote.d.ts +0 -39
  98. package/dist/dispatch/call-remote.d.ts.map +0 -1
  99. package/dist/dispatch/call-remote.js +0 -37
  100. package/dist/dispatch/call-remote.js.map +0 -1
  101. package/src/dispatch/call-remote.ts +0 -53
@@ -29,7 +29,7 @@ import {
29
29
 
30
30
  import type { RemoteIdentityConfig } from './identity'
31
31
 
32
- import { buildComposedExpr, buildComposedGrant, buildSelfExpr, buildSelfGrant } from './compose'
32
+ import { buildComposedExpr, buildComposedGrant, buildSelfExpr } from './compose'
33
33
  import { signCredential } from './sign'
34
34
 
35
35
  const DELEGATION_TTL_SECONDS = 3600
@@ -75,20 +75,6 @@ export async function bindKernel(
75
75
  )
76
76
  }
77
77
 
78
- /**
79
- * Build a `BoundClientSessionView` authenticated as the FUNCTION'S OWN
80
- * identity — no inbound delegation, authority = the function's own grants
81
- * only. The seam behind `selfKernel` for public/webhook handlers: an HMAC- or
82
- * signature-verified webhook can act on the graph as itself after verifying
83
- * the upstream. Next-hop mints delegate self only.
84
- */
85
- export async function bindSelfKernel(
86
- kernelUrl: string,
87
- config: RemoteIdentityConfig,
88
- ): Promise<BoundClientSessionView<FnMap>> {
89
- return bindSession(kernelUrl, config, buildSelfGrant().grant, () => buildSelfExpr())
90
- }
91
-
92
78
  /**
93
79
  * Shared session construction: sign a credential as this function's identity
94
80
  * carrying `grant`, bind the session to it, and wire the lazy NEXT-HOP mint.
@@ -122,7 +108,10 @@ async function bindSession(
122
108
  schema: getRegistry(kernelUrl),
123
109
  pool: getPool(kernelUrl),
124
110
  delegation: {
125
- mint: delegationMintVia(() => session, credential),
111
+ mint: delegationMintVia(
112
+ () => session,
113
+ () => credential,
114
+ ),
126
115
  ttl: DELEGATION_TTL_SECONDS,
127
116
  },
128
117
  delegationPolicy: {
@@ -136,43 +125,29 @@ async function bindSession(
136
125
  /**
137
126
  * Bind a session to a PRE-SIGNED credential — no delegation mint, no composed
138
127
  * grant; the credential IS the authority. The seam behind
139
- * `DomainIssuer.sessionFor` (a worker acting as an identity it issues). Pool +
128
+ * `DomainAuthority.sessionFor` (a worker acting as an identity it issues). Pool +
140
129
  * schema registry are the same per-URL caches the composed sessions use.
141
130
  */
142
131
  export function bindCredentialSession(
143
132
  kernelUrl: string,
144
133
  credential: string,
134
+ opts: { delegation?: UnresolvedIdentityExpr } = {},
145
135
  ): BoundClientSessionView<FnMap> {
146
- const session = new ClientSession<FnMap>({
136
+ const session: ClientSession<FnMap> = new ClientSession<FnMap>({
147
137
  default: kernelUrl,
148
138
  schema: getRegistry(kernelUrl),
149
139
  pool: getPool(kernelUrl),
140
+ delegation: {
141
+ mint: delegationMintVia(
142
+ () => session,
143
+ () => credential,
144
+ ),
145
+ ttl: DELEGATION_TTL_SECONDS,
146
+ },
147
+ delegationPolicy: {
148
+ ...allowAllDelegations({ default: kernelUrl }),
149
+ delegationFor: () => opts.delegation ?? buildSelfExpr(),
150
+ },
150
151
  })
151
152
  return session.as(credential)
152
153
  }
153
-
154
- /**
155
- * Build the `selfKernel` accessor handed to remote-function handlers.
156
- * Resolves the kernel URL from the explicit argument or `deps.KERNEL_URL`
157
- * (a public request carries no credential, so the parent kernel cannot be
158
- * inferred — it must be configured).
159
- */
160
- export function makeSelfKernel(
161
- identity: RemoteIdentityConfig,
162
- deps: unknown,
163
- ): (kernelUrl?: string) => Promise<BoundClientSessionView<FnMap>> {
164
- return async (kernelUrl?: string) => {
165
- const env = deps as { INSTANCE_KERNEL_URL?: unknown; KERNEL_URL?: unknown } | null | undefined
166
- // Prefer the INSTANCE kernel (the graph this domain is installed on);
167
- // KERNEL_URL on managed services is the HOST kernel (the box) — wrong
168
- // graph for domain writes, kept only as a last-resort fallback.
169
- const url = kernelUrl ?? env?.INSTANCE_KERNEL_URL ?? env?.KERNEL_URL
170
- if (typeof url !== 'string' || url.length === 0) {
171
- throw new Error(
172
- 'selfKernel: no kernel URL — pass one explicitly or set INSTANCE_KERNEL_URL in the ' +
173
- 'worker env (managed deploys set it automatically).',
174
- )
175
- }
176
- return bindSelfKernel(url, identity)
177
- }
178
- }
@@ -176,7 +176,7 @@ export async function publishSchema(args: {
176
176
  error(
177
177
  `No schema package found (no package.json at ./schema or the current dir). A schema\n` +
178
178
  ` package declares peerDependencies (@astrale-os/kernel-core + kernel-dsl + zod) and a\n` +
179
- ` publishConfig that repoints main/exports to ./dist — see domains/workspace/schema.`,
179
+ ` publishConfig that repoints main/exports to ./dist — see domains/shell/schema.`,
180
180
  )
181
181
  return 1
182
182
  }
@@ -153,7 +153,7 @@ export interface DefineDomainConfig<S extends Schema, TDeps, TEnv = unknown> {
153
153
  * `has_parent` position: the domain's `installed_in` edge and EVERY typed
154
154
  * address (`/:<origin>`, `/:<origin>:Class`, …) stay ROOT-mounted, so
155
155
  * addressing is unchanged. A platform domain that must stay top-level sets its
156
- * own origin path (e.g. `'/workspace.astrale.ai'`).
156
+ * own origin path (e.g. `'/shell.astrale.ai'`).
157
157
  */
158
158
  path?: string
159
159
  /**
@@ -4,6 +4,7 @@ export type { ViewDef, ViewRenderContext } from './view'
4
4
  export { defineRemoteFunction } from './remote-function'
5
5
  export type {
6
6
  AnyRemoteFunctionDef,
7
+ RemoteFunctionAuthorizeContext,
7
8
  RemoteFunctionContext,
8
9
  RemoteFunctionDef,
9
10
  } from './remote-function'
@@ -23,11 +23,12 @@ import type { BoundClientSessionView } from '@astrale-os/kernel-client/session'
23
23
  import type { Context } from 'hono'
24
24
  import type { z } from 'zod'
25
25
 
26
- import type { DomainIssuer } from '../auth/issuer-mint'
27
- import type { CallRemoteFn } from '../dispatch/call-remote'
28
- import type { AuthForPolicy, KernelForAuth } from '../method/context'
26
+ import type { FunctionContextApi } from '../auth/function-context'
27
+ import type { DomainAuthority } from '../auth/issuer-mint'
28
+ import type { AuthForPolicy, CallerContext, KernelForAuth, RemoteEnv } from '../method/context'
29
+ import type { Step } from '../step'
29
30
 
30
- export type RemoteFunctionContext<
31
+ type RemoteFunctionBaseContext<
31
32
  TParams,
32
33
  TDeps = unknown,
33
34
  TKernel = BoundClientSessionView<FnMap> | null,
@@ -45,6 +46,8 @@ export type RemoteFunctionContext<
45
46
  auth: AuthForPolicy<TAuth>
46
47
  /** Typed dependency container injected at server startup. */
47
48
  deps: TDeps
49
+ /** Local serving metadata. */
50
+ env: RemoteEnv
48
51
  /**
49
52
  * `BoundClientSessionView` to the parent kernel, bound to the composed
50
53
  * credential `union(delegation, self)` — same shape as `RemoteContext.kernel`
@@ -53,32 +56,33 @@ export type RemoteFunctionContext<
53
56
  * `kernel.createNode` / `kernel.mutate(patch)`, …) over the `function.get` /
54
57
  * `function.mutate` syscalls. Nullability follows {@link KernelForAuth} of the
55
58
  * function's `auth`: non-null for the default `'required'`, `… | null` for
56
- * `'optional'`, `null` for `'public'` (use {@link RemoteFunctionContext.selfKernel}
57
- * there, after verifying the upstream).
59
+ * `'optional'`, `null` for `'public'` (use `ctx.fn.kernel()` there, after
60
+ * verifying the upstream).
58
61
  */
59
62
  kernel: TKernel
60
- /**
61
- * Mint seam for identities THIS DOMAIN issues — same contract as
62
- * {@link RemoteContext.issuer}.
63
- */
64
- issuer: DomainIssuer
65
- /**
66
- * Call another worker's remote method, re-minting the credential for the
67
- * target's audience. Same contract as {@link RemoteContext.callRemote}: throws
68
- * on a public/unauthenticated request; needs `USE` on
69
- * `Identity.mintDelegationCredential` + the target method's grants.
70
- */
71
- callRemote: CallRemoteFn
72
- /**
73
- * Acquire a kernel session authenticated as THIS FUNCTION'S OWN identity —
74
- * authority = the function's own grants only, no caller delegation. The
75
- * webhook seam: when an `auth: 'public'` upstream can't carry an Astrale
76
- * token (HMAC-signature webhooks, Stripe-style), VERIFY THE UPSTREAM'S
77
- * SIGNATURE FIRST, then act on the graph as yourself. `kernelUrl` defaults
78
- * to `deps.KERNEL_URL` (set automatically on managed deploys); pass it
79
- * explicitly for other targets.
80
- */
81
- selfKernel: (kernelUrl?: string) => Promise<BoundClientSessionView<FnMap>>
63
+ /** Inbound kernel/peer context. Present only for authenticated invocations. */
64
+ caller?: CallerContext
65
+ /** Mint seam for identities THIS DOMAIN issues. */
66
+ domain: DomainAuthority
67
+ /** Current function identity tools. */
68
+ fn: FunctionContextApi
69
+ }
70
+
71
+ export type RemoteFunctionAuthorizeContext<
72
+ TParams,
73
+ TDeps = unknown,
74
+ TKernel = BoundClientSessionView<FnMap> | null,
75
+ TAuth extends AuthPolicy = AuthPolicy,
76
+ > = RemoteFunctionBaseContext<TParams, TDeps, TKernel, TAuth>
77
+
78
+ export interface RemoteFunctionContext<
79
+ TParams,
80
+ TDeps = unknown,
81
+ TKernel = BoundClientSessionView<FnMap> | null,
82
+ TAuth extends AuthPolicy = AuthPolicy,
83
+ > extends RemoteFunctionBaseContext<TParams, TDeps, TKernel, TAuth> {
84
+ /** Durable-shaped step builder. Inline today, replayable by future backends. */
85
+ step: Step
82
86
  }
83
87
 
84
88
  export type RemoteFunctionDef<
@@ -107,12 +111,12 @@ export type RemoteFunctionDef<
107
111
  * so it drives `ctx.auth` and {@link KernelForAuth} on the
108
112
  * `execute`/`authorize` context: omit it (or `'required'`) makes both
109
113
  * non-null; `'optional'` widens them to `... | null`; `'public'` makes them
110
- * `null` (webhooks reach the graph via `ctx.selfKernel`).
114
+ * `null` (webhooks reach the graph via `ctx.fn.kernel()`).
111
115
  */
112
116
  auth?: TAuth
113
117
  /** Optional pre-execute authorization. Throw to deny. */
114
118
  authorize?: (
115
- ctx: RemoteFunctionContext<TParams, TDeps, KernelForAuth<TAuth>, TAuth>,
119
+ ctx: RemoteFunctionAuthorizeContext<TParams, TDeps, KernelForAuth<TAuth>, TAuth>,
116
120
  ) => void | Promise<void>
117
121
  /** The function body. May be async. */
118
122
  execute: (
@@ -21,12 +21,12 @@
21
21
  */
22
22
 
23
23
  import type { AuthPolicy, FunctionBinding } from '@astrale-os/kernel-api/routed'
24
- import type { FnMap } from '@astrale-os/kernel-client'
25
- import type { BoundClientSessionView } from '@astrale-os/kernel-client/session'
26
24
  import type { EdgeEndpoint } from '@astrale-os/kernel-dsl'
27
25
  import type { Context } from 'hono'
28
26
 
27
+ import type { FunctionContextApi } from '../auth/function-context'
29
28
  import type { AuthForPolicy } from '../method/context'
29
+ import type { RemoteEnv } from '../method/context'
30
30
 
31
31
  export type ViewRenderContext<TDeps = unknown, TAuth extends AuthPolicy = AuthPolicy> = {
32
32
  /** Hono request context — read params, headers, query, etc. */
@@ -45,14 +45,10 @@ export type ViewRenderContext<TDeps = unknown, TAuth extends AuthPolicy = AuthPo
45
45
  auth: AuthForPolicy<TAuth>
46
46
  /** Typed dependency container injected at server startup. */
47
47
  deps: TDeps
48
- /**
49
- * Kernel session authenticated as THE VIEW'S OWN identity (its grants
50
- * only) the seam for a server-rendered view that reads the graph (e.g.
51
- * a public list page). Grant the view's function identity narrow READ on
52
- * what it renders (in a seed), never root. Dials the INSTANCE kernel
53
- * (`deps.INSTANCE_KERNEL_URL`, set by managed deploys) unless overridden.
54
- */
55
- selfKernel: (kernelUrl?: string) => Promise<BoundClientSessionView<FnMap>>
48
+ /** Local serving metadata. */
49
+ env: RemoteEnv
50
+ /** View function identity tools. Use `fn.kernel()` for server-rendered graph reads. */
51
+ fn: FunctionContextApi
56
52
  }
57
53
 
58
54
  export type ViewDef<TDeps = unknown, TAuth extends AuthPolicy = AuthPolicy> = {
@@ -22,10 +22,11 @@ import type { RemoteIdentityConfig } from '../auth/identity'
22
22
  import type { AnyRemoteHandler } from '../method/single'
23
23
  import type { MethodIndex } from './resolve'
24
24
 
25
- import { makeIssuerMint } from '../auth/issuer-mint'
25
+ import { makeFunctionContext } from '../auth/function-context'
26
+ import { makeDomainAuthority } from '../auth/issuer-mint'
26
27
  import { resolveInboundAuth } from '../auth/resolve'
28
+ import { createInlineStep } from '../step'
27
29
  import { runAuthorize } from './authorize'
28
- import { makeCallRemote } from './call-remote'
29
30
  import { MethodNotFoundError, SdkResultValidationError, SdkValidationError } from './errors'
30
31
  import { executeHandler } from './execute'
31
32
  import { buildIdentityMap } from './identity'
@@ -51,7 +52,7 @@ export type SdkDispatcherConfig<TDeps> = {
51
52
  * install (the URL it fetched the domain at).
52
53
  */
53
54
  issuer: string
54
- /** The worker's serving URL (`config.url`) — exposed to handlers as `ctx.url`. */
55
+ /** The worker's serving URL (`config.url`) — exposed to handlers as `ctx.env.url`. */
55
56
  url: string
56
57
  /**
57
58
  * The domain schema. When present, non-static handlers receive the rich,
@@ -189,7 +190,6 @@ export class SdkDispatcher<TDeps = unknown> implements KernelAPI {
189
190
  authorize?: (ctx: unknown) => void | Promise<void>
190
191
  }
191
192
  const handlerParams = validation.data
192
- const callRemote = makeCallRemote(kernel)
193
193
  // Enrich the parsed self with the lazy `node()` accessor, bound to this
194
194
  // request's kernel (null when the auth policy yields none — `node()` then
195
195
  // rejects). Done here, not in `resolveSelf`, so the parse stays kernel-free.
@@ -200,20 +200,46 @@ export class SdkDispatcher<TDeps = unknown> implements KernelAPI {
200
200
  ? withBoundNode(parsedSelf, kernel, this.binder, bound.owner)
201
201
  : withNode(parsedSelf, kernel)
202
202
  : undefined
203
+ const inboundIss = auth?.credential?.verified?.iss as string | undefined
204
+ const kernelUrl = kernel?.default ?? inboundIss
205
+ const caller =
206
+ auth && inboundIss
207
+ ? {
208
+ iss: inboundIss,
209
+ url: kernelUrl ?? inboundIss,
210
+ }
211
+ : undefined
212
+
203
213
  const ctx = {
204
214
  params: handlerParams,
205
215
  auth,
206
216
  self,
207
217
  deps: this.deps,
208
- url: this.url,
218
+ env: { url: this.url },
209
219
  kernel,
210
- issuer: makeIssuerMint(fnIdentity),
211
- callRemote,
220
+ ...(caller !== undefined ? { caller } : {}),
221
+ domain: makeDomainAuthority(fnIdentity),
222
+ fn: makeFunctionContext(fnIdentity, this.deps, {
223
+ ref: bound.ref,
224
+ ...(kernelUrl !== undefined ? { defaultKernelUrl: kernelUrl } : {}),
225
+ }),
212
226
  }
213
227
 
214
228
  if (handler.authorize) await runAuthorize(handler.authorize, ctx)
215
229
 
216
- const result = await executeHandler({ handler, ref: bound.ref, ...ctx })
230
+ const result = await executeHandler({
231
+ handler,
232
+ ref: bound.ref,
233
+ ...ctx,
234
+ step: createInlineStep({
235
+ scope: {
236
+ kind: 'method',
237
+ ref: bound.ref,
238
+ owner: bound.owner,
239
+ method: bound.method,
240
+ },
241
+ }),
242
+ })
217
243
  return validateOutput(bound, result)
218
244
  }
219
245
 
@@ -11,8 +11,10 @@ import type { FnMap } from '@astrale-os/kernel-client'
11
11
  import type { BoundClientSessionView } from '@astrale-os/kernel-client/session'
12
12
  import type { AuthContext } from '@astrale-os/kernel-core'
13
13
 
14
- import type { DomainIssuer } from '../auth/issuer-mint'
15
- import type { CallRemoteFn } from './call-remote'
14
+ import type { FunctionContextApi } from '../auth/function-context'
15
+ import type { DomainAuthority } from '../auth/issuer-mint'
16
+ import type { CallerContext, RemoteEnv } from '../method/context'
17
+ import type { Step } from '../step'
16
18
  import type { SelfResult, TypedSelf } from './self'
17
19
 
18
20
  // oxlint-disable-next-line no-explicit-any
@@ -29,11 +31,13 @@ export type ExecuteParams = {
29
31
  /** Untyped fallback ({@link withNode}) or the rich typed self ({@link withBoundNode}). */
30
32
  self: SelfResult | TypedSelf<unknown> | undefined
31
33
  deps: unknown
32
- url: string
34
+ env: RemoteEnv
33
35
  kernel: BoundClientSessionView<FnMap> | null
34
- /** Mint seam for identities this domain issues (`ctx.issuer`). */
35
- issuer: DomainIssuer
36
- callRemote: CallRemoteFn
36
+ caller?: CallerContext
37
+ /** Mint seam for identities this domain issues. */
38
+ domain: DomainAuthority
39
+ fn: FunctionContextApi
40
+ step: Step
37
41
  }
38
42
 
39
43
  export async function executeHandler(ctx: ExecuteParams): Promise<unknown> {
@@ -48,9 +52,11 @@ export async function executeHandler(ctx: ExecuteParams): Promise<unknown> {
48
52
  auth: ctx.auth,
49
53
  self: ctx.self,
50
54
  deps: ctx.deps,
51
- url: ctx.url,
55
+ env: ctx.env,
52
56
  kernel: ctx.kernel,
53
- issuer: ctx.issuer,
54
- callRemote: ctx.callRemote,
57
+ ...(ctx.caller !== undefined ? { caller: ctx.caller } : {}),
58
+ domain: ctx.domain,
59
+ fn: ctx.fn,
60
+ step: ctx.step,
55
61
  })
56
62
  }
@@ -8,7 +8,6 @@ export {
8
8
  } from './validate'
9
9
  export { resolveSelf, withBoundNode, type SelfResult, type TypedSelf } from './self'
10
10
  export { executeHandler, type ExecuteParams } from './execute'
11
- export { makeCallRemote, type CallRemoteFn, type KernelCaller } from './call-remote'
12
11
  export {
13
12
  AuthorizationDeniedError,
14
13
  MethodNotFoundError,
package/src/index.ts CHANGED
@@ -6,6 +6,7 @@ export type {
6
6
  GraphApi,
7
7
  Kernel,
8
8
  KernelForAuth,
9
+ RemoteAuthorizeContext,
9
10
  RemoteContext,
10
11
  RemoteHandler,
11
12
  MethodImpl,
@@ -66,7 +67,16 @@ export type {
66
67
  // entry's `render` / `execute` (+ auth hooks) is mounted as a worker route by
67
68
  // `createRemoteServer`.
68
69
  export { defineView, defineRemoteFunction } from './define'
69
- export type { ViewDef, ViewRenderContext, RemoteFunctionDef, RemoteFunctionContext } from './define'
70
+ export type {
71
+ ViewDef,
72
+ ViewRenderContext,
73
+ RemoteFunctionAuthorizeContext,
74
+ RemoteFunctionDef,
75
+ RemoteFunctionContext,
76
+ } from './define'
77
+
78
+ // ─── Durable-shaped steps ────────────────────────────────────────────────
79
+ export type { Step } from './step'
70
80
 
71
81
  // ─── Server ──────────────────────────────────────────────────────────────
72
82
  // `createRemoteServer` dynamically imports `@hono/node-server` via `./server/start`.
@@ -97,12 +107,17 @@ export type {
97
107
 
98
108
  // ─── Auth ────────────────────────────────────────────────────────────────
99
109
  export type { RemoteIdentityConfig, AuthenticateResult } from './auth'
100
- export type { DomainIssuer, MintIssuedParams } from './auth'
110
+ export type {
111
+ DomainAuthority,
112
+ FunctionContextApi,
113
+ FunctionCredentialOptions,
114
+ FunctionKernelOptions,
115
+ MintIssuedParams,
116
+ } from './auth'
101
117
  export {
102
118
  authenticateRequest,
103
- bindSelfKernel,
104
119
  buildComposedGrant,
105
- makeSelfKernel,
120
+ makeFunctionContext,
106
121
  signCredential,
107
122
  } from './auth'
108
123
  export { AuthMissingError, AuthInvalidError } from './auth'
@@ -125,4 +140,4 @@ export {
125
140
  SdkValidationError,
126
141
  SdkResultValidationError,
127
142
  } from './dispatch'
128
- export type { SelfResult, TypedSelf, CallRemoteFn, KernelCaller } from './dispatch'
143
+ export type { SelfResult, TypedSelf } from './dispatch'
@@ -4,7 +4,8 @@
4
4
  * Assembled by the dispatch pipeline before calling `execute`. Carries the
5
5
  * validated params, the resolved auth context, the bound node instance (for
6
6
  * non-static methods), the typed dependency container, and a
7
- * `BoundClientSessionView` to call back into the parent kernel.
7
+ * `BoundClientSessionView` to call back into the parent kernel, plus explicit
8
+ * `domain`, `caller`, and `fn` namespaces for identity-sensitive work.
8
9
  */
9
10
 
10
11
  import type { AuthPolicy } from '@astrale-os/kernel-api/routed'
@@ -12,8 +13,9 @@ import type { FnMap } from '@astrale-os/kernel-client'
12
13
  import type { BoundClientSessionView } from '@astrale-os/kernel-client/session'
13
14
  import type { AuthContext } from '@astrale-os/kernel-core'
14
15
 
15
- import type { DomainIssuer } from '../auth/issuer-mint'
16
- import type { CallRemoteFn } from '../dispatch/call-remote'
16
+ import type { FunctionContextApi } from '../auth/function-context'
17
+ import type { DomainAuthority } from '../auth/issuer-mint'
18
+ import type { Step } from '../step'
17
19
 
18
20
  export type { GraphApi } from '@astrale-os/kernel-client/graph'
19
21
 
@@ -33,8 +35,8 @@ export type Kernel = BoundClientSessionView<FnMap>
33
35
  * - `'required'` (the default) — the dispatcher rejects a credentialless call
34
36
  * before `execute`, so the kernel is ALWAYS present → non-null.
35
37
  * - `'optional'` — a kernel only when a credential was supplied → `… | null`.
36
- * - `'public'` — never any inbound credential → `null`. (Public handlers that
37
- * must touch the graph use `selfKernel` after verifying their own upstream.)
38
+ * - `'public'` — never any inbound credential → `null`. Public handlers that
39
+ * must touch the graph use `ctx.fn.kernel()` after verifying their upstream.
38
40
  *
39
41
  * Distributes over a `AuthPolicy` union (e.g. when `auth` is typed but not a
40
42
  * literal) to the widened `Kernel | null` — the safe superset, matching the
@@ -57,7 +59,19 @@ export type AuthForPolicy<TAuth extends AuthPolicy> = TAuth extends 'public'
57
59
  ? AuthContext | null
58
60
  : AuthContext
59
61
 
60
- export type RemoteContext<
62
+ export type RemoteEnv = {
63
+ /** This worker's canonical serving URL. */
64
+ url: string
65
+ }
66
+
67
+ export type CallerContext = {
68
+ /** Issuer of the inbound kernel/peer credential. */
69
+ iss: string
70
+ /** Kernel URL associated with this invocation. */
71
+ url: string
72
+ }
73
+
74
+ type RemoteBaseContext<
61
75
  TParams,
62
76
  TSelf,
63
77
  TDeps,
@@ -76,8 +90,8 @@ export type RemoteContext<
76
90
  self: TSelf
77
91
  /** Typed dependency container injected at server startup. */
78
92
  deps: TDeps
79
- /** The worker's own serving URL */
80
- url: string
93
+ /** Local serving metadata. */
94
+ env: RemoteEnv
81
95
  /**
82
96
  * `BoundClientSessionView` to the parent kernel, bound to the composed
83
97
  * credential `union(delegation, self)`. Its nullability is `{@link
@@ -88,26 +102,34 @@ export type RemoteContext<
88
102
  * plus `kernel.createNode` / `kernel.updateNode` /
89
103
  * `kernel.deleteNode` / `kernel.createEdge` / `kernel.updateEdge` /
90
104
  * `kernel.deleteEdge` / `kernel.mutate(patch)`) over the `function.get` /
91
- * `function.mutate` syscalls. For ANOTHER worker's remote method use
92
- * {@link RemoteContext.callRemote} — `kernel.call` to a remote method fails the
93
- * audience check.
105
+ * `function.mutate` syscalls. Remote-bound calls are made with
106
+ * `kernel.call(...)`; the client follows redirects and remints the next-hop
107
+ * delegation under the current bound authority.
94
108
  */
95
109
  kernel: TKernel
96
- /**
97
- * Mint seam for identities THIS DOMAIN issues (`iss` = this worker): sign a
98
- * credential for a domain-owned principal (an App identity, a role umbrella,
99
- * a managed user) and optionally open a kernel session AS it. See
100
- * {@link DomainIssuer}. The kernel enforces trust/frozen/grant rules this
101
- * only signs under the worker's own issuer.
102
- */
103
- issuer: DomainIssuer
104
- /**
105
- * Call another worker's remote method (a Function with `binding.remoteUrl`),
106
- * re-minting the credential for the target's audience so it isn't rejected at
107
- * authentication. Throws on a public/unauthenticated request (no credential
108
- * to mint from). The calling Function's identity must hold `USE` on
109
- * `Identity.mintDelegationCredential` AND the target method's own grants —
110
- * `callRemote` fixes the audience, not authorization.
111
- */
112
- callRemote: CallRemoteFn
110
+ /** Inbound kernel/peer context. Present only for authenticated invocations. */
111
+ caller?: CallerContext
112
+ /** Mint seam for identities THIS DOMAIN issues (`iss` = this worker). */
113
+ domain: DomainAuthority
114
+ /** Current function identity tools: grant-bearing credentials and self-bound kernels. */
115
+ fn: FunctionContextApi
116
+ }
117
+
118
+ export type RemoteAuthorizeContext<
119
+ TParams,
120
+ TSelf,
121
+ TDeps,
122
+ TKernel = Kernel | null,
123
+ TAuth extends AuthPolicy = AuthPolicy,
124
+ > = RemoteBaseContext<TParams, TSelf, TDeps, TKernel, TAuth>
125
+
126
+ export interface RemoteContext<
127
+ TParams,
128
+ TSelf,
129
+ TDeps,
130
+ TKernel = Kernel | null,
131
+ TAuth extends AuthPolicy = AuthPolicy,
132
+ > extends RemoteBaseContext<TParams, TSelf, TDeps, TKernel, TAuth> {
133
+ /** Durable-shaped step builder. Inline today, replayable by future backends. */
134
+ step: Step
113
135
  }
@@ -1,4 +1,11 @@
1
- export type { AuthForPolicy, GraphApi, Kernel, KernelForAuth, RemoteContext } from './context'
1
+ export type {
2
+ AuthForPolicy,
3
+ GraphApi,
4
+ Kernel,
5
+ KernelForAuth,
6
+ RemoteAuthorizeContext,
7
+ RemoteContext,
8
+ } from './context'
2
9
  export type {
3
10
  RemoteHandler,
4
11
  AnyRemoteHandler,
@@ -10,7 +10,7 @@ import type {
10
10
  import type { Schema } from '@astrale-os/kernel-dsl'
11
11
 
12
12
  import type { TypedSelf } from '../dispatch/self'
13
- import type { KernelForAuth, RemoteContext } from './context'
13
+ import type { KernelForAuth, RemoteAuthorizeContext, RemoteContext } from './context'
14
14
 
15
15
  /**
16
16
  * Remote method handler. `execute` is optional only for binding stubs; any
@@ -47,7 +47,7 @@ export type RemoteHandler<TParams, TResult, TSelf, TDeps, TAuth extends AuthPoli
47
47
  * has_perm checks remain authoritative; this is additive gating.
48
48
  */
49
49
  authorize?: (
50
- ctx: RemoteContext<TParams, TSelf, TDeps, KernelForAuth<TAuth>, TAuth>,
50
+ ctx: RemoteAuthorizeContext<TParams, TSelf, TDeps, KernelForAuth<TAuth>, TAuth>,
51
51
  ) => void | Promise<void>
52
52
  }
53
53