@getstrata/core 1.0.8 → 1.1.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/CHANGELOG.md +52 -0
- package/dist/core/auth/authContext.d.ts +5 -2
- package/dist/core/auth/emailVerification.d.ts +1 -1
- package/dist/core/auth/guard.d.ts +5 -1
- package/dist/core/auth/jwtGuard.d.ts +6 -2
- package/dist/core/auth/oauth/oidcIdToken.d.ts +19 -0
- package/dist/core/auth/oauth/oidcProvider.d.ts +16 -4
- package/dist/core/auth/oauth/samlProvider.d.ts +7 -4
- package/dist/core/auth/oneTimeToken.d.ts +19 -0
- package/dist/core/auth/passwordLogin.d.ts +20 -0
- package/dist/core/auth/saml/samlAssertionReplay.d.ts +20 -0
- package/dist/core/auth/saml/samlServiceProvider.d.ts +51 -0
- package/dist/core/contracts/authUserDirectory.d.ts +2 -3
- package/dist/core/database/errors.d.ts +2 -1
- package/dist/core/http/response.d.ts +3 -1
- package/dist/core/mail/mailer.d.ts +6 -1
- package/dist/core/security/oauthState.d.ts +6 -2
- package/dist/core/security/safeFetch.d.ts +1 -0
- package/dist/core/security/safePath.d.ts +4 -0
- package/dist/core/security/safeUrl.d.ts +14 -1
- package/dist/core/security/totp.d.ts +1 -1
- package/dist/core/tenant/databaseTenantContext.d.ts +2 -1
- package/dist/core/tenant/enableTenantRls.d.ts +6 -0
- package/dist/core/tenant/postgresAppRole.d.ts +75 -0
- package/dist/entries/audit/exportAuditLogs.js +223 -40
- package/dist/entries/auth/accessControl.js +1 -0
- package/dist/entries/auth/basicAuthGuard.js +638 -17
- package/dist/entries/auth/emailVerification.js +1 -1
- package/dist/entries/auth/intendedUrlCookie.js +32 -2
- package/dist/entries/auth/jwt.js +1 -1
- package/dist/entries/auth/jwtGuard.js +192 -3
- package/dist/entries/auth/membershipMiddleware.js +1 -0
- package/dist/entries/auth/membershipScope.js +1 -0
- package/dist/entries/auth/membershipService.js +1 -0
- package/dist/entries/auth/oauth/oidcProvider.js +542 -20
- package/dist/entries/auth/oauth/providers.js +313 -5
- package/dist/entries/auth/oauth/samlProvider.js +552 -74
- package/dist/entries/auth/oneTimeToken.js +362 -0
- package/dist/entries/auth/password.js +1 -1
- package/dist/entries/auth/passwordLogin.js +548 -0
- package/dist/entries/auth/policy.js +1 -0
- package/dist/entries/auth/saml/samlServiceProvider.js +571 -0
- package/dist/entries/auth/scimAuthMiddleware.js +10 -3
- package/dist/entries/auth/sessionCookie.js +1 -1
- package/dist/entries/auth/sessionGuard.js +1 -1
- package/dist/entries/auth/tokenHash.js +2 -6
- package/dist/entries/crypto/fieldEncryption.js +1 -1
- package/dist/entries/crypto/mfaSecret.js +31 -5
- package/dist/entries/database/errors.js +29 -12
- package/dist/entries/database/model.js +9 -9
- package/dist/entries/facades.js +72 -9
- package/dist/entries/http/authMiddleware.js +7 -14
- package/dist/entries/http/corsMiddleware.js +69 -2
- package/dist/entries/http/csrfMiddleware.js +33 -43
- package/dist/entries/http/csrfToken.js +2 -2
- package/dist/entries/http/flashMiddleware.js +4 -2
- package/dist/entries/http/flashSession.js +4 -2
- package/dist/entries/http/formRequest.js +2 -2
- package/dist/entries/http/memoryThrottleMiddleware.js +63 -0
- package/dist/entries/http/pagination.js +2 -2
- package/dist/entries/http/requirePasswordConfirmMiddleware.js +36 -3
- package/dist/entries/http/requireWebAuthMiddleware.js +32 -2
- package/dist/entries/http/response.js +101 -45
- package/dist/entries/http/routeModelBinding.js +2 -2
- package/dist/entries/http/safeInternalPath.js +32 -2
- package/dist/entries/http/scimThrottleMiddleware.js +7 -1
- package/dist/entries/http/securedRouteModelBinding.js +2 -2
- package/dist/entries/http/securityHeadersMiddleware.js +3 -64
- package/dist/entries/http/signedUrl.js +6 -5
- package/dist/entries/http/throttleMiddleware.js +63 -0
- package/dist/entries/http/validation.js +2 -2
- package/dist/entries/http/webFormRequest.js +2 -2
- package/dist/entries/jobs/exportAuditLogsJob.js +223 -40
- package/dist/entries/mail/mailer.js +54 -8
- package/dist/entries/media/imageTransform.js +12 -1
- package/dist/entries/openapi/generator.js +0 -7
- package/dist/entries/security/oauthState.js +30 -39
- package/dist/entries/security/publicReads.js +1 -1
- package/dist/entries/security/recoveryCodes.js +2 -2
- package/dist/entries/security/safeFetch.js +195 -94
- package/dist/entries/security/safePath.js +25 -0
- package/dist/entries/security/scimTenantTokens.js +10 -3
- package/dist/entries/security/totp.js +16 -4
- package/dist/entries/storage/storage.js +24 -2
- package/dist/entries/tenant/databaseTenantContext.js +34 -12
- package/dist/entries/tenant/enableTenantRls.js +385 -0
- package/dist/entries/tracing/tracingMiddleware.js +308 -5
- package/dist/framework/public-api.d.ts +10 -3
- package/dist/index.js +2767 -1515
- package/package.json +32 -3
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
// ../../src/core/tracing/otel.ts
|
|
3
|
-
import { randomBytes } from "crypto";
|
|
4
|
-
|
|
5
2
|
// ../../src/core/runtime/appEnv.ts
|
|
6
3
|
var NON_PRODUCTION_APP_ENVS = new Set(["local", "development", "dev", "test", "testing", "ci"]);
|
|
7
4
|
function normalizeEnvValue(value) {
|
|
@@ -22,6 +19,9 @@ function envFlagEnabled(value) {
|
|
|
22
19
|
return value === "true";
|
|
23
20
|
}
|
|
24
21
|
|
|
22
|
+
// ../../src/core/tracing/otel.ts
|
|
23
|
+
import { randomBytes } from "crypto";
|
|
24
|
+
|
|
25
25
|
// ../../src/core/runtime/appKeyPrefix.ts
|
|
26
26
|
function appKeyPrefix() {
|
|
27
27
|
return process.env.APP_KEY_PREFIX?.trim() || "strata";
|
|
@@ -85,6 +85,293 @@ function sdkClientClassName() {
|
|
|
85
85
|
return fromName ? `${fromName}Client` : "AppClient";
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
+
// ../../src/core/security/safeUrl.ts
|
|
89
|
+
import { lookup as dnsLookupImpl } from "dns/promises";
|
|
90
|
+
import { BadRequestError } from "@getstrata/core/errors/http";
|
|
91
|
+
var dnsLookup = dnsLookupImpl;
|
|
92
|
+
var BLOCKED_HOSTNAMES = new Set([
|
|
93
|
+
"localhost",
|
|
94
|
+
"127.0.0.1",
|
|
95
|
+
"0.0.0.0",
|
|
96
|
+
"::1",
|
|
97
|
+
"metadata.google.internal"
|
|
98
|
+
]);
|
|
99
|
+
function parseCanonicalDottedDecimal(hostname) {
|
|
100
|
+
const parts = hostname.split(".");
|
|
101
|
+
if (parts.length !== 4) {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
const octets = [];
|
|
105
|
+
for (const part of parts) {
|
|
106
|
+
if (!/^(0|[1-9]\d{0,2})$/u.test(part)) {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
const value = Number.parseInt(part, 10);
|
|
110
|
+
if (!Number.isInteger(value) || value < 0 || value > 255) {
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
octets.push(value);
|
|
114
|
+
}
|
|
115
|
+
return octets;
|
|
116
|
+
}
|
|
117
|
+
function parseDottedIpv4(hostname) {
|
|
118
|
+
return parseCanonicalDottedDecimal(hostname);
|
|
119
|
+
}
|
|
120
|
+
function isBlockedIpv4Octets(octets) {
|
|
121
|
+
const [a = 0, b = 0] = octets;
|
|
122
|
+
if (a === 10 || a === 127 || a === 0) {
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
if (a === 169 && b === 254) {
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
if (a === 172 && b >= 16 && b <= 31) {
|
|
129
|
+
return true;
|
|
130
|
+
}
|
|
131
|
+
if (a === 192 && b === 168) {
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
if (a === 100 && b >= 64 && b <= 127) {
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
137
|
+
if (a === 198 && (b === 18 || b === 19)) {
|
|
138
|
+
return true;
|
|
139
|
+
}
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
function expandIpv6(hostname) {
|
|
143
|
+
const trimmed = hostname.trim().toLowerCase();
|
|
144
|
+
const unbracketed = trimmed.startsWith("[") && trimmed.endsWith("]") ? trimmed.slice(1, -1) : trimmed;
|
|
145
|
+
if (unbracketed.includes("%")) {
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
const mapped = unbracketed.match(/^::ffff:([0-9a-fx.]+)$/iu);
|
|
149
|
+
if (mapped?.[1]) {
|
|
150
|
+
const octets = parseDottedIpv4(mapped[1]);
|
|
151
|
+
if (!octets) {
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
return [
|
|
155
|
+
0,
|
|
156
|
+
0,
|
|
157
|
+
0,
|
|
158
|
+
0,
|
|
159
|
+
0,
|
|
160
|
+
65535,
|
|
161
|
+
octets[0] << 8 | octets[1],
|
|
162
|
+
octets[2] << 8 | octets[3]
|
|
163
|
+
];
|
|
164
|
+
}
|
|
165
|
+
const halves = unbracketed.split("::");
|
|
166
|
+
if (halves.length > 2) {
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
const parseGroup = (part) => {
|
|
170
|
+
if (!/^[0-9a-f]{1,4}$/u.test(part)) {
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
return Number.parseInt(part, 16);
|
|
174
|
+
};
|
|
175
|
+
if (halves.length === 1) {
|
|
176
|
+
const groups = unbracketed.split(":");
|
|
177
|
+
if (groups.length !== 8) {
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
const values = groups.map(parseGroup);
|
|
181
|
+
return values.every((value) => value !== null) ? values : null;
|
|
182
|
+
}
|
|
183
|
+
const head = halves[0] ? halves[0].split(":").filter(Boolean) : [];
|
|
184
|
+
const tail = halves[1] ? halves[1].split(":").filter(Boolean) : [];
|
|
185
|
+
if (head.length + tail.length > 8) {
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
const values = [];
|
|
189
|
+
for (const part of head) {
|
|
190
|
+
const value = parseGroup(part);
|
|
191
|
+
if (value === null) {
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
values.push(value);
|
|
195
|
+
}
|
|
196
|
+
while (values.length < 8 - tail.length) {
|
|
197
|
+
values.push(0);
|
|
198
|
+
}
|
|
199
|
+
for (const part of tail) {
|
|
200
|
+
const value = parseGroup(part);
|
|
201
|
+
if (value === null) {
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
values.push(value);
|
|
205
|
+
}
|
|
206
|
+
return values.length === 8 ? values : null;
|
|
207
|
+
}
|
|
208
|
+
function isBlockedIpv6(hostname) {
|
|
209
|
+
const groups = expandIpv6(hostname);
|
|
210
|
+
if (!groups) {
|
|
211
|
+
return hostname.includes(":");
|
|
212
|
+
}
|
|
213
|
+
const first = groups[0] ?? 0;
|
|
214
|
+
const second = groups[1] ?? 0;
|
|
215
|
+
if (groups.every((group) => group === 0)) {
|
|
216
|
+
return true;
|
|
217
|
+
}
|
|
218
|
+
if (groups.slice(0, 7).every((group) => group === 0) && groups[7] === 1) {
|
|
219
|
+
return true;
|
|
220
|
+
}
|
|
221
|
+
if ((first & 65472) === 65152) {
|
|
222
|
+
return true;
|
|
223
|
+
}
|
|
224
|
+
if ((first & 65024) === 64512) {
|
|
225
|
+
return true;
|
|
226
|
+
}
|
|
227
|
+
if ((first & 65280) === 65280) {
|
|
228
|
+
return true;
|
|
229
|
+
}
|
|
230
|
+
if (first === 0 && second === 0 && groups[2] === 0 && groups[3] === 0 && groups[4] === 0 && groups[5] === 65535) {
|
|
231
|
+
const a = (groups[6] ?? 0) >> 8;
|
|
232
|
+
const b = (groups[6] ?? 0) & 255;
|
|
233
|
+
const c = (groups[7] ?? 0) >> 8;
|
|
234
|
+
const d = (groups[7] ?? 0) & 255;
|
|
235
|
+
return isBlockedIpv4Octets([a, b, c, d]);
|
|
236
|
+
}
|
|
237
|
+
return false;
|
|
238
|
+
}
|
|
239
|
+
function isBlockedHostname(hostname) {
|
|
240
|
+
const normalized = hostname.trim().toLowerCase();
|
|
241
|
+
if (normalized.length === 0) {
|
|
242
|
+
return true;
|
|
243
|
+
}
|
|
244
|
+
if (BLOCKED_HOSTNAMES.has(normalized)) {
|
|
245
|
+
return true;
|
|
246
|
+
}
|
|
247
|
+
if (normalized.endsWith(".local") || normalized.endsWith(".internal")) {
|
|
248
|
+
return true;
|
|
249
|
+
}
|
|
250
|
+
if (normalized.includes(":")) {
|
|
251
|
+
return isBlockedIpv6(normalized);
|
|
252
|
+
}
|
|
253
|
+
if (/^\d+$/u.test(normalized)) {
|
|
254
|
+
return true;
|
|
255
|
+
}
|
|
256
|
+
if (normalized.includes(".")) {
|
|
257
|
+
const canonical = parseCanonicalDottedDecimal(normalized);
|
|
258
|
+
if (canonical) {
|
|
259
|
+
return isBlockedIpv4Octets(canonical);
|
|
260
|
+
}
|
|
261
|
+
if (/^[0-9a-fx.]+$/iu.test(normalized)) {
|
|
262
|
+
return true;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
return false;
|
|
266
|
+
}
|
|
267
|
+
function productionSafeOutboundOptions(options) {
|
|
268
|
+
if (!isProductionEnv()) {
|
|
269
|
+
return options;
|
|
270
|
+
}
|
|
271
|
+
return { ...options, allowPrivate: false, resolveDns: true };
|
|
272
|
+
}
|
|
273
|
+
function assertSafeOutboundUrl(rawUrl, options = {}) {
|
|
274
|
+
const resolved = productionSafeOutboundOptions(options);
|
|
275
|
+
let parsed;
|
|
276
|
+
try {
|
|
277
|
+
parsed = new URL(rawUrl);
|
|
278
|
+
} catch {
|
|
279
|
+
throw new BadRequestError("Webhook URL is invalid.");
|
|
280
|
+
}
|
|
281
|
+
if (parsed.protocol !== "https:" && !(resolved.allowHttp && parsed.protocol === "http:")) {
|
|
282
|
+
throw new BadRequestError("Webhook URL must use HTTPS.");
|
|
283
|
+
}
|
|
284
|
+
if (parsed.username || parsed.password) {
|
|
285
|
+
throw new BadRequestError("Webhook URL must not include credentials.");
|
|
286
|
+
}
|
|
287
|
+
if (!resolved.allowPrivate && isBlockedHostname(parsed.hostname)) {
|
|
288
|
+
throw new BadRequestError("Webhook URL targets a blocked host.");
|
|
289
|
+
}
|
|
290
|
+
return parsed;
|
|
291
|
+
}
|
|
292
|
+
function isBlockedIpAddress(address) {
|
|
293
|
+
return isBlockedHostname(address.trim().toLowerCase());
|
|
294
|
+
}
|
|
295
|
+
function isLiteralIpHostname(hostname) {
|
|
296
|
+
return parseCanonicalDottedDecimal(hostname) !== null || expandIpv6(hostname) !== null;
|
|
297
|
+
}
|
|
298
|
+
function pinUrlToAddress(url, address) {
|
|
299
|
+
const pinned = new URL(url.toString());
|
|
300
|
+
const ipv6 = expandIpv6(address.replace(/^\[|\]$/gu, ""));
|
|
301
|
+
pinned.hostname = ipv6 ? `[${address.replace(/^\[|\]$/gu, "")}]` : address;
|
|
302
|
+
return pinned;
|
|
303
|
+
}
|
|
304
|
+
async function resolveSafeOutboundTarget(rawUrl, options = {}) {
|
|
305
|
+
const resolvedOptions = productionSafeOutboundOptions(options);
|
|
306
|
+
const parsed = assertSafeOutboundUrl(rawUrl, resolvedOptions);
|
|
307
|
+
if (resolvedOptions.resolveDns === false || resolvedOptions.allowPrivate) {
|
|
308
|
+
return { url: parsed, addresses: [] };
|
|
309
|
+
}
|
|
310
|
+
const hostname = parsed.hostname.trim().toLowerCase();
|
|
311
|
+
if (isLiteralIpHostname(hostname)) {
|
|
312
|
+
return { url: parsed, addresses: [hostname] };
|
|
313
|
+
}
|
|
314
|
+
let results;
|
|
315
|
+
try {
|
|
316
|
+
results = await dnsLookup(hostname, { all: true, verbatim: true });
|
|
317
|
+
} catch {
|
|
318
|
+
throw new BadRequestError("Webhook URL targets a blocked host.");
|
|
319
|
+
}
|
|
320
|
+
if (results.length === 0 || results.some((result) => isBlockedIpAddress(result.address))) {
|
|
321
|
+
throw new BadRequestError("Webhook URL targets a blocked host.");
|
|
322
|
+
}
|
|
323
|
+
return { url: parsed, addresses: results.map((result) => result.address) };
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// ../../src/core/security/safeFetch.ts
|
|
327
|
+
var DEFAULT_FETCH_TIMEOUT_MS = 1e4;
|
|
328
|
+
async function safeFetch(input, init = {}, options = {}) {
|
|
329
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_FETCH_TIMEOUT_MS;
|
|
330
|
+
const maxRedirects = options.maxRedirects ?? 0;
|
|
331
|
+
const resolveDns = options.resolveDns ?? true;
|
|
332
|
+
const urlOptions = {
|
|
333
|
+
allowHttp: options.allowHttp,
|
|
334
|
+
resolveDns,
|
|
335
|
+
allowPrivate: options.allowPrivate
|
|
336
|
+
};
|
|
337
|
+
const controller = new AbortController;
|
|
338
|
+
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
339
|
+
try {
|
|
340
|
+
let current = await resolveSafeOutboundTarget(input, urlOptions);
|
|
341
|
+
let redirectCount = 0;
|
|
342
|
+
while (true) {
|
|
343
|
+
const address = current.addresses[0];
|
|
344
|
+
const fetchUrl = address ? pinUrlToAddress(current.url, address).toString() : current.url.toString();
|
|
345
|
+
const headers = new Headers(init.headers);
|
|
346
|
+
if (address && !headers.has("host")) {
|
|
347
|
+
headers.set("Host", current.url.host);
|
|
348
|
+
}
|
|
349
|
+
const fetchInit = {
|
|
350
|
+
...init,
|
|
351
|
+
headers,
|
|
352
|
+
signal: controller.signal,
|
|
353
|
+
redirect: "manual"
|
|
354
|
+
};
|
|
355
|
+
if (address) {
|
|
356
|
+
fetchInit.tls = { serverName: current.url.hostname };
|
|
357
|
+
}
|
|
358
|
+
const response = await fetch(fetchUrl, fetchInit);
|
|
359
|
+
if (response.status >= 300 && response.status < 400) {
|
|
360
|
+
const location = response.headers.get("location");
|
|
361
|
+
if (!location || redirectCount >= maxRedirects) {
|
|
362
|
+
return response;
|
|
363
|
+
}
|
|
364
|
+
current = await resolveSafeOutboundTarget(new URL(location, current.url).toString(), urlOptions);
|
|
365
|
+
redirectCount += 1;
|
|
366
|
+
continue;
|
|
367
|
+
}
|
|
368
|
+
return response;
|
|
369
|
+
}
|
|
370
|
+
} finally {
|
|
371
|
+
clearTimeout(timeout);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
88
375
|
// ../../src/core/tracing/otel.ts
|
|
89
376
|
function randomHex(bytes) {
|
|
90
377
|
return randomBytes(bytes).toString("hex");
|
|
@@ -111,7 +398,7 @@ async function exportOtelSpan(span) {
|
|
|
111
398
|
}
|
|
112
399
|
const serviceName = otelServiceName();
|
|
113
400
|
const url = endpoint.endsWith("/v1/traces") ? endpoint : `${endpoint.replace(/\/$/, "")}/v1/traces`;
|
|
114
|
-
await
|
|
401
|
+
await safeFetch(url, {
|
|
115
402
|
method: "POST",
|
|
116
403
|
headers: { "content-type": "application/json" },
|
|
117
404
|
body: JSON.stringify({
|
|
@@ -124,6 +411,11 @@ async function exportOtelSpan(span) {
|
|
|
124
411
|
}
|
|
125
412
|
]
|
|
126
413
|
})
|
|
414
|
+
}, {
|
|
415
|
+
allowHttp: !isProductionEnv(),
|
|
416
|
+
allowPrivate: !isProductionEnv(),
|
|
417
|
+
timeoutMs: 5000,
|
|
418
|
+
maxRedirects: 0
|
|
127
419
|
});
|
|
128
420
|
}
|
|
129
421
|
|
|
@@ -148,9 +440,20 @@ function runWithTraceContext(context, callback) {
|
|
|
148
440
|
}
|
|
149
441
|
|
|
150
442
|
// ../../src/core/tracing/tracingMiddleware.ts
|
|
443
|
+
function readClientTraceId(request) {
|
|
444
|
+
if (!envFlagEnabled(process.env.APP_DEBUG)) {
|
|
445
|
+
return null;
|
|
446
|
+
}
|
|
447
|
+
const raw = request.headers.get("x-trace-id")?.trim() ?? "";
|
|
448
|
+
if (!raw) {
|
|
449
|
+
return null;
|
|
450
|
+
}
|
|
451
|
+
const compact = raw.replace(/-/g, "");
|
|
452
|
+
return /^[0-9a-f]{32}$/iu.test(compact) ? compact.toLowerCase() : null;
|
|
453
|
+
}
|
|
151
454
|
function createTracingMiddleware() {
|
|
152
455
|
return async (request, next) => {
|
|
153
|
-
const traceId = (request
|
|
456
|
+
const traceId = readClientTraceId(request) ?? crypto.randomUUID().replace(/-/g, "");
|
|
154
457
|
const spanId = crypto.randomUUID().replace(/-/g, "").slice(0, 16);
|
|
155
458
|
const startedAt = performance.now();
|
|
156
459
|
const path = new URL(request.url).pathname;
|
|
@@ -6,8 +6,8 @@ export type { AdminColumn, AdminColumnType, AdminResource, AdminResourceDefiniti
|
|
|
6
6
|
export { AdminResourceRegistry, formatAdminValue, } from "../core/admin/index.ts";
|
|
7
7
|
export type { AbilityChecker } from "../core/auth/abilityChecker.ts";
|
|
8
8
|
export { isGlobalAdmin, resolveUserId } from "../core/auth/accessControl.ts";
|
|
9
|
-
export type { AuthUser } from "../core/auth/authContext.ts";
|
|
10
|
-
export { authContext, currentAuthUser, runWithAuthUser } from "../core/auth/authContext.ts";
|
|
9
|
+
export type { AuthUser, CredentialSource } from "../core/auth/authContext.ts";
|
|
10
|
+
export { authContext, currentAuthUser, currentCredentialSource, runWithAuthContext, runWithAuthUser, } from "../core/auth/authContext.ts";
|
|
11
11
|
export { BasicAuthGuard } from "../core/auth/basicAuthGuard.ts";
|
|
12
12
|
export type { AuthGuard } from "../core/auth/guard.ts";
|
|
13
13
|
export { ApiTokenGuard, AuthManager, CompositeGuard, DatabaseTokenGuard, GuestGuard, } from "../core/auth/guard.ts";
|
|
@@ -18,7 +18,12 @@ export { configureMembershipLookup, currentOrganizationIds, currentOrgRole, hasM
|
|
|
18
18
|
export { createMembershipMiddleware } from "../core/auth/membershipMiddleware.ts";
|
|
19
19
|
export { appendOrganizationScope, appendProjectScope, assertOrganizationReadable, assertResourceInCurrentTenant, emptyPaginateResult, resolveOrganizationScope, scopedOrganizationIds, } from "../core/auth/membershipScope.ts";
|
|
20
20
|
export { default as MembershipService, resolveMembershipService, } from "../core/auth/membershipService.ts";
|
|
21
|
+
export { createOidcHandshake, OidcProvider } from "../core/auth/oauth/oidcProvider.ts";
|
|
22
|
+
export { SamlProvider } from "../core/auth/oauth/samlProvider.ts";
|
|
23
|
+
export { AUTH_ONE_TIME_PURPOSES, generateOneTimeToken, hashOneTimeToken, } from "../core/auth/oneTimeToken.ts";
|
|
24
|
+
export { completePasswordLogin } from "../core/auth/passwordLogin.ts";
|
|
21
25
|
export { Policy, PolicyGate } from "../core/auth/policy.ts";
|
|
26
|
+
export { consumeSamlAssertion, createSamlServiceProvider, InMemorySamlAssertionReplayStore, readSamlEnvOptions, resetSamlReplayCacheForTests, SamlServiceProvider, setNodeSamlLoaderForTests, setSamlAssertionReplayStoreForTests, } from "../core/auth/saml/samlServiceProvider.ts";
|
|
22
27
|
export { createScimAuthMiddleware } from "../core/auth/scimAuthMiddleware.ts";
|
|
23
28
|
export { createTokenAbilityChecker } from "../core/auth/tokenAbilityChecker.ts";
|
|
24
29
|
export { type CacheDriver, type CreateCacheStoreOptions, createCacheStore, } from "../core/cache/createCacheStore.ts";
|
|
@@ -130,11 +135,13 @@ export { resolveApplicationAuth, resolveApplicationCache, resolveApplicationConf
|
|
|
130
135
|
export type { ScheduledTask } from "../core/scheduler/schedule.ts";
|
|
131
136
|
export { appSchedule, runDueScheduledTasks, Schedule } from "../core/scheduler/schedule.ts";
|
|
132
137
|
export { guestCanViewResource, isPublicReadsEnabled } from "../core/security/publicReads.ts";
|
|
133
|
-
export {
|
|
138
|
+
export { assertPathUnderRoot, assertUrlPathUnderRoot } from "../core/security/safePath.ts";
|
|
139
|
+
export { assertSafeOutboundUrl, assertSafeOutboundUrlResolved, isBlockedHostname, isBlockedIpAddress, pinUrlToAddress, resetDnsLookupForTests, resolveSafeOutboundTarget, setDnsLookupForTests, } from "../core/security/safeUrl.ts";
|
|
134
140
|
export type { SecurityEventDetails } from "../core/security/securityEvents.ts";
|
|
135
141
|
export { logSecurityEvent } from "../core/security/securityEvents.ts";
|
|
136
142
|
export type { StorageDriver } from "../core/storage/storage.ts";
|
|
137
143
|
export { createStorageDriver, LocalStorageDriver, resetDefaultStorage, StorageManager, } from "../core/storage/storage.ts";
|
|
144
|
+
export { enableTenantRlsSql, enableUserOwnedRlsSql, generatedRlsBootstrapSql, RLS_HELPER_SQL, } from "../core/tenant/enableTenantRls.ts";
|
|
138
145
|
export type { TenancyDriver } from "../core/tenant/tenancyConfig.ts";
|
|
139
146
|
export { isRlsTenancy, isTenancyEnabled, readTenancyDriver, } from "../core/tenant/tenancyConfig.ts";
|
|
140
147
|
export type { TenantContext } from "../core/tenant/tenantContext.ts";
|