codymaster 4.5.1 → 4.5.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codymaster",
3
- "version": "4.5.1",
3
+ "version": "4.5.2",
4
4
  "description": "68+ Skills. Ship 10x faster. AI-powered coding skill kit for Claude, Cursor, Gemini & more.",
5
5
  "main": "dist/index.js",
6
6
  "repository": {
@@ -46,6 +46,7 @@
46
46
  "type": "commonjs",
47
47
  "files": [
48
48
  "dist/",
49
+ "scripts/",
49
50
  "skills/",
50
51
  "adapters/",
51
52
  "commands/",
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Gate 0: Secret Hygiene
4
+ * Fastest gate (< 0.5s). Checks for leaked secrets before anything else runs.
5
+ */
6
+ const fs = require('fs');
7
+ const { execSync } = require('child_process');
8
+
9
+ let failed = false;
10
+
11
+ // 1. Check wrangler config files for hardcoded secret values
12
+ const wranglerFiles = ['wrangler.toml', 'wrangler.jsonc', 'wrangler.json'];
13
+ const dangerous = [
14
+ 'SERVICE_KEY', 'ANON_KEY', 'DB_PASSWORD', 'SECRET_KEY', 'PRIVATE_KEY', 'API_SECRET',
15
+ 'GCP_SERVICE_ACCOUNT', 'AZURE_CONNECTION_STRING', 'HEROKU_API_KEY', 'POSTMAN_API_KEY'
16
+ ];
17
+
18
+ for (const wf of wranglerFiles) {
19
+ if (!fs.existsSync(wf)) continue;
20
+ const src = fs.readFileSync(wf, 'utf-8');
21
+ for (const key of dangerous) {
22
+ const valuePattern = new RegExp(key + '\\s*[=:]\\s*["\'][a-zA-Z0-9/+=]{20,}', 'g');
23
+ if (valuePattern.test(src)) {
24
+ console.error('❌ DANGEROUS: ' + wf + ' contains a ' + key + ' VALUE');
25
+ console.error(' Fix: wrangler secret put ' + key + ' (then remove from ' + wf + ')');
26
+ failed = true;
27
+ }
28
+ }
29
+ }
30
+
31
+ // 2. Check .gitignore has required patterns
32
+ if (fs.existsSync('.gitignore')) {
33
+ const gi = fs.readFileSync('.gitignore', 'utf-8');
34
+ const required = ['.env', '.dev.vars'];
35
+ const missing = required.filter(r => !gi.includes(r));
36
+ if (missing.length > 0) {
37
+ console.error('❌ .gitignore missing: ' + missing.join(', '));
38
+ failed = true;
39
+ }
40
+ } else {
41
+ console.error('❌ No .gitignore found!');
42
+ failed = true;
43
+ }
44
+
45
+ // 3. Check .env / .dev.vars files aren't tracked by git
46
+ try {
47
+ const tracked = execSync('git ls-files', { encoding: 'utf-8' });
48
+ const badFiles = ['.env', '.dev.vars', '.env.local', '.env.production'];
49
+ const trackedBad = badFiles.filter(f => tracked.split('\n').includes(f));
50
+ if (trackedBad.length > 0) {
51
+ console.error('❌ CRITICAL: Secret files tracked by git: ' + trackedBad.join(', '));
52
+ console.error(' Fix: git rm --cached ' + trackedBad.join(' '));
53
+ failed = true;
54
+ }
55
+ } catch (e) {
56
+ // Not a git repo — skip
57
+ }
58
+
59
+ if (failed) {
60
+ console.error('\n🛡️ Gate 0 FAILED. Fix issues above before deploying.');
61
+ process.exit(1);
62
+ }
63
+ console.log('✅ Gate 0 passed: secret hygiene verified');
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Gate 1: Syntax Validation
4
+ * Fast-fail (< 2s). Catches syntax errors before the slower test suite.
5
+ * - Parses all JS files in public/js/ with acorn
6
+ * - Runs tsc --noEmit for TypeScript in src/
7
+ */
8
+ const { parse } = require('acorn');
9
+ const fs = require('fs');
10
+ const path = require('path');
11
+ const { execSync } = require('child_process');
12
+
13
+ let failed = false;
14
+
15
+ // 1. Parse all JS files in public/js/
16
+ const jsDir = 'public/js';
17
+ if (fs.existsSync(jsDir)) {
18
+ const jsFiles = fs.readdirSync(jsDir).filter(f => f.endsWith('.js'));
19
+ for (const file of jsFiles) {
20
+ const filePath = path.join(jsDir, file);
21
+ const code = fs.readFileSync(filePath, 'utf-8');
22
+ try {
23
+ parse(code, { ecmaVersion: 2022, sourceType: 'script' });
24
+ } catch (err) {
25
+ console.error(`❌ Syntax error in ${filePath}:`);
26
+ console.error(` Line ${err.loc?.line}, Column ${err.loc?.column}: ${err.message}`);
27
+ failed = true;
28
+ }
29
+ }
30
+ if (!failed) {
31
+ console.log(`✅ ${jsFiles.length} JS files parsed successfully`);
32
+ }
33
+ } else {
34
+ console.log('⚠ No public/js/ directory found, skipping JS syntax check');
35
+ }
36
+
37
+ // 2. TypeScript compilation check
38
+ if (fs.existsSync('tsconfig.json')) {
39
+ try {
40
+ execSync('npx tsc --noEmit', { encoding: 'utf-8', stdio: 'pipe' });
41
+ console.log('✅ TypeScript compilation check passed');
42
+ } catch (err) {
43
+ console.error('❌ TypeScript compilation errors:');
44
+ console.error(err.stdout || err.stderr || err.message);
45
+ failed = true;
46
+ }
47
+ }
48
+
49
+ if (failed) {
50
+ console.error('\n🔴 Gate 1 FAILED. Fix syntax errors before proceeding.');
51
+ process.exit(1);
52
+ }
53
+ console.log('✅ Gate 1 passed: syntax validation complete');
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Gate 5: Dist Asset Verification
4
+ * Verifies critical files exist in public/ after build:html + docs:build.
5
+ * Build can "succeed" but produce an incomplete output directory.
6
+ */
7
+ const fs = require('fs');
8
+ const path = require('path');
9
+
10
+ const publicDir = 'public';
11
+ // Critical HTML pages
12
+ const requiredHtml = [
13
+ 'dashboard/index.html',
14
+ ];
15
+
16
+ // Critical JS files
17
+ const requiredJs = [
18
+ 'dashboard/app.js',
19
+ ];
20
+
21
+ // Critical CSS files
22
+ const requiredCss = [
23
+ 'dashboard/style.css',
24
+ ];
25
+
26
+ // Build required file list
27
+ const required = [];
28
+
29
+ // HTML pages
30
+ for (const html of requiredHtml) {
31
+ required.push(path.join(publicDir, html));
32
+ }
33
+
34
+ // JS files
35
+ for (const js of requiredJs) {
36
+ required.push(path.join(publicDir, js));
37
+ }
38
+
39
+ // CSS files
40
+ for (const css of requiredCss) {
41
+ required.push(path.join(publicDir, css));
42
+ }
43
+
44
+
45
+ // Check all required files
46
+ const missing = required.filter(f => !fs.existsSync(f));
47
+
48
+ if (missing.length > 0) {
49
+ console.error('❌ Missing critical files:');
50
+ missing.forEach(f => console.error(' ' + f));
51
+ console.error(`\n🔴 Gate 5 FAILED. ${missing.length} file(s) missing from build output.`);
52
+ process.exit(1);
53
+ }
54
+
55
+ console.log(`✅ Gate 5 passed: all ${required.length} critical files present`);
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Gate 6: Post-Deploy Smoke Test
4
+ * Verifies the deployed site returns HTTP 200.
5
+ * Usage: node scripts/gate-6-smoke-test.js [optional-url]
6
+ */
7
+
8
+ const DEPLOY_URL = process.argv[2] || process.env.DEPLOY_URL || 'https://cody.todyle.com';
9
+
10
+ async function smokeTest() {
11
+ console.log(`🔍 Smoke testing: ${DEPLOY_URL}`);
12
+
13
+ try {
14
+ const res = await fetch(DEPLOY_URL);
15
+ if (res.status === 200) {
16
+ console.log(`✅ Gate 6 passed: HTTP ${res.status} from ${DEPLOY_URL}`);
17
+ } else {
18
+ console.error(`❌ Gate 6 FAILED: HTTP ${res.status} from ${DEPLOY_URL}`);
19
+ console.error(' ⚠ Consider immediate rollback.');
20
+ process.exit(1);
21
+ }
22
+ } catch (err) {
23
+ console.error(`❌ Gate 6 FAILED: Could not reach ${DEPLOY_URL}`);
24
+ console.error(` Error: ${err.message}`);
25
+ console.error(' ⚠ Consider immediate rollback.');
26
+ process.exit(1);
27
+ }
28
+ }
29
+
30
+ smokeTest();