Historical snapshot: this report describes the repository at the June 19, 2026 commit listed below. Its findings were remediated in the subsequent hardening work and are retained as point-in-time evidence, not as a current defect list.
- Repository:
/home/ubuntu/rahul/quickvoice - Commit:
d0284076a776a80bc39f06d90d56b4c650e366ac - Started:
2026-06-19T06:22:07+00:00 - Finished:
2026-06-19T06:58:32+00:00 - Module session status: 6 passed
This report was generated by scripts/codex_module_audit.py, which runs one isolated Codex audit session per module and aggregates the final module reports.
| Module | Status | Return Code | Duration | Logs |
|---|---|---|---|---|
root-tooling |
passed | 0 | 448.7s | .audit_runs/2026-06-19T062207+0000/root-tooling.stdout.jsonl, .audit_runs/2026-06-19T062207+0000/root-tooling.stderr.log |
apps-web |
passed | 0 | 412.6s | .audit_runs/2026-06-19T062207+0000/apps-web.stdout.jsonl, .audit_runs/2026-06-19T062207+0000/apps-web.stderr.log |
apps-console |
passed | 0 | 360.3s | .audit_runs/2026-06-19T062207+0000/apps-console.stdout.jsonl, .audit_runs/2026-06-19T062207+0000/apps-console.stderr.log |
apps-server |
passed | 0 | 317.7s | .audit_runs/2026-06-19T062207+0000/apps-server.stdout.jsonl, .audit_runs/2026-06-19T062207+0000/apps-server.stderr.log |
apps-ai |
passed | 0 | 410.4s | .audit_runs/2026-06-19T062207+0000/apps-ai.stdout.jsonl, .audit_runs/2026-06-19T062207+0000/apps-ai.stderr.log |
packages-config |
passed | 0 | 236.0s | .audit_runs/2026-06-19T062207+0000/packages-config.stdout.jsonl, .audit_runs/2026-06-19T062207+0000/packages-config.stderr.log |
- Status:
passed - Return code:
0 - Duration:
448.7s - Stdout log:
.audit_runs/2026-06-19T062207+0000/root-tooling.stdout.jsonl - Stderr log:
.audit_runs/2026-06-19T062207+0000/root-tooling.stderr.log
Audited root-tooling at commit d0284076a776a80bc39f06d90d56b4c650e366ac. Highest risk areas are broken local env bootstrap, missing PR build/test gates, and a security audit workflow that passes despite known high advisories. No tracked files were changed by the audit.
-
High: Local development bootstrap is broken.
scripts/dev-env.sh:19-23copiesapps/server/.env.dev.example,apps/console/.env.dev.example, andapps/web/.env.dev.example, but those files are absent. Repro:./scripts/dev-env.shfails withcp: cannot stat ... apps/server/.env.dev.example;node --test tests/dev-orchestration.test.mjsalso fails attests/dev-orchestration.test.mjs:49-60. Impact:task env:devandtask up:devcannot reliably onboard developers. Fix: add the missing templates or stop copying them, and preflight all sources before creating any destination files. -
High: PRs are not gated by build, lint, typecheck, or tests.
server-build.yml:3-14andai-build.yml:3-9run only onpushtomainor manual dispatch. The only PR workflow issecurity-audit.yml:6-7, and it does not runpackage.json:12-17scripts. Impact: broken app code can merge, and Docker image failures are discovered after merge. Fix: add a required PR CI workflow running frozen install, lint, typecheck, builds, JS tests, and Python tests; make deploy workflows depend on that signal. -
High: Security audit passes while high vulnerabilities exist.
.github/workflows/security-audit.yml:31-32usespnpm audit --audit-level critical. Repro: that command exited0while reporting105 vulnerabilities foundincluding47 high;pnpm audit --audit-level moderateexited1. Examples include high advisories fornext,axios,minimatch,flatted, andprotobufjs. Fix: fail at least onhigh, triage dev-only vs prod paths, and track suppressions explicitly.
-
Medium: Root quality scripts have coverage gaps.
pnpm check-typesonly runsserver#check-types; Turborepo dry-run showedconsole#check-typesandweb#check-typesas<NONEXISTENT>.pnpm lintskips the server becauseapps/server/package.json:10-17has nolintscript. Fix: add missing package scripts and make CI fail on missing expected tasks. -
Medium: Dev Postgres is exposed on all host interfaces with static credentials.
docker-compose.dev.yml:8-13publishes5432:5432withquickvoice/quickvoice. Impact: on many Docker hosts this is reachable beyond localhost. Fix: bind127.0.0.1:5432:5432and document dev-only credentials. -
Medium: Local Docker dependencies omit Redis.
docker-compose.dev.yml:3-24only starts Postgres, whileapps/server/src/config/redis.ts:3defaults toredis://localhost:6379and BullMQ uses it atapps/server/src/queues/kb.queue.ts:22-23. Impact: KB queue paths fail in local dev unless Redis is installed separately. Fix: add a Redis service andREDIS_URLenv template entry. -
Medium: Deploy workflows publish mutable
latestwithout promotion controls.server-build.yml:51-55andai-build.yml:46-50tag every main build as both SHA andlatest; neither workflow hasenvironment,concurrency, smoke tests, image scan, or rollback metadata. Fix: use protected environments, immutable promotion tags, concurrency, and post-build validation.
-
Low: Mixed lockfiles undermine pnpm dependency hygiene.
package.json:24declarespnpm@9.0.0, but tracked npm lockfiles also exist; rootpackage-lock.json:8-14even pinsbetter-authdifferently frompackage.json:28-30. Fix: keep one authoritative lockfile strategy and remove stale package-manager locks. -
Low: Local dependency install can rewrite the lockfile.
scripts/dev-node-deps.sh:24runs plainpnpm install. Fix: default topnpm install --frozen-lockfileand add an explicit update task for lockfile changes.
- Dev startup prints the wrong AI API URL. Root
.env.dev.example:8-9setsAI_API_PORT=8000, butapps/ai/.env.dev.example:2sets5555;scripts/dev-up.sh:53-58sources the AI env in the child process whilescripts/dev-up.sh:83prints the root value. Impact: users are told to open:8000while the service can run on:5555. Fix: make one port source authoritative.
- No required PR workflow for root
build,lint,check-types, JS tests, Python tests, and Docker build validation. - No root aggregate
testorciscript;package.json:17only exposestest:dev-orchestration. - Dependabot only covers npm at
/(.github/dependabot.yml:3-4); it does not cover GitHub Actions, Docker images, orapps/ai/requirements.txt. - No SBOM, image signing/provenance, or container vulnerability scanning in deploy workflows.
- Add
task ci/pnpm ci:localto run the same checks as required PR CI. - Add
task doctorchecks for missing env templates, port conflicts, Redis availability, and Docker Compose health. - Add Docker Compose profiles for optional local services such as Redis and local object-storage/mail substitutes.
git rev-parse HEADmatched the requested commit.bash -n scripts/dev-clear-processes.sh scripts/dev-doctor.sh scripts/dev-env.sh scripts/dev-node-deps.sh scripts/dev-up.shpassed.docker compose -f docker-compose.dev.yml --env-file .env.dev.example configpassed.task --listpassed.node --test tests/dev-orchestration.test.mjsfailed as described.node --test tests/kb-worker-config.test.mjspassed.pnpm audit --audit-level criticalexited0;pnpm audit --audit-level moderateexited1.pnpm dlx turbo@2.8.20 run {check-types,lint,build} --dry=jsonused for task graph inspection only.
- Full install/build/lint/typecheck were not run because
node_modulesis absent andpnpm installwould create repository files. - Docker image builds and AWS/ECR deploy paths were not executed because they require external credentials and push side effects.
- Docker services were not started because that would create containers/volumes.
- Worktree had pre-existing changes: modified
.gitignore, untrackedscripts/codex_module_audit.py, and untrackedtests/test_codex_module_audit.py.
- Status:
passed - Return code:
0 - Duration:
412.6s - Stdout log:
.audit_runs/2026-06-19T062207+0000/apps-web.stdout.jsonl - Stderr log:
.audit_runs/2026-06-19T062207+0000/apps-web.stderr.log
Audited apps/web at commit d0284076a776a80bc39f06d90d56b4c650e366ac. No files were modified. Main risks are broken conversion paths, future-dated content being publicly indexed, missing public assets, and inconsistent compliance/pricing claims.
-
High: Contact form submit path is broken. Proven: contact-us-form-section.tsx:96 posts to
/api/contact, butapps/web/src/apphas no API route. Repro: submit/company/contact; request 404s and likely falls into the generic error path. Fix: addapp/api/contact/route.ts, use a server action, or replace the form with a working external lead-capture flow. -
High: Public CTAs link to nonexistent routes. Proven:
/use-cases/appointment-schedulingrenders/contactand/demolinks at appointment-scheduling-cta-section.tsx:60 and 68;/use-cases/customer-supportdoes the same at customer-support-cta-section.tsx:58. Those routes do not exist. Fix: use/company/contactandDEMO_BOOKING_URL. -
High: Future-dated blog posts are published and treated as latest. Proven:
getAllPosts()returns all markdown without filtering dates at blog.ts:48, and the blog index selects the last sorted post as “Latest Article” at blog/page.tsx:96. Static scan found 36 posts dated after June 19, 2026, up to week-52:4. Fix: filter future dates unless explicitly previewing/scheduling.
-
Missing social and visible image assets.
/og-image.pngis referenced across many pages, e.g. blog/page.tsx:19, but is not inpublic/. Visiblenext/imagesources such as careers-hero-section.tsx:192 and operations-automation-why-section.tsx:102 also point to missing/images/...files. Impact: broken page imagery and broken social previews. -
Compliance and pricing copy contradict each other. Pricing says BAA is Enterprise-only at pricing/page.tsx:201, while the HIPAA page says every healthcare customer gets a BAA at hipaa/page.tsx:53 and 419. Fix: align legal/commercial wording before publishing.
-
Free-trial allowance is inconsistent. Pricing says Free includes 15 minutes/month at pricing/page.tsx:31, but homepage FAQ says up to 100 minutes at faq-2.tsx:89. Impact: trust and support friction.
-
Desktop dropdown navigation is hover-only. Dropdowns open via mouse enter/leave at header-1.tsx:162, with parent links set to
#at header-1.tsx:27. Impact: keyboard users cannot reliably access nested navigation.
-
Nested landmarks and duplicate
main-content. Layout wraps every page in<main id="main-content">at layout.tsx:91, while pages also render<main>, including duplicateid="main-content"on the homepage at page.tsx:145. Fix: keep the landmark/id in one place. -
Manifest icons 404. manifest.ts:15 references
/iconand manifest.ts:20 references/apple-icon, but no matching files/routes exist. -
Global preload is applied to every route. layout.tsx:62 preloads
/dashboard.pngglobally, although it is homepage-specific. Fix: move preload/priority handling to the component/page that needs it.
-
Several visible buttons are inert: “Watch Our Story” at careers-hero-section.tsx:165, “View All Benefits” at careers-benefits-section.tsx:187, and “Apply Now” at careers-job-opportunities-section.tsx:193.
-
FAQ accordion buttons lack
aria-expanded/aria-controls, e.g. faq-2.tsx:237. -
Missing images create blank/broken visual areas on Careers and Operations Automation pages.
-
SearchActionpoints tohttps://quickvoice.co/blog?q=...at page.tsx:35, but the blog page has no search handling.
- Working contact/demo lead submission backend.
- Content publish-state handling for draft/scheduled blog posts.
- Centralized CTA route validation for
/register,/login, demo, and contact URLs. - Accessible keyboard-first dropdown/accordion components.
- Per-page OG image generation or a real shared
/og-image.png. - Blog search/filter UI to match the declared
SearchAction. - Conversion analytics for contact/demo/signup CTAs.
- Scheduled content workflow with preview mode and sitemap exclusion.
git rev-parse HEADconfirmedd0284076a776a80bc39f06d90d56b4c650e366ac.git status --shortshowed unrelated dirty files outsideapps/web; untouched.- Static file/route inspection with
find,rg,nl. - Node frontmatter scan: 90 blog posts, 36 future-dated after June 19, 2026.
- Asset inventory: only
dashboard.png,earth.webp, logos,robots.txt, andllms.txtexist inapps/web/public.
pnpm --filter web lintblocked:eslintnot found; dependencies not installed.pnpm --filter web exec tsc --noEmit --incremental falseblocked:tscnot found.- Did not run
next build,next dev, or rendered browser QA because those would create.next/artifacts, violating the no-create rule. - External services and production env were not verified:
NEXT_PUBLIC_CONSOLE_URL, TidyCal, analytics, and compliance certification claims.
- Status:
passed - Return code:
0 - Duration:
360.3s - Stdout log:
.audit_runs/2026-06-19T062207+0000/apps-console.stdout.jsonl - Stderr log:
.audit_runs/2026-06-19T062207+0000/apps-console.stderr.log
Audited apps/console at commit d0284076a776a80bc39f06d90d56b4c650e366ac. No files under apps/console were modified.
Main risks: onboarding can navigate to an invalid org after create failure, phone-number buying sends the wrong provider value, roles/access-control UI is not actually wired, and several data pages render failed API loads as empty/zero states.
-
Proven: create-organization failure still shows success and navigates to
/orgs/undefined. CreateOrg.tsx:43 handleserrorbut does not return or throw; CreateOrg.tsx:51 still toasts success and CreateOrg.tsx:52 pushesdata?.id. Repro with duplicate/invalid org slug. Fix by returning/throwing on error, requiringdata.id, and not clearing the error infinally. -
Proven: buy-number flow sends upper-case provider values despite lower-case console API types.
TelephonyProvideris"twilio" | "telnyx"in types.ts:6, but the form uses"TWILIO" | "TELNYX"in BuyNumberDrawer.tsx:44 and casts that runtime value at BuyNumberDrawer.tsx:70. Impact: search/buy requests can fail or hit wrong provider handling. Use lower-case form values or transform before API calls. -
Proven: roles page is a UI shell, not functional role management. roles/page.tsx:61 notes wiring is follow-up; roles/page.tsx:63 hardcodes
rolesto[], and delete has no handler at roles/page.tsx:216. Impact: custom access control cannot be viewed or managed. Wire list/create/delete/update to the auth API with real loading/error states.
-
Proven: multiple API failures render as empty or zero data. Examples: dashboard ignores
isErrorand shows0values at dashboard/page.tsx:22, agents defaults to[]at agents/page.tsx:11, calls shows “No calls match” after query failure at CallsTable.tsx:263, and KB does the same at kb/page.tsx:13. Add explicitisErrorstates with retry. -
Proven: enabled webhooks can be saved with blank URLs. Schema allows
""at WebhooksTab.tsx:34, then submit builds enabled webhook objects at WebhooksTab.tsx:78. Add conditional validation: URL required when enabled. -
Proven code risk: MCP setup opens external pages without
noopener. mcp.ts:13 useswindow.open(setupUrl, "_blank"); settingopener = nullafter open at mcp.ts:19 is weaker than opening withnoopener,noreferrer. Use the thirdwindow.openargument and validate setup URLs. -
Proven: agent template picker is ignored.
selectedTemplateis maintained at NewAgentDialog.tsx:80, but submit always sendstemplateId: nullat NewAgentDialog.tsx:89. Send the selected template or remove the picker.
-
Proven: “Forgot password?” links to a missing route. login-form.tsx:119 links
/forgot-password, but no matching app route exists. -
Proven: registration has weak submit/error handling. register-form.tsx:40 has no
try/finally, logs auth errors at register-form.tsx:47, and the submit button is not disabled while loading at register-form.tsx:157. -
Proven: tool parameter/header validation permits empty keys and names. ToolSheet.tsx:41 uses bare
z.string()for key/value and param fields. Add minimum validation or filter blank rows before submit.
- Mobile sidebar hides the sheet close button at sidebar.tsx:189, and nav links in NavMain.tsx:52 do not close the mobile sheet.
- Several dense tables use
overflow-hiddeninstead of horizontal scroll, e.g. CallsTable.tsx:304, AgentsTable.tsx:136, KbTable.tsx:151. - Destructive member removal has no confirmation at organization/page.tsx:383.
- Several icon-only controls lack accessible labels, including ToolCard.tsx:90 and detach buttons in ToolsTab.tsx:100.
- Password reset/forgot-password screens and handlers.
- Real custom role listing/edit/delete and member role changes.
- Agent delete is disabled in both table/detail flows.
- Per-agent limits tab exists but is not included in
AgentTabs; current page only says roadmap. - Billing usage is a TODO at billing/page.tsx:202.
- Campaign outbound UI is absent despite
campaignSchemaat campaign.ts:3.
- Audit log for org settings, API keys, members, roles, billing, and destructive actions.
- Agent test-call/simulation flow; table currently has disabled “Test”.
- Pending invites management, ownership transfer, and role reassignment.
- Mobile card views for calls, agents, KB, and numbers instead of squeezed tables.
- Billing usage forecasts and overage warnings.
git rev-parse HEAD->d0284076a776a80bc39f06d90d56b4c650e366acgit diff -- apps/console --stat-> no output- Static inspection with
rg,find,sed, andnl -ba pnpm --dir apps/console lint-> blocked:eslint: not found,node_modulesmissingpnpm --dir apps/console exec tsc --noEmit -p tsconfig.json-> blocked:tscnot found
- Lint, typecheck, build, and browser/a11y verification were not completed because dependencies are not installed.
- API contract assumptions beyond console-local types were not verified against live services or credentials.
- Existing dirty worktree entries are outside
apps/consoleand were not touched.
- Status:
passed - Return code:
0 - Duration:
317.7s - Stdout log:
.audit_runs/2026-06-19T062207+0000/apps-server.stdout.jsonl - Stderr log:
.audit_runs/2026-06-19T062207+0000/apps-server.stderr.log
Audited apps/server at d0284076a776a80bc39f06d90d56b4c650e366ac read-only. Main risks: API keys bypass RBAC, KB creation can write with caller-supplied tenant context, and webhook/tool “secret” values are stored/returned as plaintext.
-
High: API keys bypass all per-route RBAC. Evidence: valid API keys become
authMethod: "apiKey"in auth.middleware.ts:96, thenrequirePermissionreturns without checking the requested permission in authorize.middleware.ts:69. Repro: use any valid org API key against mutating routes such asPOST /api/v1/numbersorDELETE /api/v1/calls/:id; the route permission is skipped. Impact: leaked/low-scope API keys can mutate org resources and trigger paid telephony/MCP actions. Fix: verify API-key permissions/scopes againstpermissions, or map API keys to a user/member role and call the same permission engine. -
High: KB creation trusts caller-supplied
organizationIdanduserId. Evidence: controller passes raw body in kb.controller.ts:10; schema requires clientuserId/organizationIdin kb.schema.ts:39; repository writes them directly in kb.repository.ts:14. Repro: authenticated org A admin posts/api/v1/kbwithorganizationIdoragentIdfrom another org. Impact: cross-tenant KB rows, queue jobs, andknowledgeSourcesCountcorruption. Fix: injectreq.auth.activeOrganizationId/req.auth.userId, remove those body fields, and verifyagentIdbelongs to the active org in the same transaction. -
High: integration secrets are stored and returned as normal JSON/plaintext. Evidence: webhook fields accept
{ value, type: "Secret" }in agent.schema.ts:50, then are persisted unchanged in agent.repository.ts:69 and returned by config reads in agent.controller.ts:80. Tool headers/body are JSON fields in schema.prisma:536;Secret.valueis also plainStringat schema.prisma:653. Impact: DB compromise or read-capable org members can recover API keys/webhook secrets. Fix: envelope-encrypt secrets, store references not values, redact reads, and resolve secrets only at execution time.
-
Validation output is discarded.
validate()callsschema.parse(req.body)but never assigns parsed data in validate.middleware.ts:10. Zod defaults, transforms, and stripped unknown keys are not applied unless routes parse inline, as outbound does in outbound-call.route.ts:38. Fix by assigningreq.body = schema.parse(req.body). -
Outbound LiveKit flow can leave orphan side effects. A DB row is created, then LiveKit dispatch is created before SIP participant creation in outbound-call.service.ts:86 and outbound-call.service.ts:106; catch only marks failed in outbound-call.service.ts:134. Add cleanup/idempotency.
-
PII and tool data are retained without redaction controls. Call transcripts are stored raw in calllog.repository.ts:46 while
isPiiRedacteddefaults false in schema.prisma:467. MCP arguments/results are preview-logged in mcp.service.ts:552. Add retention/redaction policies. -
Tool counters can drift. Attach always increments
toolsCountin tool.repository.ts:75; detach decrements without proving the relation exists in tool.repository.ts:93. Recount from relations or conditionally update. -
SSRF risk in URL-bearing integrations. Tool
api_urlaccepts any URL in tool.schema.ts:20; webhooks accept any URL in agent.schema.ts:47; MCP custom URL blocking only covers localhost literals in mcp.service.ts:63. Block private/link-local ranges after DNS resolution.
- Rate limiting runs after
express.json()in index.ts:81, so body parsing work happens before throttling. - Error middleware returns raw
err.messagefor 500s in error.middleware.ts:8, risking internal detail leaks. - Telnyx number search logs provider response data in phone.service.ts:63; trunk updates also log debug state in phone.service.ts:210.
- Public Swagger docs expose internal auth schemes and persist auth in browser storage: index.ts:32, swagger.ts:60.
- Swagger tells users to provide KB
userIdandorganizationId, matching the security bug: swagger.ts:270. - Error responses are inconsistent: rate limit returns
{ success, message }, global errors return{ message }.
- No observed server-side enforcement of plan minutes/quotas from plans.ts:1.
- No Stripe metered usage reporting found for call minutes/costs.
- No retention job for transcripts, recordings, MCP logs, or KB data.
- KB delete TODOs leave S3/vector cleanup unimplemented in kb.service.ts:38.
- Number release/delete route is commented out.
- Org-scoped audit log for API-key use, config changes, telephony purchases, MCP execution, and internal calls.
- Central secret manager with rotation, redaction, and execution-time resolution.
- Per-org rate limits and quota dashboards tied to billing plans.
- Readiness checks for DB, Redis, S3, Stripe, Twilio/Telnyx, LiveKit, and Smithery.
git rev-parse HEADconfirmedd0284076a776a80bc39f06d90d56b4c650e366ac.git status --shortchecked before/after; existing.gitignoremodification and untracked audit helper files were not touched.- Static inspection with
rg,find,sed, andnl. pnpm --dir apps/server check-typesattempted.
- Typecheck blocked:
tsc: not found;apps/server/node_modulesis missing. I did not install dependencies because that would write files. - Tests/builds not run for the same dependency reason.
- DB, Redis, Stripe, Twilio, Telnyx, LiveKit, S3, Inngest, and Smithery integration behavior was not exercised due missing credentials/services.
- Inngest endpoint auth/signature behavior remains unverified.
- Status:
passed - Return code:
0 - Duration:
410.4s - Stdout log:
.audit_runs/2026-06-19T062207+0000/apps-ai.stdout.jsonl - Stderr log:
.audit_runs/2026-06-19T062207+0000/apps-ai.stderr.log
Audited apps/ai at d0284076a776a80bc39f06d90d56b4c650e366ac in read-only mode. No apps/ai files were changed. Highest risk areas are internal API auth, KB URL/file ingestion, call finalization, RAG failure behavior, and PII-heavy logging.
-
High: unauthenticated FastAPI config proxy can leak runtime agent config. api.py:30 exposes
GET /agents/{agent_id}/configwithout_verify_internal, while config_handler.py:52 calls the backend with the internal bearer key. Repro: run AI API withSERVER_API_URLandINTERNAL_API_KEY, then request/agents/<id>/configwithout auth. Impact: system prompts, variables, webhooks, and MCP connection metadata can be exposed. Fix: require internal auth on this route and fail startup if the key is absent outside explicit dev mode. -
High: KB ingestion permits SSRF and unbounded server-side downloads. kb_handler.py:39 and kb_handler.py:49 fetch caller-provided
url/presignedUrlwith redirects and no scheme, host, IP, content-type, or size restrictions. Combined with optional auth in api.py:17, this can hit metadata services/internal hosts or ingest huge files into Gemini/Pinecone. Fix: fail-closed auth, block private/link-local IPs, allowlist schemes/hosts where possible, stream with byte limits, and cap chunks/embeddings per job.
-
Call logs can be dropped during shutdown. Finalization only runs from
participant_disconnectedand is launched viaasyncio.create_taskin main.py:281. There is noctx.add_shutdown_callback, so SIGTERM, worker recycle, network disconnects, or early job shutdown can skip transcripts/log posting. Fix: make finalization idempotent, register it with LiveKit job shutdown, await it, and retry via a durable queue. -
Transcript timestamps are wrong for LiveKit messages. livekit_handler.py:40 passes
msg.created_at, which LiveKit documents as a float timestamp, but calllog_handler.py:103 only preserves strings ordatetime; floats become “now”. Reproduced locally: a1704067200.0transcript timestamp became the current audit time. Fix: handle numeric epoch seconds. -
Re-indexing shorter KB documents leaves stale Pinecone chunks. kb_handler.py:162 uses stable IDs
kbId#iand kb_handler.py:176 only upserts. Old higher-index chunks remain after a shorter replacement, so RAG can cite deleted content. Fix: delete bykbIdbefore re-upsert or version documents and filter current versions. -
RAG provider failures silently degrade into no-context answers. rag_handler.py:60 catches all exceptions and returns
""; main.py:147 then proceeds without a user-visible failure. Impact: agents can hallucinate when KB is unavailable. Fix: distinguish “no matches” from “retrieval failed”, emit metrics, and inject/return a clear KB-unavailable signal. -
PII and sensitive runtime data are logged at INFO. Full config payloads, call context, message objects, and transcripts are logged at config_handler.py:59, main.py:222, and livekit_handler.py:30. logger.py:24 also enables diagnostic trace detail. Fix: redact phone numbers, transcripts, prompts, headers, webhook URLs, and disable
diagnose=Truein production. -
MCP execution lacks AI-side guardrails. The LLM can call main.py:187 with arbitrary arguments; server-side org/agent attachment checks reduce cross-tenant risk, but prompt injection can still trigger connected tools and return unbounded tool output into the conversation. Fix: enforce local allowlists from
config["mcp_connections"], classify side-effect tools, require confirmation where needed, and truncate/redact outputs. -
Runtime config fetch fails open to a generic agent. If
SERVER_API_URLorINTERNAL_API_KEYis missing, config_handler.py:50 falls back to defaults. Production calls can run with the wrong prompt and later fail call logging due missing org/user fields. Fix: fail closed in worker/API runtime except explicit local dev.
- livekit_handler.py:53 does not close
LiveKitAPIin afinallypath if egress startup fails after client creation. - api.py:56 says it returns
207 Multi-Status, but FastAPI returns the default200. - requirements.txt has mostly unpinned dependencies and no lock/constraints or dev requirements, making Python builds hard to reproduce.
- KB failures and “no KB match” collapse into similar behavior, so users get confident answers or “no matching context” without knowing the KB backend failed.
- The bot can run with the default generic prompt on config misconfiguration, instead of telling callers the agent is unavailable.
- KB processing returns
success: trueeven when individual documents fail, which can create confusing status unless every caller inspects per-document results.
- Fail-closed internal auth middleware for all non-health FastAPI routes.
- Privacy controls in the AI runtime for
store_call_audio,zero_pii_retention, and retention settings; main.py:277 always starts recording. - Durable call-log delivery with retry/backoff and dead-letter visibility.
- Metrics/tracing for provider latency, RAG hit/miss/error, KB document size/chunk count, recording failures, and MCP execution.
- Tests for FastAPI auth, SSRF validation, shutdown finalization, stale vector cleanup, provider failures, and PII redaction.
- Add KB citations with document name, page/sheet, chunk ID, and score.
- Add hybrid keyword/vector search and optional reranking for better RAG precision.
- Add per-agent KB ingestion budgets and cost controls.
- Add an admin reindex/delete workflow that removes stale vectors safely.
- Add MCP tool governance: read-only vs write tools, confirmation prompts, and audit summaries.
- Verified commit with
git rev-parse HEAD. - Read
apps/aifiles with line-numbered inspection and scoped ripgrep searches. - Ran dependency-free syntax check:
syntax ok for 17 python files. - Ran
PYTHONDONTWRITEBYTECODE=1 python3 -m unittest discover -s tests -p 'test_*.py' -v: 3 call-log tests passed; 5 test modules blocked by missing dependencies. - Reproduced numeric transcript timestamp bug with
build_call_log_payload. - Confirmed
apps/airemained clean withgit status --short -- apps/aiand no cache files were created. - Referenced official LiveKit docs for
ChatContext.created_atandJobContext.add_shutdown_callback: https://docs.livekit.io/reference/python/livekit/agents/
- Full test suite blocked:
pytest,loguru,livekit, anddotenvare not installed. - LiveKit, Pinecone, Google embedding, and backend API integrations were not exercised because credentials/services are unavailable.
- No actual SSRF, provider, recording, or MCP network calls were attempted.
- I did not generate security-scan artifacts because the audit rules prohibit creating files.
- Status:
passed - Return code:
0 - Duration:
236.0s - Stdout log:
.audit_runs/2026-06-19T062207+0000/packages-config.stdout.jsonl - Stderr log:
.audit_runs/2026-06-19T062207+0000/packages-config.stderr.log
Audited only packages/eslint-config and packages/typescript-config at commit d0284076a776a80bc39f06d90d56b4c650e366ac. No repository files were changed. The main risks are weak lint gates, unused shared ESLint config, and TypeScript defaults that leak browser globals into the server.
- High: Shared ESLint config downgrades all lint failures to warnings.
Proven in base.js and base.js:
eslint-plugin-only-warnis included in the base preset, andturbo/no-undeclared-env-varsis explicitly onlywarnat base.js. Any consumer of@repo/eslint-config/base,next-js, orreact-internalcan pass CI with lint violations unless every lint command also uses--max-warnings=0. Fix: removeonly-warnfrom shared CI presets, keep it only in a local/dev preset if needed, and make cache-affecting rules such asturbo/no-undeclared-env-varserrors in CI.
-
Medium: Shared ESLint package is not consumed by the workspace apps.
apps/webandapps/consoleimporteslint-config-nextdirectly in eslint.config.mjs and eslint.config.mjs.rgfound no dependency or import of@repo/eslint-configoutside its own package. Impact: changes topackages/eslint-configdo not protect current app linting. Fix: either adopt the shared package in app configs or remove/rename it until it is part of the quality gate. -
Medium: Server inherits DOM typings from the shared TypeScript base. base.json includes
DOMandDOM.Iterable; apps/server/tsconfig.json extends that base. Impact: server code can typecheck accidental browser APIs such aswindow/document, hiding runtime errors. Fix: makebase.jsonruntime-neutral and add separatenode.json/browser.json/nextjs.jsonpresets. -
Medium: Shared Next ESLint preset is weaker than the app presets. next.js wires only
@next/nextrules plus React hooks; it does not useeslint-config-next/core-web-vitalsoreslint-config-next/typescript, unlike the apps. Lockfile data also shows the shared package resolves@next/eslint-plugin-next@16.2.0while apps useeslint-config-next@16.2.1. Impact: adopting the shared preset may lose import, accessibility, and exact Next rule coverage. Fix: base the shared Next preset oneslint-config-nextor fully mirror its plugin set and versions.
-
Low: TypeScript config package has no explicit export map. package.json exposes no
exportsfor./base.json,./nextjs.json, or./react-library.json. Fix: add explicit JSON subpath exports to define the supported public surface. -
Low: Package metadata is inconsistent.
@repo/typescript-configisprivate: truebut also haspublishConfig.access: publicin package.json. The ESLint README still says@turbo/eslint-configin README.md. Fix: remove stale publish metadata or document publishing intent, and update README naming/usage examples.
No direct UI surface in this module. Indirect UI risk: the shared Next ESLint preset does not clearly preserve the current apps’ accessibility lint coverage.
- Package-level smoke tests that import each ESLint export and validate each TS config.
- CI task that runs lint/config validation when
packages/eslint-config/**changes. - Runtime-specific TS presets for Node server, Next app, and React library.
--max-warnings=0or equivalent strict lint gate.
- Add stricter optional TS presets covering
noUnusedLocals,noUnusedParameters,noImplicitReturns,noFallthroughCasesInSwitch, andexactOptionalPropertyTypes. - Add README examples for each exported config and expected consumer package dependencies.
- Verified commit with
git rev-parse HEAD. - Inspected scoped files, app consumers, root workspace config, lockfile, and CI workflows.
- Searched usages with
rgfor@repo/eslint-configand@repo/typescript-config. - Ran
node --checkon all ESLint config JS files: passed. - Parsed all scoped JSON config/package files with
JSON.parse: passed.
pnpm --filter server check-types,pnpm --filter web lint, andpnpm --filter console lintwere blocked becausenode_modulesis missing (tsc/eslintnot found). I did not runpnpm installbecause it would write repository files.- ESLint config runtime import checks were also blocked by missing installed dependencies.
- Each module prompt explicitly instructed Codex not to edit repository files.
- Generated logs are stored under
.audit_runs/and ignored by git. - A
changed_filesstatus means a module session modified tracked files and requires manual inspection before trusting the report.