@astrale-os/kernel-client 0.6.0-beta.75 → 0.6.0-beta.77

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.
@@ -1,15 +1,14 @@
1
1
  import { NodeId } from '@astrale-os/kernel-core/graph/node';
2
2
  import { Path } from '@astrale-os/kernel-core/path';
3
- import { K } from '@astrale-os/kernel-core/schema';
4
- import { download } from '@astrale-os/kernel-core/schema/kernel/syscalls/references';
3
+ import { download, meaning, upload, } from '@astrale-os/kernel-core/schema/kernel/syscalls/references';
5
4
  import { PropertyKey } from '@astrale-os/kernel-dsl/v1/addressing';
6
5
  import * as artifact from '@astrale-os/kernel-protocol/artifact';
7
6
  import { CODES } from '@astrale-os/kernel-protocol/errors';
8
7
  import { ClientError, ProtocolError, ResponseError, TransportError } from '../errors/index.js';
9
8
  import { admitControlOptions, runSessionOperation } from './context/index.js';
10
- import { reference } from './reference.js';
9
+ import { kernelReference } from './reference.js';
11
10
  import { requireResultKind } from './routing/index.js';
12
- const UPLOAD = reference(K, K.functions.upload);
11
+ const UPLOAD = kernelReference(upload, meaning.upload);
13
12
  const DOWNLOAD = Path.project(download);
14
13
  const CONTENT_TIMEOUT_MS = 30 * 60 * 1_000;
15
14
  const MAXIMUM_ATTEMPTS = 3;
@@ -11,8 +11,8 @@ type IssuerDependencies = Pick<ExchangeDependencies, 'kernel' | 'fetch' | 'polic
11
11
  export declare function tokenEndpoint(dependencies: IssuerDependencies, domain: IssuerId, operation: SessionOperation): Promise<string>;
12
12
  /**
13
13
  * Present a delegation at a Domain's token endpoint and admit the returned credential as provider
14
- * evidence: its issuer must be that Domain, its audience the source Kernel, and its signed expiry
15
- * the reported one.
14
+ * evidence: it must be the exchange representation served with `Cache-Control: no-store`, its
15
+ * issuer that Domain, its audience the source Kernel, and its signed expiry the reported one.
16
16
  */
17
17
  export declare function redeem(dependencies: IssuerDependencies, domain: IssuerId, endpoint: string, delegation: MintedCredential, operation: SessionOperation): Promise<SessionCredential>;
18
18
  export {};
@@ -23,11 +23,14 @@ export async function tokenEndpoint(dependencies, domain, operation) {
23
23
  }
24
24
  /**
25
25
  * Present a delegation at a Domain's token endpoint and admit the returned credential as provider
26
- * evidence: its issuer must be that Domain, its audience the source Kernel, and its signed expiry
27
- * the reported one.
26
+ * evidence: it must be the exchange representation served with `Cache-Control: no-store`, its
27
+ * issuer that Domain, its audience the source Kernel, and its signed expiry the reported one.
28
28
  */
29
29
  export async function redeem(dependencies, domain, endpoint, delegation, operation) {
30
- const exchanged = await fetchAdmitted(dependencies, TOKEN_EXCHANGE, endpoint, operation, (body) => issuer.exchange.acceptResponse(body), delegation);
30
+ const exchanged = await fetchAdmitted(dependencies, TOKEN_EXCHANGE, endpoint, operation, (body, headers) => {
31
+ requireCredentialHeaders(headers);
32
+ return issuer.exchange.acceptResponse(body);
33
+ }, delegation);
31
34
  let claims;
32
35
  try {
33
36
  claims = inspect(exchanged.token);
@@ -78,7 +81,7 @@ async function fetchAdmitted(dependencies, leg, url, operation, admit, credentia
78
81
  requireExactResponse(response, url, 'Domain token exchange');
79
82
  if (!response.ok)
80
83
  throw await refusal(response, leg, signal);
81
- return admit(codecs.json.decode(await boundedResponse(response, dependencies.maximumResponseBytes, signal)));
84
+ return admit(codecs.json.decode(await boundedResponse(response, dependencies.maximumResponseBytes, signal)), response.headers);
82
85
  }
83
86
  catch (cause) {
84
87
  throw signal.aborted ? cause : unadmitted(cause, leg);
@@ -124,6 +127,20 @@ function unadmitted(cause, leg) {
124
127
  }
125
128
  return cause;
126
129
  }
130
+ /** A credential is served as the exchange representation and never stored by an HTTP cache. */
131
+ function requireCredentialHeaders(headers) {
132
+ const mediaType = headers.get('content-type')?.split(';', 1)[0].trim().toLowerCase();
133
+ if (mediaType !== issuer.exchange.MEDIA_TYPE) {
134
+ throw invalidResponse('Domain token exchange returned an unsupported Content-Type.');
135
+ }
136
+ const directives = headers
137
+ .get('cache-control')
138
+ ?.split(',')
139
+ .map((directive) => directive.trim().toLowerCase()) ?? [];
140
+ if (!directives.includes('no-store')) {
141
+ throw invalidResponse('Domain token exchange response is missing Cache-Control: no-store.');
142
+ }
143
+ }
127
144
  function invalidResponse(message, cause) {
128
145
  return new ExchangeError(message, {
129
146
  failure: 'invalid-response',
@@ -1,14 +1,13 @@
1
1
  import { Path } from '@astrale-os/kernel-core/path';
2
- import { K } from '@astrale-os/kernel-core/schema';
3
- import { reference } from './reference.js';
4
- const methods = K.classes.Execution.methods;
2
+ import { execution as methods, meaning, } from '@astrale-os/kernel-core/schema/kernel/syscalls/references';
3
+ import { kernelReference } from './reference.js';
5
4
  const bound = {
6
- status: reference(K, methods.status),
7
- result: reference(K, methods.result),
8
- cancel: reference(K, methods.cancel),
9
- signal: reference(K, methods.signal),
10
- resume: reference(K, methods.resume),
11
- delete: reference(K, methods.delete),
5
+ status: kernelReference(methods.status, meaning.execution.status),
6
+ result: kernelReference(methods.result, meaning.execution.result),
7
+ cancel: kernelReference(methods.cancel, meaning.execution.cancel),
8
+ signal: kernelReference(methods.signal, meaning.execution.signal),
9
+ resume: kernelReference(methods.resume, meaning.execution.resume),
10
+ delete: kernelReference(methods.delete, meaning.execution.delete),
12
11
  };
13
12
  function receiver(execution) {
14
13
  return Path.id(typeof execution === 'string' ? execution : execution.id);
@@ -1,6 +1,7 @@
1
1
  import type { Path as PathValue, PathLike } from '@astrale-os/kernel-core/path';
2
+ import type { FunctionRef } from '@astrale-os/kernel-core/schema/kernel/syscalls/references';
2
3
  import type { CallableInputOf, CallableInputModeOf, CallableOutputOf, CallableResultOf, Domain, ResolvedFunction, ExecutableMethod } from '@astrale-os/kernel-dsl/v1';
3
- import type { Revision } from '@astrale-os/kernel-dsl/v1/addressing';
4
+ import type { MethodAddress, Revision } from '@astrale-os/kernel-dsl/v1/addressing';
4
5
  import type { MeaningFingerprint } from '@astrale-os/kernel-dsl/v1/schema/fingerprint';
5
6
  import { type Key as KeyType } from '@astrale-os/kernel-dsl/v1/addressing';
6
7
  import type { Binary, Input } from '../client/index.js';
@@ -45,6 +46,13 @@ type ExecutableInstanceMethod = ExecutableMethod<unknown, unknown, false>;
45
46
  export declare function reference<const Callable extends ResolvedFunction | ExecutableStaticMethod>(domain: Pick<Domain, 'origin' | 'revision'>, callable: Callable): CallableReference<ReferenceInput<Callable>, ReferenceOutput<Callable>, CallableInputModeOf<Callable>>;
46
47
  /** Project one exact resolved instance Method into a receiver-bound typed Client reference. */
47
48
  export declare function reference<const Callable extends ExecutableInstanceMethod>(domain: Pick<Domain, 'origin' | 'revision'>, callable: Callable): InstanceCallableReference<ReferenceInput<Callable>, ReferenceOutput<Callable>>;
49
+ /**
50
+ * Reference a Kernel callable from its Core coordinate and precomputed meaning, so runtime code never
51
+ * loads the Kernel Schema. Core keeps each meaning equal to the resolved Kernel; every Kernel
52
+ * callable referenced this way answers a value.
53
+ */
54
+ export declare function kernelReference(callable: FunctionRef<'kernel.astrale.ai'>, fingerprint: MeaningFingerprint): CallableReference<unknown>;
55
+ export declare function kernelReference(callable: MethodAddress, fingerprint: MeaningFingerprint): InstanceCallableReference<unknown>;
48
56
  export declare function admitReference(input: CallableReference<unknown>): CallableReference<unknown>;
49
57
  export declare function matchesCallable(target: PathValue, callable: KeyType.Callable): boolean;
50
58
  export {};
@@ -1,5 +1,6 @@
1
1
  import { Path } from '@astrale-os/kernel-core/path';
2
- import { callableAddress, Key, patterns, } from '@astrale-os/kernel-dsl/v1/addressing';
2
+ import { meaning } from '@astrale-os/kernel-core/schema/kernel/syscalls/references';
3
+ import { callableAddress, Key, MethodKey, patterns, } from '@astrale-os/kernel-dsl/v1/addressing';
3
4
  import { callableFingerprint } from '@astrale-os/kernel-dsl/v1/schema/fingerprint';
4
5
  const FINGERPRINT_PATTERN = /^sha256:[0-9a-f]{64}$/u;
5
6
  export function reference(domain, callable) {
@@ -26,6 +27,21 @@ export function reference(domain, callable) {
26
27
  : Path.project(callable.ref);
27
28
  return admitReference({ ...common, target });
28
29
  }
30
+ export function kernelReference(callable, fingerprint) {
31
+ const key = callable.kind === 'method' ? MethodKey.of(callable.owner, callable.name) : Key.of(callable);
32
+ const common = Object.freeze({
33
+ origin: Key.origin(key),
34
+ revision: meaning.revision,
35
+ fingerprint,
36
+ callable: key,
37
+ outputMode: 'value',
38
+ });
39
+ if (callable.kind === 'function')
40
+ return admitReference({ ...common, target: Path.project(callable) });
41
+ const method = key;
42
+ const bind = (receiver) => admitReference({ ...common, target: Path.instanceMethod(Path.from(receiver), method) });
43
+ return Object.assign(bind, common);
44
+ }
29
45
  export function admitReference(input) {
30
46
  if (input === null || typeof input !== 'object')
31
47
  invalid();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astrale-os/kernel-client",
3
- "version": "0.6.0-beta.75",
3
+ "version": "0.6.0-beta.77",
4
4
  "description": "Universal Client — protocol-first, transport-agnostic",
5
5
  "keywords": [
6
6
  "astrale",
@@ -65,14 +65,14 @@
65
65
  "access": "public"
66
66
  },
67
67
  "dependencies": {
68
- "@astrale-os/kernel-core": "0.9.0-beta.56",
68
+ "@astrale-os/kernel-core": "0.9.0-beta.57",
69
69
  "@astrale-os/kernel-dsl": "0.2.0-beta.41",
70
- "@astrale-os/kernel-protocol": "0.5.0-beta.62",
70
+ "@astrale-os/kernel-protocol": "0.5.0-beta.63",
71
71
  "@tanstack/pacer": "0.20.1",
72
72
  "msgpackr": "^2.0.5"
73
73
  },
74
74
  "devDependencies": {
75
- "@astrale-os/kernel-server": "0.5.0-beta.64",
75
+ "@astrale-os/kernel-server": "0.5.0-beta.65",
76
76
  "@astrale/typescript-config": "npm:@jsr/astrale__typescript-config@~1.1.0",
77
77
  "@types/node": "^22.0.0",
78
78
  "typescript": "7.0.2",