Skip to content

Fess 15.8.0

Latest

Choose a tag to compare

@marevol marevol released this 20 Aug 11:33
· 1 commit to master since this release

We're pleased to announce the release of Fess 15.8.0.

This release adds a content chunking and embedding pipeline with a semantic branch for regular search and RAG chat, and delivers a large single sign-on hardening pass covering SAML, Microsoft Entra ID, SPNEGO, OpenID Connect and LDAP — including several permission-resolution fixes that affect which documents a user can see. The search engine baseline moves to OpenSearch 3.8, and Fess plugins are now distributed from maven.codelibs.org.

Important — api.v2.* configuration keys renamed to api.* (#3280). The API version belongs in the endpoint path, not in a settings key. An override still written under an old key is no longer read and the documented default applies instead. The /api/v2 endpoint paths themselves are unchanged.

api.v2.param.max.length                    -> api.param.max.length
api.v2.param.max.array.size                -> api.param.max.array.size
api.v2.click.max.rt                        -> api.click.max.timestamp
api.v2.chat.stream.keepalive.interval.ms   -> api.chat.stream.keepalive.interval.ms
api.v2.chat.rate.limit.per.user.per.minute -> api.chat.rate.limit.per.user.per.minute

Important — plugin distribution moved to maven.codelibs.org. Fess plugins are now released to the CodeLibs repository instead of Maven Central, and the admin plugin installer looks there first. Maven Central is still consulted for plugins released before the migration (#3205, #3210).

Highlights

  • Content Chunking & Semantic Chunk Search
    Crawled document content can now be split into chunks, optionally embedded, and used both for RAG chat context selection and for a semantic branch of regular search. The pipeline ships with a Chunker SPI, an EmbeddingClient SPI that external providers implement as fess-llm-* plugins, a built-in OpenSearch ML Commons provider that adds no new dependencies, and a ChunkVectorJob that runs indexing in a child process. A chunk-only mode lets you chunk documents first and embed them later in place. Everything is disabled by default (content_chunker.enabled=false), so an installation that does not opt in is unaffected (#3184).

  • Boundary-Aware Chunking
    Chunks are cut at sensible text boundaries instead of a fixed character count. Each cut moves to the nearest candidate of the strongest tier available — a sentence end beats a clause separator, which beats a writing-system change — so words and sentences are no longer split in half, which improves both BM25 matching and embedding quality. No character is dropped; only the cut point moves. Non-Latin sentence marks are recognised and orthographic clusters are protected (#3211, #3232, #3233, #3234).

  • Single Sign-On Hardening
    A comprehensive review and hardening pass across every SSO integration: SAML request/response binding and replay rejection, Entra ID token refresh and Microsoft Graph resilience, SPNEGO realm enforcement, OpenID Connect claim handling, and LDAP group resolution. Credentials, tokens and private keys are kept out of logs and diagnostic screens, and refused handshakes are reported as messages rather than stack traces. See the sections below for details.

  • OpenSearch 3.8 Support
    Fess is now built against OpenSearch 3.8.0, with the bundled analysis, configsync, minhash and k-NN plugins updated to match (#3207).

Improvements

Single Sign-On — SAML

  • Bind SAML responses to the AuthnRequest that started the login and reject replayed assertions (#3214, #3256)
  • Refuse a LogoutRequest that names another user or names nobody, and stop a LogoutResponse from ending a session it never belonged to (#3262, #3300, #3324)
  • Derive SP URLs per request, ignore blank overrides, and serve SP metadata before the IdP is configured (#3217, #3240, #3246)
  • Let LastaFlute own the single-logout redirect (#3219)
  • Report insecure SAML settings, warn when assertion decryption would accept any key transport algorithm, and refuse to publish SP metadata that could not be signed (#3224, #3306, #3307)
  • Refuse a non-positive AuthnRequest TTL or cap instead of failing every login, and tell an expired session apart from a blocked cookie (#3260, #3270, #3271)
  • Explain why a SAML response was refused, and tell administrators how to accept a repeated attribute name (#3303, #3283)
  • Mask the SAML SP private key on the System Info screen and in bug reports (#3305)
  • Publish the lazily computed SAML and OIDC permission caches safely (#3253)

Single Sign-On — Microsoft Entra ID

  • Share one MSAL4J application so silent token refresh actually works, and stop the refresh path calling Microsoft Graph on every request (#3227, #3243)
  • Resolve group memberships in the background and tell the user while it is in progress (#3273)
  • Bound Microsoft Graph calls, record backoff from the group lookup, and stop a transient Graph failure refusing every login (#3221, #3258, #3254)
  • Do not cache a failed parent-group lookup, key the parent-group cache by the permission fields it used, and stop an async lookup being lost by a concurrent reader (#3223, #3297, #3238)
  • Use the query response mode so the callback keeps its session, and request the OIDC scopes at the authorization endpoint (#3215, #3226)
  • Bound and synchronize the state map held in the session, and refuse a state TTL that expires every login (#3222, #3295)
  • Report login failures instead of swallowing them at DEBUG level, and mask credentials in debug logs (#3218, #3213)
  • Expose the response mode in Admin and localize the SSO settings screen (#3252)
  • Ignore a permission field that is not a string (#3296)

Single Sign-On — Windows / SPNEGO

  • Harden the Windows SSO defaults and fix login failure handling (#3181, #3245)
  • Expose the allowed realms in Admin, reject the NTLM/Basic configuration conflict, and enforce the realm allow list on the Basic fallback (#3220, #3244, #3250, #3251)
  • Report a refused handshake or a malformed Authorization header by message instead of a stack trace (#3263, #3269, #3315)
  • Correct SPNEGO logging levels, configuration fallback and dead settings, and allow the pre-authentication password to be cleared (#3216, #3241, #3242)

Single Sign-On — OpenID Connect

  • Report a callback failure to the user instead of raising a system error (#3289)
  • Accept a single-valued groups claim (#3290)
  • Keep tokens and raw signature bytes out of the debug log (#3291)

LDAP & Permission Resolution

  • Name a permission from the directory entry, the group's sAMAccountName, or the asserted user name — not from a slice of a DN. A name containing a backslash previously collapsed onto another principal's permission, so a user could match documents belonging to a different group (#3292, #3299, #3309, #3310, #3317)
  • Bound the LDAP connect, read and search waits so a slow directory cannot hang a login (#3274)
  • Tell the user when the nested LDAP group walk fails instead of proceeding with partial permissions (#3277)
  • Let ldap.role.search.user.enabled withhold the user's own permission as documented (#3311)
  • Report a search-role prefix that cannot work (#3293)

Access Control & API Security

  • Decide admin API access on the access token itself, not on a request parameter — a search token configured with a parameter name could otherwise reach the whole administration API (#3320)
  • Answer an unauthorized admin API request with 401, and honor login.required on the /api/v2 surface (#3313, #3284)
  • Filter by the guest roles when a logged-in user resolved no permission, instead of running unfiltered (#3314)
  • Let a setting decide how authentication.admin.users is compared, and trim the entries of authentication.admin.users and authentication.admin.roles (#3316, #3319, #3321)
  • Keep an externally authenticated administrator signed in (#3276)
  • Stop reporting a caller's malformed credential as a v2 server error (#3286)
  • Match a trusted proxy by address rather than by spelling when applying rate limits (#3287)
  • Release login lockouts on schedule and restore the audit trail (#3197)
  • Stop the logout endpoints from recording a logout nobody performed (#3327)
  • Mask SSO client credentials and rag.llm.<provider>.api.key in System Info and bug reports (#3212, #3201)

Search & Relevance

  • Report an unsupported facet field instead of silently returning no hits (#3199)
  • Stop reporting a search that never ran as a complete result (#3288)
  • Show the previous page on multi-page semantic-only results (#3180)
  • Stop a restored search query from failing the login it follows, and filter restored search parameters the way stored ones are filtered (#3325, #3326)
  • Fall back gracefully on malformed rt and hash parameters in the /go/ redirect (#3189)
  • Quote the replacement when highlighting cached content (#3186)
  • Stream all documents from /api/v2/documents/all instead of stopping after the first (#3185)

Search UI & Themes

  • Restore code content literally and escape text sharing a block with a fence, and parse the server snippet instead of escaping it a second time (#3278, #3192)
  • Drop raw-text elements instead of unwrapping them in the Bootstrap sanitizer, and stop stripping h1, h5 and h6 headings (#3187, #3194)
  • Allow file: and smb: result links in the static theme (#3196)
  • Compare the v2 API error codes the server actually sends (#3198)
  • Accessible copy-URL button and shared-asset hygiene in the Bootstrap theme (#3195)
  • Forward advanced-search link state when the query is empty (#3177)
  • Remove duplicate error rendering on the Admin theme list page (#3179)

Administration & Configuration

  • Keep the stored resultCollapsed value when its checkbox is hidden (#3190)
  • Route genuine 400s to the request error page and keep 401s intact for API clients (#3188)
  • Make the remaining hardcoded LLM prompt bases injectable (#3281)
  • Share provider-agnostic members and credential-URL rules across embedding clients (#3202)

Crawling & Indexing

  • Parse HTML once per page in FessXpathTransformer (#3183)
  • Hand proxy credentials over in the shape the crawler clients actually read (#3285)

Diagnostics & Logging

  • Correct log levels so ERROR means the service is unusable — misleveled messages were triggering operator notifications for recoverable conditions (#3282)

Platform & Distribution

  • Base on OpenSearch 3.8.0 (#3207)
  • Point the plugin installer at maven.codelibs.org and deploy plugin artifacts there (#3205, #3210)
  • Modernize control flow for Java 21 and regenerate FessConfig (#3280)

Bug Fixes

  • /api/v2/documents/all returned only the first document instead of streaming the full set (#3185)
  • Highlighting cached content mangled replacements containing special characters (#3186)
  • Semantic-only results spanning multiple pages could not page backwards (#3180)
  • Result links using file: or smb: were disabled in the static theme (#3196)
  • SSO client credentials were exposed in System Info and bug reports (#3212)
  • The Admin theme list page rendered its error messages twice (#3179)

We recommend upgrading to Fess 15.8.0 for the SSO and permission-resolution fixes, the new content chunking and semantic search pipeline, and OpenSearch 3.8 support. If you override any api.v2.* configuration key, rename it to api.* before upgrading.

📜 Documentation
📦 Docker Image: GitHub Packages - codelibs/fess
💬 Community Forum: discuss.codelibs.org

Thank you for using Fess!