improve#4
Conversation
|
Important Review skippedToo many files! This PR contains 299 files, which is 149 over the limit of 150. ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (299)
You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Review Summary by QodoComprehensive issue thread interactions, dependency management, and plugin services expansion with security and performance enhancements
WalkthroughsDescription• **Issue thread interactions system**: New service module for managing issue thread interactions (suggest_tasks, ask_user_questions, request_confirmation) with full lifecycle management, CRUD operations, and state transitions with idempotency support • **Issue dependency management**: Added issue dependency readiness tracking to prevent transitions to in_progress when blockers are unresolved; implemented child issue creation with acceptance criteria and optional parent blocking • **Company member management**: Added comprehensive company member management endpoints with role-based access control, permission grants, and invite resolution with DNS lookup and IP address validation to prevent SSRF attacks • **Issue references tracking**: Implemented issue reference tracking and syncing across documents, comments, and issue updates with activity logging • **Plugin host services expansion**: Extended plugin database namespace access and issue operations with relations management, subtree retrieval, orchestration summaries, and wakeup request methods with budget validation • **Database backup engine**: Added pg_dump and psql CLI-based backup/restore engine as alternative to JavaScript implementation for improved performance with automatic engine selection and fallback support • **Execution quarantine controls**: Added preserveLiveWork option to worktree commands to optionally skip execution quarantine with metrics tracking • **Test infrastructure**: Enhanced test setup for issue attachment routes, added comprehensive Storybook fixture data, expanded heartbeat recovery tests with new failure scenarios • **Invite system enhancements**: Extended invite system with company branding (logos, brand colors), human role support, and increased TTL from 10 minutes to 72 hours • **Query optimization**: Optimized database queries with chunking to handle large issue lists efficiently; added issue description truncation and base64 encoding for preview display • **Authorization enhancements**: Enhanced agent mutation authorization with checkout management override support and reporting-chain hierarchy checks • **Storybook configuration**: Created Tailwind CSS entry point for Storybook styling • **Code quality**: Minor formatting and style consistency improvements Diagramflowchart LR
A["Issue Thread<br/>Interactions"] -->|"state transitions"| B["Issue Service"]
B -->|"dependency tracking"| C["Blocker<br/>Management"]
D["Company Access<br/>Control"] -->|"invite resolution"| E["Member<br/>Management"]
F["Plugin Host<br/>Services"] -->|"database access"| G["Plugin Database<br/>Namespace"]
F -->|"issue operations"| B
H["Database<br/>Backup Engine"] -->|"pg_dump CLI"| I["Performance<br/>Optimization"]
J["Worktree<br/>Commands"] -->|"execution quarantine"| K["Agent<br/>Lifecycle"]
File Changes1. server/src/routes/access.ts
|
Code Review by Qodo
1. AgentConfigForm hardcodes hermes_local
|
| const next = { ...base, ...overlay.adapterConfig }; | ||
| if (adapterType === "hermes_local") { | ||
| const hermesCommand = | ||
| typeof next.hermesCommand === "string" && next.hermesCommand.length > 0 | ||
| ? next.hermesCommand | ||
| : typeof next.command === "string" && next.command.length > 0 | ||
| ? next.command | ||
| : undefined; | ||
| if (hermesCommand) { | ||
| next.hermesCommand = hermesCommand; | ||
| } | ||
| } | ||
| return next; |
There was a problem hiding this comment.
1. agentconfigform hardcodes hermes_local 📘 Rule violation ⛨ Security
The UI adds Hermes-specific configuration handling (hermesCommand) keyed off the hermes_local adapter type, coupling core UI behavior to Hermes rather than relying on the external plugin contract. This violates the requirement that Hermes be integrated only via the plugin system with no Hermes-specific logic in core UI/server.
Agent Prompt
## Issue description
Core UI special-cases the Hermes adapter via `adapterType === "hermes_local"` and manages a Hermes-only config field (`hermesCommand`). Hermes must be external-plugin-only and not require Hermes-specific logic in core UI.
## Issue Context
The compliance requirement forbids Hermes-specific integration in core UI/server; Hermes should be handled through the generic adapter/plugin contract (plugin-provided schema/config + ui-parser).
## Fix Focus Areas
- ui/src/components/AgentConfigForm.tsx[351-363]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
|
|
||
| export const hermesLocalUIAdapter: UIAdapterModule = { | ||
| type: "hermes_local", | ||
| label: "Hermes Agent", | ||
| parseStdoutLine: parseHermesStdoutLine, | ||
| ConfigFields: SchemaConfigFields, | ||
| buildAdapterConfig: buildSchemaAdapterConfig, | ||
| buildAdapterConfig: buildHermesConfig, |
There was a problem hiding this comment.
2. hermeslocaluiadapter uses hermes builder 📘 Rule violation ⚙ Maintainability
The core UI adapter registration for hermes_local uses buildHermesConfig, embedding Hermes-specific behavior in core UI instead of using the generic schema-based adapter configuration flow. This breaks the external-plugin-only Hermes requirement.
Agent Prompt
## Issue description
`ui/src/adapters/hermes-local/index.ts` now uses `buildHermesConfig` for `hermes_local`, which is Hermes-specific logic inside core UI.
## Issue Context
Hermes must be integrated only as an external plugin; core UI should not contain Hermes-specific adapter logic and should rely on the generic schema config fields / plugin-provided config+parser.
## Fix Focus Areas
- ui/src/adapters/hermes-local/index.ts[11-11]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| export async function runDatabaseRestore(opts: RunDatabaseRestoreOptions): Promise<void> { | ||
| const connectTimeout = Math.max(1, Math.trunc(opts.connectTimeoutSeconds ?? 5)); | ||
| try { | ||
| await restoreWithPsql(opts, connectTimeout); | ||
| return; | ||
| } catch (error) { | ||
| if (!(await hasStatementBreakpoints(opts.backupFile))) { | ||
| throw new Error( | ||
| `Failed to restore ${basename(opts.backupFile)} with psql: ${sanitizeRestoreErrorMessage(error)}`, | ||
| ); | ||
| } | ||
| } | ||
|
|
||
| const sql = postgres(opts.connectionString, { max: 1, connect_timeout: connectTimeout }); | ||
|
|
||
| try { |
There was a problem hiding this comment.
3. Restore fallback breaks copy 🐞 Bug ≡ Correctness
runDatabaseBackup can emit COPY ... FROM stdin blocks, but if psql restore fails, runDatabaseRestore falls back to replaying “statements” via sql.unsafe(), which cannot execute COPY data blocks or the \\. terminator. This can make restores fail (and/or obscure the original psql error) in environments where psql is missing or errors.
Agent Prompt
### Issue description
`runDatabaseRestore()` always tries `psql` first, then falls back to executing breakpoint-delimited chunks via `postgres().unsafe()`. Backups generated in `runDatabaseBackup()` may contain `COPY ... FROM stdin` blocks and `\\.` terminators, which cannot be executed through the `postgres` client as plain SQL.
### Issue Context
- COPY blocks are emitted by default when `backupEngine !== "javascript"` and no per-column nullification is needed.
- The fallback path is triggered whenever `psql` errors (missing binary, auth failures, etc.), and will then attempt to execute COPY blocks as a single SQL statement.
### Fix Focus Areas
- packages/db/src/backup-lib.ts[846-883]
- packages/db/src/backup-lib.ts[951-971]
### What to change
- Add a cheap scan (stream) to detect whether the backup file contains COPY blocks / `\\.` meta-terminators.
- If COPY blocks are present and `psql` restore fails, throw a clear error (e.g., "psql restore failed; COPY-based backups require psql") and **do not** attempt the JS `postgres` fallback.
- Alternatively: only use the JS fallback when you can prove the backup is “SQL-only” (no COPY blocks).
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| const pgDumpBin = process.env.TASKCORE_PG_DUMP_PATH || "pg_dump"; | ||
| const child = spawn( | ||
| pgDumpBin, | ||
| [ | ||
| `--dbname=${opts.connectionString}`, | ||
| "--format=plain", | ||
| "--clean", | ||
| "--if-exists", | ||
| "--no-owner", | ||
| "--no-privileges", | ||
| "--schema=public", | ||
| ], | ||
| { | ||
| stdio: ["ignore", "pipe", "pipe"], | ||
| env: { | ||
| ...process.env, | ||
| PGCONNECT_TIMEOUT: String(opts.connectTimeout), | ||
| }, | ||
| }, | ||
| ); | ||
|
|
||
| if (!child.stdout) { | ||
| throw new Error("pg_dump did not expose stdout"); | ||
| } | ||
|
|
||
| await Promise.all([ | ||
| pipeline(child.stdout, createGzip(), createWriteStream(opts.backupFile)), | ||
| waitForChildExit(child, pgDumpBin), | ||
| ]); | ||
| } | ||
|
|
||
| async function restoreWithPsql(opts: RunDatabaseRestoreOptions, connectTimeout: number): Promise<void> { | ||
| const psqlBin = process.env.TASKCORE_PSQL_PATH || "psql"; | ||
| const child = spawn( | ||
| psqlBin, | ||
| [ | ||
| `--dbname=${opts.connectionString}`, | ||
| "--set=ON_ERROR_STOP=1", | ||
| "--quiet", | ||
| "--no-psqlrc", | ||
| ], | ||
| { | ||
| stdio: ["pipe", "ignore", "pipe"], | ||
| env: { | ||
| ...process.env, | ||
| PGCONNECT_TIMEOUT: String(connectTimeout), | ||
| }, | ||
| }, | ||
| ); | ||
|
|
||
| if (!child.stdin) { | ||
| throw new Error("psql did not expose stdin"); | ||
| } | ||
|
|
||
| const input = opts.backupFile.endsWith(".gz") | ||
| ? createReadStream(opts.backupFile).pipe(createGunzip()) | ||
| : createReadStream(opts.backupFile); | ||
|
|
||
| await Promise.all([ | ||
| pipeline(input, child.stdin), | ||
| waitForChildExit(child, psqlBin), | ||
| ]); |
There was a problem hiding this comment.
4. Db creds exposed in argv 🐞 Bug ⛨ Security
The new pg_dump/psql paths pass the full DB connection string via --dbname=..., which can include passwords. That leaks credentials to other local users via process listings while pg_dump/psql runs.
Agent Prompt
### Issue description
`runPgDumpBackup()` and `restoreWithPsql()` pass `opts.connectionString` as a command-line argument (`--dbname=...`). When the connection string contains credentials, they become visible in OS process listings.
### Issue Context
This code is used by server-triggered backups (`runDatabaseBackup({ connectionString: activeDatabaseConnectionString, ... })`), and embedded postgres URLs include `user:password@...`.
### Fix Focus Areas
- packages/db/src/backup-lib.ts[273-340]
- server/src/index.ts[421-439]
- server/src/index.ts[557-562]
### What to change
- Parse the connection string and pass connection parameters without embedding the password in argv:
- Prefer `--host`, `--port`, `--username`, `--dbname` and provide the password via `PGPASSWORD` env var, or
- Create a temporary `.pgpass` file with `0600` perms and set `PGPASSFILE`.
- Ensure any logs/errors do not echo the full URL with password.
- Apply the same approach to both `pg_dump` and `psql` spawn paths.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
Thinking Path
What Changed
Verification
Risks
Model Used
Checklist