chore: clean up proxy config and remove unused test script#16
Conversation
- Remove ACME_EMAIL from README example (no longer needed) - Delete unused services/db/test-setup.sh test script - Remove debug-level global config block from Caddyfile - Change Caddyfile log level from DEBUG to INFO
📝 WalkthroughWalkthroughThree files were modified to remove or simplify configuration and testing infrastructure. The README.md had an environment variable line removed from deployment instructions. The entire services/db/test-setup.sh file, which contained a 12-step end-to-end test workflow for a Tale DB Docker container setup, was deleted. The services/proxy/Caddyfile was updated to remove the global configuration block with debug and email settings and to change the log level from DEBUG to INFO. Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: ASSERTIVE Plan: Pro (Legacy) 📒 Files selected for processing (3)
💤 Files with no reviewable changes (2)
🧰 Additional context used📓 Path-based instructions (1)**/*📄 CodeRabbit inference engine (.cursor/rules/workspace_rules.mdc)
Files:
🔇 Additional comments (2)
Comment |
…inding Five clustered cross-tenant + IDOR P0s flagged by the two-round data-protection review (round-1 #5, #16, #17, #27, round-2 V1, V7, V8): P0-1, P0-2: generic admin-trash restore `restoreRowToActive` (soft_delete_helpers) added required `organizationId` arg + `userMembershipIds` set; refuses cross-org rows with `not_found` (no foreign-id existence oracle) and rows whose author is on a custodian hold. Added `authorField` to `SOFT_DELETE_RESOURCE_CONFIG` per resource type so the cascade fires uniformly across the 14 restorable types. `restoreSoftDeletedRow` (governance/restore.ts) threads holds + orgId. P0-3, P0-4: REST cross-tenant on GET/PATCH/DELETE Added optional `callerOrgId` arg to every internal query/mutation reachable from REST: threads (`getThreadMetadata`, `getThreadMessagesInternal`), customers (get/update/delete), vendors (get/update/delete), products (get/update/delete), documents (getDocumentByIdRaw, updateDocument, deleteDocumentById), workflow executions (getExecution, getRawExecution, listExecutionsCursorInternal, getExecutionStepJournalInternal), workflow triggers (cancelExecutionInternal, updateScheduleInternal, deleteScheduleInternal, deleteWebhookInternal). Each REST handler passes `rc.org.organizationId`. Mismatches return null/empty (so REST surfaces 404) — never throw cross-tenantly to avoid leaking row existence. P0-5: rag_search IDOR + thread-binding Architectural change: chat uploads bind to their thread at upload time. - file_metadata schema: new optional `threadId` + composite index `by_organizationId_and_threadId`. - file_metadata.saveFileMetadata: accepts threadId; refuses cross-org threadId via threadMetadata lookup. - chat-input upload hook: passes the current chat threadId. - New helpers: `threads/get_thread_ancestor_chain.ts` (action-side walk of the delegation chain via existing `getParentThreadId`), `agent_tools/rag/helpers/verify_thread_scoped_access.ts` (query that same-org-checks each storageId, then if `meta.threadId` is set, requires it in the caller's accessible chain). - rag_search search-op: when explicit fileIds are supplied, verify via the new query (replaces unauthenticated short-circuit). - rag_search retrieve-op: replaces commit d7bc3da's stricter "agent allow-list" check, which over-strictly blocked legitimate chat-upload retrieval (chat uploads never appear in the agent's pre-configured `knowledgeFileIds`/`agentTeamId`/`includeOrgKnowledge` sets). Same-org + thread-scope is the correct invariant. Cascade integration: - threads/cascade_helpers.ts: deletes bound fileMetadata + storage blobs as part of thread hard-delete (Pass B / GDPR erasure path). RAG-side fan-out is deferred to commit 4 (P0-13). - threads/delete_chat_thread.ts (Pass A trash): cascades soft-delete to bound fileMetadata rows (lifecycleStatus='trashed', mirrors grace-extension defense). - threads/restore_chat_thread.ts: cascades restore to fileMetadata rows trashed within ±5s skew of the thread's trash time (avoids zombie-restoring files that were independently trashed earlier). Verified: `bun typecheck` clean; 871 tests across affected areas pass. Regression tests for the new gates land in commit 6 (test guards) per the bundle plan.
…inding Five clustered cross-tenant + IDOR P0s flagged by the two-round data-protection review (round-1 #5, #16, #17, #27, round-2 V1, V7, V8): P0-1, P0-2: generic admin-trash restore `restoreRowToActive` (soft_delete_helpers) added required `organizationId` arg + `userMembershipIds` set; refuses cross-org rows with `not_found` (no foreign-id existence oracle) and rows whose author is on a custodian hold. Added `authorField` to `SOFT_DELETE_RESOURCE_CONFIG` per resource type so the cascade fires uniformly across the 14 restorable types. `restoreSoftDeletedRow` (governance/restore.ts) threads holds + orgId. P0-3, P0-4: REST cross-tenant on GET/PATCH/DELETE Added optional `callerOrgId` arg to every internal query/mutation reachable from REST: threads (`getThreadMetadata`, `getThreadMessagesInternal`), customers (get/update/delete), vendors (get/update/delete), products (get/update/delete), documents (getDocumentByIdRaw, updateDocument, deleteDocumentById), workflow executions (getExecution, getRawExecution, listExecutionsCursorInternal, getExecutionStepJournalInternal), workflow triggers (cancelExecutionInternal, updateScheduleInternal, deleteScheduleInternal, deleteWebhookInternal). Each REST handler passes `rc.org.organizationId`. Mismatches return null/empty (so REST surfaces 404) — never throw cross-tenantly to avoid leaking row existence. P0-5: rag_search IDOR + thread-binding Architectural change: chat uploads bind to their thread at upload time. - file_metadata schema: new optional `threadId` + composite index `by_organizationId_and_threadId`. - file_metadata.saveFileMetadata: accepts threadId; refuses cross-org threadId via threadMetadata lookup. - chat-input upload hook: passes the current chat threadId. - New helpers: `threads/get_thread_ancestor_chain.ts` (action-side walk of the delegation chain via existing `getParentThreadId`), `agent_tools/rag/helpers/verify_thread_scoped_access.ts` (query that same-org-checks each storageId, then if `meta.threadId` is set, requires it in the caller's accessible chain). - rag_search search-op: when explicit fileIds are supplied, verify via the new query (replaces unauthenticated short-circuit). - rag_search retrieve-op: replaces commit d7bc3da's stricter "agent allow-list" check, which over-strictly blocked legitimate chat-upload retrieval (chat uploads never appear in the agent's pre-configured `knowledgeFileIds`/`agentTeamId`/`includeOrgKnowledge` sets). Same-org + thread-scope is the correct invariant. Cascade integration: - threads/cascade_helpers.ts: deletes bound fileMetadata + storage blobs as part of thread hard-delete (Pass B / GDPR erasure path). RAG-side fan-out is deferred to commit 4 (P0-13). - threads/delete_chat_thread.ts (Pass A trash): cascades soft-delete to bound fileMetadata rows (lifecycleStatus='trashed', mirrors grace-extension defense). - threads/restore_chat_thread.ts: cascades restore to fileMetadata rows trashed within ±5s skew of the thread's trash time (avoids zombie-restoring files that were independently trashed earlier). Verified: `bun typecheck` clean; 871 tests across affected areas pass. Regression tests for the new gates land in commit 6 (test guards) per the bundle plan.
Closes #15, #16, #17, #18, #41 — secret sanitiser + audio-fetch headers. - `sanitize_secrets.ts` JSON-value class now honours backslash-escaped characters: `(?:[^"\\]|\\.)*` instead of `[^"]*`. Previously a value containing `\"` (an escaped quote inside the string) terminated the redaction at the first inner quote and left the rest of the JSON object exposed. Test added that pins the new behaviour. - `sanitize_secrets.ts` patterns extended with Stripe (`sk_/pk_/rk_` × `live/test`), OpenAI org/project identifiers (`org-…`, `proj_…`), Cookie / Set-Cookie header lines, and bare Better Auth session tokens. An idempotency check (sanitize ∘ sanitize = sanitize) and a 100k-char ReDoS guard round out the new coverage. - `http.ts /api/tts-audio` moves the per-IP rate limit ABOVE the Better Auth session lookup. An unauthenticated attacker hammering the route was previously forcing a DB session-query per request — mirrors the `/storage` route's order. - `http.ts /api/tts-audio` Cache-Control changes from `private, max-age=600` to `private, max-age=0, must-revalidate`. A removed member can no longer replay cached audio for up to 10 minutes past their removal; the revalidating round-trip re-hits the membership gate on every replay. - `http.ts /api/tts-audio` sets `Accept-Ranges: none` so iOS Safari `<audio preload="auto">` range probes don't trigger audible mid-chunk restarts.
Closes #15, #16, #17, #18, #41 — secret sanitiser + audio-fetch headers. - `sanitize_secrets.ts` JSON-value class now honours backslash-escaped characters: `(?:[^"\\]|\\.)*` instead of `[^"]*`. Previously a value containing `\"` (an escaped quote inside the string) terminated the redaction at the first inner quote and left the rest of the JSON object exposed. Test added that pins the new behaviour. - `sanitize_secrets.ts` patterns extended with Stripe (`sk_/pk_/rk_` × `live/test`), OpenAI org/project identifiers (`org-…`, `proj_…`), Cookie / Set-Cookie header lines, and bare Better Auth session tokens. An idempotency check (sanitize ∘ sanitize = sanitize) and a 100k-char ReDoS guard round out the new coverage. - `http.ts /api/tts-audio` moves the per-IP rate limit ABOVE the Better Auth session lookup. An unauthenticated attacker hammering the route was previously forcing a DB session-query per request — mirrors the `/storage` route's order. - `http.ts /api/tts-audio` Cache-Control changes from `private, max-age=600` to `private, max-age=0, must-revalidate`. A removed member can no longer replay cached audio for up to 10 minutes past their removal; the revalidating round-trip re-hits the membership gate on every replay. - `http.ts /api/tts-audio` sets `Accept-Ranges: none` so iOS Safari `<audio preload="auto">` range probes don't trigger audible mid-chunk restarts.
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.