@palbase/backend 29.0.0 → 30.0.1

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 (34) hide show
  1. package/dist/bin/palbase-backend.cjs +22 -7
  2. package/dist/bin/palbase-backend.cjs.map +1 -1
  3. package/dist/bin/palbase-backend.js +2 -2
  4. package/dist/{chunk-DHJ3SYAE.js → chunk-RADVOY7Y.js} +23 -9
  5. package/dist/{chunk-DHJ3SYAE.js.map → chunk-RADVOY7Y.js.map} +1 -1
  6. package/dist/{chunk-ESSQ3YML.js → chunk-YRVIWHJC.js} +7 -3
  7. package/dist/{chunk-ESSQ3YML.js.map → chunk-YRVIWHJC.js.map} +1 -1
  8. package/dist/db/index.d.cts +1 -1
  9. package/dist/db/index.d.ts +1 -1
  10. package/dist/engine/index.cjs +22 -7
  11. package/dist/engine/index.cjs.map +1 -1
  12. package/dist/engine/index.d.cts +3 -3
  13. package/dist/engine/index.d.ts +3 -3
  14. package/dist/engine/index.js +2 -2
  15. package/dist/{index-BOe82fsK.d.ts → index-8qy3kIuA.d.ts} +66 -4
  16. package/dist/{index-ChvoVczS.d.cts → index-DtCgaZAg.d.cts} +66 -4
  17. package/dist/{index-BZfmdRmh.d.cts → index-Zi7MptvP.d.cts} +3 -3
  18. package/dist/{index-BYDUKexK.d.ts → index-b-Q3l7W5.d.ts} +3 -3
  19. package/dist/index.cjs +55 -2
  20. package/dist/index.cjs.map +1 -1
  21. package/dist/index.d.cts +51 -11
  22. package/dist/index.d.ts +51 -11
  23. package/dist/index.js +50 -1
  24. package/dist/index.js.map +1 -1
  25. package/dist/openapi/index.d.cts +2 -2
  26. package/dist/openapi/index.d.ts +2 -2
  27. package/dist/{registry-DaqHsOq8.d.ts → registry-BGJ-Al6F.d.ts} +1 -1
  28. package/dist/{registry-B2KfKWv1.d.cts → registry-CEYLH-Iz.d.cts} +1 -1
  29. package/dist/test/index.d.cts +1 -1
  30. package/dist/test/index.d.ts +1 -1
  31. package/docs/README.md +1 -1
  32. package/docs/llms-full.txt +1 -1
  33. package/package.json +1 -1
  34. package/template/package.json +1 -1
@@ -1056,6 +1056,7 @@ var Storage = Object.assign({
1056
1056
  });
1057
1057
  var Cache = makeServiceProxy("Cache");
1058
1058
  var Secrets = makeServiceProxy("Secrets");
1059
+ var Auth = makeServiceProxy("Auth");
1059
1060
  var Log = makeServiceProxy("Log");
1060
1061
  var Notifications = makeServiceProxy("Notifications");
1061
1062
  var rawFlags = makeServiceProxy("Flags");
@@ -4514,7 +4515,7 @@ var AUTHOR_ANSWERED = /* @__PURE__ */ new Set([
4514
4515
  409,
4515
4516
  429
4516
4517
  ]);
4517
- async function refuseUnlessAuthorized(client, spec, requestId) {
4518
+ async function refuseUnlessAuthorized(client, spec, requestId, rolesOfCaller) {
4518
4519
  if (spec.permission !== void 0) {
4519
4520
  const [row] = await client.query("select auth.has_permission($1) as ok", [
4520
4521
  spec.permission
@@ -4524,16 +4525,22 @@ async function refuseUnlessAuthorized(client, spec, requestId) {
4524
4525
  }
4525
4526
  }
4526
4527
  if (spec.role !== void 0) {
4527
- const [row] = await client.query("select $1 = any(auth.app_roles()) as ok", [
4528
- spec.role
4529
- ]);
4530
- if (row?.ok !== true) {
4528
+ const held = await rolesOfCaller();
4529
+ if (!held.includes(spec.role)) {
4531
4530
  return envelope("forbidden", `This endpoint requires the "${spec.role}" role`, 403, requestId);
4532
4531
  }
4533
4532
  }
4534
4533
  return null;
4535
4534
  }
4536
4535
  __name(refuseUnlessAuthorized, "refuseUnlessAuthorized");
4536
+ function makeRoleResolver(client) {
4537
+ let pending = null;
4538
+ return () => {
4539
+ pending ??= client.query("select unnest(auth.app_roles()) as role").then((rows) => rows.map((r) => r.role));
4540
+ return pending;
4541
+ };
4542
+ }
4543
+ __name(makeRoleResolver, "makeRoleResolver");
4537
4544
  async function createApp(opts) {
4538
4545
  const { config, controllers } = opts;
4539
4546
  const container = buildContainer();
@@ -4582,6 +4589,7 @@ async function createApp(opts) {
4582
4589
  Database: db?.client ?? stubModule("Database (a start hook runs before any request \u2014 open your own connection here)"),
4583
4590
  Cache: cache,
4584
4591
  Log: log,
4592
+ Auth: modules.Auth ?? stubModule("Auth"),
4585
4593
  Documents: modules.Documents ?? stubModule("Documents"),
4586
4594
  Storage: modules.Storage ?? stubModule("Storage"),
4587
4595
  Notifications: modules.Notifications ?? stubModule("Notifications"),
@@ -4632,7 +4640,7 @@ async function createApp(opts) {
4632
4640
  claimsJson: JSON.stringify(callerClaims)
4633
4641
  });
4634
4642
  try {
4635
- const refusal = await refuseUnlessAuthorized(uploadDb.client, spec, requestId);
4643
+ const refusal = await refuseUnlessAuthorized(uploadDb.client, spec, requestId, makeRoleResolver(uploadDb.client));
4636
4644
  if (refusal) {
4637
4645
  await uploadDb.commit();
4638
4646
  return refusal;
@@ -4679,8 +4687,9 @@ async function createApp(opts) {
4679
4687
  serviceRole: config.dbServiceRole,
4680
4688
  claimsJson: JSON.stringify(claims ?? {})
4681
4689
  });
4690
+ const rolesOfCaller = makeRoleResolver(db.client);
4682
4691
  if (claims) {
4683
- const refusal = await refuseUnlessAuthorized(db.client, spec, requestId);
4692
+ const refusal = await refuseUnlessAuthorized(db.client, spec, requestId, rolesOfCaller);
4684
4693
  if (refusal) return refusal;
4685
4694
  }
4686
4695
  if (claims && spec.verifiedEmail && claims.email_verified !== true) {
@@ -4833,6 +4842,12 @@ async function createApp(opts) {
4833
4842
  role: claims.role,
4834
4843
  emailVerified: claims.email_verified === true,
4835
4844
  metadata: claims.metadata ?? {},
4845
+ // The caller's APPLICATION roles, from `auth.user_roles` — the
4846
+ // same resolution the gate used, so the handler cannot read a
4847
+ // different set than the one it was admitted on. Never from a
4848
+ // claim: a revoked role has to bite on the next request, and a
4849
+ // token says only what was true when it was minted.
4850
+ roles: await rolesOfCaller(),
4836
4851
  // Server-owned and only ever filled from a verdict palauth
4837
4852
  // returned. Never from a raw header, never from JWT metadata —
4838
4853
  // the type has said so since it was written and this is the