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,177 @@
|
|
|
1
|
+
import { t as compact } from "./compact-y6vfu2_f.js";
|
|
2
|
+
import { n as deniedDigest, t as approvalDigest } from "./digest-BI-6aa6d.js";
|
|
3
|
+
//#region src/core/wire-denial.ts
|
|
4
|
+
const IN_PROCESS = /* @__PURE__ */ new Set(["closure-error", "validation"]);
|
|
5
|
+
function jsonDetail(value) {
|
|
6
|
+
if (value === void 0 || value === null || value instanceof Error) return;
|
|
7
|
+
if (typeof value === "string" || typeof value === "boolean") return value;
|
|
8
|
+
if (typeof value === "number") return Number.isFinite(value) ? value : void 0;
|
|
9
|
+
if (typeof value !== "object") return;
|
|
10
|
+
try {
|
|
11
|
+
return JSON.parse(JSON.stringify(value));
|
|
12
|
+
} catch {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function wireDenial(denial) {
|
|
17
|
+
return compact({
|
|
18
|
+
role: denial.role,
|
|
19
|
+
reason: denial.reason,
|
|
20
|
+
to: denial.to,
|
|
21
|
+
detail: IN_PROCESS.has(denial.reason) ? void 0 : jsonDetail(denial.detail)
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
function wireDenials(denials) {
|
|
25
|
+
return denials.map(wireDenial);
|
|
26
|
+
}
|
|
27
|
+
//#endregion
|
|
28
|
+
//#region src/core/errors.ts
|
|
29
|
+
const PROBLEM_BASE = "https://permdock.dev/problems";
|
|
30
|
+
var PermDockDeniedError = class extends Error {
|
|
31
|
+
name = "PermDockDeniedError";
|
|
32
|
+
decision;
|
|
33
|
+
permission;
|
|
34
|
+
scope;
|
|
35
|
+
resource;
|
|
36
|
+
subject;
|
|
37
|
+
/** `PERMDOCK_DENIED;<permission>`; survives the Server Component boundary (`parsePermDockDigest`). */
|
|
38
|
+
digest;
|
|
39
|
+
constructor(input) {
|
|
40
|
+
super(input.message);
|
|
41
|
+
this.decision = input.decision;
|
|
42
|
+
this.permission = input.permission;
|
|
43
|
+
this.scope = input.scope;
|
|
44
|
+
this.resource = input.resource;
|
|
45
|
+
this.subject = input.subject;
|
|
46
|
+
this.digest = deniedDigest(input.permission);
|
|
47
|
+
}
|
|
48
|
+
toProblemDetails(options) {
|
|
49
|
+
return compact({
|
|
50
|
+
type: `${PROBLEM_BASE}/denied`,
|
|
51
|
+
title: "Permission denied",
|
|
52
|
+
status: 403,
|
|
53
|
+
detail: this.message,
|
|
54
|
+
instance: options?.instance,
|
|
55
|
+
permission: this.permission,
|
|
56
|
+
scope: this.scope,
|
|
57
|
+
resource: this.resource,
|
|
58
|
+
denials: wireDenials(this.decision.denials),
|
|
59
|
+
alternatives: this.decision.alternatives.map((leaf) => leaf.key)
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
var PermDockApprovalRequiredError = class extends Error {
|
|
64
|
+
name = "PermDockApprovalRequiredError";
|
|
65
|
+
decision;
|
|
66
|
+
permission;
|
|
67
|
+
scope;
|
|
68
|
+
resource;
|
|
69
|
+
token;
|
|
70
|
+
reason;
|
|
71
|
+
/** `PERMDOCK_APPROVAL_REQUIRED;<permission>;<token>`; the token is already bound to this subject. */
|
|
72
|
+
digest;
|
|
73
|
+
constructor(input) {
|
|
74
|
+
super(input.message);
|
|
75
|
+
this.decision = input.decision;
|
|
76
|
+
this.permission = input.permission;
|
|
77
|
+
this.scope = input.scope;
|
|
78
|
+
this.resource = input.resource;
|
|
79
|
+
this.token = input.decision.token;
|
|
80
|
+
this.reason = input.decision.reason;
|
|
81
|
+
this.digest = approvalDigest(input.permission, input.decision.token);
|
|
82
|
+
}
|
|
83
|
+
toProblemDetails(options) {
|
|
84
|
+
return compact({
|
|
85
|
+
type: `${PROBLEM_BASE}/approval-required`,
|
|
86
|
+
title: "Approval required",
|
|
87
|
+
status: 403,
|
|
88
|
+
detail: this.message,
|
|
89
|
+
instance: options?.instance,
|
|
90
|
+
permission: this.permission,
|
|
91
|
+
scope: this.scope,
|
|
92
|
+
resource: this.resource,
|
|
93
|
+
reason: this.reason,
|
|
94
|
+
token: this.token
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
var PermDockValidationError = class extends Error {
|
|
99
|
+
name = "PermDockValidationError";
|
|
100
|
+
code;
|
|
101
|
+
permission;
|
|
102
|
+
resource;
|
|
103
|
+
issues;
|
|
104
|
+
boundary;
|
|
105
|
+
constructor(input) {
|
|
106
|
+
super(input.message);
|
|
107
|
+
this.code = input.code;
|
|
108
|
+
this.permission = input.permission;
|
|
109
|
+
this.resource = input.resource;
|
|
110
|
+
this.issues = input.issues ?? [];
|
|
111
|
+
this.boundary = input.boundary;
|
|
112
|
+
}
|
|
113
|
+
toProblemDetails(options) {
|
|
114
|
+
return compact({
|
|
115
|
+
type: `${PROBLEM_BASE}/validation`,
|
|
116
|
+
title: "Invalid resource data",
|
|
117
|
+
status: 400,
|
|
118
|
+
detail: this.message,
|
|
119
|
+
instance: options?.instance,
|
|
120
|
+
permission: this.permission,
|
|
121
|
+
issues: this.issues
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
/** The `name` of the deny grant a `deny` denial carries in `detail`, if any. */
|
|
126
|
+
function denyName(detail) {
|
|
127
|
+
if (detail === null || typeof detail !== "object" || !("name" in detail)) return;
|
|
128
|
+
return typeof detail.name === "string" ? detail.name : void 0;
|
|
129
|
+
}
|
|
130
|
+
function deniedMessage(permission, subjectId, denials, alternatives) {
|
|
131
|
+
const clauses = denials.map((denial) => {
|
|
132
|
+
const name = denial.reason === "deny" ? denyName(denial.detail) : void 0;
|
|
133
|
+
return name === void 0 ? `${denial.role ?? "none"} (${denial.reason})` : `${denial.role ?? "none"} (${denial.reason} '${name}')`;
|
|
134
|
+
}).join(", ");
|
|
135
|
+
const alt = alternatives.length === 0 ? "" : ` Alternatives: ${alternatives.join(", ")}.`;
|
|
136
|
+
return `${permission} denied for subject ${subjectId ?? "anonymous"}: ${clauses}.${alt}`;
|
|
137
|
+
}
|
|
138
|
+
function approvalMessage(permission, reason, token) {
|
|
139
|
+
return `${permission} requires human approval (${reason}). Token: ${token}.`;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* The `reason` of a long-lived connection's aborted `signal`. `denied` carries
|
|
143
|
+
* the decision that re-denied the permission the connection was opened for.
|
|
144
|
+
*/
|
|
145
|
+
var PermDockRevokedError = class extends Error {
|
|
146
|
+
name = "PermDockRevokedError";
|
|
147
|
+
code;
|
|
148
|
+
permission;
|
|
149
|
+
decision;
|
|
150
|
+
constructor(input) {
|
|
151
|
+
super(`PermDock: connection ended (${input.code}).`);
|
|
152
|
+
this.code = input.code;
|
|
153
|
+
if (input.permission !== void 0) this.permission = input.permission;
|
|
154
|
+
if (input.decision !== void 0) this.decision = input.decision;
|
|
155
|
+
}
|
|
156
|
+
toProblemDetails(options) {
|
|
157
|
+
if (this.code === "denied") return compact({
|
|
158
|
+
type: `${PROBLEM_BASE}/denied`,
|
|
159
|
+
title: "Permission denied",
|
|
160
|
+
status: 403,
|
|
161
|
+
detail: this.code,
|
|
162
|
+
instance: options?.instance,
|
|
163
|
+
permission: this.permission,
|
|
164
|
+
denials: this.decision?.outcome === "denied" ? wireDenials(this.decision.denials) : void 0
|
|
165
|
+
});
|
|
166
|
+
return compact({
|
|
167
|
+
type: `${PROBLEM_BASE}/unauthenticated`,
|
|
168
|
+
title: "Authorization ended",
|
|
169
|
+
status: 401,
|
|
170
|
+
detail: this.code,
|
|
171
|
+
instance: options?.instance,
|
|
172
|
+
permission: this.permission
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
//#endregion
|
|
177
|
+
export { approvalMessage as a, PermDockValidationError as i, PermDockDeniedError as n, deniedMessage as o, PermDockRevokedError as r, wireDenials as s, PermDockApprovalRequiredError as t };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
//#region src/approvals/errors.ts
|
|
2
|
+
var ApprovalError = class extends Error {
|
|
3
|
+
name = "ApprovalError";
|
|
4
|
+
code;
|
|
5
|
+
constructor(code, message) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.code = code;
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
const CODES = /* @__PURE__ */ new Set([
|
|
11
|
+
"approval-not-found",
|
|
12
|
+
"approval-not-pending",
|
|
13
|
+
"approval-expired",
|
|
14
|
+
"approver-unauthenticated",
|
|
15
|
+
"approver-is-actor",
|
|
16
|
+
"approver-is-principal",
|
|
17
|
+
"approver-not-eligible",
|
|
18
|
+
"approver-repeated"
|
|
19
|
+
]);
|
|
20
|
+
/** Matches by `name` and `code`, so an error from another copy of the module still maps. */
|
|
21
|
+
function isApprovalError(value) {
|
|
22
|
+
if (!(value instanceof Error) || value.name !== "ApprovalError") return false;
|
|
23
|
+
const code = Reflect.get(value, "code");
|
|
24
|
+
return typeof code === "string" && CODES.has(code);
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
export { isApprovalError as n, ApprovalError as t };
|
|
@@ -0,0 +1,479 @@
|
|
|
1
|
+
import { t as compact } from "./compact-y6vfu2_f.js";
|
|
2
|
+
import { g as listPermissions, i as findPermission } from "./permissions-DC7GROPA.js";
|
|
3
|
+
import { s as wireDenials } from "./errors-Iy71s7Oj.js";
|
|
4
|
+
import { i as readApprovalHeader, s as resumeDecision } from "./helpers-DnSOrhB9.js";
|
|
5
|
+
import { t as timeoutSignal } from "./timeout-D51niuQP.js";
|
|
6
|
+
import { l as validationProblem, n as batchTooLarge, o as problemResponse, t as PROBLEM_BASE } from "./problem-Cgp9-KZA.js";
|
|
7
|
+
//#region src/server/web-bot-auth.ts
|
|
8
|
+
/** Milliseconds a key directory fetch may take before the signature counts as unverifiable. */
|
|
9
|
+
const DIRECTORY_TIMEOUT_MS = 5e3;
|
|
10
|
+
const DEFAULT_MAX_AGE = 300;
|
|
11
|
+
const FUTURE_SKEW = 60;
|
|
12
|
+
const DIRECTORY_PATH = "/.well-known/http-message-signatures-directory";
|
|
13
|
+
var InvalidSignatureError = class extends Error {
|
|
14
|
+
name = "InvalidSignatureError";
|
|
15
|
+
response;
|
|
16
|
+
constructor(response) {
|
|
17
|
+
super("Web Bot Auth signature was rejected");
|
|
18
|
+
this.response = response;
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
function invalidSignatureResponse(error) {
|
|
22
|
+
return error instanceof InvalidSignatureError ? error.response : void 0;
|
|
23
|
+
}
|
|
24
|
+
function invalidSignatureProblem(detail) {
|
|
25
|
+
return problemResponse(compact({
|
|
26
|
+
type: `${PROBLEM_BASE}/invalid-signature`,
|
|
27
|
+
title: "Invalid signature",
|
|
28
|
+
status: 403,
|
|
29
|
+
detail
|
|
30
|
+
}));
|
|
31
|
+
}
|
|
32
|
+
function discoverViaSignatureAgent(options) {
|
|
33
|
+
const fetchFn = options.fetch ?? fetch;
|
|
34
|
+
const allow = new Set(options.allow);
|
|
35
|
+
const cache = /* @__PURE__ */ new Map();
|
|
36
|
+
const lookup = async ({ keyid, agent }) => {
|
|
37
|
+
if (agent === void 0) return;
|
|
38
|
+
let url;
|
|
39
|
+
try {
|
|
40
|
+
url = new URL(agent);
|
|
41
|
+
} catch {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
if (url.protocol !== "https:" || !allow.has(url.hostname)) return;
|
|
45
|
+
const directoryUrl = url.pathname === "/" || url.pathname === "" ? `${url.origin}${DIRECTORY_PATH}` : agent;
|
|
46
|
+
let pending = cache.get(directoryUrl);
|
|
47
|
+
if (pending === void 0) {
|
|
48
|
+
pending = loadDirectory(fetchFn, directoryUrl);
|
|
49
|
+
cache.set(directoryUrl, pending);
|
|
50
|
+
}
|
|
51
|
+
let keys;
|
|
52
|
+
try {
|
|
53
|
+
keys = await pending;
|
|
54
|
+
} catch {
|
|
55
|
+
cache.delete(directoryUrl);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
return keys.find((key) => key.kid === keyid);
|
|
59
|
+
};
|
|
60
|
+
return { lookup };
|
|
61
|
+
}
|
|
62
|
+
async function verifyWebBotAuth(request, options) {
|
|
63
|
+
if (options === void 0 || options.verify === false) return;
|
|
64
|
+
const signatureInput = request.headers.get("Signature-Input");
|
|
65
|
+
if (signatureInput === null) {
|
|
66
|
+
if (options.required === true) throw new InvalidSignatureError(invalidSignatureProblem("Signature-Input is required"));
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const parsed = parseSignatureInput(signatureInput);
|
|
70
|
+
const signatureHeader = request.headers.get("Signature");
|
|
71
|
+
if (parsed === void 0 || signatureHeader === null) throw reject("Signature-Input could not be parsed");
|
|
72
|
+
const signature = parseSignature(signatureHeader, parsed.label);
|
|
73
|
+
if (signature === void 0) throw reject("Signature could not be parsed");
|
|
74
|
+
const now = options.now?.() ?? Math.floor(Date.now() / 1e3);
|
|
75
|
+
const maxAge = options.maxAge ?? DEFAULT_MAX_AGE;
|
|
76
|
+
if (typeof parsed.created !== "number") throw reject("Signature-Input created is required");
|
|
77
|
+
if (parsed.created > now + FUTURE_SKEW) throw reject("Signature-Input created is in the future");
|
|
78
|
+
if (now - parsed.created > maxAge) throw reject("Signature-Input created is too old");
|
|
79
|
+
if (typeof parsed.expires === "number" && parsed.expires < now) throw reject("Signature-Input expires is in the past");
|
|
80
|
+
if (parsed.keyid === void 0) throw reject("Signature-Input keyid is required");
|
|
81
|
+
const agent = parseSignatureAgent(request.headers.get("Signature-Agent"), parsed.label);
|
|
82
|
+
const lookup = typeof options.keys === "function" ? options.keys : options.keys.lookup;
|
|
83
|
+
let key;
|
|
84
|
+
try {
|
|
85
|
+
key = await lookup({
|
|
86
|
+
request,
|
|
87
|
+
keyid: parsed.keyid,
|
|
88
|
+
agent
|
|
89
|
+
});
|
|
90
|
+
} catch {
|
|
91
|
+
throw reject("Web Bot Auth key lookup failed");
|
|
92
|
+
}
|
|
93
|
+
if (key === void 0) throw reject("Web Bot Auth key was not found");
|
|
94
|
+
const base = signatureBase(request, parsed);
|
|
95
|
+
if (base === void 0) throw reject("signed components could not be covered");
|
|
96
|
+
const alg = parsed.alg ?? algorithmFromJwk(key);
|
|
97
|
+
if (alg === void 0) throw reject("signature algorithm is not supported");
|
|
98
|
+
if (!await verifyBytes(key, alg, signature, base)) throw reject("HTTP Message Signature did not verify");
|
|
99
|
+
return Object.freeze({
|
|
100
|
+
id: parsed.keyid,
|
|
101
|
+
kind: "web-bot-auth"
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
function reject(detail) {
|
|
105
|
+
return new InvalidSignatureError(invalidSignatureProblem(detail));
|
|
106
|
+
}
|
|
107
|
+
function parseSignatureInput(header) {
|
|
108
|
+
const member = firstDictionaryMember(header);
|
|
109
|
+
if (member === void 0) return;
|
|
110
|
+
const inner = parseInnerListAndParams(member.value);
|
|
111
|
+
if (inner === void 0) return;
|
|
112
|
+
return compact({
|
|
113
|
+
label: member.key,
|
|
114
|
+
components: inner.components,
|
|
115
|
+
created: inner.created,
|
|
116
|
+
expires: inner.expires,
|
|
117
|
+
keyid: inner.keyid,
|
|
118
|
+
alg: inner.alg,
|
|
119
|
+
innerListAndParams: member.value.trim()
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
function parseSignature(header, label) {
|
|
123
|
+
const member = dictionaryMember(header, label);
|
|
124
|
+
if (member === void 0) return;
|
|
125
|
+
return decodeSfBytes(member);
|
|
126
|
+
}
|
|
127
|
+
function parseSignatureAgent(header, label) {
|
|
128
|
+
if (header === null) return;
|
|
129
|
+
const trimmed = header.trim();
|
|
130
|
+
if (trimmed.startsWith("\"")) return unquote(trimmed);
|
|
131
|
+
const member = dictionaryMember(trimmed, label) ?? firstDictionaryMember(trimmed)?.value;
|
|
132
|
+
if (member === void 0) return;
|
|
133
|
+
return unquote(member.trim());
|
|
134
|
+
}
|
|
135
|
+
function firstDictionaryMember(header) {
|
|
136
|
+
const first = splitTopLevel(header, ",")[0];
|
|
137
|
+
if (first === void 0) return;
|
|
138
|
+
const eq = first.indexOf("=");
|
|
139
|
+
if (eq <= 0) return;
|
|
140
|
+
return {
|
|
141
|
+
key: first.slice(0, eq).trim(),
|
|
142
|
+
value: first.slice(eq + 1)
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
function dictionaryMember(header, label) {
|
|
146
|
+
for (const part of splitTopLevel(header, ",")) {
|
|
147
|
+
const eq = part.indexOf("=");
|
|
148
|
+
if (eq <= 0) continue;
|
|
149
|
+
if (part.slice(0, eq).trim() === label) return part.slice(eq + 1);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
function parseInnerListAndParams(value) {
|
|
153
|
+
const trimmed = value.trim();
|
|
154
|
+
if (!trimmed.startsWith("(")) return;
|
|
155
|
+
const close = trimmed.indexOf(")");
|
|
156
|
+
if (close < 0) return;
|
|
157
|
+
const components = parseQuotedList(trimmed.slice(1, close));
|
|
158
|
+
if (components === void 0) return;
|
|
159
|
+
const params = parseParams(trimmed.slice(close + 1));
|
|
160
|
+
return compact({
|
|
161
|
+
components,
|
|
162
|
+
created: asUnix(params["created"]),
|
|
163
|
+
expires: asUnix(params["expires"]),
|
|
164
|
+
keyid: typeof params["keyid"] === "string" ? params["keyid"] : void 0,
|
|
165
|
+
alg: typeof params["alg"] === "string" ? params["alg"] : void 0
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
function parseQuotedList(inner) {
|
|
169
|
+
const items = [];
|
|
170
|
+
const parts = splitTopLevel(inner, " ");
|
|
171
|
+
for (const part of parts) {
|
|
172
|
+
const next = part.trim();
|
|
173
|
+
if (next === "") continue;
|
|
174
|
+
if (!next.startsWith("\"") || !next.endsWith("\"")) return;
|
|
175
|
+
const item = unquote(next);
|
|
176
|
+
if (item === void 0) return;
|
|
177
|
+
items.push(item);
|
|
178
|
+
}
|
|
179
|
+
return items;
|
|
180
|
+
}
|
|
181
|
+
function parseParams(suffix) {
|
|
182
|
+
const params = {};
|
|
183
|
+
for (const part of suffix.split(";")) {
|
|
184
|
+
const next = part.trim();
|
|
185
|
+
if (next === "") continue;
|
|
186
|
+
const eq = next.indexOf("=");
|
|
187
|
+
if (eq <= 0) continue;
|
|
188
|
+
const name = next.slice(0, eq);
|
|
189
|
+
const raw = next.slice(eq + 1);
|
|
190
|
+
if (raw.startsWith("\"")) {
|
|
191
|
+
const quoted = unquote(raw);
|
|
192
|
+
if (quoted !== void 0) params[name] = quoted;
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
const numeric = Number(raw);
|
|
196
|
+
params[name] = Number.isFinite(numeric) ? numeric : raw;
|
|
197
|
+
}
|
|
198
|
+
return params;
|
|
199
|
+
}
|
|
200
|
+
function asUnix(value) {
|
|
201
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
202
|
+
}
|
|
203
|
+
function signatureBase(request, parsed) {
|
|
204
|
+
const lines = [];
|
|
205
|
+
for (const component of parsed.components) {
|
|
206
|
+
const value = componentValue(request, component);
|
|
207
|
+
if (value === void 0) return;
|
|
208
|
+
lines.push(`"${component}": ${value}`);
|
|
209
|
+
}
|
|
210
|
+
lines.push(`"@signature-params": ${parsed.innerListAndParams}`);
|
|
211
|
+
return new TextEncoder().encode(lines.join("\n"));
|
|
212
|
+
}
|
|
213
|
+
function componentValue(request, component) {
|
|
214
|
+
if (component.startsWith("@")) {
|
|
215
|
+
const url = new URL(request.url);
|
|
216
|
+
switch (component) {
|
|
217
|
+
case "@method": return request.method;
|
|
218
|
+
case "@authority": return url.host;
|
|
219
|
+
case "@path": return url.pathname;
|
|
220
|
+
case "@query": return url.search;
|
|
221
|
+
case "@target-uri": return url.href;
|
|
222
|
+
case "@scheme": return url.protocol.replace(":", "");
|
|
223
|
+
case "@request-target": return `${url.pathname}${url.search}`;
|
|
224
|
+
default: return;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
return request.headers.get(component) ?? void 0;
|
|
228
|
+
}
|
|
229
|
+
function algorithmFromJwk(key) {
|
|
230
|
+
if (key.kty === "OKP" && key.crv === "Ed25519") return "ed25519";
|
|
231
|
+
if (key.kty === "EC" && key.crv === "P-256") return "ecdsa-p256-sha256";
|
|
232
|
+
}
|
|
233
|
+
async function verifyBytes(key, alg, signature, data) {
|
|
234
|
+
try {
|
|
235
|
+
if (alg === "ed25519") {
|
|
236
|
+
const cryptoKey = await crypto.subtle.importKey("jwk", key, "Ed25519", false, ["verify"]);
|
|
237
|
+
return await crypto.subtle.verify("Ed25519", cryptoKey, signature, data);
|
|
238
|
+
}
|
|
239
|
+
if (alg === "ecdsa-p256-sha256") {
|
|
240
|
+
const cryptoKey = await crypto.subtle.importKey("jwk", key, {
|
|
241
|
+
name: "ECDSA",
|
|
242
|
+
namedCurve: "P-256"
|
|
243
|
+
}, false, ["verify"]);
|
|
244
|
+
return await crypto.subtle.verify({
|
|
245
|
+
name: "ECDSA",
|
|
246
|
+
hash: "SHA-256"
|
|
247
|
+
}, cryptoKey, signature, data);
|
|
248
|
+
}
|
|
249
|
+
return false;
|
|
250
|
+
} catch {
|
|
251
|
+
return false;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
async function loadDirectory(fetchFn, directoryUrl) {
|
|
255
|
+
const response = await fetchFn(directoryUrl, {
|
|
256
|
+
headers: { accept: "application/http-message-signatures-directory+json, application/json" },
|
|
257
|
+
signal: timeoutSignal(DIRECTORY_TIMEOUT_MS)
|
|
258
|
+
});
|
|
259
|
+
if (!response.ok) throw new TypeError("directory fetch failed");
|
|
260
|
+
const body = await response.json();
|
|
261
|
+
if (body === null || typeof body !== "object" || Array.isArray(body)) return [];
|
|
262
|
+
const keys = body.keys;
|
|
263
|
+
if (!Array.isArray(keys)) return [];
|
|
264
|
+
return keys.filter(isWebBotAuthJwk);
|
|
265
|
+
}
|
|
266
|
+
function isWebBotAuthJwk(value) {
|
|
267
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
268
|
+
}
|
|
269
|
+
function splitTopLevel(input, separator) {
|
|
270
|
+
const parts = [];
|
|
271
|
+
let current = "";
|
|
272
|
+
let quotes = false;
|
|
273
|
+
let depth = 0;
|
|
274
|
+
for (const char of input) {
|
|
275
|
+
if (char === "\"" && depth === 0) {
|
|
276
|
+
quotes = !quotes;
|
|
277
|
+
current += char;
|
|
278
|
+
continue;
|
|
279
|
+
}
|
|
280
|
+
if (!quotes && char === "(") {
|
|
281
|
+
depth += 1;
|
|
282
|
+
current += char;
|
|
283
|
+
continue;
|
|
284
|
+
}
|
|
285
|
+
if (!quotes && char === ")" && depth > 0) {
|
|
286
|
+
depth -= 1;
|
|
287
|
+
current += char;
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
if (!quotes && depth === 0 && char === separator) {
|
|
291
|
+
parts.push(current);
|
|
292
|
+
current = "";
|
|
293
|
+
continue;
|
|
294
|
+
}
|
|
295
|
+
current += char;
|
|
296
|
+
}
|
|
297
|
+
if (current !== "") parts.push(current);
|
|
298
|
+
return parts;
|
|
299
|
+
}
|
|
300
|
+
function unquote(value) {
|
|
301
|
+
if (!value.startsWith("\"")) return value;
|
|
302
|
+
if (!value.endsWith("\"") || value.length < 2) return;
|
|
303
|
+
return value.slice(1, -1).replaceAll("\\\"", "\"");
|
|
304
|
+
}
|
|
305
|
+
function decodeSfBytes(value) {
|
|
306
|
+
const trimmed = value.trim();
|
|
307
|
+
if (!trimmed.startsWith(":") || !trimmed.endsWith(":") || trimmed.length < 2) return;
|
|
308
|
+
try {
|
|
309
|
+
const binary = atob(trimmed.slice(1, -1));
|
|
310
|
+
const bytes = new Uint8Array(binary.length);
|
|
311
|
+
for (let index = 0; index < binary.length; index += 1) bytes[index] = binary.codePointAt(index) ?? 0;
|
|
312
|
+
return bytes;
|
|
313
|
+
} catch {
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
//#endregion
|
|
318
|
+
//#region src/server/evaluations.ts
|
|
319
|
+
const DENIED = {
|
|
320
|
+
outcome: "denied",
|
|
321
|
+
denials: [{
|
|
322
|
+
role: null,
|
|
323
|
+
reason: "no-grant"
|
|
324
|
+
}],
|
|
325
|
+
alternatives: []
|
|
326
|
+
};
|
|
327
|
+
function permissionOf(tree, item) {
|
|
328
|
+
const action = typeof item.action?.name === "string" ? item.action.name : void 0;
|
|
329
|
+
if (action === void 0) return;
|
|
330
|
+
const byKey = findPermission(tree, action);
|
|
331
|
+
if (byKey !== void 0) return byKey;
|
|
332
|
+
const resource = typeof item.resource?.type === "string" ? item.resource.type : void 0;
|
|
333
|
+
if (resource === void 0) return;
|
|
334
|
+
const dotted = findPermission(tree, `${resource}.${action}`);
|
|
335
|
+
if (dotted !== void 0) return dotted;
|
|
336
|
+
return listPermissions(tree).find((leaf) => leaf.resource === resource && leaf.action === action);
|
|
337
|
+
}
|
|
338
|
+
function resourceData(item) {
|
|
339
|
+
const properties = item.resource?.properties;
|
|
340
|
+
if (properties !== null && typeof properties === "object") return properties;
|
|
341
|
+
const id = item.resource?.id;
|
|
342
|
+
if (typeof id === "string" || typeof id === "number") return { id: String(id) };
|
|
343
|
+
}
|
|
344
|
+
function resourceRef(permission, item, data) {
|
|
345
|
+
const fromRow = data !== null && typeof data === "object" && "id" in data ? data.id : void 0;
|
|
346
|
+
const fromWire = item.resource?.id;
|
|
347
|
+
const id = typeof fromRow === "string" || typeof fromRow === "number" ? String(fromRow) : typeof fromWire === "string" || typeof fromWire === "number" ? String(fromWire) : void 0;
|
|
348
|
+
return compact({
|
|
349
|
+
type: permission.resource,
|
|
350
|
+
id
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
function evaluationRow(decision) {
|
|
354
|
+
switch (decision.outcome) {
|
|
355
|
+
case "granted": return {
|
|
356
|
+
decision: true,
|
|
357
|
+
context: {
|
|
358
|
+
outcome: "granted",
|
|
359
|
+
permdock: decision
|
|
360
|
+
}
|
|
361
|
+
};
|
|
362
|
+
case "denied": return {
|
|
363
|
+
decision: false,
|
|
364
|
+
context: {
|
|
365
|
+
outcome: "denied",
|
|
366
|
+
permdock: {
|
|
367
|
+
...decision,
|
|
368
|
+
denials: wireDenials(decision.denials)
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
};
|
|
372
|
+
case "approval-required": return {
|
|
373
|
+
decision: false,
|
|
374
|
+
context: {
|
|
375
|
+
outcome: "approval-required",
|
|
376
|
+
permdock: decision
|
|
377
|
+
}
|
|
378
|
+
};
|
|
379
|
+
default: return decision;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
function applyApprovalResume(decision, permission, permdock, store, request, resource, adapter) {
|
|
383
|
+
return resumeDecision({
|
|
384
|
+
decision,
|
|
385
|
+
permission,
|
|
386
|
+
subject: permdock.subject,
|
|
387
|
+
store,
|
|
388
|
+
resource,
|
|
389
|
+
adapter,
|
|
390
|
+
token: readApprovalHeader(request.headers)
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
function evaluateOne(policy, permdock, item, store, header, adapter) {
|
|
394
|
+
const permission = permissionOf(policy.permissions, item);
|
|
395
|
+
if (permission === void 0) return Promise.resolve(DENIED);
|
|
396
|
+
const data = resourceData(item);
|
|
397
|
+
const decide = permdock.decide;
|
|
398
|
+
const decision = decide(permission, data, compact({
|
|
399
|
+
source: "endpoint",
|
|
400
|
+
adapter,
|
|
401
|
+
trusted: false,
|
|
402
|
+
boundary: "decision-endpoint"
|
|
403
|
+
}));
|
|
404
|
+
return resumeDecision({
|
|
405
|
+
decision,
|
|
406
|
+
permission,
|
|
407
|
+
subject: permdock.subject,
|
|
408
|
+
store,
|
|
409
|
+
resource: resourceRef(permission, item, data),
|
|
410
|
+
adapter,
|
|
411
|
+
token: header,
|
|
412
|
+
consume: false
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
async function resolvePermdock(options, request, tenant) {
|
|
416
|
+
if (options.resolve !== void 0) {
|
|
417
|
+
const permdock = await options.resolve(request);
|
|
418
|
+
return tenant === void 0 ? permdock : permdock.tenant(tenant);
|
|
419
|
+
}
|
|
420
|
+
if (options.getPermDock !== void 0) return options.getPermDock(tenant === void 0 ? void 0 : { tenant });
|
|
421
|
+
throw new TypeError("evaluations handler needs resolve or getPermDock");
|
|
422
|
+
}
|
|
423
|
+
function createEvaluationsHandler(options) {
|
|
424
|
+
const adapter = options.adapter ?? "server";
|
|
425
|
+
const maxEvaluations = options.maxEvaluations ?? 256;
|
|
426
|
+
const POST = async (request) => {
|
|
427
|
+
let body;
|
|
428
|
+
try {
|
|
429
|
+
body = await request.json();
|
|
430
|
+
} catch {
|
|
431
|
+
return validationProblem("evaluations body was not valid JSON");
|
|
432
|
+
}
|
|
433
|
+
if (body === null || typeof body !== "object" || Array.isArray(body)) return validationProblem("evaluations body must be an object");
|
|
434
|
+
const evaluations = body.evaluations;
|
|
435
|
+
if (evaluations === void 0) return validationProblem("evaluations array is required");
|
|
436
|
+
if (!Array.isArray(evaluations)) return validationProblem("evaluations must be an array");
|
|
437
|
+
if (evaluations.length > maxEvaluations) return batchTooLarge(maxEvaluations);
|
|
438
|
+
const header = readApprovalHeader(request.headers);
|
|
439
|
+
let permdock;
|
|
440
|
+
try {
|
|
441
|
+
permdock = await resolvePermdock(options, request);
|
|
442
|
+
} catch (error) {
|
|
443
|
+
if (error instanceof InvalidSignatureError) return error.response;
|
|
444
|
+
throw error;
|
|
445
|
+
}
|
|
446
|
+
const rows = await Promise.all(evaluations.map(async (item) => {
|
|
447
|
+
const entry = item !== null && typeof item === "object" ? item : {};
|
|
448
|
+
return evaluationRow(await evaluateOne(options.policy, permdock, entry, options.store, header, adapter));
|
|
449
|
+
}));
|
|
450
|
+
return Response.json({ evaluations: rows });
|
|
451
|
+
};
|
|
452
|
+
const GET = async (request) => {
|
|
453
|
+
const url = new URL(request.url);
|
|
454
|
+
if (url.pathname.includes("authzen-configuration")) {
|
|
455
|
+
const origin = url.origin;
|
|
456
|
+
return Response.json({
|
|
457
|
+
policy_decision_point: origin,
|
|
458
|
+
access_evaluation_endpoint: `${origin}/access/v1/evaluation`,
|
|
459
|
+
access_evaluations_endpoint: `${origin}/access/v1/evaluations`
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
const tenant = url.searchParams.get("tenant") ?? void 0;
|
|
463
|
+
let permdock;
|
|
464
|
+
try {
|
|
465
|
+
permdock = await resolvePermdock(options, request, tenant);
|
|
466
|
+
} catch (error) {
|
|
467
|
+
if (error instanceof InvalidSignatureError) return error.response;
|
|
468
|
+
throw error;
|
|
469
|
+
}
|
|
470
|
+
const snapshot = permdock.snapshot();
|
|
471
|
+
return Response.json(await Promise.resolve(snapshot));
|
|
472
|
+
};
|
|
473
|
+
return {
|
|
474
|
+
POST,
|
|
475
|
+
GET
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
//#endregion
|
|
479
|
+
export { invalidSignatureProblem as a, discoverViaSignatureAgent as i, createEvaluationsHandler as n, invalidSignatureResponse as o, InvalidSignatureError as r, verifyWebBotAuth as s, applyApprovalResume as t };
|