Skip to content

6.1.1

Choose a tag to compare

@ginccc ginccc released this 23 Jun 16:54
2e58702

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.md with 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@PermitAll added 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 on ResourceStoreException.
  • Secrets vault — Tenant reset endpoint added, double-vaulting bug fixed, tenantId sanitized in logs.

36 new security tests covering all ownership validation paths.


🐞 Bug Fixes

Concurrency & Null Safety (from Code Review)

  • PropertySetterTask NPECATCH_ANY_INPUT_AS_PROPERTY handler now guards against null input:initial data, preventing pipeline crashes on empty/whitespace-only messages.
  • Config version race condition — Introduced optimistic locking via storeIfCurrentVersion() on IResourceStorage. MongoDB uses version-conditioned updateOne; PostgreSQL uses UPDATE WHERE version = ?. Prevents silent last-write-wins on concurrent edits.
  • ComponentCache HashMap race — Replaced HashMap with ConcurrentHashMap in the @ApplicationScoped singleton. 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 before onComplete(). Interrupted threads route to onFailure() 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:
    1. Initial fix: Per-path quarkus.http.filter entries with order-based precedence.
    2. Follow-up: Both filters were firing and adding separate Content-Security-Policy headers. 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-ui from the default CSP filter.

Other Fixes

  • White page at rootindex.html reverted 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. Added post.logout.redirect.uris to Keycloak client config. Preserved idToken for id_token_hint.
  • MCP stale conversation cleanupgetOrCreateManagedConversation() was catching jakarta.ws.rs.NotFoundException but the code path throws ConversationNotFoundException. Changed catch clause to the correct exception type.
  • Tenant quota 404 on fresh instances — Added default tenant quota bootstrapping to both MongoTenantQuotaStore and PostgresTenantQuotaStore. Atomic bootstrap via setOnInsert (Mongo) / DO NOTHING (Postgres).
  • Gitleaks false positives — Resolved false positives in rotateKek tests; added .gitleaksignore entries 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 testsresetTenant, 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-action bumped 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.parser configs 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) with fetch-based SSE streaming across all 6 SSE callers.
  • Debugger error handlingprompt-viewer, pipeline-trace, and memory-inspector now display error indicators instead of silently showing empty state.

Keycloak Auth Fixes

  • Fixed logout redirecting to bare origin instead of /manage.
  • Preserved idToken for Keycloak id_token_hint on logout.
  • Fixed auth implementation for token handling edge cases.

URI Parser Robustness

  • All URI parsers made robust against plain path Location headers (no scheme/host).
  • Handles corrupted backend group descriptor URIs with version embedded in path segment.
  • Guards against undefined id and NaN version in URI parsers.

Code Quality & Type Alignment

  • Fixed CostDashboard and RestToolHistory types to match backend response shapes.
  • Fixed ViewState type to match backend enum (UNSEEN|SEEN).
  • Added missing EXECUTION_INTERRUPTED to ConversationState.
  • parseFloat fix (was parseInt), 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