@soulbatical/tetra-dev-toolkit 1.16.0 → 1.16.1
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.
|
@@ -134,14 +134,52 @@ export async function run(config, projectRoot) {
|
|
|
134
134
|
const whitelistMatch = systemDbContent.match(/new Set\s*(?:<[^>]+>)?\s*\(\s*\[([\s\S]*?)\]\s*\)/m)
|
|
135
135
|
|
|
136
136
|
if (whitelistMatch) {
|
|
137
|
-
const
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
137
|
+
const rawLines = whitelistMatch[1].split('\n')
|
|
138
|
+
let lastComment = null
|
|
139
|
+
|
|
140
|
+
for (let i = 0; i < rawLines.length; i++) {
|
|
141
|
+
const line = rawLines[i].trim()
|
|
142
|
+
|
|
143
|
+
// Track comments — group comments (// ...) or inline comments
|
|
144
|
+
const commentMatch = line.match(/^\s*\/\/\s*(.+)/)
|
|
145
|
+
if (commentMatch) {
|
|
146
|
+
lastComment = commentMatch[1].trim()
|
|
147
|
+
continue
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const entryMatch = line.match(/['"]([^'"]+)['"]/)
|
|
151
|
+
if (!entryMatch) { continue }
|
|
152
|
+
|
|
153
|
+
const entry = entryMatch[1]
|
|
154
|
+
whitelist.add(entry)
|
|
155
|
+
|
|
156
|
+
// Check for inline comment: 'entry', // reason
|
|
157
|
+
const inlineCommentMatch = line.match(/['"][^'"]+['"]\s*,?\s*\/\/\s*(.+)/)
|
|
158
|
+
const reason = inlineCommentMatch ? inlineCommentMatch[1].trim() : lastComment
|
|
159
|
+
|
|
160
|
+
// Find line number in original file
|
|
161
|
+
const entryLineInFile = systemDbContent.substring(0, systemDbContent.indexOf(entry)).split('\n').length
|
|
162
|
+
|
|
163
|
+
if (!reason) {
|
|
164
|
+
results.findings.push({
|
|
165
|
+
file: systemDbPath.replace(projectRoot + '/', ''),
|
|
166
|
+
line: entryLineInFile,
|
|
167
|
+
type: 'whitelist-no-justification',
|
|
168
|
+
severity: 'high',
|
|
169
|
+
message: `systemDB whitelist entry '${entry}' has NO comment explaining WHY it needs service role key access. Every whitelist entry MUST have a comment above or inline.`,
|
|
170
|
+
fix: `Add a comment explaining why '${entry}' cannot use adminDB/userDB. Example:\n // OAuth callback — browser redirect, no JWT in header\n '${entry}',`
|
|
171
|
+
})
|
|
172
|
+
results.summary.high++
|
|
173
|
+
results.summary.total++
|
|
174
|
+
results.passed = false
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Reset lastComment after consuming it for a non-dynamic entry
|
|
178
|
+
// (don't reset for "// Dynamic:" comments which apply to patterns, not specific entries)
|
|
179
|
+
if (lastComment && !lastComment.toLowerCase().startsWith('dynamic')) {
|
|
180
|
+
lastComment = null
|
|
181
|
+
}
|
|
182
|
+
}
|
|
145
183
|
}
|
|
146
184
|
|
|
147
185
|
if (whitelist.size > MAX_WHITELIST_SIZE) {
|
|
@@ -159,6 +197,28 @@ export async function run(config, projectRoot) {
|
|
|
159
197
|
}
|
|
160
198
|
}
|
|
161
199
|
|
|
200
|
+
// Also check .tetra-quality.json for documented whitelist with justifications
|
|
201
|
+
const configWhitelist = config?.supabase?.systemDbWhitelist || {}
|
|
202
|
+
if (typeof configWhitelist === 'object' && !Array.isArray(configWhitelist)) {
|
|
203
|
+
// Format: { "context-name": "reason why systemDB is needed" }
|
|
204
|
+
for (const [context, reason] of Object.entries(configWhitelist)) {
|
|
205
|
+
whitelist.add(context)
|
|
206
|
+
if (!reason || typeof reason !== 'string' || reason.trim().length < 5) {
|
|
207
|
+
results.findings.push({
|
|
208
|
+
file: '.tetra-quality.json',
|
|
209
|
+
line: 1,
|
|
210
|
+
type: 'config-whitelist-no-justification',
|
|
211
|
+
severity: 'high',
|
|
212
|
+
message: `systemDbWhitelist entry '${context}' has empty or insufficient justification: "${reason || ''}". Explain WHY this context cannot use adminDB/userDB.`,
|
|
213
|
+
fix: `In .tetra-quality.json, set: "systemDbWhitelist": { "${context}": "Reason: e.g. OAuth callback — no JWT available, browser redirect flow" }`
|
|
214
|
+
})
|
|
215
|
+
results.summary.high++
|
|
216
|
+
results.summary.total++
|
|
217
|
+
results.passed = false
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
162
222
|
// ─── Check 2: systemDB in forbidden locations ───────────────
|
|
163
223
|
|
|
164
224
|
const files = await glob('**/*.ts', {
|