permission-gap-detector 1.0.0 → 1.0.2

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/CHANGELOG.md CHANGED
@@ -1,9 +1,22 @@
1
1
  # Changelog
2
2
 
3
- ## 1.0.0 — prepared 19 October 2026 (npm publication pending)
3
+ ## 1.0.2
4
+
5
+ - Reject control characters in route paths before rendering reports.
6
+ - Accept UTF-8 BOM JSON files and literal filenames after `--`.
7
+ - Add command-specific help with documented exit codes.
8
+ - Expand regression coverage to 27 tests and include a clean route example.
9
+
10
+
11
+ ## 1.0.1
12
+
13
+ - Keep the distribution focused on source code, usage examples, and package documentation.
14
+ - Simplify the README and published file list.
15
+
16
+ ## 1.0.0
4
17
 
5
18
  - Add missing and invalid permission checks.
6
19
  - Add duplicate and conflicting policy detection.
7
20
  - Add summary counts and declaration coverage.
8
21
  - Add CommonJS API and CLI with JSON output and exit codes.
9
- - Add 20 tests, examples, and college evaluation documentation.
22
+ - Add 20 automated tests and usage examples.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Permission Gap Detector
2
2
 
3
- A small, dependency-free CommonJS Node.js package that checks **declared API route permissions**. Built as an Advanced Software Development college assignment.
3
+ A small, dependency-free CommonJS Node.js package that checks **declared API route permissions**.
4
4
 
5
5
  ## Problem statement
6
6
 
@@ -20,13 +20,13 @@ It does not inspect Express middleware or prove that an application is secure.
20
20
 
21
21
  Requires Node.js 20 or newer and npm. No external dependencies.
22
22
 
23
- The release is prepared as version 1.0.0. **npm publication is pending account authentication.** Once published:
23
+ Install from npm:
24
24
 
25
25
  ```bash
26
26
  npm install permission-gap-detector
27
27
  ```
28
28
 
29
- Until then, install directly from GitHub:
29
+ Alternatively, install directly from GitHub:
30
30
 
31
31
  ```bash
32
32
  npm install github:Aditya030207/npm-package-project
@@ -35,7 +35,7 @@ npm install github:Aditya030207/npm-package-project
35
35
  Or run `npm pack` in this repository and install the resulting archive in another project:
36
36
 
37
37
  ```bash
38
- npm install /absolute/path/to/permission-gap-detector-1.0.0.tgz
38
+ npm install /absolute/path/to/permission-gap-detector-1.0.2.tgz
39
39
  ```
40
40
 
41
41
  ## Basic usage
@@ -63,7 +63,7 @@ Input is an array of ordinary route objects. Each object needs:
63
63
  | Field | Accepted values |
64
64
  | --- | --- |
65
65
  | `method` | GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS, CONNECT, TRACE; case-insensitive |
66
- | `path` | A string starting with `/`, without whitespace |
66
+ | `path` | A string starting with `/`, without whitespace or control characters |
67
67
  | `access` | Exactly `public`, `authenticated`, or `admin` |
68
68
 
69
69
  `public` allows anyone; `authenticated` requires a logged-in user; `admin` requires administrator access. These are declarations, not enforcement.
@@ -119,7 +119,7 @@ The three convenience functions return only their named findings. Use `auditRout
119
119
 
120
120
  ## CLI usage
121
121
 
122
- After npm publication:
122
+ Run directly from npm:
123
123
 
124
124
  ```bash
125
125
  npx permission-gap-detector check routes.json
@@ -132,18 +132,19 @@ npx --no-install permission-gap check routes.json
132
132
  npx --no-install permission-gap check routes.json --json
133
133
  ```
134
134
 
135
- For a direct shell command, globally install the package with `npm install -g permission-gap-detector` after publication, then run `permission-gap check routes.json`. Both binary names point to the same CLI.
135
+ For a direct shell command, globally install the package with `npm install -g permission-gap-detector` then run `permission-gap check routes.json`. Both binary names point to the same CLI.
136
136
 
137
- From this repository (works before publication):
137
+ From this repository:
138
138
 
139
139
  ```bash
140
140
  node bin/cli.js check examples/routes.json
141
141
  node bin/cli.js check examples/routes.json --json
142
142
  node bin/cli.js --help
143
+ node bin/cli.js check --help
143
144
  node bin/cli.js --version
144
145
  ```
145
146
 
146
- Files must contain a JSON array, not an object wrapping the array. Paths are relative to the current working directory; quote paths containing spaces. Exit codes: **0** = no findings, **1** = audit findings, **2** = invalid command, unreadable file, malformed JSON, or non-array input. Human-readable failures go to stderr. With `--json`, failures are `{ "error": "message" }` on stdout.
147
+ UTF-8 files may begin with a byte order mark (BOM). Files must contain a JSON array, not an object wrapping the array. Paths are relative to the current working directory; quote paths containing spaces. Use `permission-gap check --json -- -routes.json` for a filename beginning with a dash; options must come before `--`. Exit codes: **0** = no findings, **1** = audit findings, **2** = invalid command, unreadable file, malformed JSON, or non-array input. Human-readable failures go to stderr. With `--json`, failures are `{ "error": "message" }` on stdout.
147
148
 
148
149
  ## Example output
149
150
 
@@ -177,6 +178,14 @@ Audit Complete
177
178
 
178
179
  The example intentionally has issues and exits with code 1.
179
180
 
181
+ For a complete set of consistent declarations, run:
182
+
183
+ ```bash
184
+ node bin/cli.js check examples/clean-routes.json
185
+ ```
186
+
187
+ This example uses all three supported permissions, reports 100% declaration coverage with no findings, and exits with code 0. Compare it with `examples/routes.json` to see how missing and conflicting declarations change the result. Neither result verifies middleware enforcement.
188
+
180
189
  ## Development and testing
181
190
 
182
191
  ```bash
@@ -188,7 +197,7 @@ node examples/basic.js
188
197
  npm pack --dry-run
189
198
  ```
190
199
 
191
- The 20 automated tests use `node:test` and strict assertions. They cover valid policies, input validation, missing permissions, duplicates, conflicts, counting, immutability, reports, and CLI behavior with real temporary files and child processes.
200
+ The 27 automated tests use `node:test` and strict assertions. They cover valid policies, input validation, missing permissions, duplicates, conflicts, counting, immutability, reports, and CLI behavior with real temporary files and child processes.
192
201
 
193
202
  ## Source structure
194
203
 
@@ -204,41 +213,16 @@ npm-package-project/
204
213
  ├── tests/package.test.js # API and CLI tests
205
214
  ├── examples/
206
215
  │ ├── basic.js
207
- │ └── routes.json
216
+ │ ├── routes.json
217
+ │ └── clean-routes.json
208
218
  ├── package.json
209
219
  ├── package-lock.json
210
220
  ├── README.md
211
221
  ├── CHANGELOG.md
212
- ├── PROJECT_PROGRESS.md
213
- ├── VIVA_GUIDE.md
214
222
  ├── LICENSE
215
223
  └── .gitignore
216
224
  ```
217
225
 
218
- ## Publication
219
-
220
- From the package directory, authenticate interactively and publish:
221
-
222
- ```bash
223
- npm login
224
- npm whoami
225
- npm test
226
- npm pack --dry-run
227
- npm publish --access public
228
- npm view permission-gap-detector@1.0.0 version
229
- ```
230
-
231
- Complete any npm browser or two-factor authentication prompts. The name was absent from the npm registry on 19 October 2026; availability is not a reservation. If npm rejects the name, select an available name or your own npm scope and update the package metadata and usage instructions. After successful publication, update this README's pending status. Verify installation in a fresh directory with `npm install permission-gap-detector@1.0.0`, then run the basic usage example and CLI.
232
-
233
- ## College demonstration
234
-
235
- 1. Explain the missing-permission problem and the distinction between declarations and enforcement.
236
- 2. Run `npm test` to show the test results.
237
- 3. Run `node bin/cli.js check examples/routes.json` and explain the missing policy, two extra duplicates, one conflicting group, and 83.3% coverage.
238
- 4. In a copy of the JSON, assign `admin` to the DELETE route and remove the repeated GET definitions. Rerun to show no issues and 100% coverage.
239
- 5. Show the exported functions in `src/index.js` and the grouping loop in `src/checkDuplicates.js`.
240
- 6. Show the GitHub repository and install the packed archive into a separate project. Show the npm listing once publication is complete.
241
-
242
226
  ## Limitations
243
227
 
244
228
  This audits only supplied route declarations. It does not scan source code, discover Express routes, execute middleware, validate tokens, enforce access rules, or assess application security. It does not infer route equivalence, inherited policies, Express mount paths, or wildcard matching. A public policy on a sensitive route is only detected as a conflict if another definition declares a different valid policy. Keep route declarations synchronized with the actual application.
package/bin/cli.js CHANGED
@@ -4,24 +4,30 @@ const { auditRoutes } = require('../src');
4
4
  const generateReport = require('../src/generateReport');
5
5
  const { version } = require('../package.json');
6
6
  const args = process.argv.slice(2);
7
- const json = args.includes('--json');
8
- const usage = 'Usage: permission-gap check <routes.json> [--json]\nOptions: --help, --version, --json';
7
+ // Arguments after -- are literal filenames, even when they begin with a dash.
8
+ const separator = args.indexOf('--');
9
+ const options = separator === -1 ? args : args.slice(0, separator);
10
+ const filenames = separator === -1 ? [] : args.slice(separator + 1);
11
+ const json = options.includes('--json');
12
+ const usage = 'Usage: permission-gap check <routes.json> [--json]\n permission-gap check [--json] -- <filename>\nOptions: --help, --version, --json\nExit codes: 0 = no findings, 1 = audit findings, 2 = input error';
9
13
 
10
14
  try {
11
- if (args.length === 1 && args[0] === '--help') {
15
+ if ((args.length === 1 && args[0] === '--help') ||
16
+ (args.length === 2 && args[0] === 'check' && args[1] === '--help')) {
12
17
  console.log(usage);
13
18
  } else if (args.length === 1 && args[0] === '--version') {
14
19
  console.log(version);
15
20
  } else {
16
- const positional = args.filter(arg => arg !== '--json');
17
- if (positional.length !== 2 || positional[0] !== 'check' || positional[1].startsWith('--') || args.filter(arg => arg === '--json').length > 1) {
21
+ const positional = [...options.filter(arg => arg !== '--json'), ...filenames];
22
+ const unknownOption = options.some(arg => arg.startsWith('-') && arg !== '--json');
23
+ if (positional.length !== 2 || positional[0] !== 'check' || unknownOption || options.filter(arg => arg === '--json').length > 1) {
18
24
  throw new Error(usage);
19
25
  }
20
26
  let content;
21
27
  try { content = fs.readFileSync(positional[1], 'utf8'); }
22
28
  catch { throw new Error(`Cannot read file: ${positional[1]}`); }
23
29
  let routes;
24
- try { routes = JSON.parse(content); }
30
+ try { routes = JSON.parse(content.replace(/^\uFEFF/, '')); }
25
31
  catch { throw new Error(`Invalid JSON in file: ${positional[1]}`); }
26
32
  const result = auditRoutes(routes);
27
33
  console.log(json ? JSON.stringify(result, null, 2) : generateReport(result));
@@ -0,0 +1,17 @@
1
+ [
2
+ {
3
+ "method": "GET",
4
+ "path": "/products",
5
+ "access": "public"
6
+ },
7
+ {
8
+ "method": "POST",
9
+ "path": "/products",
10
+ "access": "authenticated"
11
+ },
12
+ {
13
+ "method": "DELETE",
14
+ "path": "/products/:id",
15
+ "access": "admin"
16
+ }
17
+ ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "permission-gap-detector",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Check declared API route permissions for missing policies, duplicates, and conflicts.",
5
5
  "main": "src/index.js",
6
6
  "type": "commonjs",
@@ -12,9 +12,7 @@
12
12
  "src/",
13
13
  "bin/",
14
14
  "examples/",
15
- "CHANGELOG.md",
16
- "VIVA_GUIDE.md",
17
- "PROJECT_PROGRESS.md"
15
+ "CHANGELOG.md"
18
16
  ],
19
17
  "scripts": {
20
18
  "test": "node --test",
@@ -9,8 +9,8 @@ function validateRoutes(routes) {
9
9
  const route = routes[index];
10
10
  if (!route || typeof route !== 'object' || Array.isArray(route) ||
11
11
  typeof route.method !== 'string' || !METHODS.includes(route.method.toUpperCase()) ||
12
- typeof route.path !== 'string' || !route.path.startsWith('/') || /\s/.test(route.path)) {
13
- invalidRoutes.push({ index, message: 'Expected an object with a supported HTTP method and a path starting with / without whitespace.' });
12
+ typeof route.path !== 'string' || !route.path.startsWith('/') || /[\s\x00-\x1f\x7f-\x9f]/.test(route.path)) {
13
+ invalidRoutes.push({ index, message: 'Expected an object with a supported HTTP method and a path starting with / without whitespace or control characters.' });
14
14
  continue;
15
15
  }
16
16
  validRoutes.push({ index, method: route.method.toUpperCase(), path: route.path, access: route.access });
@@ -1,21 +0,0 @@
1
- # Project progress
2
-
3
- ## Intended schedule: 4–26 October 2026
4
-
5
- These are planned milestones, not claims that work occurred on those dates.
6
-
7
- | Planned dates | Milestones |
8
- | --- | --- |
9
- | October 4–6: Planning | Choose package idea; define problem statement; plan features. |
10
- | October 7–10: Basic Setup | Initialize Node.js project; design route format; create package structure. |
11
- | October 11–14: Core Development | Missing permission detection; permission validation; duplicate detection. |
12
- | October 15–18: Remaining Features | Permission conflicts; coverage calculation; report output. |
13
- | October 19–21: Testing | CLI; unit tests; input validation; bug fixes. |
14
- | October 22–24: Documentation | README; usage examples; installation instructions; final testing. |
15
- | October 25–26: Publication and Submission | NPM packaging; public GitHub repository; NPM publication; final demonstration. |
16
-
17
- ## Actual work
18
-
19
- 19 October 2026: Implemented the API and CLI, wrote and passed 20 automated tests, added examples, README, MIT license, changelog, and viva guide. Git commits use their real creation timestamps. Implementation was completed earlier than some planned milestones.
20
-
21
- npm publication remains pending npm authentication. Publication and submission must not be presented as completed until separately verified.
package/VIVA_GUIDE.md DELETED
@@ -1,52 +0,0 @@
1
- # Viva guide
2
-
3
- **What problem does this package solve?**
4
- It finds missing or inconsistent access declarations in a developer-maintained API route list.
5
-
6
- **Why did we create it?**
7
- It is easy to add an endpoint and forget to record who should access it. This reusable check makes omissions visible before review or release.
8
-
9
- **How does auditRoutes() work?**
10
- It checks that the input is an array, separates invalid route structures, checks access values, groups matching routes, and returns findings with counts and coverage. It does not change the input.
11
-
12
- **How are duplicates detected?**
13
- A Map groups definitions using the uppercase HTTP method plus the exact path. A group with more than one definition is duplicated. A group of three contributes two extra definitions to the duplicate count.
14
-
15
- **How are permission conflicts detected?**
16
- Within each duplicate group, a Set collects distinct supported permissions. More than one supported permission means a conflict. Invalid or missing values have separate findings.
17
-
18
- **How is coverage calculated?**
19
- Valid permission definitions / total submitted definitions × 100, rounded to one decimal. Empty input has 0%. Duplicate definitions stay in the denominator and may have valid policies. Coverage describes declaration completeness; even 100% can contain conflicts.
20
-
21
- **Authentication versus authorization?**
22
- Authentication checks who a person is, such as verifying their login. Authorization checks what that person may do, such as deleting a user. This package labels intended access but implements neither mechanism.
23
-
24
- **What is package.json?**
25
- It describes the npm package: name, version, main module, CLI commands, scripts, license, Node requirement, and repository. The files field controls which project files go into the published archive.
26
-
27
- **What does module.exports do?**
28
- It makes functions available to other files through CommonJS require(). Our entry point exports four named functions.
29
-
30
- **How do automated tests work?**
31
- Node's built-in runner executes test cases. Assertions compare actual behavior with expected results. CLI tests launch a real child process and use temporary files. npm test runs node --test. A failing assertion makes the test command fail.
32
-
33
- **Why no dependencies?**
34
- The checks need only loops, arrays, Map, and Set. Node already provides file reading, process arguments, and a test runner.
35
-
36
- **How is an npm package published?**
37
- Choose an available name, prepare metadata and files, run tests and npm pack --dry-run, log in with npm login, then run npm publish --access public. Complete required authentication prompts and verify the registry version and a fresh install. This project's publication is pending login; do not claim it is already published.
38
-
39
- **What is version 1.0.0?**
40
- It is the first working release. Semantic versioning uses major.minor.patch: breaking API changes increase major, compatible features increase minor, and compatible fixes increase patch.
41
-
42
- **What do CLI exit codes mean?**
43
- Zero means the audit found no issues; one means findings were detected; two means an input or command error. Other scripts can use these statuses.
44
-
45
- **What are the limitations?**
46
- The package sees only supplied declarations. It does not discover routes or verify middleware, authentication, authorization, or overall security. Paths are compared exactly; it does not understand Express routing semantics.
47
-
48
- **How would you demonstrate reuse?**
49
- Install the archive in an empty project, require permission-gap-detector, call auditRoutes with a route array, and show the summary. Then run the installed CLI on the same route data.
50
-
51
- **What is the approximate algorithmic cost?**
52
- Validation and permission checks visit each entry once. Grouping uses a Map; checking policies visits each group entry once. Typical time and memory are linear in the number of definitions, with string handling also depending on path length.