Subtree searches that don’t name an entry type are answered locally — A directory search across a base that spans more than one configured context, without naming an entry type (for example a virtual-list-view browse from a directory client), is now answered from IdentityScribe’s own data instead of being forwarded to the upstream directory. Searches that already name a type, or target a single configured context, keep their current behavior. Migration: To keep forwarding these searches to the upstream directory, set channels.ldap.untyped-search = delegate (or SCRIBE_LDAP_UNTYPED_SEARCH=delegate). Mark any subtree that must be served by the upstream directory as an ignore-contexts entry.
Planner telemetry uses one consistent naming scheme — The metrics and trace attributes that describe how the query planner executed a search were spread across several inconsistent names and namespaces. They now live under a single scribe.plan.* metric namespace, and a single per-search-strategy latency histogram replaces the former gate-only one — so every routed search is measured, not only the gated ones. Migration: Dashboards or alerts keyed on the previous planner metric names (scribe.directory.plan.*, scribe.planner.*, scribe.database.plan_mode.*) or on the retired scribe.gate.query.duration histogram must be repointed to the scribe.plan.* series — per-search latency is now scribe.plan.route.duration.seconds. Custom queries that grouped planner metrics by older route, gate-source, or dispatch-leading attributes should move to the consolidated scribe.plan.route, scribe.plan.lead, scribe.gate.route, and scribe.gate.route_source attributes; reason labels are shortened under the new schema.
The Observe MCP endpoint requires authentication by default — Requests to the Observe MCP endpoint (/observe/mcp) now require an operator session or accepted credential; anonymous requests are denied. This endpoint previously inherited the global monitoring auth setting, which left it open whenever global authentication was off. Migration: For trusted local evaluation, set monitoring.mcp.auth.enabled=false or SCRIBE_MONITORING_MCP_AUTH_ENABLED=false. For shared environments, sign in or send an approved credential.
Added
Observe surfaces the query planner’s preparation cost — The planner does extra database work around a search — readiness and sizing checks it runs before the result query itself — and that cost used to be invisible. The Observe Inbox evidence-health panel now adds an “Estimation & GUC cost” section showing how much per-query sizing work ran and which connection pools still pay a per-request connection-setup cost, so you can spot pools that would benefit from a baked session profile. The underlying timing is exported for your own dashboards, and with trace export on (monitoring.traces.enabled = true) the background estimation and plan-mode checks show up on the trace timeline with their timing and frequency. Numbers read “evidence pending” until the first sample arrives. The same per-query sizing and connection-setup cost also appears in a query’s diagnostic report. See Signals.
Clearer LDAP sign-in diagnostics — When an LDAP sign-in succeeds but the directory service account cannot read the account back — an access-rights or filter configuration issue rather than a wrong password — operators now get a distinct signal that separates the two, and sign-in failures appear on the request timeline. The response sent to the client is unchanged.
Every search records which strategy ran, and how fast each strategy is — Each query’s trace now carries the search strategy it took, so one trace shows which kind of search ran. Per-strategy latency is now recorded for every routed search, including merge and range searches that previously went unmeasured, and the Observe evidence-health panel shows per-strategy p95 latency and a recent (5-minute) mix beside the cumulative totals — so a slowdown or shift in one kind of search shows up without waiting for process-lifetime aggregates. A query’s diagnostic report now names its search strategy too, and Observe workload cards group by strategy — so two slow searches of different kinds no longer collapse into one card.
Failure detail in logs can be redacted for shared log backends — Failure messages, failure details, and exception stack traces written to the structured and application logs can now be redacted before they leave the process, so query filter text, distinguished names, and attribute values that appear in error detail need not reach a shared SIEM. Redaction is opt-in and off by default — local incident logs keep full detail — and is set per field under monitoring.log.redaction (exception.message, exception.stacktrace, failure.details, exception.cause.*, warning.details), using the same hash and omit options as trace export. With no redaction rule configured, log output is unchanged.
Changed
Sorted searches that narrow to a small set of entries return quickly over large directories — A sorted or virtual-list-view browse that narrows to a small set — by entry distinguished names (a single one or a long list), by a unique identifier (uuid or uoid), or by a selective attribute value such as a rare surname — now returns in a fraction of a second across very large directories, where the same search could previously take many seconds. This applies when the search names the entry types it spans (or its base maps to specific types) and sorts on an attribute the directory keeps sorted, on the first page and when paging forward by cursor or page offset. Results and ordering are unchanged.
Broad sorted browses served locally return quickly over large directories — A sorted or virtual-list-view browse over a base that spans several entry types, with no narrowing filter, now returns in a fraction of a second across very large directories — on its first page, when paging forward by cursor, and at a deep page offset — where the same browse could previously take tens of seconds. This applies when IdentityScribe answers the browse from its own data rather than forwarding it (see the subtree-search entry above) and the spanned types keep the sort attribute indexed. Results and ordering are unchanged.
Observe presents evidence consistently across its views — The Observe Inbox, Workloads, recurring-workload groups, query diagnostic report, and storage-coverage views now share one evidence model, so a given signal reads the same way in every view. Expandable rows respond to the keyboard like native controls, and the views render correctly on small and mobile screens. The signals shown are unchanged.
Fixed
Operator views label searches by strategy — The Observe planner evidence-health panel now labels each search by an outcome-framed search strategy (Filtered search, Sorted listing, Combined-condition search, Membership search, Range search), matching the per-query diagnostic report. The information shown is otherwise unchanged.
Failed sign-ins return at a constant time — A failed credential check now returns at the same fixed time whether the username does not exist, the password is wrong, or the password was correct but the account could not be read back. Response timing no longer reveals which of these happened, so it cannot be used to confirm a valid password or probe which accounts exist. This covers credential validation at the LDAP bind, the HTTP 401 response, and the browser login form; the response a client sees is otherwise unchanged. The fixed time is auth.failure-delay (SCRIBE_AUTH_FAILURE_DELAY), default 2 seconds — set it comfortably above your slowest failed sign-in for the guarantee to hold (the 2s default covers a healthy directory). Setting it to 0 disables both the delay and the constant-time response.
Sorted prefix searches keep accented matches — Sorted and virtual-list-view searches that filter the sorted attribute with “starts with” now keep entries whose names contain accents or other non-ASCII characters. These searches no longer omit valid matches while paging, and result ordering is unchanged.
Sorted and paged directory searches no longer fail with an error — An LDAP search that has to be forwarded to the upstream directory (for example a sorted or virtual-list-view browse from a directory client) could return an “invalid request” error instead of the intended “this search cannot be served here” response. These searches now return the correct response.
Directory searches that select entries by distinguished name no longer need an entry type — A subtree search that filters on one or more entry DNs (for example an Identity Hub lookup that names users and roles by their distinguished names) across a base that spans more than one configured context previously returned an error asking for an entry type. IdentityScribe now recognizes the entry type from each distinguished name and returns the matching entries. Searches whose DNs fall outside the configured contexts keep their existing behavior.
REST error responses no longer expose internal diagnostic details — Error responses from the REST API previously included a details object that could carry internal directory layout (the configured base DNs for each entry type) and internal attribute names. REST error responses now omit that object, returning only the safe code, message, and HTTP status — matching the GraphQL and MCP channels. The code, message, and status are unchanged.