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,571 @@
1
+ import { t as compact } from "../compact-y6vfu2_f.js";
2
+ import { n as freezeDeep } from "../freeze-y1_jQL4v.js";
3
+ import { n as sha256, t as bytesToBase64Url } from "../sha256-BO0swRXL.js";
4
+ import { t as anonymousSubject } from "../subject-C6dLxqHU.js";
5
+ import { i as linkPolicyViolation, o as parseCapability, s as redeemerAllows, t as capabilitySubject } from "../capability-B68OFnZx.js";
6
+ import { a as decodeHeader, i as issuerFromDiscovery, n as assertSubjectConfig, o as normalizeTyp, r as fail, t as joseTokenVerifier } from "../verifier-B90agnhl.js";
7
+ import { t as loadJose } from "../load-jose-BL6LH4bL.js";
8
+ import { n as mapClaimsToSubject, r as validateCustomClaims, t as acceptMismatch } from "../map-claims-B_6I1Rn-.js";
9
+ //#region src/jwt/capability.ts
10
+ function emit(options, reason, cause, token) {
11
+ if (options.onAuth === void 0) return;
12
+ const header = decodeHeader(token);
13
+ options.onAuth(compact({
14
+ reason,
15
+ cause,
16
+ source: "capability",
17
+ kid: header?.kid,
18
+ alg: header?.alg,
19
+ typ: header?.typ,
20
+ issuer: options.issuer,
21
+ requestId: options.requestId
22
+ }));
23
+ }
24
+ async function claimOnce(replay, key, expiresAt) {
25
+ if (replay.claim !== void 0) return replay.claim(key, expiresAt);
26
+ if (await replay.seen(key)) return false;
27
+ await replay.remember(key, expiresAt);
28
+ return true;
29
+ }
30
+ async function stores(options, capability, issuedAt, once) {
31
+ try {
32
+ const policy = await options.linkPolicy?.(capability);
33
+ if (policy !== void 0 && linkPolicyViolation(capability, policy, issuedAt) !== void 0) return "link-policy";
34
+ if (options.revoked !== void 0 && await options.revoked(capability.id)) return "capability-revoked";
35
+ const replay = options.replay;
36
+ if (once !== void 0 && (replay === void 0 || !await claimOnce(replay, once.key, once.expiresAt))) return "capability-replayed";
37
+ return { ok: true };
38
+ } catch {
39
+ return {
40
+ ok: false,
41
+ reason: "source-threw"
42
+ };
43
+ }
44
+ }
45
+ /**
46
+ * Resolves a `permdock-capability+jwt` into the `link` subject it acts as.
47
+ * Every failure (signature, `typ`, `iss`, `aud`, expiry, a malformed claim,
48
+ * a revoked link, a replayed one-time token, a redeemer the viewer does not
49
+ * satisfy, a throwing store) is the anonymous subject, never a throw.
50
+ */
51
+ async function subjectFromCapability(token, options) {
52
+ if (token === void 0 || token === null || token.length === 0) return anonymousSubject();
53
+ const deny = (cause, reason = "invalid-token") => {
54
+ emit(options, reason, cause, token);
55
+ return anonymousSubject();
56
+ };
57
+ if (typeof options.issuer !== "string" || options.issuer.length === 0) return deny("wrong-issuer");
58
+ if (options.audience === void 0 || options.audience.length === 0) return deny("wrong-audience");
59
+ let verifier;
60
+ try {
61
+ verifier = options.verifier ?? joseTokenVerifier({
62
+ ...options,
63
+ typ: "permdock-capability+jwt"
64
+ });
65
+ } catch {
66
+ return deny("malformed");
67
+ }
68
+ let verified;
69
+ try {
70
+ verified = await verifier.verify(token, compact({
71
+ typ: "permdock-capability+jwt",
72
+ issuer: options.issuer,
73
+ audience: options.audience,
74
+ clockTolerance: options.clockTolerance
75
+ }));
76
+ } catch {
77
+ return deny("malformed");
78
+ }
79
+ if (!verified.ok) return deny(verified.cause);
80
+ if (normalizeTyp(verified.header.typ) !== "permdock-capability+jwt") return deny("wrong-token-type");
81
+ const parsed = parseCapability(verified.claims["capability"]);
82
+ const exp = verified.claims.exp;
83
+ if (parsed?.holder !== "link" || verified.claims.sub !== parsed.id || typeof exp !== "number") return deny("invalid-claims");
84
+ const capability = {
85
+ ...parsed,
86
+ expiresAt: Math.min(parsed.expiresAt, exp)
87
+ };
88
+ const now = Date.now() / 1e3;
89
+ if (capability.expiresAt <= now) return deny("expired");
90
+ if (!redeemerAllows(capability.redeemer, options.viewer, now)) return deny("redeemer-mismatch");
91
+ const jti = verified.claims["jti"];
92
+ if (capability.once === true && (options.replay === void 0 || typeof jti !== "string" || jti === "")) return deny("invalid-claims");
93
+ const iat = verified.claims.iat;
94
+ const checked = await stores(options, capability, typeof iat === "number" ? iat : void 0, capability.once === true ? {
95
+ key: `capability\u0000${options.issuer}\u0000${String(jti)}`,
96
+ expiresAt: capability.expiresAt
97
+ } : void 0);
98
+ if (typeof checked === "string") return deny(checked);
99
+ if (!checked.ok) return deny(void 0, checked.reason);
100
+ return capabilitySubject(capability, { issuer: options.issuer });
101
+ }
102
+ //#endregion
103
+ //#region src/jwt/ci-oidc.ts
104
+ const PROVIDERS = {
105
+ github: {
106
+ issuer: "https://token.actions.githubusercontent.com",
107
+ jwks: "https://token.actions.githubusercontent.com/.well-known/jwks"
108
+ },
109
+ gitlab: {
110
+ issuer: "https://gitlab.com",
111
+ jwks: "https://gitlab.com/oauth/discovery/keys"
112
+ },
113
+ buildkite: {
114
+ issuer: "https://agent.buildkite.com",
115
+ jwks: "https://agent.buildkite.com/.well-known/jwks"
116
+ }
117
+ };
118
+ function text(claims, key) {
119
+ const value = Object.hasOwn(claims, key) ? claims[key] : void 0;
120
+ return typeof value === "string" && value !== "" ? value : void 0;
121
+ }
122
+ function fullRef(name, type) {
123
+ if (name === void 0) return;
124
+ if (name.startsWith("refs/")) return name;
125
+ return type === "tag" ? `refs/tags/${name}` : `refs/heads/${name}`;
126
+ }
127
+ function jobClaims(provider, claims) {
128
+ switch (provider) {
129
+ case "github": return compact({
130
+ repository: text(claims, "repository"),
131
+ ref: text(claims, "ref"),
132
+ environment: text(claims, "environment")
133
+ });
134
+ case "gitlab": return compact({
135
+ repository: text(claims, "project_path"),
136
+ ref: fullRef(text(claims, "ref"), text(claims, "ref_type") === "tag" ? "tag" : "branch"),
137
+ environment: text(claims, "environment")
138
+ });
139
+ case "buildkite": {
140
+ const organization = text(claims, "organization_slug");
141
+ const pipeline = text(claims, "pipeline_slug");
142
+ const tag = text(claims, "build_tag");
143
+ return compact({
144
+ repository: organization === void 0 || pipeline === void 0 ? void 0 : `${organization}/${pipeline}`,
145
+ ref: tag === void 0 ? fullRef(text(claims, "build_branch"), "branch") : fullRef(tag, "tag")
146
+ });
147
+ }
148
+ default: return provider;
149
+ }
150
+ }
151
+ /**
152
+ * Resolves a CI provider's OIDC token (GitHub Actions, GitLab CI, Buildkite)
153
+ * into a `workload` principal whose id is `sub`. Every failure (signature,
154
+ * issuer, audience, expiry, a missing `sub`, the `schema`) is the anonymous
155
+ * subject, never a throw and never a user.
156
+ */
157
+ async function subjectFromCiOidc(token, options) {
158
+ if (token === void 0 || token === null || token.length === 0) return anonymousSubject();
159
+ const known = Object.hasOwn(PROVIDERS, options.provider) ? PROVIDERS[options.provider] : void 0;
160
+ const issuer = options.issuer ?? known?.issuer;
161
+ const deny = (cause) => {
162
+ const header = decodeHeader(token);
163
+ options.onAuth?.(compact({
164
+ reason: "invalid-token",
165
+ cause,
166
+ source: "ci-oidc",
167
+ kid: header?.kid,
168
+ alg: header?.alg,
169
+ typ: header?.typ,
170
+ issuer,
171
+ requestId: options.requestId
172
+ }));
173
+ return anonymousSubject();
174
+ };
175
+ if (known === void 0 || issuer === void 0) return deny("wrong-issuer");
176
+ if (options.audience === void 0 || options.audience.length === 0) return deny("wrong-audience");
177
+ let verifier;
178
+ try {
179
+ verifier = options.verifier ?? joseTokenVerifier(options.issuer === void 0 || options.jwks !== void 0 ? {
180
+ ...options,
181
+ issuer,
182
+ jwks: options.jwks ?? known.jwks
183
+ } : {
184
+ ...options,
185
+ issuer,
186
+ discovery: issuer
187
+ });
188
+ } catch {
189
+ return deny("malformed");
190
+ }
191
+ let verified;
192
+ try {
193
+ verified = await verifier.verify(token, compact({
194
+ typ: ["JWT"],
195
+ issuer,
196
+ audience: options.audience,
197
+ clockTolerance: options.clockTolerance
198
+ }));
199
+ } catch {
200
+ return deny("malformed");
201
+ }
202
+ if (!verified.ok) return deny(verified.cause);
203
+ const sub = text(verified.claims, "sub");
204
+ if (sub === void 0) return deny("invalid-claims");
205
+ if (options.schema !== void 0 && !validateCustomClaims(verified.claims, options.schema).ok) return deny("invalid-claims");
206
+ const principal = {
207
+ id: sub,
208
+ kind: "workload",
209
+ issuer,
210
+ provider: options.provider,
211
+ ...jobClaims(options.provider, verified.claims)
212
+ };
213
+ return freezeDeep({
214
+ principal,
215
+ context: {}
216
+ });
217
+ }
218
+ //#endregion
219
+ //#region src/jwt/dpop.ts
220
+ const DPOP_WINDOW_SECONDS = 60;
221
+ const PROOF_ALGS = /* @__PURE__ */ new Set([
222
+ "ES256",
223
+ "PS256",
224
+ "Ed25519",
225
+ "EdDSA",
226
+ "RS256"
227
+ ]);
228
+ const PRIVATE_MEMBERS = [
229
+ "d",
230
+ "p",
231
+ "q",
232
+ "dp",
233
+ "dq",
234
+ "qi",
235
+ "k"
236
+ ];
237
+ function headerOf(request) {
238
+ return request.headers.get("DPoP") ?? request.headers.get("dpop");
239
+ }
240
+ function requestUrl(request) {
241
+ const url = new URL(request.url);
242
+ url.hash = "";
243
+ return url.href;
244
+ }
245
+ function verifyDpopProof(request, claims, accessToken) {
246
+ return verify(request, claims, accessToken);
247
+ }
248
+ async function verify(request, claims, accessToken) {
249
+ const proof = headerOf(request);
250
+ if (proof === null || proof.length === 0) return {
251
+ ok: false,
252
+ cause: "dpop-proof-invalid"
253
+ };
254
+ const expectedJkt = claims["cnf"] !== null && typeof claims["cnf"] === "object" && !Array.isArray(claims["cnf"]) && typeof claims["cnf"].jkt === "string" ? claims["cnf"].jkt : void 0;
255
+ if (expectedJkt === void 0) return {
256
+ ok: false,
257
+ cause: "dpop-proof-invalid"
258
+ };
259
+ const header = decodeHeader(proof);
260
+ if (header?.typ?.toLowerCase() !== "dpop+jwt") return {
261
+ ok: false,
262
+ cause: "dpop-proof-invalid"
263
+ };
264
+ const jwk = header["jwk"];
265
+ if (!PROOF_ALGS.has(header.alg ?? "") || jwk === null || typeof jwk !== "object" || Array.isArray(jwk) || PRIVATE_MEMBERS.some((member) => member in jwk)) return {
266
+ ok: false,
267
+ cause: "dpop-proof-invalid"
268
+ };
269
+ try {
270
+ const jose = await loadJose();
271
+ const key = await jose.importJWK(jwk, header.alg);
272
+ const result = await jose.jwtVerify(proof, key, {
273
+ typ: "dpop+jwt",
274
+ maxTokenAge: DPOP_WINDOW_SECONDS
275
+ });
276
+ if (await jose.calculateJwkThumbprint(jwk, "sha256") !== expectedJkt) return {
277
+ ok: false,
278
+ cause: "dpop-proof-invalid"
279
+ };
280
+ const htm = result.payload["htm"];
281
+ const htu = result.payload["htu"];
282
+ if (htm !== request.method || htu !== requestUrl(request)) return {
283
+ ok: false,
284
+ cause: "dpop-proof-invalid"
285
+ };
286
+ if (accessToken !== void 0) {
287
+ const ath = bytesToBase64Url(sha256(accessToken));
288
+ if (result.payload["ath"] !== ath) return {
289
+ ok: false,
290
+ cause: "dpop-proof-invalid"
291
+ };
292
+ }
293
+ return { ok: true };
294
+ } catch {
295
+ return {
296
+ ok: false,
297
+ cause: "dpop-proof-invalid"
298
+ };
299
+ }
300
+ }
301
+ //#endregion
302
+ //#region src/jwt/introspection.ts
303
+ function emitAuth$1(options, cause) {
304
+ if (options.onAuth === void 0) return;
305
+ options.onAuth(compact({
306
+ reason: "invalid-token",
307
+ cause,
308
+ source: "jwt",
309
+ issuer: options.issuer,
310
+ requestId: options.requestId
311
+ }));
312
+ }
313
+ function isRecord$1(value) {
314
+ return value !== null && typeof value === "object" && !Array.isArray(value);
315
+ }
316
+ function keyToCnf(key) {
317
+ if (!isRecord$1(key)) return;
318
+ if (isRecord$1(key["jwk"])) return { jwk: key["jwk"] };
319
+ return { jwk: key };
320
+ }
321
+ function introspectionToClaims(body) {
322
+ const cnf = keyToCnf(body["key"]);
323
+ return compact({
324
+ sub: typeof body["sub"] === "string" ? body["sub"] : void 0,
325
+ iss: typeof body["iss"] === "string" ? body["iss"] : void 0,
326
+ aud: body["aud"],
327
+ exp: typeof body["exp"] === "number" ? body["exp"] : void 0,
328
+ iat: typeof body["iat"] === "number" ? body["iat"] : void 0,
329
+ nbf: typeof body["nbf"] === "number" ? body["nbf"] : void 0,
330
+ jti: typeof body["jti"] === "string" ? body["jti"] : void 0,
331
+ scope: typeof body["scope"] === "string" ? body["scope"] : void 0,
332
+ authorization_details: body["authorization_details"],
333
+ access: body["access"],
334
+ client_id: typeof body["client_id"] === "string" ? body["client_id"] : void 0,
335
+ roles: body["roles"],
336
+ groups: body["groups"],
337
+ entitlements: body["entitlements"],
338
+ sid: typeof body["sid"] === "string" ? body["sid"] : void 0,
339
+ acr: typeof body["acr"] === "string" ? body["acr"] : void 0,
340
+ amr: body["amr"],
341
+ auth_time: body["auth_time"],
342
+ act: body["act"],
343
+ cnf
344
+ });
345
+ }
346
+ function instanceActor(body) {
347
+ const id = typeof body["instance_id"] === "string" ? body["instance_id"] : typeof body["client_id"] === "string" ? body["client_id"] : void 0;
348
+ if (id === void 0) return;
349
+ return {
350
+ id,
351
+ kind: "oauth-client"
352
+ };
353
+ }
354
+ function attachActor(subject, body, binding) {
355
+ if (subject.actor !== void 0) return subject;
356
+ const actor = instanceActor(body);
357
+ if (actor === void 0) return subject;
358
+ const principal = subject.principal;
359
+ if (principal === null) return subject;
360
+ return freezeDeep({
361
+ ...subject,
362
+ principal: freezeDeep(compact({
363
+ ...principal,
364
+ binding: void 0
365
+ })),
366
+ actor: freezeDeep(compact({
367
+ ...actor,
368
+ binding
369
+ }))
370
+ });
371
+ }
372
+ /**
373
+ * RFC 7662 leaves `aud` and `iss` optional; a response that names another
374
+ * resource server or issuer than the one configured is not for this API.
375
+ */
376
+ function boundToConfig(body, options) {
377
+ if (options.issuer !== void 0 && body["iss"] !== void 0 && body["iss"] !== options.issuer) return false;
378
+ if (options.audience === void 0) return true;
379
+ const expected = Array.isArray(options.audience) ? options.audience : [options.audience];
380
+ const aud = body["aud"];
381
+ return (typeof aud === "string" ? [aud] : Array.isArray(aud) ? aud : []).some((item) => expected.includes(item));
382
+ }
383
+ function subjectFromIntrospection(response, options = {}) {
384
+ try {
385
+ if (!isRecord$1(response) || response["active"] !== true || !boundToConfig(response, options)) return anonymousSubject();
386
+ const mapped = mapClaimsToSubject(introspectionToClaims(response), options);
387
+ if (mapped.invalidChain) {
388
+ emitAuth$1(options, "invalid-chain");
389
+ return anonymousSubject();
390
+ }
391
+ if (mapped.subject.principal === null) return anonymousSubject();
392
+ return attachActor(mapped.subject, response, mapped.subject.principal.binding);
393
+ } catch {
394
+ return anonymousSubject();
395
+ }
396
+ }
397
+ //#endregion
398
+ //#region src/jwt/signer.ts
399
+ const SIGNING_ALGS = /* @__PURE__ */ new Set([
400
+ "ES256",
401
+ "PS256",
402
+ "Ed25519",
403
+ "RS256"
404
+ ]);
405
+ function isRecord(value) {
406
+ return value !== null && typeof value === "object" && !Array.isArray(value);
407
+ }
408
+ function publicJwk(key) {
409
+ const { d: _d, p: _p, q: _q, dp: _dp, dq: _dq, qi: _qi, k: _k, ...pub } = key;
410
+ return pub;
411
+ }
412
+ function joseTokenSigner(options) {
413
+ if (options.alg === "HS256" || options.alg === "EdDSA") throw new Error("PermDock: joseTokenSigner refuses HS* and polymorphic EdDSA on outputs.");
414
+ if (!SIGNING_ALGS.has(options.alg)) throw new Error(`PermDock: unsupported signing alg '${options.alg}'.`);
415
+ if (options.kid.length === 0) throw new Error("PermDock: joseTokenSigner requires kid.");
416
+ const importKey = async () => {
417
+ if (options.key instanceof Uint8Array) throw new TypeError("PermDock: HMAC keys cannot sign PermDock outputs.");
418
+ return (await loadJose()).importJWK(options.key, options.alg);
419
+ };
420
+ return {
421
+ kid: options.kid,
422
+ sign(payload, signOptions) {
423
+ return signJwt(payload, signOptions);
424
+ },
425
+ jwks() {
426
+ if (isRecord(options.key)) return Promise.resolve({ keys: [publicJwk(options.key)] });
427
+ return Promise.resolve({ keys: [] });
428
+ }
429
+ };
430
+ async function signJwt(payload, signOptions) {
431
+ const jose = await loadJose();
432
+ const key = await importKey();
433
+ const now = Math.floor(Date.now() / 1e3);
434
+ const jwt = new jose.SignJWT({ ...payload });
435
+ jwt.setProtectedHeader({
436
+ alg: options.alg,
437
+ kid: options.kid,
438
+ typ: signOptions.typ
439
+ });
440
+ jwt.setIssuedAt(now);
441
+ jwt.setJti(globalThis.crypto.randomUUID());
442
+ if (options.issuer !== void 0) jwt.setIssuer(options.issuer);
443
+ if (signOptions.audience !== void 0) jwt.setAudience(signOptions.audience);
444
+ jwt.setExpirationTime(signOptions.expiresAt ?? now + 3600);
445
+ return jwt.sign(key);
446
+ }
447
+ }
448
+ //#endregion
449
+ //#region src/jwt/subject.ts
450
+ function emitAuth(options, cause, token) {
451
+ if (options.onAuth === void 0) return;
452
+ const header = token === void 0 ? void 0 : decodeHeader(token);
453
+ options.onAuth(compact({
454
+ reason: "invalid-token",
455
+ cause,
456
+ source: "jwt",
457
+ kid: header?.kid,
458
+ alg: header?.alg,
459
+ typ: header?.typ,
460
+ issuer: options.issuer,
461
+ requestId: options.requestId
462
+ }));
463
+ }
464
+ function tokenInQuery(request) {
465
+ if (request === void 0) return false;
466
+ return new URL(request.url, "https://permdock.invalid").searchParams.has("access_token");
467
+ }
468
+ function mtlsThumbprint(claims) {
469
+ const cnf = claims["cnf"];
470
+ if (cnf === null || typeof cnf !== "object" || Array.isArray(cnf)) return;
471
+ const value = cnf["x5t#S256"];
472
+ return typeof value === "string" ? value : void 0;
473
+ }
474
+ async function extraMemberships(options, subject, tenant) {
475
+ if (options.memberships === void 0 || subject.principal === null) return subject;
476
+ try {
477
+ const extra = await options.memberships.membershipsFor(compact({
478
+ id: subject.principal.id,
479
+ kind: subject.principal.kind
480
+ }), compact({ tenant }));
481
+ if (extra.length === 0) return subject;
482
+ const merged = [...subject.principal.memberships ?? [], ...extra];
483
+ return freezeDeep({
484
+ ...subject,
485
+ principal: {
486
+ ...subject.principal,
487
+ memberships: merged
488
+ }
489
+ });
490
+ } catch {
491
+ return subject;
492
+ }
493
+ }
494
+ function subjectFromJwt(token, options, request) {
495
+ return resolveSubject(token, options, request);
496
+ }
497
+ function createJwtSubjectResolver(options) {
498
+ assertSubjectConfig(options);
499
+ const verifier = options.verifier ?? joseTokenVerifier(options);
500
+ return (token, request) => resolveSubject(token, {
501
+ ...options,
502
+ verifier
503
+ }, request);
504
+ }
505
+ async function resolveSubject(token, options, request) {
506
+ if (options.verifier === void 0) assertSubjectConfig(options);
507
+ if (token === void 0 || token === null || token.length === 0) return anonymousSubject();
508
+ if (options.profile === "fapi2" && tokenInQuery(request)) {
509
+ emitAuth(options, "token-in-query", token);
510
+ return anonymousSubject();
511
+ }
512
+ const verifier = options.verifier ?? joseTokenVerifier(options);
513
+ const issuer = options.issuer ?? (options.discovery === void 0 ? void 0 : issuerFromDiscovery(options.discovery));
514
+ let verified;
515
+ try {
516
+ verified = await verifier.verify(token, compact({
517
+ audience: options.audience,
518
+ issuer,
519
+ clockTolerance: options.clockTolerance,
520
+ typ: options.accept === "id-token" ? ["JWT"] : options.profile === "fapi2" ? "at+jwt" : ["at+jwt", "JWT"]
521
+ }));
522
+ } catch {
523
+ verified = fail("malformed");
524
+ }
525
+ if (!verified.ok) {
526
+ emitAuth(options, verified.cause, token);
527
+ return anonymousSubject();
528
+ }
529
+ if (acceptMismatch(verified.claims, verified.header.typ, options, options.audience)) {
530
+ emitAuth(options, "wrong-token-type", token);
531
+ return anonymousSubject();
532
+ }
533
+ const sender = options.sender ?? (options.profile === "fapi2" ? "dpop" : "none");
534
+ const cnf = verified.claims["cnf"];
535
+ const hasCnf = cnf !== null && typeof cnf === "object";
536
+ if (options.profile === "fapi2" && !hasCnf) {
537
+ emitAuth(options, "sender-constraint-required", token);
538
+ return anonymousSubject();
539
+ }
540
+ if (sender === "dpop") {
541
+ const proof = request === void 0 ? {
542
+ ok: false,
543
+ cause: "dpop-proof-invalid"
544
+ } : await verifyDpopProof(request, verified.claims, token);
545
+ if (!proof.ok) {
546
+ emitAuth(options, proof.cause, token);
547
+ return anonymousSubject();
548
+ }
549
+ }
550
+ if (sender === "mtls") {
551
+ const expected = options.certificateThumbprint;
552
+ const seen = mtlsThumbprint(verified.claims);
553
+ if (expected === void 0 || seen !== expected) {
554
+ emitAuth(options, "mtls-binding-mismatch", token);
555
+ return anonymousSubject();
556
+ }
557
+ }
558
+ const mapped = mapClaimsToSubject(verified.claims, options);
559
+ if (mapped.invalidChain) {
560
+ emitAuth(options, "invalid-chain", token);
561
+ return anonymousSubject();
562
+ }
563
+ if (mapped.subject.principal === null) {
564
+ emitAuth(options, "invalid-claims", token);
565
+ return anonymousSubject();
566
+ }
567
+ if (mapped.invalidClaims) emitAuth(options, "invalid-claims", token);
568
+ return extraMemberships(options, mapped.subject, mapped.subject.principal.tenant);
569
+ }
570
+ //#endregion
571
+ export { createJwtSubjectResolver, joseTokenSigner, joseTokenVerifier, subjectFromCapability, subjectFromCiOidc, subjectFromIntrospection, subjectFromJwt, verifyDpopProof };