@gfargo/doorman 2.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.
@@ -0,0 +1,23 @@
1
+ declare const WORDPRESS_PATHS: string[];
2
+ declare const PHP_CONTROL_PANEL_PATHS: string[];
3
+
4
+ /**
5
+ * Creates a doorman function that checks if a request's pathname matches any of the provided paths.
6
+ *
7
+ * @param paths - An array of string paths to block. If a request's pathname starts with any of these paths, the doorman will block the request.
8
+ * @returns A function that takes a request object containing a nextUrl.pathname and returns a boolean indicating whether the request should be blocked.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * const doorman = createDoorman(['/admin', '/private']);
13
+ * const isBlocked = doorman({ nextUrl: { pathname: '/admin/dashboard' } });
14
+ * // isBlocked will be true
15
+ * ```
16
+ */
17
+ declare function createDoorman(paths: string[]): (request: {
18
+ nextUrl: {
19
+ pathname: string;
20
+ };
21
+ }) => boolean;
22
+
23
+ export { PHP_CONTROL_PANEL_PATHS, WORDPRESS_PATHS, createDoorman };
@@ -0,0 +1,23 @@
1
+ declare const WORDPRESS_PATHS: string[];
2
+ declare const PHP_CONTROL_PANEL_PATHS: string[];
3
+
4
+ /**
5
+ * Creates a doorman function that checks if a request's pathname matches any of the provided paths.
6
+ *
7
+ * @param paths - An array of string paths to block. If a request's pathname starts with any of these paths, the doorman will block the request.
8
+ * @returns A function that takes a request object containing a nextUrl.pathname and returns a boolean indicating whether the request should be blocked.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * const doorman = createDoorman(['/admin', '/private']);
13
+ * const isBlocked = doorman({ nextUrl: { pathname: '/admin/dashboard' } });
14
+ * // isBlocked will be true
15
+ * ```
16
+ */
17
+ declare function createDoorman(paths: string[]): (request: {
18
+ nextUrl: {
19
+ pathname: string;
20
+ };
21
+ }) => boolean;
22
+
23
+ export { PHP_CONTROL_PANEL_PATHS, WORDPRESS_PATHS, createDoorman };
@@ -0,0 +1 @@
1
+ "use strict";var o=Object.defineProperty;var c=Object.getOwnPropertyDescriptor;var m=Object.getOwnPropertyNames;var h=Object.prototype.hasOwnProperty;var l=(r,p)=>{for(var t in p)o(r,t,{get:p[t],enumerable:!0})},s=(r,p,t,n)=>{if(p&&typeof p=="object"||typeof p=="function")for(let e of m(p))!h.call(r,e)&&e!==t&&o(r,e,{get:()=>p[e],enumerable:!(n=c(p,e))||n.enumerable});return r};var x=r=>s(o({},"__esModule",{value:!0}),r);var w={};l(w,{PHP_CONTROL_PANEL_PATHS:()=>f,WORDPRESS_PATHS:()=>i,createDoorman:()=>a});module.exports=x(w);var i=["/wp-content/","/wp-admin/","/wp-includes/","/wp-json/","/wp-login.php","/xmlrpc.php"],f=["/ws.php","/xmrlpc.php","/makeasmtp.php","/text.php","/images/xmrlpc.php","/img/xmrlpc.php","/cgi-bin/xmrlpc.php","/css/xmrlpc.php","/alfa-rex2.php","/alfanew2.php"];function a(r){return p=>{let t=!1;for(let n of r)if(p.nextUrl.pathname.startsWith(n)){t=!0;break}return t}}0&&(module.exports={PHP_CONTROL_PANEL_PATHS,WORDPRESS_PATHS,createDoorman});
@@ -0,0 +1 @@
1
+ var o=["/wp-content/","/wp-admin/","/wp-includes/","/wp-json/","/wp-login.php","/xmlrpc.php"],a=["/ws.php","/xmrlpc.php","/makeasmtp.php","/text.php","/images/xmrlpc.php","/img/xmrlpc.php","/cgi-bin/xmrlpc.php","/css/xmrlpc.php","/alfa-rex2.php","/alfanew2.php"];function n(r){return t=>{let p=!1;for(let e of r)if(t.nextUrl.pathname.startsWith(e)){p=!0;break}return p}}export{a as PHP_CONTROL_PANEL_PATHS,o as WORDPRESS_PATHS,n as createDoorman};
package/package.json ADDED
@@ -0,0 +1,157 @@
1
+ {
2
+ "name": "@gfargo/doorman",
3
+ "version": "2.1.0",
4
+ "description": "Manage firewall rules as code across multiple providers",
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
8
+ "bin": {
9
+ "doorman": "./bin/run",
10
+ "vercel-doorman": "./bin/run-deprecated"
11
+ },
12
+ "directories": {
13
+ "lib": "src",
14
+ "bin": "bin"
15
+ },
16
+ "files": [
17
+ "dist",
18
+ "bin",
19
+ "skills"
20
+ ],
21
+ "agents": {
22
+ "skills": [
23
+ {
24
+ "name": "doorman",
25
+ "path": "./skills/doorman"
26
+ }
27
+ ]
28
+ },
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "git+ssh://git@github.com/gfargo/doorman.git"
32
+ },
33
+ "scripts": {
34
+ "prebuild": "pnpm clean",
35
+ "build": "tsup-node",
36
+ "build:schema": "ts-node ./schema/generate-schema.ts; pnpm lint:fix; pnpm format:fix",
37
+ "build:watch": "tsup-node --watch",
38
+ "clean": "rimraf dist",
39
+ "commit": "cz",
40
+ "commitlint": "commitlint --edit",
41
+ "compile": "tsc",
42
+ "format": "prettier . --check",
43
+ "format:fix": "prettier . --write",
44
+ "lint": "eslint .",
45
+ "lint:fix": "eslint . --fix",
46
+ "start": "ts-node ./bin/run.ts",
47
+ "start:node": "node ./bin/run",
48
+ "test": "jest",
49
+ "test:watch": "jest --watchAll",
50
+ "test:coverage": "jest --coverage",
51
+ "test:ci": "jest --ci --coverage --watchAll=false",
52
+ "dev": "pnpm start",
53
+ "doorman": "pnpm start",
54
+ "prepare": "husky",
55
+ "release": "semantic-release",
56
+ "docs:dev": "echo 'Documentation server would start here'",
57
+ "validate:examples": "find examples -name '*.json' -exec pnpm start validate --config {} \\;",
58
+ "benchmark": "echo 'Performance benchmarks would run here'"
59
+ },
60
+ "keywords": [
61
+ "firewall",
62
+ "waf",
63
+ "IaC",
64
+ "security",
65
+ "vercel",
66
+ "cloudflare",
67
+ "cli"
68
+ ],
69
+ "author": "Griffen Fargo <ghfargo@gmail.com>",
70
+ "license": "MIT",
71
+ "devDependencies": {
72
+ "@commitlint/cli": "^20.5.3",
73
+ "@commitlint/config-conventional": "^20.5.3",
74
+ "@jest/globals": "^30.3.0",
75
+ "@semantic-release/changelog": "^6.0.3",
76
+ "@semantic-release/git": "^10.0.1",
77
+ "@semantic-release/github": "^12.0.6",
78
+ "@semantic-release/npm": "^12.0.1",
79
+ "@tsconfig/node20": "^20.1.4",
80
+ "@types/jest": "^30.0.0",
81
+ "@types/node": "^20.12.12",
82
+ "@types/prompts": "^2.4.9",
83
+ "@types/signale": "^1.4.7",
84
+ "@types/yargs": "^17.0.32",
85
+ "@typescript-eslint/eslint-plugin": "^8.59.1",
86
+ "@typescript-eslint/parser": "^8.59.1",
87
+ "commitizen": "^4.3.0",
88
+ "cz-conventional-changelog": "^3.3.0",
89
+ "eslint": "^9.39.4",
90
+ "eslint-config-prettier": "^9.1.0",
91
+ "eslint-plugin-jest": "^29.15.2",
92
+ "eslint-plugin-prettier": "^5.1.3",
93
+ "eslint-plugin-unused-imports": "^4.4.1",
94
+ "globals": "^17.6.0",
95
+ "husky": "^9.0.11",
96
+ "jest": "^30.3.0",
97
+ "prettier": "^3.2.5",
98
+ "rimraf": "^6.1.3",
99
+ "semantic-release": "^25.0.3",
100
+ "ts-jest": "^29.4.9",
101
+ "ts-json-schema-generator": "^2.3.0",
102
+ "ts-node": "^10.9.2",
103
+ "tsup": "^8.5.1",
104
+ "typescript": "^5.4.5",
105
+ "typescript-eslint": "^8.59.1"
106
+ },
107
+ "dependencies": {
108
+ "ajv": "^8.18.0",
109
+ "chalk": "^5.3.0",
110
+ "cli-table3": "^0.6.5",
111
+ "consola": "^3.4.2",
112
+ "dotenv": "^16.4.5",
113
+ "find-up": "^6.3.0",
114
+ "yargs": "^17.7.2",
115
+ "zod": "^3.23.8"
116
+ },
117
+ "config": {
118
+ "commitizen": {
119
+ "path": "cz-conventional-changelog"
120
+ }
121
+ },
122
+ "pnpm": {
123
+ "overrides": {
124
+ "micromatch@<4.0.8": ">=4.0.8",
125
+ "cross-spawn": "^7.0.6",
126
+ "nanoid": ">=3.3.8",
127
+ "@octokit/request-error": ">=6.1.7",
128
+ "@octokit/endpoint": ">=10.1.3",
129
+ "@octokit/request": ">=9.2.1",
130
+ "@octokit/plugin-paginate-rest": ">=11.4.1",
131
+ "braces": ">=3.0.3",
132
+ "tmp": ">=0.2.6",
133
+ "esbuild": ">=0.25.0",
134
+ "@babel/helpers": ">=7.26.10",
135
+ "@babel/core": ">=7.29.6",
136
+ "handlebars": ">=4.7.9",
137
+ "minimatch@<3.1.4": ">=3.1.4",
138
+ "minimatch@>=9.0.0 <9.0.7": ">=9.0.7",
139
+ "glob@>=10.2.0 <10.5.0": ">=10.5.0",
140
+ "brace-expansion@<1.1.13": ">=1.1.13",
141
+ "brace-expansion@>=2.0.0 <2.0.3": ">=2.0.3",
142
+ "brace-expansion": ">=5.0.9",
143
+ "flatted@<3.4.2": ">=3.4.2",
144
+ "picomatch@<2.3.2": ">=2.3.2",
145
+ "js-yaml": ">=4.3.1",
146
+ "ajv@<6.14.0": "6.14.0",
147
+ "lodash@<=4.17.23": ">=4.18.0",
148
+ "lodash-es@<=4.17.23": ">=4.18.0",
149
+ "rollup@>=4.0.0 <4.59.0": ">=4.59.0",
150
+ "postcss@<8.5.10": ">=8.5.10",
151
+ "yaml@>=2.0.0 <2.8.3": ">=2.8.3",
152
+ "diff@>=4.0.0 <4.0.4": ">=4.0.4",
153
+ "undici": ">=7.29.0",
154
+ "fast-uri": ">=3.1.5"
155
+ }
156
+ }
157
+ }
@@ -0,0 +1,132 @@
1
+ ---
2
+ name: doorman
3
+ description: 'Use when managing Vercel or Cloudflare WAF rules as code, configuring firewall rules, IP blocking, rate limiting, bot protection, or automating multi-provider security configuration deployment with Doorman CLI.'
4
+ ---
5
+
6
+ # Doorman
7
+
8
+ Multi-provider WAF automation as code. Manage Vercel Firewall and Cloudflare WAF rules in version-controlled `.doorman.json` files with automated deployment via CLI.
9
+
10
+ ## Key Concepts
11
+
12
+ - **Config file**: `.doorman.json` (also supports legacy `vercel-firewall.config.json`)
13
+ - **Providers**: Vercel (default) and Cloudflare (`--provider cloudflare`)
14
+ - **Workflow**: Edit config → validate → diff → sync
15
+ - **Schema**: `https://doorman.griffen.codes/schema.json`
16
+
17
+ ## Commands
18
+
19
+ ```bash
20
+ doorman init --interactive # Create new config
21
+ doorman validate # Check config syntax
22
+ doorman status # Sync status + health score
23
+ doorman list # Show deployed rules
24
+ doorman diff # Local vs remote differences
25
+ doorman sync # Deploy local config to provider
26
+ doorman download # Pull remote rules to local config
27
+ doorman template <name> # Add pre-built rule template
28
+ doorman watch # Auto-sync on file changes
29
+ doorman backup # Create config backup
30
+ doorman export --format <fmt> # Export as markdown|json|yaml|terraform
31
+ ```
32
+
33
+ All commands accept `--provider vercel|cloudflare` and `--config <path>`.
34
+
35
+ ## Environment Variables
36
+
37
+ ```bash
38
+ # Vercel
39
+ VERCEL_TOKEN=your_token
40
+ VERCEL_PROJECT_ID=prj_xxx
41
+ VERCEL_TEAM_ID=team_xxx
42
+
43
+ # Cloudflare
44
+ CLOUDFLARE_API_TOKEN=your_token
45
+ CLOUDFLARE_ZONE_ID=zone_xxx
46
+ CLOUDFLARE_ACCOUNT_ID=acc_xxx # optional, enables Lists API
47
+ ```
48
+
49
+ ## Config Structure
50
+
51
+ ```json
52
+ {
53
+ "$schema": "https://doorman.griffen.codes/schema.json",
54
+ "projectId": "prj_xxx",
55
+ "teamId": "team_xxx",
56
+ "rules": [],
57
+ "ips": []
58
+ }
59
+ ```
60
+
61
+ For Cloudflare, use `provider` and `providers` fields instead of `projectId`/`teamId`.
62
+
63
+ ## Rule Quick Reference
64
+
65
+ ```json
66
+ {
67
+ "id": "rule_block_admin",
68
+ "name": "Block Admin Access",
69
+ "description": "Block unauthorized admin access",
70
+ "active": true,
71
+ "conditionGroup": [
72
+ {
73
+ "conditions": [
74
+ { "type": "path", "op": "pre", "value": "/admin" },
75
+ { "type": "method", "op": "eq", "value": "POST" }
76
+ ]
77
+ }
78
+ ],
79
+ "action": {
80
+ "mitigate": {
81
+ "action": "deny"
82
+ }
83
+ }
84
+ }
85
+ ```
86
+
87
+ **Logic**: Conditions within a group are AND'd. Multiple groups are OR'd.
88
+
89
+ **Condition types**: `path`, `method`, `host`, `user_agent`, `ip_address`, `header`, `query`, `cookie`, `geo_country`, `geo_city`, `geo_continent`, `scheme`
90
+
91
+ **Operators**: `eq`, `pre` (starts_with), `suf` (ends_with), `sub` (contains), `inc` (in array), `re` (regex), `ex` (exists), `nex` (not exists)
92
+
93
+ **Actions**: `deny`, `challenge`, `rate_limit`, `redirect`, `log`, `bypass`
94
+
95
+ **See `rules-reference.md` for complete field documentation, advanced patterns, and examples.**
96
+
97
+ ## IP Blocking
98
+
99
+ ```json
100
+ {
101
+ "ips": [{ "ip": "192.168.1.0/24", "action": "deny", "hostname": "bad-subnet", "notes": "Blocked for abuse" }]
102
+ }
103
+ ```
104
+
105
+ ## Templates
106
+
107
+ ```bash
108
+ doorman template bad-bots # Block malicious bots
109
+ doorman template ai-bots # Block AI crawlers
110
+ doorman template wordpress # Block WordPress attack paths
111
+ doorman template block-ofac-sanctioned-countries # OFAC compliance
112
+ ```
113
+
114
+ ## Workflow
115
+
116
+ ```bash
117
+ # Add a rule: edit .doorman.json, then:
118
+ doorman validate && doorman sync
119
+
120
+ # Pull existing rules from provider:
121
+ doorman download
122
+
123
+ # Check what would change before deploying:
124
+ doorman diff
125
+ ```
126
+
127
+ ## Resources
128
+
129
+ - [Docs](https://doorman.griffen.codes/docs)
130
+ - [GitHub](https://github.com/gfargo/doorman)
131
+ - [Wiki](https://github.com/gfargo/doorman/wiki)
132
+ - [Examples](https://github.com/gfargo/doorman/tree/main/examples)