@ddd-ts-kit/kernel 0.7.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.
- package/README.md +42 -9
- package/dist/application/audit/tenant-scope-of.d.ts +4 -1
- package/dist/application/audit/tenant-scope-of.d.ts.map +1 -1
- package/dist/application/audit/tenant-scope-of.js +6 -2
- package/dist/application/audit/tenant-scope-of.js.map +1 -1
- package/dist/application/cache/tenant-cache-key.d.ts +5 -0
- package/dist/application/cache/tenant-cache-key.d.ts.map +1 -0
- package/dist/application/cache/tenant-cache-key.js +7 -0
- package/dist/application/cache/tenant-cache-key.js.map +1 -0
- package/dist/application/events/execution-context-of-event.d.ts +2 -1
- package/dist/application/events/execution-context-of-event.d.ts.map +1 -1
- package/dist/application/events/execution-context-of-event.js +3 -1
- package/dist/application/events/execution-context-of-event.js.map +1 -1
- package/dist/application/events/integration-event.d.ts +6 -0
- package/dist/application/events/integration-event.d.ts.map +1 -1
- package/dist/application/events/scoped-publisher.d.ts +4 -3
- package/dist/application/events/scoped-publisher.d.ts.map +1 -1
- package/dist/application/events/scoped-publisher.js +11 -5
- package/dist/application/events/scoped-publisher.js.map +1 -1
- package/dist/application/execution/execution-context.d.ts +7 -1
- package/dist/application/execution/execution-context.d.ts.map +1 -1
- package/dist/application/execution/execution-context.js +7 -2
- package/dist/application/execution/execution-context.js.map +1 -1
- package/dist/application/execution/log-fields-of.d.ts.map +1 -1
- package/dist/application/execution/log-fields-of.js +1 -0
- package/dist/application/execution/log-fields-of.js.map +1 -1
- package/dist/application/ports/tenant-directory.d.ts +8 -0
- package/dist/application/ports/tenant-directory.d.ts.map +1 -0
- package/dist/application/ports/tenant-directory.js +10 -0
- package/dist/application/ports/tenant-directory.js.map +1 -0
- package/dist/application/scheduling/execution-context-of-job.d.ts +3 -1
- package/dist/application/scheduling/execution-context-of-job.d.ts.map +1 -1
- package/dist/application/scheduling/execution-context-of-job.js +1 -1
- package/dist/application/scheduling/execution-context-of-job.js.map +1 -1
- package/dist/application/scheduling/job-execution.d.ts +2 -0
- package/dist/application/scheduling/job-execution.d.ts.map +1 -1
- package/dist/application/scheduling/job-options.d.ts +6 -0
- package/dist/application/scheduling/job-options.d.ts.map +1 -1
- package/dist/application/scheduling/job-policy.d.ts.map +1 -1
- package/dist/application/scheduling/job-policy.js +4 -2
- package/dist/application/scheduling/job-policy.js.map +1 -1
- package/dist/application/session/has-scope.d.ts +5 -0
- package/dist/application/session/has-scope.d.ts.map +1 -0
- package/dist/application/session/has-scope.js +5 -0
- package/dist/application/session/has-scope.js.map +1 -0
- package/dist/application/session/session-scope.d.ts +4 -0
- package/dist/application/session/session-scope.d.ts.map +1 -0
- package/dist/application/session/session-scope.js +2 -0
- package/dist/application/session/session-scope.js.map +1 -0
- package/dist/application/session/session-scopes.d.ts +11 -0
- package/dist/application/session/session-scopes.d.ts.map +1 -0
- package/dist/application/session/session-scopes.js +2 -0
- package/dist/application/session/session-scopes.js.map +1 -0
- package/dist/application/session/session.d.ts +6 -0
- package/dist/application/session/session.d.ts.map +1 -1
- package/dist/application/tenancy/across-tenants.d.ts +12 -0
- package/dist/application/tenancy/across-tenants.d.ts.map +1 -0
- package/dist/application/tenancy/across-tenants.js +47 -0
- package/dist/application/tenancy/across-tenants.js.map +1 -0
- package/dist/application/tenancy/assert-tenant-id.d.ts +3 -0
- package/dist/application/tenancy/assert-tenant-id.d.ts.map +1 -0
- package/dist/application/tenancy/assert-tenant-id.js +10 -0
- package/dist/application/tenancy/assert-tenant-id.js.map +1 -0
- package/dist/application/tenancy/elevation-options.d.ts +12 -0
- package/dist/application/tenancy/elevation-options.d.ts.map +1 -0
- package/dist/application/tenancy/elevation-options.js +2 -0
- package/dist/application/tenancy/elevation-options.js.map +1 -0
- package/dist/application/tenancy/invalid-tenant-elevation-error.d.ts +5 -0
- package/dist/application/tenancy/invalid-tenant-elevation-error.d.ts.map +1 -0
- package/dist/application/tenancy/invalid-tenant-elevation-error.js +8 -0
- package/dist/application/tenancy/invalid-tenant-elevation-error.js.map +1 -0
- package/dist/application/tenancy/invalid-tenant-id-error.d.ts +6 -0
- package/dist/application/tenancy/invalid-tenant-id-error.d.ts.map +1 -0
- package/dist/application/tenancy/invalid-tenant-id-error.js +10 -0
- package/dist/application/tenancy/invalid-tenant-id-error.js.map +1 -0
- package/dist/application/tenancy/is-tenant-id.d.ts +3 -0
- package/dist/application/tenancy/is-tenant-id.d.ts.map +1 -0
- package/dist/application/tenancy/is-tenant-id.js +12 -0
- package/dist/application/tenancy/is-tenant-id.js.map +1 -0
- package/dist/application/tenancy/is-tenant-member.d.ts +4 -0
- package/dist/application/tenancy/is-tenant-member.d.ts.map +1 -0
- package/dist/application/tenancy/is-tenant-member.js +6 -0
- package/dist/application/tenancy/is-tenant-member.js.map +1 -0
- package/dist/application/tenancy/tenant-elevation.d.ts +11 -0
- package/dist/application/tenancy/tenant-elevation.d.ts.map +1 -0
- package/dist/application/tenancy/tenant-elevation.js +2 -0
- package/dist/application/tenancy/tenant-elevation.js.map +1 -0
- package/dist/application/tenancy/tenant-key.d.ts +9 -0
- package/dist/application/tenancy/tenant-key.d.ts.map +1 -0
- package/dist/application/tenancy/tenant-key.js +11 -0
- package/dist/application/tenancy/tenant-key.js.map +1 -0
- package/dist/application/tenancy/tenant-reach-of.d.ts +9 -0
- package/dist/application/tenancy/tenant-reach-of.d.ts.map +1 -0
- package/dist/application/tenancy/tenant-reach-of.js +18 -0
- package/dist/application/tenancy/tenant-reach-of.js.map +1 -0
- package/dist/application/tenancy/tenant-reach.d.ts +12 -0
- package/dist/application/tenancy/tenant-reach.d.ts.map +1 -0
- package/dist/application/tenancy/tenant-reach.js +2 -0
- package/dist/application/tenancy/tenant-reach.js.map +1 -0
- package/dist/application/tenancy/tenants-of.d.ts +8 -0
- package/dist/application/tenancy/tenants-of.d.ts.map +1 -0
- package/dist/application/tenancy/tenants-of.js +14 -0
- package/dist/application/tenancy/tenants-of.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/in-memory/in-memory-tenant-directory.d.ts +8 -0
- package/dist/infrastructure/in-memory/in-memory-tenant-directory.d.ts.map +1 -0
- package/dist/infrastructure/in-memory/in-memory-tenant-directory.js +12 -0
- package/dist/infrastructure/in-memory/in-memory-tenant-directory.js.map +1 -0
- package/dist/infrastructure/tenancy/tenant-isolation-policies.d.ts +13 -0
- package/dist/infrastructure/tenancy/tenant-isolation-policies.d.ts.map +1 -0
- package/dist/infrastructure/tenancy/tenant-isolation-policies.js +13 -0
- package/dist/infrastructure/tenancy/tenant-isolation-policies.js.map +1 -0
- package/dist/infrastructure/tenancy/tenant-policy-expressions.d.ts +11 -0
- package/dist/infrastructure/tenancy/tenant-policy-expressions.d.ts.map +1 -0
- package/dist/infrastructure/tenancy/tenant-policy-expressions.js +15 -0
- package/dist/infrastructure/tenancy/tenant-policy-expressions.js.map +1 -0
- package/dist/infrastructure/tenancy/tenant-setting-values.d.ts +13 -0
- package/dist/infrastructure/tenancy/tenant-setting-values.d.ts.map +1 -0
- package/dist/infrastructure/tenancy/tenant-setting-values.js +19 -0
- package/dist/infrastructure/tenancy/tenant-setting-values.js.map +1 -0
- package/dist/infrastructure/tenancy/tenant-settings.d.ts +13 -0
- package/dist/infrastructure/tenancy/tenant-settings.d.ts.map +1 -0
- package/dist/infrastructure/tenancy/tenant-settings.js +13 -0
- package/dist/infrastructure/tenancy/tenant-settings.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -552,8 +552,13 @@ The authenticated session of an actor, as plain data.
|
|
|
552
552
|
| `authenticationStrength?` | `{ mfa?, assuranceLevel? }` |
|
|
553
553
|
| `impersonatedBy?` | id of the support actor acting as `actor`; `logFieldsOf` carries it to every log line |
|
|
554
554
|
| `locale?`, `timeZone?`, `client?` | BCP 47 tag, IANA zone, `{ ip?, userAgent? }` as opaque strings |
|
|
555
|
+
| `scopes?` | what the credential allows whoever presents it (the OAuth 2.0 `scope`): a limit on the client, never what the actor may do |
|
|
555
556
|
| `extensions` | the fields of the project |
|
|
556
557
|
|
|
558
|
+
`hasScope(session, scope)` reads the scopes; a project names its scope vocabulary once by
|
|
559
|
+
declaration merging of `SessionScopes` (`interface SessionScopes { readonly 'invoices:read': true }`),
|
|
560
|
+
and `SessionScope`, the type a guard takes, is then that vocabulary instead of any string.
|
|
561
|
+
|
|
557
562
|
`isExpired(session, clock.now())`, `isImpersonated(session)`, `anonymousSession()`,
|
|
558
563
|
`systemSession(name, issuedAt?)`, and `isSession(value)`, the structural guard a boundary uses on
|
|
559
564
|
what it received as a principal.
|
|
@@ -561,8 +566,8 @@ what it received as a principal.
|
|
|
561
566
|
### ExecutionContext and ExecutionScope
|
|
562
567
|
|
|
563
568
|
What every unit of work carries, whatever started it: `correlationId`, `causationId?`, `actor`,
|
|
564
|
-
`session?`, `tenantId?`, `
|
|
565
|
-
was due), `origin` (`http`, `event`, `schedule`, `cli`, or a string of the project) and `extensions`. `executionContext(init)` builds one and takes the tenant
|
|
569
|
+
`session?`, `tenantId?`, `elevation?` (platform staff reading over tenants, see "Tenancy"),
|
|
570
|
+
`locale?`, `deadline?`, `scheduledAt?` (for a scheduled job, the instant it was due), `origin` (`http`, `event`, `schedule`, `cli`, or a string of the project) and `extensions`. `executionContext(init)` builds one and takes the tenant
|
|
566
571
|
of the actor; `withActor(context, actor)` is the same work seen as another actor.
|
|
567
572
|
|
|
568
573
|
`ExecutionScope` (`current()`, `require()`, `run(context, work)`) gives the context of the work
|
|
@@ -584,11 +589,13 @@ tenant scoping and outgoing headers.
|
|
|
584
589
|
|
|
585
590
|
A consumed event opens its own context: `executionContextOfEvent(event, { consumer })` has
|
|
586
591
|
origin `event`, the correlation of the event (its id when it names none), the event as
|
|
587
|
-
`causationId
|
|
592
|
+
`causationId`, `systemActor(consumer)` as actor and the `tenantId` of the event, so the
|
|
593
|
+
consumer reads and writes in that tenant only; `inEventScope(scope, { consumer }, handler)`
|
|
588
594
|
wraps a handler with it. The standard envelope carries no actor, so that no personal data
|
|
589
595
|
travels by default: a project whose envelopes name one passes `actorOf`. On the way out,
|
|
590
|
-
`scopedPublisher(publisher, scope)` stamps the correlation of the work in
|
|
591
|
-
event published without
|
|
596
|
+
`scopedPublisher(publisher, scope)` stamps the correlation and the tenant of the work in
|
|
597
|
+
progress on every event published without them, so everything one stimulus causes is found
|
|
598
|
+
again across processes and stays in its tenant.
|
|
592
599
|
|
|
593
600
|
`ActorContext` stays, unchanged. `ScopedActorContext` implements it on top of a scope: the
|
|
594
601
|
current actor is the actor of the current execution context, so the two cannot disagree.
|
|
@@ -701,7 +708,8 @@ const hit: Quote | undefined = await cache.get(quoteKey('EUR-USD'));
|
|
|
701
708
|
```
|
|
702
709
|
|
|
703
710
|
The key carries the type of its value. `InMemoryCache(clock, { maxEntries? })` expires by the
|
|
704
|
-
`Clock` and is bounded.
|
|
711
|
+
`Clock` and is bounded. `tenantCacheKey<Quote>(scope, 'quote', pair)` is the same key confined to
|
|
712
|
+
the tenant of the work in progress: what one tenant cached is never served to another.
|
|
705
713
|
|
|
706
714
|
### Lock
|
|
707
715
|
|
|
@@ -748,9 +756,10 @@ instead of rejecting: only an unknown name rejects (`UnknownJobError`), and a na
|
|
|
748
756
|
twice throws (`DuplicateJobError`).
|
|
749
757
|
|
|
750
758
|
A run happens inside `ExecutionScope`, in the context `executionContextOfJob(name, { correlationId,
|
|
751
|
-
scheduledAt, deadline? })` builds: origin `schedule`, `systemActor(name)`, a correlation of its
|
|
759
|
+
scheduledAt, deadline?, tenantId? })` builds: origin `schedule`, `systemActor(name)`, a correlation of its
|
|
752
760
|
own, and `scheduledAt`, the instant the run was due, which `ExecutionContext` carries for this
|
|
753
|
-
origin.
|
|
761
|
+
origin. A job is `global` by default and runs in no tenant; `tenancy: 'per-tenant'` makes the
|
|
762
|
+
scheduler run it once per tenant of a `TenantDirectory`, each run in that tenant.
|
|
754
763
|
|
|
755
764
|
`parseJobSchedule(schedule)` validates a schedule and answers the form occurrences are
|
|
756
765
|
computed from (`InvalidJobScheduleError`, code `INVALID_JOB_SCHEDULE`, otherwise);
|
|
@@ -770,12 +779,36 @@ if (!decision.allowed) {
|
|
|
770
779
|
|
|
771
780
|
A sliding window: at any instant, at most `limit` allowed calls in the `windowMs` before it. A
|
|
772
781
|
`RateLimitDecision` is `{ allowed, remaining, retryAfterMs }`; a refused call is not counted.
|
|
773
|
-
The key is whatever is limited: a client, a tenant, a route and an address together.
|
|
782
|
+
The key is whatever is limited: a client, a tenant, a route and an address together. In a
|
|
783
|
+
multi-tenant project, `tenantKey(scope, 'password-reset', accountId)` confines it to the tenant of
|
|
784
|
+
the work in progress (`tenant:<id>:password-reset:<account>`) and refuses work that names none.
|
|
774
785
|
|
|
775
786
|
`InMemoryRateLimiter(clock)` counts inside one process; the adapter shared by several instances
|
|
776
787
|
is in `@ddd-ts-kit/redis`. `rateLimitDecisionOf(counted, limit)` turns what an adapter counted
|
|
777
788
|
into the decision.
|
|
778
789
|
|
|
790
|
+
### Tenancy
|
|
791
|
+
|
|
792
|
+
The tenant of the work is `ExecutionContext.tenantId`, set at the boundary and read by
|
|
793
|
+
infrastructure only, like the rest of the context. The kernel holds what every strategy shares;
|
|
794
|
+
the isolation itself (tenant column, row-level security, schema or database per tenant) is in the
|
|
795
|
+
persistence packages, and the whole picture in
|
|
796
|
+
[Multitenancy](../../docs/concepts/multitenancy.md).
|
|
797
|
+
|
|
798
|
+
| Concept | What it does |
|
|
799
|
+
|---|---|
|
|
800
|
+
| `isTenantId(value)`, `assertTenantId(id)`, `InvalidTenantIdError` | the one grammar of a tenant id (letters, digits, `_`, `-`, at most 63): `executionContext`, `executionContextOfEvent`, `acrossTenants`, `InMemoryTenantDirectory`, `tenantScopeOf`, `tenantReachOf` and the row-level security settings refuse any other, so that no tenant id can be read as a wildcard, a list or a key separator |
|
|
801
|
+
| `tenantScopeOf(scope)` | the one tenant a write names; `NoCurrentTenantError` for work that names none |
|
|
802
|
+
| `tenantReachOf(scope)` | what a read may see: `{ kind: 'tenant', tenantId }`, or `{ kind: 'elevated', tenants }` under an elevation |
|
|
803
|
+
| `tenantsOf(actor)`, `isTenantMember(actor, tenantId)` | the tenants an actor belongs to: its `tenantId` and its `tenants` attribute |
|
|
804
|
+
| `acrossTenants({ scope, trail, clock, ids }, { reason, tenants }, work)` | platform staff reading over tenants: refused without a reason or a tenant, recorded in the `AuditTrail` (action `tenancy:elevate`) before the work runs; writes still name one tenant |
|
|
805
|
+
| `tenantKey(scope, ...segments)`, `tenantCacheKey(scope, ...segments)` | keys of rate limits, locks and caches confined to the tenant: `tenant:<id>:<segments>`, each segment percent-encoded, so that two lists of segments never give one key |
|
|
806
|
+
| `TenantDirectory`, `InMemoryTenantDirectory` | the tenants that exist, for per-tenant jobs, provisioning and migrations |
|
|
807
|
+
| `TENANT_SETTINGS`, `tenantSettingValues(context)`, `TENANT_ISOLATION_POLICIES`, `tenantPolicyExpressions(column)` | what the row-level security of the persistence packages shares: the three settings of a transaction (`ddd_ts_kit.tenant_id`, and for an elevation only `ddd_ts_kit.reach` and `ddd_ts_kit.every_tenant`), their values for the work in progress, the names of the four policies (one per command) and their `read` and `write` expressions |
|
|
808
|
+
|
|
809
|
+
An elevation is never implied by a role: the platform decides the permission to elevate (a use
|
|
810
|
+
case or a guard), then calls `acrossTenants`. A trail that fails to record it refuses it.
|
|
811
|
+
|
|
779
812
|
### Page and PageRequest
|
|
780
813
|
|
|
781
814
|
One shape for every search, in two variants:
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import type { ExecutionScope } from '../ports/execution-scope.js';
|
|
2
2
|
import type { TenantScoped } from './tenant-scoped.js';
|
|
3
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* For a repository adapter scoping a statement: the tenant of the work in progress, checked
|
|
5
|
+
* against the grammar of `isTenantId` again however the context was built.
|
|
6
|
+
*/
|
|
4
7
|
export declare function tenantScopeOf(scope: ExecutionScope): TenantScoped;
|
|
5
8
|
//# sourceMappingURL=tenant-scope-of.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tenant-scope-of.d.ts","sourceRoot":"","sources":["../../../src/application/audit/tenant-scope-of.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"tenant-scope-of.d.ts","sourceRoot":"","sources":["../../../src/application/audit/tenant-scope-of.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAGlE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,GAAG,YAAY,CAQjE"}
|
|
@@ -1,10 +1,14 @@
|
|
|
1
|
+
import { assertTenantId } from '../tenancy/assert-tenant-id.js';
|
|
1
2
|
import { NoCurrentTenantError } from './no-current-tenant-error.js';
|
|
2
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* For a repository adapter scoping a statement: the tenant of the work in progress, checked
|
|
5
|
+
* against the grammar of `isTenantId` again however the context was built.
|
|
6
|
+
*/
|
|
3
7
|
export function tenantScopeOf(scope) {
|
|
4
8
|
const { tenantId } = scope.require();
|
|
5
9
|
if (tenantId === undefined) {
|
|
6
10
|
throw new NoCurrentTenantError();
|
|
7
11
|
}
|
|
8
|
-
return { tenantId };
|
|
12
|
+
return { tenantId: assertTenantId(tenantId) };
|
|
9
13
|
}
|
|
10
14
|
//# sourceMappingURL=tenant-scope-of.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tenant-scope-of.js","sourceRoot":"","sources":["../../../src/application/audit/tenant-scope-of.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAGpE
|
|
1
|
+
{"version":3,"file":"tenant-scope-of.js","sourceRoot":"","sources":["../../../src/application/audit/tenant-scope-of.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAGpE;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,KAAqB;IACjD,MAAM,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC;IAErC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,MAAM,IAAI,oBAAoB,EAAE,CAAC;IACnC,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,cAAc,CAAC,QAAQ,CAAC,EAAE,CAAC;AAChD,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ExecutionScope } from '../ports/execution-scope.js';
|
|
2
|
+
import { type CacheKey } from './cache-key.js';
|
|
3
|
+
/** `cacheKey` confined to the tenant of the work in progress: what one tenant cached is never served to another. */
|
|
4
|
+
export declare function tenantCacheKey<T>(scope: ExecutionScope, ...segments: readonly string[]): CacheKey<T>;
|
|
5
|
+
//# sourceMappingURL=tenant-cache-key.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tenant-cache-key.d.ts","sourceRoot":"","sources":["../../../src/application/cache/tenant-cache-key.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAElE,OAAO,EAAE,KAAK,QAAQ,EAAY,MAAM,gBAAgB,CAAC;AAEzD,oHAAoH;AACpH,wBAAgB,cAAc,CAAC,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,GAAG,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,CAEpG"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { tenantKey } from '../tenancy/tenant-key.js';
|
|
2
|
+
import { cacheKey } from './cache-key.js';
|
|
3
|
+
/** `cacheKey` confined to the tenant of the work in progress: what one tenant cached is never served to another. */
|
|
4
|
+
export function tenantCacheKey(scope, ...segments) {
|
|
5
|
+
return cacheKey(tenantKey(scope, ...segments));
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=tenant-cache-key.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tenant-cache-key.js","sourceRoot":"","sources":["../../../src/application/cache/tenant-cache-key.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAiB,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAEzD,oHAAoH;AACpH,MAAM,UAAU,cAAc,CAAI,KAAqB,EAAE,GAAG,QAA2B;IACrF,OAAO,QAAQ,CAAI,SAAS,CAAC,KAAK,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC;AACpD,CAAC"}
|
|
@@ -3,7 +3,8 @@ import type { EventExecutionOptions } from './event-execution-options.js';
|
|
|
3
3
|
import type { IntegrationEvent } from './integration-event.js';
|
|
4
4
|
/**
|
|
5
5
|
* The execution context of a consumed event: origin `event`, the correlation of the event (its
|
|
6
|
-
* own id when it names none, which starts a new chain),
|
|
6
|
+
* own id when it names none, which starts a new chain), the event as the direct cause, and the
|
|
7
|
+
* tenant the event belongs to, so the consumer reads and writes in that tenant only.
|
|
7
8
|
*/
|
|
8
9
|
export declare function executionContextOfEvent(event: IntegrationEvent, options: EventExecutionOptions): ExecutionContext;
|
|
9
10
|
//# sourceMappingURL=execution-context-of-event.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execution-context-of-event.d.ts","sourceRoot":"","sources":["../../../src/application/events/execution-context-of-event.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,gBAAgB,EAAoB,MAAM,mCAAmC,CAAC;AAC5F,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D
|
|
1
|
+
{"version":3,"file":"execution-context-of-event.d.ts","sourceRoot":"","sources":["../../../src/application/events/execution-context-of-event.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,gBAAgB,EAAoB,MAAM,mCAAmC,CAAC;AAC5F,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,qBAAqB,GAAG,gBAAgB,CAQjH"}
|
|
@@ -2,7 +2,8 @@ import { systemActor } from '../actor/system-actor.js';
|
|
|
2
2
|
import { executionContext } from '../execution/execution-context.js';
|
|
3
3
|
/**
|
|
4
4
|
* The execution context of a consumed event: origin `event`, the correlation of the event (its
|
|
5
|
-
* own id when it names none, which starts a new chain),
|
|
5
|
+
* own id when it names none, which starts a new chain), the event as the direct cause, and the
|
|
6
|
+
* tenant the event belongs to, so the consumer reads and writes in that tenant only.
|
|
6
7
|
*/
|
|
7
8
|
export function executionContextOfEvent(event, options) {
|
|
8
9
|
return executionContext({
|
|
@@ -10,6 +11,7 @@ export function executionContextOfEvent(event, options) {
|
|
|
10
11
|
causationId: event.id,
|
|
11
12
|
actor: options.actorOf?.(event) ?? systemActor(options.consumer),
|
|
12
13
|
origin: 'event',
|
|
14
|
+
...(event.tenantId === undefined ? {} : { tenantId: event.tenantId }),
|
|
13
15
|
});
|
|
14
16
|
}
|
|
15
17
|
//# sourceMappingURL=execution-context-of-event.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execution-context-of-event.js","sourceRoot":"","sources":["../../../src/application/events/execution-context-of-event.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAyB,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAI5F
|
|
1
|
+
{"version":3,"file":"execution-context-of-event.js","sourceRoot":"","sources":["../../../src/application/events/execution-context-of-event.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAyB,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAI5F;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CAAC,KAAuB,EAAE,OAA8B;IAC7F,OAAO,gBAAgB,CAAC;QACtB,aAAa,EAAE,KAAK,CAAC,aAAa,IAAI,KAAK,CAAC,EAAE;QAC9C,WAAW,EAAE,KAAK,CAAC,EAAE;QACrB,KAAK,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,IAAI,WAAW,CAAC,OAAO,CAAC,QAAQ,CAAC;QAChE,MAAM,EAAE,OAAO;QACf,GAAG,CAAC,KAAK,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC;KACtE,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -13,5 +13,11 @@ export interface IntegrationEvent<Payload = unknown> {
|
|
|
13
13
|
/** W3C traceparent captured at publication so consumers continue the same trace. */
|
|
14
14
|
readonly traceparent?: string;
|
|
15
15
|
readonly correlationId?: string;
|
|
16
|
+
/**
|
|
17
|
+
* The tenant the fact belongs to, stamped from the work that published it. A consumer handles
|
|
18
|
+
* the event in that tenant's scope, so its reads and writes stay in the tenant. Absent for a
|
|
19
|
+
* fact of no tenant (the platform's own).
|
|
20
|
+
*/
|
|
21
|
+
readonly tenantId?: string;
|
|
16
22
|
}
|
|
17
23
|
//# sourceMappingURL=integration-event.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"integration-event.d.ts","sourceRoot":"","sources":["../../../src/application/events/integration-event.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,gBAAgB,CAAC,OAAO,GAAG,OAAO;IACjD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,mDAAmD;IACnD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,oFAAoF;IACpF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,oFAAoF;IACpF,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"integration-event.d.ts","sourceRoot":"","sources":["../../../src/application/events/integration-event.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,gBAAgB,CAAC,OAAO,GAAG,OAAO;IACjD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,mDAAmD;IACnD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,oFAAoF;IACpF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,oFAAoF;IACpF,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B"}
|
|
@@ -2,9 +2,10 @@ import type { ExecutionScope } from '../ports/execution-scope.js';
|
|
|
2
2
|
import type { IntegrationEventPublisher } from '../ports/integration-event-publisher.js';
|
|
3
3
|
/**
|
|
4
4
|
* Decorates a publisher: an event published without `correlationId` takes the one of the work
|
|
5
|
-
* in progress, so everything one stimulus causes can be found again
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* in progress, so everything one stimulus causes can be found again, and one without `tenantId`
|
|
6
|
+
* the tenant of that work, so its consumers run in the same tenant. What an event names is
|
|
7
|
+
* kept, and outside of any execution context nothing is stamped. The name of the transport
|
|
8
|
+
* (`messagingSystem`) is passed on.
|
|
8
9
|
*/
|
|
9
10
|
export declare function scopedPublisher(publisher: IntegrationEventPublisher, scope: ExecutionScope): IntegrationEventPublisher;
|
|
10
11
|
//# sourceMappingURL=scoped-publisher.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scoped-publisher.d.ts","sourceRoot":"","sources":["../../../src/application/events/scoped-publisher.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,yCAAyC,CAAC;AAIzF
|
|
1
|
+
{"version":3,"file":"scoped-publisher.d.ts","sourceRoot":"","sources":["../../../src/application/events/scoped-publisher.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,yCAAyC,CAAC;AAIzF;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,yBAAyB,EACpC,KAAK,EAAE,cAAc,GACpB,yBAAyB,CAO3B"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { messagingSystemOf } from './messaging-system-of.js';
|
|
2
2
|
/**
|
|
3
3
|
* Decorates a publisher: an event published without `correlationId` takes the one of the work
|
|
4
|
-
* in progress, so everything one stimulus causes can be found again
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* in progress, so everything one stimulus causes can be found again, and one without `tenantId`
|
|
5
|
+
* the tenant of that work, so its consumers run in the same tenant. What an event names is
|
|
6
|
+
* kept, and outside of any execution context nothing is stamped. The name of the transport
|
|
7
|
+
* (`messagingSystem`) is passed on.
|
|
7
8
|
*/
|
|
8
9
|
export function scopedPublisher(publisher, scope) {
|
|
9
10
|
const messagingSystem = messagingSystemOf(publisher);
|
|
@@ -13,9 +14,14 @@ export function scopedPublisher(publisher, scope) {
|
|
|
13
14
|
};
|
|
14
15
|
}
|
|
15
16
|
function correlated(event, context) {
|
|
16
|
-
if (
|
|
17
|
+
if (context === undefined) {
|
|
17
18
|
return event;
|
|
18
19
|
}
|
|
19
|
-
|
|
20
|
+
const { correlationId, tenantId } = context;
|
|
21
|
+
return {
|
|
22
|
+
...event,
|
|
23
|
+
...(event.correlationId === undefined ? { correlationId } : {}),
|
|
24
|
+
...(event.tenantId === undefined && tenantId !== undefined ? { tenantId } : {}),
|
|
25
|
+
};
|
|
20
26
|
}
|
|
21
27
|
//# sourceMappingURL=scoped-publisher.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scoped-publisher.js","sourceRoot":"","sources":["../../../src/application/events/scoped-publisher.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D
|
|
1
|
+
{"version":3,"file":"scoped-publisher.js","sourceRoot":"","sources":["../../../src/application/events/scoped-publisher.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAC7B,SAAoC,EACpC,KAAqB;IAErB,MAAM,eAAe,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAErD,OAAO;QACL,OAAO,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QACjG,GAAG,CAAC,eAAe,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,CAAC;KAC9D,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,KAAuB,EAAE,OAAqC;IAChF,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;IAE5C,OAAO;QACL,GAAG,KAAK;QACR,GAAG,CAAC,KAAK,CAAC,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/D,GAAG,CAAC,KAAK,CAAC,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAChF,CAAC;AACJ,CAAC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Actor } from '../actor/actor.js';
|
|
2
2
|
import type { Session } from '../session/session.js';
|
|
3
|
+
import type { TenantElevation } from '../tenancy/tenant-elevation.js';
|
|
3
4
|
import type { ExecutionContextExtensionValues } from './execution-context-extension-values.js';
|
|
4
5
|
import type { ExecutionOrigin } from './execution-origin.js';
|
|
5
6
|
/**
|
|
@@ -14,6 +15,8 @@ export interface ExecutionContext {
|
|
|
14
15
|
readonly actor: Actor;
|
|
15
16
|
readonly session?: Session;
|
|
16
17
|
readonly tenantId?: string;
|
|
18
|
+
/** Platform staff reading over tenants, opened by `acrossTenants` and audited. Absent otherwise. */
|
|
19
|
+
readonly elevation?: TenantElevation;
|
|
17
20
|
readonly locale?: string;
|
|
18
21
|
/** The instant after which the result is useless to the caller. */
|
|
19
22
|
readonly deadline?: Date;
|
|
@@ -23,6 +26,9 @@ export interface ExecutionContext {
|
|
|
23
26
|
readonly extensions: ExecutionContextExtensionValues;
|
|
24
27
|
}
|
|
25
28
|
export type ExecutionContextInit = Omit<ExecutionContext, 'extensions' | 'tenantId'> & Partial<Pick<ExecutionContext, 'extensions' | 'tenantId'>>;
|
|
26
|
-
/**
|
|
29
|
+
/**
|
|
30
|
+
* Fills what can be derived: the tenant of the actor, no extension. A tenant id outside the
|
|
31
|
+
* grammar of `isTenantId` is refused (`InvalidTenantIdError`), whatever named it.
|
|
32
|
+
*/
|
|
27
33
|
export declare function executionContext(init: ExecutionContextInit): ExecutionContext;
|
|
28
34
|
//# sourceMappingURL=execution-context.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execution-context.d.ts","sourceRoot":"","sources":["../../../src/application/execution/execution-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"execution-context.d.ts","sourceRoot":"","sources":["../../../src/application/execution/execution-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAErD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACtE,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,yCAAyC,CAAC;AAC/F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,8EAA8E;IAC9E,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,2EAA2E;IAC3E,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,oGAAoG;IACpG,QAAQ,CAAC,SAAS,CAAC,EAAE,eAAe,CAAC;IACrC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,mEAAmE;IACnE,QAAQ,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC;IACzB,mGAAmG;IACnG,QAAQ,CAAC,WAAW,CAAC,EAAE,IAAI,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IACjC,QAAQ,CAAC,UAAU,EAAE,+BAA+B,CAAC;CACtD;AAED,MAAM,MAAM,oBAAoB,GAAG,IAAI,CAAC,gBAAgB,EAAE,YAAY,GAAG,UAAU,CAAC,GAClF,OAAO,CAAC,IAAI,CAAC,gBAAgB,EAAE,YAAY,GAAG,UAAU,CAAC,CAAC,CAAC;AAE7D;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,oBAAoB,GAAG,gBAAgB,CAS7E"}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
import { assertTenantId } from '../tenancy/assert-tenant-id.js';
|
|
2
|
+
/**
|
|
3
|
+
* Fills what can be derived: the tenant of the actor, no extension. A tenant id outside the
|
|
4
|
+
* grammar of `isTenantId` is refused (`InvalidTenantIdError`), whatever named it.
|
|
5
|
+
*/
|
|
2
6
|
export function executionContext(init) {
|
|
3
|
-
const
|
|
7
|
+
const named = init.tenantId ?? init.actor.tenantId;
|
|
8
|
+
const tenantId = named === undefined ? undefined : assertTenantId(named);
|
|
4
9
|
return Object.freeze({
|
|
5
10
|
...init,
|
|
6
11
|
...(tenantId === undefined ? {} : { tenantId }),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execution-context.js","sourceRoot":"","sources":["../../../src/application/execution/execution-context.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"execution-context.js","sourceRoot":"","sources":["../../../src/application/execution/execution-context.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AA+BhE;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAA0B;IACzD,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC;IACnD,MAAM,QAAQ,GAAG,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IAEzE,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,GAAG,IAAI;QACP,GAAG,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC;QAC/C,UAAU,EAAE,IAAI,CAAC,UAAU,IAAI,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;KACjD,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"log-fields-of.d.ts","sourceRoot":"","sources":["../../../src/application/execution/log-fields-of.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,iGAAiG;AACjG,wBAAgB,WAAW,CAAC,OAAO,EAAE,gBAAgB,GAAG,SAAS,
|
|
1
|
+
{"version":3,"file":"log-fields-of.d.ts","sourceRoot":"","sources":["../../../src/application/execution/log-fields-of.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,iGAAiG;AACjG,wBAAgB,WAAW,CAAC,OAAO,EAAE,gBAAgB,GAAG,SAAS,CAUhE"}
|
|
@@ -6,6 +6,7 @@ export function logFieldsOf(context) {
|
|
|
6
6
|
actorId: context.actor.id,
|
|
7
7
|
...(context.causationId === undefined ? {} : { causationId: context.causationId }),
|
|
8
8
|
...(context.tenantId === undefined ? {} : { tenantId: context.tenantId }),
|
|
9
|
+
...(context.elevation === undefined ? {} : { elevation: context.elevation.reason }),
|
|
9
10
|
...(context.session?.impersonatedBy === undefined ? {} : { impersonatedBy: context.session.impersonatedBy }),
|
|
10
11
|
};
|
|
11
12
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"log-fields-of.js","sourceRoot":"","sources":["../../../src/application/execution/log-fields-of.ts"],"names":[],"mappings":"AAGA,iGAAiG;AACjG,MAAM,UAAU,WAAW,CAAC,OAAyB;IACnD,OAAO;QACL,aAAa,EAAE,OAAO,CAAC,aAAa;QACpC,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE;QACzB,GAAG,CAAC,OAAO,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC;QAClF,GAAG,CAAC,OAAO,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC;QACzE,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,cAAc,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,OAAO,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC;KAC7G,CAAC;AACJ,CAAC"}
|
|
1
|
+
{"version":3,"file":"log-fields-of.js","sourceRoot":"","sources":["../../../src/application/execution/log-fields-of.ts"],"names":[],"mappings":"AAGA,iGAAiG;AACjG,MAAM,UAAU,WAAW,CAAC,OAAyB;IACnD,OAAO;QACL,aAAa,EAAE,OAAO,CAAC,aAAa;QACpC,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE;QACzB,GAAG,CAAC,OAAO,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC;QAClF,GAAG,CAAC,OAAO,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC;QACzE,GAAG,CAAC,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;QACnF,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,cAAc,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,OAAO,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC;KAC7G,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The tenants that exist, for work that runs once per tenant: a job declared `tenancy:
|
|
3
|
+
* 'per-tenant'`, the provisioning of a schema or a database, a migration applied to each.
|
|
4
|
+
*/
|
|
5
|
+
export declare abstract class TenantDirectory {
|
|
6
|
+
abstract tenants(): Promise<readonly string[]>;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=tenant-directory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tenant-directory.d.ts","sourceRoot":"","sources":["../../../src/application/ports/tenant-directory.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,8BAAsB,eAAe;IAKnC,QAAQ,CAAC,OAAO,IAAI,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAAC;CAChD"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The tenants that exist, for work that runs once per tenant: a job declared `tenancy:
|
|
3
|
+
* 'per-tenant'`, the provisioning of a schema or a database, a migration applied to each.
|
|
4
|
+
*/
|
|
5
|
+
export class TenantDirectory {
|
|
6
|
+
static {
|
|
7
|
+
Object.defineProperty(this, 'tokenKey', { value: 'kernel.TenantDirectory' });
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=tenant-directory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tenant-directory.js","sourceRoot":"","sources":["../../../src/application/ports/tenant-directory.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,OAAgB,eAAe;IACnC;QACE,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,wBAAwB,EAAE,CAAC,CAAC;IAC/E,CAAC;CAGF"}
|
|
@@ -4,10 +4,12 @@ export interface JobExecutionStart {
|
|
|
4
4
|
readonly scheduledAt: Date;
|
|
5
5
|
/** The instant the timeout of the job ends the run, when it has one. */
|
|
6
6
|
readonly deadline?: Date;
|
|
7
|
+
/** For a job declared `tenancy: 'per-tenant'`: the tenant of this run. */
|
|
8
|
+
readonly tenantId?: string;
|
|
7
9
|
}
|
|
8
10
|
/**
|
|
9
11
|
* The execution context of one run: origin `schedule`, the system actor named after the job, a
|
|
10
|
-
* correlation of its own
|
|
12
|
+
* correlation of its own, the instant the run was due, and the tenant of a per-tenant run.
|
|
11
13
|
*/
|
|
12
14
|
export declare function executionContextOfJob(job: string, start: JobExecutionStart): ExecutionContext;
|
|
13
15
|
//# sourceMappingURL=execution-context-of-job.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execution-context-of-job.d.ts","sourceRoot":"","sources":["../../../src/application/scheduling/execution-context-of-job.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,gBAAgB,EAAoB,MAAM,mCAAmC,CAAC;AAE5F,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC;IAC3B,wEAAwE;IACxE,QAAQ,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"execution-context-of-job.d.ts","sourceRoot":"","sources":["../../../src/application/scheduling/execution-context-of-job.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,gBAAgB,EAAoB,MAAM,mCAAmC,CAAC;AAE5F,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC;IAC3B,wEAAwE;IACxE,QAAQ,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC;IACzB,0EAA0E;IAC1E,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,GAAG,gBAAgB,CAE7F"}
|
|
@@ -2,7 +2,7 @@ import { systemActor } from '../actor/system-actor.js';
|
|
|
2
2
|
import { executionContext } from '../execution/execution-context.js';
|
|
3
3
|
/**
|
|
4
4
|
* The execution context of one run: origin `schedule`, the system actor named after the job, a
|
|
5
|
-
* correlation of its own
|
|
5
|
+
* correlation of its own, the instant the run was due, and the tenant of a per-tenant run.
|
|
6
6
|
*/
|
|
7
7
|
export function executionContextOfJob(job, start) {
|
|
8
8
|
return executionContext({ ...start, actor: systemActor(job), origin: 'schedule' });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execution-context-of-job.js","sourceRoot":"","sources":["../../../src/application/scheduling/execution-context-of-job.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAyB,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;
|
|
1
|
+
{"version":3,"file":"execution-context-of-job.js","sourceRoot":"","sources":["../../../src/application/scheduling/execution-context-of-job.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAyB,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAW5F;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,GAAW,EAAE,KAAwB;IACzE,OAAO,gBAAgB,CAAC,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,WAAW,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;AACrF,CAAC"}
|
|
@@ -8,5 +8,7 @@ export interface JobExecution {
|
|
|
8
8
|
readonly attempt: number;
|
|
9
9
|
/** Aborted when the run exceeds its timeout or the scheduler stops: a long job checks it. */
|
|
10
10
|
readonly signal: AbortSignal;
|
|
11
|
+
/** The tenant of this run, for a job declared `tenancy: 'per-tenant'`. */
|
|
12
|
+
readonly tenantId?: string;
|
|
11
13
|
}
|
|
12
14
|
//# sourceMappingURL=job-execution.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"job-execution.d.ts","sourceRoot":"","sources":["../../../src/application/scheduling/job-execution.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,MAAM,WAAW,YAAY;IAC3B,2EAA2E;IAC3E,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC;IAC3B,yGAAyG;IACzG,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;IACzB,uGAAuG;IACvG,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,6FAA6F;IAC7F,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"job-execution.d.ts","sourceRoot":"","sources":["../../../src/application/scheduling/job-execution.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,MAAM,WAAW,YAAY;IAC3B,2EAA2E;IAC3E,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC;IAC3B,yGAAyG;IACzG,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;IACzB,uGAAuG;IACvG,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,6FAA6F;IAC7F,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,0EAA0E;IAC1E,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B"}
|
|
@@ -21,5 +21,11 @@ export interface JobOptions {
|
|
|
21
21
|
* an application running several runs it. Best effort: see the scheduler.
|
|
22
22
|
*/
|
|
23
23
|
readonly singleInstance?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* `global` (default): one run per occurrence, in no tenant. `per-tenant`: one run per tenant
|
|
26
|
+
* of the `TenantDirectory` for each occurrence, each in that tenant's execution scope, so the
|
|
27
|
+
* job reads and writes one tenant at a time; one failing tenant does not stop the others.
|
|
28
|
+
*/
|
|
29
|
+
readonly tenancy?: 'global' | 'per-tenant';
|
|
24
30
|
}
|
|
25
31
|
//# sourceMappingURL=job-options.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"job-options.d.ts","sourceRoot":"","sources":["../../../src/application/scheduling/job-options.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACpC;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;IACtC,6EAA6E;IAC7E,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,sHAAsH;IACtH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,uGAAuG;IACvG,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B;;;OAGG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"job-options.d.ts","sourceRoot":"","sources":["../../../src/application/scheduling/job-options.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACpC;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;IACtC,6EAA6E;IAC7E,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,sHAAsH;IACtH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,uGAAuG;IACvG,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B;;;OAGG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAClC;;;;OAIG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,GAAG,YAAY,CAAC;CAC5C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"job-policy.d.ts","sourceRoot":"","sources":["../../../src/application/scheduling/job-policy.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAGnD,iDAAiD;AACjD,MAAM,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC,GAAG,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;AAEhG,yFAAyF;AACzF,wBAAgB,SAAS,CAAC,OAAO,EAAE,UAAU,GAAG,SAAS,
|
|
1
|
+
{"version":3,"file":"job-policy.d.ts","sourceRoot":"","sources":["../../../src/application/scheduling/job-policy.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAGnD,iDAAiD;AACjD,MAAM,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC,GAAG,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;AAEhG,yFAAyF;AACzF,wBAAgB,SAAS,CAAC,OAAO,EAAE,UAAU,GAAG,SAAS,CAmBxD"}
|
|
@@ -3,15 +3,17 @@ import { parseDuration } from './parse-duration.js';
|
|
|
3
3
|
/** Validates the options and fills in the defaults. Throws `InvalidJobScheduleError`. */
|
|
4
4
|
export function jobPolicy(options) {
|
|
5
5
|
const { overlap = 'skip', missed = 'skip', timeoutMs, jitterMs = 0, enabled = true, singleInstance = true } = options;
|
|
6
|
+
const tenancy = options.tenancy ?? 'global';
|
|
6
7
|
assertOneOf('overlap', overlap, ['skip', 'queue']);
|
|
7
8
|
assertOneOf('missed', missed, ['skip', 'run-once']);
|
|
9
|
+
assertOneOf('tenancy', tenancy, ['global', 'per-tenant']);
|
|
8
10
|
if (!Number.isSafeInteger(jitterMs) || jitterMs < 0) {
|
|
9
11
|
throw new InvalidJobScheduleError(`jitterMs is ${jitterMs}: a whole number of milliseconds, zero or more, is expected.`);
|
|
10
12
|
}
|
|
11
13
|
if (timeoutMs === undefined) {
|
|
12
|
-
return { overlap, missed, jitterMs, enabled, singleInstance };
|
|
14
|
+
return { overlap, missed, jitterMs, enabled, singleInstance, tenancy };
|
|
13
15
|
}
|
|
14
|
-
return { overlap, missed, jitterMs, enabled, singleInstance, timeoutMs: parseDuration(timeoutMs) };
|
|
16
|
+
return { overlap, missed, jitterMs, enabled, singleInstance, tenancy, timeoutMs: parseDuration(timeoutMs) };
|
|
15
17
|
}
|
|
16
18
|
function assertOneOf(option, value, allowed) {
|
|
17
19
|
if (allowed.includes(value)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"job-policy.js","sourceRoot":"","sources":["../../../src/application/scheduling/job-policy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAE1E,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAKpD,yFAAyF;AACzF,MAAM,UAAU,SAAS,CAAC,OAAmB;IAC3C,MAAM,EAAE,OAAO,GAAG,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,SAAS,EAAE,QAAQ,GAAG,CAAC,EAAE,OAAO,GAAG,IAAI,EAAE,cAAc,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"job-policy.js","sourceRoot":"","sources":["../../../src/application/scheduling/job-policy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAE1E,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAKpD,yFAAyF;AACzF,MAAM,UAAU,SAAS,CAAC,OAAmB;IAC3C,MAAM,EAAE,OAAO,GAAG,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,SAAS,EAAE,QAAQ,GAAG,CAAC,EAAE,OAAO,GAAG,IAAI,EAAE,cAAc,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;IACtH,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,QAAQ,CAAC;IAE5C,WAAW,CAAC,SAAS,EAAE,OAAO,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACnD,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;IACpD,WAAW,CAAC,SAAS,EAAE,OAAO,EAAE,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC;IAE1D,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;QACpD,MAAM,IAAI,uBAAuB,CAC/B,eAAe,QAAQ,8DAA8D,CACtF,CAAC;IACJ,CAAC;IAED,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,CAAC;IACzE,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,SAAS,EAAE,aAAa,CAAC,SAAS,CAAC,EAAE,CAAC;AAC9G,CAAC;AAED,SAAS,WAAW,CAAC,MAAc,EAAE,KAAa,EAAE,OAA0B;IAC5E,IAAI,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO;IACT,CAAC;IAED,MAAM,IAAI,uBAAuB,CAAC,GAAG,MAAM,QAAQ,KAAK,aAAa,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;AAC1G,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { SessionScope } from './session-scope.js';
|
|
2
|
+
import type { Session } from './session.js';
|
|
3
|
+
/** Whether the session was granted the scope; a request without a session was granted none. */
|
|
4
|
+
export declare function hasScope(session: Session | undefined, scope: SessionScope): boolean;
|
|
5
|
+
//# sourceMappingURL=has-scope.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"has-scope.d.ts","sourceRoot":"","sources":["../../../src/application/session/has-scope.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE5C,+FAA+F;AAC/F,wBAAgB,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAEnF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"has-scope.js","sourceRoot":"","sources":["../../../src/application/session/has-scope.ts"],"names":[],"mappings":"AAGA,+FAA+F;AAC/F,MAAM,UAAU,QAAQ,CAAC,OAA4B,EAAE,KAAmB;IACxE,OAAO,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC;AACnD,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { SessionScopes } from './session-scopes.js';
|
|
2
|
+
/** A scope of the project's vocabulary once `SessionScopes` declares one, any string before. */
|
|
3
|
+
export type SessionScope = [keyof SessionScopes] extends [never] ? string : Extract<keyof SessionScopes, string>;
|
|
4
|
+
//# sourceMappingURL=session-scope.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-scope.d.ts","sourceRoot":"","sources":["../../../src/application/session/session-scope.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,gGAAgG;AAChG,MAAM,MAAM,YAAY,GAAG,CAAC,MAAM,aAAa,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,aAAa,EAAE,MAAM,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-scope.js","sourceRoot":"","sources":["../../../src/application/session/session-scope.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The vocabulary of the scopes a project grants its clients, by declaration merging, so that a
|
|
3
|
+
* guard names only scopes that exist:
|
|
4
|
+
*
|
|
5
|
+
* declare module '@ddd-ts-kit/kernel' {
|
|
6
|
+
* interface SessionScopes { readonly 'invoices:read': true; readonly 'invoices:write': true }
|
|
7
|
+
* }
|
|
8
|
+
*/
|
|
9
|
+
export interface SessionScopes {
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=session-scopes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-scopes.d.ts","sourceRoot":"","sources":["../../../src/application/session/session-scopes.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,WAAW,aAAa;CAAG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-scopes.js","sourceRoot":"","sources":["../../../src/application/session/session-scopes.ts"],"names":[],"mappings":""}
|
|
@@ -22,6 +22,12 @@ export interface Session {
|
|
|
22
22
|
/** IANA time zone, for example `Europe/Paris`. */
|
|
23
23
|
readonly timeZone?: string;
|
|
24
24
|
readonly client?: SessionClient;
|
|
25
|
+
/**
|
|
26
|
+
* What the credential allows whoever presents it (the OAuth 2.0 `scope` of the token): a
|
|
27
|
+
* limit on the client, checked at the edge (`HasScope`), never what the actor may do, which
|
|
28
|
+
* stays a permission of the use case. Absent when the credential carries none.
|
|
29
|
+
*/
|
|
30
|
+
readonly scopes?: readonly string[];
|
|
25
31
|
readonly extensions: SessionExtensionValues;
|
|
26
32
|
}
|
|
27
33
|
//# sourceMappingURL=session.d.ts.map
|