({ inputs, params }, context)
| 226 | ], |
| 227 | }, |
| 228 | async execute({ inputs, params }, context) { |
| 229 | const parsedInputs = inputSchema.parse(inputs); |
| 230 | const parsedParams = parameterSchema.parse(params); |
| 231 | const databaseConnectionString = ( |
| 232 | parsedInputs.databaseConnectionString ?? parsedParams.databaseUrl |
| 233 | )?.trim(); |
| 234 | const projectRef = parsedInputs.projectRef ?? inferProjectRef(parsedInputs.supabaseUrl); |
| 235 | |
| 236 | if (!databaseConnectionString) { |
| 237 | throw new ValidationError( |
| 238 | 'Provide a Database URL (Postgres connection string) via Database URL or Connection String.', |
| 239 | { fieldErrors: { databaseUrl: ['Database URL is required.'] } }, |
| 240 | ); |
| 241 | } |
| 242 | |
| 243 | if (!projectRef) { |
| 244 | throw new ValidationError( |
| 245 | 'Could not infer Supabase project ref from URL. Please provide a valid https://<project-ref>.supabase.co URL or set projectRef explicitly.', |
| 246 | { fieldErrors: { supabaseUrl: ['Invalid or missing project reference'] } }, |
| 247 | ); |
| 248 | } |
| 249 | |
| 250 | const runnerPayload = { |
| 251 | ...parsedInputs, |
| 252 | ...parsedParams, |
| 253 | projectRef, |
| 254 | databaseConnectionString, |
| 255 | }; |
| 256 | |
| 257 | const tenantId = (context as any).tenantId ?? 'default-tenant'; |
| 258 | const volume = new IsolatedContainerVolume(tenantId, context.runId); |
| 259 | const mountPath = '/data'; |
| 260 | const configFilename = 'scanner_config.yaml'; |
| 261 | const outputFilename = 'report.json'; |
| 262 | const containerConfigPath = `${mountPath}/${configFilename}`; |
| 263 | const containerOutputFile = `${mountPath}/${outputFilename}`; |
| 264 | |
| 265 | // Build scanner_config.yaml to place inside the isolated volume |
| 266 | const configYamlLines: string[] = []; |
| 267 | configYamlLines.push('project:'); |
| 268 | configYamlLines.push(` ref: ${projectRef}`); |
| 269 | configYamlLines.push('database:'); |
| 270 | configYamlLines.push(` connection_string: ${JSON.stringify(databaseConnectionString)}`); |
| 271 | if (parsedInputs.serviceRoleKey && parsedInputs.serviceRoleKey.trim().length > 0) { |
| 272 | configYamlLines.push('api:'); |
| 273 | configYamlLines.push(` service_role_key: ${JSON.stringify(parsedInputs.serviceRoleKey)}`); |
| 274 | } |
| 275 | configYamlLines.push('scanner:'); |
| 276 | configYamlLines.push(' output:'); |
| 277 | configYamlLines.push(' format: json'); |
| 278 | configYamlLines.push(` file: ${containerOutputFile}`); |
| 279 | // Tuning thresholds – avoid non‑zero exit unless explicitly requested |
| 280 | configYamlLines.push('thresholds:'); |
| 281 | if (typeof parsedParams.minimumScore === 'number') { |
| 282 | configYamlLines.push(` minimum_score: ${parsedParams.minimumScore}`); |
| 283 | } else { |
| 284 | configYamlLines.push(' minimum_score: 0'); |
| 285 | } |
nothing calls this directly
no test coverage detected