@palbase/backend 32.0.0 → 33.0.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 (53) hide show
  1. package/dist/bin/palbase-backend.cjs +79 -26
  2. package/dist/bin/palbase-backend.cjs.map +1 -1
  3. package/dist/bin/palbase-backend.js +5 -5
  4. package/dist/{chunk-IXAX5CON.js → chunk-C4ZA5AT2.js} +1 -1
  5. package/dist/{chunk-IXAX5CON.js.map → chunk-C4ZA5AT2.js.map} +1 -1
  6. package/dist/{chunk-AZJIKCOR.js → chunk-DCDHAKF3.js} +39 -23
  7. package/dist/{chunk-AZJIKCOR.js.map → chunk-DCDHAKF3.js.map} +1 -1
  8. package/dist/{chunk-Z4CZRMNF.js → chunk-GOPZPM2A.js} +2 -2
  9. package/dist/{chunk-5C5UCILO.js → chunk-N54QZER3.js} +3 -3
  10. package/dist/{chunk-XEGZ3S2Q.js → chunk-QMFOL2K6.js} +32 -7
  11. package/dist/chunk-QMFOL2K6.js.map +1 -0
  12. package/dist/{chunk-KGP6ALIU.js → chunk-XOX6RFPZ.js} +30 -8
  13. package/dist/chunk-XOX6RFPZ.js.map +1 -0
  14. package/dist/db/index.cjs +14 -4
  15. package/dist/db/index.cjs.map +1 -1
  16. package/dist/db/index.d.cts +1 -1
  17. package/dist/db/index.d.ts +1 -1
  18. package/dist/db/index.js +3 -3
  19. package/dist/engine/index.cjs +79 -26
  20. package/dist/engine/index.cjs.map +1 -1
  21. package/dist/engine/index.d.cts +3 -3
  22. package/dist/engine/index.d.ts +3 -3
  23. package/dist/engine/index.js +5 -5
  24. package/dist/{index-DgYkdNT9.d.cts → index-BWgnGj68.d.cts} +68 -20
  25. package/dist/{index-BILC9WwS.d.ts → index-Bi74dcOu.d.ts} +2 -2
  26. package/dist/{index-BgWnP07a.d.ts → index-Dg10RnZO.d.ts} +68 -20
  27. package/dist/{index-CWGiJ2Up.d.cts → index-g6iQyYci.d.cts} +2 -2
  28. package/dist/index.cjs +59 -12
  29. package/dist/index.cjs.map +1 -1
  30. package/dist/index.d.cts +6 -6
  31. package/dist/index.d.ts +6 -6
  32. package/dist/index.js +5 -5
  33. package/dist/openapi/index.d.cts +2 -2
  34. package/dist/openapi/index.d.ts +2 -2
  35. package/dist/{registry-BcRYIQ-R.d.cts → registry-6VT5RPeO.d.cts} +1 -1
  36. package/dist/{registry-ClzjxIWy.d.ts → registry-B-sxJJN0.d.ts} +1 -1
  37. package/dist/test/index.cjs +35 -8
  38. package/dist/test/index.cjs.map +1 -1
  39. package/dist/test/index.d.cts +1 -1
  40. package/dist/test/index.d.ts +1 -1
  41. package/dist/test/index.js +7 -5
  42. package/dist/test/index.js.map +1 -1
  43. package/docs/README.md +1 -1
  44. package/docs/auth.md +102 -20
  45. package/docs/llms-full.txt +129 -21
  46. package/docs/schema.md +26 -0
  47. package/package.json +1 -1
  48. package/template/db/public.ts +23 -0
  49. package/template/package.json +1 -1
  50. package/dist/chunk-KGP6ALIU.js.map +0 -1
  51. package/dist/chunk-XEGZ3S2Q.js.map +0 -1
  52. /package/dist/{chunk-Z4CZRMNF.js.map → chunk-GOPZPM2A.js.map} +0 -0
  53. /package/dist/{chunk-5C5UCILO.js.map → chunk-N54QZER3.js.map} +0 -0
@@ -3,15 +3,15 @@ import {
3
3
  assertNoOrphanEntryPoints,
4
4
  buildContainer,
5
5
  buildRelations
6
- } from "./chunk-5C5UCILO.js";
6
+ } from "./chunk-N54QZER3.js";
7
7
  import {
8
8
  __requestALS,
9
9
  __runStartHooks,
10
10
  __runWithRuntime
11
- } from "./chunk-XEGZ3S2Q.js";
11
+ } from "./chunk-QMFOL2K6.js";
12
12
  import {
13
13
  CODECS
14
- } from "./chunk-KGP6ALIU.js";
14
+ } from "./chunk-XOX6RFPZ.js";
15
15
  import {
16
16
  assertNoExpressionHandles,
17
17
  assertUsableFilter,
@@ -25,7 +25,7 @@ import {
25
25
  looksLikeUnbrandedPlanRef,
26
26
  looksLikeUnbrandedRef,
27
27
  qualifiedTableKey
28
- } from "./chunk-IXAX5CON.js";
28
+ } from "./chunk-C4ZA5AT2.js";
29
29
  import {
30
30
  getRoutes,
31
31
  resolveEffectiveAuth
@@ -3187,23 +3187,21 @@ async function createApp(opts) {
3187
3187
  if (spec.required && !callerClaims) {
3188
3188
  return envelope("unauthorized", "A valid access token is required", 401, requestId);
3189
3189
  }
3190
- if (callerClaims) {
3191
- const uploadDb = createRequestDatabase(sql, {
3192
- role: config.dbRole,
3193
- serviceRole: config.dbServiceRole,
3194
- claimsJson: JSON.stringify(callerClaims)
3195
- });
3196
- try {
3197
- const refusal = await refuseUnlessAuthorized(uploadDb.client, spec, requestId, makeRoleResolver(uploadDb.client));
3198
- if (refusal) {
3199
- await uploadDb.commit();
3200
- return refusal;
3201
- }
3190
+ const uploadDb = createRequestDatabase(sql, {
3191
+ role: config.dbRole,
3192
+ serviceRole: config.dbServiceRole,
3193
+ claimsJson: JSON.stringify(callerClaims ?? {})
3194
+ });
3195
+ try {
3196
+ const refusal = await refuseUnlessAuthorized(uploadDb.client, spec, requestId, makeRoleResolver(uploadDb.client));
3197
+ if (refusal) {
3202
3198
  await uploadDb.commit();
3203
- } catch (err) {
3204
- await uploadDb.rollback(err);
3205
- throw err;
3199
+ return refusal;
3206
3200
  }
3201
+ await uploadDb.commit();
3202
+ } catch (err) {
3203
+ await uploadDb.rollback(err);
3204
+ throw err;
3207
3205
  }
3208
3206
  const grant = grantFor(target?.entry, {
3209
3207
  userId: typeof callerClaims?.sub === "string" ? callerClaims.sub : null,
@@ -3242,11 +3240,18 @@ async function createApp(opts) {
3242
3240
  claimsJson: JSON.stringify(claims ?? {})
3243
3241
  });
3244
3242
  const rolesOfCaller = makeRoleResolver(db.client);
3245
- if (claims) {
3246
- const refusal = await refuseUnlessAuthorized(db.client, spec, requestId, rolesOfCaller);
3247
- if (refusal) return refusal;
3243
+ let dispatched = false;
3244
+ const settleBeforeRefusal = /* @__PURE__ */ __name(async () => {
3245
+ if (dispatched) return;
3246
+ await db.rollback(new Error("request refused before dispatch"));
3247
+ }, "settleBeforeRefusal");
3248
+ const refusal = await refuseUnlessAuthorized(db.client, spec, requestId, rolesOfCaller);
3249
+ if (refusal) {
3250
+ await settleBeforeRefusal();
3251
+ return refusal;
3248
3252
  }
3249
3253
  if (claims && spec.verifiedEmail && claims.email_verified !== true) {
3254
+ await settleBeforeRefusal();
3250
3255
  return envelope("email_not_verified", "A verified email address is required", 403, requestId);
3251
3256
  }
3252
3257
  let parsedBody;
@@ -3255,6 +3260,7 @@ async function createApp(opts) {
3255
3260
  if (req.method !== "GET" && req.method !== "HEAD") {
3256
3261
  const declared = Number(req.headers.get("content-length") ?? "");
3257
3262
  if (Number.isFinite(declared) && declared > MAX_BODY_BYTES) {
3263
+ await settleBeforeRefusal();
3258
3264
  return new Response(JSON.stringify({
3259
3265
  error: "payload_too_large",
3260
3266
  error_description: `Request body exceeds ${MAX_BODY_BYTES} bytes`,
@@ -3267,6 +3273,7 @@ async function createApp(opts) {
3267
3273
  }
3268
3274
  const buf = await req.arrayBuffer().catch(() => null);
3269
3275
  if (buf && buf.byteLength > MAX_BODY_BYTES) {
3276
+ await settleBeforeRefusal();
3270
3277
  return new Response(JSON.stringify({
3271
3278
  error: "payload_too_large",
3272
3279
  error_description: `Request body exceeds ${MAX_BODY_BYTES} bytes`,
@@ -3302,6 +3309,7 @@ async function createApp(opts) {
3302
3309
  ...JSON_HEADERS
3303
3310
  };
3304
3311
  if (attest.nextChallenge) headers["x-palbase-attest-challenge"] = attest.nextChallenge;
3312
+ await settleBeforeRefusal();
3305
3313
  return new Response(JSON.stringify({
3306
3314
  error: attest.reason,
3307
3315
  error_description: "This endpoint requires a verified app instance",
@@ -3316,6 +3324,7 @@ async function createApp(opts) {
3316
3324
  attestChallengeOut = attest.nextChallenge;
3317
3325
  const retryAfter = limiter.check(meta.options?.rateLimit, RateLimiter.key(hit.entry.id, userId, req.headers), Date.now());
3318
3326
  if (retryAfter !== null) {
3327
+ await settleBeforeRefusal();
3319
3328
  return new Response(JSON.stringify({
3320
3329
  error: "too_many_requests",
3321
3330
  error_description: "Rate limit exceeded for this endpoint",
@@ -3347,6 +3356,7 @@ async function createApp(opts) {
3347
3356
  readParsedBody();
3348
3357
  const r = p.schema.safeParse(parsedBody);
3349
3358
  if (!r.success) {
3359
+ await settleBeforeRefusal();
3350
3360
  return envelope("bad_request", "Request body failed validation", 400, requestId, {
3351
3361
  data: {
3352
3362
  fields: fieldErrors(r.error)
@@ -3359,6 +3369,7 @@ async function createApp(opts) {
3359
3369
  case "query": {
3360
3370
  const r = p.schema.safeParse(Object.fromEntries(url.searchParams));
3361
3371
  if (!r.success) {
3372
+ await settleBeforeRefusal();
3362
3373
  return envelope("bad_request", "Query parameters failed validation", 400, requestId, {
3363
3374
  data: {
3364
3375
  fields: fieldErrors(r.error)
@@ -3379,6 +3390,7 @@ async function createApp(opts) {
3379
3390
  }
3380
3391
  const r = p.schema.safeParse(headersFor(raw, p.schema));
3381
3392
  if (!r.success) {
3393
+ await settleBeforeRefusal();
3382
3394
  return envelope("bad_request", "Request headers failed validation", 400, requestId, {
3383
3395
  data: {
3384
3396
  fields: fieldErrors(r.error)
@@ -3411,17 +3423,20 @@ async function createApp(opts) {
3411
3423
  break;
3412
3424
  case "uploadedObject": {
3413
3425
  if (uploadSecret === "" || !verifySignature(req.headers.get(SIGNATURE_HEADER) ?? "", uploadSecret)) {
3426
+ await settleBeforeRefusal();
3414
3427
  return envelope("unauthorized", "This endpoint accepts uploads through storage, not directly", 401, requestId);
3415
3428
  }
3416
3429
  readParsedBody();
3417
3430
  const envelopeIn = parsedBody;
3418
3431
  if (!envelopeIn?.uploadedObject) {
3432
+ await settleBeforeRefusal();
3419
3433
  return envelope("bad_request", "the completion call carried no uploaded object", 400, requestId);
3420
3434
  }
3421
3435
  const uploadId = envelopeIn.uploadedObject.uploadId;
3422
3436
  if (typeof uploadId === "string" && uploadId !== "") {
3423
3437
  const already = completions.recall(uploadId);
3424
3438
  if (already) {
3439
+ await settleBeforeRefusal();
3425
3440
  return new Response(already.body, {
3426
3441
  status: already.status,
3427
3442
  headers: already.contentType ? {
@@ -3471,6 +3486,7 @@ async function createApp(opts) {
3471
3486
  args[p.index] = void 0;
3472
3487
  }
3473
3488
  }
3489
+ dispatched = true;
3474
3490
  try {
3475
3491
  const services = buildServices(db);
3476
3492
  if (meta.options?.sseConfig !== void 0) {
@@ -3663,4 +3679,4 @@ export {
3663
3679
  installEgressFence,
3664
3680
  createApp
3665
3681
  };
3666
- //# sourceMappingURL=chunk-AZJIKCOR.js.map
3682
+ //# sourceMappingURL=chunk-DCDHAKF3.js.map