@astrale-os/sdk 0.1.4 → 0.1.6

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.
@@ -17,6 +17,8 @@ export type VerifiedInbound = {
17
17
  /** Delegation — scoped caller permissions as kernel-signed credential */
18
18
  delegation: Delegation;
19
19
  };
20
+ /** Clear cached JWKS resolvers. Used in tests when keys rotate between fixtures. */
21
+ export declare function clearJwksCache(): void;
20
22
  /**
21
23
  * Verify an inbound delegation credential using kernel-core's verification.
22
24
  *
@@ -1 +1 @@
1
- {"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../src/auth/verify.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,WAAW,EACX,eAAe,EACf,UAAU,EAEV,kBAAkB,EACnB,MAAM,yBAAyB,CAAA;AAUhC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA;AAKtD,MAAM,MAAM,eAAe,GAAG;IAC5B,2DAA2D;IAC3D,QAAQ,EAAE,kBAAkB,CAAA;IAC5B,+CAA+C;IAC/C,MAAM,EAAE,MAAM,CAAA;IACd,2DAA2D;IAC3D,WAAW,EAAE,WAAW,CAAA;IACxB,yEAAyE;IACzE,UAAU,EAAE,UAAU,CAAA;CACvB,CAAA;AA4DD;;;;GAIG;AACH,wBAAsB,uBAAuB,CAC3C,UAAU,EAAE,eAAe,EAC3B,MAAM,EAAE,oBAAoB,GAC3B,OAAO,CAAC,eAAe,CAAC,CA+B1B"}
1
+ {"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../src/auth/verify.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,WAAW,EACX,eAAe,EACf,UAAU,EAEV,kBAAkB,EACnB,MAAM,yBAAyB,CAAA;AAYhC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA;AAKtD,MAAM,MAAM,eAAe,GAAG;IAC5B,2DAA2D;IAC3D,QAAQ,EAAE,kBAAkB,CAAA;IAC5B,+CAA+C;IAC/C,MAAM,EAAE,MAAM,CAAA;IACd,2DAA2D;IAC3D,WAAW,EAAE,WAAW,CAAA;IACxB,yEAAyE;IACzE,UAAU,EAAE,UAAU,CAAA;CACvB,CAAA;AAkBD,oFAAoF;AACpF,wBAAgB,cAAc,IAAI,IAAI,CAGrC;AAiFD;;;;GAIG;AACH,wBAAsB,uBAAuB,CAC3C,UAAU,EAAE,eAAe,EAC3B,MAAM,EAAE,oBAAoB,GAC3B,OAAO,CAAC,eAAe,CAAC,CA+C1B"}
@@ -5,19 +5,68 @@
5
5
  * (CredentialMethodResolver, MethodRegistry) instead of manual JWT handling.
6
6
  * Not tied to JWT — supports any credential method kernel-core provides.
7
7
  */
8
- import { CredentialMethodResolver, MethodRegistry, verifyAudience, verifyCredential, } from '@astrale-os/kernel-core';
8
+ import { CredentialMethodResolver, MethodRegistry, SignatureVerificationError, SigningKeyNotFoundError, verifyAudience, verifyCredential, } from '@astrale-os/kernel-core';
9
9
  import { createLocalJWKSet, createRemoteJWKSet } from 'jose';
10
10
  import { derivePublicJwk } from '../server/jwks';
11
11
  import { canonicalizeServingUrl } from '../server/serving-url';
12
12
  const methodResolver = new CredentialMethodResolver(new MethodRegistry());
13
+ // JWKS resolvers cached per JWKS URL (module-level, like the pools/selfIds
14
+ // Maps in kernel-client.ts). jose handles freshness WITHIN a resolver: 10min
15
+ // max-age, 30s fetch cooldown, and auto-refetch on kid-miss when not cooling
16
+ // down. The one gap — issuer restarts with new keys while the cooldown pins
17
+ // the old set (the incident that got a prior indefinite cache removed) — is
18
+ // covered by evict-and-retry-once in `verifyInboundCredential`, so indefinite
19
+ // Map residency is safe and the per-call JWKS fetch is gone.
20
+ const remoteResolvers = new Map();
21
+ // Self-issued credentials verify against the worker's own in-memory key;
22
+ // cache the local JWKS per canonical self-issuer (one key per worker) so the
23
+ // public-JWK derivation isn't redone on every request.
24
+ const localResolvers = new Map();
25
+ /** Clear cached JWKS resolvers. Used in tests when keys rotate between fixtures. */
26
+ export function clearJwksCache() {
27
+ remoteResolvers.clear();
28
+ localResolvers.clear();
29
+ }
30
+ /**
31
+ * M-28 fix: a bare-slug iss (`mails.localhost`) makes
32
+ * `new URL('mails.localhost/.well-known/jwks.json')` throw "Invalid URL
33
+ * string". The dispatcher's identity map normalizes the iss it signs with,
34
+ * but inbound creds from older clients may still carry the slug form. Coerce
35
+ * to a URL with a default `https://` scheme (matches kernel.astrale.ai
36
+ * canonical form). If the actual receiver is on http://localhost the
37
+ * receiver-side resolver still works because both endpoints are on localhost
38
+ * — but for prod targets requiring TLS this is the right default.
39
+ */
40
+ function jwksUrlFor(issuer) {
41
+ const normalized = /^https?:\/\//.test(issuer) ? issuer : `https://${issuer}`;
42
+ return `${normalized}/.well-known/jwks.json`;
43
+ }
44
+ function getRemoteResolver(jwksUrl) {
45
+ let resolver = remoteResolvers.get(jwksUrl);
46
+ if (!resolver) {
47
+ resolver = createRemoteJWKSet(new URL(jwksUrl));
48
+ remoteResolvers.set(jwksUrl, resolver);
49
+ }
50
+ return resolver;
51
+ }
52
+ function getLocalResolver(selfIssuer, privateKey) {
53
+ let resolver = localResolvers.get(selfIssuer);
54
+ if (!resolver) {
55
+ resolver = createLocalJWKSet({ keys: [derivePublicJwk(privateKey)] });
56
+ localResolvers.set(selfIssuer, resolver);
57
+ }
58
+ return resolver;
59
+ }
13
60
  /**
14
61
  * Build the key resolver for one verifying server. Captures `config` so it can
15
62
  * short-circuit the server's OWN issuer (`config.issuer`): a self-issued
16
63
  * credential is verified against the in-memory public key, never fetched — a
17
64
  * Worker can't fetch its own hostname, and it already holds the key. Every other
18
- * issuer is resolved live via JWKS (`createRemoteJWKSet`).
65
+ * issuer is resolved via the cached per-URL JWKS resolvers above; every JWKS
66
+ * URL touched is recorded in `resolvedJwksUrls` so the caller can evict
67
+ * exactly those resolvers if verification fails on an unknown signing key.
19
68
  */
20
- function makeResolveKeys(config) {
69
+ function makeResolveKeys(config, resolvedJwksUrls) {
21
70
  // The worker's own canonical iss. STRICT: `config.issuer` is the serving URL
22
71
  // by contract (both producers — buildIdentityMap / buildAuxIdentityMap — feed
23
72
  // it `canonicalizeServingUrl(config.url)`), so a value that doesn't parse is
@@ -26,13 +75,6 @@ function makeResolveKeys(config) {
26
75
  // worker's own hostname — which Cloudflare forbids — turning a config bug
27
76
  // into an opaque per-call failure.
28
77
  const selfIssuer = canonicalizeServingUrl(config.issuer);
29
- // TODO(cache): Re-add JWKS caching with a short TTL or kid-miss retry.
30
- // A prior implementation cached `createRemoteJWKSet` per issuer URL
31
- // indefinitely. jose's internal cache (30s cooldown, 10min max-age) caused
32
- // stale keys when the issuer restarted — the resolver served old keys and
33
- // jose refused to refetch within the cooldown window. On CF Workers the
34
- // module-level Map persisted across requests, making it worse. For now we
35
- // create a fresh resolver per call (jose deduplicates concurrent fetches).
36
78
  return async (issuer, _method, _kid) => {
37
79
  const url = issuer;
38
80
  // Self-issued credential (iss == this worker's own serving URL): resolve
@@ -47,20 +89,12 @@ function makeResolveKeys(config) {
47
89
  canonical = undefined;
48
90
  }
49
91
  if (canonical === selfIssuer) {
50
- return createLocalJWKSet({ keys: [derivePublicJwk(config.privateKey)] });
92
+ return getLocalResolver(selfIssuer, config.privateKey);
51
93
  }
52
94
  }
53
- // M-28 fix: a bare-slug iss (`mails.localhost`) makes
54
- // `new URL('mails.localhost/.well-known/jwks.json')` throw "Invalid
55
- // URL string". The dispatcher's identity map normalizes the iss it
56
- // signs with, but inbound creds from older clients may still carry
57
- // the slug form. Coerce to a URL with a default `https://` scheme
58
- // (matches kernel.astrale.ai canonical form). If the actual receiver
59
- // is on http://localhost the receiver-side resolver still works
60
- // because both endpoints are on localhost — but for prod targets
61
- // requiring TLS this is the right default.
62
- const normalized = /^https?:\/\//.test(url) ? url : `https://${url}`;
63
- return createRemoteJWKSet(new URL(`${normalized}/.well-known/jwks.json`));
95
+ const jwksUrl = jwksUrlFor(url);
96
+ resolvedJwksUrls.add(jwksUrl);
97
+ return getRemoteResolver(jwksUrl);
64
98
  };
65
99
  }
66
100
  /**
@@ -70,10 +104,31 @@ function makeResolveKeys(config) {
70
104
  */
71
105
  export async function verifyInboundCredential(credential, config) {
72
106
  // Verify using kernel-core's credential verification pipeline
73
- const verified = await verifyCredential({
74
- methodResolver,
75
- resolveKeys: makeResolveKeys(config),
76
- }, credential);
107
+ const resolvedJwksUrls = new Set();
108
+ const deps = { methodResolver, resolveKeys: makeResolveKeys(config, resolvedJwksUrls) };
109
+ let verified;
110
+ try {
111
+ verified = await verifyCredential(deps, credential);
112
+ }
113
+ catch (error) {
114
+ // A cached resolver can hold a stale key set after the issuer rotates:
115
+ // - new kid → jose kid-misses but its 30s fetch cooldown blocks the
116
+ // refetch (SigningKeyNotFoundError) — the incident that got a prior
117
+ // indefinite cache removed;
118
+ // - SAME kid, new key material (kernel kids derive from the subject, so
119
+ // a re-keyed issuer reuses its kid) → the signature check fails
120
+ // (SignatureVerificationError).
121
+ // Both: evict the resolver(s) this verification touched and retry ONCE
122
+ // with fresh ones. Forged-token spam thus costs at most one JWKS fetch
123
+ // per bad credential — equal to the uncached per-call baseline, never
124
+ // worse. An empty set means self-issued — refetching can't help, rethrow.
125
+ const staleKeySuspect = error instanceof SigningKeyNotFoundError || error instanceof SignatureVerificationError;
126
+ if (!staleKeySuspect || resolvedJwksUrls.size === 0)
127
+ throw error;
128
+ for (const url of resolvedJwksUrls)
129
+ remoteResolvers.delete(url);
130
+ verified = await verifyCredential(deps, credential);
131
+ }
77
132
  // Validate audience matches this function's issuer (its serving URL).
78
133
  // kernel-core's verifyAudience compares canonically.
79
134
  verifyAudience(verified, config.issuer);
@@ -1 +1 @@
1
- {"version":3,"file":"verify.js","sourceRoot":"","sources":["../../src/auth/verify.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"verify.js","sourceRoot":"","sources":["../../src/auth/verify.ts"],"names":[],"mappings":"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"}
@@ -18,6 +18,8 @@
18
18
  * lives at an external host.
19
19
  */
20
20
  import type { AuthPolicy, FunctionBinding } from '@astrale-os/kernel-api/routed';
21
+ import type { FnMap } from '@astrale-os/kernel-client';
22
+ import type { BoundClientSessionView } from '@astrale-os/kernel-client/session';
21
23
  import type { AuthContext } from '@astrale-os/kernel-core';
22
24
  import type { EdgeEndpoint } from '@astrale-os/kernel-dsl';
23
25
  import type { Context } from 'hono';
@@ -34,6 +36,14 @@ export type ViewRenderContext<TDeps = unknown> = {
34
36
  auth: AuthContext | null;
35
37
  /** Typed dependency container injected at server startup. */
36
38
  deps: TDeps;
39
+ /**
40
+ * Kernel session authenticated as THE VIEW'S OWN identity (its grants
41
+ * only) — the seam for a server-rendered view that reads the graph (e.g.
42
+ * a public list page). Grant the view's function identity narrow READ on
43
+ * what it renders (in a seed), never root. Dials the INSTANCE kernel
44
+ * (`deps.INSTANCE_KERNEL_URL`, set by managed deploys) unless overridden.
45
+ */
46
+ selfKernel: (kernelUrl?: string) => Promise<BoundClientSessionView<FnMap>>;
37
47
  };
38
48
  export type ViewDef<TDeps = unknown> = {
39
49
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../../src/define/view.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAChF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA;AAC1D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAEnC,MAAM,MAAM,iBAAiB,CAAC,KAAK,GAAG,OAAO,IAAI;IAC/C,+DAA+D;IAC/D,CAAC,EAAE,OAAO,CAAA;IACV;;;;OAIG;IACH,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC9B,qEAAqE;IACrE,IAAI,EAAE,WAAW,GAAG,IAAI,CAAA;IACxB,6DAA6D;IAC7D,IAAI,EAAE,KAAK,CAAA;CACZ,CAAA;AAED,MAAM,MAAM,OAAO,CAAC,KAAK,GAAG,OAAO,IAAI;IACrC;;;;;;;;OAQG;IACH,OAAO,CAAC,EAAE,eAAe,CAAA;IACzB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,uDAAuD;IACvD,IAAI,CAAC,EAAE,UAAU,CAAA;IACjB;;;OAGG;IACH,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,iBAAiB,CAAC,KAAK,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACnE;;;;OAIG;IACH,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,iBAAiB,CAAC,KAAK,CAAC,KAAK,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;IACxE;;;;;OAKG;IACH,OAAO,CAAC,EAAE,YAAY,GAAG,YAAY,EAAE,CAAA;IACvC,2CAA2C;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,GAAG,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAE/E"}
1
+ {"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../../src/define/view.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAChF,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAA;AACtD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAA;AAC/E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA;AAC1D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAEnC,MAAM,MAAM,iBAAiB,CAAC,KAAK,GAAG,OAAO,IAAI;IAC/C,+DAA+D;IAC/D,CAAC,EAAE,OAAO,CAAA;IACV;;;;OAIG;IACH,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC9B,qEAAqE;IACrE,IAAI,EAAE,WAAW,GAAG,IAAI,CAAA;IACxB,6DAA6D;IAC7D,IAAI,EAAE,KAAK,CAAA;IACX;;;;;;OAMG;IACH,UAAU,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,sBAAsB,CAAC,KAAK,CAAC,CAAC,CAAA;CAC3E,CAAA;AAED,MAAM,MAAM,OAAO,CAAC,KAAK,GAAG,OAAO,IAAI;IACrC;;;;;;;;OAQG;IACH,OAAO,CAAC,EAAE,eAAe,CAAA;IACzB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,uDAAuD;IACvD,IAAI,CAAC,EAAE,UAAU,CAAA;IACjB;;;OAGG;IACH,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,iBAAiB,CAAC,KAAK,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACnE;;;;OAIG;IACH,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,iBAAiB,CAAC,KAAK,CAAC,KAAK,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;IACxE;;;;;OAKG;IACH,OAAO,CAAC,EAAE,YAAY,GAAG,YAAY,EAAE,CAAA;IACvC,2CAA2C;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,GAAG,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAE/E"}
@@ -1 +1 @@
1
- {"version":3,"file":"view.js","sourceRoot":"","sources":["../../src/define/view.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAiEH;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAkB,GAAmB;IAC7D,OAAO,GAAG,CAAA;AACZ,CAAC"}
1
+ {"version":3,"file":"view.js","sourceRoot":"","sources":["../../src/define/view.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AA2EH;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAkB,GAAmB;IAC7D,OAAO,GAAG,CAAA;AACZ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"auxiliary-routes.d.ts","sourceRoot":"","sources":["../../src/server/auxiliary-routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,OAAO,KAAK,EAAW,IAAI,EAAE,MAAM,MAAM,CAAA;AAQzC,OAAO,EAKL,KAAK,eAAe,EAErB,MAAM,+BAA+B,CAAA;AACtC,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,2BAA2B,CAAA;AAG7E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAA;AACrE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAA;AAE7C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAS1D,MAAM,MAAM,qBAAqB,CAAC,KAAK,IAAI;IACzC,GAAG,EAAE,IAAI,CAAA;IACT,gFAAgF;IAChF,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAA;IACtC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;IAC9C,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAA;IACtD,sBAAsB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;IACxD,IAAI,EAAE,KAAK,CAAA;IACX;;;;OAIG;IACH,UAAU,EAAE,cAAc,CAAA;IAC1B;;;;;OAKG;IACH,IAAI,EAAE,UAAU,CAAA;CACjB,CAAA;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,qBAAqB,CAAC,KAAK,CAAC,GAAG,IAAI,CA4EtF"}
1
+ {"version":3,"file":"auxiliary-routes.d.ts","sourceRoot":"","sources":["../../src/server/auxiliary-routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,OAAO,KAAK,EAAW,IAAI,EAAE,MAAM,MAAM,CAAA;AAQzC,OAAO,EAKL,KAAK,eAAe,EAErB,MAAM,+BAA+B,CAAA;AACtC,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,2BAA2B,CAAA;AAG7E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAA;AACrE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAA;AAE7C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAS1D,MAAM,MAAM,qBAAqB,CAAC,KAAK,IAAI;IACzC,GAAG,EAAE,IAAI,CAAA;IACT,gFAAgF;IAChF,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAA;IACtC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;IAC9C,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAA;IACtD,sBAAsB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;IACxD,IAAI,EAAE,KAAK,CAAA;IACX;;;;OAIG;IACH,UAAU,EAAE,cAAc,CAAA;IAC1B;;;;;OAKG;IACH,IAAI,EAAE,UAAU,CAAA;CACjB,CAAA;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,qBAAqB,CAAC,KAAK,CAAC,GAAG,IAAI,CAiFtF"}
@@ -41,11 +41,16 @@ export function mountAuxiliaryRoutes(config) {
41
41
  // Views are transport-only (iframe HTML/redirect) — the kernel client
42
42
  // built by `resolveInboundAuth` is intentionally NOT forwarded. Code
43
43
  // inside the loaded iframe talks back to the kernel via the shell
44
- // (WebSocket), not via this worker route.
44
+ // (WebSocket), not via this worker route. SERVER-rendered views that
45
+ // read the graph use `selfKernel` instead: the view's OWN identity,
46
+ // narrow grants (the cold-agent gate run had to deep-import SDK
47
+ // internals for exactly this — now it's the supported seam).
45
48
  run: async ({ c, params, auth }) => {
49
+ const selfKernel = makeSelfKernel(identity, deps);
50
+ const ctx = { c, params, auth, deps, selfKernel };
46
51
  if (def.authorize)
47
- await runAuthorize(def.authorize, { c, params, auth, deps });
48
- return def.render({ c, params, auth, deps });
52
+ await runAuthorize(def.authorize, ctx);
53
+ return def.render(ctx);
49
54
  },
50
55
  });
51
56
  }
@@ -1 +1 @@
1
- {"version":3,"file":"auxiliary-routes.js","sourceRoot":"","sources":["../../src/server/auxiliary-routes.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"auxiliary-routes.js","sourceRoot":"","sources":["../../src/server/auxiliary-routes.ts"],"names":[],"mappings":"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"}
@@ -34,6 +34,11 @@ export interface WorkerEntryConfig<TDeps> {
34
34
  * Resolve the raw serving URL from `env` (+ the per-request origin, for workers
35
35
  * that fall back to the request host). Defaults to the `WORKER_URL` env var.
36
36
  * The result is always canonicalized before use.
37
+ *
38
+ * The `requestOrigin` honors an `X-Forwarded-Proto: https` upgrade (see
39
+ * `clientOrigin`), so a dev worker behind a TLS-terminating proxy (cloudflared
40
+ * tunnel, reverse proxy) resolves its public `https://` origin, not the raw
41
+ * `http://` one workerd sees.
37
42
  */
38
43
  resolveUrl?: (env: TDeps, requestOrigin: string) => string;
39
44
  /** Optional: the `SELF` service binding used to route same-host subrequests. */
@@ -55,6 +60,18 @@ export interface WorkerEntryConfig<TDeps> {
55
60
  export interface WorkerEntry<TDeps> {
56
61
  fetch(request: Request, env: TDeps): Response | Promise<Response>;
57
62
  }
63
+ /**
64
+ * The request origin as the CLIENT reached it — i.e. the origin a fallback
65
+ * serving URL (and therefore the `iss`) may be derived from. Behind a
66
+ * TLS-terminating proxy (a cloudflared tunnel in front of `wrangler dev`, any
67
+ * reverse proxy) the worker sees plain HTTP, so `request.url` says `http://…`
68
+ * while the public URL is `https://…`; the proxy advertises the original
69
+ * scheme via `X-Forwarded-Proto`. Honoring it is restricted to the http→https
70
+ * UPGRADE of the SAME host (never a downgrade, never a host change), so a
71
+ * spoofed header can at worst derive an `iss` the kernel's JWKS check then
72
+ * fails — it can never make this worker speak for another origin.
73
+ */
74
+ export declare function clientOrigin(url: URL, request: Request): string;
58
75
  export declare function createWorkerEntry<TDeps>(config: WorkerEntryConfig<TDeps>): WorkerEntry<TDeps>;
59
76
  export {};
60
77
  //# sourceMappingURL=worker-entry.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"worker-entry.d.ts","sourceRoot":"","sources":["../../src/server/worker-entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAA;AAMlD,KAAK,OAAO,GAAG;IAAE,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;CAAE,CAAA;AAGxE,MAAM,WAAW,iBAAiB,CAAC,KAAK;IACtC;;;;OAIG;IACH,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,KAAK,kBAAkB,CAAC,KAAK,CAAC,CAAA;IAC7D;;;;OAIG;IACH,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,KAAK,MAAM,CAAA;IAC1D,gFAAgF;IAChF,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,OAAO,GAAG,IAAI,GAAG,SAAS,CAAA;IACxD;;;;;OAKG;IACH,MAAM,CAAC,EAAE,CACP,GAAG,EAAE,KAAK,EACV,GAAG,EAAE,GAAG,EACR,OAAO,EAAE,OAAO,KACb,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAAA;IACzD;;;;OAIG;IACH,cAAc,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,KAAK,OAAO,CAAA;CAC3D;AAED,MAAM,WAAW,WAAW,CAAC,KAAK;IAChC,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,GAAG,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;CAClE;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,iBAAiB,CAAC,KAAK,CAAC,GAAG,WAAW,CAAC,KAAK,CAAC,CAoD7F"}
1
+ {"version":3,"file":"worker-entry.d.ts","sourceRoot":"","sources":["../../src/server/worker-entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAA;AAMlD,KAAK,OAAO,GAAG;IAAE,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;CAAE,CAAA;AAGxE,MAAM,WAAW,iBAAiB,CAAC,KAAK;IACtC;;;;OAIG;IACH,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,KAAK,kBAAkB,CAAC,KAAK,CAAC,CAAA;IAC7D;;;;;;;;;OASG;IACH,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,KAAK,MAAM,CAAA;IAC1D,gFAAgF;IAChF,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,OAAO,GAAG,IAAI,GAAG,SAAS,CAAA;IACxD;;;;;OAKG;IACH,MAAM,CAAC,EAAE,CACP,GAAG,EAAE,KAAK,EACV,GAAG,EAAE,GAAG,EACR,OAAO,EAAE,OAAO,KACb,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAAA;IACzD;;;;OAIG;IACH,cAAc,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,KAAK,OAAO,CAAA;CAC3D;AAED,MAAM,WAAW,WAAW,CAAC,KAAK;IAChC,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,GAAG,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;CAClE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,CAM/D;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,iBAAiB,CAAC,KAAK,CAAC,GAAG,WAAW,CAAC,KAAK,CAAC,CAmE7F"}
@@ -22,14 +22,46 @@
22
22
  import { createRemoteServer } from './create';
23
23
  import { requireEnv } from './require-env';
24
24
  import { canonicalizeServingUrl } from './serving-url';
25
+ /**
26
+ * The request origin as the CLIENT reached it — i.e. the origin a fallback
27
+ * serving URL (and therefore the `iss`) may be derived from. Behind a
28
+ * TLS-terminating proxy (a cloudflared tunnel in front of `wrangler dev`, any
29
+ * reverse proxy) the worker sees plain HTTP, so `request.url` says `http://…`
30
+ * while the public URL is `https://…`; the proxy advertises the original
31
+ * scheme via `X-Forwarded-Proto`. Honoring it is restricted to the http→https
32
+ * UPGRADE of the SAME host (never a downgrade, never a host change), so a
33
+ * spoofed header can at worst derive an `iss` the kernel's JWKS check then
34
+ * fails — it can never make this worker speak for another origin.
35
+ */
36
+ export function clientOrigin(url, request) {
37
+ if (url.protocol !== 'http:')
38
+ return url.origin;
39
+ const forwarded = request.headers.get('x-forwarded-proto');
40
+ // Multiple proxies append: "https, http" — the first hop is the client-facing one.
41
+ const scheme = forwarded?.split(',')[0]?.trim().toLowerCase();
42
+ return scheme === 'https' ? `https://${url.host}` : url.origin;
43
+ }
25
44
  export function createWorkerEntry(config) {
26
- let cache = null;
45
+ // Cache the built app per distinct resolved URL — plural and bounded. On the
46
+ // request-origin fallback the URL legitimately alternates for one worker
47
+ // (direct http hits vs https-upgraded tunnel hits, workers.dev + custom
48
+ // domain), and a single slot would tear down and rebuild the whole app on
49
+ // every alternation. The bound caps abuse via attacker-minted Host /
50
+ // X-Forwarded-Proto values on that same fallback path.
51
+ const MAX_CACHED_APPS = 4;
52
+ const apps = new Map();
27
53
  let self = null;
28
54
  function getApp(url, env) {
29
- if (cache && cache.url === url)
30
- return cache.app;
55
+ const cached = apps.get(url);
56
+ if (cached)
57
+ return cached.app;
31
58
  const { app } = createRemoteServer(config.build(url, env));
32
- cache = { url, origin: new URL(url).origin, app };
59
+ if (apps.size >= MAX_CACHED_APPS) {
60
+ const oldest = apps.keys().next().value;
61
+ if (oldest !== undefined)
62
+ apps.delete(oldest);
63
+ }
64
+ apps.set(url, { origin: new URL(url).origin, app });
33
65
  return app;
34
66
  }
35
67
  // A Worker can't fetch its own hostname. When a SELF service binding is
@@ -41,11 +73,14 @@ export function createWorkerEntry(config) {
41
73
  if (config.selfBinding) {
42
74
  const originalFetch = globalThis.fetch;
43
75
  globalThis.fetch = (async (input, init) => {
44
- if (cache && self) {
76
+ if (apps.size > 0 && self) {
45
77
  const href = typeof input === 'string' ? input : input instanceof URL ? input.href : input.url;
46
78
  try {
47
- if (new URL(href).origin === cache.origin)
48
- return self.fetch(new Request(input, init));
79
+ const origin = new URL(href).origin;
80
+ for (const cached of apps.values()) {
81
+ if (cached.origin === origin)
82
+ return self.fetch(new Request(input, init));
83
+ }
49
84
  }
50
85
  catch {
51
86
  // non-absolute URL — fall through to the original fetch
@@ -68,7 +103,7 @@ export function createWorkerEntry(config) {
68
103
  return handled;
69
104
  }
70
105
  const raw = config.resolveUrl
71
- ? config.resolveUrl(env, requestUrl.origin)
106
+ ? config.resolveUrl(env, clientOrigin(requestUrl, request))
72
107
  : requireEnv(env, 'WORKER_URL', "the worker's public serving URL (its iss identity)");
73
108
  const url = canonicalizeServingUrl(raw);
74
109
  const dispatched = config.rewriteRequest ? config.rewriteRequest(env, request) : request;
@@ -1 +1 @@
1
- {"version":3,"file":"worker-entry.js","sourceRoot":"","sources":["../../src/server/worker-entry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"worker-entry.js","sourceRoot":"","sources":["../../src/server/worker-entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAIH,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAA;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC1C,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAA;AAgDtD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,YAAY,CAAC,GAAQ,EAAE,OAAgB;IACrD,IAAI,GAAG,CAAC,QAAQ,KAAK,OAAO;QAAE,OAAO,GAAG,CAAC,MAAM,CAAA;IAC/C,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAA;IAC1D,mFAAmF;IACnF,MAAM,MAAM,GAAG,SAAS,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;IAC7D,OAAO,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,WAAW,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAA;AAChE,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAQ,MAAgC;IACvE,6EAA6E;IAC7E,yEAAyE;IACzE,wEAAwE;IACxE,0EAA0E;IAC1E,qEAAqE;IACrE,uDAAuD;IACvD,MAAM,eAAe,GAAG,CAAC,CAAA;IACzB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAwC,CAAA;IAC5D,IAAI,IAAI,GAAmB,IAAI,CAAA;IAE/B,SAAS,MAAM,CAAC,GAAW,EAAE,GAAU;QACrC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QAC5B,IAAI,MAAM;YAAE,OAAO,MAAM,CAAC,GAAG,CAAA;QAC7B,MAAM,EAAE,GAAG,EAAE,GAAG,kBAAkB,CAAQ,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAA;QACjE,IAAI,IAAI,CAAC,IAAI,IAAI,eAAe,EAAE,CAAC;YACjC,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAA;YACvC,IAAI,MAAM,KAAK,SAAS;gBAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;QAC/C,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;QACnD,OAAO,GAAG,CAAA;IACZ,CAAC;IAED,wEAAwE;IACxE,2EAA2E;IAC3E,+DAA+D;IAC/D,+EAA+E;IAC/E,8EAA8E;IAC9E,4EAA4E;IAC5E,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;QACvB,MAAM,aAAa,GAAG,UAAU,CAAC,KAAK,CAAA;QACtC,UAAU,CAAC,KAAK,GAAG,CAAC,KAAK,EAAE,KAAwB,EAAE,IAAkB,EAAE,EAAE;YACzE,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;gBAC1B,MAAM,IAAI,GACR,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,YAAY,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAA;gBACnF,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,MAAM,CAAA;oBACnC,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;wBACnC,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM;4BAAE,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAA;oBAC3E,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,wDAAwD;gBAC1D,CAAC;YACH,CAAC;YACD,OAAO,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;QACnC,CAAC,CAAiB,CAAA;IACpB,CAAC;IAED,OAAO;QACL,KAAK,CAAC,KAAK,CAAC,OAAgB,EAAE,GAAU;YACtC,IAAI,MAAM,CAAC,WAAW;gBAAE,IAAI,KAAK,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,IAAI,CAAA;YAChE,4DAA4D;YAC5D,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;YACnF,IAAI,MAAM,CAAC,MAAM,IAAI,UAAU,EAAE,CAAC;gBAChC,wEAAwE;gBACxE,2EAA2E;gBAC3E,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,UAAU,EAAE,OAAO,CAAC,CAAA;gBAC7D,IAAI,OAAO,KAAK,SAAS;oBAAE,OAAO,OAAO,CAAA;YAC3C,CAAC;YACD,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU;gBAC3B,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE,YAAY,CAAC,UAAW,EAAE,OAAO,CAAC,CAAC;gBAC5D,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,YAAY,EAAE,oDAAoD,CAAC,CAAA;YACvF,MAAM,GAAG,GAAG,sBAAsB,CAAC,GAAG,CAAC,CAAA;YACvC,MAAM,UAAU,GAAG,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAA;YACxF,OAAO,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,CAAA;QAC3C,CAAC;KACF,CAAA;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astrale-os/sdk",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "description": "Astrale Remote Domain SDK - Define and deploy domains as standalone Hono servers",
5
5
  "keywords": [
6
6
  "astrale",
@@ -17,6 +17,8 @@ import type {
17
17
  import {
18
18
  CredentialMethodResolver,
19
19
  MethodRegistry,
20
+ SignatureVerificationError,
21
+ SigningKeyNotFoundError,
20
22
  verifyAudience,
21
23
  verifyCredential,
22
24
  } from '@astrale-os/kernel-core'
@@ -40,14 +42,72 @@ export type VerifiedInbound = {
40
42
 
41
43
  const methodResolver = new CredentialMethodResolver(new MethodRegistry())
42
44
 
45
+ // JWKS resolvers cached per JWKS URL (module-level, like the pools/selfIds
46
+ // Maps in kernel-client.ts). jose handles freshness WITHIN a resolver: 10min
47
+ // max-age, 30s fetch cooldown, and auto-refetch on kid-miss when not cooling
48
+ // down. The one gap — issuer restarts with new keys while the cooldown pins
49
+ // the old set (the incident that got a prior indefinite cache removed) — is
50
+ // covered by evict-and-retry-once in `verifyInboundCredential`, so indefinite
51
+ // Map residency is safe and the per-call JWKS fetch is gone.
52
+ const remoteResolvers = new Map<string, ReturnType<typeof createRemoteJWKSet>>()
53
+
54
+ // Self-issued credentials verify against the worker's own in-memory key;
55
+ // cache the local JWKS per canonical self-issuer (one key per worker) so the
56
+ // public-JWK derivation isn't redone on every request.
57
+ const localResolvers = new Map<string, ReturnType<typeof createLocalJWKSet>>()
58
+
59
+ /** Clear cached JWKS resolvers. Used in tests when keys rotate between fixtures. */
60
+ export function clearJwksCache(): void {
61
+ remoteResolvers.clear()
62
+ localResolvers.clear()
63
+ }
64
+
65
+ /**
66
+ * M-28 fix: a bare-slug iss (`mails.localhost`) makes
67
+ * `new URL('mails.localhost/.well-known/jwks.json')` throw "Invalid URL
68
+ * string". The dispatcher's identity map normalizes the iss it signs with,
69
+ * but inbound creds from older clients may still carry the slug form. Coerce
70
+ * to a URL with a default `https://` scheme (matches kernel.astrale.ai
71
+ * canonical form). If the actual receiver is on http://localhost the
72
+ * receiver-side resolver still works because both endpoints are on localhost
73
+ * — but for prod targets requiring TLS this is the right default.
74
+ */
75
+ function jwksUrlFor(issuer: string): string {
76
+ const normalized = /^https?:\/\//.test(issuer) ? issuer : `https://${issuer}`
77
+ return `${normalized}/.well-known/jwks.json`
78
+ }
79
+
80
+ function getRemoteResolver(jwksUrl: string): ReturnType<typeof createRemoteJWKSet> {
81
+ let resolver = remoteResolvers.get(jwksUrl)
82
+ if (!resolver) {
83
+ resolver = createRemoteJWKSet(new URL(jwksUrl))
84
+ remoteResolvers.set(jwksUrl, resolver)
85
+ }
86
+ return resolver
87
+ }
88
+
89
+ function getLocalResolver(
90
+ selfIssuer: string,
91
+ privateKey: RemoteIdentityConfig['privateKey'],
92
+ ): ReturnType<typeof createLocalJWKSet> {
93
+ let resolver = localResolvers.get(selfIssuer)
94
+ if (!resolver) {
95
+ resolver = createLocalJWKSet({ keys: [derivePublicJwk(privateKey) as JWK] })
96
+ localResolvers.set(selfIssuer, resolver)
97
+ }
98
+ return resolver
99
+ }
100
+
43
101
  /**
44
102
  * Build the key resolver for one verifying server. Captures `config` so it can
45
103
  * short-circuit the server's OWN issuer (`config.issuer`): a self-issued
46
104
  * credential is verified against the in-memory public key, never fetched — a
47
105
  * Worker can't fetch its own hostname, and it already holds the key. Every other
48
- * issuer is resolved live via JWKS (`createRemoteJWKSet`).
106
+ * issuer is resolved via the cached per-URL JWKS resolvers above; every JWKS
107
+ * URL touched is recorded in `resolvedJwksUrls` so the caller can evict
108
+ * exactly those resolvers if verification fails on an unknown signing key.
49
109
  */
50
- function makeResolveKeys(config: RemoteIdentityConfig) {
110
+ function makeResolveKeys(config: RemoteIdentityConfig, resolvedJwksUrls: Set<string>) {
51
111
  // The worker's own canonical iss. STRICT: `config.issuer` is the serving URL
52
112
  // by contract (both producers — buildIdentityMap / buildAuxIdentityMap — feed
53
113
  // it `canonicalizeServingUrl(config.url)`), so a value that doesn't parse is
@@ -57,13 +117,6 @@ function makeResolveKeys(config: RemoteIdentityConfig) {
57
117
  // into an opaque per-call failure.
58
118
  const selfIssuer = canonicalizeServingUrl(config.issuer)
59
119
 
60
- // TODO(cache): Re-add JWKS caching with a short TTL or kid-miss retry.
61
- // A prior implementation cached `createRemoteJWKSet` per issuer URL
62
- // indefinitely. jose's internal cache (30s cooldown, 10min max-age) caused
63
- // stale keys when the issuer restarted — the resolver served old keys and
64
- // jose refused to refetch within the cooldown window. On CF Workers the
65
- // module-level Map persisted across requests, making it worse. For now we
66
- // create a fresh resolver per call (jose deduplicates concurrent fetches).
67
120
  return async (issuer: IssuerId, _method: string, _kid?: string) => {
68
121
  const url = issuer as string
69
122
 
@@ -78,21 +131,13 @@ function makeResolveKeys(config: RemoteIdentityConfig) {
78
131
  canonical = undefined
79
132
  }
80
133
  if (canonical === selfIssuer) {
81
- return createLocalJWKSet({ keys: [derivePublicJwk(config.privateKey) as JWK] })
134
+ return getLocalResolver(selfIssuer, config.privateKey)
82
135
  }
83
136
  }
84
137
 
85
- // M-28 fix: a bare-slug iss (`mails.localhost`) makes
86
- // `new URL('mails.localhost/.well-known/jwks.json')` throw "Invalid
87
- // URL string". The dispatcher's identity map normalizes the iss it
88
- // signs with, but inbound creds from older clients may still carry
89
- // the slug form. Coerce to a URL with a default `https://` scheme
90
- // (matches kernel.astrale.ai canonical form). If the actual receiver
91
- // is on http://localhost the receiver-side resolver still works
92
- // because both endpoints are on localhost — but for prod targets
93
- // requiring TLS this is the right default.
94
- const normalized = /^https?:\/\//.test(url) ? url : `https://${url}`
95
- return createRemoteJWKSet(new URL(`${normalized}/.well-known/jwks.json`))
138
+ const jwksUrl = jwksUrlFor(url)
139
+ resolvedJwksUrls.add(jwksUrl)
140
+ return getRemoteResolver(jwksUrl)
96
141
  }
97
142
  }
98
143
 
@@ -106,13 +151,29 @@ export async function verifyInboundCredential(
106
151
  config: RemoteIdentityConfig,
107
152
  ): Promise<VerifiedInbound> {
108
153
  // Verify using kernel-core's credential verification pipeline
109
- const verified = await verifyCredential(
110
- {
111
- methodResolver,
112
- resolveKeys: makeResolveKeys(config),
113
- },
114
- credential,
115
- )
154
+ const resolvedJwksUrls = new Set<string>()
155
+ const deps = { methodResolver, resolveKeys: makeResolveKeys(config, resolvedJwksUrls) }
156
+ let verified: VerifiedCredential
157
+ try {
158
+ verified = await verifyCredential(deps, credential)
159
+ } catch (error) {
160
+ // A cached resolver can hold a stale key set after the issuer rotates:
161
+ // - new kid → jose kid-misses but its 30s fetch cooldown blocks the
162
+ // refetch (SigningKeyNotFoundError) — the incident that got a prior
163
+ // indefinite cache removed;
164
+ // - SAME kid, new key material (kernel kids derive from the subject, so
165
+ // a re-keyed issuer reuses its kid) → the signature check fails
166
+ // (SignatureVerificationError).
167
+ // Both: evict the resolver(s) this verification touched and retry ONCE
168
+ // with fresh ones. Forged-token spam thus costs at most one JWKS fetch
169
+ // per bad credential — equal to the uncached per-call baseline, never
170
+ // worse. An empty set means self-issued — refetching can't help, rethrow.
171
+ const staleKeySuspect =
172
+ error instanceof SigningKeyNotFoundError || error instanceof SignatureVerificationError
173
+ if (!staleKeySuspect || resolvedJwksUrls.size === 0) throw error
174
+ for (const url of resolvedJwksUrls) remoteResolvers.delete(url)
175
+ verified = await verifyCredential(deps, credential)
176
+ }
116
177
 
117
178
  // Validate audience matches this function's issuer (its serving URL).
118
179
  // kernel-core's verifyAudience compares canonically.
@@ -19,6 +19,8 @@
19
19
  */
20
20
 
21
21
  import type { AuthPolicy, FunctionBinding } from '@astrale-os/kernel-api/routed'
22
+ import type { FnMap } from '@astrale-os/kernel-client'
23
+ import type { BoundClientSessionView } from '@astrale-os/kernel-client/session'
22
24
  import type { AuthContext } from '@astrale-os/kernel-core'
23
25
  import type { EdgeEndpoint } from '@astrale-os/kernel-dsl'
24
26
  import type { Context } from 'hono'
@@ -36,6 +38,14 @@ export type ViewRenderContext<TDeps = unknown> = {
36
38
  auth: AuthContext | null
37
39
  /** Typed dependency container injected at server startup. */
38
40
  deps: TDeps
41
+ /**
42
+ * Kernel session authenticated as THE VIEW'S OWN identity (its grants
43
+ * only) — the seam for a server-rendered view that reads the graph (e.g.
44
+ * a public list page). Grant the view's function identity narrow READ on
45
+ * what it renders (in a seed), never root. Dials the INSTANCE kernel
46
+ * (`deps.INSTANCE_KERNEL_URL`, set by managed deploys) unless overridden.
47
+ */
48
+ selfKernel: (kernelUrl?: string) => Promise<BoundClientSessionView<FnMap>>
39
49
  }
40
50
 
41
51
  export type ViewDef<TDeps = unknown> = {
@@ -102,10 +102,15 @@ export function mountAuxiliaryRoutes<TDeps>(config: AuxiliaryRoutesConfig<TDeps>
102
102
  // Views are transport-only (iframe HTML/redirect) — the kernel client
103
103
  // built by `resolveInboundAuth` is intentionally NOT forwarded. Code
104
104
  // inside the loaded iframe talks back to the kernel via the shell
105
- // (WebSocket), not via this worker route.
105
+ // (WebSocket), not via this worker route. SERVER-rendered views that
106
+ // read the graph use `selfKernel` instead: the view's OWN identity,
107
+ // narrow grants (the cold-agent gate run had to deep-import SDK
108
+ // internals for exactly this — now it's the supported seam).
106
109
  run: async ({ c, params, auth }) => {
107
- if (def.authorize) await runAuthorize(def.authorize, { c, params, auth, deps })
108
- return def.render!({ c, params, auth, deps })
110
+ const selfKernel = makeSelfKernel(identity, deps)
111
+ const ctx = { c, params, auth, deps, selfKernel }
112
+ if (def.authorize) await runAuthorize(def.authorize, ctx)
113
+ return def.render!(ctx)
109
114
  },
110
115
  })
111
116
  }
@@ -40,6 +40,11 @@ export interface WorkerEntryConfig<TDeps> {
40
40
  * Resolve the raw serving URL from `env` (+ the per-request origin, for workers
41
41
  * that fall back to the request host). Defaults to the `WORKER_URL` env var.
42
42
  * The result is always canonicalized before use.
43
+ *
44
+ * The `requestOrigin` honors an `X-Forwarded-Proto: https` upgrade (see
45
+ * `clientOrigin`), so a dev worker behind a TLS-terminating proxy (cloudflared
46
+ * tunnel, reverse proxy) resolves its public `https://` origin, not the raw
47
+ * `http://` one workerd sees.
43
48
  */
44
49
  resolveUrl?: (env: TDeps, requestOrigin: string) => string
45
50
  /** Optional: the `SELF` service binding used to route same-host subrequests. */
@@ -67,14 +72,45 @@ export interface WorkerEntry<TDeps> {
67
72
  fetch(request: Request, env: TDeps): Response | Promise<Response>
68
73
  }
69
74
 
75
+ /**
76
+ * The request origin as the CLIENT reached it — i.e. the origin a fallback
77
+ * serving URL (and therefore the `iss`) may be derived from. Behind a
78
+ * TLS-terminating proxy (a cloudflared tunnel in front of `wrangler dev`, any
79
+ * reverse proxy) the worker sees plain HTTP, so `request.url` says `http://…`
80
+ * while the public URL is `https://…`; the proxy advertises the original
81
+ * scheme via `X-Forwarded-Proto`. Honoring it is restricted to the http→https
82
+ * UPGRADE of the SAME host (never a downgrade, never a host change), so a
83
+ * spoofed header can at worst derive an `iss` the kernel's JWKS check then
84
+ * fails — it can never make this worker speak for another origin.
85
+ */
86
+ export function clientOrigin(url: URL, request: Request): string {
87
+ if (url.protocol !== 'http:') return url.origin
88
+ const forwarded = request.headers.get('x-forwarded-proto')
89
+ // Multiple proxies append: "https, http" — the first hop is the client-facing one.
90
+ const scheme = forwarded?.split(',')[0]?.trim().toLowerCase()
91
+ return scheme === 'https' ? `https://${url.host}` : url.origin
92
+ }
93
+
70
94
  export function createWorkerEntry<TDeps>(config: WorkerEntryConfig<TDeps>): WorkerEntry<TDeps> {
71
- let cache: { url: string; origin: string; app: App } | null = null
95
+ // Cache the built app per distinct resolved URL plural and bounded. On the
96
+ // request-origin fallback the URL legitimately alternates for one worker
97
+ // (direct http hits vs https-upgraded tunnel hits, workers.dev + custom
98
+ // domain), and a single slot would tear down and rebuild the whole app on
99
+ // every alternation. The bound caps abuse via attacker-minted Host /
100
+ // X-Forwarded-Proto values on that same fallback path.
101
+ const MAX_CACHED_APPS = 4
102
+ const apps = new Map<string, { origin: string; app: App }>()
72
103
  let self: Fetcher | null = null
73
104
 
74
105
  function getApp(url: string, env: TDeps): App {
75
- if (cache && cache.url === url) return cache.app
106
+ const cached = apps.get(url)
107
+ if (cached) return cached.app
76
108
  const { app } = createRemoteServer<TDeps>(config.build(url, env))
77
- cache = { url, origin: new URL(url).origin, app }
109
+ if (apps.size >= MAX_CACHED_APPS) {
110
+ const oldest = apps.keys().next().value
111
+ if (oldest !== undefined) apps.delete(oldest)
112
+ }
113
+ apps.set(url, { origin: new URL(url).origin, app })
78
114
  return app
79
115
  }
80
116
 
@@ -87,11 +123,14 @@ export function createWorkerEntry<TDeps>(config: WorkerEntryConfig<TDeps>): Work
87
123
  if (config.selfBinding) {
88
124
  const originalFetch = globalThis.fetch
89
125
  globalThis.fetch = (async (input: RequestInfo | URL, init?: RequestInit) => {
90
- if (cache && self) {
126
+ if (apps.size > 0 && self) {
91
127
  const href =
92
128
  typeof input === 'string' ? input : input instanceof URL ? input.href : input.url
93
129
  try {
94
- if (new URL(href).origin === cache.origin) return self.fetch(new Request(input, init))
130
+ const origin = new URL(href).origin
131
+ for (const cached of apps.values()) {
132
+ if (cached.origin === origin) return self.fetch(new Request(input, init))
133
+ }
95
134
  } catch {
96
135
  // non-absolute URL — fall through to the original fetch
97
136
  }
@@ -112,7 +151,7 @@ export function createWorkerEntry<TDeps>(config: WorkerEntryConfig<TDeps>): Work
112
151
  if (handled !== undefined) return handled
113
152
  }
114
153
  const raw = config.resolveUrl
115
- ? config.resolveUrl(env, requestUrl!.origin)
154
+ ? config.resolveUrl(env, clientOrigin(requestUrl!, request))
116
155
  : requireEnv(env, 'WORKER_URL', "the worker's public serving URL (its iss identity)")
117
156
  const url = canonicalizeServingUrl(raw)
118
157
  const dispatched = config.rewriteRequest ? config.rewriteRequest(env, request) : request