permdock 0.0.0 → 0.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.
Files changed (290) hide show
  1. package/README.md +268 -1
  2. package/dist/a2a/index.d.ts +178 -0
  3. package/dist/a2a/index.js +271 -0
  4. package/dist/ai-sdk/index.d.ts +74 -0
  5. package/dist/ai-sdk/index.js +137 -0
  6. package/dist/approval-required-TzNB9oQA.js +6 -0
  7. package/dist/approvals/index.d.ts +3 -0
  8. package/dist/approvals/index.js +4 -0
  9. package/dist/approvals-DaxY-Bdg.js +218 -0
  10. package/dist/approvers-aH0PJkmf.js +20 -0
  11. package/dist/arazzo-CTeVuXr5.js +70 -0
  12. package/dist/arazzo-aoTkqYsJ.js +54 -0
  13. package/dist/authzen/index.d.ts +48 -0
  14. package/dist/authzen/index.js +336 -0
  15. package/dist/better-auth/index.d.ts +92 -0
  16. package/dist/better-auth/index.js +324 -0
  17. package/dist/budget-JqcRqyhK.d.ts +11 -0
  18. package/dist/budget-NbEtbJC_.js +11 -0
  19. package/dist/capability-B68OFnZx.js +171 -0
  20. package/dist/capability-BDG_nkxt.d.ts +99 -0
  21. package/dist/catalog/index.d.ts +12 -0
  22. package/dist/catalog/index.js +2 -0
  23. package/dist/catalog-B0E6bggc.js +48 -0
  24. package/dist/catalog-H-vFGwWK.js +55 -0
  25. package/dist/catalog-doc-BSo_Q_-6.js +298 -0
  26. package/dist/catalog-idsHc0vo.js +2 -0
  27. package/dist/catalog-path-CnI0XTFK.js +12 -0
  28. package/dist/claude-agent/index.d.ts +81 -0
  29. package/dist/claude-agent/index.js +83 -0
  30. package/dist/clerk/index.d.ts +56 -0
  31. package/dist/clerk/index.js +280 -0
  32. package/dist/cli/bin.d.ts +1 -0
  33. package/dist/cli/bin.js +20 -0
  34. package/dist/cli/index.d.ts +46 -0
  35. package/dist/cli/index.js +5 -0
  36. package/dist/cloud/index.d.ts +91 -0
  37. package/dist/cloud/index.js +390 -0
  38. package/dist/cloud-BNQTrmrr.js +50 -0
  39. package/dist/cloud-Cuxr6Czw.js +117 -0
  40. package/dist/collect-B7_TIfmg.js +49 -0
  41. package/dist/collect-O-tOtbnk.js +350 -0
  42. package/dist/collect-fRPAQIWb.js +2 -0
  43. package/dist/commands-BMh_Etm2.js +93 -0
  44. package/dist/compact-y6vfu2_f.js +19 -0
  45. package/dist/compare-pfyVnBjE.js +12 -0
  46. package/dist/compile-CQbvyIBr.d.ts +30 -0
  47. package/dist/compile-D22iwvuV.js +558 -0
  48. package/dist/config-BPYmjTOp.js +26 -0
  49. package/dist/connection-JvqwHODC.js +194 -0
  50. package/dist/context-CKEAabd7.js +73 -0
  51. package/dist/context-gtAwAILx.js +6 -0
  52. package/dist/convex/index.d.ts +40 -0
  53. package/dist/convex/index.js +55 -0
  54. package/dist/create-BKF3dgFk.d.ts +162 -0
  55. package/dist/create-CSkhDU9T.js +222 -0
  56. package/dist/credential-B_rkUNlY.js +326 -0
  57. package/dist/credentials-BgRX3WEg.js +268 -0
  58. package/dist/describe-Bt1YD5uS.js +99 -0
  59. package/dist/describe-DernyItf.d.ts +37 -0
  60. package/dist/diff-BUzf5Poi.js +48 -0
  61. package/dist/diff-x5Il8LVa.js +418 -0
  62. package/dist/digest-B3kc_PgQ.d.ts +19 -0
  63. package/dist/digest-BI-6aa6d.js +27 -0
  64. package/dist/doctor-BGle8Gqi.js +1314 -0
  65. package/dist/doctor-Bqo6FwUa.js +53 -0
  66. package/dist/drizzle/index.d.ts +72 -0
  67. package/dist/drizzle/index.js +160 -0
  68. package/dist/duration-xK2jGFVc.js +25 -0
  69. package/dist/elysia/index.d.ts +71 -0
  70. package/dist/elysia/index.js +103 -0
  71. package/dist/errors-DSMnAVNa.js +43 -0
  72. package/dist/errors-DbZ1YOnb.d.ts +138 -0
  73. package/dist/errors-Iy71s7Oj.js +177 -0
  74. package/dist/errors-m3u9TmDu.js +27 -0
  75. package/dist/evaluations-DsAU9ppl.js +479 -0
  76. package/dist/eve/index.d.ts +95 -0
  77. package/dist/eve/index.js +181 -0
  78. package/dist/express/index.d.ts +46 -0
  79. package/dist/express/index.js +108 -0
  80. package/dist/fastify/index.d.ts +56 -0
  81. package/dist/fastify/index.js +141 -0
  82. package/dist/files-B_wAGYmt.js +121 -0
  83. package/dist/fixtures-Cvaw0gDG.js +64 -0
  84. package/dist/freeze-y1_jQL4v.js +31 -0
  85. package/dist/from-snapshot-BMGnhmgv.js +552 -0
  86. package/dist/generate-CH7ThJ14.js +173 -0
  87. package/dist/grantee-Bv04_Vzf.js +521 -0
  88. package/dist/headers-B5RRv3Xm.js +6 -0
  89. package/dist/headers-C8SHQccD.d.ts +6 -0
  90. package/dist/helpers-DnSOrhB9.js +682 -0
  91. package/dist/hono/index.d.ts +70 -0
  92. package/dist/hono/index.js +131 -0
  93. package/dist/hosted-BwKQ1BTA.js +265 -0
  94. package/dist/http-DPuDaChb.d.ts +13 -0
  95. package/dist/http-GgVApX1k.js +111 -0
  96. package/dist/index-CltcQ4Bf.d.ts +138 -0
  97. package/dist/index-LF_hS-yn.d.ts +177 -0
  98. package/dist/index-fG6NSXlc.d.ts +9 -0
  99. package/dist/index-xIxJLwOQ.d.ts +415 -0
  100. package/dist/index.d.ts +11 -0
  101. package/dist/index.js +21 -0
  102. package/dist/jwt/index.d.ts +87 -0
  103. package/dist/jwt/index.js +571 -0
  104. package/dist/kernel-YOGCWNLf.js +211 -0
  105. package/dist/kysely/index.d.ts +77 -0
  106. package/dist/kysely/index.js +129 -0
  107. package/dist/load-BZ24CpZP.js +69 -0
  108. package/dist/load-QOOm1z70.js +2 -0
  109. package/dist/load-jose-BL6LH4bL.js +11 -0
  110. package/dist/lru-8q4WZjBV.js +28 -0
  111. package/dist/manifest-DDQbC6K0.d.ts +118 -0
  112. package/dist/map-DowSO96j.js +158 -0
  113. package/dist/map-claims-B_6I1Rn-.js +360 -0
  114. package/dist/map-error-RJ3ZsUyA.js +16 -0
  115. package/dist/markers-B0hYLvMD.js +60 -0
  116. package/dist/may-use-CnFEjVEp.js +37 -0
  117. package/dist/mcp/index.d.ts +127 -0
  118. package/dist/mcp/index.js +563 -0
  119. package/dist/nest/index.d.ts +80 -0
  120. package/dist/nest/index.js +270 -0
  121. package/dist/next/client.d.ts +24 -0
  122. package/dist/next/client.js +31 -0
  123. package/dist/next/index.d.ts +110 -0
  124. package/dist/next/index.js +195 -0
  125. package/dist/next/plugin.d.ts +14 -0
  126. package/dist/next/plugin.js +2 -0
  127. package/dist/node/index.d.ts +43 -0
  128. package/dist/node/index.js +66 -0
  129. package/dist/openai/index.d.ts +71 -0
  130. package/dist/openai/index.js +105 -0
  131. package/dist/openapi/index.d.ts +93 -0
  132. package/dist/openapi/index.js +3 -0
  133. package/dist/openapi-CwePaF7C.js +164 -0
  134. package/dist/openapi-DWD0Uc_4.js +250 -0
  135. package/dist/openapi-DcqM8nU7.js +306 -0
  136. package/dist/openapi-import-BWRUNNeW.js +5959 -0
  137. package/dist/openapi-schema-D8j_T9tO.js +6902 -0
  138. package/dist/orpc/index.d.ts +64 -0
  139. package/dist/orpc/index.js +188 -0
  140. package/dist/otel/index.d.ts +13 -0
  141. package/dist/otel/index.js +202 -0
  142. package/dist/package-root-zGkxO3oN.js +30 -0
  143. package/dist/parse-DPfIvFMU.js +135 -0
  144. package/dist/pdp/index.d.ts +22 -0
  145. package/dist/pdp/index.js +795 -0
  146. package/dist/peer-BOr_kJE1.js +31 -0
  147. package/dist/permdock-yoZ7EjxX.js +2956 -0
  148. package/dist/permissions-B4apnahQ.d.ts +185 -0
  149. package/dist/permissions-B8vCg_bI.d.ts +52 -0
  150. package/dist/permissions-CofRqesP.js +142 -0
  151. package/dist/permissions-DC7GROPA.js +600 -0
  152. package/dist/pg-4GJWDUxG.js +953 -0
  153. package/dist/pins-CqE1jZuF.js +12 -0
  154. package/dist/plugin-4gr7IxFJ.js +65 -0
  155. package/dist/policy-ANp36PnI.js +971 -0
  156. package/dist/policy-CInmNGkM.d.ts +1959 -0
  157. package/dist/policy-Cq2fB8Q5.d.ts +20 -0
  158. package/dist/prisma/index.d.ts +135 -0
  159. package/dist/prisma/index.js +430 -0
  160. package/dist/problem-Cgp9-KZA.js +226 -0
  161. package/dist/prompt-CXYhLfsS.js +32 -0
  162. package/dist/protected-B4K3BKoX.js +138 -0
  163. package/dist/protected-BuPAycJT.d.ts +26 -0
  164. package/dist/protected-wY7nXhY9.d.ts +23 -0
  165. package/dist/provider-_wx46HpB.js +48 -0
  166. package/dist/provider-wTAUda2v.d.ts +6 -0
  167. package/dist/react/index.d.ts +6 -0
  168. package/dist/react/index.js +6 -0
  169. package/dist/react/provider-client.d.ts +2 -0
  170. package/dist/react/provider-client.js +3 -0
  171. package/dist/react-native/index.d.ts +42 -0
  172. package/dist/react-native/index.js +174 -0
  173. package/dist/refs-ChLSxbST.js +90 -0
  174. package/dist/relations-r4soIFZB.js +426 -0
  175. package/dist/revocations-Cy06JNx2.d.ts +21 -0
  176. package/dist/rls-BOFU3chG.js +233 -0
  177. package/dist/rls-CJVja9Ww.js +2119 -0
  178. package/dist/rls-graph-DxQ39PJj.js +371 -0
  179. package/dist/rls-helpers-BxRuif0l.js +1346 -0
  180. package/dist/rls-import-CXV6LBlS.js +942 -0
  181. package/dist/rls-migrate-DrFPbf8p.js +366 -0
  182. package/dist/row-check-BajTgQZ-.d.ts +43 -0
  183. package/dist/run-CJ6UvS3a.js +155 -0
  184. package/dist/runtime-DP9ttFh1.js +27 -0
  185. package/dist/saas-BRrZzJkM.js +1193 -0
  186. package/dist/schema-P8yoma__.js +296 -0
  187. package/dist/scim/index.d.ts +2 -0
  188. package/dist/scim/index.js +2 -0
  189. package/dist/scim-9NFa0XVZ.js +1445 -0
  190. package/dist/scopes-cKVp_WTw.js +212 -0
  191. package/dist/server/index.d.ts +123 -0
  192. package/dist/server/index.js +8 -0
  193. package/dist/sha256-BO0swRXL.js +150 -0
  194. package/dist/sink-Bd9PSyfq.js +141 -0
  195. package/dist/sink-Cfr9-7YC.d.ts +104 -0
  196. package/dist/skills-C_lpV4Jx.js +50 -0
  197. package/dist/skills-Dx3QLnMY.js +110 -0
  198. package/dist/snapshot-DE8dE_hz.js +1051 -0
  199. package/dist/solid/index.d.ts +63 -0
  200. package/dist/solid/index.js +197 -0
  201. package/dist/source-DoBBYJi2.js +6 -0
  202. package/dist/sources-DOpW5Ila.d.ts +347 -0
  203. package/dist/sources-DVHM3Mwq.js +284 -0
  204. package/dist/sql-Bll1d7y0.js +22 -0
  205. package/dist/src-CTNT-PBW.js +430 -0
  206. package/dist/ssf/index.d.ts +3 -0
  207. package/dist/ssf/index.js +622 -0
  208. package/dist/store-Bq90395i.d.ts +27 -0
  209. package/dist/store-C6hFW6ta.js +508 -0
  210. package/dist/stores-CkG2HrSg.js +140 -0
  211. package/dist/stores-CvOnu_2T.d.ts +41 -0
  212. package/dist/stream-BhMfZOwr.d.ts +12 -0
  213. package/dist/stream-Q_xlB6Ko.js +52 -0
  214. package/dist/style-CTm1AXDT.js +22 -0
  215. package/dist/subject-C6dLxqHU.js +24 -0
  216. package/dist/subject-settings-xt7V845g.js +82 -0
  217. package/dist/supabase/index.d.ts +67 -0
  218. package/dist/supabase/index.js +4 -0
  219. package/dist/supabase/middleware.d.ts +77 -0
  220. package/dist/supabase/middleware.js +68 -0
  221. package/dist/supabase-D8UlBA7Z.js +83 -0
  222. package/dist/supabase-DTxGtYdi.js +796 -0
  223. package/dist/supabase-hook-DW-xP4hU.js +2 -0
  224. package/dist/supabase-hook-D_OqGb_V.js +1528 -0
  225. package/dist/svelte/Protected.svelte +34 -0
  226. package/dist/svelte/index.d.ts +10 -0
  227. package/dist/svelte/index.js +53 -0
  228. package/dist/svelte/runtime.d.ts +6 -0
  229. package/dist/svelte/runtime.js +3 -0
  230. package/dist/svelte/source.d.ts +10 -0
  231. package/dist/svelte/source.js +8 -0
  232. package/dist/terminal/index.d.ts +171 -0
  233. package/dist/terminal/index.js +821 -0
  234. package/dist/testing/index.d.ts +656 -0
  235. package/dist/testing/index.js +3208 -0
  236. package/dist/testing/saas/index.d.ts +194 -0
  237. package/dist/testing/saas/index.js +3 -0
  238. package/dist/testing/saas/permissions.d.ts +2 -0
  239. package/dist/testing/saas/permissions.js +2 -0
  240. package/dist/text-diff-BdkkYSbi.js +15 -0
  241. package/dist/thenable-okc2xDsj.js +10 -0
  242. package/dist/timeout-D51niuQP.js +8 -0
  243. package/dist/trpc/index.d.ts +80 -0
  244. package/dist/trpc/index.js +205 -0
  245. package/dist/types-B8w5PFtS.d.ts +141 -0
  246. package/dist/types-B9dmiiab.d.ts +66 -0
  247. package/dist/types-BBK-exvJ.d.ts +177 -0
  248. package/dist/types-BvBk1wgn.d.ts +118 -0
  249. package/dist/types-CxquUByI.d.ts +9 -0
  250. package/dist/types-D6Z6-rKJ.d.ts +312 -0
  251. package/dist/types-DbWdEfcm.d.ts +87 -0
  252. package/dist/types-bva3i4Gf.d.ts +98 -0
  253. package/dist/types-i4BAOvdb.d.ts +97 -0
  254. package/dist/unplugin/index.d.ts +7 -0
  255. package/dist/unplugin/index.js +30 -0
  256. package/dist/usage-1ozMubLY.js +42 -0
  257. package/dist/usage-CUnK6Ou9.js +530 -0
  258. package/dist/usage-PyEor6GA.js +2 -0
  259. package/dist/validity-D0uRmJKJ.js +224 -0
  260. package/dist/verifier-B90agnhl.js +461 -0
  261. package/dist/version-CnSh33Fj.js +16 -0
  262. package/dist/vocabulary-Dk0fs-Jk.d.ts +56 -0
  263. package/dist/vue/index.d.ts +57 -0
  264. package/dist/vue/index.js +203 -0
  265. package/dist/webmcp/index.d.ts +75 -0
  266. package/dist/webmcp/index.js +313 -0
  267. package/package.json +423 -4
  268. package/rulesets/permdock.yaml +29 -0
  269. package/schemas/catalog-v1.json +507 -0
  270. package/schemas/openapi/oas-3.1.json +1298 -0
  271. package/schemas/openapi/oas-3.2.json +1516 -0
  272. package/schemas/openapi/overlay-1.1.json +79 -0
  273. package/schemas/supabase-claims-v1.json +139 -0
  274. package/schemas/supabase-manifest-v1.json +217 -0
  275. package/skills/permdock/SKILL.md +66 -0
  276. package/skills/permdock-agents/SKILL.md +77 -0
  277. package/skills/permdock-agents/references/runtimes.md +211 -0
  278. package/skills/permdock-approvals/SKILL.md +80 -0
  279. package/skills/permdock-approvals/references/stores-and-resume.md +83 -0
  280. package/skills/permdock-audit/SKILL.md +67 -0
  281. package/skills/permdock-credentials/SKILL.md +55 -0
  282. package/skills/permdock-credentials/references/tokens-keys-links.md +127 -0
  283. package/skills/permdock-data/SKILL.md +57 -0
  284. package/skills/permdock-data/references/queries-and-rls.md +54 -0
  285. package/skills/permdock-data/references/relationships.md +65 -0
  286. package/skills/permdock-tenancy/SKILL.md +77 -0
  287. package/skills/permdock-tenancy/references/ownership-and-custom-roles.md +83 -0
  288. package/skills/permdock-wire/SKILL.md +116 -0
  289. package/skills/permdock-wire/references/adapters.md +480 -0
  290. package/skills/permdock-wire/references/policy-options.md +43 -0
@@ -0,0 +1,222 @@
1
+ import { t as compact } from "./compact-y6vfu2_f.js";
2
+ import { g as listPermissions } from "./permissions-DC7GROPA.js";
3
+ import { t as createPermDock$1 } from "./permdock-yoZ7EjxX.js";
4
+ import { n as isActor } from "./subject-C6dLxqHU.js";
5
+ import { a as problemFromDecision, i as notFoundProblem, o as problemResponse, t as PROBLEM_BASE } from "./problem-Cgp9-KZA.js";
6
+ import { n as createEvaluationsHandler, r as InvalidSignatureError, t as applyApprovalResume } from "./evaluations-DsAU9ppl.js";
7
+ //#region src/server/create.ts
8
+ /** Resolves an adapter `tenant` option against its framework context; a throw is no tenant. */
9
+ async function tenantScope(option, context) {
10
+ if (option === void 0 || typeof option === "string") return { tenant: option };
11
+ try {
12
+ return { tenant: await option(context) };
13
+ } catch {
14
+ return { tenant: void 0 };
15
+ }
16
+ }
17
+ async function resolveActor(request, options) {
18
+ const verified = options.webBotAuth === void 0 ? void 0 : await options.webBotAuth(request);
19
+ if (verified !== void 0) return verified;
20
+ if (options.actor === void 0) return;
21
+ try {
22
+ const resolved = await options.actor(request);
23
+ return isActor(resolved) ? resolved : void 0;
24
+ } catch {
25
+ return;
26
+ }
27
+ }
28
+ const NO_TENANT = "\0";
29
+ function createPermDock(policy, options) {
30
+ return createKernel(policy, options);
31
+ }
32
+ function problemFor(decision, init, approval) {
33
+ if (init?.permission !== void 0) return problemFromDecision(decision, init.permission, {
34
+ principal: null,
35
+ context: {}
36
+ }, compact({
37
+ instance: init.instance,
38
+ approval
39
+ }));
40
+ return problemResponse({
41
+ type: `${PROBLEM_BASE}/denied`,
42
+ title: "Permission denied",
43
+ status: 403,
44
+ detail: decision.outcome
45
+ });
46
+ }
47
+ /**
48
+ * The kernel behind every HTTP adapter. The subject and actor are resolved
49
+ * once per `Request`; one instance is cached per `(Request, tenant)`, so a
50
+ * global middleware and a later tenant-scoped `protect` never share a tenant.
51
+ */
52
+ function createKernel(policy, options) {
53
+ const adapter = options.adapter ?? "server";
54
+ const subjects = /* @__PURE__ */ new WeakMap();
55
+ const instances = /* @__PURE__ */ new WeakMap();
56
+ const resolveSubject = (request) => {
57
+ const hit = subjects.get(request);
58
+ if (hit !== void 0) return hit;
59
+ const resolved = (async () => {
60
+ const actor = await resolveActor(request, options);
61
+ let user = null;
62
+ try {
63
+ user = await options.subject(request);
64
+ } catch {
65
+ user = null;
66
+ }
67
+ return {
68
+ user,
69
+ actor
70
+ };
71
+ })();
72
+ subjects.set(request, resolved);
73
+ return resolved;
74
+ };
75
+ const freshSubject = async (request) => {
76
+ const actor = await resolveActor(request, options);
77
+ try {
78
+ return {
79
+ user: await options.subject(request),
80
+ actor
81
+ };
82
+ } catch {
83
+ return {
84
+ user: null,
85
+ actor
86
+ };
87
+ }
88
+ };
89
+ const instanceFor = async ({ user, actor }, tenant) => {
90
+ const coreOptions = compact({
91
+ tenant,
92
+ memberships: options.memberships,
93
+ relations: options.relations,
94
+ entitlements: options.entitlements,
95
+ customRoles: options.customRoles,
96
+ policies: options.policies,
97
+ sink: options.sink,
98
+ limits: options.limits,
99
+ actor
100
+ });
101
+ const permdock = await createPermDock$1(policy, user, coreOptions);
102
+ const remote = options.pdp === void 0 ? void 0 : await options.pdp(policy, user, coreOptions);
103
+ return {
104
+ permdock: options.wrap === void 0 ? permdock : options.wrap(permdock),
105
+ remote
106
+ };
107
+ };
108
+ const build = async (request, scope) => {
109
+ const { tenant } = scope ?? await tenantScope(options.tenant, request);
110
+ let byTenant = instances.get(request);
111
+ if (byTenant === void 0) {
112
+ byTenant = /* @__PURE__ */ new Map();
113
+ instances.set(request, byTenant);
114
+ }
115
+ const key = tenant ?? NO_TENANT;
116
+ const hit = byTenant.get(key);
117
+ if (hit !== void 0) return hit;
118
+ const built = (async () => instanceFor(await resolveSubject(request), tenant))();
119
+ byTenant.set(key, built);
120
+ return built;
121
+ };
122
+ const connection = async (request, connectionOptions = {}, scope) => {
123
+ const { tenant } = scope ?? await tenantScope(options.tenant, request);
124
+ const { openConnection } = await import("./connection-JvqwHODC.js");
125
+ return openConnection({
126
+ open: async () => (await build(request, { tenant })).permdock,
127
+ rebuild: async () => (await instanceFor(await freshSubject(request), tenant)).permdock,
128
+ tenant,
129
+ ...options.revocations === void 0 ? {} : { feed: options.revocations },
130
+ adapter,
131
+ options: connectionOptions
132
+ });
133
+ };
134
+ const permdock = async (request, scope) => (await build(request, scope)).permdock;
135
+ const protect = (permission, loadData, protectOptions = {}) => async (request, scope) => {
136
+ let instance;
137
+ let remote;
138
+ try {
139
+ ({permdock: instance, remote} = await build(request, scope));
140
+ } catch (error) {
141
+ if (error instanceof InvalidSignatureError) return {
142
+ ok: false,
143
+ response: error.response
144
+ };
145
+ throw error;
146
+ }
147
+ let data;
148
+ if (loadData !== void 0) {
149
+ const loaded = await loadData(request);
150
+ if (loaded === null || loaded === void 0) return {
151
+ ok: false,
152
+ response: notFoundProblem()
153
+ };
154
+ data = loaded;
155
+ }
156
+ const decideOptions = compact({
157
+ source: "adapter",
158
+ adapter,
159
+ ...protectOptions.trusted === true ? { trusted: true } : {
160
+ trusted: false,
161
+ boundary: "http-body"
162
+ }
163
+ });
164
+ const raw = remote === void 0 ? instance.decide(permission, data, decideOptions) : await remote.decide(permission, data, decideOptions).catch(() => ({
165
+ outcome: "denied",
166
+ denials: [{
167
+ role: null,
168
+ reason: "pdp-unavailable"
169
+ }],
170
+ alternatives: []
171
+ }));
172
+ const decision = await applyApprovalResume(raw, permission, instance, options.store, request, compact({
173
+ type: permission.resource,
174
+ id: data !== null && typeof data === "object" && "id" in data && (typeof data.id === "string" || typeof data.id === "number") ? String(data.id) : void 0
175
+ }), adapter);
176
+ if (decision.outcome === "granted") return {
177
+ ok: true,
178
+ permdock: instance,
179
+ decision,
180
+ data
181
+ };
182
+ return {
183
+ ok: false,
184
+ response: problemFromDecision(decision, permission, instance.subject, compact({
185
+ approval: options.approval,
186
+ credentials: request.headers.has("authorization"),
187
+ disclosure: data === void 0 ? void 0 : policy.resources.get(permission.resource)?.disclosure
188
+ }))
189
+ };
190
+ };
191
+ const openapi = {
192
+ security: (permission) => ({
193
+ security: [{ oauth2: [permission.scope] }],
194
+ "x-permdock-permissions": [permission.key]
195
+ }),
196
+ securitySchemes: () => {
197
+ const scopes = {};
198
+ for (const leaf of listPermissions(policy.permissions)) scopes[leaf.scope] = leaf.meta.title ?? leaf.key;
199
+ return { oauth2: {
200
+ type: "oauth2",
201
+ flows: {},
202
+ scopes
203
+ } };
204
+ }
205
+ };
206
+ const permdockHandler = (scope) => createEvaluationsHandler(compact({
207
+ policy,
208
+ resolve: scope === void 0 ? permdock : async (request) => permdock(request, await scope(request)),
209
+ store: options.store,
210
+ adapter
211
+ }));
212
+ return {
213
+ permdock,
214
+ protect,
215
+ connection,
216
+ problem: (decision, init) => problemFor(decision, init, options.approval),
217
+ openapi,
218
+ permdockHandler
219
+ };
220
+ }
221
+ //#endregion
222
+ export { createPermDock as n, tenantScope as r, createKernel as t };
@@ -0,0 +1,326 @@
1
+ import { n as isReadonlyArray, t as compact } from "./compact-y6vfu2_f.js";
2
+ import { n as freezeDeep } from "./freeze-y1_jQL4v.js";
3
+ import { a as formerKeys, g as listPermissions } from "./permissions-DC7GROPA.js";
4
+ import { u as coveredByDelegation } from "./snapshot-DE8dE_hz.js";
5
+ import { n as sha256, t as bytesToBase64Url } from "./sha256-BO0swRXL.js";
6
+ import { t as anonymousSubject } from "./subject-C6dLxqHU.js";
7
+ import { a as ownRecord, n as idList, r as isId } from "./capability-B68OFnZx.js";
8
+ //#region src/core/revocations.ts
9
+ function isRevocationEvent(value) {
10
+ if (value === null || typeof value !== "object") return false;
11
+ const event = value;
12
+ return typeof event["principal"] === "string" && event["principal"].length > 0 && (event["kind"] === "session-revoked" || event["kind"] === "changed") && (event["session"] === void 0 || typeof event["session"] === "string") && (event["tenant"] === void 0 || typeof event["tenant"] === "string");
13
+ }
14
+ /** In-process feed; a multi-replica app bridges `revoke` to its own pub/sub. */
15
+ function memoryRevocationFeed() {
16
+ const listeners = /* @__PURE__ */ new Set();
17
+ return Object.freeze({
18
+ subscribe(listener) {
19
+ listeners.add(listener);
20
+ return () => {
21
+ listeners.delete(listener);
22
+ };
23
+ },
24
+ revoke(event) {
25
+ if (!isRevocationEvent(event)) throw new TypeError("PermDock: invalid revocation event.");
26
+ const frozen = Object.freeze({ ...event });
27
+ for (const listener of listeners) try {
28
+ listener(frozen);
29
+ } catch {}
30
+ }
31
+ });
32
+ }
33
+ //#endregion
34
+ //#region src/core/credential.ts
35
+ const MAX_ENTRIES = 64;
36
+ const MAX_NAME = 256;
37
+ function policies(policy) {
38
+ return isReadonlyArray(policy) ? policy : [policy];
39
+ }
40
+ /**
41
+ * The first rule of `policy` the credential breaks, or `undefined`. A key
42
+ * without `expiresAt` passes only when some policy sets `allowNoExpiry` and
43
+ * none sets `maxTtl`; an empty list therefore refuses it.
44
+ */
45
+ function credentialPolicyViolation(credential, policy) {
46
+ const list = policies(policy);
47
+ for (const item of list) if (item.kinds !== void 0 && !item.kinds.includes(credential.kind)) return "kind";
48
+ if (credential.expiresAt === void 0) return list.some((item) => item.allowNoExpiry === true) && list.every((item) => item.maxTtl === void 0) ? void 0 : "no-expiry";
49
+ for (const item of list) {
50
+ const max = item.maxTtl;
51
+ if (max !== void 0 && (typeof max !== "number" || !Number.isFinite(max) || max < 0 || credential.expiresAt - credential.createdAt > max)) return "ttl";
52
+ }
53
+ }
54
+ function parsePermissions(value) {
55
+ if (!Array.isArray(value) || value.length === 0 || value.length > MAX_ENTRIES) return;
56
+ const out = [];
57
+ for (const item of value) {
58
+ const entry = ownRecord(item);
59
+ if (entry === void 0 || !isId(entry["permission"])) return;
60
+ const ids = entry["ids"] === void 0 ? void 0 : idList(entry["ids"]);
61
+ if (entry["ids"] !== void 0 && ids === void 0) return;
62
+ out.push(compact({
63
+ permission: entry["permission"],
64
+ ids
65
+ }));
66
+ }
67
+ return out;
68
+ }
69
+ function isTime(value) {
70
+ return typeof value === "number" && Number.isFinite(value);
71
+ }
72
+ /**
73
+ * Validates an untrusted credential record and returns a frozen copy with
74
+ * only the v1 fields, or `undefined`. Unknown fields are dropped; a wrong
75
+ * type in a known field, a service credential without `tenant` and `roles`,
76
+ * or a user credential with either, rejects the whole record.
77
+ */
78
+ function parseCredential(input) {
79
+ const value = ownRecord(input);
80
+ if (value === void 0 || value["v"] !== 1 || !isId(value["id"])) return;
81
+ if (value["kind"] !== "user" && value["kind"] !== "service") return;
82
+ if (!isId(value["principal"]) || !isId(value["createdBy"])) return;
83
+ const permissions = parsePermissions(value["permissions"]);
84
+ if (permissions === void 0 || !isTime(value["createdAt"])) return;
85
+ if (value["expiresAt"] !== void 0 && !isTime(value["expiresAt"])) return;
86
+ if (value["name"] !== void 0 && (typeof value["name"] !== "string" || value["name"].length > MAX_NAME)) return;
87
+ let tenant;
88
+ let roles;
89
+ if (value["kind"] === "service") {
90
+ roles = idList(value["roles"]);
91
+ if (!isId(value["tenant"]) || roles === void 0) return;
92
+ tenant = value["tenant"];
93
+ } else if (value["tenant"] !== void 0 || value["roles"] !== void 0) return;
94
+ return freezeDeep(compact({
95
+ v: 1,
96
+ id: value["id"],
97
+ kind: value["kind"],
98
+ principal: value["principal"],
99
+ tenant,
100
+ roles,
101
+ permissions,
102
+ createdBy: value["createdBy"],
103
+ createdAt: value["createdAt"],
104
+ expiresAt: value["expiresAt"],
105
+ name: value["name"]
106
+ }));
107
+ }
108
+ function leafByKey(tree) {
109
+ const byKey = /* @__PURE__ */ new Map();
110
+ for (const leaf of listPermissions(tree)) {
111
+ byKey.set(leaf.key, leaf);
112
+ for (const old of formerKeys(leaf)) byKey.set(old, leaf);
113
+ }
114
+ return byKey;
115
+ }
116
+ /**
117
+ * The delegation a credential narrows its principal to: OAuth scopes for
118
+ * permissions on every instance, one RFC 9396 entry per id otherwise. A key
119
+ * the definitions no longer declare is dropped, so a credential whose every
120
+ * key is gone delegates nothing and every check is denied.
121
+ */
122
+ function credentialDelegation(credential, permissions) {
123
+ const leaves = leafByKey(permissions);
124
+ const scopes = [];
125
+ const details = [];
126
+ for (const entry of credential.permissions) {
127
+ const leaf = leaves.get(entry.permission);
128
+ if (leaf === void 0) continue;
129
+ if (entry.ids === void 0) {
130
+ scopes.push(leaf.scope);
131
+ continue;
132
+ }
133
+ for (const id of entry.ids) details.push({
134
+ type: leaf.resource,
135
+ actions: [leaf.action],
136
+ identifier: id
137
+ });
138
+ }
139
+ return compact({
140
+ scopes: scopes.length > 0 || details.length === 0 ? scopes : void 0,
141
+ authorizationDetails: details.length > 0 ? details : void 0
142
+ });
143
+ }
144
+ /**
145
+ * The subject a verified credential acts as. A `user` credential is its
146
+ * owner, passed live as `owner` (roles and memberships as of this request),
147
+ * with the credential's delegation: every check is the owner's rights
148
+ * intersected with the key's. A `service` credential is a `service`
149
+ * principal whose only membership is `roles` in `tenant`. An owner whose id
150
+ * is not the credential's `principal`, or who is not a user, is anonymous.
151
+ */
152
+ function credentialSubject(credential, options) {
153
+ const delegation = credentialDelegation(credential, options.permissions);
154
+ let principal;
155
+ if (credential.kind === "user") {
156
+ const owner = options.owner ?? {
157
+ id: credential.principal,
158
+ kind: "user"
159
+ };
160
+ if (owner.id !== credential.principal || owner.kind !== void 0 && owner.kind !== "user") return anonymousSubject();
161
+ principal = {
162
+ ...owner,
163
+ kind: "user",
164
+ credential
165
+ };
166
+ } else {
167
+ const membership = compact({
168
+ tenant: credential.tenant,
169
+ roles: credential.roles ?? [],
170
+ via: "credential"
171
+ });
172
+ principal = compact({
173
+ id: credential.principal,
174
+ kind: "service",
175
+ tenant: credential.tenant,
176
+ memberships: [membership],
177
+ credential
178
+ });
179
+ }
180
+ return freezeDeep(compact({
181
+ principal,
182
+ delegation,
183
+ context: {},
184
+ expiresAt: credential.expiresAt
185
+ }));
186
+ }
187
+ function credentialToken(credential) {
188
+ const payload = JSON.stringify({
189
+ t: "credential",
190
+ id: credential.id,
191
+ kind: credential.kind,
192
+ principal: credential.principal,
193
+ tenant: credential.tenant ?? null,
194
+ roles: credential.roles ?? null,
195
+ permissions: credential.permissions,
196
+ createdBy: credential.createdBy,
197
+ expiresAt: credential.expiresAt ?? null,
198
+ name: credential.name ?? null
199
+ });
200
+ return `pd1.${bytesToBase64Url(sha256(payload))}`;
201
+ }
202
+ function denied(reason, detail) {
203
+ return freezeDeep({
204
+ outcome: "denied",
205
+ denials: [compact({
206
+ role: null,
207
+ reason,
208
+ detail
209
+ })]
210
+ });
211
+ }
212
+ function permissionEntries(request, declared) {
213
+ if (!isReadonlyArray(request.permissions) || request.permissions.length === 0 || request.permissions.length > MAX_ENTRIES) return;
214
+ const out = [];
215
+ for (const item of request.permissions) {
216
+ const entry = permissionEntry(item);
217
+ if (entry === void 0 || declared.get(entry.leaf.key) === void 0) return;
218
+ out.push(entry);
219
+ }
220
+ return out;
221
+ }
222
+ function permissionEntry(item) {
223
+ if (!isScopedInput(item)) return { leaf: item };
224
+ const ids = idList(item.ids);
225
+ return ids === void 0 ? void 0 : {
226
+ leaf: item.permission,
227
+ ids
228
+ };
229
+ }
230
+ function isScopedInput(item) {
231
+ return "permission" in item && "ids" in item;
232
+ }
233
+ function refuse(reason, detail) {
234
+ return {
235
+ ok: false,
236
+ decision: denied(reason, detail)
237
+ };
238
+ }
239
+ function checkRequest(permdock, request, now) {
240
+ const creator = permdock.subject.principal;
241
+ if (creator === null) return refuse("anonymous");
242
+ if (creator.kind === "link" || "credential" in creator) return refuse("exceeds-creator", { creator: creator.kind === "link" ? "link" : "credential" });
243
+ const entries = permissionEntries(request, leafByKey(permdock.permissions));
244
+ if (entries === void 0 || !isId(request.id) || request.expiresAt !== void 0 && (!isTime(request.expiresAt) || request.expiresAt <= now)) return refuse("validation");
245
+ const subject = permdock.subject;
246
+ for (const entry of entries) for (const id of entry.ids ?? [void 0]) if (coveredByDelegation(entry.leaf, subject.delegation, id, subject.actor !== void 0) !== void 0) return refuse("exceeds-creator", { permission: entry.leaf.key });
247
+ const credential = parseCredential(compact({
248
+ v: 1,
249
+ id: request.id,
250
+ kind: request.kind,
251
+ principal: request.kind === "service" ? request.principal ?? request.id : creator.id,
252
+ tenant: request.kind === "service" ? request.tenant : void 0,
253
+ roles: request.kind === "service" ? request.roles : void 0,
254
+ permissions: entries.map((entry) => compact({
255
+ permission: entry.leaf.key,
256
+ ids: entry.ids
257
+ })),
258
+ createdBy: creator.id,
259
+ createdAt: now,
260
+ expiresAt: request.expiresAt === void 0 ? void 0 : Math.floor(request.expiresAt),
261
+ name: request.name
262
+ }));
263
+ if (credential === void 0) return refuse("validation");
264
+ if (credential.tenant !== void 0) {
265
+ const tenant = credential.tenant;
266
+ if (!permdock.tenants().includes(tenant)) return refuse("exceeds-creator", { tenant });
267
+ const roles = new Set(permdock.assignableRoles({ tenant }).map((role) => role.key));
268
+ for (const name of credential.roles ?? []) if (!roles.has(name)) return refuse("exceeds-creator", { role: name });
269
+ const ceiling = new Set(permdock.assignablePermissions({ tenant }).map((leaf) => leaf.key));
270
+ for (const entry of credential.permissions) if (!ceiling.has(entry.permission)) return refuse("exceeds-creator", { permission: entry.permission });
271
+ }
272
+ return {
273
+ ok: true,
274
+ credential
275
+ };
276
+ }
277
+ /**
278
+ * The tenant whose `credentials` policy governs a credential: a service
279
+ * key's own tenant, otherwise `active` (the creator's or the request's).
280
+ */
281
+ function credentialTenant(credential, active) {
282
+ return credential.tenant ?? active;
283
+ }
284
+ /**
285
+ * Decides whether the subject of `permdock` may create the credential in
286
+ * `request`. The creator must be a signed-in user or service that is not
287
+ * itself a link or a credential; a delegated creator hands out only what its
288
+ * delegation covers. A service key's tenant must be one the creator is a
289
+ * member of, its roles among the creator's `assignableRoles` there and its
290
+ * permissions within `assignablePermissions` there (`exceeds-creator`). The
291
+ * `credentials` policy of the key's tenant (a service key's own, a user
292
+ * key's the creator's active tenant) then applies (`credential-policy`; a
293
+ * settings source that throws denies with `rule: 'unavailable'`), and
294
+ * `approval` makes the result `approval-required` until `approved` carries
295
+ * its token. PermDock never stores the credential; the application does,
296
+ * after a `granted` result.
297
+ */
298
+ async function decideCredential(permdock, request, options = {}) {
299
+ const checked = checkRequest(permdock, request, options.now ?? Math.floor(Date.now() / 1e3));
300
+ if (!checked.ok) return checked.decision;
301
+ const { credential } = checked;
302
+ const tenant = credentialTenant(credential, permdock.subject.principal?.tenant);
303
+ let policy;
304
+ if (options.settings !== void 0 && tenant !== void 0) try {
305
+ policy = (await options.settings.settingsFor(tenant))?.credentials;
306
+ } catch {
307
+ return denied("credential-policy", { rule: "unavailable" });
308
+ }
309
+ const list = policy === void 0 ? [] : [policy];
310
+ const violation = credentialPolicyViolation(credential, list);
311
+ if (violation !== void 0) return denied("credential-policy", { rule: violation });
312
+ if (list.some((item) => item.approval === true)) {
313
+ const token = credentialToken(credential);
314
+ if (options.approved !== token) return freezeDeep({
315
+ outcome: "approval-required",
316
+ credential,
317
+ token
318
+ });
319
+ }
320
+ return freezeDeep({
321
+ outcome: "granted",
322
+ credential
323
+ });
324
+ }
325
+ //#endregion
326
+ export { decideCredential as a, credentialTenant as i, credentialPolicyViolation as n, parseCredential as o, credentialSubject as r, memoryRevocationFeed as s, credentialDelegation as t };