6.1.1
EDDI v6.1.1 is a hardening release focused on security, test coverage, and developer experience. It closes critical IDOR vulnerabilities across all user-facing endpoints, achieves OpenSSF Scorecard Gold with >90% instruction / >80% branch coverage and 9,000+ tests, delivers a completely overhauled Swagger UI with branded dark mode, and fixes several concurrency bugs found during code review. The Manager UI ships parser editing, comprehensive SSE reliability fixes, and Keycloak auth improvements.
🏅 OpenSSF Scorecard — Gold Badge Achieved
EDDI has achieved OpenSSF Scorecard Gold level, up from Silver in v6.1.0.
- 9,000+ tests (up from 5,500+ in v6.1.0) — added ~3,500 new tests across 43 test files in 10 coverage rounds.
- JaCoCo CI gates raised to 90% instruction / 80% branch (from 70%/60% in v6.1.0).
- CodeQL SAST now runs on all push-to-main events (previously skipped Dependabot merges, causing Scorecard warnings).
- All CI action dependencies pinned to SHA hashes.
- Added
SECURITY.mdwith vulnerability disclosure policy.
🛡️ Security — IDOR Remediation & Ownership Validation
A comprehensive security audit uncovered and fixed Insecure Direct Object Reference (IDOR) vulnerabilities across all user-facing REST and MCP endpoints.
New Component: OwnershipValidator
Centralized @ApplicationScoped utility for ownership checks. Three methods: validateUserAccess(), validateAndResolveUserId(), requireOwnerOrAdmin(). All checks are no-ops when authorization.enabled=false (dev mode). eddi-admin role bypasses all checks. Legacy data without ownership is allowed through gracefully. WARN-level audit logging on all failures.
Conversations (HIGH → FIXED)
Any authenticated user could previously read/modify ANY conversation by guessing the conversationId. All conversation-scoped endpoints now validate caller ownership. startConversation validates that the provided userId matches the caller's identity (admins can set any userId).
User Memory (HIGH → FIXED)
Any authenticated user could previously read/delete another user's persistent memories. All endpoints now validate that the {userId} path parameter matches the authenticated caller.
Group Conversations (HIGH → FIXED)
Any authenticated user could previously read/delete any group conversation. listGroupConversations now filters to the caller's conversations only.
MCP Memory Tools (NEW → FIXED)
MCP memory read tools now validate userId via OwnershipValidator before executing. Input validation (non-null/non-blank) runs before ownership checks for correct error messages.
Additional Security Fixes
- GDPR annotation hardening —
@RolesAllowed("eddi-admin")moved to interface level. - A2A endpoint clarity —
@PermitAlladded to all 5 GET discovery endpoints (intentional public access per A2A spec). - CodeQL remediation — 12 log injection findings fixed via
LogSanitizer.sanitize(). Fail-closed ownership check onResourceStoreException. - Secrets vault — Tenant reset endpoint added, double-vaulting bug fixed,
tenantIdsanitized in logs.
36 new security tests covering all ownership validation paths.
🐞 Bug Fixes
Concurrency & Null Safety (from Code Review)
- PropertySetterTask NPE —
CATCH_ANY_INPUT_AS_PROPERTYhandler now guards against nullinput:initialdata, preventing pipeline crashes on empty/whitespace-only messages. - Config version race condition — Introduced optimistic locking via
storeIfCurrentVersion()onIResourceStorage. MongoDB uses version-conditionedupdateOne; PostgreSQL usesUPDATE WHERE version = ?. Prevents silent last-write-wins on concurrent edits. - ComponentCache HashMap race — Replaced
HashMapwithConcurrentHashMapin the@ApplicationScopedsingleton. Fixes potential map corruption under concurrent reads (every conversation turn) and writes (lazy agent deployment). - Zombie-write snapshot clobber — After agent timeout cancellation,
Thread.currentThread().isInterrupted()is now checked beforeonComplete(). Interrupted threads route toonFailure()instead, preventing stale LLM results from overwriting newer conversation state.
Swagger UI CSP
- Blank Swagger UI page — Fixed CSP blocking inline scripts. Two independent bugs fixed across two PRs:
- Initial fix: Per-path
quarkus.http.filterentries with order-based precedence. - Follow-up: Both filters were firing and adding separate
Content-Security-Policyheaders. Browser enforces the intersection (most restrictive), so Swagger's inline scripts were still blocked. Fixed by adding a negative lookahead regex to exclude/q/swagger-uifrom the default CSP filter.
- Initial fix: Per-path
Other Fixes
- White page at root —
index.htmlreverted to a simple<meta http-equiv="refresh">redirect to/manage(was referencing deleted asset hashes after a Manager rebuild). - Keycloak logout — Fixed incorrect logout redirect; now correctly redirects to
/manage. Addedpost.logout.redirect.uristo Keycloak client config. PreservedidTokenforid_token_hint. - MCP stale conversation cleanup —
getOrCreateManagedConversation()was catchingjakarta.ws.rs.NotFoundExceptionbut the code path throwsConversationNotFoundException. Changed catch clause to the correct exception type. - Tenant quota 404 on fresh instances — Added default tenant quota bootstrapping to both
MongoTenantQuotaStoreandPostgresTenantQuotaStore. Atomic bootstrap viasetOnInsert(Mongo) /DO NOTHING(Postgres). - Gitleaks false positives — Resolved false positives in
rotateKektests; added.gitleaksignoreentries with per-line comments.
🔧 Swagger UI Overhaul
A complete visual and organizational overhaul of the Swagger UI developer experience.
Tag Taxonomy (40 tags, 9 categories)
All @Tag annotations reorganized from flat names to a category-based hierarchy:
- Agents — Setup, Agents, Administration, Agent Groups
- Configuration — Workflows, LLM, Behavior Rules, Dictionary, Output, API Calls, MCP Calls, Properties, Prompt Snippets, Global Variables
- Conversations — Conversations, Group Conversations, Conversation Store, Attachments
- Integrations — A2A Protocol, Capability Registry, Channel Integrations, Slack Webhook
- Knowledge & Memory — RAG Knowledge Bases, RAG Ingestion, User Memory
- Security — Authentication, Secrets Vault, Audit Trail, GDPR / Privacy, Tenant Quotas
- Administration — Backup, Schedules, Coordinator Admin, Orphan Admin, Log Admin, Descriptors
- Tools — Tool History, Template Preview, Standalone NLP
- UI — Chat UI
All 49 REST interface @Tag annotations now include description attributes. 4 previously untagged endpoints received new tags. New OpenApiTagSortFilter OAS filter sorts tags alphabetically at build time.
Branded Dark Mode
- Light mode: white backgrounds, dark text, amber-600 accents
- Dark mode (lamp toggle): EDDI Manager palette — zinc-950 bg, zinc-900 surfaces, amber-500 accents
- HTTP verb tinted operation blocks (blue GET, green POST, amber PUT, red DELETE, purple PATCH)
- EDDI logo branding in topbar
🧪 Testing
Test count grew from ~5,500 to 9,000+ across this release — a 64% increase.
- ~2,800 unit tests added in the initial coverage push across 43 files.
- 10 coverage expansion rounds targeting specific modules:
AgentOrchestrator,LlmTask,StructuralMatcher,McpToolProvider,McpAdminTools,ApiCallExecutor,Expression,HistorizedResourceStore,RestImportService,A2A,GroupConversation. - 36 security tests for
OwnershipValidator,RestAgentEngine,RestUserMemoryStore,RestGroupConversation. - 17 branch coverage tests for
PropertySetterTask. - Secrets vault tests —
resetTenant,handleDekDecryptionFailure,vaultApiKey. - JaCoCo thresholds raised: 70%/60% → 90%/80% (instruction/branch).
🐳 CI/CD & Infrastructure
- Quay.io release push — CI now pushes to Red Hat scan registry on release tags for container certification.
- CodeQL on all pushes — SAST job now runs on all push-to-main events (fixes OpenSSF Scorecard gap).
- Docker base image bump — Red Hat UBI9 OpenJDK 25 runtime updated to latest digest.
- Dependabot — ClusterFuzzLite base builder bumped (3 updates),
github/codeql-actionbumped to 4.36.2, UBI9 runtime bumped. - GCP provisioning script — New script for automated Google Cloud Platform system provisioning.
📦 Dependency Upgrades
| Dependency | v6.1.0 | v6.1.1 |
|---|---|---|
| Quarkus | 3.35.4 | 3.36.3 |
| LangChain4j | 1.15.1 | 1.16.3 ¹ |
| LangChain4j Beta | 1.15.1-beta25 | 1.16.3-beta26 |
| LangChain4j Community | 1.15.0-beta25 | 1.16.0-beta26 |
| Quarkus MCP Server HTTP | 1.12.1 | 1.13.0 |
| Swagger Parser | 2.1.42 | 2.1.44 |
| Testcontainers | 1.21.0 | 1.21.4 |
| WireMock | 3.12.1 | 3.13.2 |
| Jazzer | 0.28.0 | 0.30.0 |
| JaCoCo | 0.8.13 | 0.8.14 |
¹ LangChain4j 1.16.3 includes fix for CVE-2026-55405.
🖥️ EDDI Manager (Admin Dashboard)
The Manager UI (version 6.1.0 assets, bundled with EDDI 6.1.1) received significant updates focused on reliability, new editing capabilities, and test coverage.
New Features
- Parser Editor — Full parser configuration editor for
ai.labs.parserconfigs with dual-mode support: inline editing within the workflow pipeline (via dialog) and standalone resource browsing at/manage/resources/parser/:id. Collapsible sections for Configuration, Dictionaries (6 built-in types + regular dict CRUD), Corrections (3 types with Levenshtein distance), and Normalizers (4 types). 49 new tests at 98.82% line coverage. - Quotas Dashboard Improvements — Handles fresh-instance 404s with defensive API fallbacks, loading skeleton, enforcement-off banner, quota field icons, and dimmed fields when disabled.
SSE Streaming Reliability
- Cross-chunk parsing bug — Events split across TCP frames were silently dropped. Fixed in the
fetch-based SSE parser. - Reconnect timer leaks — Rapid page transitions caused duplicate connections. Timer cleanup now runs on component unmount.
- SSE auth injection — Replaced native
EventSource(which cannot send Authorization headers) withfetch-based SSE streaming across all 6 SSE callers. - Debugger error handling —
prompt-viewer,pipeline-trace, andmemory-inspectornow display error indicators instead of silently showing empty state.
Keycloak Auth Fixes
- Fixed logout redirecting to bare origin instead of
/manage. - Preserved
idTokenfor Keycloakid_token_hinton logout. - Fixed auth implementation for token handling edge cases.
URI Parser Robustness
- All URI parsers made robust against plain path
Locationheaders (no scheme/host). - Handles corrupted backend group descriptor URIs with version embedded in path segment.
- Guards against
undefinedid andNaNversion in URI parsers.
Code Quality & Type Alignment
- Fixed
CostDashboardandRestToolHistorytypes to match backend response shapes. - Fixed
ViewStatetype to match backend enum (UNSEEN|SEEN). - Added missing
EXECUTION_INTERRUPTEDtoConversationState. parseFloatfix (wasparseInt), error toast in channel creation, constant deduplication.
Testing
- 860 tests passing across 81 test files (up from ~700).
- 8 E2E Playwright specs (180 tests) added.
- Function coverage ≥70% across all components.
- CI coverage thresholds enforced: 85% lines, 75% branches.
- 918 TypeScript strict-mode errors resolved in test files.
📊 Release Stats
| Metric | Value |
|---|---|
| Commits (6.1.0 → 6.1.1) | 86 |
| Files changed | 325 |
| Insertions | +79,096 |
| Deletions | −9,581 |
| Backend tests | 9,000+ |
| Manager tests | 860 |
| Contributors | @ginccc, @rolandpickl |