Skip to content

CMR-11240: We no longer exclude concepts that are not in progress when a concept identifier is used in the search query#2405

Merged
daniel-zamora merged 4 commits intomasterfrom
CMR-11240
Mar 31, 2026
Merged

CMR-11240: We no longer exclude concepts that are not in progress when a concept identifier is used in the search query#2405
daniel-zamora merged 4 commits intomasterfrom
CMR-11240

Conversation

@daniel-zamora
Copy link
Copy Markdown
Contributor

@daniel-zamora daniel-zamora commented Mar 30, 2026

Overview

What is the objective?

Bypass the non-operational collection filter when searching by collection identifiers (concept-id, entry-id, entry-title, short-name+version, native-id) to fix broken client workflows.

What are the changes?

  • Modified search parameter logic to detect collection identifiers and skip default progress filter
  • Added test coverage for identifier bypass behavior
  • Updated API documentation

What areas of the application does this impact?

  • Collection search API
  • Client workflows using collection identifiers

Required Checklist

  • New and existing unit and int tests pass locally and remotely
  • clj-kondo has been run locally and all errors in changed files are corrected
  • I have commented my code, particularly in hard-to-understand areas
  • I have made changes to the documentation (if necessary)
  • My changes generate no new warnings

Additional Checklist

  • I have removed unnecessary/dead code and imports in files I have changed
  • I have cleaned up integration tests by doing one or more of the following:
    • migrated any are2 tests to are3 in files I have changed
    • de-duped, consolidated, removed dead int tests
    • transformed applicable int tests into unit tests
    • reduced number of system state resets by updating fixtures. Ex) (use-fixtures :each (ingest/reset-fixture {})) to be :once instead of :each

Summary by CodeRabbit

  • Documentation

    • Updated collection progress search docs with examples and guidance (wildcards, pattern matching) and standardized parameter name include_non_operational.
    • Removed prior experimental availability note.
  • Improvements

    • Identifier-based searches (concept/entry/native/short-name+version) now bypass the non-operational filter by default; explicit include_non_operational=true/false takes precedence.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 30, 2026

📝 Walkthrough

Walkthrough

Updated non-operational collection filtering to bypass the non-operational default filter when searches include collection identifier parameters; added explicit precedence for an explicit include_non_operational value. Changes span API docs, parameter parsing, test URL helper, and expanded integration tests.

Changes

Cohort / File(s) Summary
Documentation
search-app/docs/api.md
Rewrote collection_progress note: identifier-based searches automatically bypass the non-operational filter; explicit include_non_operational (true/false) takes precedence; updated examples and removed "experimental" wording; switched flag name to include_non_operational.
Parameter parsing
search-app/src/cmr/search/services/parameters/conversion.clj
Added has-identifier? detection (:concept-id, :entry-id, :entry-title, :native-id, or :short-name+:version) and changed logic so forced include-non-operational="false" is not applied when identifiers are present.
Test utilities
system-int-test/src/cmr/system_int_test/utils/url_helper.clj
Made elastic root host configurable by using es-config/*-elastic-host instead of hardcoded localhost when building elastic-root URLs.
System integration tests
system-int-test/test/cmr/system_int_test/search/collection/collection_progress_search_test.clj
Refactored assertions to table-driven style, expanded cases for flag ON/OFF, added search-collection-progress-identifier-bypass test covering multiple identifier params and precedence with include-non-operational.

Sequence Diagram(s)

(omitted — changes are limited to parameter parsing, docs, and tests and do not introduce a multi-component runtime flow requiring visualization)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

hacktoberfest-accepted

Suggested reviewers

  • jceaser
  • chris-durbin
  • ygliuvt

Poem

🐇 I hop through params with a twitchy nose,
IDs light the tunnel where the bypass flows.
Filters may hide PLANNED, DEPRECATED, or REVIEW,
But call me by ID — I'll fetch the true view. 🎉

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main behavioral change: bypassing the non-operational collection filter when collection identifiers are used in search queries.
Description check ✅ Passed The description follows the template with complete objective, changes summary, impact areas, and all checklist items marked complete with supporting evidence.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch CMR-11240

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@daniel-zamora daniel-zamora changed the title CMR-11240: search queries with collection identifiers no longer exclu… CMR-11240: We no longer exclude concepts that are not in progress when a concept identifier is used in the search query Mar 30, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
system-int-test/test/cmr/system_int_test/search/collection/collection_progress_search_test.clj (2)

79-100: Consider wrapping flag toggle in try-finally for test isolation.

If any assertion fails between enabling the flag (line 79) and disabling it (line 100), the flag remains enabled, potentially affecting subsequent tests in the same test run. This applies to both search-collection-progress-active-filter and search-collection-progress-identifier-bypass.

♻️ Suggested refactor using try-finally
     (testing "flag OFF - param ignored, all collections returned"
       (util/are3 [items search]
         (d/refs-match? items (search/find-refs :collection search))

         "no params"
         all-colls {}

         "include-non-operational=false"
         all-colls {:include-non-operational "false"}

         "include-non-operational=true"
         all-colls {:include-non-operational "true"}))

-    (side/eval-form `(cmr.search.config/set-enable-non-operational-collection-filter! true))
-
-    (testing "flag ON - filter applies unless overridden"
-      (util/are3 [items search]
-        (d/refs-match? items (search/find-refs :collection search))
-
-        "no params - only operational collections (excludes PLANNED, DEPRECATED, PREPRINT, INREVIEW)"
-        active-colls {}
-
-        "include-non-operational=false - only operational collections"
-        active-colls {:include-non-operational "false"}
-
-        "include-non-operational=true - all collections"
-        all-colls {:include-non-operational "true"}
-
-        "explicit collection-progress=PLANNED - PLANNED returned (filter not applied)"
-        [coll2] {:collection-progress "PLANNED"}
-
-        "collection-progress=PLANNED + include-non-operational=false - empty (explicit filter wins)"
-        [] {:collection-progress "PLANNED" :include-non-operational "false"}))
-
-    (side/eval-form `(cmr.search.config/set-enable-non-operational-collection-filter! false))))
+    (try
+      (side/eval-form `(cmr.search.config/set-enable-non-operational-collection-filter! true))
+
+      (testing "flag ON - filter applies unless overridden"
+        (util/are3 [items search]
+          (d/refs-match? items (search/find-refs :collection search))
+
+          "no params - only operational collections (excludes PLANNED, DEPRECATED, PREPRINT, INREVIEW)"
+          active-colls {}
+
+          "include-non-operational=false - only operational collections"
+          active-colls {:include-non-operational "false"}
+
+          "include-non-operational=true - all collections"
+          all-colls {:include-non-operational "true"}
+
+          "explicit collection-progress=PLANNED - PLANNED returned (filter not applied)"
+          [coll2] {:collection-progress "PLANNED"}
+
+          "collection-progress=PLANNED + include-non-operational=false - empty (explicit filter wins)"
+          [] {:collection-progress "PLANNED" :include-non-operational "false"}))
+      (finally
+        (side/eval-form `(cmr.search.config/set-enable-non-operational-collection-filter! false))))))
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@system-int-test/test/cmr/system_int_test/search/collection/collection_progress_search_test.clj`
around lines 79 - 100, Wrap the flag toggle calls to
cmr.search.config/set-enable-non-operational-collection-filter! in a try/finally
so the flag is always reset to false even if assertions fail; specifically,
around the test block that sets the flag to true (the code invoking
(side/eval-form
`(cmr.search.config/set-enable-non-operational-collection-filter! true))) put
the tests (the util/are3 block for search-collection-progress-active-filter and
similarly in search-collection-progress-identifier-bypass) inside the try and
call (side/eval-form
`(cmr.search.config/set-enable-non-operational-collection-filter! false))) in
the finally to guarantee test isolation.

156-157: Native-id correctly defaults to EntryTitle—optional clarity improvement.

The test is correct: coll3 is ingested with EntryTitle "ET3", and since no explicit :native-id is set, umm-c-collection->concept defaults it to the trimmed EntryTitle via the item->native-id function. The search {:native-id "ET3"} therefore correctly matches coll3.

This assumption is safe and consistent with the test pattern used for entry-title on line 150–151. However, to improve clarity, consider either explicitly setting :native-id "ET3" in the collection data or retrieving it from the ingested reference (e.g., (:native-id coll3)), which would make the implicit derivation explicit.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@system-int-test/test/cmr/system_int_test/search/collection/collection_progress_search_test.clj`
around lines 156 - 157, Test relies on implicit defaulting of native-id from
EntryTitle for coll3 which is correct but unclear; make it explicit by either
adding :native-id "ET3" to the collection data used to ingest coll3 or by using
the actual native-id from the ingested reference (e.g., refer to (:native-id
coll3)) in the search assertion. Update the test where coll3 is defined or where
the search vector is built to use the explicit native-id so readers don't need
to infer umm-c-collection->concept / item->native-id behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@search-app/docs/api.md`:
- Line 1944: Update the NOTE sentence to use the API's underscore-style query
parameter names instead of hyphens: replace "concept-id", "entry-id",
"entry-title", "short-name" and "native-id" with "concept_id", "entry_id",
"entry_title", "short_name" (with "version" where noted) and "native_id", and
keep the reference to the include-non-operational=true flag and the rule about
searching by collection identifiers unchanged.

---

Nitpick comments:
In
`@system-int-test/test/cmr/system_int_test/search/collection/collection_progress_search_test.clj`:
- Around line 79-100: Wrap the flag toggle calls to
cmr.search.config/set-enable-non-operational-collection-filter! in a try/finally
so the flag is always reset to false even if assertions fail; specifically,
around the test block that sets the flag to true (the code invoking
(side/eval-form
`(cmr.search.config/set-enable-non-operational-collection-filter! true))) put
the tests (the util/are3 block for search-collection-progress-active-filter and
similarly in search-collection-progress-identifier-bypass) inside the try and
call (side/eval-form
`(cmr.search.config/set-enable-non-operational-collection-filter! false))) in
the finally to guarantee test isolation.
- Around line 156-157: Test relies on implicit defaulting of native-id from
EntryTitle for coll3 which is correct but unclear; make it explicit by either
adding :native-id "ET3" to the collection data used to ingest coll3 or by using
the actual native-id from the ingested reference (e.g., refer to (:native-id
coll3)) in the search assertion. Update the test where coll3 is defined or where
the search vector is built to use the explicit native-id so readers don't need
to infer umm-c-collection->concept / item->native-id behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a57a5d0d-f659-46ee-8cfc-64940665e1e6

📥 Commits

Reviewing files that changed from the base of the PR and between d063d16 and c787b7b.

📒 Files selected for processing (4)
  • search-app/docs/api.md
  • search-app/src/cmr/search/services/parameters/conversion.clj
  • system-int-test/src/cmr/system_int_test/utils/url_helper.clj
  • system-int-test/test/cmr/system_int_test/search/collection/collection_progress_search_test.clj

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@search-app/docs/api.md`:
- Line 1944: Update the NOTE to clarify that the identifier-based bypass only
prevents the service from auto-applying the default non-operational collection
filter — it does not override an explicit query parameter; state that when
caller sets include-non-operational=false (or true) explicitly, that explicit
setting still applies even if identifier params (concept_id, entry_id,
entry_title, short_name+version, native_id) are present.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a4f722d4-d5d1-40f1-b780-810a11bbbc5b

📥 Commits

Reviewing files that changed from the base of the PR and between c787b7b and cd7a3c4.

📒 Files selected for processing (1)
  • search-app/docs/api.md

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Mar 30, 2026

Codecov Report

❌ Patch coverage is 50.00000% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 57.89%. Comparing base (d063d16) to head (fa9a35c).

Files with missing lines Patch % Lines
.../src/cmr/search/services/parameters/conversion.clj 40.00% 3 Missing and 3 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #2405      +/-   ##
==========================================
- Coverage   57.90%   57.89%   -0.01%     
==========================================
  Files        1067     1067              
  Lines       73454    73462       +8     
  Branches     2127     2126       -1     
==========================================
+ Hits        42532    42534       +2     
- Misses      28942    28944       +2     
- Partials     1980     1984       +4     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Valid values: ACTIVE, PLANNED, COMPLETE, DEPRECATED, NOT PROVIDED, PREPRINT, INREVIEW, SUPERSEDED

**NOTE:** When the non-operational collection filter is enabled (feature flag), collections with PLANNED, DEPRECATED, PREPRINT, and INREVIEW status are excluded from default search results. Use `include-non-operational=true` to include them. This is an experimental feature and may not be enabled in all environments.
**NOTE:** When the non-operational collection filter is enabled (feature flag), collections with PLANNED, DEPRECATED, PREPRINT, and INREVIEW status are excluded from default search results. Use `include-non-operational=true` to include them. The default filter is automatically bypassed when searching by collection identifiers (`concept_id`, `entry_id`, `entry_title`, `short_name` with `version`, or `native_id`), allowing you to find specific collections regardless of their progress status. However, if you explicitly set `include-non-operational=false` (or `true`), that explicit setting takes precedence even when using identifier parameters.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add documentation for the include_non_operational url parameter in the docs while we are in here

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
system-int-test/test/cmr/system_int_test/search/collection/collection_progress_search_test.clj (1)

79-100: Always restore the feature flag with try/finally to prevent cross-test leakage.

The flag reset currently depends on reaching the last line of each test. If an exception occurs earlier, later tests can run with the wrong global config.

🔧 Suggested hardening pattern
-    (side/eval-form `(cmr.search.config/set-enable-non-operational-collection-filter! true))
-
-    (testing "flag ON - filter applies unless overridden"
-      ...)
-
-    (side/eval-form `(cmr.search.config/set-enable-non-operational-collection-filter! false))))
+    (side/eval-form `(cmr.search.config/set-enable-non-operational-collection-filter! true))
+    (try
+      (testing "flag ON - filter applies unless overridden"
+        ...)
+      (finally
+        (side/eval-form `(cmr.search.config/set-enable-non-operational-collection-filter! false))))))

Apply the same pattern to the second test block (Line 132 onward).

Also applies to: 132-171

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@system-int-test/test/cmr/system_int_test/search/collection/collection_progress_search_test.clj`
around lines 79 - 100, The test toggles the global flag via (side/eval-form
`(cmr.search.config/set-enable-non-operational-collection-filter! true)) and
then resets it to false, but if an exception occurs the reset is skipped; change
both test blocks that call set-enable-non-operational-collection-filter! to wrap
the body in a try/finally so the final (side/eval-form
`(cmr.search.config/set-enable-non-operational-collection-filter! false)) runs
in the finally clause; locate the occurrences surrounding the testing "flag ON -
filter applies unless overridden" block and the second test block (the one
starting around line 132) and move their test logic into try with the reset call
placed in finally.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@search-app/docs/api.md`:
- Line 1944: The note is using a different query parameter spelling
(`include-non-operational`) than the rest of the doc which uses
`include_non_operational`; change the hyphenated form to the underscored form so
the note uses `include_non_operational` (ensure occurrences in the sentence
about bypass behavior and the example flag text match
`include_non_operational=true` / `include_non_operational=false` and keep the
identifier list as-is) to maintain a single consistent parameter name across the
document.

---

Nitpick comments:
In
`@system-int-test/test/cmr/system_int_test/search/collection/collection_progress_search_test.clj`:
- Around line 79-100: The test toggles the global flag via (side/eval-form
`(cmr.search.config/set-enable-non-operational-collection-filter! true)) and
then resets it to false, but if an exception occurs the reset is skipped; change
both test blocks that call set-enable-non-operational-collection-filter! to wrap
the body in a try/finally so the final (side/eval-form
`(cmr.search.config/set-enable-non-operational-collection-filter! false)) runs
in the finally clause; locate the occurrences surrounding the testing "flag ON -
filter applies unless overridden" block and the second test block (the one
starting around line 132) and move their test logic into try with the reset call
placed in finally.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 10536bbf-467c-46d4-8779-4c8457990cd8

📥 Commits

Reviewing files that changed from the base of the PR and between cd7a3c4 and fa9a35c.

📒 Files selected for processing (2)
  • search-app/docs/api.md
  • system-int-test/test/cmr/system_int_test/search/collection/collection_progress_search_test.clj

Valid values: ACTIVE, PLANNED, COMPLETE, DEPRECATED, NOT PROVIDED, PREPRINT, INREVIEW, SUPERSEDED

**NOTE:** When the non-operational collection filter is enabled (feature flag), collections with PLANNED, DEPRECATED, PREPRINT, and INREVIEW status are excluded from default search results. Use `include-non-operational=true` to include them. This is an experimental feature and may not be enabled in all environments.
**NOTE:** When the non-operational collection filter is enabled (feature flag), collections with PLANNED, DEPRECATED, PREPRINT, and INREVIEW status are excluded from default search results. Use `include-non-operational=true` to include them. The default filter is automatically bypassed when searching by collection identifiers (`concept_id`, `entry_id`, `entry_title`, `short_name` with `version`, or `native_id`), allowing you to find specific collections regardless of their progress status. However, if you explicitly set `include-non-operational=false` (or `true`), that explicit setting takes precedence even when using identifier parameters.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Use one query parameter spelling for include_non_operational in this note.

Line 1944 uses include-non-operational, but the heading and examples below use include_non_operational. Keeping one style here avoids client confusion.

✏️ Proposed doc fix
-**NOTE:** When the non-operational collection filter is enabled (feature flag), collections with PLANNED, DEPRECATED, PREPRINT, and INREVIEW status are excluded from default search results. Use `include-non-operational=true` to include them. The default filter is automatically bypassed when searching by collection identifiers (`concept_id`, `entry_id`, `entry_title`, `short_name` with `version`, or `native_id`), allowing you to find specific collections regardless of their progress status. However, if you explicitly set `include-non-operational=false` (or `true`), that explicit setting takes precedence even when using identifier parameters.
+**NOTE:** When the non-operational collection filter is enabled (feature flag), collections with PLANNED, DEPRECATED, PREPRINT, and INREVIEW status are excluded from default search results. Use `include_non_operational=true` to include them. The default filter is automatically bypassed when searching by collection identifiers (`concept_id`, `entry_id`, `entry_title`, `short_name` with `version`, or `native_id`), allowing you to find specific collections regardless of their progress status. However, if you explicitly set `include_non_operational=false` (or `true`), that explicit setting takes precedence even when using identifier parameters.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@search-app/docs/api.md` at line 1944, The note is using a different query
parameter spelling (`include-non-operational`) than the rest of the doc which
uses `include_non_operational`; change the hyphenated form to the underscored
form so the note uses `include_non_operational` (ensure occurrences in the
sentence about bypass behavior and the example flag text match
`include_non_operational=true` / `include_non_operational=false` and keep the
identifier list as-is) to maintain a single consistent parameter name across the
document.

@daniel-zamora daniel-zamora merged commit 22f1285 into master Mar 31, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants