darklens 0.0.0-stage → 1.0.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.
Files changed (4) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +116 -2
  3. package/bin/index.js +146 -0
  4. package/package.json +48 -4
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 DarkLens
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,117 @@
1
- # Temporary Holding Version
1
+ # DarkLens CLI 🔍
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ > **Automated compliance scanning for Dark Patterns & Deceptive Design in your terminal and CI/CD pipelines.**
4
+
5
+ [![npm version](https://img.shields.io/npm/v/darklens.svg)](https://www.npmjs.com/package/darklens)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-purple.svg)](https://opensource.org/licenses/MIT)
7
+
8
+ DarkLens CLI detects illegal deceptive UX patterns, confirmshaming, hidden subscription renewals, interface interference, and compliance risks across **GDPR**, **FTC Act Sec. 5**, **EU Digital Services Act (DSA)**, and **CCPA/CPRA**.
9
+
10
+ ---
11
+
12
+ ## ⚡ Quick Start
13
+
14
+ Run instantly without installation using `npx`:
15
+
16
+ ```bash
17
+ npx darklens https://staging.myapp.com --key YOUR_DARKLENS_API_KEY
18
+ ```
19
+
20
+ Or install globally:
21
+
22
+ ```bash
23
+ npm install -g darklens
24
+ darklens https://staging.myapp.com --key YOUR_DARKLENS_API_KEY
25
+ ```
26
+
27
+ ---
28
+
29
+ ## 🔑 Authentication
30
+
31
+ You can pass your API key directly via the `--key` flag or export it into your shell environment:
32
+
33
+ ```bash
34
+ export DARKLENS_API_KEY="your_api_key_here"
35
+ darklens https://staging.myapp.com
36
+ ```
37
+
38
+ > Get your API key in the [DarkLens Dashboard](https://darklens.dev/dashboard).
39
+
40
+ ---
41
+
42
+ ## 🛠️ CLI Options
43
+
44
+ | Option | Flag | Description | Default |
45
+ | :--- | :--- | :--- | :--- |
46
+ | **Target URL** | `<url>` | URL of the application to scan | *Required* |
47
+ | **API Key** | `-k, --key` | Your DarkLens API key | `$DARKLENS_API_KEY` |
48
+ | **Threshold** | `-t, --threshold` | Minimum passing score (0-100) | `70` |
49
+ | **Fail Criteria**| `-f, --fail-on` | When to exit with error: `score`, `critical`, or `any` | `score` |
50
+ | **JSON Output** | `-j, --json` | Output raw machine-readable JSON | `false` |
51
+ | **Help** | `-h, --help` | Display help screen | — |
52
+
53
+ ---
54
+
55
+ ## 🚀 CI/CD Integration Examples
56
+
57
+ ### GitHub Actions
58
+
59
+ ```yaml
60
+ name: Dark Pattern Compliance Audit
61
+
62
+ on: [pull_request]
63
+
64
+ jobs:
65
+ compliance_audit:
66
+ runs-on: ubuntu-latest
67
+ steps:
68
+ - uses: actions/checkout@v4
69
+ - name: Run DarkLens CLI
70
+ run: npx darklens https://staging.myapp.com --threshold 75
71
+ env:
72
+ DARKLENS_API_KEY: ${{ secrets.DARKLENS_API_KEY }}
73
+ ```
74
+
75
+ *(You can also use our native [DarkLens GitHub Action](https://github.com/marketplace/actions/darklens-compliance-scan).)*
76
+
77
+ ### GitLab CI
78
+
79
+ ```yaml
80
+ darklens_scan:
81
+ stage: test
82
+ image: node:20
83
+ script:
84
+ - npx darklens "$CI_ENVIRONMENT_URL" --threshold 75
85
+ rules:
86
+ - if: $CI_PIPELINE_SOURCE == 'merge_request_event'
87
+ ```
88
+
89
+ ---
90
+
91
+ ## 📋 Example Output
92
+
93
+ ```text
94
+ 🔍 DarkLens Compliance Scanner v1.0.0
95
+
96
+ ──────────────────────────────────────────────────
97
+ Target: https://staging.myapp.com
98
+ Score: 88 / 100 PASS
99
+ Threshold: 70 / 100 (Criterion: fail on score)
100
+ Breakdown: 0 Critical, 1 High, 0 Medium, 2 Low
101
+ ──────────────────────────────────────────────────
102
+
103
+ Detected Findings (3):
104
+
105
+ [1] HIGH Forced Continuity
106
+ Category: Subscription Deception
107
+ Regulation: FTC Act Sec. 5 | EU DSA Art. 25
108
+ Details: Pre-checked recurring auto-renewal box detected on checkout form.
109
+
110
+ ✔ PASSED: Build criteria satisfied.
111
+ ```
112
+
113
+ ---
114
+
115
+ ## 📄 License
116
+
117
+ MIT © [DarkLens](https://darklens.dev)
package/bin/index.js ADDED
@@ -0,0 +1,146 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { program } = require('commander');
4
+ const chalk = require('chalk');
5
+ const fetch = require('node-fetch');
6
+ const ora = require('ora');
7
+ const packageJson = require('../package.json');
8
+
9
+ program
10
+ .name('darklens')
11
+ .version(packageJson.version)
12
+ .description('DarkLens CLI: Enterprise compliance scanning for Dark Patterns & deceptive UI.')
13
+ .argument('<url>', 'The target URL to audit (e.g. https://staging.myapp.com)')
14
+ .option('-k, --key <key>', 'DarkLens API Key (or set DARKLENS_API_KEY environment variable)')
15
+ .option('-t, --threshold <score>', 'Minimum passing compliance score (0-100)', '70')
16
+ .option('-f, --fail-on <criterion>', 'Failure condition: score, critical, or any', 'score')
17
+ .option('-j, --json', 'Output raw scan results in JSON format')
18
+ .action(async (url, options) => {
19
+ const apiKey = options.key || process.env.DARKLENS_API_KEY;
20
+
21
+ if (!apiKey) {
22
+ if (options.json) {
23
+ console.error(JSON.stringify({ error: 'Missing API key. Provide via --key or DARKLENS_API_KEY env var.' }));
24
+ } else {
25
+ console.log(chalk.red('\n✖ Error: Missing DarkLens API key.'));
26
+ console.log(chalk.dim('Provide your key via:'));
27
+ console.log(` ${chalk.cyan('darklens <url> --key <your-api-key>')}`);
28
+ console.log(chalk.dim('Or set the environment variable:'));
29
+ console.log(` ${chalk.cyan('export DARKLENS_API_KEY="your-api-key"')}`);
30
+ console.log(chalk.dim('\nGet your API key at: https://darklens.dev/dashboard\n'));
31
+ }
32
+ process.exit(1);
33
+ }
34
+
35
+ const threshold = parseInt(options.threshold, 10) || 70;
36
+ const failOn = options.failOn || 'score';
37
+
38
+ let spinner = null;
39
+ if (!options.json) {
40
+ console.log(chalk.bold.hex('#8B5CF6')('\n🔍 DarkLens Compliance Scanner') + chalk.dim(` v${packageJson.version}\n`));
41
+ spinner = ora(`Scanning ${chalk.cyan(url)} for dark patterns...`).start();
42
+ }
43
+
44
+ try {
45
+ const res = await fetch('https://darklens.dev/api/ci/scan', {
46
+ method: 'POST',
47
+ headers: {
48
+ 'Authorization': `Bearer ${apiKey}`,
49
+ 'Content-Type': 'application/json',
50
+ 'User-Agent': `DarkLens-CLI/${packageJson.version}`,
51
+ },
52
+ body: JSON.stringify({
53
+ url,
54
+ threshold,
55
+ failOn,
56
+ }),
57
+ });
58
+
59
+ const data = await res.json();
60
+
61
+ // Check for real API-level errors (401 Unauthorized, 403 Forbidden, 429 Rate Limit, 500 Server Error)
62
+ if (!res.ok && res.status !== 422) {
63
+ if (spinner) spinner.fail(chalk.red(`API Error (${res.status}): ${data.message || data.error || res.statusText}`));
64
+ if (options.json) console.error(JSON.stringify(data));
65
+ process.exit(1);
66
+ }
67
+
68
+ if (spinner) spinner.stop();
69
+
70
+ // Raw JSON output mode
71
+ if (options.json) {
72
+ console.log(JSON.stringify(data, null, 2));
73
+ process.exit(data.pass ? 0 : 1);
74
+ }
75
+
76
+ // Pretty CLI output mode
77
+ const scoreColor = data.score >= threshold ? chalk.green.bold : chalk.red.bold;
78
+ const passBadge = data.pass
79
+ ? chalk.bgGreen.black(' PASS ')
80
+ : chalk.bgRed.white(' FAIL ');
81
+
82
+ console.log('──────────────────────────────────────────────────');
83
+ console.log(` Target: ${chalk.bold(url)}`);
84
+ console.log(` Score: ${scoreColor(data.score)} / 100 ${passBadge}`);
85
+ console.log(` Threshold: ${threshold} / 100 (Criterion: fail on ${failOn})`);
86
+ if (data.counts) {
87
+ console.log(` Breakdown: ${chalk.red(`${data.counts.critical || 0} Critical`)}, ${chalk.hex('#f97316')(`${data.counts.high || 0} High`)}, ${chalk.yellow(`${data.counts.medium || 0} Medium`)}, ${chalk.cyan(`${data.counts.low || 0} Low`)}`);
88
+ }
89
+ console.log('──────────────────────────────────────────────────\n');
90
+
91
+ if (data.findings && data.findings.length > 0) {
92
+ console.log(chalk.bold(`Detected Findings (${data.findings.length}):`));
93
+ data.findings.forEach((finding, idx) => {
94
+ let sevBadge;
95
+ switch ((finding.severity || '').toLowerCase()) {
96
+ case 'critical':
97
+ sevBadge = chalk.bgRed.white.bold(' CRITICAL ');
98
+ break;
99
+ case 'high':
100
+ sevBadge = chalk.red.bold(' HIGH ');
101
+ break;
102
+ case 'medium':
103
+ sevBadge = chalk.yellow.bold(' MEDIUM ');
104
+ break;
105
+ default:
106
+ sevBadge = chalk.cyan.bold(' LOW ');
107
+ }
108
+
109
+ console.log(`\n [${idx + 1}] ${sevBadge} ${chalk.bold(finding.name)}`);
110
+ if (finding.category) {
111
+ console.log(` ${chalk.dim('Category:')} ${finding.category}`);
112
+ }
113
+ if (finding.regulation) {
114
+ console.log(` ${chalk.dim('Regulation:')} ${chalk.magenta(finding.regulation)}`);
115
+ }
116
+ if (finding.description) {
117
+ console.log(` ${chalk.dim('Details:')} ${finding.description}`);
118
+ }
119
+ });
120
+ console.log('');
121
+ } else {
122
+ console.log(chalk.green('✔ No dark patterns detected. Perfect compliance score!\n'));
123
+ }
124
+
125
+ if (data.pass) {
126
+ console.log(chalk.green.bold('✔ PASSED: Build criteria satisfied.\n'));
127
+ process.exit(0);
128
+ } else {
129
+ console.log(chalk.red.bold(`✖ FAILED: ${data.failReason || 'Compliance score dropped below threshold.'}`));
130
+ console.log(chalk.dim(`View live audit dashboard & remediation fixes at: https://darklens.dev/dashboard\n`));
131
+ process.exit(1);
132
+ }
133
+
134
+ } catch (err) {
135
+ if (spinner) spinner.fail(chalk.red('Failed to connect to DarkLens API.'));
136
+ if (options.json) {
137
+ console.error(JSON.stringify({ error: err.message }));
138
+ } else {
139
+ console.error(chalk.red(err.message));
140
+ console.log(chalk.dim('Ensure your device has internet access and https://darklens.dev is reachable.\n'));
141
+ }
142
+ process.exit(1);
143
+ }
144
+ });
145
+
146
+ program.parse(process.argv);
package/package.json CHANGED
@@ -1,6 +1,50 @@
1
1
  {
2
2
  "name": "darklens",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "1.0.0",
4
+ "description": "DarkLens CLI: Enterprise compliance scanning for Dark Patterns and deceptive UI (GDPR, FTC, CCPA, EU DSA).",
5
+ "main": "bin/index.js",
6
+ "bin": {
7
+ "darklens": "bin/index.js"
8
+ },
9
+ "files": [
10
+ "bin",
11
+ "README.md",
12
+ "LICENSE"
13
+ ],
14
+ "scripts": {
15
+ "start": "node bin/index.js",
16
+ "test": "node bin/index.js --help"
17
+ },
18
+ "keywords": [
19
+ "dark-patterns",
20
+ "compliance",
21
+ "gdpr",
22
+ "ftc",
23
+ "ccpa",
24
+ "eu-dsa",
25
+ "auditing",
26
+ "devsecops",
27
+ "ci-cd",
28
+ "accessibility",
29
+ "darklens"
30
+ ],
31
+ "author": "DarkLens <support@darklens.dev> (https://darklens.dev)",
32
+ "license": "MIT",
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "https://github.com/bhanu403/darklens-cli.git"
36
+ },
37
+ "homepage": "https://darklens.dev",
38
+ "bugs": {
39
+ "url": "https://darklens.dev/contact"
40
+ },
41
+ "dependencies": {
42
+ "chalk": "^4.1.2",
43
+ "commander": "^11.0.0",
44
+ "node-fetch": "^2.7.0",
45
+ "ora": "^5.4.1"
46
+ },
47
+ "engines": {
48
+ "node": ">=16.0.0"
49
+ }
50
+ }