@stratum-hq/sdk 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -52,12 +52,16 @@ app.get("/data", (req, res) => {
52
52
 
53
53
  ## Features
54
54
 
55
- - **`StratumClient`** — HTTP client for the control plane API (`resolveTenant`, `getTenantTree`, `createTenant`, `createWebhook`, `listRegions`, …) with a built-in LRU cache that auto-invalidates on mutations.
55
+ - **`StratumClient`** — HTTP client for the control plane API (`resolveTenant`, `getTenantTree`, `createTenant`, `createWebhook`, `listRegions`, …) with a built-in LRU cache. Mutations made through the client invalidate affected entries (a move clears the whole cache); changes made elsewhere, such as a suspension or a config or permission change, are picked up when the entry expires, so the cache TTL (`cache.ttlMs`, default 60s) bounds how stale a context can be.
56
56
  - **`expressMiddleware` / `fastifyPlugin`** — resolve the tenant from a JWT claim, `X-Tenant-ID` header, or custom resolvers (tried in that order), then populate `req.tenant`.
57
57
  - **AsyncLocalStorage context** — `getTenantContext()` and `runWithTenantContext()` make the resolved context available to services that never see the request object.
58
58
  - **Custom resolvers** — supply async functions (e.g. subdomain- or query-based) via the `resolvers` option.
59
59
 
60
- JWT resolution activates only when `jwtSecret` or `jwtVerify` is provided; otherwise Bearer tokens are ignored. If no tenant is found, the middleware returns `400 MISSING_TENANT`.
60
+ JWT resolution activates only when `jwtSecret` or `jwtVerify` is provided; otherwise Bearer tokens are ignored. When it is active, the verified JWT is the tenant binding: a Bearer token that fails verification is rejected with `401 INVALID_TOKEN`, and the tenant header is not read unless you set `trustTenantHeader: true`. If no tenant is found, the middleware returns `400 MISSING_TENANT`.
61
+
62
+ `jwtSecret` verifies HS256 tokens with [`jsonwebtoken`](https://www.npmjs.com/package/jsonwebtoken), an optional peer dependency: install it alongside the SDK (`npm install jsonwebtoken`) or pass `jwtVerify` instead. The middleware throws at construction if `jwtSecret` is set and `jsonwebtoken` cannot be loaded.
63
+
64
+ `headerName` replaces the default `X-Tenant-ID` header: when it is set, only that header is read.
61
65
 
62
66
  ## Error Handling
63
67
 
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
package/dist/client.js CHANGED
@@ -3,6 +3,40 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.StratumClient = void 0;
4
4
  const core_1 = require("@stratum-hq/core");
5
5
  const cache_js_1 = require("./cache.js");
6
+ /**
7
+ * Encode an ID for use as a single URL path segment. Dot segments are refused
8
+ * because URL parsing would resolve them against the surrounding path.
9
+ */
10
+ function pathSegment(id) {
11
+ if (id === "" || id === "." || id === "..") {
12
+ throw new Error("Invalid identifier");
13
+ }
14
+ return encodeURIComponent(id);
15
+ }
16
+ function cacheKey(tenantId) {
17
+ return tenantId.toLowerCase();
18
+ }
19
+ function isObject(value) {
20
+ return typeof value === "object" && value !== null && !Array.isArray(value);
21
+ }
22
+ /**
23
+ * Check that a /context response is a ResolvedTenantContext for the requested
24
+ * tenant. Anything else fails closed rather than being bound as the request's
25
+ * tenant.
26
+ */
27
+ function assertResolvedTenantContext(value, tenantId) {
28
+ const ok = isObject(value) &&
29
+ typeof value["tenant_id"] === "string" &&
30
+ value["tenant_id"].toLowerCase() === tenantId.toLowerCase() &&
31
+ typeof value["ancestry_path"] === "string" &&
32
+ typeof value["depth"] === "number" &&
33
+ isObject(value["resolved_config"]) &&
34
+ isObject(value["resolved_permissions"]) &&
35
+ typeof value["isolation_strategy"] === "string";
36
+ if (!ok) {
37
+ throw new Error("Control plane returned an invalid tenant context");
38
+ }
39
+ }
6
40
  class StratumClient {
7
41
  baseUrl;
8
42
  apiKey;
@@ -45,20 +79,25 @@ class StratumClient {
45
79
  return response.json();
46
80
  }
47
81
  async resolveTenant(tenantId) {
82
+ if (tenantId === "" || tenantId === "." || tenantId === "..") {
83
+ throw new core_1.TenantNotFoundError(tenantId);
84
+ }
85
+ const path = `/api/v1/tenants/${pathSegment(tenantId)}/context`;
48
86
  if (this.cacheEnabled) {
49
- const cached = this.cache.get(tenantId);
87
+ const cached = this.cache.get(cacheKey(tenantId));
50
88
  if (cached)
51
89
  return cached;
52
90
  }
53
- const context = await this.fetch(`/api/v1/tenants/${tenantId}/context`);
91
+ const context = await this.fetch(path);
92
+ assertResolvedTenantContext(context, tenantId);
54
93
  if (this.cacheEnabled) {
55
- this.cache.set(tenantId, context);
94
+ this.cache.set(cacheKey(tenantId), context);
56
95
  }
57
96
  return context;
58
97
  }
59
98
  async getTenantTree(rootId) {
60
99
  if (rootId) {
61
- return this.fetch(`/api/v1/tenants/${rootId}/descendants`);
100
+ return this.fetch(`/api/v1/tenants/${pathSegment(rootId)}/descendants`);
62
101
  }
63
102
  const result = await this.fetch(`/api/v1/tenants`);
64
103
  return result.data;
@@ -70,38 +109,39 @@ class StratumClient {
70
109
  });
71
110
  }
72
111
  async getTenant(tenantId) {
73
- return this.fetch(`/api/v1/tenants/${tenantId}`);
112
+ return this.fetch(`/api/v1/tenants/${pathSegment(tenantId)}`);
74
113
  }
75
114
  async updateTenant(tenantId, input) {
76
- const node = await this.fetch(`/api/v1/tenants/${tenantId}`, {
115
+ const node = await this.fetch(`/api/v1/tenants/${pathSegment(tenantId)}`, {
77
116
  method: "PATCH",
78
117
  body: JSON.stringify(input),
79
118
  });
80
- this.cache.invalidate(tenantId);
119
+ this.cache.invalidate(cacheKey(tenantId));
81
120
  return node;
82
121
  }
83
122
  async moveTenant(tenantId, input) {
84
- const node = await this.fetch(`/api/v1/tenants/${tenantId}/move`, {
123
+ const node = await this.fetch(`/api/v1/tenants/${pathSegment(tenantId)}/move`, {
85
124
  method: "POST",
86
125
  body: JSON.stringify(input),
87
126
  });
88
- this.cache.invalidate(tenantId);
127
+ // Descendants' cached ancestry, config and permissions change with the move.
128
+ this.cache.clear();
89
129
  return node;
90
130
  }
91
131
  async archiveTenant(tenantId) {
92
- await this.fetch(`/api/v1/tenants/${tenantId}`, {
132
+ await this.fetch(`/api/v1/tenants/${pathSegment(tenantId)}`, {
93
133
  method: "DELETE",
94
134
  });
95
- this.cache.invalidate(tenantId);
135
+ this.cache.invalidate(cacheKey(tenantId));
96
136
  }
97
137
  async deleteTenant(tenantId) {
98
- await this.fetch(`/api/v1/tenants/${tenantId}`, {
138
+ await this.fetch(`/api/v1/tenants/${pathSegment(tenantId)}`, {
99
139
  method: "DELETE",
100
140
  });
101
- this.cache.invalidate(tenantId);
141
+ this.cache.invalidate(cacheKey(tenantId));
102
142
  }
103
143
  invalidateCache(tenantId) {
104
- this.cache.invalidate(tenantId);
144
+ this.cache.invalidate(cacheKey(tenantId));
105
145
  }
106
146
  clearCache() {
107
147
  this.cache.clear();
@@ -119,21 +159,21 @@ class StratumClient {
119
159
  return this.fetch(path);
120
160
  }
121
161
  async getWebhook(id) {
122
- return this.fetch(`/api/v1/webhooks/${id}`);
162
+ return this.fetch(`/api/v1/webhooks/${pathSegment(id)}`);
123
163
  }
124
164
  async updateWebhook(id, input) {
125
- return this.fetch(`/api/v1/webhooks/${id}`, {
165
+ return this.fetch(`/api/v1/webhooks/${pathSegment(id)}`, {
126
166
  method: "PATCH",
127
167
  body: JSON.stringify(input),
128
168
  });
129
169
  }
130
170
  async deleteWebhook(id) {
131
- await this.fetch(`/api/v1/webhooks/${id}`, {
171
+ await this.fetch(`/api/v1/webhooks/${pathSegment(id)}`, {
132
172
  method: "DELETE",
133
173
  });
134
174
  }
135
175
  async rotateApiKey(keyId, name) {
136
- return this.fetch(`/api/v1/api-keys/${keyId}/rotate`, {
176
+ return this.fetch(`/api/v1/api-keys/${pathSegment(keyId)}/rotate`, {
137
177
  method: "POST",
138
178
  body: JSON.stringify(name ? { name } : {}),
139
179
  });
@@ -161,13 +201,13 @@ class StratumClient {
161
201
  });
162
202
  }
163
203
  async updateRegion(id, input) {
164
- return this.fetch(`/api/v1/regions/${id}`, {
204
+ return this.fetch(`/api/v1/regions/${pathSegment(id)}`, {
165
205
  method: "PATCH",
166
206
  body: JSON.stringify(input),
167
207
  });
168
208
  }
169
209
  async deleteRegion(id) {
170
- await this.fetch(`/api/v1/regions/${id}`, {
210
+ await this.fetch(`/api/v1/regions/${pathSegment(id)}`, {
171
211
  method: "DELETE",
172
212
  });
173
213
  }
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,11 +1,21 @@
1
1
  import { StratumClient } from "./client.js";
2
2
  import type { StratumClientOptions } from "./client.js";
3
+ import { fastifyPlugin } from "./middleware/fastify.js";
3
4
  import { getTenantContext, runWithTenantContext } from "./context.js";
4
5
  import type { MiddlewareOptions } from "./types.js";
5
6
  export declare function stratum(options: StratumClientOptions): {
6
7
  client: StratumClient;
7
- middleware: (opts?: MiddlewareOptions) => (req: any, res: any, next: any) => Promise<void>;
8
- plugin: (opts?: MiddlewareOptions) => (fastify: any, _opts: any, done: any) => void;
8
+ middleware: (opts?: MiddlewareOptions) => (req: {
9
+ headers?: Record<string, string | string[] | undefined>;
10
+ tenant?: unknown;
11
+ impersonating?: boolean;
12
+ originalTenantId?: string | null;
13
+ }, res: {
14
+ status(code: number): {
15
+ json(body: unknown): void;
16
+ };
17
+ }, next: (err?: unknown) => void) => Promise<void>;
18
+ plugin: (opts?: MiddlewareOptions) => (fastify: Parameters<typeof fastifyPlugin>[0], _opts: unknown, done: Parameters<typeof fastifyPlugin>[2]) => void;
9
19
  getTenantContext: typeof getTenantContext;
10
20
  runWithTenantContext: typeof runWithTenantContext;
11
21
  };
@@ -15,7 +25,9 @@ export { getTenantContext, runWithTenantContext, setTenantContext } from "./cont
15
25
  export { expressMiddleware } from "./middleware/express.js";
16
26
  export { fastifyPlugin } from "./middleware/fastify.js";
17
27
  export { resolveFromHeader } from "./resolvers/header.js";
18
- export { resolveFromJwt } from "./resolvers/jwt.js";
28
+ export { resolveFromJwt, assertJwtSupport } from "./resolvers/jwt.js";
29
+ export { resolveTenantId } from "./resolvers/resolve.js";
30
+ export type { TenantIdResolution } from "./resolvers/resolve.js";
19
31
  export type { TenantResolver } from "./resolvers/custom.js";
20
32
  export type { MiddlewareOptions } from "./types.js";
21
33
  export type { ResolvedTenantContext, TenantNode, CreateTenantInput, UpdateTenantInput, MoveTenantInput, ResolvedPermission, } from "@stratum-hq/core";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAGxD,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACtE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpD,wBAAgB,OAAO,CAAC,OAAO,EAAE,oBAAoB;;wBAI7B,iBAAiB;oBACrB,iBAAiB,MAC9B,SAAS,GAAG,EAAE,OAAO,GAAG,EAAE,MAAM,GAAG;;;EAKzC;AAGD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,YAAY,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACxF,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,YAAY,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,YAAY,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAGpD,YAAY,EACV,qBAAqB,EACrB,UAAU,EACV,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,kBAAkB,GACnB,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAExD,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACtE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpD,wBAAgB,OAAO,CAAC,OAAO,EAAE,oBAAoB;;wBAI7B,iBAAiB;;;;;;;;;;oBACrB,iBAAiB,eAEpB,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC,CAAC,CAAC,SACrC,OAAO,QACR,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC,CAAC,CAAC;;;EAShD;AAGD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,YAAY,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACxF,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,YAAY,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACjE,YAAY,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,YAAY,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAGpD,YAAY,EACV,qBAAqB,EACrB,UAAU,EACV,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,kBAAkB,GACnB,MAAM,kBAAkB,CAAC"}
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.resolveFromJwt = exports.resolveFromHeader = exports.fastifyPlugin = exports.expressMiddleware = exports.setTenantContext = exports.runWithTenantContext = exports.getTenantContext = exports.StratumClient = void 0;
3
+ exports.resolveTenantId = exports.assertJwtSupport = exports.resolveFromJwt = exports.resolveFromHeader = exports.fastifyPlugin = exports.expressMiddleware = exports.setTenantContext = exports.runWithTenantContext = exports.getTenantContext = exports.StratumClient = void 0;
4
4
  exports.stratum = stratum;
5
5
  const client_js_1 = require("./client.js");
6
6
  const express_js_1 = require("./middleware/express.js");
@@ -11,7 +11,12 @@ function stratum(options) {
11
11
  return {
12
12
  client,
13
13
  middleware: (opts) => (0, express_js_1.expressMiddleware)(client, opts),
14
- plugin: (opts) => (fastify, _opts, done) => (0, fastify_js_1.fastifyPlugin)(fastify, { client, ...opts }, done),
14
+ plugin: (opts) => {
15
+ const plugin = (fastify, _opts, done) => (0, fastify_js_1.fastifyPlugin)(fastify, { client, ...opts }, done);
16
+ // Same non-encapsulated registration as fastifyPlugin itself.
17
+ plugin[Symbol.for("skip-override")] = true;
18
+ return plugin;
19
+ },
15
20
  getTenantContext: context_js_1.getTenantContext,
16
21
  runWithTenantContext: context_js_1.runWithTenantContext,
17
22
  };
@@ -31,4 +36,7 @@ var header_js_1 = require("./resolvers/header.js");
31
36
  Object.defineProperty(exports, "resolveFromHeader", { enumerable: true, get: function () { return header_js_1.resolveFromHeader; } });
32
37
  var jwt_js_1 = require("./resolvers/jwt.js");
33
38
  Object.defineProperty(exports, "resolveFromJwt", { enumerable: true, get: function () { return jwt_js_1.resolveFromJwt; } });
39
+ Object.defineProperty(exports, "assertJwtSupport", { enumerable: true, get: function () { return jwt_js_1.assertJwtSupport; } });
40
+ var resolve_js_1 = require("./resolvers/resolve.js");
41
+ Object.defineProperty(exports, "resolveTenantId", { enumerable: true, get: function () { return resolve_js_1.resolveTenantId; } });
34
42
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAOA,0BAWC;AAlBD,2CAA4C;AAE5C,wDAA4D;AAC5D,wDAAwD;AACxD,6CAAsE;AAGtE,SAAgB,OAAO,CAAC,OAA6B;IACnD,MAAM,MAAM,GAAG,IAAI,yBAAa,CAAC,OAAO,CAAC,CAAC;IAC1C,OAAO;QACL,MAAM;QACN,UAAU,EAAE,CAAC,IAAwB,EAAE,EAAE,CAAC,IAAA,8BAAiB,EAAC,MAAM,EAAE,IAAI,CAAC;QACzE,MAAM,EAAE,CAAC,IAAwB,EAAE,EAAE,CACnC,CAAC,OAAY,EAAE,KAAU,EAAE,IAAS,EAAE,EAAE,CACtC,IAAA,0BAAa,EAAC,OAAO,EAAE,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,EAAE,IAAI,CAAC;QACrD,gBAAgB,EAAhB,6BAAgB;QAChB,oBAAoB,EAApB,iCAAoB;KACrB,CAAC;AACJ,CAAC;AAED,iCAAiC;AACjC,yCAA4C;AAAnC,0GAAA,aAAa,OAAA;AAEtB,2CAAwF;AAA/E,8GAAA,gBAAgB,OAAA;AAAE,kHAAA,oBAAoB,OAAA;AAAE,8GAAA,gBAAgB,OAAA;AACjE,sDAA4D;AAAnD,+GAAA,iBAAiB,OAAA;AAC1B,sDAAwD;AAA/C,2GAAA,aAAa,OAAA;AACtB,mDAA0D;AAAjD,8GAAA,iBAAiB,OAAA;AAC1B,6CAAoD;AAA3C,wGAAA,cAAc,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAOA,0BAkBC;AAzBD,2CAA4C;AAE5C,wDAA4D;AAC5D,wDAAwD;AACxD,6CAAsE;AAGtE,SAAgB,OAAO,CAAC,OAA6B;IACnD,MAAM,MAAM,GAAG,IAAI,yBAAa,CAAC,OAAO,CAAC,CAAC;IAC1C,OAAO;QACL,MAAM;QACN,UAAU,EAAE,CAAC,IAAwB,EAAE,EAAE,CAAC,IAAA,8BAAiB,EAAC,MAAM,EAAE,IAAI,CAAC;QACzE,MAAM,EAAE,CAAC,IAAwB,EAAE,EAAE;YACnC,MAAM,MAAM,GAAG,CACb,OAA4C,EAC5C,KAAc,EACd,IAAyC,EACzC,EAAE,CAAC,IAAA,0BAAa,EAAC,OAAO,EAAE,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,EAAE,IAAI,CAAC,CAAC;YACvD,8DAA8D;YAC7D,MAA6C,CAAC,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,GAAG,IAAI,CAAC;YACnF,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,gBAAgB,EAAhB,6BAAgB;QAChB,oBAAoB,EAApB,iCAAoB;KACrB,CAAC;AACJ,CAAC;AAED,iCAAiC;AACjC,yCAA4C;AAAnC,0GAAA,aAAa,OAAA;AAEtB,2CAAwF;AAA/E,8GAAA,gBAAgB,OAAA;AAAE,kHAAA,oBAAoB,OAAA;AAAE,8GAAA,gBAAgB,OAAA;AACjE,sDAA4D;AAAnD,+GAAA,iBAAiB,OAAA;AAC1B,sDAAwD;AAA/C,2GAAA,aAAa,OAAA;AACtB,mDAA0D;AAAjD,8GAAA,iBAAiB,OAAA;AAC1B,6CAAsE;AAA7D,wGAAA,cAAc,OAAA;AAAE,0GAAA,gBAAgB,OAAA;AACzC,qDAAyD;AAAhD,6GAAA,eAAe,OAAA"}
@@ -1,4 +1,17 @@
1
1
  import type { StratumClient } from "../client.js";
2
2
  import type { MiddlewareOptions } from "../types.js";
3
- export declare function expressMiddleware(client: StratumClient, options?: MiddlewareOptions): (req: any, res: any, next: any) => Promise<void>;
3
+ type NextFn = (err?: unknown) => void;
4
+ type ExpressRequestLike = {
5
+ headers?: Record<string, string | string[] | undefined>;
6
+ tenant?: unknown;
7
+ impersonating?: boolean;
8
+ originalTenantId?: string | null;
9
+ };
10
+ type ExpressResponseLike = {
11
+ status(code: number): {
12
+ json(body: unknown): void;
13
+ };
14
+ };
15
+ export declare function expressMiddleware(client: StratumClient, options?: MiddlewareOptions): (req: ExpressRequestLike, res: ExpressResponseLike, next: NextFn) => Promise<void>;
16
+ export {};
4
17
  //# sourceMappingURL=express.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"express.d.ts","sourceRoot":"","sources":["../../src/middleware/express.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAKrD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,iBAAiB,IACpE,KAAK,GAAG,EAAE,KAAK,GAAG,EAAE,MAAM,GAAG,KAAG,OAAO,CAAC,IAAI,CAAC,CAqF5D"}
1
+ {"version":3,"file":"express.d.ts","sourceRoot":"","sources":["../../src/middleware/express.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAOrD,KAAK,MAAM,GAAG,CAAC,GAAG,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;AAEtC,KAAK,kBAAkB,GAAG;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;IACxD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC,CAAC;AAEF,KAAK,mBAAmB,GAAG;IACzB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG;QAAE,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAAA;KAAE,CAAC;CACrD,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,iBAAiB,IAEpE,KAAK,kBAAkB,EAAE,KAAK,mBAAmB,EAAE,MAAM,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC,CAyE9F"}
@@ -4,32 +4,22 @@ exports.expressMiddleware = expressMiddleware;
4
4
  const core_1 = require("@stratum-hq/core");
5
5
  const context_js_1 = require("../context.js");
6
6
  const jwt_js_1 = require("../resolvers/jwt.js");
7
- const header_js_1 = require("../resolvers/header.js");
7
+ const resolve_js_1 = require("../resolvers/resolve.js");
8
8
  function expressMiddleware(client, options) {
9
+ (0, jwt_js_1.assertJwtSupport)(options);
9
10
  return async (req, res, next) => {
10
11
  try {
11
12
  // Resolve tenant ID: JWT → header → custom resolvers
12
- let tenantId = null;
13
- tenantId = (0, jwt_js_1.resolveFromJwt)(req, options?.jwtClaimPath, {
14
- secret: options?.jwtSecret,
15
- verify: options?.jwtVerify,
16
- });
17
- if (!tenantId) {
18
- tenantId = (0, header_js_1.resolveFromHeader)(req);
19
- }
20
- if (!tenantId && options?.resolvers) {
21
- for (const resolver of options.resolvers) {
22
- const result = await resolver.resolve(req);
23
- if (result) {
24
- tenantId = result;
25
- break;
26
- }
27
- }
13
+ const resolution = await (0, resolve_js_1.resolveTenantId)(req, options);
14
+ if (resolution.status === "invalid_token") {
15
+ res.status(401).json({ error: { code: "INVALID_TOKEN", message: "Bearer token could not be verified" } });
16
+ return;
28
17
  }
29
- if (!tenantId) {
18
+ if (resolution.status === "missing") {
30
19
  res.status(400).json({ error: { code: "MISSING_TENANT", message: "Tenant ID could not be resolved from request" } });
31
20
  return;
32
21
  }
22
+ const tenantId = resolution.tenantId;
33
23
  let context;
34
24
  try {
35
25
  context = await client.resolveTenant(tenantId);
@@ -1 +1 @@
1
- {"version":3,"file":"express.js","sourceRoot":"","sources":["../../src/middleware/express.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"express.js","sourceRoot":"","sources":["../../src/middleware/express.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,23 @@
1
1
  import type { StratumClient } from "../client.js";
2
2
  import type { MiddlewareOptions } from "../types.js";
3
- export declare function fastifyPlugin(fastify: any, options: {
3
+ type DoneFn = (err?: unknown) => void;
4
+ interface FastifyRequestLike {
5
+ headers?: Record<string, string | string[] | undefined>;
6
+ tenant?: unknown;
7
+ impersonating?: boolean;
8
+ originalTenantId?: string | null;
9
+ }
10
+ interface FastifyReplyLike {
11
+ status(code: number): {
12
+ send(body: unknown): void;
13
+ };
14
+ }
15
+ interface FastifyLike {
16
+ decorateRequest(name: string, value: unknown): void;
17
+ addHook(event: string, handler: (request: FastifyRequestLike, reply: FastifyReplyLike, done: DoneFn) => void): void;
18
+ }
19
+ export declare function fastifyPlugin(fastify: FastifyLike, options: {
4
20
  client: StratumClient;
5
- } & MiddlewareOptions, done: any): void;
21
+ } & MiddlewareOptions, done: DoneFn): void;
22
+ export {};
6
23
  //# sourceMappingURL=fastify.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"fastify.d.ts","sourceRoot":"","sources":["../../src/middleware/fastify.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAKrD,wBAAgB,aAAa,CAC3B,OAAO,EAAE,GAAG,EACZ,OAAO,EAAE;IAAE,MAAM,EAAE,aAAa,CAAA;CAAE,GAAG,iBAAiB,EACtD,IAAI,EAAE,GAAG,GACR,IAAI,CA0FN"}
1
+ {"version":3,"file":"fastify.d.ts","sourceRoot":"","sources":["../../src/middleware/fastify.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAOrD,KAAK,MAAM,GAAG,CAAC,GAAG,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;AAEtC,UAAU,kBAAkB;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;IACxD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED,UAAU,gBAAgB;IACxB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG;QAAE,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAAA;KAAE,CAAC;CACrD;AAED,UAAU,WAAW;IACnB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IACpD,OAAO,CACL,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,CAAC,OAAO,EAAE,kBAAkB,EAAE,KAAK,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,GACpF,IAAI,CAAC;CACT;AAED,wBAAgB,aAAa,CAC3B,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE;IAAE,MAAM,EAAE,aAAa,CAAA;CAAE,GAAG,iBAAiB,EACtD,IAAI,EAAE,MAAM,GACX,IAAI,CA+EN"}
@@ -4,36 +4,26 @@ exports.fastifyPlugin = fastifyPlugin;
4
4
  const core_1 = require("@stratum-hq/core");
5
5
  const context_js_1 = require("../context.js");
6
6
  const jwt_js_1 = require("../resolvers/jwt.js");
7
- const header_js_1 = require("../resolvers/header.js");
7
+ const resolve_js_1 = require("../resolvers/resolve.js");
8
8
  function fastifyPlugin(fastify, options, done) {
9
9
  const { client, ...middlewareOptions } = options;
10
+ (0, jwt_js_1.assertJwtSupport)(middlewareOptions);
10
11
  fastify.decorateRequest("tenant", null);
11
12
  fastify.decorateRequest("impersonating", false);
12
13
  fastify.decorateRequest("originalTenantId", null);
13
14
  fastify.addHook("onRequest", (request, reply, done) => {
14
- // Resolve tenant ID: JWT → header → custom resolvers
15
- let tenantId = null;
16
- tenantId = (0, jwt_js_1.resolveFromJwt)(request, middlewareOptions.jwtClaimPath, {
17
- secret: middlewareOptions.jwtSecret,
18
- verify: middlewareOptions.jwtVerify,
19
- });
20
- if (!tenantId) {
21
- tenantId = (0, header_js_1.resolveFromHeader)(request);
22
- }
23
15
  const resolveAndRun = async () => {
24
- if (!tenantId && middlewareOptions.resolvers) {
25
- for (const resolver of middlewareOptions.resolvers) {
26
- const result = await resolver.resolve(request);
27
- if (result) {
28
- tenantId = result;
29
- break;
30
- }
31
- }
16
+ // Resolve tenant ID: JWT → header → custom resolvers
17
+ const resolution = await (0, resolve_js_1.resolveTenantId)(request, middlewareOptions);
18
+ if (resolution.status === "invalid_token") {
19
+ reply.status(401).send({ error: { code: "INVALID_TOKEN", message: "Bearer token could not be verified" } });
20
+ return;
32
21
  }
33
- if (!tenantId) {
22
+ if (resolution.status === "missing") {
34
23
  reply.status(400).send({ error: { code: "MISSING_TENANT", message: "Tenant ID could not be resolved from request" } });
35
24
  return;
36
25
  }
26
+ const tenantId = resolution.tenantId;
37
27
  let context;
38
28
  try {
39
29
  context = await client.resolveTenant(tenantId);
@@ -81,4 +71,8 @@ function fastifyPlugin(fastify, options, done) {
81
71
  });
82
72
  done();
83
73
  }
74
+ // Register the hook and decorators on the instance that calls
75
+ // `register(fastifyPlugin)`, not in an encapsulated child context, so routes
76
+ // declared on that instance run the tenant hook (the fastify-plugin convention).
77
+ fastifyPlugin[Symbol.for("skip-override")] = true;
84
78
  //# sourceMappingURL=fastify.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"fastify.js","sourceRoot":"","sources":["../../src/middleware/fastify.ts"],"names":[],"mappings":";;AAQA,sCA8FC;AAtGD,2CAAuD;AAIvD,8CAAqD;AACrD,gDAAqD;AACrD,sDAA2D;AAE3D,SAAgB,aAAa,CAC3B,OAAY,EACZ,OAAsD,EACtD,IAAS;IAET,MAAM,EAAE,MAAM,EAAE,GAAG,iBAAiB,EAAE,GAAG,OAAO,CAAC;IAEjD,OAAO,CAAC,eAAe,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACxC,OAAO,CAAC,eAAe,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;IAChD,OAAO,CAAC,eAAe,CAAC,kBAAkB,EAAE,IAAI,CAAC,CAAC;IAElD,OAAO,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,OAAY,EAAE,KAAU,EAAE,IAAS,EAAE,EAAE;QACnE,qDAAqD;QACrD,IAAI,QAAQ,GAAkB,IAAI,CAAC;QAEnC,QAAQ,GAAG,IAAA,uBAAc,EAAC,OAAO,EAAE,iBAAiB,CAAC,YAAY,EAAE;YACjE,MAAM,EAAE,iBAAiB,CAAC,SAAS;YACnC,MAAM,EAAE,iBAAiB,CAAC,SAAS;SACpC,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,QAAQ,GAAG,IAAA,6BAAiB,EAAC,OAAO,CAAC,CAAC;QACxC,CAAC;QAED,MAAM,aAAa,GAAG,KAAK,IAAI,EAAE;YAC/B,IAAI,CAAC,QAAQ,IAAI,iBAAiB,CAAC,SAAS,EAAE,CAAC;gBAC7C,KAAK,MAAM,QAAQ,IAAI,iBAAiB,CAAC,SAAS,EAAE,CAAC;oBACnD,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;oBAC/C,IAAI,MAAM,EAAE,CAAC;wBACX,QAAQ,GAAG,MAAM,CAAC;wBAClB,MAAM;oBACR,CAAC;gBACH,CAAC;YACH,CAAC;YAED,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,8CAA8C,EAAE,EAAE,CAAC,CAAC;gBACvH,OAAO;YACT,CAAC;YAED,IAAI,OAA8B,CAAC;YACnC,IAAI,CAAC;gBACH,OAAO,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;YACjD,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,GAAG,YAAY,0BAAmB,EAAE,CAAC;oBACvC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE,OAAO,EAAE,qBAAqB,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;oBAC1G,OAAO;gBACT,CAAC;gBACD,IAAI,iBAAiB,CAAC,OAAO,IAAI,GAAG,YAAY,KAAK,EAAE,CAAC;oBACtD,iBAAiB,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;gBAC1C,CAAC;gBACD,MAAM,GAAG,CAAC;YACZ,CAAC;YAED,OAAO,CAAC,MAAM,GAAG,OAAO,CAAC;YACzB,OAAO,CAAC,aAAa,GAAG,KAAK,CAAC;YAE9B,uDAAuD;YACvD,IAAI,iBAAiB,CAAC,aAAa,EAAE,OAAO,EAAE,CAAC;gBAC7C,MAAM,iBAAiB,GAAG,CAAC,iBAAiB,CAAC,aAAa,CAAC,UAAU,IAAI,sBAAsB,CAAC,CAAC,WAAW,EAAE,CAAC;gBAC/G,MAAM,mBAAmB,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,iBAAiB,CAAuB,CAAC;gBAEvF,IAAI,mBAAmB,IAAI,mBAAmB,KAAK,QAAQ,EAAE,CAAC;oBAC5D,MAAM,UAAU,GAAG,MAAM,iBAAiB,CAAC,aAAa,CAAC,SAAS,CAAC,OAAO,EAAE,QAAQ,EAAE,mBAAmB,CAAC,CAAC;oBAC3G,IAAI,CAAC,UAAU,EAAE,CAAC;wBAChB,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;4BACrB,KAAK,EAAE;gCACL,IAAI,EAAE,sBAAsB;gCAC5B,OAAO,EAAE,2CAA2C;6BACrD;yBACF,CAAC,CAAC;wBACH,OAAO;oBACT,CAAC;oBAED,MAAM,mBAAmB,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,mBAAmB,CAAC,CAAC;oBAC5E,OAAO,CAAC,MAAM,GAAG,mBAAmB,CAAC;oBACrC,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;oBAC7B,OAAO,CAAC,gBAAgB,GAAG,QAAQ,CAAC;oBAEpC,iBAAiB,CAAC,aAAa,CAAC,aAAa,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,mBAAmB,CAAC,CAAC;oBAExF,IAAA,iCAAoB,EAAC,mBAAmB,EAAE,IAAI,CAAC,CAAC;oBAChD,OAAO;gBACT,CAAC;YACH,CAAC;YAED,4EAA4E;YAC5E,IAAA,iCAAoB,EAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QACtC,CAAC,CAAC;QAEF,aAAa,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;IAEH,IAAI,EAAE,CAAC;AACT,CAAC"}
1
+ {"version":3,"file":"fastify.js","sourceRoot":"","sources":["../../src/middleware/fastify.ts"],"names":[],"mappings":"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"}
@@ -1,2 +1,6 @@
1
- export declare function resolveFromHeader(req: unknown): string | null;
1
+ /**
2
+ * Read the tenant ID from a request header. When `headerName` is given, only
3
+ * that header is read; otherwise the default X-Tenant-ID header is used.
4
+ */
5
+ export declare function resolveFromHeader(req: unknown, headerName?: string): string | null;
2
6
  //# sourceMappingURL=header.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"header.d.ts","sourceRoot":"","sources":["../../src/resolvers/header.ts"],"names":[],"mappings":"AAEA,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAO7D"}
1
+ {"version":3,"file":"header.d.ts","sourceRoot":"","sources":["../../src/resolvers/header.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CASlF"}
@@ -2,12 +2,18 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.resolveFromHeader = resolveFromHeader;
4
4
  const core_1 = require("@stratum-hq/core");
5
- function resolveFromHeader(req) {
5
+ /**
6
+ * Read the tenant ID from a request header. When `headerName` is given, only
7
+ * that header is read; otherwise the default X-Tenant-ID header is used.
8
+ */
9
+ function resolveFromHeader(req, headerName) {
6
10
  const r = req;
7
11
  const headers = r["headers"];
8
12
  if (!headers)
9
13
  return null;
10
- const value = headers[core_1.TENANT_HEADER.toLowerCase()] ?? headers[core_1.TENANT_HEADER];
14
+ const value = headerName
15
+ ? headers[headerName.toLowerCase()]
16
+ : headers[core_1.TENANT_HEADER.toLowerCase()] ?? headers[core_1.TENANT_HEADER];
11
17
  if (!value)
12
18
  return null;
13
19
  return Array.isArray(value) ? value[0] ?? null : value;
@@ -1 +1 @@
1
- {"version":3,"file":"header.js","sourceRoot":"","sources":["../../src/resolvers/header.ts"],"names":[],"mappings":";;AAEA,8CAOC;AATD,2CAAiD;AAEjD,SAAgB,iBAAiB,CAAC,GAAY;IAC5C,MAAM,CAAC,GAAG,GAA8B,CAAC;IACzC,MAAM,OAAO,GAAG,CAAC,CAAC,SAAS,CAA8D,CAAC;IAC1F,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,MAAM,KAAK,GAAG,OAAO,CAAC,oBAAa,CAAC,WAAW,EAAE,CAAC,IAAI,OAAO,CAAC,oBAAa,CAAC,CAAC;IAC7E,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC;AACzD,CAAC"}
1
+ {"version":3,"file":"header.js","sourceRoot":"","sources":["../../src/resolvers/header.ts"],"names":[],"mappings":";;AAMA,8CASC;AAfD,2CAAiD;AAEjD;;;GAGG;AACH,SAAgB,iBAAiB,CAAC,GAAY,EAAE,UAAmB;IACjE,MAAM,CAAC,GAAG,GAA8B,CAAC;IACzC,MAAM,OAAO,GAAG,CAAC,CAAC,SAAS,CAA8D,CAAC;IAC1F,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,MAAM,KAAK,GAAG,UAAU;QACtB,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC;QACnC,CAAC,CAAC,OAAO,CAAC,oBAAa,CAAC,WAAW,EAAE,CAAC,IAAI,OAAO,CAAC,oBAAa,CAAC,CAAC;IACnE,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC;AACzD,CAAC"}
@@ -2,5 +2,33 @@ export interface JwtResolverOptions {
2
2
  secret?: string;
3
3
  verify?: (token: string) => Record<string, unknown> | null;
4
4
  }
5
+ /**
6
+ * Throw if `jwtSecret` is configured without a `jwtVerify` function and the
7
+ * optional `jsonwebtoken` peer dependency cannot be loaded. Called when a
8
+ * middleware is constructed, so a missing module fails loudly at startup
9
+ * instead of making every token look unverifiable.
10
+ */
11
+ export declare function assertJwtSupport(options?: {
12
+ jwtSecret?: string;
13
+ jwtVerify?: unknown;
14
+ }): void;
15
+ /**
16
+ * Outcome of JWT tenant resolution:
17
+ * - `absent`: no bearer token, or no secret / verify function configured
18
+ * - `invalid`: a bearer token was sent but did not verify
19
+ * - `no_claim`: the token verified but carries no string tenant claim
20
+ * - `resolved`: the token verified and carries the tenant claim
21
+ */
22
+ export type JwtTenantResolution = {
23
+ status: "absent";
24
+ } | {
25
+ status: "invalid";
26
+ } | {
27
+ status: "no_claim";
28
+ } | {
29
+ status: "resolved";
30
+ tenantId: string;
31
+ };
32
+ export declare function resolveJwtTenant(req: unknown, claimPath?: string, options?: JwtResolverOptions): JwtTenantResolution;
5
33
  export declare function resolveFromJwt(req: unknown, claimPath?: string, options?: JwtResolverOptions): string | null;
6
34
  //# sourceMappingURL=jwt.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"jwt.d.ts","sourceRoot":"","sources":["../../src/resolvers/jwt.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC5D;AAcD,wBAAgB,cAAc,CAC5B,GAAG,EAAE,OAAO,EACZ,SAAS,GAAE,MAAoB,EAC/B,OAAO,CAAC,EAAE,kBAAkB,GAC3B,MAAM,GAAG,IAAI,CAuCf"}
1
+ {"version":3,"file":"jwt.d.ts","sourceRoot":"","sources":["../../src/resolvers/jwt.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC5D;AAkBD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAQ5F;AAgBD;;;;;;GAMG;AACH,MAAM,MAAM,mBAAmB,GAC3B;IAAE,MAAM,EAAE,QAAQ,CAAA;CAAE,GACpB;IAAE,MAAM,EAAE,SAAS,CAAA;CAAE,GACrB;IAAE,MAAM,EAAE,UAAU,CAAA;CAAE,GACtB;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7C,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,OAAO,EACZ,SAAS,GAAE,MAAoB,EAC/B,OAAO,CAAC,EAAE,kBAAkB,GAC3B,mBAAmB,CAuCrB;AAED,wBAAgB,cAAc,CAC5B,GAAG,EAAE,OAAO,EACZ,SAAS,GAAE,MAAoB,EAC/B,OAAO,CAAC,EAAE,kBAAkB,GAC3B,MAAM,GAAG,IAAI,CAGf"}
@@ -1,10 +1,43 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.assertJwtSupport = assertJwtSupport;
4
+ exports.resolveJwtTenant = resolveJwtTenant;
3
5
  exports.resolveFromJwt = resolveFromJwt;
4
- function verifyWithJsonwebtoken(token, secret) {
6
+ /**
7
+ * Load the optional `jsonwebtoken` peer dependency. Returns null only when the
8
+ * module is not installed; any other load failure is rethrown.
9
+ */
10
+ function loadJsonwebtoken() {
5
11
  try {
6
12
  // eslint-disable-next-line @typescript-eslint/no-require-imports
7
- const jwt = require("jsonwebtoken");
13
+ return require("jsonwebtoken");
14
+ }
15
+ catch (err) {
16
+ if (err.code === "MODULE_NOT_FOUND")
17
+ return null;
18
+ throw err;
19
+ }
20
+ }
21
+ /**
22
+ * Throw if `jwtSecret` is configured without a `jwtVerify` function and the
23
+ * optional `jsonwebtoken` peer dependency cannot be loaded. Called when a
24
+ * middleware is constructed, so a missing module fails loudly at startup
25
+ * instead of making every token look unverifiable.
26
+ */
27
+ function assertJwtSupport(options) {
28
+ if (!options?.jwtSecret || options.jwtVerify)
29
+ return;
30
+ if (!loadJsonwebtoken()) {
31
+ throw new Error("[stratum] jwtSecret is set but the optional peer dependency 'jsonwebtoken' could not be loaded. " +
32
+ "Install jsonwebtoken, or provide jwtVerify.");
33
+ }
34
+ }
35
+ function verifyWithJsonwebtoken(token, secret) {
36
+ const jwt = loadJsonwebtoken();
37
+ if (!jwt) {
38
+ throw new Error("[stratum] jwtSecret is set but the optional peer dependency 'jsonwebtoken' is not installed.");
39
+ }
40
+ try {
8
41
  const decoded = jwt.verify(token, secret, { algorithms: ["HS256"] });
9
42
  if (typeof decoded === "string")
10
43
  return null;
@@ -14,15 +47,15 @@ function verifyWithJsonwebtoken(token, secret) {
14
47
  return null;
15
48
  }
16
49
  }
17
- function resolveFromJwt(req, claimPath = "tenant_id", options) {
50
+ function resolveJwtTenant(req, claimPath = "tenant_id", options) {
18
51
  const r = req;
19
52
  const headers = r["headers"];
20
53
  if (!headers)
21
- return null;
54
+ return { status: "absent" };
22
55
  const authHeader = headers["authorization"];
23
56
  const auth = Array.isArray(authHeader) ? authHeader[0] : authHeader;
24
57
  if (!auth || !auth.startsWith("Bearer "))
25
- return null;
58
+ return { status: "absent" };
26
59
  const token = auth.slice(7);
27
60
  let claims = null;
28
61
  if (options?.verify) {
@@ -37,18 +70,22 @@ function resolveFromJwt(req, claimPath = "tenant_id", options) {
37
70
  // No secret or verify function provided — refuse to trust unsigned tokens
38
71
  console.warn("[stratum] JWT ignored: no jwtSecret or jwtVerify provided. " +
39
72
  "Configure middleware options to enable JWT tenant resolution.");
40
- return null;
73
+ return { status: "absent" };
41
74
  }
42
75
  if (!claims)
43
- return null;
76
+ return { status: "invalid" };
44
77
  // Support dotted claim paths like "stratum.tenant_id"
45
78
  const segments = claimPath.split(".");
46
79
  let current = claims;
47
80
  for (const seg of segments) {
48
81
  if (current == null || typeof current !== "object")
49
- return null;
82
+ return { status: "no_claim" };
50
83
  current = current[seg];
51
84
  }
52
- return typeof current === "string" ? current : null;
85
+ return typeof current === "string" ? { status: "resolved", tenantId: current } : { status: "no_claim" };
86
+ }
87
+ function resolveFromJwt(req, claimPath = "tenant_id", options) {
88
+ const result = resolveJwtTenant(req, claimPath, options);
89
+ return result.status === "resolved" ? result.tenantId : null;
53
90
  }
54
91
  //# sourceMappingURL=jwt.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"jwt.js","sourceRoot":"","sources":["../../src/resolvers/jwt.ts"],"names":[],"mappings":";;AAiBA,wCA2CC;AAvDD,SAAS,sBAAsB,CAAC,KAAa,EAAE,MAAc;IAC3D,IAAI,CAAC;QACH,iEAAiE;QACjE,MAAM,GAAG,GAAG,OAAO,CAAC,cAAc,CAAkC,CAAC;QACrE,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACrE,IAAI,OAAO,OAAO,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC;QAC7C,OAAO,OAAkC,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAgB,cAAc,CAC5B,GAAY,EACZ,YAAoB,WAAW,EAC/B,OAA4B;IAE5B,MAAM,CAAC,GAAG,GAA8B,CAAC;IACzC,MAAM,OAAO,GAAG,CAAC,CAAC,SAAS,CAA8D,CAAC;IAC1F,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAE1B,MAAM,UAAU,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;IAC5C,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;IACpE,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC;IAEtD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAE5B,IAAI,MAAM,GAAmC,IAAI,CAAC;IAElD,IAAI,OAAO,EAAE,MAAM,EAAE,CAAC;QACpB,+CAA+C;QAC/C,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACjC,CAAC;SAAM,IAAI,OAAO,EAAE,MAAM,EAAE,CAAC;QAC3B,0CAA0C;QAC1C,MAAM,GAAG,sBAAsB,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IACzD,CAAC;SAAM,CAAC;QACN,0EAA0E;QAC1E,OAAO,CAAC,IAAI,CACV,6DAA6D;YAC7D,+DAA+D,CAChE,CAAC;QACF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAEzB,sDAAsD;IACtD,MAAM,QAAQ,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,OAAO,GAAY,MAAM,CAAC;IAC9B,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC3B,IAAI,OAAO,IAAI,IAAI,IAAI,OAAO,OAAO,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC;QAChE,OAAO,GAAI,OAAmC,CAAC,GAAG,CAAC,CAAC;IACtD,CAAC;IAED,OAAO,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;AACtD,CAAC"}
1
+ {"version":3,"file":"jwt.js","sourceRoot":"","sources":["../../src/resolvers/jwt.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import type { MiddlewareOptions } from "../types.js";
2
+ /**
3
+ * Outcome of request tenant resolution. `invalid_token` means a bearer token
4
+ * was sent while JWT verification is configured and it did not verify; the
5
+ * caller must reject the request rather than try other sources.
6
+ */
7
+ export type TenantIdResolution = {
8
+ status: "resolved";
9
+ tenantId: string;
10
+ } | {
11
+ status: "missing";
12
+ } | {
13
+ status: "invalid_token";
14
+ };
15
+ /**
16
+ * Resolve the tenant ID for a request: verified JWT, then the tenant header,
17
+ * then custom resolvers.
18
+ *
19
+ * When `jwtSecret` or `jwtVerify` is configured, the JWT is the tenant binding:
20
+ * a token that fails verification is reported as `invalid_token`, and the
21
+ * client-supplied tenant header is not consulted unless `trustTenantHeader`
22
+ * is true.
23
+ */
24
+ export declare function resolveTenantId(req: unknown, options?: MiddlewareOptions): Promise<TenantIdResolution>;
25
+ //# sourceMappingURL=resolve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/resolvers/resolve.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAIrD;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAC1B;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACxC;IAAE,MAAM,EAAE,SAAS,CAAA;CAAE,GACrB;IAAE,MAAM,EAAE,eAAe,CAAA;CAAE,CAAC;AAEhC;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAuB5G"}
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveTenantId = resolveTenantId;
4
+ const jwt_js_1 = require("./jwt.js");
5
+ const header_js_1 = require("./header.js");
6
+ /**
7
+ * Resolve the tenant ID for a request: verified JWT, then the tenant header,
8
+ * then custom resolvers.
9
+ *
10
+ * When `jwtSecret` or `jwtVerify` is configured, the JWT is the tenant binding:
11
+ * a token that fails verification is reported as `invalid_token`, and the
12
+ * client-supplied tenant header is not consulted unless `trustTenantHeader`
13
+ * is true.
14
+ */
15
+ async function resolveTenantId(req, options) {
16
+ const jwtConfigured = Boolean(options?.jwtSecret || options?.jwtVerify);
17
+ const jwt = (0, jwt_js_1.resolveJwtTenant)(req, options?.jwtClaimPath, {
18
+ secret: options?.jwtSecret,
19
+ verify: options?.jwtVerify,
20
+ });
21
+ if (jwt.status === "resolved")
22
+ return { status: "resolved", tenantId: jwt.tenantId };
23
+ if (jwt.status === "invalid")
24
+ return { status: "invalid_token" };
25
+ if (!jwtConfigured || options?.trustTenantHeader) {
26
+ const fromHeader = (0, header_js_1.resolveFromHeader)(req, options?.headerName);
27
+ if (fromHeader)
28
+ return { status: "resolved", tenantId: fromHeader };
29
+ }
30
+ if (options?.resolvers) {
31
+ for (const resolver of options.resolvers) {
32
+ const result = await resolver.resolve(req);
33
+ if (result)
34
+ return { status: "resolved", tenantId: result };
35
+ }
36
+ }
37
+ return { status: "missing" };
38
+ }
39
+ //# sourceMappingURL=resolve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/resolvers/resolve.ts"],"names":[],"mappings":";;AAuBA,0CAuBC;AA7CD,qCAA4C;AAC5C,2CAAgD;AAYhD;;;;;;;;GAQG;AACI,KAAK,UAAU,eAAe,CAAC,GAAY,EAAE,OAA2B;IAC7E,MAAM,aAAa,GAAG,OAAO,CAAC,OAAO,EAAE,SAAS,IAAI,OAAO,EAAE,SAAS,CAAC,CAAC;IAExE,MAAM,GAAG,GAAG,IAAA,yBAAgB,EAAC,GAAG,EAAE,OAAO,EAAE,YAAY,EAAE;QACvD,MAAM,EAAE,OAAO,EAAE,SAAS;QAC1B,MAAM,EAAE,OAAO,EAAE,SAAS;KAC3B,CAAC,CAAC;IACH,IAAI,GAAG,CAAC,MAAM,KAAK,UAAU;QAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC;IACrF,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS;QAAE,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC;IAEjE,IAAI,CAAC,aAAa,IAAI,OAAO,EAAE,iBAAiB,EAAE,CAAC;QACjD,MAAM,UAAU,GAAG,IAAA,6BAAiB,EAAC,GAAG,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;QAC/D,IAAI,UAAU;YAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC;IACtE,CAAC;IAED,IAAI,OAAO,EAAE,SAAS,EAAE,CAAC;QACvB,KAAK,MAAM,QAAQ,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;YACzC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YAC3C,IAAI,MAAM;gBAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;QAC9D,CAAC;IACH,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;AAC/B,CAAC"}
package/dist/types.d.ts CHANGED
@@ -3,10 +3,19 @@ export type { ResolvedTenantContext, TenantNode, CreateTenantInput, UpdateTenant
3
3
  export type { TenantResolver } from "./resolvers/custom.js";
4
4
  export interface MiddlewareOptions {
5
5
  resolvers?: import("./resolvers/custom.js").TenantResolver[];
6
+ /** Header to read the tenant ID from. When set, only this header is read (default: X-Tenant-ID). */
6
7
  headerName?: string;
7
8
  jwtClaimPath?: string;
9
+ /** HS256 secret for JWT verification. Requires the optional `jsonwebtoken` peer dependency unless `jwtVerify` is given. */
8
10
  jwtSecret?: string;
9
11
  jwtVerify?: (token: string) => Record<string, unknown> | null;
12
+ /**
13
+ * When `jwtSecret` or `jwtVerify` is configured, the tenant header is ignored
14
+ * unless this is true, so the verified JWT is the only tenant binding. A
15
+ * bearer token that fails verification is always rejected with 401. Has no
16
+ * effect when JWT verification is not configured. Default: false.
17
+ */
18
+ trustTenantHeader?: boolean;
10
19
  onError?: (err: Error, req: unknown) => void;
11
20
  /**
12
21
  * Enable tenant impersonation via X-Impersonate-Tenant header.
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,UAAU,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAErJ,YAAY,EAAE,qBAAqB,EAAE,UAAU,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,eAAe,EAAE,kBAAkB,EAAE,CAAC;AAE7H,YAAY,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,EAAE,OAAO,uBAAuB,EAAE,cAAc,EAAE,CAAC;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC9D,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;IAC7C;;;;;;;;OAQG;IACH,aAAa,CAAC,EAAE;QACd,OAAO,EAAE,OAAO,CAAC;QACjB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QACxG,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,KAAK,IAAI,CAAC;KACxF,CAAC;CACH"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,UAAU,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAErJ,YAAY,EAAE,qBAAqB,EAAE,UAAU,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,eAAe,EAAE,kBAAkB,EAAE,CAAC;AAE7H,YAAY,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,EAAE,OAAO,uBAAuB,EAAE,cAAc,EAAE,CAAC;IAC7D,oGAAoG;IACpG,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,2HAA2H;IAC3H,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC9D;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;IAC7C;;;;;;;;OAQG;IACH,aAAa,CAAC,EAAE;QACd,OAAO,EAAE,OAAO,CAAC;QACjB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QACxG,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,KAAK,IAAI,CAAC;KACxF,CAAC;CACH"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stratum-hq/sdk",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Stratum Node.js SDK for multi-tenant context propagation",
5
5
  "keywords": [
6
6
  "multi-tenancy",
@@ -45,10 +45,12 @@
45
45
  },
46
46
  "devDependencies": {
47
47
  "@types/express": "^4.17.0",
48
+ "@types/jsonwebtoken": "^9.0.0",
48
49
  "express": "^4.18.0",
49
- "fastify": "^5.3.2",
50
+ "fastify": "^5.12.5",
51
+ "jsonwebtoken": "^9.0.0",
50
52
  "typescript": "^5.4.0",
51
- "vitest": "^1.6.0"
53
+ "vitest": "^4.1.11"
52
54
  },
53
55
  "license": "MIT",
54
56
  "author": "Christian Crank",
@@ -61,5 +63,13 @@
61
63
  "type": "git",
62
64
  "url": "https://github.com/stratum-hq/Stratum.git",
63
65
  "directory": "packages/sdk"
66
+ },
67
+ "peerDependencies": {
68
+ "jsonwebtoken": "^9.0.0"
69
+ },
70
+ "peerDependenciesMeta": {
71
+ "jsonwebtoken": {
72
+ "optional": true
73
+ }
64
74
  }
65
75
  }