First slice of the M7.2 tenant-isolation work. Adds a `DatabasePool`
that hands out per-tenant `Database` handles physically scoped to
`<prefix>_<tenant_id>` Mongo databases. Isolation is at the driver,
not at "we hope we filter" — a handle for tenant A literally cannot
see tenant B's documents because it's connected to a different db.
What's in this PR
- DatabasePool::connect — pings the cluster, prepares per-tenant lazy
handles.
- DatabasePool::for_tenant(&TenantContext) — returns a Database scoped
to that tenant. ensure_indexes runs once per tenant per process via
a DashMap-backed marker; failure rolls the marker back so the next
request retries.
- tenant_db_name — `<prefix>_<sanitized_tenant_id>` if it fits in
Mongo's 63-byte db-name cap, else `<prefix>_<sha256-16hex>` fallback.
- Sanitizer rewrites the Mongo-disallowed chars (`/ \ . " $ <space>
NUL`) so any future tenant_id shape works.
- ComplianceAgent gains a `db_pool: DatabasePool` field next to the
existing `db: Database`. Handlers / pipelines / webhooks still use
`db` — they migrate to `db_pool.for_tenant(&ctx)` in M7.2-B/C and
`db` goes away in M7.2-D.
Test plan
- cargo fmt --all clean
- cargo clippy --workspace --exclude compliance-dashboard -- -D warnings
clean
- cargo test -p compliance-core --lib — 7 pass
- cargo test -p compliance-agent --lib — 228 pass
- cargo test -p compliance-agent --test tenant_isolation — 4 pass
against live mongo on 27017:
* pool_isolates_tenants_at_driver_level — writes for acme + globex,
reads through each tenant's handle; each sees exactly its own
data with no filter doc anywhere.
* for_tenant_is_idempotent_index_creation — second + third call
for the same tenant do not error.
* tenant_db_name_sanitizes_unsafe_characters
* tenant_db_name_falls_back_to_hash_when_too_long — 100-byte
tenant_id collapses to a stable 8-byte hex suffix.
Why per-tenant DB vs `tenant_id` field + filter
- Driver-level isolation; impossible to forget the filter on one of
the 184 query call-sites in compliance-agent.
- Handlers don't change shape at migration — `agent.db.findings()`
becomes `db.findings()` after pulling `db` from
`agent.db_pool.for_tenant(&ctx)`.
- GDPR delete = `db.dropDatabase()`.
- On-prem deploy = the same code path, with one tenant.
- Trade-off accepted: index storage duplicated per tenant; Mongo's
~thousand-db ceiling is way above the 10s-100s tenants we're
targeting.
Caveats
- Existing `agent.db` continues to point at the single legacy db.
Handlers / pipelines that use it are unscoped until M7.2-B/C
migrate them.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
## Summary
- **Scan produces no results in Orca** — semgrep (`--config=auto`, unbounded memory) and syft (remote license network calls) were getting OOM-killed or hanging in resource-constrained Orca containers. Scan would "complete" with 0 findings/SBOMs silently because each scanner failure is caught and logged as a warning.
- **Dashboard Script error spam** — `document::Script` in Dioxus 0.7 needs a single text node child for inline scripts; `dangerous_inner_html` was invalid and spammed the error log on every unauthenticated page load.
## Changes
| File | Change |
|------|--------|
| `semgrep.rs` | Add `--max-memory 500 --jobs 1`; 10-minute timeout |
| `syft.rs` | Remove remote license lookup env vars; 5-minute timeout |
| `gitleaks.rs` | 5-minute timeout |
| `app_shell.rs` | Fix `dangerous_inner_html` → text child in `document::Script` |
## Test plan
- [ ] Trigger a scan on a repo in Orca — findings and SBOM entries should now appear
- [ ] Agent logs should show timeout/error warnings rather than silent empty results when tools are killed
- [ ] Navigate to dashboard unauthenticated — Script error gone from logs
- [ ] Verify scans work end-to-end with `docker compose up`
---------
Co-authored-by: Sharang Parnerkar <30073382+mighty840@users.noreply.github.com>
Reviewed-on: #78
## Summary
- Add HTTP response status checking to all Gitea tracker methods that were silently swallowing errors
- Add fallback in create_pr_review: if inline comments fail, retry as plain PR comment
## Test plan
- [ ] Deploy and trigger a PR review, check logs for actual error details
- [ ] Verify fallback posts summary comment when inline comments fail
Co-authored-by: Sharang Parnerkar <parnerkarsharang@gmail.com>
Co-authored-by: Sharang Parnerkar <30073382+mighty840@users.noreply.github.com>
Reviewed-on: #47
- Remove port 143 from mailserver (only expose 993/IMAPS)
- Enable SSL_TYPE=manual with Let's Encrypt certs
- Set DOVECOT_DISABLE_PLAINTEXT_AUTH=yes
- Add pentest_imap_tls config field (defaults to true)
Fixes CERT-Bund report: IMAP PLAIN/LOGIN without TLS on 46.225.100.82:143
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add repo_id, finding_id, and filter fields to tracing::instrument attributes
for better trace correlation in SigNoz. Replace all silently swallowed errors
(Err(_) => Vec::new()) with tracing::warn! logging across mod.rs, dast.rs,
graph.rs handlers. Add stage-level spans with .instrument() to pipeline
orchestrator for visibility into scan phases.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Dashboard: OAuth2/OIDC login flow with PKCE, session-based auth middleware
protecting all server function endpoints, check-auth server function for
frontend auth state, login page gate in AppShell, user info in sidebar.
Agent API: JWT validation middleware using Keycloak JWKS endpoint,
conditionally enabled when KEYCLOAK_URL and KEYCLOAK_REALM are set.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Sharang Parnerkar <parnerkarsharang@gmail.com>
Reviewed-on: #2
Adds code inspector, file tree components, graph visualization JS,
graph API handlers, sidebar navigation updates, and misc improvements.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add DAST scanning and code knowledge graph features across the stack:
- compliance-dast and compliance-graph workspace crates
- Agent API handlers and routes for DAST targets/scans and graph builds
- Core models and traits for DAST and graph domains
- Dashboard pages for DAST targets/findings/overview and graph explorer/impact
- Toast notification system with auto-dismiss for async action feedback
- Button click animations and disabled states for better UX
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Run cargo fmt on all crates
- Fix regex patterns using unsupported lookahead in patterns.rs
- Replace unwrap() calls with compile_regex() helper
- Fix never type fallback in GitHub tracker
- Fix redundant field name in findings page
- Allow enum_variant_names for Dioxus Route enum
- Fix &mut Vec -> &mut [T] clippy lint in sbom.rs
- Mark unused-but-intended APIs with #[allow(dead_code)]
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Feature-gate mongodb in compliance-core (optional, default on) so wasm
builds don't pull in tokio/mio via mongodb
- Use bson v2 directly for ObjectId types (wasm-compatible)
- Restructure dashboard infrastructure/mod.rs: server function modules
always compiled (for RPC stubs), server-only modules cfg-gated
- Remove reqwest from dashboard web feature (not needed, data flows
through server functions)
- Add .gitignore
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>