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.
- package/README.md +327 -1
- package/dist/a2a/index.d.ts +169 -0
- package/dist/a2a/index.js +232 -0
- package/dist/adapter-context-mlWsVGGg.js +23 -0
- package/dist/ai-sdk/index.d.ts +95 -0
- package/dist/ai-sdk/index.js +154 -0
- package/dist/approval-required-TzNB9oQA.js +6 -0
- package/dist/approvals/index.d.ts +3 -0
- package/dist/approvals/index.js +5 -0
- package/dist/approvals-DbYAuNkG.js +224 -0
- package/dist/approvers-DT4AVyIg.js +52 -0
- package/dist/arazzo-BAgw9ap6.js +70 -0
- package/dist/arazzo-cmvX2jDe.js +54 -0
- package/dist/authzen/index.d.ts +39 -0
- package/dist/authzen/index.js +302 -0
- package/dist/better-auth/index.d.ts +109 -0
- package/dist/better-auth/index.js +344 -0
- package/dist/better-supabase/index.d.ts +206 -0
- package/dist/better-supabase/index.js +620 -0
- package/dist/bind-CVy3Espv.d.ts +25 -0
- package/dist/bind-VnYn2HKq.js +97 -0
- package/dist/boundary-BM8a_P6E.js +13 -0
- package/dist/boundary-BmHxVH1J.d.ts +15 -0
- package/dist/budget-JqcRqyhK.d.ts +11 -0
- package/dist/budget-NbEtbJC_.js +11 -0
- package/dist/canonical-json-DemiK4Vp.js +26 -0
- package/dist/capability-4qPdO9gk.js +173 -0
- package/dist/capability-Dq43tT1u.d.ts +99 -0
- package/dist/catalog/index.d.ts +12 -0
- package/dist/catalog/index.js +2 -0
- package/dist/catalog-BjZSovXQ.js +2 -0
- package/dist/catalog-doc-Dsc9y7sd.js +309 -0
- package/dist/catalog-h2tlKFkq.js +48 -0
- package/dist/catalog-path-CnI0XTFK.js +12 -0
- package/dist/catalog-z8q6bi_r.js +55 -0
- package/dist/claude-agent/index.d.ts +72 -0
- package/dist/claude-agent/index.js +77 -0
- package/dist/clerk/index.d.ts +65 -0
- package/dist/clerk/index.js +301 -0
- package/dist/cli/bin.d.ts +1 -0
- package/dist/cli/bin.js +20 -0
- package/dist/cli/index.d.ts +46 -0
- package/dist/cli/index.js +5 -0
- package/dist/clients-C7zLFuWT.d.ts +12 -0
- package/dist/clients-DjU5ABMy.js +23 -0
- package/dist/cloud/index.d.ts +90 -0
- package/dist/cloud/index.js +404 -0
- package/dist/cloud-BGhHS-lY.js +50 -0
- package/dist/cloud-Bo3e9Ak3.js +118 -0
- package/dist/collect-DDDv_ESs.js +502 -0
- package/dist/collect-DLlujdHC.js +83 -0
- package/dist/collect-rG2IQ3t0.js +2 -0
- package/dist/commands-DWOrSQic.js +97 -0
- package/dist/compact-y6vfu2_f.js +19 -0
- package/dist/compare-pfyVnBjE.js +12 -0
- package/dist/compile/index.d.ts +3 -0
- package/dist/compile/index.js +2 -0
- package/dist/compile-Ba4blROR.js +613 -0
- package/dist/compile-CNnl6uIt.d.ts +94 -0
- package/dist/config-BJiM-xAm.js +157 -0
- package/dist/config-Bn00Z3ks.js +36 -0
- package/dist/config-report-Dw_JcUqT.js +44 -0
- package/dist/connection-CU8MQxRi.js +194 -0
- package/dist/context-Ttp0ekMT.js +82 -0
- package/dist/convex/index.d.ts +45 -0
- package/dist/convex/index.js +65 -0
- package/dist/create-BWyx3jua.d.ts +245 -0
- package/dist/create-CPhDL6qx.js +253 -0
- package/dist/credential-8P81ff4u.js +306 -0
- package/dist/delegation-D8pUEuce.js +103 -0
- package/dist/describe-B_gVZEVi.js +94 -0
- package/dist/describe-PdoqESvg.d.ts +36 -0
- package/dist/diff-B8Tunc3o.js +451 -0
- package/dist/diff-CzqLxZ77.js +48 -0
- package/dist/digest-B3kc_PgQ.d.ts +19 -0
- package/dist/digest-BI-6aa6d.js +27 -0
- package/dist/doctor-WpvG6p4k.js +1194 -0
- package/dist/doctor-collect-ByfYlNv1.js +664 -0
- package/dist/doctor-rOr-4ZfS.js +53 -0
- package/dist/drizzle/index.d.ts +73 -0
- package/dist/drizzle/index.js +160 -0
- package/dist/duration-xK2jGFVc.js +25 -0
- package/dist/elysia/index.d.ts +49 -0
- package/dist/elysia/index.js +59 -0
- package/dist/errors-CWfoNg9N.js +47 -0
- package/dist/errors-Cz5zn0mW.js +123 -0
- package/dist/errors-DAqevpNk.d.ts +125 -0
- package/dist/errors-DRnGZHzF.js +30 -0
- package/dist/evaluation-items-CfCCejQd.js +40 -0
- package/dist/evaluations-tz6D9A2G.js +461 -0
- package/dist/eve/index.d.ts +86 -0
- package/dist/eve/index.js +176 -0
- package/dist/expiry-BoBJ8Tvc.js +7 -0
- package/dist/express/index.d.ts +23 -0
- package/dist/express/index.js +78 -0
- package/dist/fastify/index.d.ts +33 -0
- package/dist/fastify/index.js +92 -0
- package/dist/fields-BMl1RxoX.js +26 -0
- package/dist/files-DWUN9PzI.js +125 -0
- package/dist/fixtures-ht28Cplr.js +67 -0
- package/dist/freeze-CrU8nQeX.js +60 -0
- package/dist/from-snapshot-C3sHpZNS.js +569 -0
- package/dist/generate-CH7ThJ14.js +173 -0
- package/dist/grantee-Cv5Sogfv.js +602 -0
- package/dist/graph-sql-B-dsAT6j.d.ts +29 -0
- package/dist/headers-BZSDieNT.js +6 -0
- package/dist/headers-Cf-zWvsO.d.ts +6 -0
- package/dist/helpers-H_KARDVC.js +421 -0
- package/dist/hono/index.d.ts +48 -0
- package/dist/hono/index.js +99 -0
- package/dist/hosted-DJQw46hn.js +266 -0
- package/dist/http-BIhmLfCc.js +95 -0
- package/dist/http-DPuDaChb.d.ts +13 -0
- package/dist/http-SO7qGttf.js +44 -0
- package/dist/ids-DC4V4CFu.js +18 -0
- package/dist/index-A0YNL8jZ.d.ts +177 -0
- package/dist/index-CtE07CBF.d.ts +6 -0
- package/dist/index-D3vbkoSI.d.ts +483 -0
- package/dist/index-D6_cSa1z.d.ts +201 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +26 -0
- package/dist/instance-options-BK_rNOSC.d.ts +11 -0
- package/dist/instance-options-Dhhcnm3y.js +22 -0
- package/dist/json-schema-BsAflUGW.js +106 -0
- package/dist/jwt/index.d.ts +91 -0
- package/dist/jwt/index.js +590 -0
- package/dist/kernel-GSQnMz3O.js +208 -0
- package/dist/kysely/index.d.ts +78 -0
- package/dist/kysely/index.js +129 -0
- package/dist/live-options-H2eG8dfJ.js +60 -0
- package/dist/load-DhWEB9P1.js +75 -0
- package/dist/load-DwJUafYN.js +2 -0
- package/dist/load-jose-BL6LH4bL.js +11 -0
- package/dist/lru-8q4WZjBV.js +28 -0
- package/dist/manifest-iaoBXHKc.js +783 -0
- package/dist/manifest-uDS9y5de.d.ts +206 -0
- package/dist/map-AcxK9o_D.js +147 -0
- package/dist/map-claims-Z4QZOiFF.js +369 -0
- package/dist/map-error-pgUWNNtG.js +23 -0
- package/dist/markers-B0hYLvMD.js +60 -0
- package/dist/may-use-DndQ5tQ-.js +77 -0
- package/dist/mcp/index.d.ts +159 -0
- package/dist/mcp/index.js +603 -0
- package/dist/nest/index.d.ts +75 -0
- package/dist/nest/index.js +261 -0
- package/dist/next/client.d.ts +23 -0
- package/dist/next/client.js +33 -0
- package/dist/next/index.d.ts +93 -0
- package/dist/next/index.js +180 -0
- package/dist/next/plugin.d.ts +14 -0
- package/dist/next/plugin.js +33 -0
- package/dist/node/index.d.ts +24 -0
- package/dist/node/index.js +34 -0
- package/dist/openai/index.d.ts +62 -0
- package/dist/openai/index.js +92 -0
- package/dist/openapi/index.d.ts +176 -0
- package/dist/openapi/index.js +3 -0
- package/dist/openapi-Bbg4wGVL.js +164 -0
- package/dist/openapi-BqRBvAng.js +538 -0
- package/dist/openapi-CqqEbHsL.js +250 -0
- package/dist/openapi-import-cmwetbzw.js +5959 -0
- package/dist/openapi-schema--ARjyfQr.js +6902 -0
- package/dist/orpc/index.d.ts +51 -0
- package/dist/orpc/index.js +145 -0
- package/dist/otel/index.d.ts +13 -0
- package/dist/otel/index.js +202 -0
- package/dist/package-root-zGkxO3oN.js +30 -0
- package/dist/parse-BuyjxhZV.js +53 -0
- package/dist/parse-local-manifest-BkGQNzAh.d.ts +10 -0
- package/dist/parse-local-manifest-BrMozJCo.js +36 -0
- package/dist/pdp/index.d.ts +22 -0
- package/dist/pdp/index.js +682 -0
- package/dist/peer-BOr_kJE1.js +31 -0
- package/dist/permdock-CzqXjCpU.js +3471 -0
- package/dist/permissions-CDgvKG5L.d.ts +52 -0
- package/dist/permissions-CpZrivYv.js +142 -0
- package/dist/permissions-DVoF6dMt.js +662 -0
- package/dist/permissions-DttnqqxC.d.ts +214 -0
- package/dist/pins-8ILTftC9.js +12 -0
- package/dist/policy-CFZAr_Al.d.ts +2252 -0
- package/dist/policy-D8UFyERw.d.ts +20 -0
- package/dist/policy-xyWg7QdR.js +1122 -0
- package/dist/powersync-A8x_Yyvh.js +2 -0
- package/dist/powersync-C7kLglqX.js +540 -0
- package/dist/powersync-yW1UUFzp.js +62 -0
- package/dist/prisma/index.d.ts +136 -0
- package/dist/prisma/index.js +455 -0
- package/dist/problem-B43ztKIm.js +191 -0
- package/dist/problem-details-CkL50EEf.d.ts +7 -0
- package/dist/problem-details-_AMOYz-w.js +144 -0
- package/dist/prompt-CXYhLfsS.js +32 -0
- package/dist/protected-CNsMzrVd.d.ts +27 -0
- package/dist/protected-Cs6kTaHo.js +100 -0
- package/dist/protected-bZs6rbT1.d.ts +40 -0
- package/dist/provider-Cjr62YMV.d.ts +6 -0
- package/dist/provider-DLzpb2Xz.js +52 -0
- package/dist/provider-store-DNyC1y48.js +43 -0
- package/dist/react/index.d.ts +8 -0
- package/dist/react/index.js +7 -0
- package/dist/react/provider-client.d.ts +2 -0
- package/dist/react/provider-client.js +3 -0
- package/dist/react-native/index.d.ts +198 -0
- package/dist/react-native/index.js +696 -0
- package/dist/refs-KYb4ntaz.js +91 -0
- package/dist/relations-cjOL01hZ.js +505 -0
- package/dist/replay-BsOyTrdV.js +28 -0
- package/dist/replay-sqBGMnNs.d.ts +5 -0
- package/dist/resource-ref-CaS9yVPi.js +20 -0
- package/dist/revocations-Bhr0aMIC.js +27 -0
- package/dist/revocations-Cy06JNx2.d.ts +21 -0
- package/dist/rls-BMNydpHk.js +2521 -0
- package/dist/rls-CEvs64Kj.js +238 -0
- package/dist/rls-fields-BMasREhR.js +3502 -0
- package/dist/rls-graph-pc9fuXYm.js +435 -0
- package/dist/rls-import-D8F7j35Q.js +943 -0
- package/dist/rls-migrate-7wikfrVI.js +367 -0
- package/dist/rls-ownership-B5Lkq62W.js +843 -0
- package/dist/rls-shared-aOQ4hGTO.js +493 -0
- package/dist/rls-verify-D8B7dOTh.js +745 -0
- package/dist/row-check-Dt35czLy.d.ts +40 -0
- package/dist/rpc-DOK54_CS.js +89 -0
- package/dist/run-YXCJDNYk.js +174 -0
- package/dist/runtime-CB8gQFvS.js +11 -0
- package/dist/saas-Bj_FFkjN.js +1203 -0
- package/dist/schema-D3MnDMxa.js +300 -0
- package/dist/scim/index.d.ts +2 -0
- package/dist/scim/index.js +2 -0
- package/dist/scim-BFGBBAqR.js +1445 -0
- package/dist/scopes-CVdPrWN-.js +239 -0
- package/dist/server/index.d.ts +134 -0
- package/dist/server/index.js +11 -0
- package/dist/server-DlZ28Oz5.js +268 -0
- package/dist/sha256-BO0swRXL.js +150 -0
- package/dist/shared-DRu8VFVM.js +123 -0
- package/dist/sink-Bd9PSyfq.js +141 -0
- package/dist/sink-Gs6TTVa-.d.ts +104 -0
- package/dist/skills-Biq5uup3.js +192 -0
- package/dist/skills-JaymNCdK.js +56 -0
- package/dist/snapshot-Enxd0n-s.js +975 -0
- package/dist/snapshot-cache-D6jLelln.js +44 -0
- package/dist/snapshot-cache-DwQH8ufx.d.ts +45 -0
- package/dist/solid/index.d.ts +93 -0
- package/dist/solid/index.js +188 -0
- package/dist/sources-B0UvrJ21.js +534 -0
- package/dist/sources-BcJgw0lt.d.ts +192 -0
- package/dist/sql-xdg5f4Fi.js +27 -0
- package/dist/src-CSbUiozF.js +568 -0
- package/dist/ssf/index.d.ts +4 -0
- package/dist/ssf/index.js +596 -0
- package/dist/store-DMAWwAJV.js +371 -0
- package/dist/store-D_pjn91-.d.ts +36 -0
- package/dist/store-options-yO0V6gRn.js +716 -0
- package/dist/stores-4_sqiOA1.js +87 -0
- package/dist/stores-DVR5NHLE.d.ts +52 -0
- package/dist/stream-DDpvynSB.js +66 -0
- package/dist/stream-DlvG2hs-.d.ts +12 -0
- package/dist/style-CTm1AXDT.js +22 -0
- package/dist/subject-C6dLxqHU.js +24 -0
- package/dist/subject-settings-BwBmCdTR.js +128 -0
- package/dist/supabase/index.d.ts +183 -0
- package/dist/supabase/index.js +5 -0
- package/dist/supabase/middleware.d.ts +82 -0
- package/dist/supabase/middleware.js +102 -0
- package/dist/supabase-CwafwxxF.js +83 -0
- package/dist/supabase-DTBaC20O.js +774 -0
- package/dist/supabase-config-Bs44dare.js +472 -0
- package/dist/supabase-hook-BuxLQLpU.js +1814 -0
- package/dist/supabase-hook-D5qVd_D8.js +2 -0
- package/dist/supautils-DYZnzRWV.js +91 -0
- package/dist/svelte/PermissionBoundary.svelte +37 -0
- package/dist/svelte/Protected.svelte +40 -0
- package/dist/svelte/index.d.ts +13 -0
- package/dist/svelte/index.js +107 -0
- package/dist/svelte/runtime.d.ts +7 -0
- package/dist/svelte/runtime.js +4 -0
- package/dist/svelte/source.d.ts +13 -0
- package/dist/svelte/source.js +11 -0
- package/dist/terminal/index.d.ts +163 -0
- package/dist/terminal/index.js +833 -0
- package/dist/testing/index.d.ts +745 -0
- package/dist/testing/index.js +3672 -0
- package/dist/testing/saas/index.d.ts +194 -0
- package/dist/testing/saas/index.js +3 -0
- package/dist/testing/saas/permissions.d.ts +2 -0
- package/dist/testing/saas/permissions.js +2 -0
- package/dist/text-diff-BdkkYSbi.js +15 -0
- package/dist/thenable-okc2xDsj.js +10 -0
- package/dist/timeout-D51niuQP.js +8 -0
- package/dist/token-CIWxJOCh.js +50 -0
- package/dist/trpc/index.d.ts +61 -0
- package/dist/trpc/index.js +122 -0
- package/dist/types-9AWO9EGt.d.ts +197 -0
- package/dist/types-BPxgszlT.d.ts +550 -0
- package/dist/types-BVyImy5I.d.ts +120 -0
- package/dist/types-Bvc4oWT6.d.ts +9 -0
- package/dist/types-C3s9xVJG.d.ts +48 -0
- package/dist/types-Dnemwd77.d.ts +183 -0
- package/dist/types-kxznc7cn.d.ts +52 -0
- package/dist/types-vKyAMtcX.d.ts +157 -0
- package/dist/types-vNSDF7Dq.d.ts +66 -0
- package/dist/types-yF5LmQVD.d.ts +306 -0
- package/dist/unplugin/index.d.ts +7 -0
- package/dist/unplugin/index.js +31 -0
- package/dist/usage-D07N9QJ3.js +42 -0
- package/dist/usage-D82l1CwK.js +2 -0
- package/dist/usage-DG1oeCca.js +693 -0
- package/dist/validation-error-CnjZ4t92.js +33 -0
- package/dist/validation-error-CtF23SrC.d.ts +26 -0
- package/dist/validity-uOp8UpYn.js +245 -0
- package/dist/verifier-BxBo6I44.js +466 -0
- package/dist/version-BvacVTZR.js +17 -0
- package/dist/views-Soe7bGSC.js +95 -0
- package/dist/vocabulary-DA8a8zif.d.ts +56 -0
- package/dist/vue/index.d.ts +79 -0
- package/dist/vue/index.js +196 -0
- package/dist/watch-Etoa_Mvr.js +2 -0
- package/dist/watch-UihESpsJ.js +128 -0
- package/dist/webmcp/index.d.ts +75 -0
- package/dist/webmcp/index.js +307 -0
- package/package.json +450 -5
- package/rulesets/permdock.yaml +29 -0
- package/schemas/approval-request-v1.json +175 -0
- package/schemas/catalog-v1.json +535 -0
- package/schemas/openapi/oas-3.1.json +1298 -0
- package/schemas/openapi/oas-3.2.json +1516 -0
- package/schemas/openapi/overlay-1.1.json +79 -0
- package/schemas/supabase-claims-v1.json +144 -0
- package/schemas/supabase-manifest-v1.json +361 -0
- package/skills/permdock/SKILL.md +66 -0
- package/skills/permdock-agents/SKILL.md +77 -0
- package/skills/permdock-agents/references/runtimes.md +213 -0
- package/skills/permdock-approvals/SKILL.md +80 -0
- package/skills/permdock-approvals/references/stores-and-resume.md +94 -0
- package/skills/permdock-audit/SKILL.md +67 -0
- package/skills/permdock-credentials/SKILL.md +55 -0
- package/skills/permdock-credentials/references/tokens-keys-links.md +132 -0
- package/skills/permdock-data/SKILL.md +57 -0
- package/skills/permdock-data/references/queries-and-rls.md +62 -0
- package/skills/permdock-data/references/relationships.md +67 -0
- package/skills/permdock-tenancy/SKILL.md +80 -0
- package/skills/permdock-tenancy/references/ownership-and-custom-roles.md +89 -0
- package/skills/permdock-wire/SKILL.md +116 -0
- package/skills/permdock-wire/references/adapters.md +492 -0
- package/skills/permdock-wire/references/policy-options.md +45 -0
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { Cr as Actor, Dr as CustomRole, Mr as Membership, Nr as Principal, Pr as Subject, bt as RelationSource, dt as LimitStore, kr as Delegation, un as PermDockOptions } from "../../policy-CFZAr_Al.js";
|
|
2
|
+
import { f as Permission } from "../../permissions-DttnqqxC.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-CDgvKG5L.js";
|
|
4
|
+
import { n as saasPolicy, t as SAAS_API_KEY_LIMIT } from "../../policy-D8UFyERw.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-CpZrivYv.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-Bj_FFkjN.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-CDgvKG5L.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-CpZrivYv.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,50 @@
|
|
|
1
|
+
import { t as canonicalJson } from "./canonical-json-DemiK4Vp.js";
|
|
2
|
+
import { n as sha256, t as bytesToBase64Url } from "./sha256-BO0swRXL.js";
|
|
3
|
+
//#region src/core/token.ts
|
|
4
|
+
/**
|
|
5
|
+
* Only stable identity goes into the token, so refreshing a session (new
|
|
6
|
+
* roles, assurance or claims) does not orphan an outstanding approval.
|
|
7
|
+
*/
|
|
8
|
+
function principalIdentity(principal) {
|
|
9
|
+
if (principal === null) return null;
|
|
10
|
+
return {
|
|
11
|
+
id: principal.id,
|
|
12
|
+
tenant: principal.tenant ?? null,
|
|
13
|
+
issuer: principal.issuer ?? null
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
/** A row's `version` field as token input; `null` when it is missing or not a scalar. */
|
|
17
|
+
function versionOf(row, field) {
|
|
18
|
+
if (row === null || typeof row !== "object" || !Object.hasOwn(row, field)) return null;
|
|
19
|
+
const value = row[field];
|
|
20
|
+
if (value instanceof Date) return Number.isNaN(value.getTime()) ? null : value.toISOString();
|
|
21
|
+
return typeof value === "string" || typeof value === "number" || typeof value === "bigint" || typeof value === "boolean" ? String(value) : null;
|
|
22
|
+
}
|
|
23
|
+
/** The digest that binds a token to the call's data when no row id does. */
|
|
24
|
+
function payloadDigest(data) {
|
|
25
|
+
return bytesToBase64Url(sha256(canonicalJson(data)));
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* `version` is set only for an approval that goes stale on a resource
|
|
29
|
+
* change; without it the payload, and so every other token, is unchanged.
|
|
30
|
+
* `payload` is set when `resourceId` is `*` (a collection action or a row
|
|
31
|
+
* without an id), so an approval covers the arguments it was given and no
|
|
32
|
+
* others.
|
|
33
|
+
*/
|
|
34
|
+
function decisionToken(input) {
|
|
35
|
+
const payload = JSON.stringify({
|
|
36
|
+
key: input.key,
|
|
37
|
+
resourceId: input.resourceId,
|
|
38
|
+
principal: principalIdentity(input.principal),
|
|
39
|
+
actor: input.actor === void 0 ? null : {
|
|
40
|
+
id: input.actor.id,
|
|
41
|
+
kind: input.actor.kind
|
|
42
|
+
},
|
|
43
|
+
fingerprint: input.fingerprint,
|
|
44
|
+
...input.version === void 0 ? {} : { version: input.version },
|
|
45
|
+
...input.payload === void 0 ? {} : { payload: input.payload }
|
|
46
|
+
});
|
|
47
|
+
return `pd1.${bytesToBase64Url(sha256(payload))}`;
|
|
48
|
+
}
|
|
49
|
+
//#endregion
|
|
50
|
+
export { payloadDigest as n, versionOf as r, decisionToken as t };
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { C as Policy, Nr as Principal } from "../policy-CFZAr_Al.js";
|
|
2
|
+
import { f as Permission } from "../permissions-DttnqqxC.js";
|
|
3
|
+
import { n as RevocationFeed } from "../revocations-Cy06JNx2.js";
|
|
4
|
+
import { A as ConnectionOptions, O as Connection, n as OpenApiHooks } from "../create-BWyx3jua.js";
|
|
5
|
+
import { t as ServerAdapterOptions } from "../bind-CVy3Espv.js";
|
|
6
|
+
import { t as StreamProtectOptions } from "../stream-DlvG2hs-.js";
|
|
7
|
+
import { AnyTRPCMiddlewareFunction } from "@trpc/server";
|
|
8
|
+
//#region src/trpc/create.d.ts
|
|
9
|
+
type TrpcMiddlewareOpts<TCtx = object, TInput = unknown> = {
|
|
10
|
+
readonly ctx: TCtx;
|
|
11
|
+
readonly input?: TInput;
|
|
12
|
+
readonly path: string;
|
|
13
|
+
readonly type: string;
|
|
14
|
+
readonly next: (opts?: {
|
|
15
|
+
readonly ctx: TCtx;
|
|
16
|
+
}) => Promise<unknown>;
|
|
17
|
+
};
|
|
18
|
+
type TrpcMiddleware = AnyTRPCMiddlewareFunction;
|
|
19
|
+
type TrpcPermDockOptions<TCtx = object, TUser = unknown> = ServerAdapterOptions<TrpcMiddlewareOpts<TCtx>, TUser> & {
|
|
20
|
+
/** The Web `Request` behind a context; defaults to `ctx.request` or `ctx.req`. */
|
|
21
|
+
readonly request?: (ctx: TCtx) => Request | null | undefined;
|
|
22
|
+
/** Ends or revalidates open subscriptions. */
|
|
23
|
+
readonly revocations?: RevocationFeed;
|
|
24
|
+
};
|
|
25
|
+
type TrpcOpenApiHooks = {
|
|
26
|
+
readonly security: (permission: Permission) => {
|
|
27
|
+
readonly openapi: {
|
|
28
|
+
readonly protect: true;
|
|
29
|
+
readonly security: readonly Record<string, readonly string[]>[];
|
|
30
|
+
readonly "x-permdock-permissions": readonly string[];
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
readonly securitySchemes: OpenApiHooks["securitySchemes"];
|
|
34
|
+
};
|
|
35
|
+
type TrpcPermDock<TCtx = object> = {
|
|
36
|
+
readonly permdock: () => TrpcMiddleware;
|
|
37
|
+
readonly protect: (permission: Permission | null, loadData?: (opts: TrpcMiddlewareOpts<TCtx>) => unknown, protectOptions?: StreamProtectOptions) => TrpcMiddleware;
|
|
38
|
+
/** A long-lived connection for the request behind `ctx`. */
|
|
39
|
+
readonly connection: (opts: TrpcMiddlewareOpts<TCtx>, connectionOptions?: ConnectionOptions) => Promise<Connection>;
|
|
40
|
+
readonly permdockHandler: (request: Request) => Promise<Response>;
|
|
41
|
+
readonly openapi: TrpcOpenApiHooks;
|
|
42
|
+
readonly errorFormatter: <TShape extends {
|
|
43
|
+
readonly data: object;
|
|
44
|
+
}>(opts: {
|
|
45
|
+
readonly shape: TShape;
|
|
46
|
+
readonly error: {
|
|
47
|
+
readonly cause?: unknown;
|
|
48
|
+
};
|
|
49
|
+
}) => TShape;
|
|
50
|
+
};
|
|
51
|
+
export declare function errorFormatter<TShape extends {
|
|
52
|
+
readonly data: object;
|
|
53
|
+
}>(opts: {
|
|
54
|
+
readonly shape: TShape;
|
|
55
|
+
readonly error: {
|
|
56
|
+
readonly cause?: unknown;
|
|
57
|
+
};
|
|
58
|
+
}): TShape;
|
|
59
|
+
export declare function createPermDock<TCtx = object, TUser = unknown, TPrincipal extends Principal = Principal>(policy: Policy<TUser, TPrincipal>, options: TrpcPermDockOptions<TCtx, TUser>): TrpcPermDock<TCtx>;
|
|
60
|
+
//#endregion
|
|
61
|
+
export type { TrpcMiddleware, TrpcMiddlewareOpts, TrpcOpenApiHooks, TrpcPermDock, TrpcPermDockOptions };
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { a as problemMessage } from "../http-SO7qGttf.js";
|
|
2
|
+
import { t as problemFromError } from "../map-error-pgUWNNtG.js";
|
|
3
|
+
import { n as attached } from "../bind-VnYn2HKq.js";
|
|
4
|
+
import { a as reloadAfter, r as isAsyncIterable } from "../stream-DDpvynSB.js";
|
|
5
|
+
import { i as rpcCode, n as guardStream, r as problemBody, t as bindRpcKernel } from "../rpc-DOK54_CS.js";
|
|
6
|
+
import { TRPCError, isTrackedEnvelope } from "@trpc/server";
|
|
7
|
+
//#region src/trpc/create.ts
|
|
8
|
+
const PROBLEM = Symbol.for("permdock.problem");
|
|
9
|
+
/** A `TRPCError` for a revoked subscription; the Problem Details body rides on `cause`. */
|
|
10
|
+
function trpcErrorFrom(error) {
|
|
11
|
+
const problem = error.toProblemDetails();
|
|
12
|
+
const cause = { ...problem };
|
|
13
|
+
Object.defineProperty(cause, PROBLEM, {
|
|
14
|
+
value: true,
|
|
15
|
+
enumerable: true
|
|
16
|
+
});
|
|
17
|
+
return new TRPCError({
|
|
18
|
+
code: rpcCode(problem.status),
|
|
19
|
+
message: error.code,
|
|
20
|
+
cause
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
async function throwTrpcError(response) {
|
|
24
|
+
const cause = await problemBody(response);
|
|
25
|
+
if (cause !== null && typeof cause === "object") Object.defineProperty(cause, PROBLEM, {
|
|
26
|
+
value: true,
|
|
27
|
+
enumerable: true
|
|
28
|
+
});
|
|
29
|
+
const code = rpcCode(response.status);
|
|
30
|
+
throw new TRPCError({
|
|
31
|
+
code,
|
|
32
|
+
message: problemMessage(cause, code),
|
|
33
|
+
cause
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* A PermDock error thrown further down (an `assert` in a resolver) arrives as
|
|
38
|
+
* a failed middleware result; it becomes the same TRPCError `protect` throws.
|
|
39
|
+
*/
|
|
40
|
+
function mapDownstream(result) {
|
|
41
|
+
if (result === null || typeof result !== "object" || result.ok !== false) return Promise.resolve(result);
|
|
42
|
+
const error = result.error;
|
|
43
|
+
const cause = error instanceof TRPCError && error.code === "INTERNAL_SERVER_ERROR" ? error.cause : void 0;
|
|
44
|
+
const mapped = problemFromError(cause);
|
|
45
|
+
return mapped === void 0 ? Promise.resolve(result) : throwTrpcError(mapped);
|
|
46
|
+
}
|
|
47
|
+
function errorFormatter(opts) {
|
|
48
|
+
const cause = opts.error.cause;
|
|
49
|
+
if (cause === null || typeof cause !== "object" || !(PROBLEM in cause)) return opts.shape;
|
|
50
|
+
const { [PROBLEM]: _brand, ...problem } = cause;
|
|
51
|
+
return {
|
|
52
|
+
...opts.shape,
|
|
53
|
+
data: {
|
|
54
|
+
...opts.shape.data,
|
|
55
|
+
...problem
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
function createPermDock(policy, options) {
|
|
60
|
+
const { kernel, bind, attach, scopeOf, connection, evaluate } = bindRpcKernel(policy, options, "trpc", (opts) => opts.ctx, (opts) => opts.path);
|
|
61
|
+
const permdock = () => (async (opts) => {
|
|
62
|
+
const request = bind(opts);
|
|
63
|
+
const instance = await attached(async () => kernel.permdock(request, await scopeOf(opts)));
|
|
64
|
+
if (!instance.ok) return throwTrpcError(instance.response);
|
|
65
|
+
const nextCtx = {
|
|
66
|
+
...opts.ctx,
|
|
67
|
+
permdock: instance.permdock
|
|
68
|
+
};
|
|
69
|
+
attach(nextCtx, request);
|
|
70
|
+
return mapDownstream(await opts.next({ ctx: nextCtx }));
|
|
71
|
+
});
|
|
72
|
+
/** Wraps a subscription's iterable so revocation ends it and unreadable items drop. */
|
|
73
|
+
const guardSubscription = async (result, opts, permission, loadData, protectOptions) => {
|
|
74
|
+
if (result === null || typeof result !== "object" || result.ok !== true || !isAsyncIterable(result.data)) return result;
|
|
75
|
+
return {
|
|
76
|
+
...result,
|
|
77
|
+
data: await guardStream(result.data, (connectionOptions) => connection(opts, connectionOptions), permission, loadData, protectOptions, {
|
|
78
|
+
unwrap: (item) => isTrackedEnvelope(item) ? item[1] : item,
|
|
79
|
+
onRevoked: trpcErrorFrom
|
|
80
|
+
})
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
const protect = (permission, loadData, protectOptions) => (async (opts) => {
|
|
84
|
+
const request = bind(opts);
|
|
85
|
+
const guard = await kernel.protect(permission, loadData === void 0 ? void 0 : () => loadData(opts), protectOptions)(request, await scopeOf(opts));
|
|
86
|
+
if (guard.ok) {
|
|
87
|
+
const nextCtx = {
|
|
88
|
+
...opts.ctx,
|
|
89
|
+
permdock: guard.permdock,
|
|
90
|
+
permdockData: guard.data
|
|
91
|
+
};
|
|
92
|
+
attach(nextCtx, request);
|
|
93
|
+
return guardSubscription(await mapDownstream(await opts.next({ ctx: nextCtx })), opts, permission, loadData === void 0 ? void 0 : reloadAfter(guard.data, () => loadData(opts)), protectOptions);
|
|
94
|
+
}
|
|
95
|
+
return throwTrpcError(guard.response);
|
|
96
|
+
});
|
|
97
|
+
const permdockHandler = (request) => {
|
|
98
|
+
return evaluate(request, {
|
|
99
|
+
ctx: { req: request },
|
|
100
|
+
path: "permdock",
|
|
101
|
+
type: "unknown",
|
|
102
|
+
next: (nextOpts) => Promise.resolve(nextOpts ?? { ctx: { req: request } })
|
|
103
|
+
});
|
|
104
|
+
};
|
|
105
|
+
const kernelOpenApi = kernel.openapi;
|
|
106
|
+
return {
|
|
107
|
+
permdock,
|
|
108
|
+
protect,
|
|
109
|
+
connection,
|
|
110
|
+
permdockHandler,
|
|
111
|
+
openapi: {
|
|
112
|
+
security: (permission) => ({ openapi: {
|
|
113
|
+
protect: true,
|
|
114
|
+
...kernelOpenApi.security(permission)
|
|
115
|
+
} }),
|
|
116
|
+
securitySchemes: kernelOpenApi.securitySchemes
|
|
117
|
+
},
|
|
118
|
+
errorFormatter
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
//#endregion
|
|
122
|
+
export { createPermDock, errorFormatter };
|