Thanks to visit codestin.com
Credit goes to github.com

Skip to content

feat(api): customer list search by partial key#3263

Merged
tothandras merged 1 commit intomainfrom
feat/api-customer-filters
Aug 25, 2025
Merged

feat(api): customer list search by partial key#3263
tothandras merged 1 commit intomainfrom
feat/api-customer-filters

Conversation

@tothandras
Copy link
Contributor

@tothandras tothandras commented Aug 25, 2025

Summary by CodeRabbit

  • New Features

    • Enhanced customer filtering: the “key” filter now supports case-insensitive partial matches instead of case-sensitive exact matches, making it easier to find customers by partial keys.
  • Documentation

    • Updated API documentation and SDK comments to reflect the new case-insensitive partial matching behavior for the “key” filter.

@tothandras tothandras requested a review from a team as a code owner August 25, 2025 11:37
@tothandras tothandras added area/api release-note/feature Release note: Exciting New Features labels Aug 25, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 25, 2025

📝 Walkthrough

Walkthrough

Updated customer “key” filter semantics from case-sensitive exact match to case-insensitive partial match across specs, client SDK docs, and OpenAPI descriptions. Backend implementation changed the predicate to case-insensitive substring matching in ListCustomers. No public API signatures were modified.

Changes

Cohort / File(s) Summary of changes
Backend behavior
openmeter/customer/adapter/customer.go
Switched key filter from exact match to case-insensitive substring (KeyEQKeyContainsFold) in ListCustomers.
API specifications
api/openapi.yaml, api/openapi.cloud.yaml, api/spec/src/customer/customer.tsp
Updated parameter/field descriptions to state key filter is case-insensitive partial match; no schema/signature changes.
Client SDK (JS)
api/client/javascript/src/client/schemas.ts, api/client/javascript/src/zod/index.ts
Revised documentation strings for key filter to describe case-insensitive partial matching; no type or signature changes.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/api-customer-filters

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@tothandras tothandras enabled auto-merge (squash) August 25, 2025 11:38
@tothandras tothandras disabled auto-merge August 25, 2025 11:38
@tothandras tothandras enabled auto-merge (squash) August 25, 2025 11:39
@tothandras tothandras merged commit 13f1f4b into main Aug 25, 2025
24 of 25 checks passed
@tothandras tothandras deleted the feat/api-customer-filters branch August 25, 2025 11:42
Copy link
Contributor

@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: 4

🧹 Nitpick comments (14)
api/openapi.cloud.yaml (3)

12181-12185: Clarify matching semantics and add examples/constraints to the parameter doc.

Great that the doc now reflects the case-insensitive partial match. To reduce ambiguity and improve client UX, consider documenting what “partial” means with a short example and add basic constraints to prevent pathological queries.

Proposed edit:

-      description: |-
-        Filter customers by key.
-        Case-insensitive partial match.
+      description: |-
+        Filter customers by key.
+        Case-insensitive substring match (e.g., `?key=acme` matches `acme-inc`, `AcMe_2`).
+        Matching is performed against the entire key value.
       schema:
         type: string
+        minLength: 2
+        maxLength: 128
       explode: false
+      example: acme

12182-12182: Call out Unicode and normalization expectations (one sentence).

If the backend uses case folding (e.g., LOWER/ILIKE or equivalent), specifying that matching is Unicode-aware (or ASCII-only) removes guesswork for clients using non-ASCII keys.

Suggested wording to append to the description:

  • “Case-insensitive comparison is Unicode-aware and locale-independent.” (If true)
  • Or: “Case-insensitive comparison is ASCII-only.” (If true)

Please select the accurate statement based on the implementation.


12181-12184: Plan for performance: substring searches need indexing and guardrails.

Substring matches (%term%) can degrade query performance on large datasets without proper indexing. If the backend uses Postgres, consider a trigram index on the key (e.g., GIN with gin_trgm_ops) and/or a functional index on lower(key). The proposed minLength helps reduce extremely short terms.

api/spec/src/customer/customer.tsp (2)

122-127: Doc change LGTM; consider adding example and clarifying “exact match” path to avoid ambiguity

The “Case-insensitive partial match” update aligns with the backend change. To help users and SDKs, add an example and explicitly point to the exact-match alternative.

Apply this diff:

   /**
    * Filter customers by key.
-   * Case-insensitive partial match.
+   * Case-insensitive partial (substring) match.
+   * For exact key lookup, use GET /api/v1/customers/{customerIdOrKey}.
   */
   @query
+  @example("acme")
   key?: string;

43-53: Clarify case-sensitivity for GET by key

Since list uses case-insensitive partial matching, explicitly documenting that “Get customer by ID or key” performs an exact key match will prevent confusion.

Suggestion: Add a sentence to the operation summary/description like “When using a key, matching is exact (not partial).”

openmeter/customer/adapter/customer.go (2)

49-56: Consider query performance: case-insensitive substring filters need indexes

ContainsFold typically compiles to LOWER(key) LIKE '%' || LOWER($1) || '%', which can’t use standard btree indexes. On larger tables this becomes expensive, especially when filters are broad.

Options:

  • Add trigram index (Postgres): CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_customer_key_trgm ON customer USING gin (key gin_trgm_ops);
  • If you standardize on case-insensitive equality elsewhere, consider citext for equality predicates; for substring, keep trigram.
  • If applicable, reject too-short patterns (e.g., < 2 chars) in ListCustomersInput.Validate() to reduce unselective scans.

49-72: Add tests to lock in new semantics and the empty-string behavior

Given the change in semantics, add tests that assert:

  • key filter is case-insensitive and substring-based,
  • empty/whitespace key is ignored (no filter applied).

I can draft table-driven tests for ListCustomers covering positive, negative, and empty-string cases. Want me to open a follow-up PR with tests?

api/openapi.yaml (3)

12178-12183: Clarify semantics and add examples for substring search.

“Case-insensitive partial match.” is terse and can be misread. Recommend making it explicit that this is a substring match and that passing the full key may still return multiple rows. Also document empty-string behavior.

Apply this diff to improve the description and add parameter-level examples:

       description: |-
         Filter customers by key.
-        Case-insensitive partial match.
+        Case-insensitive substring match.
+        Matches any customer keys containing the provided value, regardless of case.
+        Examples:
+          - ?key=acme → matches "ACME-001", "myAcmeCompany"
+          - ?key=001 → matches "acme-001", "cust-001"
+        Note: Providing the full key may still return multiple results if other keys contain it as a substring.
       schema:
         type: string
+        minLength: 1
       explode: false

If the backend treats key="" as “match all”, consider stating that explicitly instead of enforcing minLength: 1.


12181-12183: Consider removing explode: false for a plain string param.

For a string with style=form (default), explode is irrelevant; keeping it is harmless but redundant.

Apply this diff if you prefer to reduce noise:

       schema:
         type: string
-      explode: false

12178-12183: Add a release-note snippet describing the changed matching semantics.

Even without signature changes, clients depending on exact match semantics may see broader result sets. Surface this explicitly in release notes with upgrade guidance.

I can draft a concise release-note block and an SDK changelog entry if you confirm the desired behavior for empty strings and trimming rules (e.g., whitespace, Unicode normalization).

api/client/javascript/src/zod/index.ts (2)

6741-6744: Normalize and ignore empty/whitespace-only values to avoid accidental “match-all” queries

With partial matching, passing an empty string ("") would likely match everything. Consider trimming and converting blank inputs to undefined so that an empty value behaves the same as omitting the filter.

Apply this diff within the current chain:

   key: zod.coerce
     .string()
+    .transform((s) => s.trim() || undefined)
     .optional()
-    .describe('Filter customers by key.\nCase-insensitive partial match.'),
+    .describe('Filter customers by key.\nCase-insensitive partial match (substring).\nEmpty/whitespace-only values are ignored.'),

6741-6744: Optional: guard against multi-valued query params being coerced to a comma-joined string

zod.coerce.string() will stringify arrays (e.g., ['ac','me'] -> 'ac,me'), which could unintentionally broaden the search. If your query builder allows repeated params (e.g., ?key=a&key=b), consider taking only the first element.

If desired, switch to a preprocess step before coercion (requires adjusting the surrounding code slightly):

// Example helper (outside this diff range)
const firstString = <T>(v: T) =>
  Array.isArray(v) ? v[0] : v;

// Replace chain with:
key: zod.preprocess(firstString, zod.coerce.string())
  .transform((s) => s.trim() || undefined)
  .optional()
  .describe('Filter customers by key.\nCase-insensitive partial match (substring).\nEmpty/whitespace-only values are ignored.')
api/client/javascript/src/client/schemas.ts (2)

10680-10680: Clarify “partial” to “substring” and add an example for unambiguous behavior.

“Partial match” can be read as prefix, infix, or fuzzy. If the backend uses plain substring containment, let’s say so and include a short example to set expectations.

Apply this diff:

- *     Case-insensitive partial match. */
+ *     Case-insensitive substring match. For example, key=acme matches "ACME", "acme-co", and "myacme123". */

15080-15080: Mirror the same clarification and example in the operations interface.

Keep wording consistent across the components and operations sections to avoid divergent client docs.

Apply this diff:

- *     Case-insensitive partial match. */
+ *     Case-insensitive substring match. For example, key=acme matches "ACME", "acme-co", and "myacme123". */
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled
  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between e728f3a and e525a26.

📒 Files selected for processing (6)
  • api/client/javascript/src/client/schemas.ts (2 hunks)
  • api/client/javascript/src/zod/index.ts (1 hunks)
  • api/openapi.cloud.yaml (1 hunks)
  • api/openapi.yaml (1 hunks)
  • api/spec/src/customer/customer.tsp (1 hunks)
  • openmeter/customer/adapter/customer.go (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
openmeter/customer/adapter/customer.go (1)
openmeter/ent/db/customer/where.go (2)
  • KeyContainsFold (1122-1124)
  • Key (137-139)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: E2E
  • GitHub Check: Quickstart
  • GitHub Check: Code Generators
  • GitHub Check: Test
  • GitHub Check: Build
  • GitHub Check: Lint
  • GitHub Check: Analyze (go)
🔇 Additional comments (3)
openmeter/customer/adapter/customer.go (1)

337-346: Confirm intended case-sensitivity for GET by key vs LIST by key

GetCustomer uses equality: customerdb.Key(...). Unless the column is citext, equality is case-sensitive, while the list filter is case-insensitive. If this divergence is intentional, document it; otherwise, consider KeyEqualFold (if generated) or aligning storage to citext.

Would you like me to scan the repo to confirm:

  • whether the key column uses citext,
  • whether an EqualFold predicate exists for customerdb.Key?

I can run a repo scan script to verify and report findings.

api/openapi.yaml (1)

12178-12183: No stale “exact match” wording remains; new filter docs are consistent

All occurrences of the old “case-sensitive exact match” have been removed, and the new “Case-insensitive partial match” appears consistently in:

  • API specs (api/openapi.yaml & api/openapi.cloud.yaml)
  • Generated Go client (api/api.gen.go & client/go/client.gen.go)
  • JavaScript client (schemas.ts & Zod index)
  • Internal spec (api/spec/src/customer/customer.tsp)

Please ensure that any user-facing documentation (e.g., markdown guides) and the release notes explicitly mention this behavioral change.

api/client/javascript/src/zod/index.ts (1)

6741-6744: LGTM: description now reflects case-insensitive partial match semantics

The updated description aligns with the backend change to a case-insensitive substring filter and clarifies client expectations. No signature or validation changes are introduced here, which keeps it backward compatible for callers.

Comment on lines 10679 to 10681
/** @description Filter customers by key.
* Case-sensitive exact match. */
* Case-insensitive partial match. */
'queryCustomerList.key': string
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Confirm cross-repo consistency and note the semantic change in release notes.

Since this changes filter semantics (exact/case-sensitive → substring/case-insensitive), please ensure:

  • All SDKs and OpenAPI specs consistently state “case-insensitive substring match.”
  • Any remaining references to “exact match” or “case-sensitive” are removed.
  • Release notes/changelog call out this behavioral change to set expectations for broader result sets.

Run this script to find lingering, conflicting phrasing:

If you want, I can propose coordinated doc tweaks for OpenAPI, other language SDKs, and a short release-note entry.

Also applies to: 15079-15081


🏁 Script executed:

#!/bin/bash
# Search for phrasing that may contradict the new semantics
rg -n -C2 -i \
  -e 'exact match' \
  -e 'case[- ]sensitive' \
  -e 'partial match' \
  -e 'substring match' \
  api/ api.client/ client/ sdk/ packages/ | sed 's/^/HIT: /'

Length of output: 20088


Update all filter documentation to “case-insensitive substring match” across specs and SDKs

The following locations still refer to “exact match” or imply case-sensitive filtering and must be updated to reflect the new substring/case-insensitive behavior:

• OpenAPI specs
– api/openapi.yaml (e.g. “Simple filter for group bys with exact match.” at lines ~11861, 19149)
– api/openapi.cloud.yaml (same descriptions at lines ~11863, 18568)

• TSP specs
– api/spec/src/customer/customer.tsp (descriptions at lines 124, 131, 139, 147)
– api/spec/src/meters.tsp (lines 391, 465)

• Generated Go clients
– api/api.gen.go (comments at lines 4596, 8010, 8258)
– api/client/go/client.gen.go (comments at lines 4184, 7423, 7671)

• JavaScript Zod schemas
– api/client/javascript/src/zod/index.ts (describe() calls at lines 9332, 9411, 12660)

• JS client schemas
– api/client/javascript/src/client/schemas.ts (comments at lines 6937, 10588, 19619, 22487)

• Portal SDK
– api/client/javascript/src/portal/index.ts (comment at line 64)

Please remove or replace any “exact match” / “case-sensitive” phrasing with “case-insensitive substring match” and ensure all SDKs and OpenAPI specs consistently use the updated language. Also, add a clear entry in the release notes/changelog explaining that filter semantics have changed from exact/case-sensitive to substring/case-insensitive, so users understand broader result sets.

🤖 Prompt for AI Agents
In api/client/javascript/src/client/schemas.ts around lines 10679-10681, the
filter description currently reads "Case-insensitive partial match." — update
this phrasing to "case-insensitive substring match" to align with the new
canonical wording; audit nearby schema comment blocks in this file for other
occurrences (lines noted in the review like ~6937, 10588, 19619, 22487) and
replace any "exact match", "partial match", or "case-sensitive" language with
"case-insensitive substring match" so the SDK documentation consistently
reflects the updated filter semantics.

Comment on lines 6741 to +6744
key: zod.coerce
.string()
.optional()
.describe('Filter customers by key.\nCase-sensitive exact match.'),
.describe('Filter customers by key.\nCase-insensitive partial match.'),
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Repo-wide consistency check for wording and behavior

Ensure there are no lingering “exact match” mentions in SDKs/docs and that server predicates use a case-insensitive contains operator consistently.

Run:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Find any stale "exact match" mentions around customer key filters
rg -nI -C2 -S -e 'exact match' -e 'Exact match' -- 'api/**' 'openmeter/**' 'docs/**' || true

# 2) Confirm updated phrasing appears across specs/clients
rg -nI -C2 -S -e 'Case-insensitive partial match' -- 'api/**' 'docs/**' 'clients/**' || true

# 3) Double-check backend predicate uses case-insensitive containment
rg -nI -C2 -S -e 'ContainsFold' -e 'ILIKE' -e 'LOWER\(.*\) LIKE' -- 'openmeter/**' || true

Length of output: 642


I’m seeing that the globs in the original script don’t match any paths—let’s discover the actual top-level directories so we can re-run the searches correctly.


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# List root-level entries to identify correct paths
ls -1

Length of output: 422


Let’s re-run the consistency checks against the correct directories:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Find any stale "exact match" mentions
rg -nI -C2 -S -e 'exact match' -e 'Exact match' -- api/**/* openmeter/**/* docs/**/* || true

# 2) Confirm updated phrasing appears across specs/clients
rg -nI -C2 -S -e 'Case-insensitive partial match' -- api/**/* docs/**/* api/client/**/* || true

# 3) Double-check backend predicate uses case-insensitive containment
rg -nI -C2 -S -e 'ContainsFold' -e 'ILIKE' -e 'LOWER\(.*\) LIKE' -- openmeter/**/* || true

Length of output: 108592


Clean up remaining “exact match” references and confirm consistent use of case-insensitive contains

I ran a repo-wide search and confirmed:

  • Stale “exact match” mentions still exist in several docs and SDKs:
    • openmeter/apiconverter/filter.go – the planFilterFunc and addonFilterFunc comments refer to stopping on an “exact match.”
    • api/client/javascript/src/zod/index.ts around lines 389–393 and 9330–9334 – descriptions for filterGroupBy still say “Simple filter for group bys with exact match.”
    • Go client (api/client/go) generated types – the FilterGroupBy field in client.gen.go/types/doc.go comments “Simple filter for group bys with exact match.”
    • Python client (api/client/python/src) – similar filterGroupBy docstrings.

  • The updated phrasing (“Case-insensitive partial match”) is already applied to all customer filter parameters across SDKs:
    • API clients (Go, JavaScript, Node, Python, Web) describe key, name, primaryEmail, and subject filters as “Case-insensitive partial match.”
    • OpenAPI specs and docs reference the same wording for those parameters.

  • Backend predicates uniformly use case-insensitive containment for customer filters:
    KeyContainsFold, NameContainsFold, PrimaryEmailContainsFold, and SubjectKeyContainsFold are used in all relevant query builders.

Please update the above “exact match” references to align with the new semantics (e.g. replace with “Case-insensitive partial match”) so the entire codebase and docs consistently reflect case-insensitive contains behavior.

🤖 Prompt for AI Agents
In api/client/javascript/src/zod/index.ts around lines 6741-6744 (and also check
and update the similar descriptions at ~389-393 and ~9330-9334 in the same
file), the filter descriptions still reference “exact match”; replace those
phrases with “Case-insensitive partial match” so the `key`, `filterGroupBy` and
any other customer-filter description text reflects the case-insensitive
contains semantics, ensuring wording is identical to other SDKs and OpenAPI
docs.

Comment on lines 12179 to 12185
required: false
description: |-
Filter customers by key.
Case-sensitive exact match.
Case-insensitive partial match.
schema:
type: string
explode: false
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Confirm cross-spec and SDK consistency; add a release-note caveat for behavior change.

This is a behavior change (from exact to substring matching) that could broaden results for existing queries. Ensure all surfaces reflect the update, and note it in release notes as a potentially impactful change.

Run to verify consistency across specs and SDKs:

If any matches remain, update them and add a release-note entry that existing filters may return more rows due to substring semantics.


🏁 Script executed:

#!/bin/bash
# Verify all public specs and clients reflect the new semantics.
set -euo pipefail

echo "Searching for outdated 'Case-sensitive exact match' wording…"
rg -nP -C1 'Case-?sensitive exact match' -- \
  api/ api/spec/ api/client/ || true

echo "Inspecting all customer key filter docs…"
rg -nP -C2 '(Filter customers by key|listCustomers.*key|ListCustomers.*key)' -- \
  api/ api/spec/ api/client/

echo "Optional: check for references to exact equality in Go adapters…"
rg -nP -C2 '\bKey(EQ|Equal)\b|\bContains(Fold)?\b' -- \
  openmeter/ || true

Length of output: 285388


Docs/SDKs show "case‑insensitive partial match" — backend mapping still needs verification and fixes; add release note

Short: the API spec and generated SDKs were updated to "Case-insensitive partial match" (api/openapi.cloud.yaml, api/openapi.yaml, api/spec/src/customer/customer.tsp and generated client files). However the server code still exposes equality predicates and at least one adapter call uses equality semantics, so behavior may be inconsistent.

Please check/fix these locations (examples from the verification run):

  • api/openapi.cloud.yaml:12179-12182 — description updated to "Case-insensitive partial match".
  • api/openapi.yaml:12177-12180 and api/spec/src/customer/customer.tsp:123-125 — spec text updated.
  • api/api.gen.go (≈7628-7630) and api/client/javascript/src/{zod,index,schemas}.ts — generated clients/docs reflect partial-match text.
  • openmeter/ent/db/customer/where.go — KeyEQ (equality) and KeyContains / KeyContainsFold (contains) predicates both present.
  • openmeter/billing/adapter/customeroverride.go:175 — confirmed use of dbcustomer.KeyEQ(input.CustomerKey) (needs change if API intends substring semantics).
  • openmeter/customer/httpdriver/apimapping.go — verify mapping of the query param -> DB predicate (ensure it uses KeyContainsFold when intended).

Action items:

  • Update server-side mappings/adapters that still use KeyEQ to use the case-insensitive contains predicate (KeyContainsFold) where the API promises substring matching.
  • Run unit/integration tests and regenerate clients if needed.
  • Add a release-note: "Customer key filter changed from exact match to case-insensitive substring match; existing callers may see broader result sets — please review any code relying on exact equality."
🤖 Prompt for AI Agents
api/openapi.cloud.yaml (lines 12179-12185) and related spec files were updated
to state "Case-insensitive partial match" but server code still uses equality
predicates (e.g. openmeter/billing/adapter/customeroverride.go:175 uses
dbcustomer.KeyEQ and openmeter/customer/httpdriver/apimapping.go may map query
-> KeyEQ), causing inconsistent behavior; update those server-side mappings to
use the case-insensitive substring predicate (dbcustomer.KeyContainsFold)
wherever the API promises substring matching, adjust any logic that builds
predicates to prefer ContainsFold over EQ for the customer key, run
unit/integration tests, regenerate clients/docs if needed, and add a release
note: "Customer key filter changed from exact match to case-insensitive
substring match; existing callers may see broader result sets — please review
any code relying on exact equality."

Comment on lines 49 to 52
// Filters
if input.Key != nil {
query = query.Where(customerdb.KeyEQ(*input.Key))
query = query.Where(customerdb.KeyContainsFold(*input.Key))
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Guard against empty string: KeyContainsFold("") will match all rows

If clients pass key="" (or only whitespace), KeyContainsFold degrades to a full table match (LIKE '%%'), causing unexpected results and avoidable load. Trim and ignore empty after trim.

Apply this diff within this block:

-			if input.Key != nil {
-				query = query.Where(customerdb.KeyContainsFold(*input.Key))
-			}
+			if input.Key != nil {
+				if trimmed := strings.TrimSpace(*input.Key); trimmed != "" {
+					query = query.Where(customerdb.KeyContainsFold(trimmed))
+				}
+			}

Add the missing import:

 import (
 	"context"
 	"fmt"
 	"time"
 
 	"entgo.io/ent/dialect/sql"
 	"github.com/samber/lo"
+	"strings"
🤖 Prompt for AI Agents
In openmeter/customer/adapter/customer.go around lines 49-52, the filter
currently calls KeyContainsFold on input.Key without trimming or checking for
empty/whitespace which causes KeyContainsFold("") to match all rows; fix by
importing the strings package and, before applying the filter, trim whitespace
from *input.Key and only call query =
query.Where(customerdb.KeyContainsFold(trimmed)) if the trimmed string is
non-empty (i.e., length > 0), otherwise skip adding the filter.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/api release-note/feature Release note: Exciting New Features

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants