permdock 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 (344) hide show
  1. package/README.md +327 -1
  2. package/dist/a2a/index.d.ts +169 -0
  3. package/dist/a2a/index.js +232 -0
  4. package/dist/adapter-context-mlWsVGGg.js +23 -0
  5. package/dist/ai-sdk/index.d.ts +95 -0
  6. package/dist/ai-sdk/index.js +154 -0
  7. package/dist/approval-required-TzNB9oQA.js +6 -0
  8. package/dist/approvals/index.d.ts +3 -0
  9. package/dist/approvals/index.js +5 -0
  10. package/dist/approvals-DbYAuNkG.js +224 -0
  11. package/dist/approvers-DT4AVyIg.js +52 -0
  12. package/dist/arazzo-BAgw9ap6.js +70 -0
  13. package/dist/arazzo-cmvX2jDe.js +54 -0
  14. package/dist/authzen/index.d.ts +39 -0
  15. package/dist/authzen/index.js +302 -0
  16. package/dist/better-auth/index.d.ts +109 -0
  17. package/dist/better-auth/index.js +344 -0
  18. package/dist/better-supabase/index.d.ts +206 -0
  19. package/dist/better-supabase/index.js +620 -0
  20. package/dist/bind-CVy3Espv.d.ts +25 -0
  21. package/dist/bind-VnYn2HKq.js +97 -0
  22. package/dist/boundary-BM8a_P6E.js +13 -0
  23. package/dist/boundary-BmHxVH1J.d.ts +15 -0
  24. package/dist/budget-JqcRqyhK.d.ts +11 -0
  25. package/dist/budget-NbEtbJC_.js +11 -0
  26. package/dist/canonical-json-DemiK4Vp.js +26 -0
  27. package/dist/capability-4qPdO9gk.js +173 -0
  28. package/dist/capability-Dq43tT1u.d.ts +99 -0
  29. package/dist/catalog/index.d.ts +12 -0
  30. package/dist/catalog/index.js +2 -0
  31. package/dist/catalog-BjZSovXQ.js +2 -0
  32. package/dist/catalog-doc-Dsc9y7sd.js +309 -0
  33. package/dist/catalog-h2tlKFkq.js +48 -0
  34. package/dist/catalog-path-CnI0XTFK.js +12 -0
  35. package/dist/catalog-z8q6bi_r.js +55 -0
  36. package/dist/claude-agent/index.d.ts +72 -0
  37. package/dist/claude-agent/index.js +77 -0
  38. package/dist/clerk/index.d.ts +65 -0
  39. package/dist/clerk/index.js +301 -0
  40. package/dist/cli/bin.d.ts +1 -0
  41. package/dist/cli/bin.js +20 -0
  42. package/dist/cli/index.d.ts +46 -0
  43. package/dist/cli/index.js +5 -0
  44. package/dist/clients-C7zLFuWT.d.ts +12 -0
  45. package/dist/clients-DjU5ABMy.js +23 -0
  46. package/dist/cloud/index.d.ts +90 -0
  47. package/dist/cloud/index.js +404 -0
  48. package/dist/cloud-BGhHS-lY.js +50 -0
  49. package/dist/cloud-Bo3e9Ak3.js +118 -0
  50. package/dist/collect-DDDv_ESs.js +502 -0
  51. package/dist/collect-DLlujdHC.js +83 -0
  52. package/dist/collect-rG2IQ3t0.js +2 -0
  53. package/dist/commands-DWOrSQic.js +97 -0
  54. package/dist/compact-y6vfu2_f.js +19 -0
  55. package/dist/compare-pfyVnBjE.js +12 -0
  56. package/dist/compile/index.d.ts +3 -0
  57. package/dist/compile/index.js +2 -0
  58. package/dist/compile-Ba4blROR.js +613 -0
  59. package/dist/compile-CNnl6uIt.d.ts +94 -0
  60. package/dist/config-BJiM-xAm.js +157 -0
  61. package/dist/config-Bn00Z3ks.js +36 -0
  62. package/dist/config-report-Dw_JcUqT.js +44 -0
  63. package/dist/connection-CU8MQxRi.js +194 -0
  64. package/dist/context-Ttp0ekMT.js +82 -0
  65. package/dist/convex/index.d.ts +45 -0
  66. package/dist/convex/index.js +65 -0
  67. package/dist/create-BWyx3jua.d.ts +245 -0
  68. package/dist/create-CPhDL6qx.js +253 -0
  69. package/dist/credential-8P81ff4u.js +306 -0
  70. package/dist/delegation-D8pUEuce.js +103 -0
  71. package/dist/describe-B_gVZEVi.js +94 -0
  72. package/dist/describe-PdoqESvg.d.ts +36 -0
  73. package/dist/diff-B8Tunc3o.js +451 -0
  74. package/dist/diff-CzqLxZ77.js +48 -0
  75. package/dist/digest-B3kc_PgQ.d.ts +19 -0
  76. package/dist/digest-BI-6aa6d.js +27 -0
  77. package/dist/doctor-WpvG6p4k.js +1194 -0
  78. package/dist/doctor-collect-ByfYlNv1.js +664 -0
  79. package/dist/doctor-rOr-4ZfS.js +53 -0
  80. package/dist/drizzle/index.d.ts +73 -0
  81. package/dist/drizzle/index.js +160 -0
  82. package/dist/duration-xK2jGFVc.js +25 -0
  83. package/dist/elysia/index.d.ts +49 -0
  84. package/dist/elysia/index.js +59 -0
  85. package/dist/errors-CWfoNg9N.js +47 -0
  86. package/dist/errors-Cz5zn0mW.js +123 -0
  87. package/dist/errors-DAqevpNk.d.ts +125 -0
  88. package/dist/errors-DRnGZHzF.js +30 -0
  89. package/dist/evaluation-items-CfCCejQd.js +40 -0
  90. package/dist/evaluations-tz6D9A2G.js +461 -0
  91. package/dist/eve/index.d.ts +86 -0
  92. package/dist/eve/index.js +176 -0
  93. package/dist/expiry-BoBJ8Tvc.js +7 -0
  94. package/dist/express/index.d.ts +23 -0
  95. package/dist/express/index.js +78 -0
  96. package/dist/fastify/index.d.ts +33 -0
  97. package/dist/fastify/index.js +92 -0
  98. package/dist/fields-BMl1RxoX.js +26 -0
  99. package/dist/files-DWUN9PzI.js +125 -0
  100. package/dist/fixtures-ht28Cplr.js +67 -0
  101. package/dist/freeze-CrU8nQeX.js +60 -0
  102. package/dist/from-snapshot-C3sHpZNS.js +569 -0
  103. package/dist/generate-CH7ThJ14.js +173 -0
  104. package/dist/grantee-Cv5Sogfv.js +602 -0
  105. package/dist/graph-sql-B-dsAT6j.d.ts +29 -0
  106. package/dist/headers-BZSDieNT.js +6 -0
  107. package/dist/headers-Cf-zWvsO.d.ts +6 -0
  108. package/dist/helpers-H_KARDVC.js +421 -0
  109. package/dist/hono/index.d.ts +48 -0
  110. package/dist/hono/index.js +99 -0
  111. package/dist/hosted-DJQw46hn.js +266 -0
  112. package/dist/http-BIhmLfCc.js +95 -0
  113. package/dist/http-DPuDaChb.d.ts +13 -0
  114. package/dist/http-SO7qGttf.js +44 -0
  115. package/dist/ids-DC4V4CFu.js +18 -0
  116. package/dist/index-A0YNL8jZ.d.ts +177 -0
  117. package/dist/index-CtE07CBF.d.ts +6 -0
  118. package/dist/index-D3vbkoSI.d.ts +483 -0
  119. package/dist/index-D6_cSa1z.d.ts +201 -0
  120. package/dist/index.d.ts +16 -0
  121. package/dist/index.js +26 -0
  122. package/dist/instance-options-BK_rNOSC.d.ts +11 -0
  123. package/dist/instance-options-Dhhcnm3y.js +22 -0
  124. package/dist/json-schema-BsAflUGW.js +106 -0
  125. package/dist/jwt/index.d.ts +91 -0
  126. package/dist/jwt/index.js +590 -0
  127. package/dist/kernel-GSQnMz3O.js +208 -0
  128. package/dist/kysely/index.d.ts +78 -0
  129. package/dist/kysely/index.js +129 -0
  130. package/dist/live-options-H2eG8dfJ.js +60 -0
  131. package/dist/load-DhWEB9P1.js +75 -0
  132. package/dist/load-DwJUafYN.js +2 -0
  133. package/dist/load-jose-BL6LH4bL.js +11 -0
  134. package/dist/lru-8q4WZjBV.js +28 -0
  135. package/dist/manifest-iaoBXHKc.js +783 -0
  136. package/dist/manifest-uDS9y5de.d.ts +206 -0
  137. package/dist/map-AcxK9o_D.js +147 -0
  138. package/dist/map-claims-Z4QZOiFF.js +369 -0
  139. package/dist/map-error-pgUWNNtG.js +23 -0
  140. package/dist/markers-B0hYLvMD.js +60 -0
  141. package/dist/may-use-DndQ5tQ-.js +77 -0
  142. package/dist/mcp/index.d.ts +159 -0
  143. package/dist/mcp/index.js +603 -0
  144. package/dist/nest/index.d.ts +75 -0
  145. package/dist/nest/index.js +261 -0
  146. package/dist/next/client.d.ts +23 -0
  147. package/dist/next/client.js +33 -0
  148. package/dist/next/index.d.ts +93 -0
  149. package/dist/next/index.js +180 -0
  150. package/dist/next/plugin.d.ts +14 -0
  151. package/dist/next/plugin.js +33 -0
  152. package/dist/node/index.d.ts +24 -0
  153. package/dist/node/index.js +34 -0
  154. package/dist/openai/index.d.ts +62 -0
  155. package/dist/openai/index.js +92 -0
  156. package/dist/openapi/index.d.ts +176 -0
  157. package/dist/openapi/index.js +3 -0
  158. package/dist/openapi-Bbg4wGVL.js +164 -0
  159. package/dist/openapi-BqRBvAng.js +538 -0
  160. package/dist/openapi-CqqEbHsL.js +250 -0
  161. package/dist/openapi-import-cmwetbzw.js +5959 -0
  162. package/dist/openapi-schema--ARjyfQr.js +6902 -0
  163. package/dist/orpc/index.d.ts +51 -0
  164. package/dist/orpc/index.js +145 -0
  165. package/dist/otel/index.d.ts +13 -0
  166. package/dist/otel/index.js +202 -0
  167. package/dist/package-root-zGkxO3oN.js +30 -0
  168. package/dist/parse-BuyjxhZV.js +53 -0
  169. package/dist/parse-local-manifest-BkGQNzAh.d.ts +10 -0
  170. package/dist/parse-local-manifest-BrMozJCo.js +36 -0
  171. package/dist/pdp/index.d.ts +22 -0
  172. package/dist/pdp/index.js +682 -0
  173. package/dist/peer-BOr_kJE1.js +31 -0
  174. package/dist/permdock-CzqXjCpU.js +3471 -0
  175. package/dist/permissions-CDgvKG5L.d.ts +52 -0
  176. package/dist/permissions-CpZrivYv.js +142 -0
  177. package/dist/permissions-DVoF6dMt.js +662 -0
  178. package/dist/permissions-DttnqqxC.d.ts +214 -0
  179. package/dist/pins-8ILTftC9.js +12 -0
  180. package/dist/policy-CFZAr_Al.d.ts +2252 -0
  181. package/dist/policy-D8UFyERw.d.ts +20 -0
  182. package/dist/policy-xyWg7QdR.js +1122 -0
  183. package/dist/powersync-A8x_Yyvh.js +2 -0
  184. package/dist/powersync-C7kLglqX.js +540 -0
  185. package/dist/powersync-yW1UUFzp.js +62 -0
  186. package/dist/prisma/index.d.ts +136 -0
  187. package/dist/prisma/index.js +455 -0
  188. package/dist/problem-B43ztKIm.js +191 -0
  189. package/dist/problem-details-CkL50EEf.d.ts +7 -0
  190. package/dist/problem-details-_AMOYz-w.js +144 -0
  191. package/dist/prompt-CXYhLfsS.js +32 -0
  192. package/dist/protected-CNsMzrVd.d.ts +27 -0
  193. package/dist/protected-Cs6kTaHo.js +100 -0
  194. package/dist/protected-bZs6rbT1.d.ts +40 -0
  195. package/dist/provider-Cjr62YMV.d.ts +6 -0
  196. package/dist/provider-DLzpb2Xz.js +52 -0
  197. package/dist/provider-store-DNyC1y48.js +43 -0
  198. package/dist/react/index.d.ts +8 -0
  199. package/dist/react/index.js +7 -0
  200. package/dist/react/provider-client.d.ts +2 -0
  201. package/dist/react/provider-client.js +3 -0
  202. package/dist/react-native/index.d.ts +198 -0
  203. package/dist/react-native/index.js +696 -0
  204. package/dist/refs-KYb4ntaz.js +91 -0
  205. package/dist/relations-cjOL01hZ.js +505 -0
  206. package/dist/replay-BsOyTrdV.js +28 -0
  207. package/dist/replay-sqBGMnNs.d.ts +5 -0
  208. package/dist/resource-ref-CaS9yVPi.js +20 -0
  209. package/dist/revocations-Bhr0aMIC.js +27 -0
  210. package/dist/revocations-Cy06JNx2.d.ts +21 -0
  211. package/dist/rls-BMNydpHk.js +2521 -0
  212. package/dist/rls-CEvs64Kj.js +238 -0
  213. package/dist/rls-fields-BMasREhR.js +3502 -0
  214. package/dist/rls-graph-pc9fuXYm.js +435 -0
  215. package/dist/rls-import-D8F7j35Q.js +943 -0
  216. package/dist/rls-migrate-7wikfrVI.js +367 -0
  217. package/dist/rls-ownership-B5Lkq62W.js +843 -0
  218. package/dist/rls-shared-aOQ4hGTO.js +493 -0
  219. package/dist/rls-verify-D8B7dOTh.js +745 -0
  220. package/dist/row-check-Dt35czLy.d.ts +40 -0
  221. package/dist/rpc-DOK54_CS.js +89 -0
  222. package/dist/run-YXCJDNYk.js +174 -0
  223. package/dist/runtime-CB8gQFvS.js +11 -0
  224. package/dist/saas-Bj_FFkjN.js +1203 -0
  225. package/dist/schema-D3MnDMxa.js +300 -0
  226. package/dist/scim/index.d.ts +2 -0
  227. package/dist/scim/index.js +2 -0
  228. package/dist/scim-BFGBBAqR.js +1445 -0
  229. package/dist/scopes-CVdPrWN-.js +239 -0
  230. package/dist/server/index.d.ts +134 -0
  231. package/dist/server/index.js +11 -0
  232. package/dist/server-DlZ28Oz5.js +268 -0
  233. package/dist/sha256-BO0swRXL.js +150 -0
  234. package/dist/shared-DRu8VFVM.js +123 -0
  235. package/dist/sink-Bd9PSyfq.js +141 -0
  236. package/dist/sink-Gs6TTVa-.d.ts +104 -0
  237. package/dist/skills-Biq5uup3.js +192 -0
  238. package/dist/skills-JaymNCdK.js +56 -0
  239. package/dist/snapshot-Enxd0n-s.js +975 -0
  240. package/dist/snapshot-cache-D6jLelln.js +44 -0
  241. package/dist/snapshot-cache-DwQH8ufx.d.ts +45 -0
  242. package/dist/solid/index.d.ts +93 -0
  243. package/dist/solid/index.js +188 -0
  244. package/dist/sources-B0UvrJ21.js +534 -0
  245. package/dist/sources-BcJgw0lt.d.ts +192 -0
  246. package/dist/sql-xdg5f4Fi.js +27 -0
  247. package/dist/src-CSbUiozF.js +568 -0
  248. package/dist/ssf/index.d.ts +4 -0
  249. package/dist/ssf/index.js +596 -0
  250. package/dist/store-DMAWwAJV.js +371 -0
  251. package/dist/store-D_pjn91-.d.ts +36 -0
  252. package/dist/store-options-yO0V6gRn.js +716 -0
  253. package/dist/stores-4_sqiOA1.js +87 -0
  254. package/dist/stores-DVR5NHLE.d.ts +52 -0
  255. package/dist/stream-DDpvynSB.js +66 -0
  256. package/dist/stream-DlvG2hs-.d.ts +12 -0
  257. package/dist/style-CTm1AXDT.js +22 -0
  258. package/dist/subject-C6dLxqHU.js +24 -0
  259. package/dist/subject-settings-BwBmCdTR.js +128 -0
  260. package/dist/supabase/index.d.ts +183 -0
  261. package/dist/supabase/index.js +5 -0
  262. package/dist/supabase/middleware.d.ts +82 -0
  263. package/dist/supabase/middleware.js +102 -0
  264. package/dist/supabase-CwafwxxF.js +83 -0
  265. package/dist/supabase-DTBaC20O.js +774 -0
  266. package/dist/supabase-config-Bs44dare.js +472 -0
  267. package/dist/supabase-hook-BuxLQLpU.js +1814 -0
  268. package/dist/supabase-hook-D5qVd_D8.js +2 -0
  269. package/dist/supautils-DYZnzRWV.js +91 -0
  270. package/dist/svelte/PermissionBoundary.svelte +37 -0
  271. package/dist/svelte/Protected.svelte +40 -0
  272. package/dist/svelte/index.d.ts +13 -0
  273. package/dist/svelte/index.js +107 -0
  274. package/dist/svelte/runtime.d.ts +7 -0
  275. package/dist/svelte/runtime.js +4 -0
  276. package/dist/svelte/source.d.ts +13 -0
  277. package/dist/svelte/source.js +11 -0
  278. package/dist/terminal/index.d.ts +163 -0
  279. package/dist/terminal/index.js +833 -0
  280. package/dist/testing/index.d.ts +745 -0
  281. package/dist/testing/index.js +3672 -0
  282. package/dist/testing/saas/index.d.ts +194 -0
  283. package/dist/testing/saas/index.js +3 -0
  284. package/dist/testing/saas/permissions.d.ts +2 -0
  285. package/dist/testing/saas/permissions.js +2 -0
  286. package/dist/text-diff-BdkkYSbi.js +15 -0
  287. package/dist/thenable-okc2xDsj.js +10 -0
  288. package/dist/timeout-D51niuQP.js +8 -0
  289. package/dist/token-CIWxJOCh.js +50 -0
  290. package/dist/trpc/index.d.ts +61 -0
  291. package/dist/trpc/index.js +122 -0
  292. package/dist/types-9AWO9EGt.d.ts +197 -0
  293. package/dist/types-BPxgszlT.d.ts +550 -0
  294. package/dist/types-BVyImy5I.d.ts +120 -0
  295. package/dist/types-Bvc4oWT6.d.ts +9 -0
  296. package/dist/types-C3s9xVJG.d.ts +48 -0
  297. package/dist/types-Dnemwd77.d.ts +183 -0
  298. package/dist/types-kxznc7cn.d.ts +52 -0
  299. package/dist/types-vKyAMtcX.d.ts +157 -0
  300. package/dist/types-vNSDF7Dq.d.ts +66 -0
  301. package/dist/types-yF5LmQVD.d.ts +306 -0
  302. package/dist/unplugin/index.d.ts +7 -0
  303. package/dist/unplugin/index.js +31 -0
  304. package/dist/usage-D07N9QJ3.js +42 -0
  305. package/dist/usage-D82l1CwK.js +2 -0
  306. package/dist/usage-DG1oeCca.js +693 -0
  307. package/dist/validation-error-CnjZ4t92.js +33 -0
  308. package/dist/validation-error-CtF23SrC.d.ts +26 -0
  309. package/dist/validity-uOp8UpYn.js +245 -0
  310. package/dist/verifier-BxBo6I44.js +466 -0
  311. package/dist/version-BvacVTZR.js +17 -0
  312. package/dist/views-Soe7bGSC.js +95 -0
  313. package/dist/vocabulary-DA8a8zif.d.ts +56 -0
  314. package/dist/vue/index.d.ts +79 -0
  315. package/dist/vue/index.js +196 -0
  316. package/dist/watch-Etoa_Mvr.js +2 -0
  317. package/dist/watch-UihESpsJ.js +128 -0
  318. package/dist/webmcp/index.d.ts +75 -0
  319. package/dist/webmcp/index.js +307 -0
  320. package/package.json +450 -5
  321. package/rulesets/permdock.yaml +29 -0
  322. package/schemas/approval-request-v1.json +175 -0
  323. package/schemas/catalog-v1.json +535 -0
  324. package/schemas/openapi/oas-3.1.json +1298 -0
  325. package/schemas/openapi/oas-3.2.json +1516 -0
  326. package/schemas/openapi/overlay-1.1.json +79 -0
  327. package/schemas/supabase-claims-v1.json +144 -0
  328. package/schemas/supabase-manifest-v1.json +361 -0
  329. package/skills/permdock/SKILL.md +66 -0
  330. package/skills/permdock-agents/SKILL.md +77 -0
  331. package/skills/permdock-agents/references/runtimes.md +213 -0
  332. package/skills/permdock-approvals/SKILL.md +80 -0
  333. package/skills/permdock-approvals/references/stores-and-resume.md +94 -0
  334. package/skills/permdock-audit/SKILL.md +67 -0
  335. package/skills/permdock-credentials/SKILL.md +55 -0
  336. package/skills/permdock-credentials/references/tokens-keys-links.md +132 -0
  337. package/skills/permdock-data/SKILL.md +57 -0
  338. package/skills/permdock-data/references/queries-and-rls.md +62 -0
  339. package/skills/permdock-data/references/relationships.md +67 -0
  340. package/skills/permdock-tenancy/SKILL.md +80 -0
  341. package/skills/permdock-tenancy/references/ownership-and-custom-roles.md +89 -0
  342. package/skills/permdock-wire/SKILL.md +116 -0
  343. package/skills/permdock-wire/references/adapters.md +492 -0
  344. package/skills/permdock-wire/references/policy-options.md +45 -0
@@ -0,0 +1,306 @@
1
+ import { n as isReadonlyArray, t as compact } from "./compact-y6vfu2_f.js";
2
+ import { n as freezeDeep } from "./freeze-CrU8nQeX.js";
3
+ import { _ as listPermissions, a as formerKeys } from "./permissions-DVoF6dMt.js";
4
+ import { n as sha256, t as bytesToBase64Url } from "./sha256-BO0swRXL.js";
5
+ import { t as coveredByDelegation } from "./delegation-D8pUEuce.js";
6
+ import { t as anonymousSubject } from "./subject-C6dLxqHU.js";
7
+ import { a as ownRecord, n as idList, r as isId } from "./capability-4qPdO9gk.js";
8
+ //#region src/core/credential.ts
9
+ const MAX_NAME = 256;
10
+ function policies(policy) {
11
+ return isReadonlyArray(policy) ? policy : [policy];
12
+ }
13
+ /**
14
+ * The first rule of `policy` the credential breaks, or `undefined`. A key
15
+ * without `expiresAt` passes only when some policy sets `allowNoExpiry` and
16
+ * none sets `maxTtl`; an empty list therefore refuses it.
17
+ */
18
+ function credentialPolicyViolation(credential, policy) {
19
+ const list = policies(policy);
20
+ for (const item of list) if (item.kinds !== void 0 && !item.kinds.includes(credential.kind)) return "kind";
21
+ if (credential.expiresAt === void 0) return list.some((item) => item.allowNoExpiry === true) && list.every((item) => item.maxTtl === void 0) ? void 0 : "no-expiry";
22
+ for (const item of list) {
23
+ const max = item.maxTtl;
24
+ if (max !== void 0 && (typeof max !== "number" || !Number.isFinite(max) || max < 0 || credential.expiresAt - credential.createdAt > max)) return "ttl";
25
+ }
26
+ }
27
+ function parsePermissions(value) {
28
+ if (!Array.isArray(value) || value.length === 0) return;
29
+ const out = [];
30
+ for (const item of value) {
31
+ const entry = ownRecord(item);
32
+ if (entry === void 0 || !isId(entry["permission"])) return;
33
+ const ids = entry["ids"] === void 0 ? void 0 : idList(entry["ids"]);
34
+ if (entry["ids"] !== void 0 && ids === void 0) return;
35
+ out.push(compact({
36
+ permission: entry["permission"],
37
+ ids
38
+ }));
39
+ }
40
+ return out;
41
+ }
42
+ function isTime(value) {
43
+ return typeof value === "number" && Number.isFinite(value);
44
+ }
45
+ /**
46
+ * Validates an untrusted credential record and returns a frozen copy with
47
+ * only the v1 fields, or `undefined`. Unknown fields are dropped; a wrong
48
+ * type in a known field, a service credential without `tenant` and `roles`,
49
+ * or a user credential with `roles`, rejects the whole record.
50
+ */
51
+ function parseCredential(input) {
52
+ const value = ownRecord(input);
53
+ if (value === void 0 || value["v"] !== 1 || !isId(value["id"])) return;
54
+ if (value["kind"] !== "user" && value["kind"] !== "service") return;
55
+ if (!isId(value["principal"]) || !isId(value["createdBy"])) return;
56
+ const permissions = parsePermissions(value["permissions"]);
57
+ if (permissions === void 0 || !isTime(value["createdAt"])) return;
58
+ if (value["expiresAt"] !== void 0 && !isTime(value["expiresAt"])) return;
59
+ if (value["name"] !== void 0 && (typeof value["name"] !== "string" || value["name"].length > MAX_NAME)) return;
60
+ let tenant;
61
+ let roles;
62
+ if (value["kind"] === "service") {
63
+ roles = idList(value["roles"]);
64
+ if (!isId(value["tenant"]) || roles === void 0) return;
65
+ tenant = value["tenant"];
66
+ } else if (value["roles"] !== void 0 || value["tenant"] !== void 0 && !isId(value["tenant"])) return;
67
+ else tenant = value["tenant"];
68
+ return freezeDeep(compact({
69
+ v: 1,
70
+ id: value["id"],
71
+ kind: value["kind"],
72
+ principal: value["principal"],
73
+ tenant,
74
+ roles,
75
+ permissions,
76
+ createdBy: value["createdBy"],
77
+ createdAt: value["createdAt"],
78
+ expiresAt: value["expiresAt"],
79
+ name: value["name"]
80
+ }));
81
+ }
82
+ function leafByKey(tree) {
83
+ const byKey = /* @__PURE__ */ new Map();
84
+ for (const leaf of listPermissions(tree)) {
85
+ byKey.set(leaf.key, leaf);
86
+ for (const old of formerKeys(leaf)) byKey.set(old, leaf);
87
+ }
88
+ return byKey;
89
+ }
90
+ /**
91
+ * The delegation a credential narrows its principal to: OAuth scopes for
92
+ * permissions on every instance, one RFC 9396 entry per id otherwise. A key
93
+ * the definitions no longer declare is dropped, so a credential whose every
94
+ * key is gone delegates nothing and every check is denied.
95
+ */
96
+ function credentialDelegation(credential, permissions) {
97
+ const leaves = leafByKey(permissions);
98
+ const scopes = [];
99
+ const details = [];
100
+ for (const entry of credential.permissions) {
101
+ const leaf = leaves.get(entry.permission);
102
+ if (leaf === void 0) continue;
103
+ if (entry.ids === void 0) {
104
+ scopes.push(leaf.scope);
105
+ continue;
106
+ }
107
+ for (const id of entry.ids) details.push({
108
+ type: leaf.resource,
109
+ actions: [leaf.action],
110
+ identifier: id
111
+ });
112
+ }
113
+ return compact({
114
+ scopes: scopes.length > 0 || details.length === 0 ? scopes : void 0,
115
+ authorizationDetails: details.length > 0 ? details : void 0
116
+ });
117
+ }
118
+ /**
119
+ * The subject a verified credential acts as. A `user` credential is its
120
+ * owner, passed live as `owner` (roles and memberships as of this request),
121
+ * with the credential's delegation: every check is the owner's rights
122
+ * intersected with the key's. One that names a `tenant` makes it the active
123
+ * tenant, and `createPermDock` then keeps only the owner's memberships
124
+ * inside it and no global role. A `service` credential is a `service`
125
+ * principal whose only membership is `roles` in `tenant`. An owner whose id
126
+ * is not the credential's `principal`, or who is not a user, is anonymous.
127
+ */
128
+ function credentialSubject(credential, options) {
129
+ const delegation = credentialDelegation(credential, options.permissions);
130
+ let principal;
131
+ if (credential.kind === "user") {
132
+ const owner = options.owner ?? {
133
+ id: credential.principal,
134
+ kind: "user"
135
+ };
136
+ if (owner.id !== credential.principal || owner.kind !== void 0 && owner.kind !== "user") return anonymousSubject();
137
+ principal = compact({
138
+ ...owner,
139
+ kind: "user",
140
+ tenant: credential.tenant ?? owner.tenant,
141
+ credential
142
+ });
143
+ } else {
144
+ const membership = compact({
145
+ tenant: credential.tenant,
146
+ roles: credential.roles ?? [],
147
+ via: "credential"
148
+ });
149
+ principal = compact({
150
+ id: credential.principal,
151
+ kind: "service",
152
+ tenant: credential.tenant,
153
+ memberships: [membership],
154
+ credential
155
+ });
156
+ }
157
+ return freezeDeep(compact({
158
+ principal,
159
+ delegation,
160
+ context: {},
161
+ expiresAt: credential.expiresAt
162
+ }));
163
+ }
164
+ function credentialToken(credential) {
165
+ const payload = JSON.stringify({
166
+ t: "credential",
167
+ id: credential.id,
168
+ kind: credential.kind,
169
+ principal: credential.principal,
170
+ tenant: credential.tenant ?? null,
171
+ roles: credential.roles ?? null,
172
+ permissions: credential.permissions,
173
+ createdBy: credential.createdBy,
174
+ expiresAt: credential.expiresAt ?? null,
175
+ name: credential.name ?? null
176
+ });
177
+ return `pd1.${bytesToBase64Url(sha256(payload))}`;
178
+ }
179
+ function denied(reason, detail) {
180
+ return freezeDeep({
181
+ outcome: "denied",
182
+ denials: [compact({
183
+ role: null,
184
+ reason,
185
+ detail
186
+ })]
187
+ });
188
+ }
189
+ function permissionEntries(request, declared) {
190
+ if (!isReadonlyArray(request.permissions) || request.permissions.length === 0) return;
191
+ const out = [];
192
+ for (const item of request.permissions) {
193
+ const entry = permissionEntry(item);
194
+ if (entry === void 0 || declared.get(entry.leaf.key) === void 0) return;
195
+ out.push(entry);
196
+ }
197
+ return out;
198
+ }
199
+ function permissionEntry(item) {
200
+ if (!isScopedInput(item)) return { leaf: item };
201
+ const ids = idList(item.ids);
202
+ return ids === void 0 ? void 0 : {
203
+ leaf: item.permission,
204
+ ids
205
+ };
206
+ }
207
+ function isScopedInput(item) {
208
+ return "permission" in item && "ids" in item;
209
+ }
210
+ function refuse(reason, detail) {
211
+ return {
212
+ ok: false,
213
+ decision: denied(reason, detail)
214
+ };
215
+ }
216
+ function checkRequest(permdock, request, now) {
217
+ const creator = permdock.subject.principal;
218
+ if (creator === null) return refuse("anonymous");
219
+ if (creator.kind === "link" || "credential" in creator) return refuse("exceeds-creator", { creator: creator.kind === "link" ? "link" : "credential" });
220
+ const entries = permissionEntries(request, leafByKey(permdock.permissions));
221
+ if (entries === void 0 || !isId(request.id) || request.expiresAt !== void 0 && (!isTime(request.expiresAt) || request.expiresAt <= now)) return refuse("validation");
222
+ const subject = permdock.subject;
223
+ 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 });
224
+ const credential = parseCredential(compact({
225
+ v: 1,
226
+ id: request.id,
227
+ kind: request.kind,
228
+ principal: request.kind === "service" ? request.principal ?? request.id : creator.id,
229
+ tenant: request.tenant,
230
+ roles: request.kind === "service" ? request.roles : void 0,
231
+ permissions: entries.map((entry) => compact({
232
+ permission: entry.leaf.key,
233
+ ids: entry.ids
234
+ })),
235
+ createdBy: creator.id,
236
+ createdAt: now,
237
+ expiresAt: request.expiresAt === void 0 ? void 0 : Math.floor(request.expiresAt),
238
+ name: request.name
239
+ }));
240
+ if (credential === void 0) return refuse("validation");
241
+ if (credential.tenant !== void 0) {
242
+ const tenant = credential.tenant;
243
+ if (!permdock.tenants().includes(tenant)) return refuse("exceeds-creator", { tenant });
244
+ }
245
+ if (credential.kind === "service" && credential.tenant !== void 0) {
246
+ const tenant = credential.tenant;
247
+ const roles = new Set(permdock.assignableRoles({ tenant }).map((role) => role.key));
248
+ for (const name of credential.roles ?? []) if (!roles.has(name)) return refuse("exceeds-creator", { role: name });
249
+ const ceiling = new Set(permdock.assignablePermissions({ tenant }).map((leaf) => leaf.key));
250
+ for (const entry of credential.permissions) if (!ceiling.has(entry.permission)) return refuse("exceeds-creator", { permission: entry.permission });
251
+ }
252
+ return {
253
+ ok: true,
254
+ credential
255
+ };
256
+ }
257
+ /**
258
+ * The tenant whose `credentials` policy governs a credential: the key's own
259
+ * tenant, otherwise `active` (the creator's or the request's).
260
+ */
261
+ function credentialTenant(credential, active) {
262
+ return credential.tenant ?? active;
263
+ }
264
+ /**
265
+ * Decides whether the subject of `permdock` may create the credential in
266
+ * `request`. The creator must be a signed-in user or service that is not
267
+ * itself a link or a credential; a delegated creator hands out only what its
268
+ * delegation covers. A key's tenant must be one the creator is a member of;
269
+ * a service key's roles among the creator's `assignableRoles` there and its
270
+ * permissions within `assignablePermissions` there (`exceeds-creator`). The
271
+ * `credentials` policy of the key's tenant (its own, or for a user key
272
+ * without one the creator's active tenant) then applies (`credential-policy`; a
273
+ * settings source that throws denies with `rule: 'unavailable'`), and
274
+ * `approval` makes the result `approval-required` until `approved` carries
275
+ * its token. PermDock never stores the credential; the application does,
276
+ * after a `granted` result.
277
+ */
278
+ async function decideCredential(permdock, request, options = {}) {
279
+ const checked = checkRequest(permdock, request, options.now ?? Math.floor(Date.now() / 1e3));
280
+ if (!checked.ok) return checked.decision;
281
+ const { credential } = checked;
282
+ const tenant = credentialTenant(credential, permdock.subject.principal?.tenant);
283
+ let policy;
284
+ if (options.settings !== void 0 && tenant !== void 0) try {
285
+ policy = (await options.settings.settingsFor(tenant))?.credentials;
286
+ } catch {
287
+ return denied("credential-policy", { rule: "unavailable" });
288
+ }
289
+ const list = policy === void 0 ? [] : [policy];
290
+ const violation = credentialPolicyViolation(credential, list);
291
+ if (violation !== void 0) return denied("credential-policy", { rule: violation });
292
+ if (list.some((item) => item.approval === true)) {
293
+ const token = credentialToken(credential);
294
+ if (options.approved !== token) return freezeDeep({
295
+ outcome: "approval-required",
296
+ credential,
297
+ token
298
+ });
299
+ }
300
+ return freezeDeep({
301
+ outcome: "granted",
302
+ credential
303
+ });
304
+ }
305
+ //#endregion
306
+ export { decideCredential as a, credentialTenant as i, credentialPolicyViolation as n, parseCredential as o, credentialSubject as r, credentialDelegation as t };
@@ -0,0 +1,103 @@
1
+ import { i as findPermission, o as formerScopes, t as annotationsFor } from "./permissions-DVoF6dMt.js";
2
+ import { d as matchGrantee, s as flattenGrantee } from "./grantee-Cv5Sogfv.js";
3
+ import { t as isActive } from "./validity-uOp8UpYn.js";
4
+ //#region src/core/delegation.ts
5
+ /** The permission's scope and any scope it was renamed from: tokens issued before a rename keep working. */
6
+ function scopeNames(permission) {
7
+ return [permission.scope, ...formerScopes(permission)];
8
+ }
9
+ /**
10
+ * Whether a delegated caller may use a permission its principal holds, through
11
+ * OAuth `scopes`, RFC 9396 `authorizationDetails` or GNAP `access`.
12
+ * `undefined` means covered; otherwise the denial reason `decide` would add.
13
+ */
14
+ function coveredByDelegation(permission, delegation, resourceId, hasActor = false) {
15
+ const unscoped = hasActor ? "no-delegation" : void 0;
16
+ if (delegation === void 0) return unscoped;
17
+ const hasScopes = delegation.scopes !== void 0;
18
+ const hasDetails = delegation.authorizationDetails !== void 0;
19
+ const hasAccess = delegation.access !== void 0;
20
+ if (!hasScopes && !hasDetails && !hasAccess) return unscoped;
21
+ const emptyScopes = hasScopes && (delegation.scopes?.length ?? 0) === 0;
22
+ const emptyAccess = hasAccess && (delegation.access?.length ?? 0) === 0;
23
+ if (emptyScopes && !hasDetails && !hasAccess) return "no-delegation";
24
+ if (emptyAccess && !hasScopes && !hasDetails) return "no-delegation";
25
+ if (emptyScopes && emptyAccess && !hasDetails) return "no-delegation";
26
+ const scopes = scopeNames(permission);
27
+ const scopeOk = delegation.scopes?.some((scope) => scopes.includes(scope)) ?? false;
28
+ const detailOk = delegation.authorizationDetails?.some((detail) => {
29
+ if (detail.type !== permission.resource) return false;
30
+ const identifier = detail["identifier"];
31
+ if (identifier !== void 0 && (typeof identifier !== "string" || identifier !== resourceId)) return false;
32
+ const actions = detail.actions;
33
+ if (actions === void 0) return true;
34
+ return Array.isArray(actions) && actions.includes(permission.action);
35
+ }) ?? false;
36
+ const accessOk = accessCovers(permission, delegation.access, resourceId);
37
+ if (scopeOk || detailOk || accessOk) return;
38
+ return "not-delegated";
39
+ }
40
+ function coversRequirements(tree, requires, delegation, resourceId, hasActor = false) {
41
+ return (requires ?? []).every((key) => {
42
+ const leaf = findPermission(tree, key);
43
+ return leaf !== void 0 && coveredByDelegation(leaf, delegation, resourceId, hasActor) === void 0;
44
+ });
45
+ }
46
+ function requiresStandIn(grant) {
47
+ return (grant.requires ?? []).length > 0 && annotationsFor(grant.permission).readOnlyHint && !flattenGrantee(grant.to).some((item) => item.kind === "role");
48
+ }
49
+ function accessCovers(permission, access, resourceId) {
50
+ if (access === void 0) return false;
51
+ return access.some((entry) => {
52
+ if (typeof entry === "string") return scopeNames(permission).includes(entry);
53
+ if (entry === null || typeof entry !== "object") return false;
54
+ const type = entry["type"];
55
+ if (typeof type !== "string" || !typeMatches(type, permission.resource)) return false;
56
+ const actions = entry["actions"];
57
+ if (actions !== void 0 && (!Array.isArray(actions) || !actions.includes(permission.action))) return false;
58
+ const identifier = entry["identifier"];
59
+ if (identifier !== void 0 && (typeof identifier !== "string" || identifier !== resourceId)) return false;
60
+ return true;
61
+ });
62
+ }
63
+ function typeMatches(type, resource) {
64
+ if (type === resource) return true;
65
+ return type.endsWith(`/${resource}`);
66
+ }
67
+ /**
68
+ * Whether the subject's principal is a `from` of the delegation: every item
69
+ * matches, with roles checked against the roles the principal holds here
70
+ * (`matchGrantee` leaves role holding to the caller) and nothing that needs a
71
+ * row.
72
+ */
73
+ function handsOver(delegation, subject, heldRoles, now) {
74
+ const items = flattenGrantee(delegation.from);
75
+ if (items.length === 0 || subject.principal === null) return false;
76
+ return items.every((item) => {
77
+ if (item.kind === "role") return heldRoles.has(item.role);
78
+ if (item.kind === "relation") return false;
79
+ const match = matchGrantee(item, subject, now, void 0);
80
+ return match.matched && match.where === void 0;
81
+ });
82
+ }
83
+ /**
84
+ * The permission keys the policy's delegations let `subject.actor` use for
85
+ * `subject.principal` right now: the union over every active delegation whose
86
+ * `to` matches the actor and whose `from` the principal holds. `undefined`
87
+ * when none applies, so the call falls back to the token delegation alone.
88
+ * An actor with `readOnly: true` gets only each delegation's read-only keys.
89
+ * Attenuation only: a key here still needs a matching allow and no deny.
90
+ */
91
+ function delegatedPermissions(delegations, subject, heldRoles, now) {
92
+ const actor = subject.actor;
93
+ if (actor === void 0 || delegations === void 0) return;
94
+ let keys;
95
+ for (const delegation of delegations) {
96
+ if (delegation.to.kind !== actor.kind || delegation.to.id !== void 0 && delegation.to.id !== actor.id || delegation.to.client !== void 0 && delegation.to.client !== actor.client || !isActive(delegation.validity, now) || !handsOver(delegation, subject, heldRoles, now)) continue;
97
+ keys ??= /* @__PURE__ */ new Set();
98
+ for (const key of actor.readOnly === true ? delegation.readOnly : delegation.permissions) keys.add(key);
99
+ }
100
+ return keys;
101
+ }
102
+ //#endregion
103
+ export { requiresStandIn as i, coversRequirements as n, delegatedPermissions as r, coveredByDelegation as t };
@@ -0,0 +1,94 @@
1
+ import { i as flattenApprovers } from "./approvers-DT4AVyIg.js";
2
+ import { r as requiredPlans } from "./problem-details-_AMOYz-w.js";
3
+ //#region src/core/describe.ts
4
+ const TENANT_REASONS = /* @__PURE__ */ new Set([
5
+ "tenant-mismatch",
6
+ "no-membership",
7
+ "expired-membership",
8
+ "scope"
9
+ ]);
10
+ const DELEGATION_REASONS = /* @__PURE__ */ new Set(["not-delegated", "no-delegation"]);
11
+ function labelGrantee(grantee) {
12
+ switch (grantee.kind) {
13
+ case "role": return grantee.role;
14
+ case "plan": return grantee.plan;
15
+ case "actor": return grantee.actor;
16
+ case "authenticated": return "an authenticated user";
17
+ case "anyone": return "anyone";
18
+ case "relation": return grantee.relation;
19
+ case "inherit": return grantee.permission;
20
+ case "assurance": {
21
+ const parts = [];
22
+ if (grantee.acr !== void 0 && grantee.acr.length > 0) parts.push(`acr ${grantee.acr.join("/")}`);
23
+ if (grantee.amr !== void 0 && grantee.amr.length > 0) parts.push(`amr ${grantee.amr.join("/")}`);
24
+ return parts.length > 0 ? parts.join(" ") : "step-up";
25
+ }
26
+ default: return grantee;
27
+ }
28
+ }
29
+ const TITLES = {
30
+ granted: "Granted",
31
+ denied: "Denied",
32
+ approval: "Approval required",
33
+ tenant: "Wrong tenant",
34
+ delegation: "Not delegated",
35
+ "server-only": "Server only",
36
+ upgrade: "Upgrade required"
37
+ };
38
+ function labelApprover(approver) {
39
+ if (approver.kind === "user") return `user ${approver.id}`;
40
+ if (approver.kind === "permission") return `a holder of ${approver.permission}`;
41
+ if (approver.kind === "any-of") return `one of (${approver.of.map((entry) => flattenApprovers(entry).map(labelApprover).join(" and ")).join(", ")})`;
42
+ return labelGrantee(approver);
43
+ }
44
+ function approvers(approval) {
45
+ if (approval === void 0 || approval === "human") return [];
46
+ return [...flattenApprovers(approval.by), ...(approval.stages ?? []).flatMap((stage) => flattenApprovers(stage.by))].map(labelApprover);
47
+ }
48
+ function approvalDetail(permission, labels) {
49
+ if (labels.length === 0) return `${permission} requires human approval.`;
50
+ return `${permission} requires approval from ${labels.join(" and ")}.`;
51
+ }
52
+ function describe(decision, options) {
53
+ const messages = options?.messages;
54
+ const titleOf = (kind) => messages?.titles?.[kind] ?? TITLES[kind];
55
+ if (decision.outcome === "granted") {
56
+ const { permission } = decision.matched;
57
+ return {
58
+ kind: "granted",
59
+ title: titleOf("granted"),
60
+ detail: messages?.granted?.(permission) ?? `${permission} granted.`,
61
+ alternatives: []
62
+ };
63
+ }
64
+ if (decision.outcome === "approval-required") {
65
+ const { permission } = decision.grant;
66
+ const labels = approvers(decision.grant.approval);
67
+ return {
68
+ kind: "approval",
69
+ title: titleOf("approval"),
70
+ detail: messages?.approval?.(permission, labels) ?? approvalDetail(permission, labels),
71
+ alternatives: []
72
+ };
73
+ }
74
+ const plans = requiredPlans(decision);
75
+ if (plans.length > 0) return {
76
+ kind: "upgrade",
77
+ title: titleOf("upgrade"),
78
+ detail: messages?.upgrade?.(plans) ?? `${plans.join(" or ")} plan required.`,
79
+ alternatives: decision.alternatives,
80
+ plans
81
+ };
82
+ const reasons = decision.denials.map((denial) => denial.reason);
83
+ const kind = reasons.some((reason) => TENANT_REASONS.has(reason)) ? "tenant" : reasons.some((reason) => DELEGATION_REASONS.has(reason)) ? "delegation" : reasons.includes("opaque-condition") || reasons.includes("server-only") ? "server-only" : "denied";
84
+ const texts = messages?.reasons;
85
+ const detail = reasons.map((reason) => (typeof texts === "function" ? texts(reason, decision) : texts?.[reason]) ?? reason).join(messages?.separator ?? ", ");
86
+ return {
87
+ kind,
88
+ title: titleOf(kind),
89
+ detail,
90
+ alternatives: decision.alternatives
91
+ };
92
+ }
93
+ //#endregion
94
+ export { describe as t };
@@ -0,0 +1,36 @@
1
+ import { Qn as DeniedDecision, Yn as Decision, Zn as DenialReason } from "./policy-CFZAr_Al.js";
2
+ import { f as Permission } from "./permissions-DttnqqxC.js";
3
+ //#region src/core/describe.d.ts
4
+ type DecisionDescription = {
5
+ readonly kind: "granted" | "denied" | "approval" | "tenant" | "delegation" | "server-only" | "upgrade";
6
+ readonly title: string;
7
+ readonly detail: string;
8
+ readonly alternatives: readonly Permission[];
9
+ /** On `upgrade`: the plans any of which would grant the permission. */
10
+ readonly plans?: readonly string[];
11
+ };
12
+ /**
13
+ * Localised text for `describe`. Every entry is optional and falls back to the
14
+ * English default; `kind` and `alternatives` never change.
15
+ */
16
+ type DescribeMessages = {
17
+ readonly titles?: Partial<Record<DecisionDescription["kind"], string>>;
18
+ /**
19
+ * Text per denial reason; a denied detail joins the texts of its reasons
20
+ * with `separator`. The function form also sees the decision; `undefined`
21
+ * keeps the reason code, as a missing record entry does.
22
+ */
23
+ readonly reasons?: Partial<Record<DenialReason, string>> | ((reason: DenialReason, decision: DeniedDecision) => string | undefined);
24
+ /** Joins denial reason texts. Default `', '`. */
25
+ readonly separator?: string;
26
+ readonly granted?: (permission: string) => string;
27
+ /** `approvers` is empty for `'human'` approval. */
28
+ readonly approval?: (permission: string, approvers: readonly string[]) => string;
29
+ readonly upgrade?: (plans: readonly string[]) => string;
30
+ };
31
+ type DescribeOptions = {
32
+ readonly messages?: DescribeMessages;
33
+ };
34
+ declare function describe(decision: Decision, options?: DescribeOptions): DecisionDescription;
35
+ //#endregion
36
+ export { describe as i, DescribeMessages as n, DescribeOptions as r, DecisionDescription as t };