@ddd-ts-kit/http 0.6.0 → 0.8.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.
Files changed (71) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +42 -2
  3. package/dist/controller/controller-routes.d.ts.map +1 -1
  4. package/dist/controller/controller-routes.js +21 -3
  5. package/dist/controller/controller-routes.js.map +1 -1
  6. package/dist/controller/guard-refusals.d.ts +9 -0
  7. package/dist/controller/guard-refusals.d.ts.map +1 -0
  8. package/dist/controller/guard-refusals.js +16 -0
  9. package/dist/controller/guard-refusals.js.map +1 -0
  10. package/dist/controller/guards/has-scope.d.ts +10 -0
  11. package/dist/controller/guards/has-scope.d.ts.map +1 -0
  12. package/dist/controller/guards/has-scope.js +27 -0
  13. package/dist/controller/guards/has-scope.js.map +1 -0
  14. package/dist/controller/guards/tenant-member.d.ts +9 -0
  15. package/dist/controller/guards/tenant-member.d.ts.map +1 -0
  16. package/dist/controller/guards/tenant-member.js +22 -0
  17. package/dist/controller/guards/tenant-member.js.map +1 -0
  18. package/dist/index.d.ts +11 -0
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +8 -0
  21. package/dist/index.js.map +1 -1
  22. package/dist/pipeline/execute-options.d.ts +16 -0
  23. package/dist/pipeline/execute-options.d.ts.map +1 -1
  24. package/dist/pipeline/execute-route.d.ts.map +1 -1
  25. package/dist/pipeline/execute-route.js +35 -10
  26. package/dist/pipeline/execute-route.js.map +1 -1
  27. package/dist/pipeline/execution-of-request.d.ts +2 -0
  28. package/dist/pipeline/execution-of-request.d.ts.map +1 -1
  29. package/dist/pipeline/execution-of-request.js +1 -0
  30. package/dist/pipeline/execution-of-request.js.map +1 -1
  31. package/dist/pipeline/guard-refusal.d.ts +8 -0
  32. package/dist/pipeline/guard-refusal.d.ts.map +1 -0
  33. package/dist/pipeline/guard-refusal.js +2 -0
  34. package/dist/pipeline/guard-refusal.js.map +1 -0
  35. package/dist/tenancy/first-tenant-of.d.ts +4 -0
  36. package/dist/tenancy/first-tenant-of.d.ts.map +1 -0
  37. package/dist/tenancy/first-tenant-of.js +13 -0
  38. package/dist/tenancy/first-tenant-of.js.map +1 -0
  39. package/dist/tenancy/resolved-tenant.d.ts +22 -0
  40. package/dist/tenancy/resolved-tenant.d.ts.map +1 -0
  41. package/dist/tenancy/resolved-tenant.js +29 -0
  42. package/dist/tenancy/resolved-tenant.js.map +1 -0
  43. package/dist/tenancy/tenant-from-claim.d.ts +4 -0
  44. package/dist/tenancy/tenant-from-claim.d.ts.map +1 -0
  45. package/dist/tenancy/tenant-from-claim.js +5 -0
  46. package/dist/tenancy/tenant-from-claim.js.map +1 -0
  47. package/dist/tenancy/tenant-from-header.d.ts +4 -0
  48. package/dist/tenancy/tenant-from-header.d.ts.map +1 -0
  49. package/dist/tenancy/tenant-from-header.js +9 -0
  50. package/dist/tenancy/tenant-from-header.js.map +1 -0
  51. package/dist/tenancy/tenant-from-path.d.ts +4 -0
  52. package/dist/tenancy/tenant-from-path.d.ts.map +1 -0
  53. package/dist/tenancy/tenant-from-path.js +8 -0
  54. package/dist/tenancy/tenant-from-path.js.map +1 -0
  55. package/dist/tenancy/tenant-from-subdomain.d.ts +8 -0
  56. package/dist/tenancy/tenant-from-subdomain.d.ts.map +1 -0
  57. package/dist/tenancy/tenant-from-subdomain.js +17 -0
  58. package/dist/tenancy/tenant-from-subdomain.js.map +1 -0
  59. package/dist/tenancy/tenant-request.d.ts +10 -0
  60. package/dist/tenancy/tenant-request.d.ts.map +1 -0
  61. package/dist/tenancy/tenant-request.js +2 -0
  62. package/dist/tenancy/tenant-request.js.map +1 -0
  63. package/dist/tenancy/tenant-resolver.d.ts +8 -0
  64. package/dist/tenancy/tenant-resolver.d.ts.map +1 -0
  65. package/dist/tenancy/tenant-resolver.js +2 -0
  66. package/dist/tenancy/tenant-resolver.js.map +1 -0
  67. package/dist/tenancy/unknown-tenant-error.d.ts +6 -0
  68. package/dist/tenancy/unknown-tenant-error.d.ts.map +1 -0
  69. package/dist/tenancy/unknown-tenant-error.js +6 -0
  70. package/dist/tenancy/unknown-tenant-error.js.map +1 -0
  71. package/package.json +3 -3
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Gary Bourgeat
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -87,7 +87,7 @@ const routes = controllerRoutes([PlaceOrderController], { resolve: application.r
87
87
  | `Controller(spec)` | the decorator of a controller: `group`, `method`, `path` (after the prefix of the group), `operationId` (the class name without `Controller` by default), `summary`, `description`, `tags`, `params`, `query`, `headers`, `body`, `response: { status, description?, body? }`, `errors`, `guards`, `deprecated` |
88
88
  | `RouteGroup({ parent, prefix, tags, guards, errors })` | names a set of routes on an empty class; a child inherits from its `parent` and adds |
89
89
  | `Guard` | the interface `{ documents?, check(request: GuardRequest) }`, and the decorator of a guard class that takes dependencies |
90
- | `Authenticated`, `Public`, `HasRole(...roles)` | the guards the package ships, over the `Actor` of the request: 401 to the anonymous caller, 403 without one of the roles; `Public` lets everybody in and stands alone |
90
+ | `Authenticated`, `Public`, `HasRole(...roles)`, `HasScope(...scopes)`, `TenantMember` | the guards the package ships, over the `Actor` and the `Session` of the request: 401 to the anonymous caller, 403 without one of the roles, without every scope named (`Session.scopes`, typed by the `SessionScopes` of the project) or outside the tenant of the request; `Public` lets everybody in and stands alone. A refusal of a guard is reported to `onGuardRefusal` |
91
91
  | `RequestMapper<Request, Message>`, `Serializer<Result, Body>` | the interfaces of the two optional translators (`map`, `serialize`), and the decorators that declare them |
92
92
  | `HttpRequest<{ params, query, headers, body }>` | the request as `handle`, a mapper or a guard names it, with `actor` and `context` |
93
93
  | `controllerRoutes(controllers, { resolve, security, guards })` | the `Route` of each controller, given as a class (built by `resolve`) or as an instance; `security` names the schemes of the application (`['bearer']` by default); `guards: 'skip'` is for the spec of a controller alone |
@@ -176,6 +176,16 @@ const options: ExecuteOptions = {
176
176
  };
177
177
  ```
178
178
 
179
+ `onGuardRefusal(refusal)` is told, and awaited, every request a guard refused before its
180
+ controller (`HasRole`, `HasScope`, `TenantMember`, a guard of the project, and a tenant the caller
181
+ does not belong to): its operation, its problem and its execution context. Those refusals reach
182
+ no use case, so the authorization hook of `@ddd-ts-kit/auth` never sees them;
183
+ `auditGuardRefusals(trail, { clock, ids })` of `@ddd-ts-kit/audit` writes each one to the audit
184
+ trail as a denied decision (an anonymous caller's excepted). Only a refusal is reported, a
185
+ `DomainError` such as `UnauthorizedError` or `ForbiddenError`: a guard that fails with another
186
+ error is a fault, answered 500 and not reported. A refusal of a handler is not reported there,
187
+ and a hook that fails does not change the answer.
188
+
179
189
  `around(route, respond)` wraps the whole handling of a request, from authentication to the
180
190
  answer, refusals included, and is told the route that was matched (`method`, `path` as
181
191
  declared, `operationId`). It is where a tracer names a request `POST /orders/:id/lines` instead
@@ -194,7 +204,7 @@ as `context.execution`:
194
204
  | `correlationId` | the incoming `x-correlation-id` when well formed (letters, digits, `._:-`, at most 128), else the request id; echoed in the `x-correlation-id` response header, on problems too, and given to `onError` |
195
205
  | `origin` | `http` |
196
206
  | `actor`, `session` | from what `resolvePrincipal` answered, read structurally: a `Session` gives both, an `Actor` gives the actor, anything else is the anonymous actor |
197
- | `tenantId` | the tenant of the actor |
207
+ | `tenantId` | the tenant `resolveTenant` names, once the caller is known to belong to it; the tenant of the actor otherwise |
198
208
  | `locale` | the locale of the session, else the preferred language of `Accept-Language` |
199
209
  | `deadline` | arrival plus `requestTimeoutMs`, when the option is set |
200
210
 
@@ -219,6 +229,36 @@ option that says when a request arrived, the system clock by default.
219
229
  Use cases still receive the actor explicitly: `new PlaceOrder(context.execution.actor, body)`,
220
230
  or `actorOf(context.principal)` of `@ddd-ts-kit/auth`, which reads the same actor.
221
231
 
232
+ ### The tenant of a request
233
+
234
+ A multi-tenant application says where a request names its tenant with `resolveTenant`:
235
+
236
+ ```ts
237
+ import { firstTenantOf, tenantFromClaim, tenantFromSubdomain } from '@ddd-ts-kit/http';
238
+
239
+ const options: ExecuteOptions = {
240
+ resolveTenant: firstTenantOf(tenantFromSubdomain('app.example.com'), tenantFromClaim()),
241
+ // or tenantFromHeader('x-tenant-id'), tenantFromPath('tenantId')
242
+ };
243
+ ```
244
+
245
+ | Resolver | Names |
246
+ |---|---|
247
+ | `tenantFromSubdomain(baseDomain)` | the one label left of the base domain in `Host` (`acme.app.example.com`); behind a proxy, have it pass the original host |
248
+ | `tenantFromHeader(name?)` | the value of a header, `x-tenant-id` by default |
249
+ | `tenantFromPath(parameter?)` | a path parameter, `tenantId` by default |
250
+ | `tenantFromClaim()` | the tenant of the credential, `Actor.tenantId` |
251
+ | `firstTenantOf(...resolvers)` | the first that names one |
252
+
253
+ The pipeline then checks the membership itself, before any guard or handler: an authenticated
254
+ caller that does not belong to the tenant named (its `tenantId`, or its `tenants` attribute for an
255
+ actor of several tenants) is answered 403, so a header or a subdomain chosen by a client never
256
+ opens another tenant's data. An anonymous caller keeps the tenant it addressed, for the public
257
+ routes of a tenant. The guard `TenantMember` puts a group of routes behind a tenant: 401 to the
258
+ anonymous caller, 403 to a request in no tenant or of another tenant. Platform staff do not pass
259
+ it: they reach tenants through an elevation of the kernel (`acrossTenants`), behind guards of their
260
+ own.
261
+
222
262
  ## In the composition root
223
263
 
224
264
  The package binds and resolves nothing: routes are a plain list and `ExecuteOptions` a plain
@@ -1 +1 @@
1
- {"version":3,"file":"controller-routes.d.ts","sourceRoot":"","sources":["../../src/controller/controller-routes.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AAO9E;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,SAAS,CAAC,eAAe,GAAG,gBAAgB,CAAC,EAAE,EAC5D,OAAO,GAAE,uBAA4B,GACpC,SAAS,KAAK,EAAE,CAMlB"}
1
+ {"version":3,"file":"controller-routes.d.ts","sourceRoot":"","sources":["../../src/controller/controller-routes.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AAQ9E;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,SAAS,CAAC,eAAe,GAAG,gBAAgB,CAAC,EAAE,EAC5D,OAAO,GAAE,uBAA4B,GACpC,SAAS,KAAK,EAAE,CAMlB"}
@@ -1,4 +1,6 @@
1
+ import { DomainError } from '@ddd-ts-kit/kernel';
1
2
  import { assertUniqueRoutes } from '../route/assert-unique-routes.js';
3
+ import { guardRefusals } from './guard-refusals.js';
2
4
  import { resolvedController } from './resolved-controller.js';
3
5
  const DEFAULT_SECURITY = ['bearer'];
4
6
  /**
@@ -28,14 +30,30 @@ function routeOf(resolved, options) {
28
30
  security: securityOf(resolved.guards, options.security ?? DEFAULT_SECURITY),
29
31
  ...(spec.deprecated === true ? { deprecated: true } : {}),
30
32
  async handle(input) {
31
- for (const guard of guards) {
32
- await guard.check(guardRequest(identity, input));
33
- }
33
+ await passedGuards(guards, guardRequest(identity, input));
34
34
  const answer = await controller.handle({ ...input, actor: input.context.execution.actor });
35
35
  return body === undefined ? { status } : { status, body: answer };
36
36
  },
37
37
  };
38
38
  }
39
+ /**
40
+ * Every guard, in order. A refusal one throws (a `DomainError`: `UnauthorizedError`,
41
+ * `ForbiddenError` or one of the project) is marked as a refusal at the edge before it goes on to
42
+ * the pipeline; a fault (a lookup that failed) is not, and is never audited as a decision.
43
+ */
44
+ async function passedGuards(guards, request) {
45
+ try {
46
+ for (const guard of guards) {
47
+ await guard.check(request);
48
+ }
49
+ }
50
+ catch (error) {
51
+ if (error instanceof DomainError) {
52
+ guardRefusals.mark(error);
53
+ }
54
+ throw error;
55
+ }
56
+ }
39
57
  function requestOf(parts) {
40
58
  const declared = Object.entries({
41
59
  params: parts.params,
@@ -1 +1 @@
1
- {"version":3,"file":"controller-routes.js","sourceRoot":"","sources":["../../src/controller/controller-routes.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"controller-routes.js","sourceRoot":"","sources":["../../src/controller/controller-routes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * The errors a guard threw to refuse a request, told apart from the refusals of a handler so
3
+ * that the pipeline can report them as refusals at the edge (`onGuardRefusal`).
4
+ */
5
+ export declare const guardRefusals: {
6
+ mark(error: unknown): void;
7
+ has(error: unknown): boolean;
8
+ };
9
+ //# sourceMappingURL=guard-refusals.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guard-refusals.d.ts","sourceRoot":"","sources":["../../src/controller/guard-refusals.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,eAAO,MAAM,aAAa;IACxB,IAAI,QAAQ,OAAO,GAAG,IAAI;IAK1B,GAAG,QAAQ,OAAO,GAAG,OAAO;CAG7B,CAAC"}
@@ -0,0 +1,16 @@
1
+ const refused = new WeakSet();
2
+ /**
3
+ * The errors a guard threw to refuse a request, told apart from the refusals of a handler so
4
+ * that the pipeline can report them as refusals at the edge (`onGuardRefusal`).
5
+ */
6
+ export const guardRefusals = {
7
+ mark(error) {
8
+ if (typeof error === 'object' && error !== null) {
9
+ refused.add(error);
10
+ }
11
+ },
12
+ has(error) {
13
+ return typeof error === 'object' && error !== null && refused.has(error);
14
+ },
15
+ };
16
+ //# sourceMappingURL=guard-refusals.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guard-refusals.js","sourceRoot":"","sources":["../../src/controller/guard-refusals.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,GAAG,IAAI,OAAO,EAAU,CAAC;AAEtC;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,IAAI,CAAC,KAAc;QACjB,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YAChD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;IACD,GAAG,CAAC,KAAc;QAChB,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAC3E,CAAC;CACF,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { type SessionScope } from '@ddd-ts-kit/kernel';
2
+ import type { Guard } from '../guard.js';
3
+ /**
4
+ * Lets through a request whose session was granted every scope named (`Session.scopes`, the
5
+ * `scope` claim of the token): 401 to the anonymous caller, 403 when one is missing. A scope
6
+ * limits the client that presents the credential (a mobile application, an integration); what
7
+ * the actor may do stays a permission of the use case.
8
+ */
9
+ export declare function HasScope(...scopes: readonly SessionScope[]): Guard;
10
+ //# sourceMappingURL=has-scope.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"has-scope.d.ts","sourceRoot":"","sources":["../../../src/controller/guards/has-scope.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAI9E,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEzC;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,GAAG,MAAM,EAAE,SAAS,YAAY,EAAE,GAAG,KAAK,CAiBlE"}
@@ -0,0 +1,27 @@
1
+ import { hasScope, isAnonymous } from '@ddd-ts-kit/kernel';
2
+ import { DeclarationError } from '@ddd-ts-kit/kernel/declarations';
3
+ import { ForbiddenError } from '../../error/forbidden-error.js';
4
+ import { UnauthorizedError } from '../../error/unauthorized-error.js';
5
+ /**
6
+ * Lets through a request whose session was granted every scope named (`Session.scopes`, the
7
+ * `scope` claim of the token): 401 to the anonymous caller, 403 when one is missing. A scope
8
+ * limits the client that presents the credential (a mobile application, an integration); what
9
+ * the actor may do stays a permission of the use case.
10
+ */
11
+ export function HasScope(...scopes) {
12
+ if (scopes.length === 0) {
13
+ throw new DeclarationError('HasScope() names no scope: name at least one, or use Authenticated.');
14
+ }
15
+ return {
16
+ documents: { errors: ['UNAUTHORIZED', 'FORBIDDEN'] },
17
+ check({ actor, session }) {
18
+ if (isAnonymous(actor)) {
19
+ throw new UnauthorizedError('Authentication is required');
20
+ }
21
+ if (!scopes.every((scope) => hasScope(session, scope))) {
22
+ throw new ForbiddenError('A scope this route requires was not granted');
23
+ }
24
+ },
25
+ };
26
+ }
27
+ //# sourceMappingURL=has-scope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"has-scope.js","sourceRoot":"","sources":["../../../src/controller/guards/has-scope.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAqB,MAAM,oBAAoB,CAAC;AAC9E,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AAGtE;;;;;GAKG;AACH,MAAM,UAAU,QAAQ,CAAC,GAAG,MAA+B;IACzD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,gBAAgB,CAAC,qEAAqE,CAAC,CAAC;IACpG,CAAC;IAED,OAAO;QACL,SAAS,EAAE,EAAE,MAAM,EAAE,CAAC,cAAc,EAAE,WAAW,CAAC,EAAE;QACpD,KAAK,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE;YACtB,IAAI,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;gBACvB,MAAM,IAAI,iBAAiB,CAAC,4BAA4B,CAAC,CAAC;YAC5D,CAAC;YAED,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC;gBACvD,MAAM,IAAI,cAAc,CAAC,6CAA6C,CAAC,CAAC;YAC1E,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { Guard } from '../guard.js';
2
+ /**
3
+ * Lets through a caller that belongs to the tenant of the request: 401 to the anonymous caller,
4
+ * 403 to a request that names no tenant or to a caller of another tenant. The routes of tenant
5
+ * data stand behind it; the routes of platform staff stand behind a guard of their own, and
6
+ * reach tenants through an elevation, never through this one.
7
+ */
8
+ export declare const TenantMember: Guard;
9
+ //# sourceMappingURL=tenant-member.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenant-member.d.ts","sourceRoot":"","sources":["../../../src/controller/guards/tenant-member.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEzC;;;;;GAKG;AACH,eAAO,MAAM,YAAY,EAAE,KAa1B,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { isAnonymous, isTenantMember } from '@ddd-ts-kit/kernel';
2
+ import { ForbiddenError } from '../../error/forbidden-error.js';
3
+ import { UnauthorizedError } from '../../error/unauthorized-error.js';
4
+ /**
5
+ * Lets through a caller that belongs to the tenant of the request: 401 to the anonymous caller,
6
+ * 403 to a request that names no tenant or to a caller of another tenant. The routes of tenant
7
+ * data stand behind it; the routes of platform staff stand behind a guard of their own, and
8
+ * reach tenants through an elevation, never through this one.
9
+ */
10
+ export const TenantMember = {
11
+ documents: { errors: ['UNAUTHORIZED', 'FORBIDDEN'] },
12
+ check({ actor, context }) {
13
+ if (isAnonymous(actor)) {
14
+ throw new UnauthorizedError('Authentication is required');
15
+ }
16
+ const { tenantId } = context.execution;
17
+ if (tenantId === undefined || !isTenantMember(actor, tenantId)) {
18
+ throw new ForbiddenError('This route serves the members of a tenant');
19
+ }
20
+ },
21
+ };
22
+ //# sourceMappingURL=tenant-member.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenant-member.js","sourceRoot":"","sources":["../../../src/controller/guards/tenant-member.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AAGtE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,YAAY,GAAU;IACjC,SAAS,EAAE,EAAE,MAAM,EAAE,CAAC,cAAc,EAAE,WAAW,CAAC,EAAE;IACpD,KAAK,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE;QACtB,IAAI,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;YACvB,MAAM,IAAI,iBAAiB,CAAC,4BAA4B,CAAC,CAAC;QAC5D,CAAC;QAED,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,SAAS,CAAC;QAEvC,IAAI,QAAQ,KAAK,SAAS,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,QAAQ,CAAC,EAAE,CAAC;YAC/D,MAAM,IAAI,cAAc,CAAC,2CAA2C,CAAC,CAAC;QACxE,CAAC;IACH,CAAC;CACF,CAAC"}
package/dist/index.d.ts CHANGED
@@ -14,7 +14,9 @@ export type { GuardRequest } from './controller/guard-request.js';
14
14
  export { Guard } from './controller/guard.js';
15
15
  export { Authenticated } from './controller/guards/authenticated.js';
16
16
  export { HasRole } from './controller/guards/has-role.js';
17
+ export { HasScope } from './controller/guards/has-scope.js';
17
18
  export { Public } from './controller/guards/public.js';
19
+ export { TenantMember } from './controller/guards/tenant-member.js';
18
20
  export type { HttpController } from './controller/http-controller.js';
19
21
  export type { HttpRequest } from './controller/http-request.js';
20
22
  export { RequestMapper } from './controller/request-mapper.js';
@@ -46,6 +48,7 @@ export { pageResponse } from './pagination/page-response.js';
46
48
  export { pageSchemaOf } from './pagination/page-schema-of.js';
47
49
  export { CORRELATION_HEADER } from './pipeline/correlation-header.js';
48
50
  export type { ErrorContext } from './pipeline/error-context.js';
51
+ export type { GuardRefusal } from './pipeline/guard-refusal.js';
49
52
  export type { ExecuteOptions } from './pipeline/execute-options.js';
50
53
  export { executeRoute } from './pipeline/execute-route.js';
51
54
  export type { RawRequest } from './pipeline/raw-request.js';
@@ -71,4 +74,12 @@ export type { RouteInput } from './route/route-input.js';
71
74
  export type { RouteOutput } from './route/route-output.js';
72
75
  export type { RouteSpec } from './route/route-spec.js';
73
76
  export type { Route } from './route/route.js';
77
+ export { firstTenantOf } from './tenancy/first-tenant-of.js';
78
+ export { tenantFromClaim } from './tenancy/tenant-from-claim.js';
79
+ export { tenantFromHeader } from './tenancy/tenant-from-header.js';
80
+ export { tenantFromPath } from './tenancy/tenant-from-path.js';
81
+ export { tenantFromSubdomain } from './tenancy/tenant-from-subdomain.js';
82
+ export type { TenantRequest } from './tenancy/tenant-request.js';
83
+ export type { TenantResolver } from './tenancy/tenant-resolver.js';
84
+ export { UnknownTenantError } from './tenancy/unknown-tenant-error.js';
74
85
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -4,7 +4,9 @@ export { Controller } from './controller/controller.js';
4
4
  export { Guard } from './controller/guard.js';
5
5
  export { Authenticated } from './controller/guards/authenticated.js';
6
6
  export { HasRole } from './controller/guards/has-role.js';
7
+ export { HasScope } from './controller/guards/has-scope.js';
7
8
  export { Public } from './controller/guards/public.js';
9
+ export { TenantMember } from './controller/guards/tenant-member.js';
8
10
  export { RequestMapper } from './controller/request-mapper.js';
9
11
  export { RouteGroup } from './controller/route-group.js';
10
12
  export { Serializer } from './controller/serializer.js';
@@ -34,4 +36,10 @@ export { defineRoute } from './route/define-route.js';
34
36
  export { defineRoutes } from './route/define-routes.js';
35
37
  export { DuplicateRouteError } from './route/duplicate-route-error.js';
36
38
  export { prefixRoutes } from './route/prefix-routes.js';
39
+ export { firstTenantOf } from './tenancy/first-tenant-of.js';
40
+ export { tenantFromClaim } from './tenancy/tenant-from-claim.js';
41
+ export { tenantFromHeader } from './tenancy/tenant-from-header.js';
42
+ export { tenantFromPath } from './tenancy/tenant-from-path.js';
43
+ export { tenantFromSubdomain } from './tenancy/tenant-from-subdomain.js';
44
+ export { UnknownTenantError } from './tenancy/unknown-tenant-error.js';
37
45
  //# 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":"AAIA,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAEnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAErE,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAKxD,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,sCAAsC,CAAC;AACrE,OAAO,EAAE,OAAO,EAAE,MAAM,iCAAiC,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AAGvD,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAG/D,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AAEvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAC1E,OAAO,EAAE,iBAAiB,EAA2B,MAAM,gCAAgC,CAAC;AAC5F,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAEtD,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAErE,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAGlE,OAAO,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AACpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,yCAAyC,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AAGtE,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAG3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAEpE,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAIvE,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAEnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAErE,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAKxD,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,sCAAsC,CAAC;AACrE,OAAO,EAAE,OAAO,EAAE,MAAM,iCAAiC,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,sCAAsC,CAAC;AAGpE,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAG/D,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AAEvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAC1E,OAAO,EAAE,iBAAiB,EAA2B,MAAM,gCAAgC,CAAC;AAC5F,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAEtD,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAErE,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAGlE,OAAO,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AACpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,yCAAyC,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AAItE,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAG3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAEpE,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAIvE,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAWxD,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AAGzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC"}
@@ -1,6 +1,8 @@
1
1
  import type { Clock, ExecutionScope } from '@ddd-ts-kit/kernel';
2
2
  import type { ErrorMapper } from '../error/error-mapper.js';
3
+ import type { TenantResolver } from '../tenancy/tenant-resolver.js';
3
4
  import type { ErrorContext } from './error-context.js';
5
+ import type { GuardRefusal } from './guard-refusal.js';
4
6
  import type { RawRequest } from './raw-request.js';
5
7
  import type { RouteAround } from './route-around.js';
6
8
  export interface ExecuteOptions {
@@ -14,6 +16,13 @@ export interface ExecuteOptions {
14
16
  readonly withPrincipal?: <T>(principal: unknown, work: () => Promise<T>) => Promise<T>;
15
17
  /** Called for every error answered as a problem, expected or not. Meant for logging. */
16
18
  readonly onError?: (error: unknown, context: ErrorContext) => void;
19
+ /**
20
+ * Called, and awaited, for every request a guard of its route refused (`HasRole`, `HasScope`,
21
+ * `TenantMember`, a guard of the project): the refusals at the edge, which no use case sees.
22
+ * `auditGuardRefusals` of `@ddd-ts-kit/audit` writes each one to the audit trail as a denied
23
+ * decision. A hook that fails does not change the answer.
24
+ */
25
+ readonly onGuardRefusal?: (refusal: GuardRefusal) => void | Promise<void>;
17
26
  /** Checks each response against the route declaration. Meant for tests. */
18
27
  readonly validateResponses?: boolean;
19
28
  /** Defaults to the incoming `x-request-id` header when it is well formed, else a UUID. */
@@ -23,6 +32,13 @@ export interface ExecuteOptions {
23
32
  * scoping read the execution context of the request. Opened outside of `withPrincipal`.
24
33
  */
25
34
  readonly executionScope?: ExecutionScope;
35
+ /**
36
+ * Names the tenant of each request (`tenantFromSubdomain`, `tenantFromHeader`, `tenantFromPath`,
37
+ * `tenantFromClaim`, or `firstTenantOf` several). The pipeline refuses with 403 an authenticated
38
+ * caller that does not belong to it, before any handler. Absent, or naming none: the tenant of
39
+ * the actor, as before.
40
+ */
41
+ readonly resolveTenant?: TenantResolver;
26
42
  /**
27
43
  * Gives every request a `deadline` in its execution context, this many milliseconds after it
28
44
  * arrived. The pipeline does not interrupt a handler: what honours the deadline reads it.
@@ -1 +1 @@
1
- {"version":3,"file":"execute-options.d.ts","sourceRoot":"","sources":["../../src/pipeline/execute-options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC;IACnC,yEAAyE;IACzE,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC;IACtD;;;OAGG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IACvF,wFAAwF;IACxF,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,KAAK,IAAI,CAAC;IACnE,2EAA2E;IAC3E,QAAQ,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IACrC,0FAA0F;IAC1F,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,KAAK,MAAM,CAAC;IACrD;;;OAGG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,cAAc,CAAC;IACzC;;;OAGG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,8FAA8F;IAC9F,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;IACvB;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;CAC/B"}
1
+ {"version":3,"file":"execute-options.d.ts","sourceRoot":"","sources":["../../src/pipeline/execute-options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AACpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC;IACnC,yEAAyE;IACzE,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC;IACtD;;;OAGG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IACvF,wFAAwF;IACxF,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,KAAK,IAAI,CAAC;IACnE;;;;;OAKG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1E,2EAA2E;IAC3E,QAAQ,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IACrC,0FAA0F;IAC1F,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,KAAK,MAAM,CAAC;IACrD;;;OAGG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,cAAc,CAAC;IACzC;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,cAAc,CAAC;IACxC;;;OAGG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,8FAA8F;IAC9F,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;IACvB;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;CAC/B"}
@@ -1 +1 @@
1
- {"version":3,"file":"execute-route.d.ts","sourceRoot":"","sources":["../../src/pipeline/execute-route.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAK/C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAkBzD,wBAAsB,YAAY,CAChC,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,UAAU,EACnB,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,aAAa,CAAC,CAOxB"}
1
+ {"version":3,"file":"execute-route.d.ts","sourceRoot":"","sources":["../../src/pipeline/execute-route.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAK/C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAoBzD,wBAAsB,YAAY,CAChC,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,UAAU,EACnB,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,aAAa,CAAC,CAOxB"}
@@ -4,6 +4,8 @@ import { assertDeclaredResponse } from './assert-declared-response.js';
4
4
  import { CORRELATION_HEADER } from './correlation-header.js';
5
5
  import { correlationIdOf } from './correlation-id-of.js';
6
6
  import { executionOfRequest } from './execution-of-request.js';
7
+ import { resolvedTenant } from '../tenancy/resolved-tenant.js';
8
+ import { guardRefusals } from '../controller/guard-refusals.js';
7
9
  import { validateRequest } from './validate-request.js';
8
10
  import { wellFormedIdentifier } from './well-formed-identifier.js';
9
11
  const defaultErrorMapper = createErrorMapper();
@@ -21,19 +23,20 @@ async function responded(call) {
21
23
  return answer(await handled(call), call);
22
24
  }
23
25
  catch (error) {
24
- return refusal(error, call);
26
+ const { response, context } = refusal(error, call);
27
+ await reportGuardRefusal(call.options, error, context);
28
+ return response;
25
29
  }
26
30
  }
27
31
  function defaultRequestId(request) {
28
32
  return wellFormedIdentifier(request.headers['x-request-id']) ?? globalThis.crypto.randomUUID();
29
33
  }
30
34
  async function handled(call) {
31
- const { route, request, options, requestId, correlationId } = call;
35
+ const { route, request, options, requestId } = call;
32
36
  const principal = await options.resolvePrincipal?.(request.raw);
33
37
  const input = validateRequest(route, request);
34
38
  const { headers } = request;
35
- const execution = executionOfRequest({ correlationId, headers, principal, deadline: deadlineOf(options) });
36
- call.reached.execution = execution;
39
+ const execution = executionOf(call, principal, input.params);
37
40
  const context = {
38
41
  requestId,
39
42
  execution,
@@ -49,6 +52,18 @@ async function handled(call) {
49
52
  }
50
53
  return result;
51
54
  }
55
+ /** The execution context of the request, in the tenant it names once the caller is known to belong to it. */
56
+ function executionOf(call, principal, params) {
57
+ const { request, options, correlationId } = call;
58
+ const { headers } = request;
59
+ const deadline = deadlineOf(options);
60
+ const execution = executionOfRequest({ correlationId, headers, principal, deadline });
61
+ call.reached.execution = execution;
62
+ const tenantId = resolvedTenant({ resolver: options.resolveTenant, headers, params, actor: execution.actor });
63
+ const named = tenantId === undefined || tenantId === execution.tenantId ? execution : undefined;
64
+ call.reached.execution = named ?? executionOfRequest({ correlationId, headers, principal, deadline, tenantId });
65
+ return call.reached.execution;
66
+ }
52
67
  function deadlineOf(options) {
53
68
  if (options.requestTimeoutMs === undefined) {
54
69
  return undefined;
@@ -83,7 +98,7 @@ function refusal(error, call) {
83
98
  const { route, options, requestId, correlationId } = call;
84
99
  const { execution } = call.reached;
85
100
  const problem = toProblem(error, options.errorMapper ?? defaultErrorMapper, requestId);
86
- notify(options, error, {
101
+ const context = {
87
102
  requestId,
88
103
  correlationId,
89
104
  operationId: route.operationId,
@@ -91,12 +106,22 @@ function refusal(error, call) {
91
106
  path: route.path,
92
107
  problem,
93
108
  ...(execution === undefined ? {} : { execution }),
94
- });
95
- return {
96
- status: problem.status,
97
- headers: { 'content-type': PROBLEM_CONTENT_TYPE, ...identifierHeaders(call) },
98
- body: problem,
99
109
  };
110
+ notify(options, error, context);
111
+ const headers = { 'content-type': PROBLEM_CONTENT_TYPE, ...identifierHeaders(call) };
112
+ return { response: { status: problem.status, headers, body: problem }, context };
113
+ }
114
+ async function reportGuardRefusal(options, error, context) {
115
+ const { execution } = context;
116
+ if (options.onGuardRefusal === undefined || execution === undefined || !guardRefusals.has(error)) {
117
+ return;
118
+ }
119
+ try {
120
+ await options.onGuardRefusal({ ...context, execution });
121
+ }
122
+ catch {
123
+ // The request is refused either way: a failing hook must not turn the refusal into a fault.
124
+ }
100
125
  }
101
126
  function notify(options, error, context) {
102
127
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"execute-route.js","sourceRoot":"","sources":["../../src/pipeline/execute-route.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"execute-route.js","sourceRoot":"","sources":["../../src/pipeline/execute-route.ts"],"names":[],"mappings":"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"}
@@ -6,6 +6,8 @@ export interface RequestExecution {
6
6
  /** What `resolvePrincipal` answered: a `Session`, an `Actor`, or anything else. */
7
7
  readonly principal: unknown;
8
8
  readonly deadline: Date | undefined;
9
+ /** The tenant the request named, already checked against the caller; the actor's own otherwise. */
10
+ readonly tenantId?: string | undefined;
9
11
  }
10
12
  /**
11
13
  * The execution context of one HTTP request. A principal shaped like a `Session` gives the
@@ -1 +1 @@
1
- {"version":3,"file":"execution-of-request.d.ts","sourceRoot":"","sources":["../../src/pipeline/execution-of-request.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,gBAAgB,EAEtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAE1D,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC;IACvC,mFAAmF;IACnF,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,IAAI,GAAG,SAAS,CAAC;CACrC;AAID;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,gBAAgB,GAAG,gBAAgB,CAY9E"}
1
+ {"version":3,"file":"execution-of-request.d.ts","sourceRoot":"","sources":["../../src/pipeline/execution-of-request.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,gBAAgB,EAEtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAE1D,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC;IACvC,mFAAmF;IACnF,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,IAAI,GAAG,SAAS,CAAC;IACpC,mGAAmG;IACnG,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACxC;AAID;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,gBAAgB,GAAG,gBAAgB,CAa9E"}
@@ -15,6 +15,7 @@ export function executionOfRequest(request) {
15
15
  ...(session === undefined ? {} : { session }),
16
16
  ...(locale === undefined ? {} : { locale }),
17
17
  ...(request.deadline === undefined ? {} : { deadline: request.deadline }),
18
+ ...(request.tenantId === undefined ? {} : { tenantId: request.tenantId }),
18
19
  });
19
20
  }
20
21
  function actorOfPrincipal(principal, session) {
@@ -1 +1 @@
1
- {"version":3,"file":"execution-of-request.js","sourceRoot":"","sources":["../../src/pipeline/execution-of-request.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"execution-of-request.js","sourceRoot":"","sources":["../../src/pipeline/execution-of-request.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { ExecutionContext } from '@ddd-ts-kit/kernel';
2
+ import type { ErrorContext } from './error-context.js';
3
+ /** A request a guard of its route refused, before any use case: what `onGuardRefusal` is told. */
4
+ export interface GuardRefusal extends Omit<ErrorContext, 'execution'> {
5
+ /** The execution context of the request: who was refused, in which session and tenant. */
6
+ readonly execution: ExecutionContext;
7
+ }
8
+ //# sourceMappingURL=guard-refusal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guard-refusal.d.ts","sourceRoot":"","sources":["../../src/pipeline/guard-refusal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,kGAAkG;AAClG,MAAM,WAAW,YAAa,SAAQ,IAAI,CAAC,YAAY,EAAE,WAAW,CAAC;IACnE,0FAA0F;IAC1F,QAAQ,CAAC,SAAS,EAAE,gBAAgB,CAAC;CACtC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=guard-refusal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guard-refusal.js","sourceRoot":"","sources":["../../src/pipeline/guard-refusal.ts"],"names":[],"mappings":""}
@@ -0,0 +1,4 @@
1
+ import type { TenantResolver } from './tenant-resolver.js';
2
+ /** The first tenant one of the resolvers names, in order: `firstTenantOf(tenantFromSubdomain('app.example.com'), tenantFromClaim())`. */
3
+ export declare function firstTenantOf(...resolvers: readonly TenantResolver[]): TenantResolver;
4
+ //# sourceMappingURL=first-tenant-of.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"first-tenant-of.d.ts","sourceRoot":"","sources":["../../src/tenancy/first-tenant-of.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,yIAAyI;AACzI,wBAAgB,aAAa,CAAC,GAAG,SAAS,EAAE,SAAS,cAAc,EAAE,GAAG,cAAc,CAYrF"}
@@ -0,0 +1,13 @@
1
+ /** The first tenant one of the resolvers names, in order: `firstTenantOf(tenantFromSubdomain('app.example.com'), tenantFromClaim())`. */
2
+ export function firstTenantOf(...resolvers) {
3
+ return (request) => {
4
+ for (const resolver of resolvers) {
5
+ const tenantId = resolver(request);
6
+ if (tenantId !== undefined) {
7
+ return tenantId;
8
+ }
9
+ }
10
+ return undefined;
11
+ };
12
+ }
13
+ //# sourceMappingURL=first-tenant-of.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"first-tenant-of.js","sourceRoot":"","sources":["../../src/tenancy/first-tenant-of.ts"],"names":[],"mappings":"AAEA,yIAAyI;AACzI,MAAM,UAAU,aAAa,CAAC,GAAG,SAAoC;IACnE,OAAO,CAAC,OAAO,EAAE,EAAE;QACjB,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YACjC,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;YAEnC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;gBAC3B,OAAO,QAAQ,CAAC;YAClB,CAAC;QACH,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { type Actor } from '@ddd-ts-kit/kernel';
2
+ import type { RawHeaders } from '../route/raw-headers.js';
3
+ import type { TenantResolver } from './tenant-resolver.js';
4
+ interface TenantResolution {
5
+ readonly resolver: TenantResolver | undefined;
6
+ readonly headers: Readonly<RawHeaders>;
7
+ readonly params: unknown;
8
+ readonly actor: Actor;
9
+ }
10
+ /**
11
+ * The tenant a request names, refused (403) when an authenticated caller does not belong to it:
12
+ * a header or a subdomain chosen by the client never opens another tenant's data. A tenant id
13
+ * outside the grammar of `isTenantId` (`*`, a list, a `:`) names no tenant that can exist, and
14
+ * is answered 404 before anything reads it, whoever calls. An anonymous caller keeps the tenant
15
+ * it addressed, for the public routes of a tenant (its sign-in page, its booking page); what it
16
+ * may do there is decided by the use cases, as for any anonymous caller. An authenticated caller
17
+ * is held to its tenants on every route, public ones included: to open the public page of
18
+ * another tenant, it calls without its credential.
19
+ */
20
+ export declare function resolvedTenant({ resolver, headers, params, actor }: TenantResolution): string | undefined;
21
+ export {};
22
+ //# sourceMappingURL=resolved-tenant.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolved-tenant.d.ts","sourceRoot":"","sources":["../../src/tenancy/resolved-tenant.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2C,KAAK,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAIzF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAG3D,UAAU,gBAAgB;IACxB,QAAQ,CAAC,QAAQ,EAAE,cAAc,GAAG,SAAS,CAAC;IAC9C,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC;IACvC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;CACvB;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,gBAAgB,GAAG,MAAM,GAAG,SAAS,CAiBzG"}
@@ -0,0 +1,29 @@
1
+ import { isAnonymous, isTenantId, isTenantMember } from '@ddd-ts-kit/kernel';
2
+ import { guardRefusals } from '../controller/guard-refusals.js';
3
+ import { ForbiddenError } from '../error/forbidden-error.js';
4
+ import { isRecord } from '../support/is-record.js';
5
+ import { UnknownTenantError } from './unknown-tenant-error.js';
6
+ /**
7
+ * The tenant a request names, refused (403) when an authenticated caller does not belong to it:
8
+ * a header or a subdomain chosen by the client never opens another tenant's data. A tenant id
9
+ * outside the grammar of `isTenantId` (`*`, a list, a `:`) names no tenant that can exist, and
10
+ * is answered 404 before anything reads it, whoever calls. An anonymous caller keeps the tenant
11
+ * it addressed, for the public routes of a tenant (its sign-in page, its booking page); what it
12
+ * may do there is decided by the use cases, as for any anonymous caller. An authenticated caller
13
+ * is held to its tenants on every route, public ones included: to open the public page of
14
+ * another tenant, it calls without its credential.
15
+ */
16
+ export function resolvedTenant({ resolver, headers, params, actor }) {
17
+ const tenantId = resolver?.({ headers, params: isRecord(params) ? params : {}, actor });
18
+ if (tenantId !== undefined && !isTenantId(tenantId)) {
19
+ throw new UnknownTenantError('The request names no tenant that can exist');
20
+ }
21
+ if (tenantId === undefined || isAnonymous(actor) || isTenantMember(actor, tenantId)) {
22
+ return tenantId;
23
+ }
24
+ const refused = new ForbiddenError('The tenant of the request is not one the caller belongs to');
25
+ // Refused at the edge like a guard refuses, and reported as one (`onGuardRefusal`).
26
+ guardRefusals.mark(refused);
27
+ throw refused;
28
+ }
29
+ //# sourceMappingURL=resolved-tenant.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolved-tenant.js","sourceRoot":"","sources":["../../src/tenancy/resolved-tenant.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,cAAc,EAAc,MAAM,oBAAoB,CAAC;AACzF,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAGnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAS/D;;;;;;;;;GASG;AACH,MAAM,UAAU,cAAc,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAoB;IACnF,MAAM,QAAQ,GAAG,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IAExF,IAAI,QAAQ,KAAK,SAAS,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACpD,MAAM,IAAI,kBAAkB,CAAC,4CAA4C,CAAC,CAAC;IAC7E,CAAC;IAED,IAAI,QAAQ,KAAK,SAAS,IAAI,WAAW,CAAC,KAAK,CAAC,IAAI,cAAc,CAAC,KAAK,EAAE,QAAQ,CAAC,EAAE,CAAC;QACpF,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,cAAc,CAAC,4DAA4D,CAAC,CAAC;IAEjG,oFAAoF;IACpF,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAE5B,MAAM,OAAO,CAAC;AAChB,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { TenantResolver } from './tenant-resolver.js';
2
+ /** The tenant of the credential (`Actor.tenantId`), which the execution context takes by default anyway: for `firstTenantOf`. */
3
+ export declare function tenantFromClaim(): TenantResolver;
4
+ //# sourceMappingURL=tenant-from-claim.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenant-from-claim.d.ts","sourceRoot":"","sources":["../../src/tenancy/tenant-from-claim.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,iIAAiI;AACjI,wBAAgB,eAAe,IAAI,cAAc,CAEhD"}
@@ -0,0 +1,5 @@
1
+ /** The tenant of the credential (`Actor.tenantId`), which the execution context takes by default anyway: for `firstTenantOf`. */
2
+ export function tenantFromClaim() {
3
+ return ({ actor }) => actor.tenantId;
4
+ }
5
+ //# sourceMappingURL=tenant-from-claim.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenant-from-claim.js","sourceRoot":"","sources":["../../src/tenancy/tenant-from-claim.ts"],"names":[],"mappings":"AAEA,iIAAiI;AACjI,MAAM,UAAU,eAAe;IAC7B,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC;AACvC,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { TenantResolver } from './tenant-resolver.js';
2
+ /** The value of a header, `x-tenant-id` by default; a header sent twice names none. */
3
+ export declare function tenantFromHeader(name?: string): TenantResolver;
4
+ //# sourceMappingURL=tenant-from-header.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenant-from-header.d.ts","sourceRoot":"","sources":["../../src/tenancy/tenant-from-header.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,uFAAuF;AACvF,wBAAgB,gBAAgB,CAAC,IAAI,SAAgB,GAAG,cAAc,CAQrE"}
@@ -0,0 +1,9 @@
1
+ /** The value of a header, `x-tenant-id` by default; a header sent twice names none. */
2
+ export function tenantFromHeader(name = 'x-tenant-id') {
3
+ const header = name.toLowerCase();
4
+ return ({ headers }) => {
5
+ const value = headers[header];
6
+ return typeof value === 'string' && value.trim() !== '' ? value.trim() : undefined;
7
+ };
8
+ }
9
+ //# sourceMappingURL=tenant-from-header.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenant-from-header.js","sourceRoot":"","sources":["../../src/tenancy/tenant-from-header.ts"],"names":[],"mappings":"AAEA,uFAAuF;AACvF,MAAM,UAAU,gBAAgB,CAAC,IAAI,GAAG,aAAa;IACnD,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IAElC,OAAO,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE;QACrB,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;QAE9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IACrF,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { TenantResolver } from './tenant-resolver.js';
2
+ /** A path parameter, `tenantId` by default: `/tenants/:tenantId/invoices`. A route without it names none. */
3
+ export declare function tenantFromPath(parameter?: string): TenantResolver;
4
+ //# sourceMappingURL=tenant-from-path.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenant-from-path.d.ts","sourceRoot":"","sources":["../../src/tenancy/tenant-from-path.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,6GAA6G;AAC7G,wBAAgB,cAAc,CAAC,SAAS,SAAa,GAAG,cAAc,CAMrE"}
@@ -0,0 +1,8 @@
1
+ /** A path parameter, `tenantId` by default: `/tenants/:tenantId/invoices`. A route without it names none. */
2
+ export function tenantFromPath(parameter = 'tenantId') {
3
+ return ({ params }) => {
4
+ const value = params[parameter];
5
+ return typeof value === 'string' && value !== '' ? value : undefined;
6
+ };
7
+ }
8
+ //# sourceMappingURL=tenant-from-path.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenant-from-path.js","sourceRoot":"","sources":["../../src/tenancy/tenant-from-path.ts"],"names":[],"mappings":"AAEA,6GAA6G;AAC7G,MAAM,UAAU,cAAc,CAAC,SAAS,GAAG,UAAU;IACnD,OAAO,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE;QACpB,MAAM,KAAK,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;QAEhC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IACvE,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { TenantResolver } from './tenant-resolver.js';
2
+ /**
3
+ * The label left of the base domain: with `app.example.com`, `acme.app.example.com` is the tenant
4
+ * `acme`. The base domain itself, another domain and a deeper subdomain name none. It reads the
5
+ * `Host` header: behind a proxy, have it pass the original host.
6
+ */
7
+ export declare function tenantFromSubdomain(baseDomain: string): TenantResolver;
8
+ //# sourceMappingURL=tenant-from-subdomain.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenant-from-subdomain.d.ts","sourceRoot":"","sources":["../../src/tenancy/tenant-from-subdomain.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,cAAc,CActE"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * The label left of the base domain: with `app.example.com`, `acme.app.example.com` is the tenant
3
+ * `acme`. The base domain itself, another domain and a deeper subdomain name none. It reads the
4
+ * `Host` header: behind a proxy, have it pass the original host.
5
+ */
6
+ export function tenantFromSubdomain(baseDomain) {
7
+ const suffix = `.${baseDomain.toLowerCase()}`;
8
+ return ({ headers }) => {
9
+ const host = typeof headers['host'] === 'string' ? headers['host'].toLowerCase().replace(/:\d+$/, '') : '';
10
+ if (!host.endsWith(suffix)) {
11
+ return undefined;
12
+ }
13
+ const label = host.slice(0, -suffix.length);
14
+ return label === '' || label.includes('.') ? undefined : label;
15
+ };
16
+ }
17
+ //# sourceMappingURL=tenant-from-subdomain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenant-from-subdomain.js","sourceRoot":"","sources":["../../src/tenancy/tenant-from-subdomain.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,UAAkB;IACpD,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,WAAW,EAAE,EAAE,CAAC;IAE9C,OAAO,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE;QACrB,MAAM,IAAI,GAAG,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAE3G,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3B,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAE5C,OAAO,KAAK,KAAK,EAAE,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC;IACjE,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { Actor } from '@ddd-ts-kit/kernel';
2
+ import type { RawHeaders } from '../route/raw-headers.js';
3
+ /** What a resolver reads to name the tenant of a request: who calls, and how the request was addressed. */
4
+ export interface TenantRequest {
5
+ readonly headers: Readonly<RawHeaders>;
6
+ /** The path parameters, through the schema of the route when it declares one. */
7
+ readonly params: Readonly<Record<string, unknown>>;
8
+ readonly actor: Actor;
9
+ }
10
+ //# sourceMappingURL=tenant-request.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenant-request.d.ts","sourceRoot":"","sources":["../../src/tenancy/tenant-request.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAE1D,2GAA2G;AAC3G,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC;IACvC,iFAAiF;IACjF,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACnD,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;CACvB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=tenant-request.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenant-request.js","sourceRoot":"","sources":["../../src/tenancy/tenant-request.ts"],"names":[],"mappings":""}
@@ -0,0 +1,8 @@
1
+ import type { TenantRequest } from './tenant-request.js';
2
+ /**
3
+ * Names the tenant of a request, or `undefined` when the request names none: the subdomain, a
4
+ * header, a path segment or a claim of the credential. What it answers becomes the `tenantId` of
5
+ * the execution context, once the pipeline has checked that the caller belongs to it.
6
+ */
7
+ export type TenantResolver = (request: TenantRequest) => string | undefined;
8
+ //# sourceMappingURL=tenant-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenant-resolver.d.ts","sourceRoot":"","sources":["../../src/tenancy/tenant-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD;;;;GAIG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,EAAE,aAAa,KAAK,MAAM,GAAG,SAAS,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=tenant-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenant-resolver.js","sourceRoot":"","sources":["../../src/tenancy/tenant-resolver.ts"],"names":[],"mappings":""}
@@ -0,0 +1,6 @@
1
+ import { DomainError } from '@ddd-ts-kit/kernel';
2
+ /** A request that names a tenant outside the grammar of `isTenantId`: no such tenant can exist. */
3
+ export declare class UnknownTenantError extends DomainError {
4
+ readonly code = "NOT_FOUND";
5
+ }
6
+ //# sourceMappingURL=unknown-tenant-error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unknown-tenant-error.d.ts","sourceRoot":"","sources":["../../src/tenancy/unknown-tenant-error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD,mGAAmG;AACnG,qBAAa,kBAAmB,SAAQ,WAAW;IACjD,QAAQ,CAAC,IAAI,eAAe;CAC7B"}
@@ -0,0 +1,6 @@
1
+ import { DomainError } from '@ddd-ts-kit/kernel';
2
+ /** A request that names a tenant outside the grammar of `isTenantId`: no such tenant can exist. */
3
+ export class UnknownTenantError extends DomainError {
4
+ code = 'NOT_FOUND';
5
+ }
6
+ //# sourceMappingURL=unknown-tenant-error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unknown-tenant-error.js","sourceRoot":"","sources":["../../src/tenancy/unknown-tenant-error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD,mGAAmG;AACnG,MAAM,OAAO,kBAAmB,SAAQ,WAAW;IACxC,IAAI,GAAG,WAAW,CAAC;CAC7B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ddd-ts-kit/http",
3
- "version": "0.6.0",
3
+ "version": "0.8.0",
4
4
  "description": "Framework-agnostic route definitions with Express, Fastify and NestJS adapters and OpenAPI 3.1 generation.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -46,8 +46,8 @@
46
46
  "dist"
47
47
  ],
48
48
  "dependencies": {
49
- "@ddd-ts-kit/kernel": "0.6.0",
50
- "@ddd-ts-kit/validation": "0.6.0"
49
+ "@ddd-ts-kit/kernel": "0.8.0",
50
+ "@ddd-ts-kit/validation": "0.8.0"
51
51
  },
52
52
  "peerDependencies": {
53
53
  "@nestjs/common": ">=11.0.0",