@shivaedev/identity 0.0.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +516 -1
  3. package/dist/identity.d.ts +36 -0
  4. package/dist/identity.d.ts.map +1 -0
  5. package/dist/identity.js +12 -0
  6. package/dist/identity.js.map +1 -0
  7. package/dist/middleware.d.ts +21 -0
  8. package/dist/middleware.d.ts.map +1 -0
  9. package/dist/middleware.js +20 -0
  10. package/dist/middleware.js.map +1 -0
  11. package/dist/permission.d.ts +11 -0
  12. package/dist/permission.d.ts.map +1 -0
  13. package/dist/permission.js +17 -0
  14. package/dist/permission.js.map +1 -0
  15. package/dist/server/adapters/betterAuthSessions.d.ts +14 -0
  16. package/dist/server/adapters/betterAuthSessions.d.ts.map +1 -0
  17. package/dist/server/adapters/betterAuthSessions.js +24 -0
  18. package/dist/server/adapters/betterAuthSessions.js.map +1 -0
  19. package/dist/server/better-auth/allowedAccounts.d.ts +10 -0
  20. package/dist/server/better-auth/allowedAccounts.d.ts.map +1 -0
  21. package/dist/server/better-auth/allowedAccounts.js +20 -0
  22. package/dist/server/better-auth/allowedAccounts.js.map +1 -0
  23. package/dist/server/better-auth/bearerSessions.d.ts +9 -0
  24. package/dist/server/better-auth/bearerSessions.d.ts.map +1 -0
  25. package/dist/server/better-auth/bearerSessions.js +38 -0
  26. package/dist/server/better-auth/bearerSessions.js.map +1 -0
  27. package/dist/server/better-auth/clientIp.d.ts +8 -0
  28. package/dist/server/better-auth/clientIp.d.ts.map +1 -0
  29. package/dist/server/better-auth/clientIp.js +28 -0
  30. package/dist/server/better-auth/clientIp.js.map +1 -0
  31. package/dist/server/better-auth/memoryRateLimit.d.ts +3 -0
  32. package/dist/server/better-auth/memoryRateLimit.d.ts.map +1 -0
  33. package/dist/server/better-auth/memoryRateLimit.js +46 -0
  34. package/dist/server/better-auth/memoryRateLimit.js.map +1 -0
  35. package/dist/server/better-auth/mount.d.ts +265 -0
  36. package/dist/server/better-auth/mount.d.ts.map +1 -0
  37. package/dist/server/better-auth/mount.js +111 -0
  38. package/dist/server/better-auth/mount.js.map +1 -0
  39. package/dist/server/better-auth/mountRoutes.d.ts +23 -0
  40. package/dist/server/better-auth/mountRoutes.d.ts.map +1 -0
  41. package/dist/server/better-auth/mountRoutes.js +51 -0
  42. package/dist/server/better-auth/mountRoutes.js.map +1 -0
  43. package/dist/server/better-auth/mountedSessions.d.ts +15 -0
  44. package/dist/server/better-auth/mountedSessions.d.ts.map +1 -0
  45. package/dist/server/better-auth/mountedSessions.js +12 -0
  46. package/dist/server/better-auth/mountedSessions.js.map +1 -0
  47. package/dist/server/better-auth/revokeUnadmitted.d.ts +10 -0
  48. package/dist/server/better-auth/revokeUnadmitted.d.ts.map +1 -0
  49. package/dist/server/better-auth/revokeUnadmitted.js +29 -0
  50. package/dist/server/better-auth/revokeUnadmitted.js.map +1 -0
  51. package/dist/server/better-auth/sessionPermissions.d.ts +3 -0
  52. package/dist/server/better-auth/sessionPermissions.d.ts.map +1 -0
  53. package/dist/server/better-auth/sessionPermissions.js +16 -0
  54. package/dist/server/better-auth/sessionPermissions.js.map +1 -0
  55. package/dist/server/better-auth/signInGate.d.ts +37 -0
  56. package/dist/server/better-auth/signInGate.d.ts.map +1 -0
  57. package/dist/server/better-auth/signInGate.js +38 -0
  58. package/dist/server/better-auth/signInGate.js.map +1 -0
  59. package/dist/server/better-auth/signInPolicy.d.ts +193 -0
  60. package/dist/server/better-auth/signInPolicy.d.ts.map +1 -0
  61. package/dist/server/better-auth/signInPolicy.js +61 -0
  62. package/dist/server/better-auth/signInPolicy.js.map +1 -0
  63. package/dist/server/better-auth/testDatabase.d.ts +19 -0
  64. package/dist/server/better-auth/testDatabase.d.ts.map +1 -0
  65. package/dist/server/better-auth/testDatabase.js +24 -0
  66. package/dist/server/better-auth/testDatabase.js.map +1 -0
  67. package/dist/server/better-auth/testing.d.ts +24 -0
  68. package/dist/server/better-auth/testing.d.ts.map +1 -0
  69. package/dist/server/better-auth/testing.js +21 -0
  70. package/dist/server/better-auth/testing.js.map +1 -0
  71. package/dist/server/better-auth/userProfiles.d.ts +14 -0
  72. package/dist/server/better-auth/userProfiles.d.ts.map +1 -0
  73. package/dist/server/better-auth/userProfiles.js +20 -0
  74. package/dist/server/better-auth/userProfiles.js.map +1 -0
  75. package/dist/server/commandChanges.d.ts +5 -0
  76. package/dist/server/commandChanges.d.ts.map +1 -0
  77. package/dist/server/commandChanges.js +44 -0
  78. package/dist/server/commandChanges.js.map +1 -0
  79. package/dist/server/local.d.ts +10 -0
  80. package/dist/server/local.d.ts.map +1 -0
  81. package/dist/server/local.js +93 -0
  82. package/dist/server/local.js.map +1 -0
  83. package/dist/server/origin.d.ts +15 -0
  84. package/dist/server/origin.d.ts.map +1 -0
  85. package/dist/server/origin.js +16 -0
  86. package/dist/server/origin.js.map +1 -0
  87. package/dist/server/permissions.d.ts +9 -0
  88. package/dist/server/permissions.d.ts.map +1 -0
  89. package/dist/server/permissions.js +31 -0
  90. package/dist/server/permissions.js.map +1 -0
  91. package/dist/server/proxyRanges.d.ts +4 -0
  92. package/dist/server/proxyRanges.d.ts.map +1 -0
  93. package/dist/server/proxyRanges.js +62 -0
  94. package/dist/server/proxyRanges.js.map +1 -0
  95. package/dist/server/resolveRole.d.ts +11 -0
  96. package/dist/server/resolveRole.d.ts.map +1 -0
  97. package/dist/server/resolveRole.js +6 -0
  98. package/dist/server/resolveRole.js.map +1 -0
  99. package/dist/server/revalidateStream.d.ts +6 -0
  100. package/dist/server/revalidateStream.d.ts.map +1 -0
  101. package/dist/server/revalidateStream.js +19 -0
  102. package/dist/server/revalidateStream.js.map +1 -0
  103. package/dist/server/session.d.ts +39 -0
  104. package/dist/server/session.d.ts.map +1 -0
  105. package/dist/server/session.js +73 -0
  106. package/dist/server/session.js.map +1 -0
  107. package/dist/server/sessionKeys.d.ts +10 -0
  108. package/dist/server/sessionKeys.d.ts.map +1 -0
  109. package/dist/server/sessionKeys.js +22 -0
  110. package/dist/server/sessionKeys.js.map +1 -0
  111. package/dist/server/sessionProfile.d.ts +3 -0
  112. package/dist/server/sessionProfile.d.ts.map +1 -0
  113. package/dist/server/sessionProfile.js +4 -0
  114. package/dist/server/sessionProfile.js.map +1 -0
  115. package/dist/server/tracing.d.ts +9 -0
  116. package/dist/server/tracing.d.ts.map +1 -0
  117. package/dist/server/tracing.js +51 -0
  118. package/dist/server/tracing.js.map +1 -0
  119. package/dist/server/transportHeaders.d.ts +4 -0
  120. package/dist/server/transportHeaders.d.ts.map +1 -0
  121. package/dist/server/transportHeaders.js +6 -0
  122. package/dist/server/transportHeaders.js.map +1 -0
  123. package/dist/server/trustedProxy.d.ts +7 -0
  124. package/dist/server/trustedProxy.d.ts.map +1 -0
  125. package/dist/server/trustedProxy.js +19 -0
  126. package/dist/server/trustedProxy.js.map +1 -0
  127. package/dist/server/trustedProxyRanges.d.ts +2 -0
  128. package/dist/server/trustedProxyRanges.d.ts.map +1 -0
  129. package/dist/server/trustedProxyRanges.js +5 -0
  130. package/dist/server/trustedProxyRanges.js.map +1 -0
  131. package/package.json +86 -4
  132. package/src/identity.ts +26 -0
  133. package/src/middleware.ts +38 -0
  134. package/src/permission.ts +24 -0
  135. package/src/server/adapters/betterAuthSessions.ts +44 -0
  136. package/src/server/better-auth/allowedAccounts.ts +29 -0
  137. package/src/server/better-auth/bearerSessions.ts +50 -0
  138. package/src/server/better-auth/clientIp.ts +34 -0
  139. package/src/server/better-auth/memoryRateLimit.ts +56 -0
  140. package/src/server/better-auth/mount.ts +146 -0
  141. package/src/server/better-auth/mountRoutes.ts +73 -0
  142. package/src/server/better-auth/mountedSessions.ts +21 -0
  143. package/src/server/better-auth/revokeUnadmitted.ts +41 -0
  144. package/src/server/better-auth/sessionPermissions.ts +18 -0
  145. package/src/server/better-auth/signInGate.ts +77 -0
  146. package/src/server/better-auth/signInPolicy.ts +72 -0
  147. package/src/server/better-auth/testDatabase.ts +27 -0
  148. package/src/server/better-auth/testing.ts +35 -0
  149. package/src/server/better-auth/userProfiles.ts +37 -0
  150. package/src/server/commandChanges.ts +52 -0
  151. package/src/server/local.ts +100 -0
  152. package/src/server/origin.ts +26 -0
  153. package/src/server/permissions.ts +51 -0
  154. package/src/server/proxyRanges.ts +61 -0
  155. package/src/server/resolveRole.ts +7 -0
  156. package/src/server/revalidateStream.ts +25 -0
  157. package/src/server/session.ts +148 -0
  158. package/src/server/sessionKeys.ts +25 -0
  159. package/src/server/sessionProfile.ts +5 -0
  160. package/src/server/tracing.ts +68 -0
  161. package/src/server/transportHeaders.ts +8 -0
  162. package/src/server/trustedProxy.ts +22 -0
  163. package/src/server/trustedProxyRanges.ts +5 -0
@@ -0,0 +1,93 @@
1
+ import { Effect, Option } from "effect";
2
+ import { HttpServerRequest, HttpServerResponse, HttpTraceContext } from "effect/http";
3
+ import { RpcSerialization } from "effect/rpc";
4
+ import { proxyAddresses, proxyMatches } from "./trustedProxy.js";
5
+ import { trustedProxyRanges as normalizedRanges } from "./trustedProxyRanges.js";
6
+ function loopbackAddress(address) {
7
+ const unmapped = unmapAddress(address);
8
+ return unmapped === "::1" || (/^127(?:\.\d{1,3}){3}$/u.test(unmapped) && unmapped.split(".").every((part) => Number(part) <= 255));
9
+ }
10
+ function unmapAddress(address) {
11
+ return address.replace(/^::ffff:/iu, "");
12
+ }
13
+ function loopbackHost(host) {
14
+ if (host === undefined) {
15
+ return false;
16
+ }
17
+ const authority = /^(?<hostname>\[[^\]]+\]|[^:]+)(?::(?<port>\d{1,5}))?$/u.exec(host)?.groups;
18
+ if (authority === undefined || (authority.port !== undefined && Number(authority.port) > 65_535)) {
19
+ return false;
20
+ }
21
+ const hostname = authority.hostname?.toLowerCase();
22
+ return hostname !== undefined && (hostname === "localhost" || hostname === "[::1]" || loopbackAddress(hostname));
23
+ }
24
+ export function sameOrigin(request) {
25
+ const origin = request.headers.origin;
26
+ if (origin === undefined) {
27
+ return true;
28
+ }
29
+ try {
30
+ const url = new URL(origin);
31
+ return url.protocol === "http:" && url.origin === origin && url.host === request.headers.host;
32
+ }
33
+ catch {
34
+ return false;
35
+ }
36
+ }
37
+ export function loopbackOnly(handler) {
38
+ return (request) => loopbackHost(request.headers.host) && Option.match(request.remoteAddress, { onNone: () => true, onSome: loopbackAddress })
39
+ ? handler(request)
40
+ : Effect.succeed(HttpServerResponse.text("Only loopback hosts are served", { status: 403 }));
41
+ }
42
+ export function trustedProxyPeer(trustedProxy) {
43
+ const addresses = trustedProxy === undefined ? undefined : proxyAddresses(trustedProxy);
44
+ return (address) => addresses !== undefined && proxyMatches(addresses, address);
45
+ }
46
+ export function trustedProxyRanges(trustedProxy) {
47
+ return normalizedRanges(trustedProxy);
48
+ }
49
+ function proxyOrigin(request, isTrustedProxy, native) {
50
+ if (!Option.exists(request.remoteAddress, isTrustedProxy)) {
51
+ return false;
52
+ }
53
+ const host = request.headers["x-forwarded-host"];
54
+ const protocol = request.headers["x-forwarded-proto"];
55
+ if (host === undefined || !/^(?:\[[\da-f:]+\]|[\da-z.-]+)(?::\d{1,5})?$/iu.test(host) || (protocol !== "http" && protocol !== "https")) {
56
+ return false;
57
+ }
58
+ try {
59
+ const url = new URL(`${protocol}://${host}`);
60
+ return native || request.headers.origin === undefined || request.headers.origin === url.origin;
61
+ }
62
+ catch {
63
+ return false;
64
+ }
65
+ }
66
+ export function localTransport(trustedProxy, nativeOrigins = []) {
67
+ const isTrustedProxy = trustedProxyPeer(trustedProxy);
68
+ return (request) => {
69
+ const native = nativeOrigins.includes(request.headers.origin ?? "");
70
+ const local = loopbackHost(request.headers.host) && Option.exists(request.remoteAddress, loopbackAddress);
71
+ return (local && (native || sameOrigin(request))) || proxyOrigin(request, isTrustedProxy, native);
72
+ };
73
+ }
74
+ export function localRpcGuard(effect, trustedProxy, nativeOrigins = []) {
75
+ const allowed = localTransport(trustedProxy, nativeOrigins);
76
+ return Effect.gen(function* () {
77
+ const request = yield* HttpServerRequest.HttpServerRequest;
78
+ const serialization = yield* RpcSerialization.RpcSerialization;
79
+ const contentType = request.headers["content-type"]?.split(";")[0]?.trim().toLowerCase();
80
+ return allowed(request) && contentType === serialization.contentType
81
+ ? yield* continueHttpTrace(effect, request)
82
+ : HttpServerResponse.text("Local same-origin requests only", { status: 403 });
83
+ });
84
+ }
85
+ const continueHttpTrace = Effect.fnUntraced(function* (effect, request) {
86
+ const incoming = HttpTraceContext.w3c(request.headers);
87
+ if (Option.isNone(incoming)) {
88
+ return yield* effect;
89
+ }
90
+ const parent = Option.getOrElse(yield* Effect.option(Effect.currentParentSpan), () => incoming.value);
91
+ return yield* Effect.withParentSpan(effect, parent);
92
+ });
93
+ //# sourceMappingURL=local.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local.js","sourceRoot":"","sources":["../../src/server/local.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import { Option } from "effect";
2
+ import { Headers } from "effect/http";
3
+ export interface OriginRequest {
4
+ readonly headers: Headers.Headers;
5
+ readonly origin: Option.Option<string>;
6
+ readonly rpc: string;
7
+ }
8
+ export type OriginPolicy = (request: OriginRequest) => boolean;
9
+ export interface TrustedOriginsOptions {
10
+ readonly allow: readonly string[];
11
+ readonly missing: "allow" | "reject";
12
+ }
13
+ export declare function trustedOrigins(options: TrustedOriginsOptions): OriginPolicy;
14
+ export declare function originRequest(headers: Headers.Headers, rpc: string): OriginRequest;
15
+ //# sourceMappingURL=origin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"origin.d.ts","sourceRoot":"","sources":["../../src/server/origin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtC,MAAM,WAAW,aAAa;IAC7B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACvC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACrB;AACD,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,EAAE,aAAa,KAAK,OAAO,CAAC;AAC/D,MAAM,WAAW,qBAAqB;IACrC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,QAAQ,CAAC;CACrC;AACD,wBAAgB,cAAc,CAAC,OAAO,EAAE,qBAAqB,GAAG,YAAY,CAM3E;AACD,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,aAAa,CAMlF"}
@@ -0,0 +1,16 @@
1
+ import { Option } from "effect";
2
+ import { Headers } from "effect/http";
3
+ export function trustedOrigins(options) {
4
+ return ({ origin }) => Option.match(origin, {
5
+ onNone: () => options.missing === "allow",
6
+ onSome: (value) => options.allow.includes(value),
7
+ });
8
+ }
9
+ export function originRequest(headers, rpc) {
10
+ return {
11
+ headers,
12
+ origin: Headers.get(headers, "origin"),
13
+ rpc,
14
+ };
15
+ }
16
+ //# sourceMappingURL=origin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"origin.js","sourceRoot":"","sources":["../../src/server/origin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAWtC,MAAM,UAAU,cAAc,CAAC,OAA8B;IAC5D,OAAO,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CACrB,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE;QACpB,MAAM,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,KAAK,OAAO;QACzC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC;KAChD,CAAC,CAAC;AACL,CAAC;AACD,MAAM,UAAU,aAAa,CAAC,OAAwB,EAAE,GAAW;IAClE,OAAO;QACN,OAAO;QACP,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC;QACtC,GAAG;KACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { Effect, Layer } from "effect";
2
+ import { type HttpServerRequest, HttpServerResponse } from "effect/http";
3
+ import type { Permission } from "@shivaedev/access/permission.ts";
4
+ import { Identity, type SessionUser } from "#identity.ts";
5
+ import { type permissionMiddleware } from "#permission.ts";
6
+ import { type SessionPolicy, type UserSessionShape } from "./session.ts";
7
+ export declare function permissionLayer<TMiddleware, TSession extends UserSessionShape>(middleware: ReturnType<ReturnType<typeof permissionMiddleware<TMiddleware>>>, policy: SessionPolicy<TSession>): Layer.Layer<TMiddleware, never, never>;
8
+ export declare function permissionRoute<TSession extends UserSessionShape>(policy: SessionPolicy<TSession>, permission: Permission): <E, R>(handler: (request: HttpServerRequest.HttpServerRequest) => Effect.Effect<HttpServerResponse.HttpServerResponse, E, R>) => (request: HttpServerRequest.HttpServerRequest) => Effect.Effect<HttpServerResponse.HttpServerResponse, E, Exclude<R, Identity | SessionUser>>;
9
+ //# sourceMappingURL=permissions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../src/server/permissions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAU,MAAM,QAAQ,CAAC;AAC/C,OAAO,EAAE,KAAK,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEzE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAElE,OAAO,EAAE,QAAQ,EAAE,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAiB,KAAK,oBAAoB,EAAqB,MAAM,gBAAgB,CAAC;AAG7F,OAAO,EAAkB,KAAK,aAAa,EAAE,KAAK,gBAAgB,EAAmB,MAAM,cAAc,CAAC;AAE1G,wBAAgB,eAAe,CAAC,WAAW,EAAE,QAAQ,SAAS,gBAAgB,EAC7E,UAAU,EAAE,UAAU,CAAC,UAAU,CAAC,OAAO,oBAAoB,CAAC,WAAW,CAAC,CAAC,CAAC,EAC5E,MAAM,EAAE,aAAa,CAAC,QAAQ,CAAC,0CAmB/B;AAQD,wBAAgB,eAAe,CAAC,QAAQ,SAAS,gBAAgB,EAAE,MAAM,EAAE,aAAa,CAAC,QAAQ,CAAC,EAAE,UAAU,EAAE,UAAU,IACjH,CAAC,EAAE,CAAC,WAAW,CAAC,OAAO,EAAE,iBAAiB,CAAC,iBAAiB,KAAK,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,kBAAkB,EAAE,CAAC,EAAE,CAAC,CAAC,eACxH,iBAAiB,CAAC,iBAAiB,KAAG,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,kBAAkB,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,QAAQ,GAAG,WAAW,CAAC,CAAC,CAQ5I"}
@@ -0,0 +1,31 @@
1
+ import { Effect, Layer, Option } from "effect";
2
+ import { HttpServerResponse } from "effect/http";
3
+ import { Forbidden } from "@shivaedev/errors/taxonomy.ts";
4
+ import { Identity } from "#identity.ts";
5
+ import { hasPermission, requirePermission } from "#permission.ts";
6
+ import { sessionCommandChanges } from "#server/commandChanges.ts";
7
+ import { revalidateStream } from "./revalidateStream.js";
8
+ import { resolveSession, withSessionUser } from "./session.js";
9
+ export function permissionLayer(middleware, policy) {
10
+ const permission = middleware.permission;
11
+ const guard = (effect, { headers, rpc, payload }) => {
12
+ const lookup = Effect.tap(resolveSession(policy, headers, rpc._tag), (session) => Option.isSome(session) && !hasPermission(session.value.user, permission)
13
+ ? Effect.fail(new Forbidden({ message: `Permission required: ${permission.name} (${permission.strength})` }))
14
+ : Effect.void);
15
+ return sessionCommandChanges(effect, rpc, payload).pipe((invocation) => Effect.flatMap(Identity, ({ id }) => invocation.pipe(revalidateStream(policy, rpc, id, lookup))), (invocation) => Effect.andThen(requirePermission(permission), invocation), withSessionUser(policy, headers, rpc._tag));
16
+ };
17
+ return Layer.succeed(middleware, guard);
18
+ }
19
+ function rejection(error) {
20
+ return HttpServerResponse.empty({
21
+ headers: { "cache-control": "private, no-store" },
22
+ status: { AuthUnavailable: 503, Forbidden: 403, Unauthorized: 401 }[error._tag],
23
+ });
24
+ }
25
+ export function permissionRoute(policy, permission) {
26
+ return (handler) => (request) => Effect.andThen(requirePermission(permission), Effect.context()).pipe(withSessionUser(policy, request.headers, request.url), Effect.matchEffect({
27
+ onFailure: (error) => Effect.succeed(rejection(error)),
28
+ onSuccess: (context) => Effect.provideContext(handler(request), context),
29
+ }));
30
+ }
31
+ //# sourceMappingURL=permissions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permissions.js","sourceRoot":"","sources":["../../src/server/permissions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { BlockList } from "node:net";
2
+ export declare function addProxyAddress(addresses: BlockList, entry: string): boolean;
3
+ export declare function proxyRanges(value: string): string[] | undefined;
4
+ //# sourceMappingURL=proxyRanges.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proxyRanges.d.ts","sourceRoot":"","sources":["../../src/server/proxyRanges.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAQ,MAAM,UAAU,CAAC;AAE3C,wBAAgB,eAAe,CAAC,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAkB5E;AA8BD,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAU/D"}
@@ -0,0 +1,62 @@
1
+ import { BlockList, isIP } from "node:net";
2
+ export function addProxyAddress(addresses, entry) {
3
+ const parts = entry.trim().split("/");
4
+ const address = parts[0] ?? "";
5
+ const family = isIP(address);
6
+ if (family === 0 || address.includes("%") || parts.length > 2) {
7
+ return false;
8
+ }
9
+ const type = family === 4 ? "ipv4" : "ipv6";
10
+ const prefix = parts[1];
11
+ if (prefix === undefined) {
12
+ addresses.addAddress(address, type);
13
+ }
14
+ else {
15
+ if (!/^\d+$/u.test(prefix) || Number(prefix) > (family === 4 ? 32 : 128)) {
16
+ return false;
17
+ }
18
+ addresses.addSubnet(address, Number(prefix), type);
19
+ }
20
+ return true;
21
+ }
22
+ function mappedIpv4(address) {
23
+ const groups = /^\[::ffff:(?<high>[\da-f]+):(?<low>[\da-f]+)\]$/u.exec(new URL(`http://[${address}]`).hostname)?.groups;
24
+ if (groups?.high === undefined || groups.low === undefined) {
25
+ return undefined;
26
+ }
27
+ const high = Number.parseInt(groups.high, 16);
28
+ const low = Number.parseInt(groups.low, 16);
29
+ return [high >>> 8, high & 255, low >>> 8, low & 255].join(".");
30
+ }
31
+ function normalizedProxyRange(entry) {
32
+ const range = new BlockList();
33
+ if (!addProxyAddress(range, entry)) {
34
+ return undefined;
35
+ }
36
+ const [address = "", prefix] = entry.split("/");
37
+ if (isIP(address) !== 6) {
38
+ return [entry];
39
+ }
40
+ const ipv4 = mappedIpv4(address);
41
+ const bits = prefix === undefined ? 128 : Number(prefix);
42
+ if (ipv4 !== undefined) {
43
+ if (bits >= 96) {
44
+ return [prefix === undefined ? ipv4 : `${ipv4}/${bits - 96}`];
45
+ }
46
+ const network = bits <= 80 ? "::" : `::${((0xff_ff << (96 - bits)) & 0xff_ff).toString(16)}:0:0`;
47
+ return [`${network}/${bits}`, "0.0.0.0/0"];
48
+ }
49
+ return bits < 96 && range.check("::ffff:0:0", "ipv6") ? [entry, "0.0.0.0/0"] : [entry];
50
+ }
51
+ export function proxyRanges(value) {
52
+ const ranges = [];
53
+ for (const entry of value.split(",")) {
54
+ const normalized = normalizedProxyRange(entry.trim());
55
+ if (normalized === undefined) {
56
+ return undefined;
57
+ }
58
+ ranges.push(...normalized);
59
+ }
60
+ return ranges;
61
+ }
62
+ //# sourceMappingURL=proxyRanges.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proxyRanges.js","sourceRoot":"","sources":["../../src/server/proxyRanges.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAE3C,MAAM,UAAU,eAAe,CAAC,SAAoB,EAAE,KAAa;IAClE,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACtC,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC/B,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;IAC7B,IAAI,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/D,OAAO,KAAK,CAAC;IACd,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;IAC5C,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IACxB,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QAC1B,SAAS,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACrC,CAAC;SAAM,CAAC;QACP,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1E,OAAO,KAAK,CAAC;QACd,CAAC;QACD,SAAS,CAAC,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC;IACpD,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC;AACD,SAAS,UAAU,CAAC,OAAe;IAClC,MAAM,MAAM,GAAG,kDAAkD,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,WAAW,OAAO,GAAG,CAAC,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IACxH,IAAI,MAAM,EAAE,IAAI,KAAK,SAAS,IAAI,MAAM,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;QAC5D,OAAO,SAAS,CAAC;IAClB,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAC9C,MAAM,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAC5C,OAAO,CAAC,IAAI,KAAK,CAAC,EAAE,IAAI,GAAG,GAAG,EAAE,GAAG,KAAK,CAAC,EAAE,GAAG,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACjE,CAAC;AACD,SAAS,oBAAoB,CAAC,KAAa;IAC1C,MAAM,KAAK,GAAG,IAAI,SAAS,EAAE,CAAC;IAC9B,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC;QACpC,OAAO,SAAS,CAAC;IAClB,CAAC;IACD,MAAM,CAAC,OAAO,GAAG,EAAE,EAAE,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAChD,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,CAAC,KAAK,CAAC,CAAC;IAChB,CAAC;IACD,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;IACjC,MAAM,IAAI,GAAG,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACzD,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACxB,IAAI,IAAI,IAAI,EAAE,EAAE,CAAC;YAChB,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,IAAI,GAAG,EAAE,EAAE,CAAC,CAAC;QAC/D,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,MAAM,CAAC;QACjG,OAAO,CAAC,GAAG,OAAO,IAAI,IAAI,EAAE,EAAE,WAAW,CAAC,CAAC;IAC5C,CAAC;IACD,OAAO,IAAI,GAAG,EAAE,IAAI,KAAK,CAAC,KAAK,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;AACxF,CAAC;AACD,MAAM,UAAU,WAAW,CAAC,KAAa;IACxC,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACtC,MAAM,UAAU,GAAG,oBAAoB,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QACtD,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC9B,OAAO,SAAS,CAAC;QAClB,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,CAAC;IAC5B,CAAC;IACD,OAAO,MAAM,CAAC;AACf,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { Effect } from "effect";
2
+ import type { RoleSet } from "@shivaedev/access/roleSet.ts";
3
+ import { AuthUnavailable } from "@shivaedev/errors/taxonomy.ts";
4
+ export declare function resolveRole(roles: RoleSet, stored: unknown): Effect.Effect<{
5
+ permissions: {
6
+ name: string;
7
+ strength: "any" | "own";
8
+ }[];
9
+ role: string;
10
+ }, AuthUnavailable, never>;
11
+ //# sourceMappingURL=resolveRole.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveRole.d.ts","sourceRoot":"","sources":["../../src/server/resolveRole.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAEhE,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO;;;;;;2BAE1D"}
@@ -0,0 +1,6 @@
1
+ import { Effect } from "effect";
2
+ import { AuthUnavailable } from "@shivaedev/errors/taxonomy.ts";
3
+ export function resolveRole(roles, stored) {
4
+ return roles.resolve(stored).pipe(Effect.mapError(() => new AuthUnavailable({ message: "Stored user role is not declared by the application" })));
5
+ }
6
+ //# sourceMappingURL=resolveRole.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveRole.js","sourceRoot":"","sources":["../../src/server/resolveRole.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAEhE,MAAM,UAAU,WAAW,CAAC,KAAc,EAAE,MAAe;IAC1D,OAAO,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,eAAe,CAAC,EAAE,OAAO,EAAE,qDAAqD,EAAE,CAAC,CAAC,CAAC,CAAC;AACnJ,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { Effect, Option } from "effect";
2
+ import { type Rpc } from "effect/rpc";
3
+ import { type AuthUnavailable, type Forbidden, Unauthorized } from "@shivaedev/errors/taxonomy.ts";
4
+ import type { SessionPolicy, SessionShape } from "./session.ts";
5
+ export declare function revalidateStream<TSession extends SessionShape>(policy: SessionPolicy<TSession>, rpc: Rpc.AnyWithProps, id: string, lookup: Effect.Effect<Option.Option<TSession>, AuthUnavailable | Forbidden>): <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E | Forbidden | Unauthorized, R>;
6
+ //# sourceMappingURL=revalidateStream.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"revalidateStream.d.ts","sourceRoot":"","sources":["../../src/server/revalidateStream.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,EAAE,KAAK,GAAG,EAAa,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,SAAS,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AACnG,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEhE,wBAAgB,gBAAgB,CAAC,QAAQ,SAAS,YAAY,EAC7D,MAAM,EAAE,aAAa,CAAC,QAAQ,CAAC,EAC/B,GAAG,EAAE,GAAG,CAAC,YAAY,EACrB,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,eAAe,GAAG,SAAS,CAAC,IAEnE,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,uDAa/C"}
@@ -0,0 +1,19 @@
1
+ import { Effect, Option } from "effect";
2
+ import { RpcSchema } from "effect/rpc";
3
+ import { Unauthorized } from "@shivaedev/errors/taxonomy.ts";
4
+ export function revalidateStream(policy, rpc, id, lookup) {
5
+ return (effect) => {
6
+ if (!RpcSchema.isStreamSchema(rpc.successSchema)) {
7
+ return effect;
8
+ }
9
+ const check = Effect.gen(function* () {
10
+ yield* Effect.sleep(policy.streamRevalidationInterval ?? "30 seconds");
11
+ const session = yield* lookup.pipe(Effect.catchTag("AuthUnavailable", () => Effect.succeed(undefined)));
12
+ if (session !== undefined && (Option.isNone(session) || session.value.user.id !== id)) {
13
+ return yield* new Unauthorized({ message: "Authentication required" });
14
+ }
15
+ });
16
+ return Effect.raceFirst(effect, Effect.forever(check));
17
+ };
18
+ }
19
+ //# sourceMappingURL=revalidateStream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"revalidateStream.js","sourceRoot":"","sources":["../../src/server/revalidateStream.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,EAAY,SAAS,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAwC,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAGnG,MAAM,UAAU,gBAAgB,CAC/B,MAA+B,EAC/B,GAAqB,EACrB,EAAU,EACV,MAA2E;IAE3E,OAAO,CAAU,MAA8B,EAAE,EAAE;QAClD,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC;YAClD,OAAO,MAAM,CAAC;QACf,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YACjC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,0BAA0B,IAAI,YAAY,CAAC,CAAC;YACvE,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;YACxG,IAAI,OAAO,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;gBACvF,OAAO,KAAK,CAAC,CAAC,IAAI,YAAY,CAAC,EAAE,OAAO,EAAE,yBAAyB,EAAE,CAAC,CAAC;YACxE,CAAC;QACF,CAAC,CAAC,CAAC;QACH,OAAO,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;IACxD,CAAC,CAAC;AACH,CAAC"}
@@ -0,0 +1,39 @@
1
+ import { Duration, Effect, Layer, Option } from "effect";
2
+ import type { Headers } from "effect/http";
3
+ import type { Permission } from "@shivaedev/access/permission.ts";
4
+ import type { RoleSet } from "@shivaedev/access/roleSet.ts";
5
+ import { type AuthUnavailable, Forbidden, Unauthorized } from "@shivaedev/errors/taxonomy.ts";
6
+ import { Identity, SessionUser, type SessionUserValue, type SessionUserWithProviderAccountsValue } from "#identity.ts";
7
+ import { Authenticated, AuthenticatedUser, AuthenticatedUserWithProviderAccounts, MaybeAuthenticated } from "#middleware.ts";
8
+ import { type OriginPolicy } from "./origin.ts";
9
+ export interface SessionShape {
10
+ readonly user: {
11
+ readonly id: string;
12
+ };
13
+ }
14
+ export interface SessionProvider<TSession extends SessionShape> {
15
+ readonly get: (headers: Headers.Headers) => Effect.Effect<Option.Option<TSession>, AuthUnavailable>;
16
+ }
17
+ export interface SessionPolicy<TSession extends SessionShape> {
18
+ readonly origin: OriginPolicy;
19
+ readonly provider: SessionProvider<TSession>;
20
+ readonly roles?: RoleSet;
21
+ readonly streamRevalidationInterval?: Duration.Input | undefined;
22
+ }
23
+ export declare const resolveSession: <TSession extends SessionShape>(policy: SessionPolicy<TSession>, headers: Headers.Headers, rpc: string) => Effect.Effect<Option.Option<TSession & {
24
+ readonly user: {
25
+ readonly permissions?: readonly Permission[];
26
+ };
27
+ }>, AuthUnavailable | Forbidden>;
28
+ export declare function authenticatedLayer<TSession extends SessionShape>(policy: SessionPolicy<TSession>): Layer.Layer<Authenticated>;
29
+ export declare function maybeAuthenticatedLayer<TSession extends SessionShape>(policy: SessionPolicy<TSession>): Layer.Layer<MaybeAuthenticated>;
30
+ export interface UserSessionShape extends SessionShape {
31
+ readonly user: SessionUserValue;
32
+ }
33
+ export declare function withSessionUser<TSession extends UserSessionShape>(policy: SessionPolicy<TSession>, headers: Headers.Headers, operation: string): <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E | AuthUnavailable | Forbidden | Unauthorized, Exclude<Exclude<R, Identity>, SessionUser>>;
34
+ export declare function authenticatedUserLayer<TSession extends UserSessionShape>(policy: SessionPolicy<TSession>): Layer.Layer<AuthenticatedUser>;
35
+ export interface ProviderAccountsSessionShape extends UserSessionShape {
36
+ readonly user: SessionUserWithProviderAccountsValue;
37
+ }
38
+ export declare function authenticatedUserWithProviderAccountsLayer<TSession extends ProviderAccountsSessionShape>(policy: SessionPolicy<TSession>): Layer.Layer<AuthenticatedUserWithProviderAccounts>;
39
+ //# sourceMappingURL=session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/server/session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,73 @@
1
+ import { Duration, Effect, Exit, Layer, Option } from "effect";
2
+ import { Forbidden, Unauthorized } from "@shivaedev/errors/taxonomy.ts";
3
+ import { Identity, OptionalIdentity, SessionUser, SessionUserWithProviderAccounts, } from "#identity.ts";
4
+ import { Authenticated, AuthenticatedUser, AuthenticatedUserWithProviderAccounts, MaybeAuthenticated } from "#middleware.ts";
5
+ import { sessionCommandChanges } from "#server/commandChanges.ts";
6
+ import { originRequest } from "./origin.js";
7
+ import { resolveRole } from "./resolveRole.js";
8
+ import { revalidateStream } from "./revalidateStream.js";
9
+ import { sessionProfile } from "./sessionProfile.js";
10
+ import { transportHeaders } from "./transportHeaders.js";
11
+ export const resolveSession = Effect.fn("PlatformRpc.resolveSession")(function* (policy, headers, rpc) {
12
+ const transport = yield* transportHeaders(headers);
13
+ if (!policy.origin(originRequest(transport, rpc))) {
14
+ return yield* new Forbidden({ message: "Origin not allowed" });
15
+ }
16
+ const session = yield* policy.provider.get(transport);
17
+ if (Option.isNone(session) || policy.roles === undefined) {
18
+ return session;
19
+ }
20
+ const access = yield* resolveRole(policy.roles, Reflect.get(session.value.user, "role"));
21
+ return Option.some({ ...session.value, user: { ...session.value.user, ...access } });
22
+ });
23
+ function identified(id) {
24
+ return Effect.andThen(Effect.annotateCurrentSpan("user.id", id), Effect.succeed(id));
25
+ }
26
+ export function authenticatedLayer(policy) {
27
+ return Layer.succeed(Authenticated, (effect, { headers, rpc, payload }) => Effect.gen(function* () {
28
+ const session = yield* resolveSession(policy, headers, rpc._tag);
29
+ if (Option.isNone(session)) {
30
+ return yield* new Unauthorized({ message: "Authentication required" });
31
+ }
32
+ const id = yield* identified(session.value.user.id);
33
+ return yield* sessionCommandChanges(effect, rpc, payload).pipe(revalidateStream(policy, rpc, id, resolveSession(policy, headers, rpc._tag)), Effect.provideService(Identity, { id }), Effect.annotateLogs({ userId: id }));
34
+ }));
35
+ }
36
+ export function maybeAuthenticatedLayer(policy) {
37
+ return Layer.succeed(MaybeAuthenticated, (effect, { headers, rpc }) => Effect.gen(function* () {
38
+ const session = yield* resolveSession(policy, headers, rpc._tag);
39
+ if (Option.isNone(session)) {
40
+ return yield* Effect.provideService(effect, OptionalIdentity, Option.none());
41
+ }
42
+ const id = yield* identified(session.value.user.id);
43
+ return yield* effect.pipe(revalidateStream(policy, rpc, id, resolveSession(policy, headers, rpc._tag)), Effect.provideService(OptionalIdentity, Option.some({ id })), Effect.annotateLogs({ userId: id }));
44
+ }));
45
+ }
46
+ export function withSessionUser(policy, headers, operation) {
47
+ return (effect) => Effect.gen(function* () {
48
+ const session = yield* resolveSession(policy, headers, operation);
49
+ if (Option.isNone(session)) {
50
+ return yield* new Unauthorized({ message: "Authentication required" });
51
+ }
52
+ const user = sessionProfile(session.value.user);
53
+ const id = yield* identified(session.value.user.id);
54
+ return yield* effect.pipe(Effect.provideService(Identity, { id }), Effect.provideService(SessionUser, user), Effect.annotateLogs({ userId: id }));
55
+ });
56
+ }
57
+ export function authenticatedUserLayer(policy) {
58
+ return Layer.succeed(AuthenticatedUser, (effect, { headers, rpc, payload }) => sessionCommandChanges(effect, rpc, payload).pipe((invocation) => Effect.flatMap(Identity, ({ id }) => invocation.pipe(revalidateStream(policy, rpc, id, resolveSession(policy, headers, rpc._tag)))), withSessionUser(policy, headers, rpc._tag)));
59
+ }
60
+ export function authenticatedUserWithProviderAccountsLayer(policy) {
61
+ return Layer.succeed(AuthenticatedUserWithProviderAccounts, (effect, { headers, rpc, payload }) => Effect.gen(function* () {
62
+ const session = yield* resolveSession(policy, headers, rpc._tag);
63
+ if (Option.isNone(session)) {
64
+ return yield* new Unauthorized({ message: "Authentication required" });
65
+ }
66
+ const { id, providerAccounts } = session.value.user;
67
+ const accounts = yield* Effect.cachedWithTTL(Effect.map(providerAccounts, (values) => values.map(({ accountId, providerId }) => ({ accountId, providerId }))), (exit) => (Exit.isSuccess(exit) ? Duration.infinity : Duration.zero));
68
+ const user = sessionProfile(session.value.user);
69
+ yield* identified(id);
70
+ return yield* sessionCommandChanges(effect, rpc, payload).pipe(revalidateStream(policy, rpc, id, resolveSession(policy, headers, rpc._tag)), Effect.provideService(Identity, { id }), Effect.provideService(SessionUser, user), Effect.provideService(SessionUserWithProviderAccounts, { ...user, providerAccounts: accounts }), Effect.annotateLogs({ userId: id }));
71
+ }));
72
+ }
73
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/server/session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import { Effect } from "effect";
2
+ import type { Rpc } from "effect/rpc";
3
+ import type { KeyContext } from "@shivaedev/contract/keys.ts";
4
+ import { type QueryReference } from "@shivaedev/contract/serverMetadata.ts";
5
+ export declare function sessionKeyContext(rpc: Pick<Rpc.AnyWithProps, "annotations">): Effect.Effect<KeyContext | undefined>;
6
+ export declare function resolveChanges(rpc: Pick<Rpc.AnyWithProps, "annotations">, references: readonly QueryReference[]): Effect.Effect<{
7
+ context: KeyContext | undefined;
8
+ keys: readonly import("@shivaedev/contract/keys.ts").Key[];
9
+ }, never, never>;
10
+ //# sourceMappingURL=sessionKeys.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionKeys.d.ts","sourceRoot":"","sources":["../../src/server/sessionKeys.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,MAAM,EAAU,MAAM,QAAQ,CAAC;AACjD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAA0B,KAAK,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAGpG,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,aAAa,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,UAAU,GAAG,SAAS,CAAC,CAWnH;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,aAAa,CAAC,EAAE,UAAU,EAAE,SAAS,cAAc,EAAE;;;iBAK/G"}
@@ -0,0 +1,22 @@
1
+ import { Context, Effect, Option } from "effect";
2
+ import { ChangesReads, KeyScope } from "@shivaedev/contract/serverMetadata.ts";
3
+ import { Identity } from "#identity.ts";
4
+ export function sessionKeyContext(rpc) {
5
+ if (Option.isNone(Context.getOption(rpc.annotations, KeyScope))) {
6
+ return Effect.succeed(undefined);
7
+ }
8
+ return Effect.gen(function* () {
9
+ const identity = yield* Effect.serviceOption(Identity);
10
+ if (Option.isNone(identity)) {
11
+ return yield* Effect.die(new Error("Session-scoped contract keys require request-local Identity"));
12
+ }
13
+ return { scope: identity.value.id };
14
+ });
15
+ }
16
+ export function resolveChanges(rpc, references) {
17
+ return Effect.map(sessionKeyContext(rpc), (context) => ({
18
+ context,
19
+ keys: Context.getUnsafe(rpc.annotations, ChangesReads)(references),
20
+ }));
21
+ }
22
+ //# sourceMappingURL=sessionKeys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionKeys.js","sourceRoot":"","sources":["../../src/server/sessionKeys.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAGjD,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAuB,MAAM,uCAAuC,CAAC;AACpG,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAExC,MAAM,UAAU,iBAAiB,CAAC,GAA0C;IAC3E,IAAI,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC;QACjE,OAAO,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAClC,CAAC;IACD,OAAO,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAC1B,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QACvD,IAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC7B,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC,CAAC;QACpG,CAAC;QACD,OAAO,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;IACrC,CAAC,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,GAA0C,EAAE,UAAqC;IAC/G,OAAO,MAAM,CAAC,GAAG,CAAC,iBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QACvD,OAAO;QACP,IAAI,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC,UAAU,CAAC;KAClE,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { SessionUserValue } from "#identity.ts";
2
+ export declare function sessionProfile({ id, name, email, role, permissions }: SessionUserValue): SessionUserValue;
3
+ //# sourceMappingURL=sessionProfile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionProfile.d.ts","sourceRoot":"","sources":["../../src/server/sessionProfile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD,wBAAgB,cAAc,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,gBAAgB,GAAG,gBAAgB,CAEzG"}
@@ -0,0 +1,4 @@
1
+ export function sessionProfile({ id, name, email, role, permissions }) {
2
+ return { email, id, name, ...(role === undefined ? {} : { role }), ...(permissions === undefined ? {} : { permissions }) };
3
+ }
4
+ //# sourceMappingURL=sessionProfile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionProfile.js","sourceRoot":"","sources":["../../src/server/sessionProfile.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,cAAc,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAoB;IACtF,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC;AAC5H,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { Layer } from "effect";
2
+ import { type SensitiveKey } from "@shivaedev/errors/sensitive.ts";
3
+ import { RequestTracing } from "#middleware.ts";
4
+ export interface RequestTracingOptions {
5
+ readonly header?: string;
6
+ readonly sensitive?: SensitiveKey;
7
+ }
8
+ export declare function requestTracingLayer(options?: RequestTracingOptions): Layer.Layer<RequestTracing>;
9
+ //# sourceMappingURL=tracing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracing.d.ts","sourceRoot":"","sources":["../../src/server/tracing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgC,KAAK,EAA6B,MAAM,QAAQ,CAAC;AAKxF,OAAO,EAAwC,KAAK,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAEzG,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEhD,MAAM,WAAW,qBAAqB;IACrC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,CAAC,EAAE,YAAY,CAAC;CAClC;AAwCD,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,qBAA0B,GAAG,KAAK,CAAC,KAAK,CAAC,cAAc,CAAC,CAepG"}