Skip to content

fix(customer-portal): CORS, case-search wire format, and case-type handling - #1378

Merged
cloby99 merged 6 commits into
wso2-open-operations:dev-app-csm-portalfrom
Rashmika998:fix/customer-portal-cors-case-search-cleanup
Aug 6, 2026
Merged

cloby99 merged 6 commits into
wso2-open-operations:dev-app-csm-portalfrom
Rashmika998:fix/customer-portal-cors-case-search-cleanup

Conversation

@Rashmika998

@Rashmika998 Rashmika998 commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Summary

entity-service

  • GET /projects/{id}/cases/stats's caseTypes was validated as UUIDs and sysid-converted — a bug, since it's this service's own domain vocabulary (case/service_request/security_report_analysis/announcement/engagement), not an ID of anything. Fixed to validate/translate the same way case search's type filter does.
  • default_case (ServiceNow's raw wire value, and what the production customer-portal frontend actually sends) was rejected outright — this service's own vocabulary uses case instead (tied to the Postgres case_type_enum). Added default_case as an explicit input alias, normalized to case before validation/translation/the Postgres repository ever see it, at every case-type entry point (search, create, stats).
  • Fixed validCaseType and the case-search group-by bucket list, both missing announcement despite the Postgres enum and openapi.yaml already documenting it as valid.

customer-portal backend-v2

  • Added CORS middleware (there was none) — Auth was rejecting every preflight OPTIONS request with 401 (no JWT on a preflight), which browsers report as a CORS error, masking the real cause. Never sets Access-Control-Allow-Credentials (this backend has no cookie-based session to protect).
  • POST /cases/search: entity-service redesigned its case-search filters into a generic predicate array and now rejects the old named-field shape outright. The frontend was never updated, so dto.CaseSearchRequest keeps the old shape as this backend's stable contract, and dto.BuildEntitySearchCasesRequest translates it into entity-service's current contract.
  • 400 responses now surface entity-service's own validation message instead of a generic string; logs include the exact upstream reason.
  • Split the product-consumption service's two independently-configurable base URLs (subscription/license vs usage-tracking); renamed PRODUCT_CONSUMPTION_BASE_URLPRODUCT_CONSUMPTION_SUBSCRIPTION_URL.
  • Fixed a net/http.ServeMux route ambiguity that panicked the server at startup (two case-search-adjacent routes couldn't both register as literal patterns).
  • Removed internal comparisons to the app this replaces from comments/docs throughout — each behavior/rationale is now stated directly as this backend's own design.

Test plan

  • go build ./..., go vet ./..., gofmt -l . clean for both entity-service and apps/customer-portal/backend-v2
  • gosec -fmt=text ./... — 0 issues in both
  • Full go test ./... passes in both, including new regression tests for the CORS middleware, the case-type alias, and the case-search predicate translation

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added expanded case search filters, including project, deployment, severity, assignee, product, tags, and creator-based filtering.
    • Added support for case-type aliases, including default_case, with improved case statistics filtering.
    • Added flexible CORS handling for browser preflight requests.
  • Bug Fixes

    • Improved upstream error reporting, preserving useful validation messages while keeping sensitive authorization errors generic.
    • Made security-report attachments optional where applicable.
  • Documentation

    • Updated API, configuration, and conversation-flow documentation to reflect current behavior and service integrations.

Rashmika998 and others added 2 commits August 5, 2026 23:18
GET /projects/{id}/cases/stats validated caseTypes as UUIDs and converted
them via uuidsToSysids -- a straight bug, since caseTypes is this service's
own domain vocabulary (case/service_request/security_report_analysis/
announcement/engagement), not an ID of anything. Fixed to validate and
translate the same way case search's type filter already does.

Separately, "default_case" -- ServiceNow's own raw caseType wire value, and
the value the production customer-portal frontend actually sends -- was
being rejected outright: this service's own domain vocabulary uses "case"
instead (tied to the Postgres case_type_enum), an inconsistency versus every
other case type value, which maps 1:1 between the domain and SN layers.
Added "default_case" as an explicit input alias, normalized to "case" before
validation/translation/the Postgres repository ever see it, at every entry
point that accepts a case type: case search filters, case creation (both
data sources), and the case-stats endpoint.

Also fixed validCaseType and the case-search group-by bucket list, both of
which were missing "announcement" despite the Postgres enum and openapi.yaml
already documenting it as a valid 5th case type.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…at in backend-v2

- Add CORS middleware, outermost in the chain (wraps Auth). There was no CORS
  handling at all; a preflight OPTIONS request carries no JWT, so Auth was
  rejecting every preflight with 401 before the browser ever saw a CORS
  header -- which the browser reports as "blocked by CORS policy", masking
  the real cause. Deliberately never sets Access-Control-Allow-Credentials:
  this backend authenticates via a caller-supplied header, never cookies, so
  reflecting any Origin back is safe only as long as that stays true.
- Surface entity-service's own validation message on a 400 instead of a
  generic string. internal/entity/client.go was putting entity-service's raw
  {"code","message"} JSON blob into apiErr.Body instead of extracting just
  the message (unlike the registry/usermanagement clients); fixed via a
  shared newUpstreamError helper. Logs now include the exact upstream reason.
- Rebuild POST /cases/search's request handling: entity-service redesigned
  its case-search filters into a generic predicate array and now rejects the
  old named-field shape outright. The frontend was never updated, so
  dto.CaseSearchRequest keeps the old shape as this backend's own stable
  contract, and dto.BuildEntitySearchCasesRequest translates it into
  entity-service's current contract -- the same dto-layer pattern already
  used for every response, just applied to this one request.
- Split the product-consumption service's two independently-configurable
  upstream base URLs (subscription/license vs usage-tracking) instead of
  treating them as one; renamed PRODUCT_CONSUMPTION_BASE_URL to
  PRODUCT_CONSUMPTION_SUBSCRIPTION_URL to match.
- Resolve a route ambiguity that panicked the server at startup: two case
  search filter routes could not both be registered as literal
  net/http.ServeMux patterns; merged under one wildcard pattern with manual
  dispatch.
- Remove internal comparisons to the app this replaces from comments/docs
  throughout; state each behavior/rationale directly as this backend's own
  design.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@Rashmika998, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 42 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 462a3589-0c19-4980-91b4-80cbab8afca1

📥 Commits

Reviewing files that changed from the base of the PR and between fb1a574 and cd48f3e.

📒 Files selected for processing (1)
  • entity-service/openapi.yaml
📝 Walkthrough

Walkthrough

The PR updates customer-portal configuration, CORS handling, case-search translation, upstream error propagation, and API documentation. It also normalizes entity-service case-type aliases and updates ServiceNow case validation and OpenAPI contracts.

Changes

Customer portal case search

Layer / File(s) Summary
Case-search DTO and entity translation
apps/customer-portal/backend-v2/internal/dto/case.go, apps/customer-portal/backend-v2/internal/entity/types.go, apps/customer-portal/backend-v2/internal/handler/cases.go
Adds named portal filters and converts them into generic entity-service predicates. Tests cover filter mapping, pagination, sorting, and CreatedByMe precedence.
Entity-service case types
entity-service/internal/service/*, entity-service/openapi.yaml
Normalizes default_case, validates case types, rejects announcement during creation, and updates ServiceNow mappings and API contracts.

Portal runtime and errors

Layer / File(s) Summary
CORS and product-consumption configuration
apps/customer-portal/backend-v2/cmd/server/main.go, apps/customer-portal/backend-v2/internal/middleware/cors.go, apps/customer-portal/backend-v2/internal/productconsumption/client.go, .env.example
Separates subscription and tracking URLs. Adds CORS preflight handling before authentication. Removes WebSocket origin configuration.
Upstream error handling
apps/customer-portal/backend-v2/internal/apierror/*, internal/entity/client.go, internal/*/client.go, internal/handler/response.go
Centralizes upstream error construction, extracts JSON messages, preserves non-empty 400 bodies, and keeps protected responses generic.

Documentation and API descriptions

Layer / File(s) Summary
Current backend contracts and behavior
apps/customer-portal/backend-v2/CLAUDE.md, README.md, openapi.yaml, asyncapi.yaml, internal/**
Updates route, WebSocket, DTO, middleware, service-integration, response, and wire-format documentation. Removes obsolete backend implementation references.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant PortalClient
  participant CasesHandler
  participant CaseSearchDTO
  participant EntityService
  PortalClient->>CasesHandler: submit case search
  CasesHandler->>CaseSearchDTO: translate named filters
  CaseSearchDTO->>EntityService: send predicates, sorting, and pagination
  EntityService-->>CasesHandler: return case results
  CasesHandler-->>PortalClient: return portal response
Loading

Possibly related PRs

Suggested labels: Area/Backend

Suggested reviewers: cloby99, dilshanfardil

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description explains the main changes and test results but omits most required template sections, including user stories, release note, documentation, security checks, and test environment. Use the repository template and complete all required sections, including purpose, goals, documentation, security checks, automation details, migrations, and test environment.
Docstring Coverage ⚠️ Warning Docstring coverage is 79.03% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main functional changes: CORS, case-search wire-format translation, and case-type handling.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
entity-service/internal/service/case_service.go (1)

48-54: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Don’t expose unsupported announcement creation.

announcement is in validCaseType, so validateCreateCaseRequest accepts it before the Postgres service rejects non-case types. If announcement is only supported for search/stats, exclude it from the create whitelist or route it through a ServiceNow-only create path that already has announcement-specific required fields and payload handling.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@entity-service/internal/service/case_service.go` around lines 48 - 54, Update
validCaseType used by validateCreateCaseRequest to prevent announcement from
being accepted by the Postgres-backed create flow; remove announcement from the
create whitelist unless creation is explicitly routed through an existing
ServiceNow-specific path with its required fields and payload handling.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/customer-portal/backend-v2/asyncapi.yaml`:
- Around line 27-30: Update the UserMessage description to reference obtaining
conversationId from the POST /projects/{id}/conversations creation response or
an existing-conversation lookup, removing the inaccurate reference to the
message POST endpoint while preserving the requirement that conversationId is
provided.

In `@apps/customer-portal/backend-v2/internal/dto/conversation.go`:
- Around line 72-75: Update the conversation state comment near the
status-to-entity mapping to use “abandoned” and “closed” and accurately describe
the map’s enum-string values rather than numeric IDs. If numeric lookup IDs
remain relevant, document them separately; otherwise remove that reference.

In `@apps/customer-portal/backend-v2/internal/handler/response.go`:
- Around line 118-129: The summarizeErr function currently logs apiErr.Body for
every apierror.Error, exposing truncated raw fallback response bodies. Update
summarizeErr to include the body only for the documented entity-service
validation message shape, and otherwise return a summary containing only the
upstream status; preserve the existing generic fallback for non-apierror values.

In `@entity-service/openapi.yaml`:
- Around line 651-659: Add default_case to both OpenAPI enum definitions: the
caseTypes query parameter at entity-service/openapi.yaml lines 651-659 and
CreateCaseRequest.type at lines 6013-6024. Keep both enums synchronized with
runtime validation and the supported portal alias.
- Around line 6014-6024: The CreateCaseRequest attachments schema currently
requires at least one item, conflicting with the optional attachments behavior
for security_report_analysis. Update the attachments definition in
CreateCaseRequest to remove the minimum-item requirement and allow the property
to be omitted or provided as an empty array, while preserving its existing item
validation.

---

Outside diff comments:
In `@entity-service/internal/service/case_service.go`:
- Around line 48-54: Update validCaseType used by validateCreateCaseRequest to
prevent announcement from being accepted by the Postgres-backed create flow;
remove announcement from the create whitelist unless creation is explicitly
routed through an existing ServiceNow-specific path with its required fields and
payload handling.
🪄 Autofix

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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 4f03b4e8-7414-43df-badc-6d7b2839b7e2

📥 Commits

Reviewing files that changed from the base of the PR and between 3289ec1 and c2a2a48.

📒 Files selected for processing (57)
  • apps/customer-portal/backend-v2/.env.example
  • apps/customer-portal/backend-v2/CLAUDE.md
  • apps/customer-portal/backend-v2/README.md
  • apps/customer-portal/backend-v2/asyncapi.yaml
  • apps/customer-portal/backend-v2/cmd/server/main.go
  • apps/customer-portal/backend-v2/internal/aichatagent/client.go
  • apps/customer-portal/backend-v2/internal/aichatagent/types.go
  • apps/customer-portal/backend-v2/internal/aichatagent/ws.go
  • apps/customer-portal/backend-v2/internal/dto/attachment.go
  • apps/customer-portal/backend-v2/internal/dto/case.go
  • apps/customer-portal/backend-v2/internal/dto/case_feedback.go
  • apps/customer-portal/backend-v2/internal/dto/case_test.go
  • apps/customer-portal/backend-v2/internal/dto/case_time_cards.go
  • apps/customer-portal/backend-v2/internal/dto/contacts.go
  • apps/customer-portal/backend-v2/internal/dto/conversation.go
  • apps/customer-portal/backend-v2/internal/dto/deployed_product_metrics.go
  • apps/customer-portal/backend-v2/internal/dto/escalation.go
  • apps/customer-portal/backend-v2/internal/dto/global.go
  • apps/customer-portal/backend-v2/internal/dto/instance.go
  • apps/customer-portal/backend-v2/internal/dto/project_stats.go
  • apps/customer-portal/backend-v2/internal/dto/registry.go
  • apps/customer-portal/backend-v2/internal/dto/time_card.go
  • apps/customer-portal/backend-v2/internal/dto/user.go
  • apps/customer-portal/backend-v2/internal/entity/client.go
  • apps/customer-portal/backend-v2/internal/entity/client_test.go
  • apps/customer-portal/backend-v2/internal/entity/types.go
  • apps/customer-portal/backend-v2/internal/handler/ai_chat.go
  • apps/customer-portal/backend-v2/internal/handler/cases.go
  • apps/customer-portal/backend-v2/internal/handler/contacts.go
  • apps/customer-portal/backend-v2/internal/handler/deployed_products.go
  • apps/customer-portal/backend-v2/internal/handler/instances.go
  • apps/customer-portal/backend-v2/internal/handler/product_consumption.go
  • apps/customer-portal/backend-v2/internal/handler/project_stats.go
  • apps/customer-portal/backend-v2/internal/handler/registry.go
  • apps/customer-portal/backend-v2/internal/handler/response.go
  • apps/customer-portal/backend-v2/internal/handler/response_test.go
  • apps/customer-portal/backend-v2/internal/handler/time_cards.go
  • apps/customer-portal/backend-v2/internal/handler/websocket.go
  • apps/customer-portal/backend-v2/internal/middleware/auth.go
  • apps/customer-portal/backend-v2/internal/middleware/cors.go
  • apps/customer-portal/backend-v2/internal/middleware/cors_test.go
  • apps/customer-portal/backend-v2/internal/productconsumption/client.go
  • apps/customer-portal/backend-v2/internal/productconsumption/subscription.go
  • apps/customer-portal/backend-v2/internal/productconsumption/types.go
  • apps/customer-portal/backend-v2/internal/usermanagement/client.go
  • apps/customer-portal/backend-v2/internal/usermanagement/types.go
  • apps/customer-portal/backend-v2/internal/usermanagement/usermanagement.go
  • apps/customer-portal/backend-v2/openapi.yaml
  • entity-service/CLAUDE.md
  • entity-service/internal/service/case_filters.go
  • entity-service/internal/service/case_filters_test.go
  • entity-service/internal/service/case_service.go
  • entity-service/internal/service/sn_case_service.go
  • entity-service/internal/service/sn_case_service_create_test.go
  • entity-service/internal/service/sn_project_stats_service.go
  • entity-service/internal/service/sn_project_stats_service_test.go
  • entity-service/openapi.yaml

Comment thread apps/customer-portal/backend-v2/asyncapi.yaml
Comment thread apps/customer-portal/backend-v2/internal/dto/conversation.go Outdated
Comment thread apps/customer-portal/backend-v2/internal/handler/response.go
Comment thread entity-service/openapi.yaml Outdated
Comment thread entity-service/openapi.yaml
…gs on PR wso2-open-operations#1378

- asyncapi.yaml: fix a stale UserMessage.conversationId description pointing
  at the follow-up-message endpoint (which requires conversationId, not
  returns one) instead of the actual conversation-creation endpoint.
- dto/conversation.go: fix "abandonded"/"close" typos and remove a numeric
  state-ID list that described a different layer's (entity-service's SN
  translation) internal representation, not this map's actual string values.
- entity/client.go: newUpstreamError no longer falls back to a raw upstream
  body excerpt when the response isn't the documented {"message":...} shape
  -- Body is left empty instead, so summarizeErr's logs and
  mapUpstreamError's 400 passthrough can never surface unbounded,
  non-message upstream content.
- entity-service/openapi.yaml: add the default_case alias to both the
  caseTypes query param and CreateCaseRequest.type enums (the description
  already documented it as accepted, but the enum itself rejected it); drop
  attachments' minItems: 1 to match security_report_analysis's actual
  optional-attachments validation.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

Copilot AI left a comment

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.

Pull request overview

This PR fixes several integration mismatches between the customer-portal backend-v2 and entity-service, focusing on (1) case-type vocabulary/alias handling, (2) adapting to entity-service’s new case-search filter wire format, and (3) enabling browser calls via CORS while improving upstream error surfacing.

Changes:

  • entity-service: Treat case types as domain enums (not UUIDs), add default_case alias normalization, and include missing announcement in validation/group-by/OpenAPI.
  • customer-portal backend-v2: Add CORS middleware and translate the portal’s stable POST /cases/search request shape into entity-service’s predicate-array contract.
  • customer-portal backend-v2: Improve upstream error extraction/logging, split product-consumption base URLs, and fix a ServeMux route ambiguity.

Reviewed changes

Copilot reviewed 57 out of 57 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
entity-service/openapi.yaml Document expanded case-type enums and alias.
entity-service/internal/service/sn_project_stats_service.go Fix caseTypes validation/mapping to domain vocabulary.
entity-service/internal/service/sn_project_stats_service_test.go Regression tests for stats caseTypes behavior.
entity-service/internal/service/sn_case_service.go Add announcement group-by value; normalize type validation call.
entity-service/internal/service/sn_case_service_create_test.go Test default_case alias create-case behavior.
entity-service/internal/service/case_service.go Add alias map + normalization; include announcement.
entity-service/internal/service/case_filters.go Normalize type filter values (alias handling).
entity-service/internal/service/case_filters_test.go Test default_case alias normalization in filters.
entity-service/CLAUDE.md Document enum-alias normalization convention.
apps/customer-portal/backend-v2/README.md Update docs for product-consumption env var rename.
apps/customer-portal/backend-v2/openapi.yaml Remove legacy “Ballerina reference” phrasing in docs.
apps/customer-portal/backend-v2/internal/usermanagement/usermanagement.go Doc cleanup around upstream error passthrough.
apps/customer-portal/backend-v2/internal/usermanagement/types.go Doc cleanup for role conversion helpers.
apps/customer-portal/backend-v2/internal/usermanagement/client.go Doc cleanup for error mapping behavior.
apps/customer-portal/backend-v2/internal/productconsumption/types.go Doc cleanup for wire-format mirroring.
apps/customer-portal/backend-v2/internal/productconsumption/subscription.go Doc cleanup for text payload expectation.
apps/customer-portal/backend-v2/internal/productconsumption/client.go Rename config fields; split subscription vs tracking base URLs.
apps/customer-portal/backend-v2/internal/middleware/cors.go Add CORS middleware with preflight handling.
apps/customer-portal/backend-v2/internal/middleware/cors_test.go Tests for preflight, origins, and credentials header absence.
apps/customer-portal/backend-v2/internal/middleware/auth.go Clarify JWT claim expectations and security headers docs.
apps/customer-portal/backend-v2/internal/handler/websocket.go Doc cleanup re: “wire compatibility” wording.
apps/customer-portal/backend-v2/internal/handler/time_cards.go Doc cleanup for read-only time-card behavior.
apps/customer-portal/backend-v2/internal/handler/response.go Pass through upstream 400 message; enhance log summarization.
apps/customer-portal/backend-v2/internal/handler/response_test.go Tests for 400 pass-through and summarizeErr behavior.
apps/customer-portal/backend-v2/internal/handler/registry.go Doc cleanup for upstream message passthrough and tokenID.
apps/customer-portal/backend-v2/internal/handler/project_stats.go Doc cleanup re: graceful degradation behavior.
apps/customer-portal/backend-v2/internal/handler/product_consumption.go Doc cleanup for authorization gate behavior.
apps/customer-portal/backend-v2/internal/handler/instances.go Doc cleanup for fan-out + DataSource asymmetry.
apps/customer-portal/backend-v2/internal/handler/deployed_products.go Doc cleanup for date range validation and path quirks.
apps/customer-portal/backend-v2/internal/handler/contacts.go Doc cleanup for fixed success response shape.
apps/customer-portal/backend-v2/internal/handler/cases.go Switch search request DTO + translate to entity predicate filters.
apps/customer-portal/backend-v2/internal/handler/ai_chat.go Doc cleanup for endpoint limitations/error handling.
apps/customer-portal/backend-v2/internal/entity/types.go Update entity client types to predicate-array filter contract.
apps/customer-portal/backend-v2/internal/entity/client.go Extract entity-service message field into apierror.Body.
apps/customer-portal/backend-v2/internal/entity/client_test.go Tests for upstream error message extraction behavior.
apps/customer-portal/backend-v2/internal/dto/user.go Doc cleanup for DTO purpose statement.
apps/customer-portal/backend-v2/internal/dto/time_card.go Doc cleanup for hidden fields rationale.
apps/customer-portal/backend-v2/internal/dto/registry.go Doc cleanup for registry naming constraints.
apps/customer-portal/backend-v2/internal/dto/project_stats.go Doc cleanup for mapping/graceful degradation/state IDs.
apps/customer-portal/backend-v2/internal/dto/instance.go Doc cleanup for mapping and DataSource forwarding notes.
apps/customer-portal/backend-v2/internal/dto/global.go Doc cleanup for feature flags and request translation.
apps/customer-portal/backend-v2/internal/dto/escalation.go Doc cleanup for action validation and request injection.
apps/customer-portal/backend-v2/internal/dto/deployed_product_metrics.go Doc cleanup for date-range helpers and response trimming.
apps/customer-portal/backend-v2/internal/dto/conversation.go Doc cleanup for state mapping description.
apps/customer-portal/backend-v2/internal/dto/contacts.go Doc cleanup for email validation constraint statement.
apps/customer-portal/backend-v2/internal/dto/case.go Add portal case-search DTO + translation to entity predicates.
apps/customer-portal/backend-v2/internal/dto/case_time_cards.go Doc cleanup; clarify grouping behavior.
apps/customer-portal/backend-v2/internal/dto/case_test.go Tests for case-search predicate translation.
apps/customer-portal/backend-v2/internal/dto/case_feedback.go Doc cleanup for trimmed emoji mapping.
apps/customer-portal/backend-v2/internal/dto/attachment.go Doc cleanup for passthrough shapes and injection behavior.
apps/customer-portal/backend-v2/internal/aichatagent/ws.go Doc cleanup for WS OAuth2 configuration separation.
apps/customer-portal/backend-v2/internal/aichatagent/types.go Doc cleanup for wire-format mirroring.
apps/customer-portal/backend-v2/internal/aichatagent/client.go Doc cleanup for service description.
apps/customer-portal/backend-v2/cmd/server/main.go Add CORS outer middleware; adjust config/env vars/routes.
apps/customer-portal/backend-v2/CLAUDE.md Update internal architecture docs for new behaviors.
apps/customer-portal/backend-v2/asyncapi.yaml Doc updates reflecting current WebSocket constraints.
apps/customer-portal/backend-v2/.env.example Rename product-consumption env var; remove WS origins var.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread apps/customer-portal/backend-v2/internal/handler/response.go
Comment thread apps/customer-portal/backend-v2/internal/handler/response.go
Comment thread apps/customer-portal/backend-v2/internal/middleware/cors.go
Comment thread apps/customer-portal/backend-v2/cmd/server/main.go
Comment thread apps/customer-portal/backend-v2/cmd/server/main.go
Comment thread apps/customer-portal/backend-v2/cmd/server/main.go
Comment thread apps/customer-portal/backend-v2/cmd/server/main.go
Comment thread apps/customer-portal/backend-v2/internal/dto/case.go
Comment thread apps/customer-portal/backend-v2/internal/handler/response.go
Comment thread entity-service/internal/service/case_service.go
Rashmika998 and others added 2 commits August 6, 2026 11:08
…Vary header

Every upstream client (registry, updates, scim, productconsumption,
aichatagent, usermanagement) built its own non-2xx apierror.Error by falling
back to a raw response excerpt when the body wasn't {"message": "..."}
shaped — the same raw-content-leak risk already fixed for the entity client.
Add apierror.NewUpstreamError as the one shared constructor (Body is the
parsed message, or empty) and route every client through it instead of
duplicating the logic. Also switch cors.go's Vary header to Add so it
doesn't clobber a Vary value a downstream handler already set.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…case creation, fix createdBy filter conflict

validCaseType gaining "announcement" (for case search/stats filters) had the
side effect of also letting POST /cases accept type=announcement, but no
code path builds a valid payload for one: the Postgres path already rejects
every type but "case", and the ServiceNow path silently drops
subject/description since its payload-building switch has no case for it.
Reject it explicitly instead, and stop advertising it as creatable in
openapi.yaml.

Separately, backend-v2's case-search filter builder appended both a
createdBy+in filter (from CreatedBy) and a createdBy+eq filter (from
CreatedByMe) when a client set both — entity-service's filters array is
AND-only, so the two together could never both match, silently returning an
empty result set. CreatedByMe now takes precedence and CreatedBy is dropped
entirely when both are set.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@entity-service/openapi.yaml`:
- Around line 6013-6026: Update the CreateCaseRequest properties block to
declare engagementType alongside the engagement case type, using the exact enum
values accepted by the endpoint’s runtime validation. Ensure the field is
modeled with the same required/optional behavior and schema type as runtime
validation, so generated clients can construct valid engagement requests while
preserving existing case types.
🪄 Autofix

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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: f980c87e-f737-4024-9b4a-e12f326ff80f

📥 Commits

Reviewing files that changed from the base of the PR and between 9e1f2c7 and fb1a574.

📒 Files selected for processing (17)
  • apps/customer-portal/backend-v2/CLAUDE.md
  • apps/customer-portal/backend-v2/internal/aichatagent/client.go
  • apps/customer-portal/backend-v2/internal/apierror/apierror.go
  • apps/customer-portal/backend-v2/internal/apierror/apierror_test.go
  • apps/customer-portal/backend-v2/internal/dto/case.go
  • apps/customer-portal/backend-v2/internal/dto/case_test.go
  • apps/customer-portal/backend-v2/internal/entity/client.go
  • apps/customer-portal/backend-v2/internal/middleware/cors.go
  • apps/customer-portal/backend-v2/internal/productconsumption/client.go
  • apps/customer-portal/backend-v2/internal/registry/client.go
  • apps/customer-portal/backend-v2/internal/scim/client.go
  • apps/customer-portal/backend-v2/internal/updates/client.go
  • apps/customer-portal/backend-v2/internal/usermanagement/client.go
  • apps/customer-portal/backend-v2/internal/usermanagement/usermanagement.go
  • entity-service/internal/service/case_service.go
  • entity-service/internal/service/sn_case_service_create_test.go
  • entity-service/openapi.yaml
🚧 Files skipped from review as they are similar to previous changes (8)
  • apps/customer-portal/backend-v2/internal/aichatagent/client.go
  • apps/customer-portal/backend-v2/internal/entity/client.go
  • entity-service/internal/service/sn_case_service_create_test.go
  • apps/customer-portal/backend-v2/internal/middleware/cors.go
  • apps/customer-portal/backend-v2/internal/dto/case.go
  • apps/customer-portal/backend-v2/internal/dto/case_test.go
  • apps/customer-portal/backend-v2/internal/productconsumption/client.go
  • apps/customer-portal/backend-v2/CLAUDE.md

Comment thread entity-service/openapi.yaml
The engagement case type's own description already said it requires
engagementType, and the Go validation enforces it, but the OpenAPI schema
never declared the property -- generated clients had no way to model it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@cloby99
cloby99 merged commit 8bc8550 into wso2-open-operations:dev-app-csm-portal Aug 6, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants