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,194 @@
1
+ import { Qt as PermDockOptions, at as LimitStore, cr as CustomRole, ft as RelationSource, hr as Subject, ir as Actor, mr as Principal, pr as Membership, ur as Delegation } from "../../policy-CInmNGkM.js";
2
+ import { d as Permission } from "../../permissions-B4apnahQ.js";
3
+ import { a as SaasProject, c as saasPlans, i as SaasFolderSchema, l as saasRoles, n as SaasDocSchema, o as SaasProjectSchema, r as SaasFolder, s as saasPermissions, t as SaasDoc, u as saasTenantRoleNames } from "../../permissions-B8vCg_bI.js";
4
+ import { n as saasPolicy, t as SAAS_API_KEY_LIMIT } from "../../policy-Cq2fB8Q5.js";
5
+ import { StandardSchemaV1 } from "@standard-schema/spec";
6
+ //#region src/testing/saas/schema.d.ts
7
+ type FieldKind = "string" | "boolean" | "nullable-string";
8
+ type FieldValue<K extends FieldKind> = K extends "string" ? string : K extends "boolean" ? boolean : string | null;
9
+ type Shape = {
10
+ readonly [field: string]: FieldKind;
11
+ };
12
+ type Infer<S extends Shape> = { [K in keyof S]: FieldValue<S[K]>; };
13
+ /** A dependency-free Standard Schema for flat fixture rows. */
14
+ export declare function rowSchema<const S extends Shape>(shape: S): StandardSchemaV1<Infer<S>>;
15
+ //#endregion
16
+ //#region src/testing/saas/seed.d.ts
17
+ type SaasPlan = "free" | "pro";
18
+ type SaasOrg = {
19
+ readonly id: string;
20
+ readonly name: string;
21
+ readonly plan: SaasPlan;
22
+ readonly customRoles: readonly CustomRole[];
23
+ };
24
+ type SaasMember = {
25
+ readonly user: string;
26
+ /** Absent on a resource-scoped membership, which carries only `on`. */
27
+ readonly tenant?: string;
28
+ readonly team?: string;
29
+ readonly on?: {
30
+ readonly resource: string;
31
+ readonly id: string;
32
+ };
33
+ readonly roles: readonly string[];
34
+ readonly expiresAt?: number;
35
+ };
36
+ /** One edge-table row: `user` holds `relation` on `folder`. */
37
+ type SaasShare = {
38
+ readonly folder: string;
39
+ readonly user: string;
40
+ readonly relation: "viewer" | "editor";
41
+ readonly expiresAt?: number;
42
+ };
43
+ type SaasSeed = {
44
+ readonly orgs: readonly SaasOrg[];
45
+ readonly members: readonly SaasMember[];
46
+ readonly projects: readonly SaasProject[];
47
+ readonly docs: readonly SaasDoc[];
48
+ readonly folders: readonly SaasFolder[];
49
+ readonly shares: readonly SaasShare[];
50
+ };
51
+ /** Epoch seconds in the past, so the membership is expired for any clock. */
52
+ export declare const SAAS_EXPIRED_AT = 1e9;
53
+ /**
54
+ * Users, one hazard each:
55
+ * - alice: admin in acme, viewer in globex (different role per org)
56
+ * - bob: member in acme (owns p1, p3, p4)
57
+ * - carol: owner in acme
58
+ * - dave: custom `contractor` role in acme (includes member)
59
+ * - erin: admin in acme AND globex (same role in two orgs)
60
+ * - frank: expired acme membership
61
+ * - mallory: no memberships at all
62
+ * - gina: `lead` of team-a in acme
63
+ * - hank: viewer in acme, `collaborator` on project p3 only
64
+ * - `user-2` and `2`: members of `org-1`; `Date.parse` maps both ids to one instant
65
+ * - tina: member of `tenant-1`; `Date.parse('org-1') === Date.parse('tenant-1')`
66
+ * - ivan: viewer in acme who holds the team role `lead` on the tenant membership (the wrong scope)
67
+ *
68
+ * Acme's folders: `root` ─ `eng` ─ `platform` ─ `infra`, and `root` ─ `hr`
69
+ * (restricted) ─ `payroll`. bob views `root`, hank views `hr`, gina edits
70
+ * `eng`, frank's view of `root` expired.
71
+ */
72
+ export declare const saasSeed: SaasSeed;
73
+ /** The seed's folder tree and shares as a `RelationSource`, for `createPermDock({ relations })`. */
74
+ export declare function saasRelations(seed?: SaasSeed): RelationSource;
75
+ /** Every user id in the seed. */
76
+ export declare const saasUsers: readonly string[];
77
+ export declare function saasOrg(id: string): SaasOrg | undefined;
78
+ /** Memberships of `user` as the PermDock `Membership` shape. */
79
+ export declare function saasMemberships(user: string, members?: readonly SaasMember[]): Membership[];
80
+ /** Custom roles of every org, as `createPermDock({ customRoles })` expects. */
81
+ export declare const saasCustomRoles: readonly CustomRole[];
82
+ /**
83
+ * The principal for `user`, with the plans of the requested `tenant`'s org.
84
+ * The tenant itself is passed to `createPermDock({ tenant })`, never trusted
85
+ * from here.
86
+ */
87
+ export declare function saasPrincipal(user: string, tenant?: string): Principal;
88
+ //#endregion
89
+ //#region src/testing/saas/sql.d.ts
90
+ /**
91
+ * Postgres tables for the SaaS domain. Column names match the resource
92
+ * fields (`"orgId"`, `"ownerId"`) so generated RLS and ORM filters compile
93
+ * against them without a column map. RLS is enabled and forced on the row
94
+ * tables; policies come from `permdock rls generate`.
95
+ */
96
+ export declare const saasSchemaSql = "\ncreate table org (\n id text primary key,\n name text not null,\n plan text not null check (plan in ('free', 'pro'))\n);\ncreate table org_member (\n user_id text not null,\n org_id text references org (id),\n team_id text,\n resource text,\n resource_id text,\n role text not null,\n expires_at bigint\n);\ncreate table project (\n id text primary key,\n \"orgId\" text not null references org (id),\n \"ownerId\" text not null,\n name text not null,\n archived boolean not null default false\n);\nalter table project enable row level security;\nalter table project force row level security;\ncreate table doc (\n id text primary key,\n \"orgId\" text not null references org (id),\n \"teamId\" text,\n title text not null,\n locked boolean not null default false\n);\nalter table doc enable row level security;\nalter table doc force row level security;\ncreate table folder (\n id text primary key,\n \"orgId\" text not null references org (id),\n \"parentId\" text references folder (id),\n name text not null,\n restricted boolean not null default false\n);\nalter table folder enable row level security;\nalter table folder force row level security;\ncreate table folder_share (\n folder_id text not null references folder (id) on delete cascade,\n user_id text not null,\n expires_at timestamptz\n);\ncreate table folder_editor (\n folder_id text not null references folder (id) on delete cascade,\n user_id text not null\n);\n";
97
+ /** `insert` statements for a seed; the default is the full shared seed. */
98
+ export declare function saasSeedSql(seed?: SaasSeed): string;
99
+ //#endregion
100
+ //#region src/testing/saas/tokens.d.ts
101
+ type EcJwk = {
102
+ readonly kty: "EC";
103
+ readonly crv: "P-256";
104
+ readonly x: string;
105
+ readonly y: string;
106
+ readonly kid: string;
107
+ readonly alg: "ES256";
108
+ readonly use: "sig";
109
+ };
110
+ export declare const saasPublicJwk: EcJwk;
111
+ export declare const saasPrivateJwk: EcJwk & {
112
+ readonly d: string;
113
+ };
114
+ export declare const saasJwks: Readonly<{
115
+ keys: EcJwk[];
116
+ }>;
117
+ export declare const saasIssuer = "https://saas.permdock.test";
118
+ export declare const saasAudience = "permdock-saas";
119
+ export declare const SAAS_TOKEN_TTL_SECONDS = 3600;
120
+ type SaasTokenOptions = {
121
+ /** Claim memberships; `false` omits the claim (database mode). Defaults to the seed. */
122
+ readonly memberships?: readonly Membership[] | false;
123
+ readonly ttl?: number;
124
+ /** Epoch seconds used for `iat`. */
125
+ readonly now?: number;
126
+ readonly issuer?: string;
127
+ readonly audience?: string;
128
+ readonly claims?: Readonly<Record<string, unknown>>;
129
+ };
130
+ /** Signs an ES256 access token for `sub` with WebCrypto; no dependency. */
131
+ export declare function signSaasToken(sub: string, options?: SaasTokenOptions): Promise<string>;
132
+ /**
133
+ * Verifies a token from `signSaasToken` (ES256, `kid`, `iss`, `aud`, `exp`)
134
+ * and returns its `sub`, or `null`; never throws. Identity only: memberships
135
+ * and plans come from the seed, never from the token.
136
+ */
137
+ export declare function verifySaasToken(token: string | null | undefined, now?: number): Promise<string | null>;
138
+ /** `verifySaasToken` plus the token's `exp` as `expiresAt` (epoch seconds). */
139
+ export declare function verifySaasSession(token: string | null | undefined, now?: number): Promise<{
140
+ readonly sub: string;
141
+ readonly expiresAt: number;
142
+ } | null>;
143
+ //#endregion
144
+ //#region src/testing/saas/scenarios.d.ts
145
+ type SaasOutcome = "granted" | "denied" | "approval-required";
146
+ type SaasScenario = {
147
+ readonly name: string;
148
+ readonly user: string;
149
+ /** The requested tenant, as a route or header would pass it. */
150
+ readonly tenant?: string;
151
+ readonly permission: Permission;
152
+ readonly row?: SaasProject | SaasDoc | SaasFolder;
153
+ readonly expected: {
154
+ readonly outcome: SaasOutcome;
155
+ /** One reason that must appear among the denials. */
156
+ readonly reason?: string;
157
+ };
158
+ /**
159
+ * `false` when the outcome depends on server-only inputs (a quota store,
160
+ * approvals), so a snapshot client is not expected to match.
161
+ */
162
+ readonly client?: boolean;
163
+ /**
164
+ * The client outcome when it is stricter than the server's: a snapshot
165
+ * cannot evaluate a closure deny, so it fails closed.
166
+ */
167
+ readonly clientOutcome?: SaasOutcome;
168
+ /** An agent acting for `user`; without `delegation` it reaches nothing. */
169
+ readonly actor?: Actor;
170
+ readonly delegation?: Delegation;
171
+ /** Units of the daily api-key quota this subject already used in the tenant. */
172
+ readonly quotaUsed?: number;
173
+ };
174
+ /** What the policy's `subject` receives: the principal, or a `Subject` carrying the actor. */
175
+ export declare function saasUser(scenario: SaasScenario): Principal | Subject;
176
+ /** A memory quota store in which every subject has already used `used` units. */
177
+ export declare function saasLimitStore(used?: number): LimitStore;
178
+ /** The `createPermDock` options a scenario runs with: tenant, custom roles, quota and folder tree. */
179
+ export declare function saasScenarioOptions(scenario: SaasScenario): PermDockOptions;
180
+ export declare function saasProject(id: string): SaasProject;
181
+ export declare function saasDoc(id: string): SaasDoc;
182
+ export declare function saasFolder(id: string): SaasFolder;
183
+ /**
184
+ * The folder tree, decided with `createPermDock({ relations: saasRelations() })`.
185
+ * A snapshot carries no graph, so every graph grant is server-only on a client.
186
+ */
187
+ export declare const saasFolderScenarios: readonly SaasScenario[];
188
+ /**
189
+ * Hand-written expectations. Never derive `expected` from the engine: the
190
+ * list is the oracle every adapter, ORM and client suite runs against.
191
+ */
192
+ export declare const saasScenarios: readonly SaasScenario[];
193
+ //#endregion
194
+ export { SAAS_API_KEY_LIMIT, type SaasDoc, SaasDocSchema, type SaasFolder, SaasFolderSchema, type SaasMember, type SaasOrg, type SaasOutcome, type SaasPlan, type SaasProject, SaasProjectSchema, type SaasScenario, type SaasSeed, type SaasShare, type SaasTokenOptions, saasPermissions, saasPlans, saasPolicy, saasRoles, saasTenantRoleNames };
@@ -0,0 +1,3 @@
1
+ import { a as saasPlans, c as rowSchema, i as saasPermissions, n as SaasFolderSchema, o as saasRoles, r as SaasProjectSchema, s as saasTenantRoleNames, t as SaasDocSchema } from "../../permissions-CofRqesP.js";
2
+ import { C as saasOrg, D as saasUsers, E as saasSeed, O as SAAS_API_KEY_LIMIT, S as saasMemberships, T as saasRelations, _ as verifySaasToken, a as saasProject, b as SAAS_EXPIRED_AT, c as saasUser, d as saasIssuer, f as saasJwks, g as verifySaasSession, h as signSaasToken, i as saasLimitStore, k as saasPolicy, l as SAAS_TOKEN_TTL_SECONDS, m as saasPublicJwk, n as saasFolder, o as saasScenarioOptions, p as saasPrivateJwk, r as saasFolderScenarios, s as saasScenarios, t as saasDoc, u as saasAudience, v as saasSchemaSql, w as saasPrincipal, x as saasCustomRoles, y as saasSeedSql } from "../../saas-BRrZzJkM.js";
3
+ export { SAAS_API_KEY_LIMIT, SAAS_EXPIRED_AT, SAAS_TOKEN_TTL_SECONDS, SaasDocSchema, SaasFolderSchema, SaasProjectSchema, rowSchema, saasAudience, saasCustomRoles, saasDoc, saasFolder, saasFolderScenarios, saasIssuer, saasJwks, saasLimitStore, saasMemberships, saasOrg, saasPermissions, saasPlans, saasPolicy, saasPrincipal, saasPrivateJwk, saasProject, saasPublicJwk, saasRelations, saasRoles, saasScenarioOptions, saasScenarios, saasSchemaSql, saasSeed, saasSeedSql, saasTenantRoleNames, saasUser, saasUsers, signSaasToken, verifySaasSession, verifySaasToken };
@@ -0,0 +1,2 @@
1
+ import { a as SaasProject, c as saasPlans, i as SaasFolderSchema, l as saasRoles, n as SaasDocSchema, o as SaasProjectSchema, r as SaasFolder, s as saasPermissions, t as SaasDoc, u as saasTenantRoleNames } from "../../permissions-B8vCg_bI.js";
2
+ export { SaasDoc, SaasDocSchema, SaasFolder, SaasFolderSchema, SaasProject, SaasProjectSchema, saasPermissions, saasPlans, saasRoles, saasTenantRoleNames };
@@ -0,0 +1,2 @@
1
+ import { a as saasPlans, i as saasPermissions, n as SaasFolderSchema, o as saasRoles, r as SaasProjectSchema, s as saasTenantRoleNames, t as SaasDocSchema } from "../../permissions-CofRqesP.js";
2
+ export { SaasDocSchema, SaasFolderSchema, SaasProjectSchema, saasPermissions, saasPlans, saasRoles, saasTenantRoleNames };
@@ -0,0 +1,15 @@
1
+ import { createTwoFilesPatch } from "diff";
2
+ //#region src/cli/text-diff.ts
3
+ const MAX_LINES = 40;
4
+ /**
5
+ * A unified diff from the file on disk to what the command would write,
6
+ * cut to the first {@link MAX_LINES} lines so a CI log stays readable.
7
+ */
8
+ function shortDiff(file, onDisk, next) {
9
+ const lines = createTwoFilesPatch(`${file} (on disk)`, `${file} (generated)`, onDisk, next, void 0, void 0, { context: 2 }).split("\n").filter((line) => !line.startsWith("=====")).filter((line, index, all) => line !== "" || index < all.length - 1);
10
+ if (lines.length <= MAX_LINES) return lines.join("\n");
11
+ const rest = lines.length - MAX_LINES;
12
+ return [...lines.slice(0, MAX_LINES), `… ${rest} more diff line${rest === 1 ? "" : "s"}`].join("\n");
13
+ }
14
+ //#endregion
15
+ export { shortDiff as t };
@@ -0,0 +1,10 @@
1
+ //#region src/core/thenable.ts
2
+ function isThenable(value) {
3
+ return value !== null && typeof value === "object" && "then" in value && typeof value.then === "function";
4
+ }
5
+ /** Settles a promise nobody awaits, so its rejection is not reported as unhandled. */
6
+ function ignoreRejection(value) {
7
+ Promise.resolve(value).then(void 0, () => void 0);
8
+ }
9
+ //#endregion
10
+ export { isThenable as n, ignoreRejection as t };
@@ -0,0 +1,8 @@
1
+ //#region src/core/timeout.ts
2
+ /** Aborts after `ms`, or earlier when `signal` aborts. */
3
+ function timeoutSignal(ms, signal) {
4
+ const deadline = AbortSignal.timeout(ms);
5
+ return signal === void 0 || signal === null ? deadline : AbortSignal.any([signal, deadline]);
6
+ }
7
+ //#endregion
8
+ export { timeoutSignal as t };
@@ -0,0 +1,80 @@
1
+ import { $ as DecisionSink, C as Policy, at as LimitStore, ct as MembershipSource, ft as RelationSource, mr as Principal, pt as RoleSource, sn as PolicySource, tt as EntitlementSource, xt as SnapshotSource } from "../policy-CInmNGkM.js";
2
+ import { d as Permission } from "../permissions-B4apnahQ.js";
3
+ import { f as ApprovalStore } from "../types-B8w5PFtS.js";
4
+ import { n as RevocationFeed } from "../revocations-Cy06JNx2.js";
5
+ import { r as PdpFactory } from "../types-BvBk1wgn.js";
6
+ import { S as ConnectionOptions, b as Connection, h as WebBotAuthVerifier, n as OpenApiHooks, o as TenantOption } from "../create-BKF3dgFk.js";
7
+ import { t as StreamProtectOptions } from "../stream-BhMfZOwr.js";
8
+ import { AnyTRPCMiddlewareFunction } from "@trpc/server";
9
+ //#region src/trpc/create.d.ts
10
+ type TrpcMiddlewareOpts<TCtx = object, TInput = unknown> = {
11
+ readonly ctx: TCtx;
12
+ readonly input?: TInput;
13
+ readonly path: string;
14
+ readonly type: string;
15
+ readonly next: (opts?: {
16
+ readonly ctx: TCtx;
17
+ }) => Promise<unknown>;
18
+ };
19
+ type TrpcMiddleware = AnyTRPCMiddlewareFunction;
20
+ type TrpcPermDockOptions<TCtx = object, TUser = unknown> = {
21
+ readonly subject: (opts: TrpcMiddlewareOpts<TCtx>) => TUser | Promise<TUser>;
22
+ readonly tenant?: TenantOption<TrpcMiddlewareOpts<TCtx>>;
23
+ /** The Web `Request` behind a context; defaults to `ctx.request` or `ctx.req`. */
24
+ readonly request?: (ctx: TCtx) => Request | null | undefined;
25
+ readonly memberships?: MembershipSource | readonly MembershipSource[];
26
+ /** The object graph for relation grants that walk a parent chain; without it they deny. */
27
+ readonly relations?: RelationSource;
28
+ readonly entitlements?: EntitlementSource;
29
+ readonly customRoles?: RoleSource;
30
+ /** Hosted grants, read once per instance; see `PolicySource`. */
31
+ readonly policies?: PolicySource;
32
+ readonly store?: ApprovalStore;
33
+ readonly sink?: DecisionSink;
34
+ readonly limits?: LimitStore;
35
+ /** `createPermDock` from `permdock/pdp`; `protect` then decides delegated permissions remotely. */
36
+ readonly pdp?: PdpFactory;
37
+ /** Accepted for adapter parity; not read by this adapter. */
38
+ readonly snapshots?: SnapshotSource;
39
+ /** `(request) => verifyWebBotAuth(request, options)`; a verified bot becomes the actor. */
40
+ readonly webBotAuth?: WebBotAuthVerifier;
41
+ /** Ends or revalidates open subscriptions. */
42
+ readonly revocations?: RevocationFeed;
43
+ };
44
+ type TrpcOpenApiHooks = {
45
+ readonly security: (permission: Permission) => {
46
+ readonly openapi: {
47
+ readonly protect: true;
48
+ readonly security: readonly Record<string, readonly string[]>[];
49
+ readonly "x-permdock-permissions": readonly string[];
50
+ };
51
+ };
52
+ readonly securitySchemes: OpenApiHooks["securitySchemes"];
53
+ };
54
+ type TrpcPermDock<TCtx = object> = {
55
+ readonly permdock: () => TrpcMiddleware;
56
+ readonly protect: (permission: Permission, loadData?: (opts: TrpcMiddlewareOpts<TCtx>) => unknown, protectOptions?: StreamProtectOptions) => TrpcMiddleware;
57
+ /** A long-lived connection for the request behind `ctx`. */
58
+ readonly connection: (opts: TrpcMiddlewareOpts<TCtx>, connectionOptions?: ConnectionOptions) => Promise<Connection>;
59
+ readonly permdockHandler: (request: Request) => Promise<Response>;
60
+ readonly openapi: TrpcOpenApiHooks;
61
+ readonly errorFormatter: <TShape extends {
62
+ readonly data: object;
63
+ }>(opts: {
64
+ readonly shape: TShape;
65
+ readonly error: {
66
+ readonly cause?: unknown;
67
+ };
68
+ }) => TShape;
69
+ };
70
+ export declare function errorFormatter<TShape extends {
71
+ readonly data: object;
72
+ }>(opts: {
73
+ readonly shape: TShape;
74
+ readonly error: {
75
+ readonly cause?: unknown;
76
+ };
77
+ }): TShape;
78
+ export declare function createPermDock<TCtx = object, TUser = unknown, TPrincipal extends Principal = Principal>(policy: Policy<TUser, TPrincipal>, options: TrpcPermDockOptions<TCtx, TUser>): TrpcPermDock<TCtx>;
79
+ //#endregion
80
+ export type { TrpcMiddleware, TrpcMiddlewareOpts, TrpcOpenApiHooks, TrpcPermDock, TrpcPermDockOptions };
@@ -0,0 +1,205 @@
1
+ import { t as compact } from "../compact-y6vfu2_f.js";
2
+ import { o as invalidSignatureResponse } from "../evaluations-DsAU9ppl.js";
3
+ import { r as tenantScope, t as createKernel } from "../create-CSkhDU9T.js";
4
+ import { t as problemFromError } from "../map-error-RJ3ZsUyA.js";
5
+ import { n as guardIterable, r as isAsyncIterable } from "../stream-Q_xlB6Ko.js";
6
+ import { TRPCError, isTrackedEnvelope } from "@trpc/server";
7
+ //#region src/trpc/create.ts
8
+ function requestFromCtx(ctx) {
9
+ if ("request" in ctx && ctx.request instanceof Request) return ctx.request;
10
+ if ("req" in ctx && ctx.req instanceof Request) return ctx.req;
11
+ }
12
+ function problemMessage(cause, fallback) {
13
+ if (cause !== null && typeof cause === "object" && "detail" in cause && typeof cause.detail === "string" && cause.detail.length > 0) return cause.detail;
14
+ return fallback;
15
+ }
16
+ const PROBLEM = Symbol.for("permdock.problem");
17
+ function trpcCode(status) {
18
+ switch (status) {
19
+ case 400: return "BAD_REQUEST";
20
+ case 401: return "UNAUTHORIZED";
21
+ case 404: return "NOT_FOUND";
22
+ case 429: return "TOO_MANY_REQUESTS";
23
+ case 503: return "SERVICE_UNAVAILABLE";
24
+ default: return "FORBIDDEN";
25
+ }
26
+ }
27
+ /** A `TRPCError` for a revoked subscription; the Problem Details body rides on `cause`. */
28
+ function trpcErrorFrom(error) {
29
+ const problem = error.toProblemDetails();
30
+ const cause = { ...problem };
31
+ Object.defineProperty(cause, PROBLEM, {
32
+ value: true,
33
+ enumerable: true
34
+ });
35
+ return new TRPCError({
36
+ code: trpcCode(problem.status),
37
+ message: error.code,
38
+ cause
39
+ });
40
+ }
41
+ async function throwTrpcError(response) {
42
+ let cause;
43
+ try {
44
+ cause = await response.json();
45
+ } catch {
46
+ cause = { status: response.status };
47
+ }
48
+ if (cause !== null && typeof cause === "object") Object.defineProperty(cause, PROBLEM, {
49
+ value: true,
50
+ enumerable: true
51
+ });
52
+ const code = trpcCode(response.status);
53
+ throw new TRPCError({
54
+ code,
55
+ message: problemMessage(cause, code),
56
+ cause
57
+ });
58
+ }
59
+ /**
60
+ * A PermDock error thrown further down (an `assert` in a resolver) arrives as
61
+ * a failed middleware result; it becomes the same TRPCError `protect` throws.
62
+ */
63
+ function mapDownstream(result) {
64
+ if (result === null || typeof result !== "object" || result.ok !== false) return Promise.resolve(result);
65
+ const error = result.error;
66
+ const cause = error instanceof TRPCError && error.code === "INTERNAL_SERVER_ERROR" ? error.cause : void 0;
67
+ const mapped = problemFromError(cause);
68
+ return mapped === void 0 ? Promise.resolve(result) : throwTrpcError(mapped);
69
+ }
70
+ function errorFormatter(opts) {
71
+ const cause = opts.error.cause;
72
+ if (cause === null || typeof cause !== "object" || !(PROBLEM in cause)) return opts.shape;
73
+ const { [PROBLEM]: _brand, ...problem } = cause;
74
+ return {
75
+ ...opts.shape,
76
+ data: {
77
+ ...opts.shape.data,
78
+ ...problem
79
+ }
80
+ };
81
+ }
82
+ function createPermDock(policy, options) {
83
+ const optsByRequest = /* @__PURE__ */ new WeakMap();
84
+ const requestByCtx = /* @__PURE__ */ new WeakMap();
85
+ const kernel = createKernel(policy, compact({
86
+ subject: (request) => {
87
+ const opts = optsByRequest.get(request);
88
+ return opts === void 0 ? null : options.subject(opts);
89
+ },
90
+ memberships: options.memberships,
91
+ relations: options.relations,
92
+ entitlements: options.entitlements,
93
+ customRoles: options.customRoles,
94
+ policies: options.policies,
95
+ store: options.store,
96
+ sink: options.sink,
97
+ limits: options.limits,
98
+ pdp: options.pdp,
99
+ webBotAuth: options.webBotAuth,
100
+ revocations: options.revocations,
101
+ adapter: "trpc"
102
+ }));
103
+ const requestOf = (ctx) => {
104
+ if (options.request !== void 0) try {
105
+ return options.request(ctx) ?? void 0;
106
+ } catch {
107
+ return;
108
+ }
109
+ return requestFromCtx(ctx);
110
+ };
111
+ /**
112
+ * One `Request` per HTTP request, shared by every procedure in a batch. The
113
+ * subject reads the first procedure's opts; the tenant is resolved from each
114
+ * procedure's own opts in `scopeOf`, never through the shared `Request`.
115
+ */
116
+ const bind = (opts) => {
117
+ const ctx = opts.ctx;
118
+ const hit = requestByCtx.get(ctx);
119
+ if (hit !== void 0) return hit;
120
+ const request = requestOf(opts.ctx) ?? new Request(`http://localhost/trpc/${opts.path}`, { method: "POST" });
121
+ requestByCtx.set(ctx, request);
122
+ if (!optsByRequest.has(request)) optsByRequest.set(request, opts);
123
+ return request;
124
+ };
125
+ const scopeOf = (opts) => tenantScope(options.tenant, opts);
126
+ const attach = (ctx, request) => {
127
+ requestByCtx.set(ctx, request);
128
+ };
129
+ const permdock = () => (async (opts) => {
130
+ const request = bind(opts);
131
+ let instance;
132
+ try {
133
+ instance = await kernel.permdock(request, await scopeOf(opts));
134
+ } catch (error) {
135
+ const response = invalidSignatureResponse(error);
136
+ if (response !== void 0) return throwTrpcError(response);
137
+ throw error;
138
+ }
139
+ const nextCtx = {
140
+ ...opts.ctx,
141
+ permdock: instance
142
+ };
143
+ attach(nextCtx, request);
144
+ return mapDownstream(await opts.next({ ctx: nextCtx }));
145
+ });
146
+ const connection = async (opts, connectionOptions) => kernel.connection(bind(opts), connectionOptions, await scopeOf(opts));
147
+ /** Wraps a subscription's iterable so revocation ends it and unreadable items drop. */
148
+ const guardSubscription = async (result, opts, permission, loadData, protectOptions) => {
149
+ if (result === null || typeof result !== "object" || result.ok !== true || !isAsyncIterable(result.data)) return result;
150
+ const conn = await connection(opts, compact({
151
+ permission,
152
+ data: loadData
153
+ }));
154
+ return {
155
+ ...result,
156
+ data: guardIterable(result.data, conn, compact({
157
+ items: protectOptions?.items,
158
+ unwrap: (item) => isTrackedEnvelope(item) ? item[1] : item,
159
+ onRevoked: trpcErrorFrom
160
+ }))
161
+ };
162
+ };
163
+ const protect = (permission, loadData, protectOptions) => (async (opts) => {
164
+ const request = bind(opts);
165
+ const guard = await kernel.protect(permission, loadData === void 0 ? void 0 : () => loadData(opts), protectOptions)(request, await scopeOf(opts));
166
+ if (guard.ok) {
167
+ const nextCtx = {
168
+ ...opts.ctx,
169
+ permdock: guard.permdock,
170
+ permdockData: guard.data
171
+ };
172
+ attach(nextCtx, request);
173
+ return guardSubscription(await mapDownstream(await opts.next({ ctx: nextCtx })), opts, permission, loadData === void 0 ? void 0 : () => loadData(opts), protectOptions);
174
+ }
175
+ return throwTrpcError(guard.response);
176
+ });
177
+ const permdockHandler = (request) => {
178
+ const opts = {
179
+ ctx: { req: request },
180
+ path: "permdock",
181
+ type: "unknown",
182
+ next: (nextOpts) => Promise.resolve(nextOpts ?? { ctx: { req: request } })
183
+ };
184
+ bind(opts);
185
+ const { POST, GET } = kernel.permdockHandler(() => scopeOf(opts));
186
+ return Promise.resolve(request.method === "GET" ? GET(request) : POST(request));
187
+ };
188
+ const kernelOpenApi = kernel.openapi;
189
+ return {
190
+ permdock,
191
+ protect,
192
+ connection,
193
+ permdockHandler,
194
+ openapi: {
195
+ security: (permission) => ({ openapi: {
196
+ protect: true,
197
+ ...kernelOpenApi.security(permission)
198
+ } }),
199
+ securitySchemes: kernelOpenApi.securitySchemes
200
+ },
201
+ errorFormatter
202
+ };
203
+ }
204
+ //#endregion
205
+ export { createPermDock, errorFormatter };
@@ -0,0 +1,141 @@
1
+ import { U as Approver, hr as Subject, o as ApprovalStage, pr as Membership, qn as RelationGrantee, r as ApprovalMode } from "./policy-CInmNGkM.js";
2
+ //#region src/approvals/types.d.ts
3
+ type ApprovalStatus = "pending" | "approved" | "rejected" | "expired";
4
+ type ApprovalApprovers = {
5
+ /** Under `mode: 'any'` (the default). */
6
+ readonly by?: Approver | readonly Approver[];
7
+ readonly mode?: ApprovalMode;
8
+ /** Under `mode: 'all'` or `'sequential'`. */
9
+ readonly stages?: readonly ApprovalStage[];
10
+ /** `false` lets the request's principal approve it; absent means `true`. */
11
+ readonly distinct?: boolean;
12
+ /** Set when the approval no longer applies once the row's `version` changes. */
13
+ readonly staleOn?: "resource-change";
14
+ /** Distinct approvers of `by` needed before `status` becomes `approved`; absent means 1. */
15
+ readonly quorum?: number;
16
+ /** Who else may approve once the request has waited `after` (a duration such as `'4h'`) since `createdAt`. */
17
+ readonly escalation?: {
18
+ readonly after: string;
19
+ readonly to: Approver | readonly Approver[];
20
+ };
21
+ };
22
+ /** One recorded approval: who gave it, when, and under `stages` the index of the stage it counts for. */
23
+ type ApprovalSignature = {
24
+ readonly by: string;
25
+ readonly at: string;
26
+ readonly stage?: number;
27
+ };
28
+ type ApprovalSubjectSummary = {
29
+ readonly principal: {
30
+ readonly id: string;
31
+ readonly roles: readonly string[];
32
+ readonly tenant?: string;
33
+ } | null;
34
+ readonly actor?: {
35
+ readonly id: string;
36
+ readonly kind: string;
37
+ };
38
+ readonly session?: string;
39
+ readonly delegation?: {
40
+ readonly scopes?: readonly string[];
41
+ readonly authorizationDetails?: readonly unknown[];
42
+ };
43
+ };
44
+ type ApprovalRequest = {
45
+ readonly v: 1;
46
+ readonly token: string;
47
+ readonly permission: string;
48
+ readonly scope: string;
49
+ readonly resource: {
50
+ readonly type: string;
51
+ readonly id?: string;
52
+ };
53
+ readonly subject: ApprovalSubjectSummary;
54
+ readonly membership?: Membership;
55
+ readonly approvers?: ApprovalApprovers;
56
+ readonly detail: string;
57
+ readonly adapter?: string;
58
+ readonly createdAt: string;
59
+ readonly expiresAt: string;
60
+ readonly status: ApprovalStatus;
61
+ /** Approvals given so far, oldest first; the request is `approved` once there are `approvers.quorum` of them. */
62
+ readonly approvals?: readonly ApprovalSignature[];
63
+ readonly resolvedAt?: string;
64
+ /** The approver whose verdict resolved the request (the last of `approvals` on a quorum), or `system:<by>` for a cancellation. */
65
+ readonly resolvedBy?: string;
66
+ readonly note?: string;
67
+ readonly consumedAt?: string;
68
+ };
69
+ type ApprovalVerdict = {
70
+ readonly status: "approved" | "rejected";
71
+ readonly by: Subject;
72
+ readonly note?: string;
73
+ /**
74
+ * The relation approvers (by `approverRelationKey`) that `by` holds on the
75
+ * request's resource, as `approverRelations` read them. Server-side input:
76
+ * set it from a `RelationSource`, never from the request body. Absent means
77
+ * none, so relation approvers match nobody.
78
+ */
79
+ readonly relations?: readonly string[];
80
+ };
81
+ type ApprovalListFilter = {
82
+ readonly status?: ApprovalStatus;
83
+ readonly principalId?: string;
84
+ readonly actorId?: string;
85
+ readonly tenant?: string;
86
+ readonly session?: string;
87
+ };
88
+ type ApprovalListQuery = ApprovalListFilter & {
89
+ /** Page size, 1 to 200; 50 when omitted. */
90
+ readonly limit?: number;
91
+ /** The `next` of the previous page; opaque to the caller. */
92
+ readonly cursor?: string;
93
+ };
94
+ /**
95
+ * One page, oldest `createdAt` first. `next` is absent on the last page; an
96
+ * unreadable cursor yields an empty last page.
97
+ */
98
+ type ApprovalPage = {
99
+ readonly items: readonly ApprovalRequest[];
100
+ readonly next?: string;
101
+ };
102
+ type ApprovalCancelMeta = {
103
+ readonly by: string;
104
+ readonly note?: string;
105
+ };
106
+ type ApprovalStore = {
107
+ create(request: ApprovalRequest): Promise<void> | void;
108
+ get(token: string): Promise<ApprovalRequest | null> | ApprovalRequest | null;
109
+ resolve(token: string, verdict: ApprovalVerdict): Promise<ApprovalRequest> | ApprovalRequest;
110
+ list(query: ApprovalListQuery): Promise<ApprovalPage> | ApprovalPage;
111
+ expire(now?: Date): Promise<number> | number;
112
+ /**
113
+ * Marks an approved, unexpired, unconsumed request consumed and returns it;
114
+ * returns `null` otherwise. Must be atomic: two concurrent calls for one
115
+ * token never both return the request.
116
+ */
117
+ consume(token: string, now?: Date): Promise<ApprovalRequest | null> | ApprovalRequest | null;
118
+ cancel?(filter: ApprovalListFilter, meta: ApprovalCancelMeta): Promise<number> | number;
119
+ };
120
+ type ApprovalResumeFailure = "approval-not-found" | "approval-pending" | "approval-rejected" | "approval-expired" | "approval-consumed";
121
+ type ApprovalInspectResult = {
122
+ readonly ok: true;
123
+ readonly request: ApprovalRequest;
124
+ } | {
125
+ readonly ok: false;
126
+ readonly detail: ApprovalResumeFailure;
127
+ };
128
+ declare const APPROVAL_HEADER: "PermDock-Approval";
129
+ declare const DEFAULT_APPROVAL_TTL_MS: number;
130
+ /** The approvals a request needs in total: `approvers.quorum` (or 1), or the sum of its stages' quorums. */
131
+ declare function approvalQuorum(request: ApprovalRequest): number;
132
+ /**
133
+ * The instant from which `approvers.escalation.to` may approve, in epoch
134
+ * milliseconds, or `undefined` when the request has no escalation or its
135
+ * `after` does not parse (then nobody escalates: fail-closed).
136
+ */
137
+ declare function escalationOpenAt(request: ApprovalRequest): number | undefined;
138
+ /** The key a verdict's `relations` lists a relation approver under. */
139
+ declare function approverRelationKey(item: RelationGrantee): string;
140
+ //#endregion
141
+ export { approverRelationKey as _, ApprovalListFilter as a, ApprovalRequest as c, ApprovalStatus as d, ApprovalStore as f, approvalQuorum as g, DEFAULT_APPROVAL_TTL_MS as h, ApprovalInspectResult as i, ApprovalResumeFailure as l, ApprovalVerdict as m, ApprovalApprovers as n, ApprovalListQuery as o, ApprovalSubjectSummary as p, ApprovalCancelMeta as r, ApprovalPage as s, APPROVAL_HEADER as t, ApprovalSignature as u, escalationOpenAt as v };