@soulbatical/tetra-dev-toolkit 1.16.0 → 1.16.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.
@@ -134,14 +134,55 @@ 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 entries = whitelistMatch[1]
138
- .split('\n')
139
- .map(line => {
140
- const m = line.match(/['"]([^'"]+)['"]/)
141
- return m ? m[1] : null
142
- })
143
- .filter(Boolean)
144
- whitelist = new Set(entries)
137
+ const rawLines = whitelistMatch[1].split('\n')
138
+ let groupComment = null
139
+
140
+ for (let i = 0; i < rawLines.length; i++) {
141
+ const line = rawLines[i].trim()
142
+
143
+ // Track group comments — a comment line that is NOT inline with an entry
144
+ // Group comments apply to ALL entries below them until the next group comment
145
+ if (/^\s*\/\//.test(line) && !line.match(/['"][^'"]+['"]/)) {
146
+ const commentText = line.replace(/^\s*\/\/\s*/, '').trim()
147
+ if (commentText.length > 0) {
148
+ groupComment = commentText
149
+ }
150
+ continue
151
+ }
152
+
153
+ // Skip empty lines (don't reset group comment)
154
+ if (!line || line === ',') continue
155
+
156
+ const entryMatch = line.match(/['"]([^'"]+)['"]/)
157
+ if (!entryMatch) continue
158
+
159
+ const entry = entryMatch[1]
160
+ whitelist.add(entry)
161
+
162
+ // Check for inline comment: 'entry', // reason
163
+ const inlineCommentMatch = line.match(/['"][^'"]+['"]\s*,?\s*\/\/\s*(.+)/)
164
+ const inlineReason = inlineCommentMatch ? inlineCommentMatch[1].trim() : null
165
+
166
+ // Entry is justified if it has an inline comment OR falls under a group comment
167
+ const hasJustification = inlineReason || groupComment
168
+
169
+ if (!hasJustification) {
170
+ // Find line number in original file
171
+ const entryLineInFile = systemDbContent.substring(0, systemDbContent.indexOf(entry)).split('\n').length
172
+
173
+ results.findings.push({
174
+ file: systemDbPath.replace(projectRoot + '/', ''),
175
+ line: entryLineInFile,
176
+ type: 'whitelist-no-justification',
177
+ severity: 'high',
178
+ message: `systemDB whitelist entry '${entry}' has NO comment explaining WHY it needs service role key access. Add a group comment above or an inline comment.`,
179
+ fix: `Add a comment explaining why '${entry}' cannot use adminDB/userDB. Example:\n // OAuth callback — browser redirect, no JWT in header\n '${entry}',`
180
+ })
181
+ results.summary.high++
182
+ results.summary.total++
183
+ results.passed = false
184
+ }
185
+ }
145
186
  }
146
187
 
147
188
  if (whitelist.size > MAX_WHITELIST_SIZE) {
@@ -159,6 +200,28 @@ export async function run(config, projectRoot) {
159
200
  }
160
201
  }
161
202
 
203
+ // Also check .tetra-quality.json for documented whitelist with justifications
204
+ const configWhitelist = config?.supabase?.systemDbWhitelist || {}
205
+ if (typeof configWhitelist === 'object' && !Array.isArray(configWhitelist)) {
206
+ // Format: { "context-name": "reason why systemDB is needed" }
207
+ for (const [context, reason] of Object.entries(configWhitelist)) {
208
+ whitelist.add(context)
209
+ if (!reason || typeof reason !== 'string' || reason.trim().length < 5) {
210
+ results.findings.push({
211
+ file: '.tetra-quality.json',
212
+ line: 1,
213
+ type: 'config-whitelist-no-justification',
214
+ severity: 'high',
215
+ message: `systemDbWhitelist entry '${context}' has empty or insufficient justification: "${reason || ''}". Explain WHY this context cannot use adminDB/userDB.`,
216
+ fix: `In .tetra-quality.json, set: "systemDbWhitelist": { "${context}": "Reason: e.g. OAuth callback — no JWT available, browser redirect flow" }`
217
+ })
218
+ results.summary.high++
219
+ results.summary.total++
220
+ results.passed = false
221
+ }
222
+ }
223
+ }
224
+
162
225
  // ─── Check 2: systemDB in forbidden locations ───────────────
163
226
 
164
227
  const files = await glob('**/*.ts', {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@soulbatical/tetra-dev-toolkit",
3
- "version": "1.16.0",
3
+ "version": "1.16.2",
4
4
  "publishConfig": {
5
5
  "access": "restricted"
6
6
  },