@spine-event-engine/auth 2.0.0-snapshot.25 → 2.0.0-snapshot.28

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 (82) hide show
  1. package/README.md +128 -11
  2. package/REFERENCE.md +166 -12
  3. package/dist/gateway/dynamic-unary-forwarder.d.ts +62 -3
  4. package/dist/gateway/dynamic-unary-forwarder.d.ts.map +1 -1
  5. package/dist/gateway/dynamic-unary-forwarder.js +189 -10
  6. package/dist/gateway/dynamic-unary-forwarder.js.map +1 -1
  7. package/dist/gateway/index.d.ts +5 -0
  8. package/dist/gateway/index.d.ts.map +1 -1
  9. package/dist/gateway/index.js +65 -7
  10. package/dist/gateway/index.js.map +1 -1
  11. package/dist/index.d.ts +60 -3
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +4 -0
  14. package/dist/index.js.map +1 -1
  15. package/dist/native/index.d.ts +43 -3
  16. package/dist/native/index.d.ts.map +1 -1
  17. package/dist/native/index.js +178 -32
  18. package/dist/native/index.js.map +1 -1
  19. package/dist/oidc/contracts.d.ts +18 -4
  20. package/dist/oidc/contracts.d.ts.map +1 -1
  21. package/dist/oidc/flow-store.d.ts +143 -0
  22. package/dist/oidc/flow-store.d.ts.map +1 -0
  23. package/dist/oidc/flow-store.js +184 -0
  24. package/dist/oidc/flow-store.js.map +1 -0
  25. package/dist/oidc/index.d.ts +29 -9
  26. package/dist/oidc/index.d.ts.map +1 -1
  27. package/dist/oidc/index.js +611 -152
  28. package/dist/oidc/index.js.map +1 -1
  29. package/dist/oidc/persistent-flow-store.d.ts +117 -0
  30. package/dist/oidc/persistent-flow-store.d.ts.map +1 -0
  31. package/dist/oidc/persistent-flow-store.js +413 -0
  32. package/dist/oidc/persistent-flow-store.js.map +1 -0
  33. package/dist/oidc/records.d.ts +15 -0
  34. package/dist/oidc/records.d.ts.map +1 -0
  35. package/dist/oidc/records.js +91 -0
  36. package/dist/oidc/records.js.map +1 -0
  37. package/dist/providers/index.d.ts +10 -5
  38. package/dist/providers/index.d.ts.map +1 -1
  39. package/dist/providers/index.js +103 -30
  40. package/dist/providers/index.js.map +1 -1
  41. package/dist/request/index.d.ts +3 -0
  42. package/dist/request/index.d.ts.map +1 -1
  43. package/dist/request/index.js +17 -1
  44. package/dist/request/index.js.map +1 -1
  45. package/dist/sessions/cookies.d.ts +46 -8
  46. package/dist/sessions/cookies.d.ts.map +1 -1
  47. package/dist/sessions/cookies.js +269 -47
  48. package/dist/sessions/cookies.js.map +1 -1
  49. package/dist/sessions/opaque-session-store.d.ts +143 -0
  50. package/dist/sessions/opaque-session-store.d.ts.map +1 -0
  51. package/dist/sessions/opaque-session-store.js +185 -0
  52. package/dist/sessions/opaque-session-store.js.map +1 -0
  53. package/dist/sessions/opaque.d.ts +93 -106
  54. package/dist/sessions/opaque.d.ts.map +1 -1
  55. package/dist/sessions/opaque.js +501 -232
  56. package/dist/sessions/opaque.js.map +1 -1
  57. package/dist/sessions/persistent-opaque-session-store.d.ts +105 -0
  58. package/dist/sessions/persistent-opaque-session-store.d.ts.map +1 -0
  59. package/dist/sessions/persistent-opaque-session-store.js +333 -0
  60. package/dist/sessions/persistent-opaque-session-store.js.map +1 -0
  61. package/dist/sessions/persistent-token-revocations.d.ts +90 -0
  62. package/dist/sessions/persistent-token-revocations.d.ts.map +1 -0
  63. package/dist/sessions/persistent-token-revocations.js +422 -0
  64. package/dist/sessions/persistent-token-revocations.js.map +1 -0
  65. package/dist/sessions/session-lifetime.d.ts +67 -0
  66. package/dist/sessions/session-lifetime.d.ts.map +1 -0
  67. package/dist/sessions/session-lifetime.js +165 -0
  68. package/dist/sessions/session-lifetime.js.map +1 -0
  69. package/dist/sessions/session-record.d.ts +15 -0
  70. package/dist/sessions/session-record.d.ts.map +1 -0
  71. package/dist/sessions/session-record.js +109 -0
  72. package/dist/sessions/session-record.js.map +1 -0
  73. package/dist/sessions/signed.d.ts +5 -4
  74. package/dist/sessions/signed.d.ts.map +1 -1
  75. package/dist/sessions/signed.js +212 -74
  76. package/dist/sessions/signed.js.map +1 -1
  77. package/dist/subscriptions/index.d.ts +35 -3
  78. package/dist/subscriptions/index.d.ts.map +1 -1
  79. package/dist/subscriptions/index.js +680 -134
  80. package/dist/subscriptions/index.js.map +1 -1
  81. package/dist/tsconfig.tsbuildinfo +1 -1
  82. package/package.json +20 -6
@@ -0,0 +1,422 @@
1
+ /*
2
+ * Copyright 2026, CodeMatters. All rights reserved.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5
+ * in compliance with the License. You may obtain a copy of the License at
6
+ *
7
+ * https://www.apache.org/licenses/LICENSE-2.0
8
+ *
9
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
10
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11
+ * or implied. See the License for the specific language governing permissions and limitations under
12
+ * the License.
13
+ */
14
+ import { createHash } from "node:crypto";
15
+ import { create } from "@bufbuild/protobuf";
16
+ import { Time } from "@spine-event-engine/core/time";
17
+ import { TokenRevocationSchema } from "@spine-event-engine/proto/auth";
18
+ import { ColumnTypes, defaultQueryCandidateLimit, RecordColumn, RecordSpec, } from "@spine-event-engine/storage";
19
+ import { StoragePreparations } from "@spine-event-engine/storage/provider";
20
+ import { SessionRecords } from "./session-record.js";
21
+ /**
22
+ * Atomic scoped revocations retained through the last token-acceptance instant.
23
+ */
24
+ export class PersistentTokenRevocations {
25
+ /**
26
+ * Declares immediate revocation capability to signed sessions.
27
+ */
28
+ kind = "supported";
29
+ #issuer;
30
+ #audience;
31
+ #scope;
32
+ #storage;
33
+ #clock;
34
+ #closed = false;
35
+ #active = 0;
36
+ #drained;
37
+ #closing;
38
+ /**
39
+ * Binds one acquired handle to its scope and trusted maintenance clock.
40
+ * @param options Validated placement and scope.
41
+ * @param storage Selected record handle.
42
+ */
43
+ constructor(options, storage) {
44
+ this.#issuer = options.issuer;
45
+ this.#audience = options.audience;
46
+ this.#scope = RevocationKeys.scope(options.issuer, options.audience);
47
+ this.#storage = storage;
48
+ this.#clock = options.clock ?? Time.currentTime;
49
+ }
50
+ /**
51
+ * Acquires and optionally prepares the selected indexed record family.
52
+ * With `createMissingStructures: false`, creation and later operations never
53
+ * check or create physical structures. Missing structures fail through ordinary
54
+ * storage operations. The default prepares the selected structure before return.
55
+ * @param options Shared factory, group, scope and preparation policy.
56
+ * @returns Ready revocation source, or a non-preparing handle when explicitly requested.
57
+ */
58
+ static async create(options) {
59
+ RevocationKeys.nonempty(options.issuer, "issuer");
60
+ RevocationKeys.nonempty(options.audience, "audience");
61
+ const storage = options.storageFactory.createRecordStorage(context, spec, options.group, {
62
+ prepareOnAccess: false,
63
+ });
64
+ try {
65
+ if (!storage.atomicCompareAndSet)
66
+ throw new Error("Token revocations require atomic compare-and-set.");
67
+ if (options.createMissingStructures !== false)
68
+ await StoragePreparations.for(options.storageFactory).prepareRecord(context, spec, options.group, "create");
69
+ return new PersistentTokenRevocations(options, storage);
70
+ }
71
+ catch (error) {
72
+ try {
73
+ storage.close();
74
+ }
75
+ catch (closeError) {
76
+ throw new AggregateError([error, closeError], "Revocation preparation and cleanup failed.");
77
+ }
78
+ throw error;
79
+ }
80
+ }
81
+ /**
82
+ * Reads the exact scoped token identifier by primary key.
83
+ * @param jti Token ID produced by the signed-session strategy.
84
+ * @returns Whether the scoped revocation is still within its inclusive deadline.
85
+ */
86
+ isRevoked(jti) {
87
+ return this.#run(async () => {
88
+ const id = RevocationKeys.id(this.#issuer, this.#audience, jti);
89
+ const found = await this.#storage.read(id);
90
+ this.#checkOpen();
91
+ if (found?.issuer !== this.#issuer ||
92
+ found.audience !== this.#audience ||
93
+ found.tokenId !== jti)
94
+ return false;
95
+ return (SessionRecords.compare(SessionRecords.deadline(this.#clock()), RevocationKeys.deadline(found)) <= 0);
96
+ });
97
+ }
98
+ /**
99
+ * Stores the maximum full last-acceptance deadline through atomic CAS.
100
+ * @param jti Token ID produced by the signed-session strategy.
101
+ * @param expiresAt Inclusive last valid instant, already including strategy skew.
102
+ * @returns Completion after a deadline no shorter than the supplied instant is stored.
103
+ */
104
+ revoke(jti, expiresAt) {
105
+ return this.#run(async () => {
106
+ const proposed = this.#record(jti, expiresAt);
107
+ for (;;) {
108
+ this.#checkOpen();
109
+ const current = await this.#storage.read(proposed.id);
110
+ this.#checkOpen();
111
+ if (current !== undefined && RevocationKeys.compare(current, proposed) >= 0)
112
+ return;
113
+ const updated = current === undefined
114
+ ? proposed
115
+ : create(TokenRevocationSchema, { ...current, whenExpires: proposed.whenExpires });
116
+ if (await this.#storage.compareAndSet(proposed.id, current, updated)) {
117
+ this.#checkOpen();
118
+ return;
119
+ }
120
+ }
121
+ });
122
+ }
123
+ /**
124
+ * Removes records strictly before an application-selected trusted cutoff.
125
+ * A record at the cutoff remains, because its token is still valid there.
126
+ * Concurrently extended records survive conditional deletion; a changed
127
+ * candidate may require a later invocation. Failure or cancellation rejects
128
+ * after any already completed removals.
129
+ * @param cutoff Current-or-earlier exact maintenance cutoff.
130
+ * @param signal Optional maintenance cancellation.
131
+ * @returns Number of confirmed removals in this invocation.
132
+ */
133
+ purgeExpired(cutoff, signal) {
134
+ return this.#run(async () => {
135
+ const valid = SessionRecords.deadline(cutoff);
136
+ signal?.throwIfAborted();
137
+ if (SessionRecords.compare(valid, SessionRecords.deadline(this.#clock())) > 0)
138
+ throw new RangeError("Purge cutoff cannot be later than the trusted clock.");
139
+ return this.#purge(valid, signal);
140
+ });
141
+ }
142
+ /**
143
+ * Closes the selected handle after fencing and draining admitted work.
144
+ * The shared factory remains open.
145
+ * @returns Completion after the selected handle is closed.
146
+ */
147
+ close() {
148
+ if (this.#closing !== undefined)
149
+ return this.#closing;
150
+ this.#closed = true;
151
+ this.#closing = this.#finishClose();
152
+ return this.#closing;
153
+ }
154
+ /**
155
+ * Builds one complete scoped record with its exact supplied deadline.
156
+ * @param jti Token identifier to revoke.
157
+ * @param expiresAt Full last-acceptance deadline.
158
+ * @returns Complete persisted record.
159
+ */
160
+ #record(jti, expiresAt) {
161
+ return create(TokenRevocationSchema, {
162
+ id: RevocationKeys.id(this.#issuer, this.#audience, jti),
163
+ issuer: this.#issuer,
164
+ audience: this.#audience,
165
+ tokenId: jti,
166
+ whenExpires: SessionRecords.deadline(expiresAt),
167
+ });
168
+ }
169
+ /**
170
+ * Completes closure after admitted storage operations settle.
171
+ * @returns Completion after handle release.
172
+ */
173
+ async #finishClose() {
174
+ if (this.#active > 0)
175
+ await new Promise((resolve) => (this.#drained = resolve));
176
+ this.#storage.close();
177
+ }
178
+ /**
179
+ * Admits one operation while the handle is open and tracks its settlement.
180
+ * @typeParam T Operation result.
181
+ * @param work Storage operation to run.
182
+ * @returns Settled operation result.
183
+ */
184
+ async #run(work) {
185
+ this.#checkOpen();
186
+ this.#active += 1;
187
+ try {
188
+ return await work();
189
+ }
190
+ finally {
191
+ this.#active -= 1;
192
+ if (this.#active === 0)
193
+ this.#drained?.();
194
+ }
195
+ }
196
+ /**
197
+ * Rejects work after closure, including loops resumed from awaited storage.
198
+ */
199
+ #checkOpen() {
200
+ if (this.#closed)
201
+ throw new Error("Token revocations are closed.");
202
+ }
203
+ /**
204
+ * Traverses flow-scoped indexed expiry groups before the cutoff.
205
+ * @param cutoff Strict maintenance cutoff.
206
+ * @param signal Optional cancellation.
207
+ * @returns Number of confirmed removals.
208
+ */
209
+ async #purge(cutoff, signal) {
210
+ const lower = RevocationKeys.lower(this.#scope);
211
+ const upper = RevocationKeys.upper(this.#scope, cutoff);
212
+ let completed;
213
+ let removed = 0;
214
+ for (;;) {
215
+ signal?.throwIfAborted();
216
+ this.#checkOpen();
217
+ const key = await this.#nextExpiry(lower, upper, completed);
218
+ signal?.throwIfAborted();
219
+ this.#checkOpen();
220
+ if (key === undefined)
221
+ return removed;
222
+ const [count, raced] = await this.#purgeTie(key, cutoff, signal);
223
+ removed += count;
224
+ if (raced)
225
+ return removed;
226
+ completed = key;
227
+ }
228
+ }
229
+ /**
230
+ * Selects the next exact indexed expiry in this issuer/audience scope.
231
+ * @param lower First possible key in scope.
232
+ * @param upper Strict cutoff key in scope.
233
+ * @param completed Last drained expiry key.
234
+ * @returns Next candidate expiry key, if any.
235
+ */
236
+ async #nextExpiry(lower, upper, completed) {
237
+ const entries = await this.#storage.queryPlanEntries({
238
+ predicate: {
239
+ kind: "all",
240
+ predicates: [
241
+ { kind: "comparison", column: "expires_order", operator: "lessThan", value: upper },
242
+ {
243
+ kind: "comparison",
244
+ column: "expires_order",
245
+ operator: completed === undefined ? "greaterOrEqual" : "greaterThan",
246
+ value: completed ?? lower,
247
+ },
248
+ ],
249
+ },
250
+ order: [{ column: "expires_order", direction: "asc" }],
251
+ limit: 1,
252
+ });
253
+ const first = entries[0];
254
+ return first === undefined ? undefined : RevocationKeys.order(first.record);
255
+ }
256
+ /**
257
+ * Pages one exact expiry group by immutable storage ID.
258
+ * @param key Selected exact expiry key.
259
+ * @param cutoff Strict maintenance cutoff.
260
+ * @param signal Optional cancellation.
261
+ * @returns Removed count and whether a candidate changed concurrently.
262
+ */
263
+ async #purgeTie(key, cutoff, signal) {
264
+ let after;
265
+ let removed = 0;
266
+ let raced = false;
267
+ for (;;) {
268
+ signal?.throwIfAborted();
269
+ const entries = await this.#storage.queryEntries({
270
+ filters: [{ column: "expires_order", value: key }],
271
+ sort: [{ field: "id" }],
272
+ limit: defaultQueryCandidateLimit,
273
+ ...(after === undefined ? {} : { after }),
274
+ });
275
+ signal?.throwIfAborted();
276
+ this.#checkOpen();
277
+ if (entries.length === 0)
278
+ return [removed, raced];
279
+ for (const entry of entries) {
280
+ const result = await this.#removeEligible(entry.record, cutoff, signal);
281
+ if (result === true)
282
+ removed += 1;
283
+ if (result === false)
284
+ raced = true;
285
+ }
286
+ const last = entries.at(-1);
287
+ if (last === undefined)
288
+ return [removed, raced];
289
+ after = { id: last.id, values: [{ field: "id", value: last.id }] };
290
+ }
291
+ }
292
+ /**
293
+ * Conditionally removes one scoped record still strictly before the cutoff.
294
+ * @param candidate Selected record snapshot.
295
+ * @param cutoff Strict maintenance cutoff.
296
+ * @param signal Optional cancellation.
297
+ * @returns True if removed, false if changed, undefined if ineligible.
298
+ */
299
+ async #removeEligible(candidate, cutoff, signal) {
300
+ signal?.throwIfAborted();
301
+ this.#checkOpen();
302
+ if (candidate.issuer !== this.#issuer ||
303
+ candidate.audience !== this.#audience ||
304
+ RevocationKeys.compareDeadline(candidate, cutoff) >= 0)
305
+ return undefined;
306
+ const removed = await this.#storage.compareAndSet(candidate.id, candidate, undefined);
307
+ signal?.throwIfAborted();
308
+ this.#checkOpen();
309
+ return removed;
310
+ }
311
+ }
312
+ /**
313
+ * Exact scope, identity and expiry encodings for signed revocations.
314
+ */
315
+ const RevocationKeys = Object.freeze({
316
+ /**
317
+ * Validates an identifier without imposing a new length policy.
318
+ *
319
+ * @param value Identifier supplied by the selected strategy or application.
320
+ * @param name Error context.
321
+ * @returns Validated identifier.
322
+ */
323
+ nonempty(value, name) {
324
+ if (typeof value !== "string" || value.length === 0)
325
+ throw new TypeError(`${name} must be nonempty.`);
326
+ return value;
327
+ },
328
+ /**
329
+ * Creates the unambiguous issuer and audience scope digest.
330
+ *
331
+ * @param issuer Issuing service.
332
+ * @param audience Recipient.
333
+ * @returns Fixed scope prefix for indexed expiry.
334
+ */
335
+ scope(issuer, audience) {
336
+ return createHash("sha256")
337
+ .update(JSON.stringify([issuer, audience]))
338
+ .digest();
339
+ },
340
+ /**
341
+ * Creates the scoped token-ID digest for primary lookup.
342
+ *
343
+ * @param issuer Issuing service.
344
+ * @param audience Recipient.
345
+ * @param jti Token identifier.
346
+ * @returns Fixed storage ID.
347
+ */
348
+ id(issuer, audience, jti) {
349
+ RevocationKeys.nonempty(jti, "jti");
350
+ return createHash("sha256")
351
+ .update(JSON.stringify([issuer, audience, jti]))
352
+ .digest("hex");
353
+ },
354
+ /**
355
+ * Encodes the first possible expiry in a scope.
356
+ *
357
+ * @param scope Fixed issuer/audience digest.
358
+ * @returns Lower indexed bound.
359
+ */
360
+ lower(scope) {
361
+ return Buffer.concat([scope, Buffer.alloc(12)]);
362
+ },
363
+ /**
364
+ * Encodes one exact deadline within a scope.
365
+ *
366
+ * @param scope Fixed issuer/audience digest.
367
+ * @param cutoff Exact deadline.
368
+ * @returns Indexed bound.
369
+ */
370
+ upper(scope, cutoff) {
371
+ return Buffer.concat([scope, SessionRecords.orderKey(cutoff)]);
372
+ },
373
+ /**
374
+ * Encodes a record's scope and exact deadline for indexed ordering.
375
+ *
376
+ * @param record Complete scoped revocation.
377
+ * @returns Indexed order key.
378
+ */
379
+ order(record) {
380
+ return RevocationKeys.upper(RevocationKeys.scope(record.issuer, record.audience), RevocationKeys.deadline(record));
381
+ },
382
+ /**
383
+ * Reads one complete required deadline.
384
+ *
385
+ * @param record Revocation to check.
386
+ * @returns Validated exact deadline.
387
+ */
388
+ deadline(record) {
389
+ if (record.whenExpires === undefined)
390
+ throw new Error("Revocation has no deadline.");
391
+ return SessionRecords.deadline(record.whenExpires);
392
+ },
393
+ /**
394
+ * Compares two revocation records by exact deadline.
395
+ *
396
+ * @param left Current record.
397
+ * @param right Proposed record.
398
+ * @returns Exact timestamp ordering.
399
+ */
400
+ compare(left, right) {
401
+ return SessionRecords.compare(RevocationKeys.deadline(left), RevocationKeys.deadline(right));
402
+ },
403
+ /**
404
+ * Compares a record's exact deadline with an application cutoff.
405
+ *
406
+ * @param record Current revocation.
407
+ * @param cutoff Trusted maintenance cutoff.
408
+ * @returns Exact timestamp ordering.
409
+ */
410
+ compareDeadline(record, cutoff) {
411
+ return SessionRecords.compare(RevocationKeys.deadline(record), cutoff);
412
+ },
413
+ });
414
+ const context = { name: "__AUTH_TOKEN_REVOCATIONS__", multitenant: false };
415
+ const spec = new RecordSpec({
416
+ recordType: TokenRevocationSchema,
417
+ idKind: "string",
418
+ extractId: (record) => record.id,
419
+ columns: [new RecordColumn("expires_order", ColumnTypes.fixedBytes(44), RevocationKeys.order)],
420
+ indexes: [{ name: "expiry", columns: ["expires_order", "id"] }],
421
+ });
422
+ //# sourceMappingURL=persistent-token-revocations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"persistent-token-revocations.js","sourceRoot":"","sources":["../../src/sessions/persistent-token-revocations.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ import type { Timestamp } from "@bufbuild/protobuf/wkt";
2
+ /**
3
+ * Tracks process-local operation lifetimes by authenticated session identity.
4
+ */
5
+ export declare class SessionLifetimes {
6
+ #private;
7
+ /**
8
+ * Creates a registry using the strategy's trusted clock for exact expiry.
9
+ *
10
+ * @param clock Returns current Unix milliseconds, or undefined on failure.
11
+ */
12
+ constructor(clock: () => number | undefined);
13
+ /**
14
+ * Registers before the authoritative validity read.
15
+ *
16
+ * @param identity Authenticated stable session or token identity.
17
+ * @param operation Host-managed operation lifetime.
18
+ * @returns Monitor removed when the operation ends.
19
+ */
20
+ register(identity: string, operation: AbortSignal): SessionMonitor;
21
+ /**
22
+ * Stops current process operations for a stable authenticated identity.
23
+ *
24
+ * @param identity Stable session or scoped token identity.
25
+ */
26
+ invalidate(identity: string): void;
27
+ /**
28
+ * Stops every retained operation before strategy close drains work.
29
+ */
30
+ close(): void;
31
+ }
32
+ /**
33
+ * One operation's invalidation signal and exact expiry timer.
34
+ */
35
+ export declare class SessionMonitor {
36
+ #private;
37
+ /**
38
+ * Captures one host operation and its removal callback.
39
+ *
40
+ * @param operation Host cancellation signal.
41
+ * @param clock Strategy's trusted clock.
42
+ * @param onRemove Removes this monitor from the identity registry.
43
+ */
44
+ constructor(operation: AbortSignal, clock: () => number | undefined, onRemove: () => void);
45
+ /**
46
+ * Returns the captured invalidation signal.
47
+ *
48
+ * @returns Signal that aborts when this operation loses authority.
49
+ */
50
+ get signal(): AbortSignal;
51
+ /**
52
+ * Attaches host termination after registration.
53
+ */
54
+ attach(): void;
55
+ /**
56
+ * Accepts a resolved deadline only while the operation remains live.
57
+ *
58
+ * @param deadline Exact session expiry from the authoritative read.
59
+ * @returns Whether the session may be forwarded now.
60
+ */
61
+ ready(deadline: Timestamp): boolean;
62
+ /**
63
+ * Stops the local operation and releases its listener and timer.
64
+ */
65
+ release: () => void;
66
+ }
67
+ //# sourceMappingURL=session-lifetime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-lifetime.d.ts","sourceRoot":"","sources":["../../src/sessions/session-lifetime.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAExD;;GAEG;AACH,qBAAa,gBAAgB;;IAO3B;;;;OAIG;gBACS,KAAK,EAAE,MAAM,MAAM,GAAG,SAAS;IAI3C;;;;;;OAMG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,GAAG,cAAc;IAalE;;;;OAIG;IACH,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAIlC;;OAEG;IACH,KAAK,IAAI,IAAI;CAgBd;AAED;;GAEG;AACH,qBAAa,cAAc;;IAazB;;;;;;OAMG;gBACS,SAAS,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,MAAM,GAAG,SAAS,EAAE,QAAQ,EAAE,MAAM,IAAI;IAMzF;;;;OAIG;IACH,IAAI,MAAM,IAAI,WAAW,CAExB;IAED;;OAEG;IACH,MAAM,IAAI,IAAI;IAKd;;;;;OAKG;IACH,KAAK,CAAC,QAAQ,EAAE,SAAS,GAAG,OAAO;IAOnC;;OAEG;IACH,OAAO,QAAO,IAAI,CAOhB;CAuBH"}
@@ -0,0 +1,165 @@
1
+ /*
2
+ * Copyright 2026, CodeMatters. All rights reserved.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5
+ * in compliance with the License. You may obtain a copy of the License at
6
+ *
7
+ * https://www.apache.org/licenses/LICENSE-2.0
8
+ *
9
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
10
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11
+ * or implied. See the License for the specific language governing permissions and limitations under
12
+ * the License.
13
+ */
14
+ /**
15
+ * Tracks process-local operation lifetimes by authenticated session identity.
16
+ */
17
+ export class SessionLifetimes {
18
+ #clock;
19
+ #active = new Map();
20
+ #closed = false;
21
+ /**
22
+ * Creates a registry using the strategy's trusted clock for exact expiry.
23
+ *
24
+ * @param clock Returns current Unix milliseconds, or undefined on failure.
25
+ */
26
+ constructor(clock) {
27
+ this.#clock = clock;
28
+ }
29
+ /**
30
+ * Registers before the authoritative validity read.
31
+ *
32
+ * @param identity Authenticated stable session or token identity.
33
+ * @param operation Host-managed operation lifetime.
34
+ * @returns Monitor removed when the operation ends.
35
+ */
36
+ register(identity, operation) {
37
+ operation.throwIfAborted();
38
+ if (this.#closed)
39
+ throw new Error("Session strategy is closed.");
40
+ const monitor = new SessionMonitor(operation, this.#clock, () => {
41
+ this.#remove(identity, monitor);
42
+ });
43
+ const group = this.#active.get(identity) ?? new Set();
44
+ group.add(monitor);
45
+ this.#active.set(identity, group);
46
+ monitor.attach();
47
+ return monitor;
48
+ }
49
+ /**
50
+ * Stops current process operations for a stable authenticated identity.
51
+ *
52
+ * @param identity Stable session or scoped token identity.
53
+ */
54
+ invalidate(identity) {
55
+ for (const monitor of [...(this.#active.get(identity) ?? [])])
56
+ monitor.release();
57
+ }
58
+ /**
59
+ * Stops every retained operation before strategy close drains work.
60
+ */
61
+ close() {
62
+ this.#closed = true;
63
+ for (const identity of [...this.#active.keys()])
64
+ this.invalidate(identity);
65
+ }
66
+ /**
67
+ * Removes one completed monitor without affecting sibling operations.
68
+ *
69
+ * @param identity Stable identity used at registration.
70
+ * @param monitor Completed operation monitor.
71
+ */
72
+ #remove(identity, monitor) {
73
+ const group = this.#active.get(identity);
74
+ group?.delete(monitor);
75
+ if (group?.size === 0)
76
+ this.#active.delete(identity);
77
+ }
78
+ }
79
+ /**
80
+ * One operation's invalidation signal and exact expiry timer.
81
+ */
82
+ export class SessionMonitor {
83
+ #operation;
84
+ #clock;
85
+ #onRemove;
86
+ #controller = new AbortController();
87
+ #timer;
88
+ #deadline;
89
+ /**
90
+ * Captures one host operation and its removal callback.
91
+ *
92
+ * @param operation Host cancellation signal.
93
+ * @param clock Strategy's trusted clock.
94
+ * @param onRemove Removes this monitor from the identity registry.
95
+ */
96
+ constructor(operation, clock, onRemove) {
97
+ this.#operation = operation;
98
+ this.#clock = clock;
99
+ this.#onRemove = onRemove;
100
+ }
101
+ /**
102
+ * Returns the captured invalidation signal.
103
+ *
104
+ * @returns Signal that aborts when this operation loses authority.
105
+ */
106
+ get signal() {
107
+ return this.#controller.signal;
108
+ }
109
+ /**
110
+ * Attaches host termination after registration.
111
+ */
112
+ attach() {
113
+ this.#operation.addEventListener("abort", this.release, { once: true });
114
+ if (this.#operation.aborted)
115
+ this.release();
116
+ }
117
+ /**
118
+ * Accepts a resolved deadline only while the operation remains live.
119
+ *
120
+ * @param deadline Exact session expiry from the authoritative read.
121
+ * @returns Whether the session may be forwarded now.
122
+ */
123
+ ready(deadline) {
124
+ if (this.#controller.signal.aborted || this.#operation.aborted)
125
+ return false;
126
+ this.#deadline = deadline.seconds * 1000000000n + BigInt(deadline.nanos);
127
+ this.#schedule();
128
+ return !this.#controller.signal.aborted;
129
+ }
130
+ /**
131
+ * Stops the local operation and releases its listener and timer.
132
+ */
133
+ release = () => {
134
+ if (this.#controller.signal.aborted)
135
+ return;
136
+ this.#controller.abort();
137
+ this.#operation.removeEventListener("abort", this.release);
138
+ if (this.#timer !== undefined)
139
+ clearTimeout(this.#timer);
140
+ this.#timer = undefined;
141
+ this.#onRemove();
142
+ };
143
+ /**
144
+ * Schedules only the remaining interval, respecting platform timer range.
145
+ */
146
+ #schedule() {
147
+ const now = this.#clock();
148
+ const deadline = this.#deadline;
149
+ if (now === undefined || deadline === undefined) {
150
+ this.release();
151
+ return;
152
+ }
153
+ const remaining = deadline - BigInt(now) * 1000000n;
154
+ if (remaining <= 0n) {
155
+ this.release();
156
+ return;
157
+ }
158
+ const milliseconds = (remaining + 999999n) / 1000000n;
159
+ const delay = Number(milliseconds > 2147483647n ? 2147483647n : milliseconds);
160
+ this.#timer = setTimeout(() => {
161
+ this.#schedule();
162
+ }, delay);
163
+ }
164
+ }
165
+ //# sourceMappingURL=session-lifetime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-lifetime.js","sourceRoot":"","sources":["../../src/sessions/session-lifetime.ts"],"names":[],"mappings":"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"}