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,53 @@
|
|
|
1
|
+
import { a as listArg, i as globalArgs, t as COMMAND_DESCRIPTIONS } from "./commands-BMh_Etm2.js";
|
|
2
|
+
import { n as ask, t as CANCELLED } from "./prompt-CXYhLfsS.js";
|
|
3
|
+
import { defineCommand } from "citty";
|
|
4
|
+
//#region src/cli/commands/doctor.ts
|
|
5
|
+
function doctor(ctx) {
|
|
6
|
+
return defineCommand({
|
|
7
|
+
meta: {
|
|
8
|
+
name: "doctor",
|
|
9
|
+
description: COMMAND_DESCRIPTIONS.doctor
|
|
10
|
+
},
|
|
11
|
+
args: {
|
|
12
|
+
...globalArgs,
|
|
13
|
+
only: {
|
|
14
|
+
type: "string",
|
|
15
|
+
description: "Check codes or groups to run, repeatable",
|
|
16
|
+
valueHint: "codes"
|
|
17
|
+
},
|
|
18
|
+
fix: {
|
|
19
|
+
type: "boolean",
|
|
20
|
+
description: "Apply safe fixes: install skills, regenerate the catalog"
|
|
21
|
+
},
|
|
22
|
+
strict: {
|
|
23
|
+
type: "boolean",
|
|
24
|
+
description: "Exit 1 on warnings too"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
async run({ args: parsed, rawArgs }) {
|
|
28
|
+
let fix = parsed.fix === true;
|
|
29
|
+
if (fix && ctx.interactive) {
|
|
30
|
+
const answer = await ask(`Install the Agent Skills and regenerate the catalog in ${ctx.cwd}?`);
|
|
31
|
+
if (answer === void 0) {
|
|
32
|
+
ctx.report(CANCELLED);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
fix = answer;
|
|
36
|
+
}
|
|
37
|
+
const result = await (await import("./doctor-BGle8Gqi.js")).runDoctor({
|
|
38
|
+
cwd: ctx.cwd,
|
|
39
|
+
config: ctx.config,
|
|
40
|
+
only: listArg(rawArgs, "only"),
|
|
41
|
+
json: ctx.json,
|
|
42
|
+
fix,
|
|
43
|
+
strict: parsed.strict === true,
|
|
44
|
+
color: ctx.color,
|
|
45
|
+
now: ctx.now,
|
|
46
|
+
io: ctx.io
|
|
47
|
+
});
|
|
48
|
+
ctx.report(result);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
//#endregion
|
|
53
|
+
export { doctor };
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { _r as Condition, hr as Subject, tn as WhereResult } from "../policy-CInmNGkM.js";
|
|
2
|
+
import { n as WithSubjectOptions, r as RelationsMapping, t as RowCheck } from "../row-check-BajTgQZ-.js";
|
|
3
|
+
import { t as MembershipsMapping } from "../compile-CQbvyIBr.js";
|
|
4
|
+
import { SQL, Table } from "drizzle-orm";
|
|
5
|
+
//#region src/drizzle/types.d.ts
|
|
6
|
+
/** A column of the Drizzle table `T` or an `SQL` expression; anything for a structural stand-in. */
|
|
7
|
+
type DrizzleColumnOf<T> = T extends Table ? T["_"]["columns"][keyof T["_"]["columns"]] | SQL : unknown;
|
|
8
|
+
type DrizzleWhereOptions<T = unknown> = {
|
|
9
|
+
/** Condition field to column of the table passed to `toWhere`. */
|
|
10
|
+
readonly columns?: Readonly<Record<string, DrizzleColumnOf<T>>>;
|
|
11
|
+
readonly subject?: Subject;
|
|
12
|
+
readonly memberships?: MembershipsMapping;
|
|
13
|
+
/** Where the relation graph lives; graph grants compile to Postgres subqueries with it and are refused without. */
|
|
14
|
+
readonly relations?: RelationsMapping;
|
|
15
|
+
readonly now?: number;
|
|
16
|
+
readonly operators?: DrizzleOperators;
|
|
17
|
+
};
|
|
18
|
+
type DrizzleOperators = {
|
|
19
|
+
readonly and: (...args: unknown[]) => unknown;
|
|
20
|
+
readonly or: (...args: unknown[]) => unknown;
|
|
21
|
+
readonly not: (value: unknown) => unknown;
|
|
22
|
+
readonly eq: (column: unknown, value: unknown) => unknown;
|
|
23
|
+
readonly ne: (column: unknown, value: unknown) => unknown;
|
|
24
|
+
readonly gt: (column: unknown, value: unknown) => unknown;
|
|
25
|
+
readonly gte: (column: unknown, value: unknown) => unknown;
|
|
26
|
+
readonly lt: (column: unknown, value: unknown) => unknown;
|
|
27
|
+
readonly lte: (column: unknown, value: unknown) => unknown;
|
|
28
|
+
readonly inArray: (column: unknown, values: readonly unknown[]) => unknown;
|
|
29
|
+
readonly notInArray: (column: unknown, values: readonly unknown[]) => unknown;
|
|
30
|
+
readonly isNull: (column: unknown) => unknown;
|
|
31
|
+
readonly isNotNull: (column: unknown) => unknown;
|
|
32
|
+
readonly like: (column: unknown, value: unknown) => unknown;
|
|
33
|
+
readonly sql: (strings: TemplateStringsArray, ...values: unknown[]) => unknown;
|
|
34
|
+
};
|
|
35
|
+
type DrizzleWithSubjectOptions = WithSubjectOptions & {
|
|
36
|
+
/** `import * as operators from 'drizzle-orm'`, on runtimes without `require`. */
|
|
37
|
+
readonly operators?: DrizzleOperators;
|
|
38
|
+
};
|
|
39
|
+
//#endregion
|
|
40
|
+
//#region src/drizzle/to-where.d.ts
|
|
41
|
+
/** Compiles a condition into a Drizzle `SQL` filter over `table`; no grant compiles to `false`. */
|
|
42
|
+
export declare function toWhere<T extends object>(input: Condition | WhereResult, table: T, options?: DrizzleWhereOptions<T>): SQL;
|
|
43
|
+
type DrizzleDatabase<Tx> = {
|
|
44
|
+
transaction<T>(fn: (tx: Tx) => Promise<T>): Promise<T>;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Runs `fn` in a transaction whose role and claims are `permdock.subject`'s, so the generated
|
|
48
|
+
* RLS policies decide for the same subject as the in-process checks.
|
|
49
|
+
*/
|
|
50
|
+
export declare function withSubject<Tx extends {
|
|
51
|
+
execute(query: never): unknown;
|
|
52
|
+
}, T>(db: DrizzleDatabase<Tx>, permdock: {
|
|
53
|
+
readonly subject: Subject;
|
|
54
|
+
}, fn: (tx: Tx) => Promise<T>, options?: DrizzleWithSubjectOptions): Promise<T>;
|
|
55
|
+
type DrizzleSelectable = {
|
|
56
|
+
select(fields: Record<string, unknown>): {
|
|
57
|
+
from(table: never): {
|
|
58
|
+
where(where: unknown): {
|
|
59
|
+
limit(count: number): PromiseLike<readonly {
|
|
60
|
+
readonly granted?: unknown;
|
|
61
|
+
}[]>;
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* One query for one row: `{ found: false }` when `key` matches nothing, otherwise whether the
|
|
68
|
+
* permission filter keeps the row. Throws when `key` matches more than one row.
|
|
69
|
+
*/
|
|
70
|
+
export declare function checkRow<T extends object>(db: DrizzleSelectable, table: T, input: Condition | WhereResult, key: SQL, options?: DrizzleWhereOptions<T>): Promise<RowCheck>;
|
|
71
|
+
//#endregion
|
|
72
|
+
export type { DrizzleOperators, DrizzleWhereOptions, DrizzleWithSubjectOptions, MembershipsMapping, RelationsMapping, RowCheck, WithSubjectOptions };
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { t as compact } from "../compact-y6vfu2_f.js";
|
|
2
|
+
import { x as assertSafeKey } from "../permissions-DC7GROPA.js";
|
|
3
|
+
import { n as escapeLike, t as compileWhere } from "../compile-D22iwvuV.js";
|
|
4
|
+
import { i as rowCheckFrom, r as subjectStatements, t as statementTemplate } from "../subject-settings-xt7V845g.js";
|
|
5
|
+
//#region src/drizzle/to-where.ts
|
|
6
|
+
function loadOperators(injected) {
|
|
7
|
+
if (injected !== void 0) return injected;
|
|
8
|
+
const loader = globalThis.process?.getBuiltinModule?.("node:module");
|
|
9
|
+
try {
|
|
10
|
+
if (loader === void 0) throw new Error("no module loader");
|
|
11
|
+
return loader.createRequire(import.meta.url)("drizzle-orm");
|
|
12
|
+
} catch {
|
|
13
|
+
throw new Error("PermDock: permdock/drizzle requires the drizzle-orm peer; pass `operators` on runtimes without require");
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function ident(name) {
|
|
17
|
+
assertSafeKey(name, "sql identifier");
|
|
18
|
+
if (!/^[A-Za-z_][A-Za-z0-9_]*$/u.test(name)) throw new Error(`PermDock: unsafe SQL identifier '${name}'`);
|
|
19
|
+
return name;
|
|
20
|
+
}
|
|
21
|
+
function column(table, field, columns) {
|
|
22
|
+
assertSafeKey(field, "condition field");
|
|
23
|
+
const mapped = (columns !== void 0 && Object.hasOwn(columns, field) ? columns[field] : void 0) ?? (Object.hasOwn(table, field) ? table[field] : void 0);
|
|
24
|
+
if (mapped === void 0 || typeof mapped === "function") throw new Error(`PermDock: unknown column '${field}'`);
|
|
25
|
+
return mapped;
|
|
26
|
+
}
|
|
27
|
+
/** Drizzle's Postgres array columns (`text().array()`) report `dataType: 'array'`. */
|
|
28
|
+
function isArrayColumn(col) {
|
|
29
|
+
if (col === null || typeof col !== "object") return false;
|
|
30
|
+
const { dataType, dimensions } = col;
|
|
31
|
+
return dataType === "array" || typeof dimensions === "number" && dimensions > 0;
|
|
32
|
+
}
|
|
33
|
+
function tagged(parts, ops) {
|
|
34
|
+
const strings = [""];
|
|
35
|
+
const values = [];
|
|
36
|
+
for (const part of parts) if ("text" in part) strings[strings.length - 1] += part.text;
|
|
37
|
+
else {
|
|
38
|
+
values.push(part.value);
|
|
39
|
+
strings.push("");
|
|
40
|
+
}
|
|
41
|
+
const template = strings;
|
|
42
|
+
Object.defineProperty(template, "raw", { value: strings });
|
|
43
|
+
return ops.sql(template, ...values);
|
|
44
|
+
}
|
|
45
|
+
function existsSql(node, table, options, ops) {
|
|
46
|
+
const m = (name) => `m.${ident(name)}`;
|
|
47
|
+
const parts = [
|
|
48
|
+
{ text: `exists (select 1 from ${ident(node.table)} m where ${m(node.rowColumn)} = ` },
|
|
49
|
+
{ value: column(table, node.rowField, options.columns) },
|
|
50
|
+
{ text: ` and ${m(node.user)} = ` },
|
|
51
|
+
{ value: node.userValue }
|
|
52
|
+
];
|
|
53
|
+
if (node.roles.length > 0) {
|
|
54
|
+
parts.push({ text: ` and ${m(node.role)} in (` });
|
|
55
|
+
for (const [index, role] of node.roles.entries()) {
|
|
56
|
+
if (index > 0) parts.push({ text: ", " });
|
|
57
|
+
parts.push({ value: role });
|
|
58
|
+
}
|
|
59
|
+
parts.push({ text: ")" });
|
|
60
|
+
}
|
|
61
|
+
if (node.expiresAt !== void 0) {
|
|
62
|
+
const expires = m(node.expiresAt);
|
|
63
|
+
parts.push({ text: ` and (${expires} is null or ${expires} > ` }, { value: node.now }, { text: ")" });
|
|
64
|
+
}
|
|
65
|
+
if (node.tenantColumn !== void 0 && node.tenantValue !== void 0) {
|
|
66
|
+
const tenant = m(node.tenantColumn);
|
|
67
|
+
parts.push({ text: ` and (${tenant} is null or ${tenant} = ` }, { value: node.tenantValue }, { text: ")" });
|
|
68
|
+
}
|
|
69
|
+
if (node.resourceColumn !== void 0 && node.resourceValue !== void 0) parts.push({ text: ` and ${m(node.resourceColumn)} = ` }, { value: node.resourceValue });
|
|
70
|
+
parts.push({ text: ")" });
|
|
71
|
+
return tagged(parts, ops);
|
|
72
|
+
}
|
|
73
|
+
function containsSql(col, value, ops) {
|
|
74
|
+
if (isArrayColumn(col)) return tagged([
|
|
75
|
+
{ value },
|
|
76
|
+
{ text: " = any(" },
|
|
77
|
+
{ value: col },
|
|
78
|
+
{ text: ")" }
|
|
79
|
+
], ops);
|
|
80
|
+
if (typeof value === "string") return ops.like(col, `%${escapeLike(value)}%`);
|
|
81
|
+
return tagged([
|
|
82
|
+
{ value: col },
|
|
83
|
+
{ text: " @> " },
|
|
84
|
+
{ value }
|
|
85
|
+
], ops);
|
|
86
|
+
}
|
|
87
|
+
function render(node, table, options, ops) {
|
|
88
|
+
switch (node.kind) {
|
|
89
|
+
case "never": return ops.sql`false`;
|
|
90
|
+
case "always": return ops.sql`true`;
|
|
91
|
+
case "isNull": {
|
|
92
|
+
const col = column(table, node.field, options.columns);
|
|
93
|
+
return node.negated ? ops.isNotNull(col) : ops.isNull(col);
|
|
94
|
+
}
|
|
95
|
+
case "and": return ops.and(...node.items.map((item) => render(item, table, options, ops)));
|
|
96
|
+
case "or": return ops.or(...node.items.map((item) => render(item, table, options, ops)));
|
|
97
|
+
case "not": return ops.not(render(node.item, table, options, ops));
|
|
98
|
+
case "exists": return existsSql(node, table, options, ops);
|
|
99
|
+
case "sql": return tagged(node.parts.map((part) => {
|
|
100
|
+
if ("text" in part) return part;
|
|
101
|
+
if ("column" in part) return { value: column(table, part.column, options.columns) };
|
|
102
|
+
return { value: "subject" in part ? node.subject : part.value };
|
|
103
|
+
}), ops);
|
|
104
|
+
case "compare": {
|
|
105
|
+
const col = column(table, node.field, options.columns);
|
|
106
|
+
switch (node.op) {
|
|
107
|
+
case "eq": return ops.eq(col, node.value);
|
|
108
|
+
case "ne": return ops.ne(col, node.value);
|
|
109
|
+
case "gt": return ops.gt(col, node.value);
|
|
110
|
+
case "gte": return ops.gte(col, node.value);
|
|
111
|
+
case "lt": return ops.lt(col, node.value);
|
|
112
|
+
case "lte": return ops.lte(col, node.value);
|
|
113
|
+
case "in": return ops.inArray(col, node.value);
|
|
114
|
+
case "notIn": return ops.notInArray(col, node.value);
|
|
115
|
+
case "contains": return containsSql(col, node.value, ops);
|
|
116
|
+
/* v8 ignore next 4 */
|
|
117
|
+
default: {
|
|
118
|
+
const exhaustive = node.op;
|
|
119
|
+
throw new Error(`PermDock: unknown compare '${String(exhaustive)}'`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/* v8 ignore next 6 */
|
|
124
|
+
default: throw new Error(`PermDock: unknown compiled node '${String(node)}'`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/** Compiles a condition into a Drizzle `SQL` filter over `table`; no grant compiles to `false`. */
|
|
128
|
+
function toWhere(input, table, options = {}) {
|
|
129
|
+
return render(compileWhere(input, compact({
|
|
130
|
+
subject: options.subject,
|
|
131
|
+
memberships: options.memberships,
|
|
132
|
+
now: options.now,
|
|
133
|
+
relations: options.relations
|
|
134
|
+
})), table, options, loadOperators(options.operators));
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Runs `fn` in a transaction whose role and claims are `permdock.subject`'s, so the generated
|
|
138
|
+
* RLS policies decide for the same subject as the in-process checks.
|
|
139
|
+
*/
|
|
140
|
+
function withSubject(db, permdock, fn, options = {}) {
|
|
141
|
+
const statements = subjectStatements(permdock, options);
|
|
142
|
+
const { sql } = loadOperators(options.operators);
|
|
143
|
+
return db.transaction(async (tx) => {
|
|
144
|
+
const execute = tx.execute.bind(tx);
|
|
145
|
+
for (const statement of statements) await execute(sql(statementTemplate(statement), ...statement.values));
|
|
146
|
+
return fn(tx);
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* One query for one row: `{ found: false }` when `key` matches nothing, otherwise whether the
|
|
151
|
+
* permission filter keeps the row. Throws when `key` matches more than one row.
|
|
152
|
+
*/
|
|
153
|
+
async function checkRow(db, table, input, key, options = {}) {
|
|
154
|
+
const { sql } = loadOperators(options.operators);
|
|
155
|
+
const filter = toWhere(input, table, options);
|
|
156
|
+
const rows = await db.select({ granted: sql`coalesce((${filter}), false)` }).from(table).where(key).limit(2);
|
|
157
|
+
return rowCheckFrom(rows);
|
|
158
|
+
}
|
|
159
|
+
//#endregion
|
|
160
|
+
export { checkRow, toWhere, withSubject };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
//#region src/core/duration.ts
|
|
2
|
+
/**
|
|
3
|
+
* Parses a duration string (`'30s'`, `'15m'`, `'4h'`, `'7d'`, `'2w'`) into
|
|
4
|
+
* whole seconds. Fail-closed: a malformed or non-positive duration is
|
|
5
|
+
* `undefined`, and every caller treats that as "no bound", never a default.
|
|
6
|
+
*/
|
|
7
|
+
const UNITS = {
|
|
8
|
+
s: 1,
|
|
9
|
+
m: 60,
|
|
10
|
+
h: 3600,
|
|
11
|
+
d: 86400,
|
|
12
|
+
w: 604800
|
|
13
|
+
};
|
|
14
|
+
function parseDuration(input) {
|
|
15
|
+
if (typeof input === "number") return Number.isFinite(input) && input > 0 ? Math.floor(input) : void 0;
|
|
16
|
+
if (typeof input !== "string") return;
|
|
17
|
+
const match = /^(\d+)(s|m|h|d|w)$/u.exec(input.trim());
|
|
18
|
+
if (match === null) return;
|
|
19
|
+
const amount = Number(match[1]);
|
|
20
|
+
const unit = UNITS[match[2] ?? ""];
|
|
21
|
+
if (unit === void 0 || !Number.isFinite(amount) || amount <= 0) return;
|
|
22
|
+
return amount * unit;
|
|
23
|
+
}
|
|
24
|
+
//#endregion
|
|
25
|
+
export { parseDuration as t };
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { $ as DecisionSink, C as Policy, E as PolicyVocabulary, Zt as PermDock, at as LimitStore, ct as MembershipSource, ft as RelationSource, mr as Principal, pt as RoleSource, sn as PolicySource, tt as EntitlementSource, xt as SnapshotSource } from "../policy-CInmNGkM.js";
|
|
2
|
+
import { d as Permission } from "../permissions-B4apnahQ.js";
|
|
3
|
+
import { f as ApprovalStore } from "../types-B8w5PFtS.js";
|
|
4
|
+
import { n as RevocationFeed } from "../revocations-Cy06JNx2.js";
|
|
5
|
+
import { o as OtelWrap } from "../types-B9dmiiab.js";
|
|
6
|
+
import { r as PdpFactory } from "../types-BvBk1wgn.js";
|
|
7
|
+
import { S as ConnectionOptions, b as Connection, g as discoverViaSignatureAgent, h as WebBotAuthVerifier, n as OpenApiHooks, o as TenantOption, r as ProtectOptions, u as InvalidSignatureError, y as verifyWebBotAuth } from "../create-BKF3dgFk.js";
|
|
8
|
+
import { Elysia } from "elysia";
|
|
9
|
+
//#region src/elysia/create.d.ts
|
|
10
|
+
type ElysiaCtx = {
|
|
11
|
+
readonly request: Request;
|
|
12
|
+
readonly body?: unknown;
|
|
13
|
+
readonly params?: Readonly<Record<string, string | undefined>>;
|
|
14
|
+
};
|
|
15
|
+
type ElysiaPermDockOptions<TUser = unknown> = {
|
|
16
|
+
readonly subject: (ctx: ElysiaCtx) => TUser | Promise<TUser>;
|
|
17
|
+
readonly tenant?: TenantOption<ElysiaCtx>;
|
|
18
|
+
readonly memberships?: MembershipSource | readonly MembershipSource[];
|
|
19
|
+
/** The object graph for relation grants that walk a parent chain; without it they deny. */
|
|
20
|
+
readonly relations?: RelationSource;
|
|
21
|
+
readonly entitlements?: EntitlementSource;
|
|
22
|
+
readonly customRoles?: RoleSource;
|
|
23
|
+
/** Hosted grants, read once per instance; see `PolicySource`. */
|
|
24
|
+
readonly policies?: PolicySource;
|
|
25
|
+
readonly store?: ApprovalStore;
|
|
26
|
+
readonly sink?: DecisionSink;
|
|
27
|
+
readonly limits?: LimitStore;
|
|
28
|
+
/** `createPermDock` from `permdock/pdp`; `protect` then decides delegated permissions remotely. */
|
|
29
|
+
readonly pdp?: PdpFactory;
|
|
30
|
+
/** Accepted for adapter parity; not read by this adapter. */
|
|
31
|
+
readonly snapshots?: SnapshotSource;
|
|
32
|
+
/** `(permdock) => withOtel(permdock, options)` from `permdock/otel`. */
|
|
33
|
+
readonly otel?: OtelWrap;
|
|
34
|
+
/** `(request) => verifyWebBotAuth(request, options)`; a verified bot becomes the actor. */
|
|
35
|
+
readonly webBotAuth?: WebBotAuthVerifier;
|
|
36
|
+
/** Ends or revalidates open sockets. */
|
|
37
|
+
readonly revocations?: RevocationFeed;
|
|
38
|
+
};
|
|
39
|
+
/** The `ws` Elysia passes to `.ws` handlers; `data` is the upgrade context. */
|
|
40
|
+
type ElysiaSocket = {
|
|
41
|
+
readonly data: ElysiaCtx;
|
|
42
|
+
close(code?: number, reason?: string): unknown;
|
|
43
|
+
};
|
|
44
|
+
type ElysiaContext<V extends PolicyVocabulary = PolicyVocabulary> = ElysiaCtx & {
|
|
45
|
+
permdock: PermDock<V>;
|
|
46
|
+
permdockData?: unknown;
|
|
47
|
+
};
|
|
48
|
+
type ElysiaProtect = (permission: Permission, loadData?: (ctx: ElysiaCtx) => unknown, protectOptions?: ProtectOptions) => (ctx: ElysiaCtx) => Promise<Response | undefined>;
|
|
49
|
+
/** The `permdock()` plugin: its global derive types `permdock` in every later handler. */
|
|
50
|
+
type ElysiaPermDockPlugin<V extends PolicyVocabulary = PolicyVocabulary> = Elysia<"", {
|
|
51
|
+
decorator: Record<never, never>;
|
|
52
|
+
store: Record<never, never>;
|
|
53
|
+
derive: {
|
|
54
|
+
readonly permdock: PermDock<V>;
|
|
55
|
+
};
|
|
56
|
+
resolve: Record<never, never>;
|
|
57
|
+
}>;
|
|
58
|
+
type ElysiaPermDock<V extends PolicyVocabulary = PolicyVocabulary> = {
|
|
59
|
+
readonly permdock: () => ElysiaPermDockPlugin<V>;
|
|
60
|
+
readonly protect: ElysiaProtect;
|
|
61
|
+
/**
|
|
62
|
+
* One connection per socket: the same promise for every handler
|
|
63
|
+
* of that socket; closes it with `1008` when the connection aborts.
|
|
64
|
+
*/
|
|
65
|
+
readonly connection: (ws: ElysiaSocket, connectionOptions?: ConnectionOptions) => Promise<Connection>;
|
|
66
|
+
readonly permdockHandler: () => Elysia;
|
|
67
|
+
readonly openapi: OpenApiHooks;
|
|
68
|
+
};
|
|
69
|
+
export declare function createPermDock<TUser, TPrincipal extends Principal = Principal, V extends PolicyVocabulary = PolicyVocabulary>(policy: Policy<TUser, TPrincipal, V>, options: ElysiaPermDockOptions<TUser>): ElysiaPermDock<V>;
|
|
70
|
+
//#endregion
|
|
71
|
+
export { type ElysiaContext, type ElysiaCtx, type ElysiaPermDock, type ElysiaPermDockOptions, type ElysiaProtect, type ElysiaSocket, InvalidSignatureError, discoverViaSignatureAgent, verifyWebBotAuth };
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { t as compact } from "../compact-y6vfu2_f.js";
|
|
2
|
+
import { i as discoverViaSignatureAgent, r as InvalidSignatureError, s as verifyWebBotAuth } from "../evaluations-DsAU9ppl.js";
|
|
3
|
+
import { r as tenantScope, t as createKernel } from "../create-CSkhDU9T.js";
|
|
4
|
+
import { t as problemFromError } from "../map-error-RJ3ZsUyA.js";
|
|
5
|
+
import { i as onRevoked, t as POLICY_VIOLATION } from "../stream-Q_xlB6Ko.js";
|
|
6
|
+
import { Elysia } from "elysia";
|
|
7
|
+
//#region src/elysia/create.ts
|
|
8
|
+
function createPermDock(policy, options) {
|
|
9
|
+
const contexts = /* @__PURE__ */ new WeakMap();
|
|
10
|
+
const bound = /* @__PURE__ */ new WeakMap();
|
|
11
|
+
const seed = globalThis.crypto.randomUUID();
|
|
12
|
+
const kernel = createKernel(policy, compact({
|
|
13
|
+
subject: (request) => {
|
|
14
|
+
const ctx = contexts.get(request);
|
|
15
|
+
return ctx === void 0 ? null : options.subject(ctx);
|
|
16
|
+
},
|
|
17
|
+
memberships: options.memberships,
|
|
18
|
+
relations: options.relations,
|
|
19
|
+
entitlements: options.entitlements,
|
|
20
|
+
customRoles: options.customRoles,
|
|
21
|
+
policies: options.policies,
|
|
22
|
+
store: options.store,
|
|
23
|
+
sink: options.sink,
|
|
24
|
+
limits: options.limits,
|
|
25
|
+
pdp: options.pdp,
|
|
26
|
+
webBotAuth: options.webBotAuth,
|
|
27
|
+
revocations: options.revocations,
|
|
28
|
+
adapter: "elysia",
|
|
29
|
+
wrap: options.otel
|
|
30
|
+
}));
|
|
31
|
+
const bind = (ctx) => {
|
|
32
|
+
const hit = bound.get(ctx);
|
|
33
|
+
if (hit !== void 0) return hit;
|
|
34
|
+
const next = toRequest(ctx);
|
|
35
|
+
bound.set(ctx, next);
|
|
36
|
+
contexts.set(next, ctx);
|
|
37
|
+
return next;
|
|
38
|
+
};
|
|
39
|
+
const scopeOf = (ctx) => tenantScope(options.tenant, ctx);
|
|
40
|
+
const decorate = (ctx, instance, data) => {
|
|
41
|
+
const scoped = ctx;
|
|
42
|
+
scoped.permdock = instance;
|
|
43
|
+
if (data !== void 0) scoped.permdockData = data;
|
|
44
|
+
};
|
|
45
|
+
const permdock = () => new Elysia({
|
|
46
|
+
name: "permdock",
|
|
47
|
+
seed
|
|
48
|
+
}).derive({ as: "global" }, async (ctx) => {
|
|
49
|
+
const instance = await kernel.permdock(bind(ctx), await scopeOf(ctx));
|
|
50
|
+
decorate(ctx, instance);
|
|
51
|
+
return { permdock: instance };
|
|
52
|
+
}).onError({ as: "global" }, ({ error }) => problemFromError(error));
|
|
53
|
+
const protect = (permission, loadData, protectOptions) => async (ctx) => {
|
|
54
|
+
const guard = await kernel.protect(permission, loadData === void 0 ? void 0 : () => loadData(ctx), protectOptions)(bind(ctx), await scopeOf(ctx));
|
|
55
|
+
if (!guard.ok) return guard.response;
|
|
56
|
+
decorate(ctx, guard.permdock, guard.data);
|
|
57
|
+
};
|
|
58
|
+
const sockets = /* @__PURE__ */ new WeakMap();
|
|
59
|
+
const connection = (ws, connectionOptions) => {
|
|
60
|
+
const hit = sockets.get(ws.data);
|
|
61
|
+
if (hit !== void 0) return hit;
|
|
62
|
+
const opened = (async () => {
|
|
63
|
+
const conn = await kernel.connection(bind(ws.data), connectionOptions, await scopeOf(ws.data));
|
|
64
|
+
onRevoked(conn, (problem) => {
|
|
65
|
+
ws.close(POLICY_VIOLATION, problem.type);
|
|
66
|
+
});
|
|
67
|
+
return conn;
|
|
68
|
+
})();
|
|
69
|
+
sockets.set(ws.data, opened);
|
|
70
|
+
return opened;
|
|
71
|
+
};
|
|
72
|
+
const permdockHandler = () => {
|
|
73
|
+
const { POST, GET } = kernel.permdockHandler((request) => {
|
|
74
|
+
const ctx = contexts.get(request);
|
|
75
|
+
return ctx === void 0 ? { tenant: void 0 } : scopeOf(ctx);
|
|
76
|
+
});
|
|
77
|
+
return new Elysia({
|
|
78
|
+
name: "permdock-handler",
|
|
79
|
+
seed
|
|
80
|
+
}).post("/", (ctx) => POST(bind(ctx))).get("/", (ctx) => GET(bind(ctx)));
|
|
81
|
+
};
|
|
82
|
+
return {
|
|
83
|
+
permdock,
|
|
84
|
+
protect,
|
|
85
|
+
connection,
|
|
86
|
+
permdockHandler,
|
|
87
|
+
openapi: kernel.openapi
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function toRequest(ctx) {
|
|
91
|
+
const method = ctx.request.method;
|
|
92
|
+
if (method === "GET" || method === "HEAD" || ctx.body === void 0) return ctx.request;
|
|
93
|
+
const headers = new Headers(ctx.request.headers);
|
|
94
|
+
const body = typeof ctx.body === "string" ? ctx.body : JSON.stringify(ctx.body);
|
|
95
|
+
if (!headers.has("content-type")) headers.set("content-type", "application/json");
|
|
96
|
+
return new Request(ctx.request.url, {
|
|
97
|
+
method,
|
|
98
|
+
headers,
|
|
99
|
+
body
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
//#endregion
|
|
103
|
+
export { InvalidSignatureError, createPermDock, discoverViaSignatureAgent, verifyWebBotAuth };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { stripVTControlCharacters } from "node:util";
|
|
2
|
+
//#region src/cli/errors.ts
|
|
3
|
+
var CliError = class extends Error {
|
|
4
|
+
kind;
|
|
5
|
+
constructor(kind, message, options) {
|
|
6
|
+
super(message, options);
|
|
7
|
+
this.name = "CliError";
|
|
8
|
+
this.kind = kind;
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
const TITLES = {
|
|
12
|
+
usage: "Usage or configuration error",
|
|
13
|
+
unavailable: "A database or service the command needs did not answer"
|
|
14
|
+
};
|
|
15
|
+
/** An unclassified error is a usage error: a module that throws while loading is the project's to fix. */
|
|
16
|
+
function cliErrorKind(error) {
|
|
17
|
+
return error instanceof CliError ? error.kind : "usage";
|
|
18
|
+
}
|
|
19
|
+
function exitCodeOf(kind) {
|
|
20
|
+
return kind === "usage" ? 2 : 1;
|
|
21
|
+
}
|
|
22
|
+
function cliProblem(kind, message, command) {
|
|
23
|
+
return {
|
|
24
|
+
type: `https://permdock.dev/problems/cli-${kind}`,
|
|
25
|
+
title: TITLES[kind],
|
|
26
|
+
detail: stripVTControlCharacters(message),
|
|
27
|
+
...command === void 0 ? {} : { command },
|
|
28
|
+
exitCode: exitCodeOf(kind)
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The result a command reports for a usage error it caught. A `CliError`
|
|
33
|
+
* propagates instead, so `run()` prints it, as Problem Details under `--json`.
|
|
34
|
+
*/
|
|
35
|
+
function usageResult(error) {
|
|
36
|
+
if (error instanceof CliError) throw error;
|
|
37
|
+
return {
|
|
38
|
+
code: 2,
|
|
39
|
+
output: error instanceof Error ? error.message : String(error)
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
//#endregion
|
|
43
|
+
export { usageResult as a, exitCodeOf as i, cliErrorKind as n, cliProblem as r, CliError as t };
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { Mn as Decision, Pt as WireDenial, hr as Subject } from "./policy-CInmNGkM.js";
|
|
2
|
+
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
3
|
+
//#region src/core/errors.d.ts
|
|
4
|
+
/** Where and how a human approves; carries no secret. */
|
|
5
|
+
type ApprovalHint = {
|
|
6
|
+
readonly at?: string;
|
|
7
|
+
readonly hint?: string;
|
|
8
|
+
};
|
|
9
|
+
type ProblemDetails = {
|
|
10
|
+
readonly type: string;
|
|
11
|
+
readonly title: string;
|
|
12
|
+
readonly status: number;
|
|
13
|
+
readonly detail: string;
|
|
14
|
+
readonly instance?: string;
|
|
15
|
+
readonly permission?: string;
|
|
16
|
+
readonly scope?: string;
|
|
17
|
+
readonly resource?: {
|
|
18
|
+
readonly type: string;
|
|
19
|
+
readonly id?: string;
|
|
20
|
+
};
|
|
21
|
+
readonly denials?: readonly WireDenial[];
|
|
22
|
+
readonly alternatives?: readonly string[];
|
|
23
|
+
readonly reason?: string;
|
|
24
|
+
readonly token?: string;
|
|
25
|
+
readonly issues?: readonly StandardSchemaV1.Issue[];
|
|
26
|
+
readonly approval?: ApprovalHint;
|
|
27
|
+
/** RFC 9470 step-up parameters on `step-up-required`. */
|
|
28
|
+
readonly acrValues?: readonly string[];
|
|
29
|
+
readonly maxAge?: number;
|
|
30
|
+
/** The plans that would grant the permission, on `not-entitled`. */
|
|
31
|
+
readonly plans?: readonly string[];
|
|
32
|
+
};
|
|
33
|
+
declare class PermDockDeniedError extends Error {
|
|
34
|
+
override readonly name: "PermDockDeniedError";
|
|
35
|
+
readonly decision: Extract<Decision, {
|
|
36
|
+
readonly outcome: "denied";
|
|
37
|
+
}>;
|
|
38
|
+
readonly permission: string;
|
|
39
|
+
readonly scope: string;
|
|
40
|
+
readonly resource: {
|
|
41
|
+
readonly type: string;
|
|
42
|
+
readonly id?: string;
|
|
43
|
+
};
|
|
44
|
+
readonly subject: Subject;
|
|
45
|
+
/** `PERMDOCK_DENIED;<permission>`; survives the Server Component boundary (`parsePermDockDigest`). */
|
|
46
|
+
readonly digest: string;
|
|
47
|
+
constructor(input: {
|
|
48
|
+
readonly decision: Extract<Decision, {
|
|
49
|
+
readonly outcome: "denied";
|
|
50
|
+
}>;
|
|
51
|
+
readonly permission: string;
|
|
52
|
+
readonly scope: string;
|
|
53
|
+
readonly resource: {
|
|
54
|
+
readonly type: string;
|
|
55
|
+
readonly id?: string;
|
|
56
|
+
};
|
|
57
|
+
readonly subject: Subject;
|
|
58
|
+
readonly message: string;
|
|
59
|
+
});
|
|
60
|
+
toProblemDetails(options?: {
|
|
61
|
+
readonly instance?: string;
|
|
62
|
+
}): ProblemDetails;
|
|
63
|
+
}
|
|
64
|
+
declare class PermDockApprovalRequiredError extends Error {
|
|
65
|
+
override readonly name: "PermDockApprovalRequiredError";
|
|
66
|
+
readonly decision: Extract<Decision, {
|
|
67
|
+
readonly outcome: "approval-required";
|
|
68
|
+
}>;
|
|
69
|
+
readonly permission: string;
|
|
70
|
+
readonly scope: string;
|
|
71
|
+
readonly resource: {
|
|
72
|
+
readonly type: string;
|
|
73
|
+
readonly id?: string;
|
|
74
|
+
};
|
|
75
|
+
readonly token: string;
|
|
76
|
+
readonly reason: string;
|
|
77
|
+
/** `PERMDOCK_APPROVAL_REQUIRED;<permission>;<token>`; the token is already bound to this subject. */
|
|
78
|
+
readonly digest: string;
|
|
79
|
+
constructor(input: {
|
|
80
|
+
readonly decision: Extract<Decision, {
|
|
81
|
+
readonly outcome: "approval-required";
|
|
82
|
+
}>;
|
|
83
|
+
readonly permission: string;
|
|
84
|
+
readonly scope: string;
|
|
85
|
+
readonly resource: {
|
|
86
|
+
readonly type: string;
|
|
87
|
+
readonly id?: string;
|
|
88
|
+
};
|
|
89
|
+
readonly message: string;
|
|
90
|
+
});
|
|
91
|
+
toProblemDetails(options?: {
|
|
92
|
+
readonly instance?: string;
|
|
93
|
+
}): ProblemDetails;
|
|
94
|
+
}
|
|
95
|
+
declare class PermDockValidationError extends Error {
|
|
96
|
+
override readonly name: "PermDockValidationError";
|
|
97
|
+
readonly code: "invalid-data" | "async-schema" | "no-schema" | "non-portable-condition";
|
|
98
|
+
readonly permission: string;
|
|
99
|
+
readonly resource: string;
|
|
100
|
+
readonly issues: readonly StandardSchemaV1.Issue[];
|
|
101
|
+
readonly boundary: string;
|
|
102
|
+
constructor(input: {
|
|
103
|
+
readonly code: "invalid-data" | "async-schema" | "no-schema" | "non-portable-condition";
|
|
104
|
+
readonly permission: string;
|
|
105
|
+
readonly resource: string;
|
|
106
|
+
readonly issues?: readonly StandardSchemaV1.Issue[];
|
|
107
|
+
readonly boundary: string;
|
|
108
|
+
readonly message: string;
|
|
109
|
+
});
|
|
110
|
+
toProblemDetails(options?: {
|
|
111
|
+
readonly instance?: string;
|
|
112
|
+
}): ProblemDetails;
|
|
113
|
+
}
|
|
114
|
+
type RevokedCode = "session-revoked" | "expired" | "denied" | "subject-changed";
|
|
115
|
+
/**
|
|
116
|
+
* The `reason` of a long-lived connection's aborted `signal`. `denied` carries
|
|
117
|
+
* the decision that re-denied the permission the connection was opened for.
|
|
118
|
+
*/
|
|
119
|
+
declare class PermDockRevokedError extends Error {
|
|
120
|
+
override readonly name: "PermDockRevokedError";
|
|
121
|
+
readonly code: RevokedCode;
|
|
122
|
+
readonly permission?: string;
|
|
123
|
+
readonly decision?: Exclude<Decision, {
|
|
124
|
+
readonly outcome: "granted";
|
|
125
|
+
}>;
|
|
126
|
+
constructor(input: {
|
|
127
|
+
readonly code: RevokedCode;
|
|
128
|
+
readonly permission?: string;
|
|
129
|
+
readonly decision?: Exclude<Decision, {
|
|
130
|
+
readonly outcome: "granted";
|
|
131
|
+
}>;
|
|
132
|
+
});
|
|
133
|
+
toProblemDetails(options?: {
|
|
134
|
+
readonly instance?: string;
|
|
135
|
+
}): ProblemDetails;
|
|
136
|
+
}
|
|
137
|
+
//#endregion
|
|
138
|
+
export { PermDockValidationError as a, PermDockRevokedError as i, PermDockApprovalRequiredError as n, ProblemDetails as o, PermDockDeniedError as r, RevokedCode as s, ApprovalHint as t };
|