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.
- package/README.md +268 -1
- package/dist/a2a/index.d.ts +178 -0
- package/dist/a2a/index.js +271 -0
- package/dist/ai-sdk/index.d.ts +74 -0
- package/dist/ai-sdk/index.js +137 -0
- package/dist/approval-required-TzNB9oQA.js +6 -0
- package/dist/approvals/index.d.ts +3 -0
- package/dist/approvals/index.js +4 -0
- package/dist/approvals-DaxY-Bdg.js +218 -0
- package/dist/approvers-aH0PJkmf.js +20 -0
- package/dist/arazzo-CTeVuXr5.js +70 -0
- package/dist/arazzo-aoTkqYsJ.js +54 -0
- package/dist/authzen/index.d.ts +48 -0
- package/dist/authzen/index.js +336 -0
- package/dist/better-auth/index.d.ts +92 -0
- package/dist/better-auth/index.js +324 -0
- package/dist/budget-JqcRqyhK.d.ts +11 -0
- package/dist/budget-NbEtbJC_.js +11 -0
- package/dist/capability-B68OFnZx.js +171 -0
- package/dist/capability-BDG_nkxt.d.ts +99 -0
- package/dist/catalog/index.d.ts +12 -0
- package/dist/catalog/index.js +2 -0
- package/dist/catalog-B0E6bggc.js +48 -0
- package/dist/catalog-H-vFGwWK.js +55 -0
- package/dist/catalog-doc-BSo_Q_-6.js +298 -0
- package/dist/catalog-idsHc0vo.js +2 -0
- package/dist/catalog-path-CnI0XTFK.js +12 -0
- package/dist/claude-agent/index.d.ts +81 -0
- package/dist/claude-agent/index.js +83 -0
- package/dist/clerk/index.d.ts +56 -0
- package/dist/clerk/index.js +280 -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/cloud/index.d.ts +91 -0
- package/dist/cloud/index.js +390 -0
- package/dist/cloud-BNQTrmrr.js +50 -0
- package/dist/cloud-Cuxr6Czw.js +117 -0
- package/dist/collect-B7_TIfmg.js +49 -0
- package/dist/collect-O-tOtbnk.js +350 -0
- package/dist/collect-fRPAQIWb.js +2 -0
- package/dist/commands-BMh_Etm2.js +93 -0
- package/dist/compact-y6vfu2_f.js +19 -0
- package/dist/compare-pfyVnBjE.js +12 -0
- package/dist/compile-CQbvyIBr.d.ts +30 -0
- package/dist/compile-D22iwvuV.js +558 -0
- package/dist/config-BPYmjTOp.js +26 -0
- package/dist/connection-JvqwHODC.js +194 -0
- package/dist/context-CKEAabd7.js +73 -0
- package/dist/context-gtAwAILx.js +6 -0
- package/dist/convex/index.d.ts +40 -0
- package/dist/convex/index.js +55 -0
- package/dist/create-BKF3dgFk.d.ts +162 -0
- package/dist/create-CSkhDU9T.js +222 -0
- package/dist/credential-B_rkUNlY.js +326 -0
- package/dist/credentials-BgRX3WEg.js +268 -0
- package/dist/describe-Bt1YD5uS.js +99 -0
- package/dist/describe-DernyItf.d.ts +37 -0
- package/dist/diff-BUzf5Poi.js +48 -0
- package/dist/diff-x5Il8LVa.js +418 -0
- package/dist/digest-B3kc_PgQ.d.ts +19 -0
- package/dist/digest-BI-6aa6d.js +27 -0
- package/dist/doctor-BGle8Gqi.js +1314 -0
- package/dist/doctor-Bqo6FwUa.js +53 -0
- package/dist/drizzle/index.d.ts +72 -0
- package/dist/drizzle/index.js +160 -0
- package/dist/duration-xK2jGFVc.js +25 -0
- package/dist/elysia/index.d.ts +71 -0
- package/dist/elysia/index.js +103 -0
- package/dist/errors-DSMnAVNa.js +43 -0
- package/dist/errors-DbZ1YOnb.d.ts +138 -0
- package/dist/errors-Iy71s7Oj.js +177 -0
- package/dist/errors-m3u9TmDu.js +27 -0
- package/dist/evaluations-DsAU9ppl.js +479 -0
- package/dist/eve/index.d.ts +95 -0
- package/dist/eve/index.js +181 -0
- package/dist/express/index.d.ts +46 -0
- package/dist/express/index.js +108 -0
- package/dist/fastify/index.d.ts +56 -0
- package/dist/fastify/index.js +141 -0
- package/dist/files-B_wAGYmt.js +121 -0
- package/dist/fixtures-Cvaw0gDG.js +64 -0
- package/dist/freeze-y1_jQL4v.js +31 -0
- package/dist/from-snapshot-BMGnhmgv.js +552 -0
- package/dist/generate-CH7ThJ14.js +173 -0
- package/dist/grantee-Bv04_Vzf.js +521 -0
- package/dist/headers-B5RRv3Xm.js +6 -0
- package/dist/headers-C8SHQccD.d.ts +6 -0
- package/dist/helpers-DnSOrhB9.js +682 -0
- package/dist/hono/index.d.ts +70 -0
- package/dist/hono/index.js +131 -0
- package/dist/hosted-BwKQ1BTA.js +265 -0
- package/dist/http-DPuDaChb.d.ts +13 -0
- package/dist/http-GgVApX1k.js +111 -0
- package/dist/index-CltcQ4Bf.d.ts +138 -0
- package/dist/index-LF_hS-yn.d.ts +177 -0
- package/dist/index-fG6NSXlc.d.ts +9 -0
- package/dist/index-xIxJLwOQ.d.ts +415 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +21 -0
- package/dist/jwt/index.d.ts +87 -0
- package/dist/jwt/index.js +571 -0
- package/dist/kernel-YOGCWNLf.js +211 -0
- package/dist/kysely/index.d.ts +77 -0
- package/dist/kysely/index.js +129 -0
- package/dist/load-BZ24CpZP.js +69 -0
- package/dist/load-QOOm1z70.js +2 -0
- package/dist/load-jose-BL6LH4bL.js +11 -0
- package/dist/lru-8q4WZjBV.js +28 -0
- package/dist/manifest-DDQbC6K0.d.ts +118 -0
- package/dist/map-DowSO96j.js +158 -0
- package/dist/map-claims-B_6I1Rn-.js +360 -0
- package/dist/map-error-RJ3ZsUyA.js +16 -0
- package/dist/markers-B0hYLvMD.js +60 -0
- package/dist/may-use-CnFEjVEp.js +37 -0
- package/dist/mcp/index.d.ts +127 -0
- package/dist/mcp/index.js +563 -0
- package/dist/nest/index.d.ts +80 -0
- package/dist/nest/index.js +270 -0
- package/dist/next/client.d.ts +24 -0
- package/dist/next/client.js +31 -0
- package/dist/next/index.d.ts +110 -0
- package/dist/next/index.js +195 -0
- package/dist/next/plugin.d.ts +14 -0
- package/dist/next/plugin.js +2 -0
- package/dist/node/index.d.ts +43 -0
- package/dist/node/index.js +66 -0
- package/dist/openai/index.d.ts +71 -0
- package/dist/openai/index.js +105 -0
- package/dist/openapi/index.d.ts +93 -0
- package/dist/openapi/index.js +3 -0
- package/dist/openapi-CwePaF7C.js +164 -0
- package/dist/openapi-DWD0Uc_4.js +250 -0
- package/dist/openapi-DcqM8nU7.js +306 -0
- package/dist/openapi-import-BWRUNNeW.js +5959 -0
- package/dist/openapi-schema-D8j_T9tO.js +6902 -0
- package/dist/orpc/index.d.ts +64 -0
- package/dist/orpc/index.js +188 -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-DPfIvFMU.js +135 -0
- package/dist/pdp/index.d.ts +22 -0
- package/dist/pdp/index.js +795 -0
- package/dist/peer-BOr_kJE1.js +31 -0
- package/dist/permdock-yoZ7EjxX.js +2956 -0
- package/dist/permissions-B4apnahQ.d.ts +185 -0
- package/dist/permissions-B8vCg_bI.d.ts +52 -0
- package/dist/permissions-CofRqesP.js +142 -0
- package/dist/permissions-DC7GROPA.js +600 -0
- package/dist/pg-4GJWDUxG.js +953 -0
- package/dist/pins-CqE1jZuF.js +12 -0
- package/dist/plugin-4gr7IxFJ.js +65 -0
- package/dist/policy-ANp36PnI.js +971 -0
- package/dist/policy-CInmNGkM.d.ts +1959 -0
- package/dist/policy-Cq2fB8Q5.d.ts +20 -0
- package/dist/prisma/index.d.ts +135 -0
- package/dist/prisma/index.js +430 -0
- package/dist/problem-Cgp9-KZA.js +226 -0
- package/dist/prompt-CXYhLfsS.js +32 -0
- package/dist/protected-B4K3BKoX.js +138 -0
- package/dist/protected-BuPAycJT.d.ts +26 -0
- package/dist/protected-wY7nXhY9.d.ts +23 -0
- package/dist/provider-_wx46HpB.js +48 -0
- package/dist/provider-wTAUda2v.d.ts +6 -0
- package/dist/react/index.d.ts +6 -0
- package/dist/react/index.js +6 -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 +42 -0
- package/dist/react-native/index.js +174 -0
- package/dist/refs-ChLSxbST.js +90 -0
- package/dist/relations-r4soIFZB.js +426 -0
- package/dist/revocations-Cy06JNx2.d.ts +21 -0
- package/dist/rls-BOFU3chG.js +233 -0
- package/dist/rls-CJVja9Ww.js +2119 -0
- package/dist/rls-graph-DxQ39PJj.js +371 -0
- package/dist/rls-helpers-BxRuif0l.js +1346 -0
- package/dist/rls-import-CXV6LBlS.js +942 -0
- package/dist/rls-migrate-DrFPbf8p.js +366 -0
- package/dist/row-check-BajTgQZ-.d.ts +43 -0
- package/dist/run-CJ6UvS3a.js +155 -0
- package/dist/runtime-DP9ttFh1.js +27 -0
- package/dist/saas-BRrZzJkM.js +1193 -0
- package/dist/schema-P8yoma__.js +296 -0
- package/dist/scim/index.d.ts +2 -0
- package/dist/scim/index.js +2 -0
- package/dist/scim-9NFa0XVZ.js +1445 -0
- package/dist/scopes-cKVp_WTw.js +212 -0
- package/dist/server/index.d.ts +123 -0
- package/dist/server/index.js +8 -0
- package/dist/sha256-BO0swRXL.js +150 -0
- package/dist/sink-Bd9PSyfq.js +141 -0
- package/dist/sink-Cfr9-7YC.d.ts +104 -0
- package/dist/skills-C_lpV4Jx.js +50 -0
- package/dist/skills-Dx3QLnMY.js +110 -0
- package/dist/snapshot-DE8dE_hz.js +1051 -0
- package/dist/solid/index.d.ts +63 -0
- package/dist/solid/index.js +197 -0
- package/dist/source-DoBBYJi2.js +6 -0
- package/dist/sources-DOpW5Ila.d.ts +347 -0
- package/dist/sources-DVHM3Mwq.js +284 -0
- package/dist/sql-Bll1d7y0.js +22 -0
- package/dist/src-CTNT-PBW.js +430 -0
- package/dist/ssf/index.d.ts +3 -0
- package/dist/ssf/index.js +622 -0
- package/dist/store-Bq90395i.d.ts +27 -0
- package/dist/store-C6hFW6ta.js +508 -0
- package/dist/stores-CkG2HrSg.js +140 -0
- package/dist/stores-CvOnu_2T.d.ts +41 -0
- package/dist/stream-BhMfZOwr.d.ts +12 -0
- package/dist/stream-Q_xlB6Ko.js +52 -0
- package/dist/style-CTm1AXDT.js +22 -0
- package/dist/subject-C6dLxqHU.js +24 -0
- package/dist/subject-settings-xt7V845g.js +82 -0
- package/dist/supabase/index.d.ts +67 -0
- package/dist/supabase/index.js +4 -0
- package/dist/supabase/middleware.d.ts +77 -0
- package/dist/supabase/middleware.js +68 -0
- package/dist/supabase-D8UlBA7Z.js +83 -0
- package/dist/supabase-DTxGtYdi.js +796 -0
- package/dist/supabase-hook-DW-xP4hU.js +2 -0
- package/dist/supabase-hook-D_OqGb_V.js +1528 -0
- package/dist/svelte/Protected.svelte +34 -0
- package/dist/svelte/index.d.ts +10 -0
- package/dist/svelte/index.js +53 -0
- package/dist/svelte/runtime.d.ts +6 -0
- package/dist/svelte/runtime.js +3 -0
- package/dist/svelte/source.d.ts +10 -0
- package/dist/svelte/source.js +8 -0
- package/dist/terminal/index.d.ts +171 -0
- package/dist/terminal/index.js +821 -0
- package/dist/testing/index.d.ts +656 -0
- package/dist/testing/index.js +3208 -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/trpc/index.d.ts +80 -0
- package/dist/trpc/index.js +205 -0
- package/dist/types-B8w5PFtS.d.ts +141 -0
- package/dist/types-B9dmiiab.d.ts +66 -0
- package/dist/types-BBK-exvJ.d.ts +177 -0
- package/dist/types-BvBk1wgn.d.ts +118 -0
- package/dist/types-CxquUByI.d.ts +9 -0
- package/dist/types-D6Z6-rKJ.d.ts +312 -0
- package/dist/types-DbWdEfcm.d.ts +87 -0
- package/dist/types-bva3i4Gf.d.ts +98 -0
- package/dist/types-i4BAOvdb.d.ts +97 -0
- package/dist/unplugin/index.d.ts +7 -0
- package/dist/unplugin/index.js +30 -0
- package/dist/usage-1ozMubLY.js +42 -0
- package/dist/usage-CUnK6Ou9.js +530 -0
- package/dist/usage-PyEor6GA.js +2 -0
- package/dist/validity-D0uRmJKJ.js +224 -0
- package/dist/verifier-B90agnhl.js +461 -0
- package/dist/version-CnSh33Fj.js +16 -0
- package/dist/vocabulary-Dk0fs-Jk.d.ts +56 -0
- package/dist/vue/index.d.ts +57 -0
- package/dist/vue/index.js +203 -0
- package/dist/webmcp/index.d.ts +75 -0
- package/dist/webmcp/index.js +313 -0
- package/package.json +423 -4
- package/rulesets/permdock.yaml +29 -0
- package/schemas/catalog-v1.json +507 -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 +139 -0
- package/schemas/supabase-manifest-v1.json +217 -0
- package/skills/permdock/SKILL.md +66 -0
- package/skills/permdock-agents/SKILL.md +77 -0
- package/skills/permdock-agents/references/runtimes.md +211 -0
- package/skills/permdock-approvals/SKILL.md +80 -0
- package/skills/permdock-approvals/references/stores-and-resume.md +83 -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 +127 -0
- package/skills/permdock-data/SKILL.md +57 -0
- package/skills/permdock-data/references/queries-and-rls.md +54 -0
- package/skills/permdock-data/references/relationships.md +65 -0
- package/skills/permdock-tenancy/SKILL.md +77 -0
- package/skills/permdock-tenancy/references/ownership-and-custom-roles.md +83 -0
- package/skills/permdock-wire/SKILL.md +116 -0
- package/skills/permdock-wire/references/adapters.md +480 -0
- package/skills/permdock-wire/references/policy-options.md +43 -0
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { a as listArg, i as globalArgs, s as stringArg, t as COMMAND_DESCRIPTIONS } from "./commands-BMh_Etm2.js";
|
|
2
|
+
import { defineCommand } from "citty";
|
|
3
|
+
//#region src/cli/commands/openapi.ts
|
|
4
|
+
function openapi(ctx) {
|
|
5
|
+
return defineCommand({
|
|
6
|
+
meta: {
|
|
7
|
+
name: "openapi",
|
|
8
|
+
description: COMMAND_DESCRIPTIONS.openapi
|
|
9
|
+
},
|
|
10
|
+
args: {
|
|
11
|
+
...globalArgs,
|
|
12
|
+
action: {
|
|
13
|
+
type: "positional",
|
|
14
|
+
required: false,
|
|
15
|
+
description: "emit (default) or import"
|
|
16
|
+
},
|
|
17
|
+
doc: {
|
|
18
|
+
type: "string",
|
|
19
|
+
description: "OpenAPI document: a path, or a URL for import",
|
|
20
|
+
valueHint: "path"
|
|
21
|
+
},
|
|
22
|
+
out: {
|
|
23
|
+
type: "string",
|
|
24
|
+
description: "File to write",
|
|
25
|
+
valueHint: "file"
|
|
26
|
+
},
|
|
27
|
+
from: {
|
|
28
|
+
type: "string",
|
|
29
|
+
description: "Module exporting the policy, instead of the config",
|
|
30
|
+
valueHint: "module"
|
|
31
|
+
},
|
|
32
|
+
target: {
|
|
33
|
+
type: "enum",
|
|
34
|
+
options: [
|
|
35
|
+
"3.1",
|
|
36
|
+
"3.2",
|
|
37
|
+
"3.3"
|
|
38
|
+
],
|
|
39
|
+
default: "3.2",
|
|
40
|
+
description: "OpenAPI version; 3.3 is the pinned Security Profiles draft"
|
|
41
|
+
},
|
|
42
|
+
format: {
|
|
43
|
+
type: "enum",
|
|
44
|
+
options: ["document", "overlay"],
|
|
45
|
+
default: "document",
|
|
46
|
+
description: "A full document or an Overlay"
|
|
47
|
+
},
|
|
48
|
+
overlay: {
|
|
49
|
+
type: "enum",
|
|
50
|
+
options: ["1.1", "1.2"],
|
|
51
|
+
default: "1.1",
|
|
52
|
+
description: "Overlay version; 1.2 is the pinned reusable-actions draft"
|
|
53
|
+
},
|
|
54
|
+
check: {
|
|
55
|
+
type: "boolean",
|
|
56
|
+
description: "Exit 1 when --out is stale; write nothing"
|
|
57
|
+
},
|
|
58
|
+
profile: {
|
|
59
|
+
type: "enum",
|
|
60
|
+
options: ["fapi2"],
|
|
61
|
+
description: "Security profile to declare"
|
|
62
|
+
},
|
|
63
|
+
"profile-scheme": {
|
|
64
|
+
type: "string",
|
|
65
|
+
description: "Security scheme name for the profile",
|
|
66
|
+
valueHint: "name"
|
|
67
|
+
},
|
|
68
|
+
scheme: {
|
|
69
|
+
type: "string",
|
|
70
|
+
default: "permdockOAuth",
|
|
71
|
+
description: "OAuth security scheme name",
|
|
72
|
+
valueHint: "name"
|
|
73
|
+
},
|
|
74
|
+
"metadata-url": {
|
|
75
|
+
type: "string",
|
|
76
|
+
description: "OAuth authorization server metadata URL",
|
|
77
|
+
valueHint: "url"
|
|
78
|
+
},
|
|
79
|
+
"device-flow": {
|
|
80
|
+
type: "boolean",
|
|
81
|
+
description: "Declare the device authorization flow"
|
|
82
|
+
},
|
|
83
|
+
arity: {
|
|
84
|
+
type: "boolean",
|
|
85
|
+
description: "Mark instance and collection operations"
|
|
86
|
+
},
|
|
87
|
+
"authorization-url": {
|
|
88
|
+
type: "string",
|
|
89
|
+
description: "OAuth authorization endpoint",
|
|
90
|
+
valueHint: "url"
|
|
91
|
+
},
|
|
92
|
+
"token-url": {
|
|
93
|
+
type: "string",
|
|
94
|
+
description: "OAuth token endpoint",
|
|
95
|
+
valueHint: "url"
|
|
96
|
+
},
|
|
97
|
+
"device-authorization-url": {
|
|
98
|
+
type: "string",
|
|
99
|
+
description: "OAuth device authorization endpoint",
|
|
100
|
+
valueHint: "url"
|
|
101
|
+
},
|
|
102
|
+
schema: {
|
|
103
|
+
type: "enum",
|
|
104
|
+
options: [
|
|
105
|
+
"zod",
|
|
106
|
+
"valibot",
|
|
107
|
+
"arktype"
|
|
108
|
+
],
|
|
109
|
+
description: "import: schema library for the generated resources"
|
|
110
|
+
},
|
|
111
|
+
map: {
|
|
112
|
+
type: "string",
|
|
113
|
+
description: "import: JSON mapping of operations to permissions",
|
|
114
|
+
valueHint: "json"
|
|
115
|
+
},
|
|
116
|
+
annotate: {
|
|
117
|
+
type: "boolean",
|
|
118
|
+
description: "import: write x-permdock-permissions back into the document"
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
async run({ args: parsed, rawArgs }) {
|
|
122
|
+
const doc = listArg(rawArgs, "doc")[0];
|
|
123
|
+
if (parsed._[0] === "import") {
|
|
124
|
+
if (doc === void 0) throw new Error("openapi --doc is required");
|
|
125
|
+
const { runOpenapiImport } = await import("./openapi-import-BWRUNNeW.js");
|
|
126
|
+
ctx.report(await runOpenapiImport({
|
|
127
|
+
cwd: ctx.cwd,
|
|
128
|
+
doc,
|
|
129
|
+
out: stringArg(parsed.out),
|
|
130
|
+
schema: parsed.schema,
|
|
131
|
+
map: stringArg(parsed.map),
|
|
132
|
+
annotate: parsed.annotate === true,
|
|
133
|
+
io: ctx.io
|
|
134
|
+
}));
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
const result = await (await import("./openapi-DWD0Uc_4.js")).runOpenapi({
|
|
138
|
+
cwd: ctx.cwd,
|
|
139
|
+
config: ctx.config,
|
|
140
|
+
rest: parsed._,
|
|
141
|
+
doc,
|
|
142
|
+
out: stringArg(parsed.out),
|
|
143
|
+
from: stringArg(parsed.from),
|
|
144
|
+
target: parsed.target,
|
|
145
|
+
format: parsed.format,
|
|
146
|
+
overlay: parsed.overlay,
|
|
147
|
+
check: parsed.check === true,
|
|
148
|
+
profile: parsed.profile,
|
|
149
|
+
profileScheme: stringArg(parsed["profile-scheme"]),
|
|
150
|
+
scheme: parsed.scheme,
|
|
151
|
+
metadataUrl: listArg(rawArgs, "metadata-url")[0],
|
|
152
|
+
deviceFlow: parsed["device-flow"] === true,
|
|
153
|
+
arity: parsed.arity === true,
|
|
154
|
+
authorizationUrl: stringArg(parsed["authorization-url"]),
|
|
155
|
+
tokenUrl: stringArg(parsed["token-url"]),
|
|
156
|
+
deviceAuthorizationUrl: stringArg(parsed["device-authorization-url"]),
|
|
157
|
+
io: ctx.io
|
|
158
|
+
});
|
|
159
|
+
ctx.report(result);
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
//#endregion
|
|
164
|
+
export { openapi };
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import { n as validateOverlay, t as validateOpenapi } from "./openapi-schema-D8j_T9tO.js";
|
|
2
|
+
import { c as getResource, i as findPermission } from "./permissions-DC7GROPA.js";
|
|
3
|
+
import { a as definePolicy } from "./policy-ANp36PnI.js";
|
|
4
|
+
import { a as loadModule, n as asPolicy, o as pickNamed, t as asPermissionTree } from "./load-BZ24CpZP.js";
|
|
5
|
+
import { t as shortDiff } from "./text-diff-BdkkYSbi.js";
|
|
6
|
+
import { r as openapiVersion, t as createPermDock } from "./openapi-DcqM8nU7.js";
|
|
7
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
8
|
+
import { dirname, resolve } from "node:path";
|
|
9
|
+
//#region src/cli/openapi.ts
|
|
10
|
+
function isRecord(value) {
|
|
11
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
12
|
+
}
|
|
13
|
+
function mergeRecord(base, extra) {
|
|
14
|
+
const result = {};
|
|
15
|
+
for (const [key, value] of Object.entries(base)) result[key] = value;
|
|
16
|
+
for (const [key, value] of Object.entries(extra)) result[key] = value;
|
|
17
|
+
return result;
|
|
18
|
+
}
|
|
19
|
+
/** Keeps what the document already says about a scheme (flow URLs, other flows, description); PermDock owns the scopes. */
|
|
20
|
+
function mergeSchemes(existing, emitted) {
|
|
21
|
+
const result = {};
|
|
22
|
+
for (const [name, scheme] of Object.entries(emitted)) {
|
|
23
|
+
const before = existing[name];
|
|
24
|
+
if (!isRecord(before) || !isRecord(scheme)) {
|
|
25
|
+
result[name] = scheme;
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
const beforeFlows = isRecord(before["flows"]) ? before["flows"] : {};
|
|
29
|
+
const flows = { ...beforeFlows };
|
|
30
|
+
for (const [kind, flow] of Object.entries(isRecord(scheme["flows"]) ? scheme["flows"] : {})) {
|
|
31
|
+
const previous = beforeFlows[kind];
|
|
32
|
+
flows[kind] = isRecord(previous) && isRecord(flow) ? {
|
|
33
|
+
...previous,
|
|
34
|
+
...flow
|
|
35
|
+
} : flow;
|
|
36
|
+
}
|
|
37
|
+
result[name] = {
|
|
38
|
+
...before,
|
|
39
|
+
...scheme,
|
|
40
|
+
...isRecord(scheme["flows"]) ? { flows } : {}
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
return result;
|
|
44
|
+
}
|
|
45
|
+
function stableJson(value) {
|
|
46
|
+
return `${JSON.stringify(value, null, 2)}\n`;
|
|
47
|
+
}
|
|
48
|
+
async function loadPolicy(cwd, config, from) {
|
|
49
|
+
const policyPath = from ?? config.policy;
|
|
50
|
+
if (policyPath !== void 0) {
|
|
51
|
+
const abs = resolve(cwd, policyPath);
|
|
52
|
+
return asPolicy(pickNamed(await loadModule(abs), ["policy"]));
|
|
53
|
+
}
|
|
54
|
+
const permissionsPath = config.permissions;
|
|
55
|
+
if (permissionsPath === void 0) throw new Error("PermDock CLI: openapi needs --from, policy or permissions in the config");
|
|
56
|
+
const tree = asPermissionTree(pickNamed(await loadModule(resolve(cwd, permissionsPath)), ["permissions"]));
|
|
57
|
+
return definePolicy(tree, {
|
|
58
|
+
roles: [],
|
|
59
|
+
subject: () => null
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
function leavesOf(policy, keys) {
|
|
63
|
+
return keys.map((key) => {
|
|
64
|
+
if (typeof key !== "string") throw new TypeError("PermDock CLI: x-permdock-permissions must be strings");
|
|
65
|
+
const leaf = findPermission(policy.permissions, key);
|
|
66
|
+
if (leaf === void 0) throw new Error(`PermDock CLI: unknown permission '${key}'`);
|
|
67
|
+
return leaf;
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
/** Operations carrying `x-permdock-permissions`, joined by `operationId`; those without one are findings. */
|
|
71
|
+
function overlayOperations(document, policy) {
|
|
72
|
+
const operations = [];
|
|
73
|
+
const unnamed = [];
|
|
74
|
+
const secured = [];
|
|
75
|
+
const paths = isRecord(document["paths"]) ? document["paths"] : {};
|
|
76
|
+
for (const [path, item] of Object.entries(paths)) for (const [method, operation] of Object.entries(isRecord(item) ? item : {})) {
|
|
77
|
+
if (!isRecord(operation) || !Array.isArray(operation["x-permdock-permissions"])) continue;
|
|
78
|
+
const permissions = leavesOf(policy, operation["x-permdock-permissions"]);
|
|
79
|
+
const operationId = operation["operationId"];
|
|
80
|
+
if (typeof operationId !== "string" || operationId.length === 0) {
|
|
81
|
+
unnamed.push(`${method.toUpperCase()} ${path}`);
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
if (operation["security"] !== void 0) secured.push(operationId);
|
|
85
|
+
operations.push({
|
|
86
|
+
operationId,
|
|
87
|
+
permissions
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
operations,
|
|
92
|
+
unnamed,
|
|
93
|
+
secured
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
/** `instance` when any listed permission acts on one row; the id is the last path template parameter. */
|
|
97
|
+
function arityOf(policy, leaves, path) {
|
|
98
|
+
if (!leaves.some((leaf) => getResource(policy.permissions, leaf.resource)?.instanceActions.has(leaf.action) === true)) return { kind: "collection" };
|
|
99
|
+
const parameter = [...path.matchAll(/\{([^}]+)\}/gu)].at(-1)?.[1];
|
|
100
|
+
return parameter === void 0 ? { kind: "instance" } : {
|
|
101
|
+
kind: "instance",
|
|
102
|
+
parameter
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
function applyDocument(document, policy, openapi, arity, target) {
|
|
106
|
+
const components = isRecord(document["components"]) ? document["components"] : {};
|
|
107
|
+
const schemes = isRecord(components["securitySchemes"]) ? components["securitySchemes"] : {};
|
|
108
|
+
const nextSchemes = mergeRecord(schemes, mergeSchemes(schemes, openapi.securitySchemes()));
|
|
109
|
+
const scopeSets = [];
|
|
110
|
+
const paths = isRecord(document["paths"]) ? document["paths"] : {};
|
|
111
|
+
const nextPaths = {};
|
|
112
|
+
for (const [path, item] of Object.entries(paths)) {
|
|
113
|
+
if (!isRecord(item)) {
|
|
114
|
+
nextPaths[path] = item;
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
const nextItem = {};
|
|
118
|
+
for (const [method, operation] of Object.entries(item)) {
|
|
119
|
+
if (!isRecord(operation)) {
|
|
120
|
+
nextItem[method] = operation;
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
const keys = operation["x-permdock-permissions"];
|
|
124
|
+
if (!Array.isArray(keys)) {
|
|
125
|
+
nextItem[method] = operation;
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
const leaves = leavesOf(policy, keys);
|
|
129
|
+
scopeSets.push(leaves.map((leaf) => leaf.scope));
|
|
130
|
+
const described = mergeRecord(operation, openapi.describe(leaves));
|
|
131
|
+
nextItem[method] = arity ? mergeRecord(described, { "x-permdock-arity": arityOf(policy, leaves, path) }) : described;
|
|
132
|
+
}
|
|
133
|
+
nextPaths[path] = nextItem;
|
|
134
|
+
}
|
|
135
|
+
const requirements = openapi.securityProfileRequirements(scopeSets);
|
|
136
|
+
const nextComponents = mergeRecord(components, mergeRecord({ securitySchemes: nextSchemes }, requirements === void 0 ? {} : { securityProfileRequirements: requirements }));
|
|
137
|
+
return mergeRecord(document, {
|
|
138
|
+
...target === "3.3" ? { openapi: openapiVersion(target) } : {},
|
|
139
|
+
components: nextComponents,
|
|
140
|
+
paths: nextPaths,
|
|
141
|
+
"x-permdock-catalog": openapi.catalog()
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
function urls(values) {
|
|
145
|
+
return Object.fromEntries(Object.entries(values).filter((entry) => entry[1] !== void 0));
|
|
146
|
+
}
|
|
147
|
+
/** A finding when the source validates but PermDock's output does not. */
|
|
148
|
+
function outputConformance(source, result, format, overlay) {
|
|
149
|
+
if (format === "overlay") {
|
|
150
|
+
if (overlay !== "1.1") return;
|
|
151
|
+
const checked = validateOverlay(result);
|
|
152
|
+
return checked.ok ? void 0 : `openapi emit: ${checked.error}`;
|
|
153
|
+
}
|
|
154
|
+
if (!validateOpenapi(source).ok) return;
|
|
155
|
+
const checked = validateOpenapi(result);
|
|
156
|
+
return checked.ok ? void 0 : `openapi emit: ${checked.error}\npass --authorization-url and --token-url, or declare the scheme's flows in the document`;
|
|
157
|
+
}
|
|
158
|
+
async function runOpenapi(input) {
|
|
159
|
+
if ((input.rest[0] ?? "emit") !== "emit") return {
|
|
160
|
+
code: 2,
|
|
161
|
+
output: "openapi action must be emit or import"
|
|
162
|
+
};
|
|
163
|
+
if (input.doc === void 0) return {
|
|
164
|
+
code: 2,
|
|
165
|
+
output: "openapi --doc is required"
|
|
166
|
+
};
|
|
167
|
+
const policy = await loadPolicy(input.cwd, input.config, input.from);
|
|
168
|
+
const openapi = createPermDock(policy, {
|
|
169
|
+
target: input.target,
|
|
170
|
+
...input.profile === void 0 ? {} : { securityProfile: input.profile },
|
|
171
|
+
...input.profileScheme === void 0 ? {} : { profileScheme: input.profileScheme },
|
|
172
|
+
scheme: {
|
|
173
|
+
name: input.scheme,
|
|
174
|
+
type: "oauth2",
|
|
175
|
+
...input.metadataUrl === void 0 ? {} : { oauth2MetadataUrl: input.metadataUrl },
|
|
176
|
+
flows: {
|
|
177
|
+
authorizationCode: urls({
|
|
178
|
+
authorizationUrl: input.authorizationUrl,
|
|
179
|
+
tokenUrl: input.tokenUrl
|
|
180
|
+
}),
|
|
181
|
+
...input.deviceFlow ? { deviceAuthorization: urls({
|
|
182
|
+
deviceAuthorizationUrl: input.deviceAuthorizationUrl,
|
|
183
|
+
tokenUrl: input.tokenUrl
|
|
184
|
+
}) } : {}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
const docPath = resolve(input.cwd, input.doc);
|
|
189
|
+
if (!existsSync(docPath)) return {
|
|
190
|
+
code: 2,
|
|
191
|
+
output: `PermDock CLI: document not found: ${input.doc}`
|
|
192
|
+
};
|
|
193
|
+
let parsed;
|
|
194
|
+
try {
|
|
195
|
+
parsed = JSON.parse(readFileSync(docPath, "utf8"));
|
|
196
|
+
} catch {
|
|
197
|
+
return {
|
|
198
|
+
code: 2,
|
|
199
|
+
output: "PermDock CLI: --doc must be a JSON OpenAPI document"
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
if (!isRecord(parsed)) return {
|
|
203
|
+
code: 2,
|
|
204
|
+
output: "PermDock CLI: OpenAPI document must be an object"
|
|
205
|
+
};
|
|
206
|
+
const covered = input.format === "overlay" ? overlayOperations(parsed, policy) : void 0;
|
|
207
|
+
if (covered !== void 0 && covered.unnamed.length > 0) return {
|
|
208
|
+
code: 1,
|
|
209
|
+
output: `openapi emit: an Overlay targets operations by operationId; none on ${covered.unnamed.join(", ")}`
|
|
210
|
+
};
|
|
211
|
+
if (input.check && covered !== void 0 && covered.secured.length > 0) return {
|
|
212
|
+
code: 1,
|
|
213
|
+
output: `openapi drift: the source already sets security the Overlay replaces on ${covered.secured.join(", ")}`
|
|
214
|
+
};
|
|
215
|
+
const result = covered !== void 0 ? openapi.overlay({
|
|
216
|
+
extends: input.doc,
|
|
217
|
+
version: input.overlay,
|
|
218
|
+
operations: covered.operations
|
|
219
|
+
}) : applyDocument(parsed, policy, openapi, input.arity === true, input.target);
|
|
220
|
+
const conformance = outputConformance(parsed, result, input.format, input.overlay);
|
|
221
|
+
if (conformance !== void 0) return {
|
|
222
|
+
code: 1,
|
|
223
|
+
output: conformance
|
|
224
|
+
};
|
|
225
|
+
const text = stableJson(result);
|
|
226
|
+
const outPath = resolve(input.cwd, input.out ?? input.doc);
|
|
227
|
+
if (input.check) {
|
|
228
|
+
if (!existsSync(outPath)) return {
|
|
229
|
+
code: 1,
|
|
230
|
+
output: `openapi drift: missing ${input.out ?? input.doc}`
|
|
231
|
+
};
|
|
232
|
+
const current = readFileSync(outPath, "utf8");
|
|
233
|
+
if (current === text) return {
|
|
234
|
+
code: 0,
|
|
235
|
+
output: "openapi up to date"
|
|
236
|
+
};
|
|
237
|
+
return {
|
|
238
|
+
code: 1,
|
|
239
|
+
output: `openapi drift\n${shortDiff(input.out ?? input.doc, current, text)}`
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
mkdirSync(dirname(outPath), { recursive: true });
|
|
243
|
+
writeFileSync(outPath, text);
|
|
244
|
+
return {
|
|
245
|
+
code: 0,
|
|
246
|
+
output: `wrote ${input.out ?? input.doc}`
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
//#endregion
|
|
250
|
+
export { runOpenapi };
|