@soulbatical/tetra-dev-toolkit 1.20.0 → 2.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.
@@ -1,197 +0,0 @@
1
- /**
2
- * Tetra Core Compliance — HARD BLOCK
3
- *
4
- * If a project has @soulbatical/tetra-core as a dependency, it MUST use:
5
- * 1. configureAuth() — sets up authentication middleware
6
- * 2. authenticateToken — middleware on protected routes
7
- * 3. adminDB/userDB/systemDB — db helpers (NOT raw createClient)
8
- *
9
- * If ANY of these are missing, the project is NOT secure.
10
- * There is no "skip" — if you have tetra-core, you use it fully or not at all.
11
- *
12
- * This check also detects projects that SHOULD have tetra-core but don't:
13
- * - Has a backend/ dir with Express + Supabase → MUST have tetra-core
14
- */
15
-
16
- import { readFileSync, existsSync } from 'fs'
17
- import { join } from 'path'
18
- import { glob } from 'glob'
19
-
20
- export const meta = {
21
- id: 'tetra-core-compliance',
22
- name: 'Tetra Core Compliance',
23
- category: 'security',
24
- severity: 'critical',
25
- description: 'Ensures projects using @soulbatical/tetra-core implement ALL required security patterns — auth, middleware, db helpers'
26
- }
27
-
28
- export async function run(config, projectRoot) {
29
- const results = {
30
- passed: true,
31
- findings: [],
32
- summary: { total: 0, critical: 0, high: 0, medium: 0, low: 0 }
33
- }
34
-
35
- // ─── Step 1: Does this project have tetra-core? ────────────────
36
-
37
- const packageJsonPaths = [
38
- join(projectRoot, 'package.json'),
39
- join(projectRoot, 'backend', 'package.json')
40
- ]
41
-
42
- let hasTetraCore = false
43
- let tetraCoreLocation = null
44
-
45
- for (const pkgPath of packageJsonPaths) {
46
- if (!existsSync(pkgPath)) continue
47
- try {
48
- const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'))
49
- const deps = { ...pkg.dependencies, ...pkg.devDependencies }
50
- if (deps['@soulbatical/tetra-core']) {
51
- hasTetraCore = true
52
- tetraCoreLocation = pkgPath.replace(projectRoot + '/', '')
53
- break
54
- }
55
- } catch { /* skip */ }
56
- }
57
-
58
- // ─── Step 2: Check if project SHOULD have tetra-core ───────────
59
-
60
- if (!hasTetraCore) {
61
- // Check if this is an Express + Supabase backend that should have it
62
- const backendDirs = ['backend/src', 'src']
63
- let hasExpress = false
64
- let hasSupabase = false
65
-
66
- for (const dir of backendDirs) {
67
- const pkgPath = dir === 'src' ? join(projectRoot, 'package.json') : join(projectRoot, 'backend', 'package.json')
68
- if (!existsSync(pkgPath)) continue
69
- try {
70
- const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'))
71
- const deps = { ...pkg.dependencies, ...pkg.devDependencies }
72
- if (deps['express']) hasExpress = true
73
- if (deps['@supabase/supabase-js']) hasSupabase = true
74
- } catch { /* skip */ }
75
- }
76
-
77
- if (hasExpress && hasSupabase) {
78
- results.passed = false
79
- results.findings.push({
80
- type: 'missing-tetra-core',
81
- severity: 'critical',
82
- message: 'Project has Express + Supabase but does NOT have @soulbatical/tetra-core. This means NO standard auth middleware, NO db helpers, NO RLS enforcement. Install tetra-core and follow the architecture guide.',
83
- fix: 'npm install @soulbatical/tetra-core && see stella_howto_get slug="tetra-architecture-guide"'
84
- })
85
- results.summary.critical++
86
- results.summary.total++
87
- } else {
88
- // Not a backend project, skip
89
- results.skipped = true
90
- results.skipReason = 'Not a Tetra backend project (no Express + Supabase)'
91
- return results
92
- }
93
-
94
- return results
95
- }
96
-
97
- // ─── Step 3: Has tetra-core → check FULL compliance ────────────
98
-
99
- const backendSrc = existsSync(join(projectRoot, 'backend', 'src')) ? 'backend/src' : 'src'
100
-
101
- // Check 3a: configureAuth() is called somewhere
102
- const tsFiles = await glob(`${backendSrc}/**/*.ts`, {
103
- cwd: projectRoot,
104
- ignore: ['**/node_modules/**', '**/*.test.ts', '**/*.spec.ts', '**/*.d.ts']
105
- })
106
-
107
- let hasConfigureAuth = false
108
- let hasAuthenticateToken = false
109
- let hasDbHelpers = false
110
- let dbHelperImports = { adminDB: false, userDB: false, systemDB: false, publicDB: false, superadminDB: false }
111
- let hasRawCreateClient = false
112
- let rawCreateClientFiles = []
113
-
114
- for (const file of tsFiles) {
115
- try {
116
- const content = readFileSync(join(projectRoot, file), 'utf-8')
117
-
118
- if (content.includes('configureAuth')) hasConfigureAuth = true
119
- if (content.includes('authenticateToken')) hasAuthenticateToken = true
120
-
121
- // Check for db helper usage
122
- if (/(?:import|from).*(?:adminDB|userDB|systemDB|publicDB|superadminDB)/.test(content)) {
123
- hasDbHelpers = true
124
- if (content.includes('adminDB')) dbHelperImports.adminDB = true
125
- if (content.includes('userDB')) dbHelperImports.userDB = true
126
- if (content.includes('systemDB')) dbHelperImports.systemDB = true
127
- if (content.includes('publicDB')) dbHelperImports.publicDB = true
128
- if (content.includes('superadminDB')) dbHelperImports.superadminDB = true
129
- }
130
-
131
- // Check for raw createClient usage (should be caught by direct-supabase-client check too)
132
- if (/import\s*\{[^}]*createClient[^}]*\}\s*from\s*['"]@supabase\/supabase-js['"]/.test(content)) {
133
- if (!/import\s+type/.test(content)) {
134
- // Not in core wrapper files
135
- if (!/core\//.test(file) && !/SupabaseUserClient/.test(file) && !/scripts\//.test(file)) {
136
- hasRawCreateClient = true
137
- rawCreateClientFiles.push(file)
138
- }
139
- }
140
- }
141
- } catch { /* skip */ }
142
- }
143
-
144
- // ─── Report findings ──────────────────────────────────────────
145
-
146
- if (!hasConfigureAuth) {
147
- results.passed = false
148
- results.findings.push({
149
- type: 'missing-configureAuth',
150
- severity: 'critical',
151
- message: 'Project has @soulbatical/tetra-core but NEVER calls configureAuth(). This means the auth middleware is not initialized — all routes are potentially unprotected.',
152
- fix: 'Create an auth-config.ts that calls configureAuth({ loadUserContext, roleHierarchy }). See sparkbuddy-live/backend/src/auth-config.ts for reference.'
153
- })
154
- results.summary.critical++
155
- results.summary.total++
156
- }
157
-
158
- if (!hasAuthenticateToken) {
159
- results.passed = false
160
- results.findings.push({
161
- type: 'missing-authenticateToken',
162
- severity: 'critical',
163
- message: 'Project has @soulbatical/tetra-core but NO route uses authenticateToken middleware. All API endpoints are unprotected.',
164
- fix: 'Add authenticateToken middleware to all protected routes: router.use(authenticateToken, requireOrganizationAdmin)'
165
- })
166
- results.summary.critical++
167
- results.summary.total++
168
- }
169
-
170
- if (!hasDbHelpers) {
171
- results.passed = false
172
- results.findings.push({
173
- type: 'missing-db-helpers',
174
- severity: 'critical',
175
- message: 'Project has @soulbatical/tetra-core but does NOT use any db helpers (adminDB, userDB, systemDB, publicDB). Database access has no RLS enforcement.',
176
- fix: 'Use adminDB(req) for admin routes, userDB(req) for user routes, systemDB(context) for system operations. See stella_howto_get slug="tetra-architecture-guide"'
177
- })
178
- results.summary.critical++
179
- results.summary.total++
180
- }
181
-
182
- // Info: which helpers are used
183
- const usedHelpers = Object.entries(dbHelperImports).filter(([_, used]) => used).map(([name]) => name)
184
- const unusedHelpers = Object.entries(dbHelperImports).filter(([_, used]) => !used).map(([name]) => name)
185
-
186
- results.info = {
187
- tetraCoreLocation,
188
- configureAuth: hasConfigureAuth,
189
- authenticateToken: hasAuthenticateToken,
190
- dbHelpers: {
191
- used: usedHelpers,
192
- unused: unusedHelpers
193
- }
194
- }
195
-
196
- return results
197
- }