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,833 @@
1
+ import { t as compact } from "../compact-y6vfu2_f.js";
2
+ import { a as deniedMessage, i as approvalMessage, n as PermDockDeniedError, t as PermDockApprovalRequiredError } from "../errors-Cz5zn0mW.js";
3
+ import { t as createPermDock$1 } from "../permdock-CzqXjCpU.js";
4
+ import { n as resourceRef } from "../resource-ref-CaS9yVPi.js";
5
+ import { i as isSubject } from "../subject-C6dLxqHU.js";
6
+ import { l as storedApprovalToken, s as resumeDecision } from "../helpers-H_KARDVC.js";
7
+ import { t as timeoutSignal } from "../timeout-D51niuQP.js";
8
+ import { t as instanceOptions } from "../instance-options-Dhhcnm3y.js";
9
+ import { mkdirSync, readFileSync, statSync, unlinkSync, writeFileSync } from "node:fs";
10
+ import path from "node:path";
11
+ import { createInterface } from "node:readline";
12
+ import { homedir } from "node:os";
13
+ //#region src/terminal/device.ts
14
+ /** Milliseconds an authorization server request may take. */
15
+ const TERMINAL_TIMEOUT_MS = 1e4;
16
+ function isRecord$1(value) {
17
+ return value !== null && typeof value === "object" && !Array.isArray(value);
18
+ }
19
+ async function readJson(response) {
20
+ try {
21
+ const body = await response.json();
22
+ return isRecord$1(body) ? body : null;
23
+ } catch {
24
+ return null;
25
+ }
26
+ }
27
+ /** POSTs a form and reads a JSON object back; any network or parse failure is `null`. */
28
+ async function postForm(runtime, url, fields) {
29
+ const fetchImpl = runtime.fetch ?? fetch;
30
+ try {
31
+ return await readJson(await fetchImpl(url, {
32
+ method: "POST",
33
+ headers: { "content-type": "application/x-www-form-urlencoded" },
34
+ body: new URLSearchParams(fields),
35
+ signal: timeoutSignal(TERMINAL_TIMEOUT_MS)
36
+ }));
37
+ } catch {
38
+ return null;
39
+ }
40
+ }
41
+ async function discoverDeviceEndpoints(issuer, runtime) {
42
+ const fetchImpl = runtime.fetch ?? fetch;
43
+ const url = issuer.endsWith("/") ? `${issuer}.well-known/oauth-authorization-server` : `${issuer}/.well-known/oauth-authorization-server`;
44
+ try {
45
+ const body = await readJson(await fetchImpl(url, { signal: timeoutSignal(TERMINAL_TIMEOUT_MS) }));
46
+ if (body === null) return {};
47
+ return compact({
48
+ authorizationEndpoint: typeof body["device_authorization_endpoint"] === "string" ? body["device_authorization_endpoint"] : void 0,
49
+ tokenEndpoint: typeof body["token_endpoint"] === "string" ? body["token_endpoint"] : void 0,
50
+ revocationEndpoint: typeof body["revocation_endpoint"] === "string" ? body["revocation_endpoint"] : void 0
51
+ });
52
+ } catch {
53
+ return {};
54
+ }
55
+ }
56
+ function parseAuthorization(body) {
57
+ if (typeof body["device_code"] !== "string" || typeof body["user_code"] !== "string" || typeof body["verification_uri"] !== "string" || typeof body["expires_in"] !== "number") return null;
58
+ return compact({
59
+ device_code: body["device_code"],
60
+ user_code: body["user_code"],
61
+ verification_uri: body["verification_uri"],
62
+ verification_uri_complete: typeof body["verification_uri_complete"] === "string" ? body["verification_uri_complete"] : void 0,
63
+ expires_in: body["expires_in"],
64
+ interval: typeof body["interval"] === "number" ? body["interval"] : void 0
65
+ });
66
+ }
67
+ function parseToken(body, now) {
68
+ if (typeof body["error"] === "string") return {
69
+ ok: false,
70
+ error: body["error"]
71
+ };
72
+ if (typeof body["access_token"] !== "string") return {
73
+ ok: false,
74
+ error: "invalid-token"
75
+ };
76
+ return {
77
+ ok: true,
78
+ credential: compact({
79
+ access_token: body["access_token"],
80
+ refresh_token: typeof body["refresh_token"] === "string" ? body["refresh_token"] : void 0,
81
+ expires_at: typeof body["expires_in"] === "number" ? now + body["expires_in"] : void 0,
82
+ token_type: typeof body["token_type"] === "string" ? body["token_type"] : void 0
83
+ })
84
+ };
85
+ }
86
+ async function runDeviceFlow(device, runtime, write) {
87
+ const sleep = runtime.sleep ?? defaultSleep;
88
+ const now = runtime.now ?? (() => Math.floor(Date.now() / 1e3));
89
+ let authorizationEndpoint = device.authorizationEndpoint;
90
+ let tokenEndpoint = device.tokenEndpoint;
91
+ if ((authorizationEndpoint === void 0 || tokenEndpoint === void 0) && device.issuer !== void 0) {
92
+ const discovered = await discoverDeviceEndpoints(device.issuer, runtime);
93
+ authorizationEndpoint = authorizationEndpoint ?? discovered.authorizationEndpoint;
94
+ tokenEndpoint = tokenEndpoint ?? discovered.tokenEndpoint;
95
+ }
96
+ if (authorizationEndpoint === void 0 || tokenEndpoint === void 0) return null;
97
+ const startedBody = await postForm(runtime, authorizationEndpoint, {
98
+ client_id: device.clientId,
99
+ scope: device.scope ?? ""
100
+ });
101
+ const authorization = startedBody === null ? null : parseAuthorization(startedBody);
102
+ if (authorization === null) return null;
103
+ device.onPrompt?.(compact({
104
+ user_code: authorization.user_code,
105
+ verification_uri: authorization.verification_uri,
106
+ verification_uri_complete: authorization.verification_uri_complete
107
+ }));
108
+ write(`Visit ${authorization.verification_uri} and enter ${authorization.user_code}\n`);
109
+ if (authorization.verification_uri_complete !== void 0) device.open?.(authorization.verification_uri_complete);
110
+ let interval = authorization.interval ?? 5;
111
+ const deadline = now() + authorization.expires_in;
112
+ while (now() < deadline) {
113
+ await sleep(interval * 1e3);
114
+ const polledBody = await postForm(runtime, tokenEndpoint, {
115
+ grant_type: "urn:ietf:params:oauth:grant-type:device_code",
116
+ device_code: authorization.device_code,
117
+ client_id: device.clientId
118
+ });
119
+ if (polledBody === null) return null;
120
+ const token = parseToken(polledBody, now());
121
+ if (token.ok) return token.credential;
122
+ if (token.error === "slow_down") {
123
+ interval += 5;
124
+ continue;
125
+ }
126
+ if (token.error === "authorization_pending") continue;
127
+ return null;
128
+ }
129
+ return null;
130
+ }
131
+ async function refreshCredential(device, credential, runtime) {
132
+ if (credential.refresh_token === void 0) return null;
133
+ const now = runtime.now ?? (() => Math.floor(Date.now() / 1e3));
134
+ let tokenEndpoint = device.tokenEndpoint;
135
+ if (tokenEndpoint === void 0 && device.issuer !== void 0) tokenEndpoint = (await discoverDeviceEndpoints(device.issuer, runtime)).tokenEndpoint;
136
+ if (tokenEndpoint === void 0) return null;
137
+ const body = await postForm(runtime, tokenEndpoint, {
138
+ grant_type: "refresh_token",
139
+ refresh_token: credential.refresh_token,
140
+ client_id: device.clientId
141
+ });
142
+ if (body === null) return null;
143
+ const token = parseToken(body, now());
144
+ return token.ok ? token.credential : null;
145
+ }
146
+ async function revokeCredential(device, credential, runtime) {
147
+ if (device === void 0 || credential.refresh_token === void 0) return;
148
+ let revocationEndpoint = device.revocationEndpoint;
149
+ if (revocationEndpoint === void 0 && device.issuer !== void 0) revocationEndpoint = (await discoverDeviceEndpoints(device.issuer, runtime)).revocationEndpoint;
150
+ if (revocationEndpoint === void 0) return;
151
+ await postForm(runtime, revocationEndpoint, {
152
+ token: credential.refresh_token,
153
+ token_type_hint: "refresh_token",
154
+ client_id: device.clientId
155
+ });
156
+ }
157
+ function defaultSleep(ms) {
158
+ return new Promise((resolve) => {
159
+ setTimeout(resolve, ms);
160
+ });
161
+ }
162
+ //#endregion
163
+ //#region src/terminal/exit.ts
164
+ const EX_OK = 0;
165
+ const EX_USAGE = 64;
166
+ const EX_TEMPFAIL = 75;
167
+ const EX_NOPERM = 77;
168
+ const EX_CONFIG = 78;
169
+ var TerminalExit = class extends Error {
170
+ name = "TerminalExit";
171
+ code;
172
+ constructor(code) {
173
+ super(`exit ${String(code)}`);
174
+ this.code = code;
175
+ }
176
+ };
177
+ function defaultExit(code) {
178
+ process.exit.bind(process)(code);
179
+ throw new TerminalExit(code);
180
+ }
181
+ //#endregion
182
+ //#region src/terminal/filter.ts
183
+ function snapshotAllows(permdock, permission) {
184
+ const snapshot = permdock.snapshot();
185
+ if (typeof snapshot === "string" || snapshot instanceof Promise) return false;
186
+ return snapshot.grants.some((grant) => grant.permission === permission.key && grant.effect === "allow");
187
+ }
188
+ function commandAllowed(permdock, permission) {
189
+ if (permission.kind === "collection") return permdock.can(permission);
190
+ return snapshotAllows(permdock, permission);
191
+ }
192
+ function filterCommandEntries(permdock, entries, options) {
193
+ const mode = options.mode;
194
+ if (permdock === void 0) {
195
+ if (mode === "hide") return [];
196
+ return entries.map((entry) => ({
197
+ ...entry,
198
+ description: `${entry.description} (requires ${entry.permission.scope})`
199
+ }));
200
+ }
201
+ const visible = [];
202
+ for (const entry of entries) {
203
+ if (commandAllowed(permdock, entry.permission)) {
204
+ visible.push(entry);
205
+ continue;
206
+ }
207
+ if (mode === "annotate") visible.push({
208
+ ...entry,
209
+ description: `${entry.description} (requires ${entry.permission.scope})`
210
+ });
211
+ }
212
+ return visible;
213
+ }
214
+ //#endregion
215
+ //#region src/terminal/format.ts
216
+ function exitCode(decision) {
217
+ switch (decision.outcome) {
218
+ case "granted": return 0;
219
+ case "approval-required": return 75;
220
+ case "denied": return 77;
221
+ default: return decision;
222
+ }
223
+ }
224
+ function permissionKey(decision, permission) {
225
+ if (permission !== void 0) return permission.key;
226
+ if (decision.outcome === "granted") return decision.matched.permission;
227
+ if (decision.outcome === "approval-required") return decision.grant.permission;
228
+ return "unknown";
229
+ }
230
+ function permissionScope(permission) {
231
+ return permission?.scope ?? "";
232
+ }
233
+ function resourceOf(permission) {
234
+ return { type: permission?.resource ?? "unknown" };
235
+ }
236
+ function formatDecision(decision, options = {}) {
237
+ const json = options.json === true;
238
+ const key = permissionKey(decision, options.permission);
239
+ const scope = permissionScope(options.permission);
240
+ const resource = resourceOf(options.permission);
241
+ const subject = options.subject;
242
+ if (decision.outcome === "granted") return json ? `${JSON.stringify({
243
+ outcome: "granted",
244
+ permission: key
245
+ })}\n` : "";
246
+ if (decision.outcome === "approval-required") {
247
+ const error = new PermDockApprovalRequiredError({
248
+ decision,
249
+ permission: key,
250
+ scope,
251
+ resource,
252
+ message: approvalMessage(key, decision.reason, decision.token)
253
+ });
254
+ const details = compact({
255
+ ...error.toProblemDetails(compact({ instance: options.instance })),
256
+ approval: options.approval
257
+ });
258
+ if (json) return `${JSON.stringify(details)}\n`;
259
+ return `${details.detail}\n`;
260
+ }
261
+ const details = new PermDockDeniedError({
262
+ decision,
263
+ permission: key,
264
+ scope,
265
+ resource,
266
+ subject: subject ?? {
267
+ principal: null,
268
+ context: {}
269
+ },
270
+ message: deniedMessage(key, subject?.principal?.id, decision.denials, decision.alternatives.map((leaf) => leaf.key))
271
+ }).toProblemDetails(compact({ instance: options.instance }));
272
+ if (json) return `${JSON.stringify(details)}\n`;
273
+ return `${details.detail}\n`;
274
+ }
275
+ //#endregion
276
+ //#region src/terminal/storage.ts
277
+ const FILE_MODE = 384;
278
+ const DIR_MODE = 448;
279
+ const GROUP_OR_WORLD = 63;
280
+ function credentialsPath(service, runtime) {
281
+ if (runtime.configDir !== void 0) return path.join(runtime.configDir, "credentials.json");
282
+ const home = runtime.homedir ?? homedir;
283
+ const env = runtime.env ?? process.env;
284
+ if ((runtime.platform ?? process.platform) === "win32") {
285
+ const appData = env["APPDATA"] ?? path.join(home(), "AppData", "Roaming");
286
+ return path.join(appData, service, "credentials.json");
287
+ }
288
+ const xdg = env["XDG_CONFIG_HOME"] ?? path.join(home(), ".config");
289
+ return path.join(xdg, service, "credentials.json");
290
+ }
291
+ function isRecord(value) {
292
+ return value !== null && typeof value === "object" && !Array.isArray(value);
293
+ }
294
+ function parseCredential(value) {
295
+ if (!isRecord(value) || typeof value["access_token"] !== "string") return null;
296
+ return compact({
297
+ access_token: value["access_token"],
298
+ refresh_token: typeof value["refresh_token"] === "string" ? value["refresh_token"] : void 0,
299
+ expires_at: typeof value["expires_at"] === "number" ? value["expires_at"] : void 0,
300
+ token_type: typeof value["token_type"] === "string" ? value["token_type"] : void 0
301
+ });
302
+ }
303
+ function keyringEntry(storage, profile) {
304
+ if (storage.keyring === void 0) return null;
305
+ try {
306
+ return new storage.keyring(storage.service, profile);
307
+ } catch {
308
+ return null;
309
+ }
310
+ }
311
+ function readKeyring(storage, profile) {
312
+ const entry = keyringEntry(storage, profile);
313
+ if (entry === null) return null;
314
+ try {
315
+ const raw = entry.getPassword();
316
+ return typeof raw === "string" ? parseCredential(JSON.parse(raw)) : null;
317
+ } catch {
318
+ return null;
319
+ }
320
+ }
321
+ function readCredentials(storage, profile, runtime) {
322
+ return readKeyring(storage, profile) ?? readFile(storage.service, profile, runtime);
323
+ }
324
+ function readFile(service, profile, runtime) {
325
+ const file = credentialsPath(service, runtime);
326
+ let raw;
327
+ try {
328
+ const stat = statSync(file);
329
+ if ((runtime.platform ?? process.platform) !== "win32" && (stat.mode & GROUP_OR_WORLD) !== 0) return null;
330
+ raw = readFileSync(file, "utf8");
331
+ } catch {
332
+ return null;
333
+ }
334
+ try {
335
+ const parsed = JSON.parse(raw);
336
+ if (!isRecord(parsed) || !isRecord(parsed["profiles"])) return null;
337
+ return parseCredential(parsed["profiles"][profile]);
338
+ } catch {
339
+ return null;
340
+ }
341
+ }
342
+ /** The OS keychain when `storage.keyring` is set and works; otherwise the mode-0600 file. */
343
+ function writeCredentials(storage, profile, credential, runtime) {
344
+ const entry = keyringEntry(storage, profile);
345
+ if (entry !== null) try {
346
+ entry.setPassword(JSON.stringify(credential));
347
+ deleteFile(storage.service, profile, runtime);
348
+ return;
349
+ } catch {}
350
+ writeFile(storage.service, profile, credential, runtime);
351
+ }
352
+ function writeFile(service, profile, credential, runtime) {
353
+ const file = credentialsPath(service, runtime);
354
+ mkdirSync(path.dirname(file), {
355
+ recursive: true,
356
+ mode: DIR_MODE
357
+ });
358
+ let profiles = {};
359
+ try {
360
+ const existing = JSON.parse(readFileSync(file, "utf8"));
361
+ if (isRecord(existing) && isRecord(existing["profiles"])) profiles = existing["profiles"];
362
+ } catch {
363
+ profiles = {};
364
+ }
365
+ profiles[profile] = credential;
366
+ writeFileSync(file, `${JSON.stringify({ profiles }, null, 2)}\n`, {
367
+ encoding: "utf8",
368
+ mode: FILE_MODE
369
+ });
370
+ }
371
+ function deleteCredentials(storage, profile, runtime) {
372
+ const entry = keyringEntry(storage, profile);
373
+ if (entry !== null) try {
374
+ entry.deletePassword();
375
+ } catch {}
376
+ deleteFile(storage.service, profile, runtime);
377
+ }
378
+ function deleteFile(service, profile, runtime) {
379
+ const file = credentialsPath(service, runtime);
380
+ let parsed;
381
+ try {
382
+ parsed = JSON.parse(readFileSync(file, "utf8"));
383
+ } catch {
384
+ return;
385
+ }
386
+ if (!isRecord(parsed) || !isRecord(parsed["profiles"])) return;
387
+ const profiles = {};
388
+ for (const key of Object.keys(parsed["profiles"])) if (key !== profile) profiles[key] = parsed["profiles"][key];
389
+ if (Object.keys(profiles).length === 0) {
390
+ try {
391
+ unlinkSync(file);
392
+ } catch {}
393
+ return;
394
+ }
395
+ writeFileSync(file, `${JSON.stringify({ profiles }, null, 2)}\n`, {
396
+ encoding: "utf8",
397
+ mode: FILE_MODE
398
+ });
399
+ }
400
+ //#endregion
401
+ //#region src/terminal/token.ts
402
+ const JWT_PART = /^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/u;
403
+ function looksLikeJwt(value) {
404
+ return JWT_PART.test(value);
405
+ }
406
+ function warnJwtInArgv(argv, write) {
407
+ for (const arg of argv) if (looksLikeJwt(arg)) {
408
+ write("warning: a JWT-shaped value was found in argv; tokens must not be passed as flags\n");
409
+ return;
410
+ }
411
+ }
412
+ function profileFromArgv(argv) {
413
+ const index = argv.indexOf("--as");
414
+ if (index === -1) return;
415
+ const next = argv[index + 1];
416
+ return next === void 0 || next.startsWith("-") ? void 0 : next;
417
+ }
418
+ function sourceName(source) {
419
+ if (typeof source === "string") return source;
420
+ if ("source" in source) return source.source;
421
+ return "env";
422
+ }
423
+ function envName(source, fallback) {
424
+ if (typeof source === "string") return fallback;
425
+ return source.env ?? fallback;
426
+ }
427
+ async function fromCiOidc(runtime, source) {
428
+ const env = runtime.env ?? process.env;
429
+ const fetchImpl = runtime.fetch ?? fetch;
430
+ const named = typeof source === "string" ? void 0 : source.env;
431
+ const audience = typeof source === "object" && "audience" in source ? source.audience : void 0;
432
+ if (named !== void 0) {
433
+ const value = env[named];
434
+ return typeof value === "string" && value !== "" ? value : null;
435
+ }
436
+ if (typeof env["CI_JOB_JWT_V2"] === "string" && env["CI_JOB_JWT_V2"] !== "") return env["CI_JOB_JWT_V2"];
437
+ if (typeof env["ACTIONS_ID_TOKEN_REQUEST_URL"] === "string" && typeof env["ACTIONS_ID_TOKEN_REQUEST_TOKEN"] === "string") try {
438
+ const url = new URL(env["ACTIONS_ID_TOKEN_REQUEST_URL"]);
439
+ if (audience !== void 0) url.searchParams.set("audience", audience);
440
+ const body = await (await fetchImpl(url, {
441
+ headers: { Authorization: `Bearer ${env["ACTIONS_ID_TOKEN_REQUEST_TOKEN"]}` },
442
+ signal: timeoutSignal(TERMINAL_TIMEOUT_MS)
443
+ })).json();
444
+ if (body !== null && typeof body === "object" && "value" in body && typeof body.value === "string") return body.value;
445
+ } catch {
446
+ return null;
447
+ }
448
+ return null;
449
+ }
450
+ async function resolveToken(sources, options) {
451
+ const walk = options.force === void 0 ? sources : [options.force];
452
+ const now = options.runtime.now ?? (() => Math.floor(Date.now() / 1e3));
453
+ for (const source of walk) {
454
+ const name = sourceName(source);
455
+ switch (name) {
456
+ case "env": {
457
+ const key = envName(source, "PERMDOCK_TOKEN");
458
+ const value = (options.runtime.env ?? process.env)[key];
459
+ if (typeof value === "string" && value !== "") return value;
460
+ break;
461
+ }
462
+ case "keychain": {
463
+ if (options.storage === void 0) break;
464
+ const stored = readCredentials(options.storage, options.profile, options.runtime);
465
+ if (stored === null) break;
466
+ if (stored.expires_at !== void 0 && stored.expires_at <= now()) {
467
+ if (options.device !== void 0) {
468
+ const refreshed = await refreshCredential(options.device, stored, options.runtime);
469
+ if (refreshed !== null) {
470
+ writeCredentials(options.storage, options.profile, refreshed, options.runtime);
471
+ return refreshed.access_token;
472
+ }
473
+ }
474
+ break;
475
+ }
476
+ return stored.access_token;
477
+ }
478
+ case "ci-oidc": {
479
+ const oidc = await fromCiOidc(options.runtime, source);
480
+ if (oidc !== null) return oidc;
481
+ break;
482
+ }
483
+ case "device": {
484
+ if (options.device === void 0) break;
485
+ const credential = await runDeviceFlow(options.device, options.runtime, options.write);
486
+ if (credential === null) break;
487
+ if (options.storage !== void 0) writeCredentials(options.storage, options.profile, credential, options.runtime);
488
+ return credential.access_token;
489
+ }
490
+ default: return name;
491
+ }
492
+ }
493
+ return null;
494
+ }
495
+ //#endregion
496
+ //#region src/terminal/create.ts
497
+ /** A thrown subject, loader or decision, or an instance check without a row. */
498
+ const FAILED_CLOSED = {
499
+ outcome: "denied",
500
+ denials: [{
501
+ role: null,
502
+ reason: "validation"
503
+ }],
504
+ alternatives: []
505
+ };
506
+ function writeOf(options) {
507
+ return options.runtime?.write ?? ((text) => {
508
+ process.stderr.write(text);
509
+ });
510
+ }
511
+ function argvOf(options) {
512
+ return options.runtime?.argv ?? process.argv;
513
+ }
514
+ function envOf(options) {
515
+ return options.runtime?.env ?? process.env;
516
+ }
517
+ /**
518
+ * The local y/N is the requester answering for themselves, so it stands in
519
+ * for an approval only where the grant allows that (`distinct: false`) and no
520
+ * agent is acting for the user.
521
+ */
522
+ function answersLocally(decision, subject) {
523
+ const approval = decision.grant.approval;
524
+ return typeof approval === "object" && approval.distinct === false && subject.actor === void 0;
525
+ }
526
+ function isInteractive(options) {
527
+ if (typeof options.interactive === "boolean") return options.interactive;
528
+ if (options.interactive !== void 0) return true;
529
+ return (options.runtime?.stdoutIsTTY ?? process.stdout.isTTY) === true && envOf(options)["CI"] === void 0;
530
+ }
531
+ function jsonOutput(options) {
532
+ if (options.output?.json !== void 0) return options.output.json;
533
+ return argvOf(options).includes("--json");
534
+ }
535
+ function flag(options, value, names) {
536
+ if (value !== void 0) return value;
537
+ const argv = argvOf(options);
538
+ return names.some((name) => argv.includes(name));
539
+ }
540
+ function actorFromResolved(value) {
541
+ if (value === null || value === void 0) return {};
542
+ if (isSubject(value)) {
543
+ const principal = value.principal;
544
+ const actor = value.actor ?? (principal === null ? void 0 : {
545
+ id: principal.id,
546
+ kind: principal.kind ?? "oauth-client"
547
+ });
548
+ return compact({
549
+ actor,
550
+ delegation: value.delegation
551
+ });
552
+ }
553
+ if (typeof value === "object" && value !== null && "id" in value && "kind" in value && typeof value.id === "string" && typeof value.kind === "string") return { actor: value };
554
+ return {};
555
+ }
556
+ function defaultConfirm(input) {
557
+ const rl = createInterface({
558
+ input: process.stdin,
559
+ output: process.stderr
560
+ });
561
+ return new Promise((resolve) => {
562
+ rl.question(`${input.permission} on ${describeResource(input.resource)} (${input.reason}). Continue? [y/N] `, (answer) => {
563
+ rl.close();
564
+ resolve(answer.trim().toLowerCase() === "y");
565
+ });
566
+ });
567
+ }
568
+ function describeResource(resource) {
569
+ return resource.id === void 0 ? resource.type : `${resource.type} ${resource.id}`;
570
+ }
571
+ const defaultTyped = (input) => {
572
+ const rl = createInterface({
573
+ input: process.stdin,
574
+ output: process.stderr
575
+ });
576
+ return new Promise((resolve) => {
577
+ rl.question(`${input.permission} on ${describeResource(input.resource)} cannot be undone. Type ${input.expected} to continue: `, (answer) => {
578
+ rl.close();
579
+ resolve(answer);
580
+ });
581
+ });
582
+ };
583
+ function createPermDock(policy, options) {
584
+ const write = writeOf(options);
585
+ const exit = options.runtime?.exit ?? defaultExit;
586
+ const runtime = compact({
587
+ ...options.runtime,
588
+ configDir: options.runtime?.configDir ?? options.storage?.dir
589
+ });
590
+ warnJwtInArgv(argvOf(options), write);
591
+ let cached;
592
+ let last;
593
+ let lastProfile = "default";
594
+ const tokenFor = (profile, force) => (sources) => resolveToken(sources, compact({
595
+ profile,
596
+ storage: options.storage,
597
+ device: options.device,
598
+ runtime,
599
+ write,
600
+ force
601
+ }));
602
+ const resolve = async (resolveOptions = {}) => {
603
+ const profile = resolveOptions.as ?? profileFromArgv(argvOf(options)) ?? "default";
604
+ lastProfile = profile;
605
+ const context = {
606
+ token: tokenFor(profile, resolveOptions.source),
607
+ profile
608
+ };
609
+ let user = null;
610
+ try {
611
+ user = await options.subject(context);
612
+ } catch {
613
+ user = null;
614
+ }
615
+ let actor;
616
+ let delegation;
617
+ if (options.actor !== void 0) try {
618
+ const resolved = actorFromResolved(await options.actor(context));
619
+ actor = resolved.actor;
620
+ delegation = resolved.delegation;
621
+ } catch {
622
+ actor = void 0;
623
+ delegation = void 0;
624
+ }
625
+ const built = await createPermDock$1(policy, user, compact({
626
+ tenant: options.tenant,
627
+ actor,
628
+ delegation,
629
+ ...instanceOptions(options)
630
+ }));
631
+ last = built;
632
+ return built;
633
+ };
634
+ const permdock = (resolveOptions = {}) => {
635
+ if (resolveOptions.refresh === true || cached === void 0) cached = resolve(resolveOptions);
636
+ return cached;
637
+ };
638
+ const format = (decision, formatOptions = {}) => formatDecision(decision, compact({
639
+ json: formatOptions.json ?? jsonOutput(options),
640
+ permission: formatOptions.permission,
641
+ instance: formatOptions.instance,
642
+ subject: formatOptions.subject ?? last?.subject,
643
+ approval: formatOptions.approval ?? options.approval
644
+ }));
645
+ const filterCommands = (entries, filterOptions) => {
646
+ const next = filterOptions ?? { mode: "hide" };
647
+ return filterCommandEntries(next.permdock ?? last, entries, next);
648
+ };
649
+ const protect = (permission, load) => (action) => async (...args) => {
650
+ const dryRun = flag(options, options.dryRun, ["--dry-run"]);
651
+ let instance;
652
+ let data;
653
+ let decide;
654
+ let first;
655
+ try {
656
+ instance = await permdock();
657
+ if (load !== void 0) {
658
+ data = await load(...args);
659
+ if (permission.kind === "instance" && (data === null || data === void 0)) {
660
+ write(format(FAILED_CLOSED, {
661
+ permission,
662
+ subject: instance.subject
663
+ }));
664
+ return exit(exitCode(FAILED_CLOSED));
665
+ }
666
+ }
667
+ decide = instance.decide;
668
+ first = decide(permission, data, dryRun ? {
669
+ source: "simulate",
670
+ adapter: "terminal"
671
+ } : {
672
+ source: "adapter",
673
+ adapter: "terminal"
674
+ });
675
+ } catch {
676
+ write(format(FAILED_CLOSED, { permission }));
677
+ return exit(exitCode(FAILED_CLOSED));
678
+ }
679
+ if (dryRun) {
680
+ write(first.outcome === "granted" ? jsonOutput(options) ? `${JSON.stringify({
681
+ outcome: "granted",
682
+ permission: permission.key,
683
+ dryRun: true
684
+ })}\n` : `dry run: ${permission.key} on ${describeResource(resourceRef(permission, data))} is granted; nothing ran\n` : format(first, {
685
+ permission,
686
+ subject: instance.subject
687
+ }));
688
+ return exit(exitCode(first));
689
+ }
690
+ if (first.outcome === "denied") {
691
+ write(format(first, {
692
+ permission,
693
+ subject: instance.subject
694
+ }));
695
+ return exit(exitCode(first));
696
+ }
697
+ let granted;
698
+ if (first.outcome === "granted") granted = first;
699
+ else if (answersLocally(first, instance.subject)) {
700
+ if (!isInteractive(options)) {
701
+ write(format(first, {
702
+ permission,
703
+ subject: instance.subject
704
+ }));
705
+ return exit(exitCode(first));
706
+ }
707
+ const confirm = typeof options.interactive === "object" ? options.interactive.confirm ?? defaultConfirm : defaultConfirm;
708
+ const promptToken = first.token;
709
+ if (!await confirm({
710
+ permission: permission.key,
711
+ resource: resourceRef(permission, data),
712
+ reason: first.reason,
713
+ token: promptToken
714
+ })) {
715
+ write(format({
716
+ outcome: "denied",
717
+ denials: [{
718
+ role: null,
719
+ reason: "approval"
720
+ }],
721
+ alternatives: []
722
+ }, {
723
+ permission,
724
+ subject: instance.subject
725
+ }));
726
+ return exit(77);
727
+ }
728
+ const again = decide(permission, data, compact({
729
+ source: "adapter",
730
+ adapter: "terminal"
731
+ }));
732
+ if (again.outcome === "denied") {
733
+ write(format(again, {
734
+ permission,
735
+ subject: instance.subject
736
+ }));
737
+ return exit(exitCode(again));
738
+ }
739
+ if (again.outcome === "granted") granted = again;
740
+ else if (again.token === promptToken) {
741
+ const principal = instance.subject.principal;
742
+ if (principal === null) {
743
+ write(format(again, {
744
+ permission,
745
+ subject: instance.subject
746
+ }));
747
+ return exit(77);
748
+ }
749
+ granted = {
750
+ outcome: "granted",
751
+ subject: {
752
+ ...instance.subject,
753
+ principal
754
+ },
755
+ matched: again.grant,
756
+ token: again.token
757
+ };
758
+ } else {
759
+ write(format(again, {
760
+ permission,
761
+ subject: instance.subject
762
+ }));
763
+ return exit(77);
764
+ }
765
+ } else {
766
+ if (options.store === void 0) {
767
+ write(format(first, {
768
+ permission,
769
+ subject: instance.subject
770
+ }));
771
+ if (!jsonOutput(options)) write(`${permission.key} needs someone other than you to approve it: pass a store to createPermDock so the request can be approved and the command rerun\n`);
772
+ return exit(77);
773
+ }
774
+ const resumed = await resumeDecision({
775
+ decision: first,
776
+ permission,
777
+ subject: instance.subject,
778
+ store: options.store,
779
+ resource: resourceRef(permission, data),
780
+ adapter: "terminal",
781
+ token: await storedApprovalToken(options.store, first)
782
+ });
783
+ if (resumed.outcome !== "granted") {
784
+ write(format(resumed, {
785
+ permission,
786
+ subject: instance.subject
787
+ }));
788
+ return exit(exitCode(resumed));
789
+ }
790
+ granted = resumed;
791
+ }
792
+ if (permission.meta.destructive === true && !flag(options, options.yes, ["--yes", "-y"])) {
793
+ const resource = resourceRef(permission, data);
794
+ if (!isInteractive(options)) {
795
+ write(`${permission.key} on ${describeResource(resource)} is destructive: pass --yes to run it without a terminal\n`);
796
+ return exit(64);
797
+ }
798
+ const typed = typeof options.interactive === "object" ? options.interactive.typed ?? defaultTyped : defaultTyped;
799
+ const expected = resource.id ?? permission.key;
800
+ if ((await typed({
801
+ permission: permission.key,
802
+ resource,
803
+ expected
804
+ })).trim() !== expected) {
805
+ write(`${permission.key}: confirmation did not match; nothing ran\n`);
806
+ return exit(77);
807
+ }
808
+ }
809
+ return action({
810
+ permdock: instance,
811
+ data,
812
+ decision: granted
813
+ }, ...args);
814
+ };
815
+ const logout = async () => {
816
+ if (options.storage === void 0) return;
817
+ const stored = readCredentials(options.storage, lastProfile, runtime);
818
+ if (stored !== null) await revokeCredential(options.device, stored, runtime);
819
+ deleteCredentials(options.storage, lastProfile, runtime);
820
+ cached = void 0;
821
+ last = void 0;
822
+ };
823
+ return {
824
+ permdock,
825
+ protect,
826
+ filterCommands,
827
+ format,
828
+ exitCode,
829
+ logout
830
+ };
831
+ }
832
+ //#endregion
833
+ export { EX_CONFIG, EX_NOPERM, EX_OK, EX_TEMPFAIL, EX_USAGE, TerminalExit, createPermDock, exitCode, formatDecision, looksLikeJwt };