@spine-event-engine/auth 2.0.0-snapshot.2

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 (57) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +112 -0
  3. package/REFERENCE.md +94 -0
  4. package/dist/gateway/dynamic-subscription-creator.d.ts +52 -0
  5. package/dist/gateway/dynamic-subscription-creator.d.ts.map +1 -0
  6. package/dist/gateway/dynamic-subscription-creator.js +71 -0
  7. package/dist/gateway/dynamic-subscription-creator.js.map +1 -0
  8. package/dist/gateway/dynamic-unary-forwarder.d.ts +130 -0
  9. package/dist/gateway/dynamic-unary-forwarder.d.ts.map +1 -0
  10. package/dist/gateway/dynamic-unary-forwarder.js +185 -0
  11. package/dist/gateway/dynamic-unary-forwarder.js.map +1 -0
  12. package/dist/gateway/index.d.ts +164 -0
  13. package/dist/gateway/index.d.ts.map +1 -0
  14. package/dist/gateway/index.js +195 -0
  15. package/dist/gateway/index.js.map +1 -0
  16. package/dist/index.d.ts +433 -0
  17. package/dist/index.d.ts.map +1 -0
  18. package/dist/index.js +56 -0
  19. package/dist/index.js.map +1 -0
  20. package/dist/native/index.d.ts +182 -0
  21. package/dist/native/index.d.ts.map +1 -0
  22. package/dist/native/index.js +463 -0
  23. package/dist/native/index.js.map +1 -0
  24. package/dist/oidc/contracts.d.ts +334 -0
  25. package/dist/oidc/contracts.d.ts.map +1 -0
  26. package/dist/oidc/contracts.js +15 -0
  27. package/dist/oidc/contracts.js.map +1 -0
  28. package/dist/oidc/index.d.ts +41 -0
  29. package/dist/oidc/index.d.ts.map +1 -0
  30. package/dist/oidc/index.js +825 -0
  31. package/dist/oidc/index.js.map +1 -0
  32. package/dist/providers/index.d.ts +154 -0
  33. package/dist/providers/index.d.ts.map +1 -0
  34. package/dist/providers/index.js +574 -0
  35. package/dist/providers/index.js.map +1 -0
  36. package/dist/request/index.d.ts +10 -0
  37. package/dist/request/index.d.ts.map +1 -0
  38. package/dist/request/index.js +81 -0
  39. package/dist/request/index.js.map +1 -0
  40. package/dist/sessions/cookies.d.ts +104 -0
  41. package/dist/sessions/cookies.d.ts.map +1 -0
  42. package/dist/sessions/cookies.js +295 -0
  43. package/dist/sessions/cookies.js.map +1 -0
  44. package/dist/sessions/opaque.d.ts +163 -0
  45. package/dist/sessions/opaque.d.ts.map +1 -0
  46. package/dist/sessions/opaque.js +268 -0
  47. package/dist/sessions/opaque.js.map +1 -0
  48. package/dist/sessions/signed.d.ts +245 -0
  49. package/dist/sessions/signed.d.ts.map +1 -0
  50. package/dist/sessions/signed.js +534 -0
  51. package/dist/sessions/signed.js.map +1 -0
  52. package/dist/subscriptions/index.d.ts +463 -0
  53. package/dist/subscriptions/index.d.ts.map +1 -0
  54. package/dist/subscriptions/index.js +814 -0
  55. package/dist/subscriptions/index.js.map +1 -0
  56. package/dist/tsconfig.tsbuildinfo +1 -0
  57. package/package.json +37 -0
package/dist/index.js ADDED
@@ -0,0 +1,56 @@
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 {} from "@spine-event-engine/proto/client";
15
+ /**
16
+ * Builds the allowlisted transport facts used by authorization and diagnostics.
17
+ */
18
+ export const TransportFacts = Object.freeze({
19
+ // prettier-ignore
20
+ /**
21
+ * Builds allowlisted facts while omitting credentials and unknown headers.
22
+ * @param input Supplies raw transport facts and optional headers.
23
+ * @returns Returns the safe transport context.
24
+ */
25
+ from(input) {
26
+ const headers = Object.fromEntries(Object.entries(input.headers ?? {})
27
+ .filter((entry) => entry[1] !== undefined)
28
+ .map(([name, value]) => [name.toLowerCase(), value]));
29
+ return TransportFactsValues.compact({
30
+ service: input.service,
31
+ method: input.method,
32
+ origin: input.origin,
33
+ requestId: headers["x-request-id"],
34
+ correlationId: headers["x-correlation-id"],
35
+ peerAddress: input.peerAddress,
36
+ userAgent: input.userAgent,
37
+ });
38
+ },
39
+ });
40
+ export { IncomingRequests } from "./request/index.js";
41
+ const TransportFactsValues = Object.freeze({
42
+ compact(context) {
43
+ return Object.fromEntries(Object.entries(context).filter(([, value]) => value !== undefined));
44
+ },
45
+ });
46
+ export { UnaryGateway } from "./gateway/index.js";
47
+ export { OpaqueSessionCookies } from "./sessions/cookies.js";
48
+ export { OpaqueSessions } from "./sessions/opaque.js";
49
+ export { SignedSessions } from "./sessions/signed.js";
50
+ export { OidcFlow } from "./oidc/index.js";
51
+ export { createGitHubProvider, createGoogleProvider, createOidcProvider, discoverOidcProvider, } from "./providers/index.js";
52
+ export { InMemorySubscriptionBindings, SubscriptionGateway } from "./subscriptions/index.js";
53
+ export { createNativeGatewayServices, NativeSubscriptionCreator, SubscriptionUpdateRelay, } from "./native/index.js";
54
+ export { DynamicUnaryForwarder, } from "./gateway/dynamic-unary-forwarder.js";
55
+ export { DynamicSubscriptionCreator } from "./gateway/dynamic-subscription-creator.js";
56
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAYH,OAAO,EAKN,MAAM,kCAAkC,CAAC;AA8hB1C;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAAgC,MAAM,CAAC,MAAM,CAAC;IACvE,kBAAkB;IAElB;;;;OAIG;IACH,IAAI,CAAC,KAA0B;QAC7B,MAAM,OAAO,GAAG,MAAM,CAAC,WAAW,CAChC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC;aAChC,MAAM,CAAC,CAAC,KAAK,EAA6B,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC;aACpE,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,KAAK,CAAC,CAAC,CACvD,CAAC;QACF,OAAO,oBAAoB,CAAC,OAAO,CAAC;YAClC,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,SAAS,EAAE,OAAO,CAAC,cAAc,CAAC;YAClC,aAAa,EAAE,OAAO,CAAC,kBAAkB,CAAC;YAC1C,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,SAAS,EAAE,KAAK,CAAC,SAAS;SAC3B,CAAC,CAAC;IACL,CAAC;CACF,CAAC,CAAC;AACH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,MAAM,oBAAoB,GAAG,MAAM,CAAC,MAAM,CAAC;IACzC,OAAO,CACL,OACqD;QAErD,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC,CAC7B,CAAC;IAC1C,CAAC;CACF,CAAC,CAAC;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,4BAA4B,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC7F,OAAO,EACL,2BAA2B,EAC3B,yBAAyB,EACzB,uBAAuB,GACxB,MAAM,mBAAmB,CAAC;AAoF3B,OAAO,EACL,qBAAqB,GAGtB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,0BAA0B,EAAE,MAAM,2CAA2C,CAAC"}
@@ -0,0 +1,182 @@
1
+ import { type HandlerContext, type ServiceImpl, type Transport } from "@connectrpc/connect";
2
+ import { CommandService, QueryService, SubscriptionService, type SubscriptionUpdate } from "@spine-event-engine/proto/client";
3
+ import { AuthenticationService } from "@spine-event-engine/proto/auth";
4
+ import type { UnaryForwarder, UnaryGateway } from "../gateway/index.js";
5
+ import type { RequestCredential, TransportRequestContext } from "../index.js";
6
+ import type { BackendSubscriptionEnvelope, PublicSubscriptionWire, SubscriptionAbortSignal, SubscriptionCreator, SubscriptionUpdateSink, SubscriptionUpdateWire, SubscriptionGateway } from "../subscriptions/index.js";
7
+ /**
8
+ * Finite public-stream bounds. Defaults are 64 messages and 1,048,576 bytes;
9
+ * supplied bounds must be positive safe integers.
10
+ */
11
+ export interface SubscriptionRelayLimits {
12
+ /**
13
+ * Limits the number of queued updates.
14
+ */
15
+ readonly maxMessages?: number;
16
+ /**
17
+ * Limits the total queued update bytes.
18
+ */
19
+ readonly maxBytes?: number;
20
+ }
21
+ /**
22
+ * A bounded asynchronous FIFO relay between one private backend stream and one public Connect stream.
23
+ */
24
+ export declare class SubscriptionUpdateRelay implements AsyncIterable<SubscriptionUpdate> {
25
+ #private;
26
+ /**
27
+ * Creates a bounded FIFO relay.
28
+ * @param limits The optional message and byte bounds.
29
+ */
30
+ constructor(limits?: SubscriptionRelayLimits);
31
+ /**
32
+ * Copies and validates an update before FIFO admission. Count precedes bytes;
33
+ * either bound rejects with `ResourceExhausted`.
34
+ * @param update The update bytes to admit.
35
+ * @returns Completes after the update is admitted or rejected.
36
+ */
37
+ push(update: SubscriptionUpdateWire): Promise<void>;
38
+ /**
39
+ * Starts graceful FIFO drain; later cancellation or failure supersedes it and purges queued bytes.
40
+ */
41
+ close(): void;
42
+ /**
43
+ * Throws queued and future consumers, purging bytes.
44
+ * @param reason The terminal failure reason.
45
+ */
46
+ fail(reason: unknown): void;
47
+ /**
48
+ * Returns the public iterator; `return()` cancels it and purges queued bytes, while `throw()` fails it.
49
+ * @returns The single public update iterator.
50
+ */
51
+ [Symbol.asyncIterator](): AsyncIterator<SubscriptionUpdate>;
52
+ }
53
+ /**
54
+ * Native Connect adapter. Post/Read use their matching Command/Query descriptors;
55
+ * Subscribe/Activate/Cancel/Dispose use the shared Subscription descriptors.
56
+ * Every call receives only an admitted AbortSignal, never browser credentials or facts.
57
+ */
58
+ export declare class NativeSubscriptionCreator implements SubscriptionCreator, UnaryForwarder {
59
+ #private;
60
+ /**
61
+ * Creates a native adapter over one Connect transport.
62
+ * @param transport The native Connect transport.
63
+ */
64
+ constructor(transport: Transport);
65
+ /**
66
+ * Sends an admitted Post or Read envelope through its matching native descriptor.
67
+ * @param request The admitted unary request envelope.
68
+ * @returns The encoded native response.
69
+ */
70
+ forward(request: {
71
+ readonly service: string;
72
+ readonly method: string;
73
+ readonly value: Uint8Array;
74
+ readonly signal?: AbortSignal;
75
+ }): Promise<Uint8Array>;
76
+ /**
77
+ * Creates a native subscription with the supplied admitted cancellation signal.
78
+ * @param request The admitted canonical subscription definition.
79
+ * @param signal The admitted cancellation signal.
80
+ * @returns The private backend subscription envelope.
81
+ */
82
+ subscribe(request: PublicSubscriptionWire, signal: SubscriptionAbortSignal): Promise<BackendSubscriptionEnvelope>;
83
+ /**
84
+ * Streams native Activate updates through the supplied asynchronous public-update sink.
85
+ * @param request The private native subscription envelope and update sink.
86
+ * @param signal The admitted cancellation signal.
87
+ * @returns Completes after native activation ends.
88
+ */
89
+ activate(request: {
90
+ readonly wire: BackendSubscriptionEnvelope;
91
+ readonly updates: SubscriptionUpdateSink;
92
+ }, signal: SubscriptionAbortSignal): Promise<void>;
93
+ /**
94
+ * Cancels the native subscription represented by the canonical definition.
95
+ * @param request The canonical subscription definition.
96
+ * @param signal The admitted cancellation signal.
97
+ * @returns Completes after native cancellation ends.
98
+ */
99
+ cancel(request: {
100
+ readonly wire: PublicSubscriptionWire;
101
+ }, signal: SubscriptionAbortSignal): Promise<void>;
102
+ /**
103
+ * Performs mandatory native cancellation/disposal compensation for a private envelope.
104
+ * @param envelope The private backend subscription envelope.
105
+ * @param signal The admitted cancellation signal.
106
+ * @returns Completes after native disposal ends.
107
+ */
108
+ dispose(envelope: BackendSubscriptionEnvelope, signal: SubscriptionAbortSignal): Promise<void>;
109
+ }
110
+ /**
111
+ * Application-owned extractor of browser credentials and allowlisted request facts from Connect context.
112
+ */
113
+ export interface NativeGatewayRequestContext {
114
+ /**
115
+ * Reads credentials for the gateway only; they are never forwarded to native services.
116
+ * @param context The incoming Connect handler context.
117
+ * @returns The extracted request credential.
118
+ */
119
+ credential(context: HandlerContext): RequestCredential | undefined;
120
+ /**
121
+ * Reads the allowlisted authorization and diagnostic transport view for the gateway only.
122
+ * @param context The incoming Connect handler context.
123
+ * @returns The allowed transport facts.
124
+ */
125
+ transport(context: HandlerContext): TransportRequestContext;
126
+ }
127
+ /**
128
+ * B4 Connect services. Each handler delegates to the reviewed B2/B3 gateway boundary.
129
+ */
130
+ export interface NativeGatewayServices {
131
+ /**
132
+ * Connect AuthenticationService implementation for informational context resolution.
133
+ */
134
+ readonly authentication: ServiceImpl<typeof AuthenticationService>;
135
+ /**
136
+ * Connect CommandService implementation whose Post handler delegates to the B2 unary gateway.
137
+ */
138
+ readonly command: ServiceImpl<typeof CommandService>;
139
+ /**
140
+ * Connect QueryService implementation whose Read handler delegates to the B2 unary gateway.
141
+ */
142
+ readonly query: ServiceImpl<typeof QueryService>;
143
+ /**
144
+ * Connect SubscriptionService implementation whose handlers delegate to the B3 subscription gateway.
145
+ */
146
+ readonly subscription: ServiceImpl<typeof SubscriptionService>;
147
+ }
148
+ /**
149
+ * Named options for {@link createNativeGatewayServices}.
150
+ */
151
+ export interface NativeGatewayServicesOptions {
152
+ /**
153
+ * B2 Post/Read boundary.
154
+ */
155
+ readonly unary: UnaryGateway;
156
+ /**
157
+ * B3 Subscribe/Activate/Cancel boundary.
158
+ */
159
+ readonly subscriptions: SubscriptionGateway;
160
+ /**
161
+ * Application-owned context extractor.
162
+ */
163
+ readonly requests: NativeGatewayRequestContext;
164
+ /**
165
+ * Optional public relay bounds.
166
+ */
167
+ readonly relay?: SubscriptionRelayLimits;
168
+ }
169
+ /**
170
+ * Creates native handlers without exposing private envelopes.
171
+ *
172
+ * Unauthenticated requests map to `Unauthenticated`; forbidden or denied requests to
173
+ * `PermissionDenied`; request/capacity limits to `ResourceExhausted`; busy bindings to `Aborted`;
174
+ * and unknown operations to `Unimplemented`. Malformed, stale-context, backend-envelope, and other
175
+ * validation rejections map to `InvalidArgument`. Terminal context/iterator paths abort native
176
+ * work. Natural completion drains FIFO updates, whereas failure or iterator cancellation purges
177
+ * them.
178
+ * @param options The unary, subscription, context, and relay dependencies.
179
+ * @returns The native Connect service implementations.
180
+ */
181
+ export declare function createNativeGatewayServices(options: NativeGatewayServicesOptions): NativeGatewayServices;
182
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/native/index.ts"],"names":[],"mappings":"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"}