Skip to content

Add localized client metadata support for applications and DCR#2286

Merged
ThaminduDilshan merged 1 commit intoasgardeo:mainfrom
nandhu-kumar:main-local-2106
Apr 30, 2026
Merged

Add localized client metadata support for applications and DCR#2286
ThaminduDilshan merged 1 commit intoasgardeo:mainfrom
nandhu-kumar:main-local-2106

Conversation

@nandhu-kumar
Copy link
Copy Markdown
Contributor

@nandhu-kumar nandhu-kumar commented Apr 9, 2026

fixes #2106

Purpose

OAuth 2.0 Dynamic Client Registration (RFC 7591) requires clients to register localized metadata
variants using OIDC language-tagged fields (e.g. "client_name#fr": "Mon Client"). Previously,
Thunder's DCR endpoint ignored these fields entirely, meaning clients could not register
language-specific display names, logo URIs, terms-of-service, or policy URIs.

This PR adds full support for OIDC language-tagged DCR metadata fields.

Approach

Parsing language-tagged fields (RFC 7591 §2.1)

DCRRegistrationRequest.UnmarshalJSON now scans all top-level JSON keys for the field#lang-tag
pattern. Valid BCP 47 tags (normalised via golang.org/x/text/language) are extracted into four
typed maps: LocalizedClientName, LocalizedLogoURI, LocalizedTosURI, LocalizedPolicyURI.
Invalid tags are rejected immediately with a 400 error before any storage occurs.

DCRRegistrationResponse.MarshalJSON serializes those maps back as top-level #-keyed keys so
clients receive the echoed variants in the 201 response.

Persisting to i18n store (transaction limitation + compensation)

The DCR outer transactioner operates on the runtime DB, while both the application store and i18n
store use configDB. Because of this mismatch, they cannot participate in the same transaction.

Localized variants are written to the i18n store after the application record commits. On write
failure, a compensation path cleans up any partial i18n rows and deletes the newly-created
application, maintaining consistency without distributed transactions.

Each app's translations are stored under the namespace app.<id> with keys client_name,
logo_uri, tos_uri, policy_uri.

i18n integration

Added SetTranslationOverridesForNamespace to perform bulk writes of localized variants during DCR
registration, reducing multiple DB calls into a single operation.

A new GetTranslationsByNamespace method on I18nServiceInterface fetches all locale rows for a
namespace in a single query, avoiding the N+1 pattern. This is used to support localized metadata
handling within the DCR flow.

Cleanup on application deletion

The existing deleteLocalizedVariants call in the application service lifecycle ensures i18n rows
are cleaned up when an application is deleted.

Related Issues

Related PRs

  • N/A

Checklist

  • Followed the contribution guidelines.
  • Manual test round performed and verified.
  • Documentation provided. (Add links if there are any)
    • Ran Vale and fixed all errors and warnings
  • Tests provided.
    • Unit Tests — backend/internal/oauth/oauth2/dcr/service_test.go: covering
      RegisterClient with localized variants, i18n write failure compensation, and related scenarios
    • Integration Tests — tests/integration/oauth/dcr/dcr_test.go: register with localized
      fields (assert echoed in response), invalid BCP 47 tag rejection (400)
  • Breaking changes. (Fill if applicable)
    • Breaking changes section filled.
    • breaking change label added.

Security checks

  • Followed secure coding standards in WSO2 Secure Coding Guidelines
  • Confirmed that this PR doesn't commit any secrets.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 9, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR adds BCP47-tagged localized client metadata to DCR flows, threads an i18nService dependency through initialization, persists localized fields via the i18n subsystem with transactional compensation on failure, and extends the i18n service/store APIs and resolution semantics (exact-match for non-system namespaces).

Changes

Cohort / File(s) Summary
Initialization / Wiring
backend/cmd/server/servicemanager.go, backend/internal/application/init.go, backend/internal/application/init_test.go, backend/internal/oauth/init.go
Thread i18nService through application and oauth initializers; update tests to pass nil where appropriate.
DCR Init & Constructor
backend/internal/oauth/oauth2/dcr/init.go, backend/internal/oauth/oauth2/dcr/init_test.go
Add i18nService parameter to DCR initializer and update tests to include trailing nil arg.
DCR Models (request/response)
backend/internal/oauth/oauth2/dcr/model.go, backend/internal/oauth/oauth2/dcr/model_test.go, tests/integration/oauth/dcr/model.go
Add localized maps for client_name/logo_uri/tos_uri/policy_uri; implement custom Unmarshal/Marshal to parse/emit field#<tag> keys with BCP47 normalization and variant caps; add comprehensive tests.
DCR Service Logic
backend/internal/oauth/oauth2/dcr/service.go, backend/internal/oauth/oauth2/dcr/service_test.go, tests/integration/oauth/dcr/dcr_test.go
Inject i18nService; persist localized variants after transaction commit; implement write validation, compensation (delete translations + delete application) on failure; extend unit/integration tests for success/failure paths and validations.
Application Service i18n integration
backend/internal/application/service.go, backend/internal/application/service_test.go
Store i18nService on application service, add AppI18nNamespace, call deletion of localized variants during DeleteApplication, and add tests.
i18n Core: API, store, constants
backend/internal/system/i18n/mgt/constants.go, .../service.go, .../store.go, .../store_constants.go, .../file_based_store.go
Allow dots in namespace regex; add NormaliseBCP47Tag and MaxBCP47TagLength; add DeleteTranslationsByNamespace, DeleteTranslationsByNamespaceAndKey, and GetTranslationsByNamespace to service/store; add DB queries for deletions; file-based store returns unsupported for deletions; change non-system namespace resolution to exact-match.
i18n Mocks & Tests
backend/internal/system/i18n/mgt/I18nServiceInterface_mock_test.go, .../i18nStoreInterface_mock_test.go, .../service_test.go, .../store_test.go, .../file_based_store_test.go
Add mock methods and extensive unit tests covering normalization, exact-match behavior, get/delete APIs, and error mappings.
Other small updates
backend/internal/application/init_test.go, various test updates
Add nil args at new initializer call sites; small test harness updates.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant DCR as DCR Service
    participant DB as Database<br/>(Transaction)
    participant I18n as I18n Service
    participant AppSvc as Application Service

    Client->>DCR: POST RegisterClient (body includes localized fields)
    DCR->>DB: Begin transaction / CreateApplication
    DB-->>AppSvc: appID (within tx)
    DB->>DB: Commit
    DCR->>I18n: For each localized field -> SetTranslationOverrideForKey(namespace, key, lang, value)
    alt i18n writes succeed
        I18n-->>DCR: ok
        DCR->>Client: 201 Created (response includes localized maps)
    else i18n write failure
        I18n-->>DCR: error
        DCR->>I18n: DeleteTranslationsByNamespace(namespace)  -- compensation
        DCR->>AppSvc: DeleteApplication(appID)               -- compensation
        DCR->>Client: 500 Server Error (mapped from i18n error)
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related issues

Possibly related PRs

Suggested labels

breaking change

Suggested reviewers

  • rajithacharith
  • ThaminduDilshan
  • thiva-k
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 93.33% which is sufficient. The required threshold is 80.00%.
Description check ✅ Passed The PR description is comprehensive and follows the template structure with clear Purpose, Approach, Related Issues, and Checklist sections.
Title check ✅ Passed The PR title clearly and accurately summarizes the main objective: adding localized client metadata support for applications and DCR.

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

✨ 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 and usage tips.

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 9, 2026

Codecov Report

❌ Patch coverage is 78.87789% with 64 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.27%. Comparing base (4903719) to head (206b8b2).
⚠️ Report is 4 commits behind head on main.

Files with missing lines Patch % Lines
backend/internal/system/i18n/mgt/service.go 70.31% 10 Missing and 9 partials ⚠️
backend/internal/application/service.go 57.14% 13 Missing and 5 partials ⚠️
backend/internal/oauth/oauth2/dcr/service.go 86.41% 6 Missing and 5 partials ⚠️
backend/internal/oauth/oauth2/dcr/model.go 83.33% 5 Missing and 5 partials ⚠️
backend/internal/system/i18n/mgt/store.go 84.00% 2 Missing and 2 partials ⚠️
...ckend/internal/system/i18n/mgt/file_based_store.go 66.66% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2286      +/-   ##
==========================================
- Coverage   86.29%   86.27%   -0.02%     
==========================================
  Files         916      919       +3     
  Lines       65513    65806     +293     
==========================================
+ Hits        56532    56772     +240     
- Misses       6900     6927      +27     
- Partials     2081     2107      +26     
Flag Coverage Δ
backend-integration-postgres 51.74% <54.78%> (+0.04%) ⬆️
backend-integration-redis 51.39% <54.78%> (+0.05%) ⬆️
backend-integration-sqlite 52.25% <54.78%> (+0.05%) ⬆️
backend-unit 79.96% <66.33%> (-0.07%) ⬇️
frontend-apps-console-unit 85.72% <ø> (+<0.01%) ⬆️
frontend-apps-gate-unit 97.35% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ 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.

@nandhu-kumar
Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 9, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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

🧹 Nitpick comments (1)
backend/internal/oauth/oauth2/dcr/handler.go (1)

92-98: Consider logging server errors for the GET endpoint.

Per repository conventions, server errors (HTTP 500) should be logged at the handler layer. The current implementation logs via writeServiceErrorResponse for generic errors, but the 404 path bypasses this. This is acceptable since 404 is a client error, but consider adding logging for unexpected server-type errors before returning 404:

if svcErr.Code == ErrorClientNotFound.Code {
    sysutils.WriteJSONError(w, svcErr.Code, svcErr.ErrorDescription, http.StatusNotFound, nil)
    return
}
if svcErr.Type == serviceerror.ServerErrorType {
    logger := log.GetLogger().With(log.String(log.LoggerKeyComponentName, "DCRHandler"))
    logger.Error("Internal server error processing DCR GET request",
        log.String("app_id", appID),
        log.String("error_code", svcErr.Code),
    )
}
dh.writeServiceErrorResponse(w, svcErr)

This mirrors the logging pattern in HandleDCRRegistration.

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

In `@backend/internal/oauth/oauth2/dcr/handler.go` around lines 92 - 98, The GET
handler currently returns 404 for ErrorClientNotFound but doesn't log
server-type errors; update the svcErr handling in HandleDCRGet (handler.go) to
keep the existing 404 path, and before calling dh.writeServiceErrorResponse(w,
svcErr) add a check if svcErr.Type == serviceerror.ServerErrorType then create a
logger via log.GetLogger().With(log.String(log.LoggerKeyComponentName,
"DCRHandler")) and call logger.Error with a brief message like "Internal server
error processing DCR GET request" including appID and svcErr.Code; this mirrors
the logging pattern used in HandleDCRRegistration.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@backend/cmd/server/servicemanager.go`:
- Around line 269-270: Add documentation for the new public OAuth2 DCR read
endpoint introduced by oauth.Initialize: document the GET
/oauth2/dcr/register/{app_id} endpoint in docs (e.g., docs/content/apis.mdx or a
dedicated DCR guide), include request/response examples showing localized fields
using the `#` suffix (e.g., `client_name#fr`), specify the 404 response when a
client is not found, and link or reference the OAuth2 DCR behavior so consumers
of the API understand usage and error handling.

In `@backend/internal/oauth/oauth2/dcr/handler.go`:
- Around line 76-102: Add API docs for the new GET /oauth2/dcr/register/{app_id}
endpoint implemented by HandleDCRGetClient: create/update the relevant docs/*
API reference page to describe the endpoint path, HTTP method, authorization
requirements (same as DCR registration), request parameters (path param app_id),
full response schema including localized variant fields like client_name#<lang>
and logo_uri#<lang>, and list possible error responses (400 Invalid Request
Format, 401 Unauthorized when DCR auth fails, 404 Client Not Found) with
examples; ensure the response examples match the service return shape produced
by dh.dcrService.GetClient and add any necessary schema definitions and
cross-references used by the existing DCR docs.

In `@backend/internal/oauth/oauth2/dcr/service.go`:
- Around line 44-46: Add documentation for the new GET
/oauth2/dcr/register/{app_id} endpoint and the extended DCR request/response
schema that now supports language-tagged metadata keys (e.g.,
client_name#<lang>, logo_uri#<lang>, tos_uri#<lang>, policy_uri#<lang>); update
the API reference entry to include the new endpoint, request/response examples
showing localized keys, and expected error cases, and add or update the DCR
guide to describe how localized metadata is chosen/merged, validation rules, and
sample payloads so callers of GetClient and the DCR registration flow know how
to produce and consume the localized fields.
- Around line 381-398: The code currently ignores errors from
ds.i18nService.GetTranslationsByNamespace, causing GetClient to return success
while localized metadata is missing; update the GetClient implementation (the
block using ds.i18nService and calling GetTranslationsByNamespace) to handle
i18nErr explicitly by returning or propagating an error (wrap with context like
"failed to load localized metadata for app <appID>") instead of silently
skipping, so callers see a failure when translations can't be read; ensure you
reference ds.i18nService, GetTranslationsByNamespace, and the GetClient response
handling
(response.LocalizedClientName/LocalizedLogoURI/LocalizedTosURI/LocalizedPolicyURI)
when making this change.

---

Nitpick comments:
In `@backend/internal/oauth/oauth2/dcr/handler.go`:
- Around line 92-98: The GET handler currently returns 404 for
ErrorClientNotFound but doesn't log server-type errors; update the svcErr
handling in HandleDCRGet (handler.go) to keep the existing 404 path, and before
calling dh.writeServiceErrorResponse(w, svcErr) add a check if svcErr.Type ==
serviceerror.ServerErrorType then create a logger via
log.GetLogger().With(log.String(log.LoggerKeyComponentName, "DCRHandler")) and
call logger.Error with a brief message like "Internal server error processing
DCR GET request" including appID and svcErr.Code; this mirrors the logging
pattern used in HandleDCRRegistration.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f6e749e4-3b4f-49c2-92d2-4450aad3397f

📥 Commits

Reviewing files that changed from the base of the PR and between de930f4 and 7cd46ba.

⛔ Files ignored due to path filters (2)
  • backend/tests/mocks/i18n/mgtmock/I18nServiceInterface_mock.go is excluded by !**/*_mock.go
  • backend/tests/mocks/i18n/mgtmock/i18nStoreInterface_mock.go is excluded by !**/*_mock.go
📒 Files selected for processing (22)
  • backend/cmd/server/servicemanager.go
  • backend/internal/application/init.go
  • backend/internal/application/init_test.go
  • backend/internal/application/service.go
  • backend/internal/oauth/init.go
  • backend/internal/oauth/oauth2/dcr/DCRServiceInterface_mock_test.go
  • backend/internal/oauth/oauth2/dcr/error_constants.go
  • backend/internal/oauth/oauth2/dcr/handler.go
  • backend/internal/oauth/oauth2/dcr/init.go
  • backend/internal/oauth/oauth2/dcr/init_test.go
  • backend/internal/oauth/oauth2/dcr/model.go
  • backend/internal/oauth/oauth2/dcr/service.go
  • backend/internal/oauth/oauth2/dcr/service_test.go
  • backend/internal/system/i18n/mgt/I18nServiceInterface_mock_test.go
  • backend/internal/system/i18n/mgt/constants.go
  • backend/internal/system/i18n/mgt/file_based_store.go
  • backend/internal/system/i18n/mgt/i18nStoreInterface_mock_test.go
  • backend/internal/system/i18n/mgt/service.go
  • backend/internal/system/i18n/mgt/store.go
  • backend/internal/system/i18n/mgt/store_constants.go
  • tests/integration/oauth/dcr/dcr_test.go
  • tests/integration/oauth/dcr/model.go

Comment thread backend/cmd/server/servicemanager.go Outdated
Comment thread backend/internal/oauth/oauth2/dcr/handler.go Outdated
Comment thread backend/internal/oauth/oauth2/dcr/service.go Outdated
Comment thread backend/internal/oauth/oauth2/dcr/service.go Outdated
@nandhu-kumar
Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 15, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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: 2

🧹 Nitpick comments (1)
backend/internal/oauth/oauth2/dcr/service.go (1)

149-160: Keep 500 logging in the handler, not the service.

These new logger.Error calls will double-log the same server failure once the handler writes the 500. Return the ServiceError here and let the DCR handlers own the error log.

Based on learnings, "ensure server (HTTP 500/InternalServerError) errors are logged at the handler layer, while services return a ServiceError without logging."

Also applies to: 335-337

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

In `@backend/internal/oauth/oauth2/dcr/service.go` around lines 149 - 160, The
service currently logs internal errors (logger.Error) during i18n write
compensation and delete failures inside the DCR service method; remove these
logger.Error calls and instead return a ServiceError (or wrap the original
error) from the method so the DCR handlers can log the 500. Specifically, in the
block that calls
ds.i18nService.DeleteTranslationsByNamespace("app."+createdAppID) and
ds.appService.DeleteApplication(ctx, createdAppID) remove the logger.Error
invocations and ensure the function returns a ServiceError containing the
underlying error (preserving context like createdAppID) for the handler to log;
apply the same change to the other similar logging at the referenced lines
(335-337).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@backend/internal/oauth/oauth2/dcr/handler.go`:
- Around line 91-98: HandleDCRGetClient is missing server-side logging when
dh.dcrService.GetClient returns a non-not-found error; mirror the pattern used
in HandleDCRRegistration by logging the svcErr before responding. Modify the
error branch in HandleDCRGetClient: after detecting svcErr and before calling
dh.writeServiceErrorResponse (and in the not-found branch if desired), call the
handler's logger to log svcErr (include svcErr.Code and svcErr.ErrorDescription
or the whole error) so failures from dh.dcrService.GetClient are recorded;
ensure you reference dh.dcrService.GetClient, svcErr, HandleDCRGetClient and
dh.writeServiceErrorResponse when locating the change.

In `@backend/internal/oauth/oauth2/dcr/service.go`:
- Around line 340-345: The code assumes the OAuth entry lives at
app.InboundAuthConfig[0]; instead iterate the app.InboundAuthConfig slice to
find the element whose OAuthAppConfig is non-nil, assign that to oauthCfg, and
only if none found return &ErrorClientNotFound; then compute scopeString from
oauthCfg.Scopes as before. Update references to
app.InboundAuthConfig[0].OAuthAppConfig, oauthCfg, and scopeString accordingly
so the logic works regardless of entry order.

---

Nitpick comments:
In `@backend/internal/oauth/oauth2/dcr/service.go`:
- Around line 149-160: The service currently logs internal errors (logger.Error)
during i18n write compensation and delete failures inside the DCR service
method; remove these logger.Error calls and instead return a ServiceError (or
wrap the original error) from the method so the DCR handlers can log the 500.
Specifically, in the block that calls
ds.i18nService.DeleteTranslationsByNamespace("app."+createdAppID) and
ds.appService.DeleteApplication(ctx, createdAppID) remove the logger.Error
invocations and ensure the function returns a ServiceError containing the
underlying error (preserving context like createdAppID) for the handler to log;
apply the same change to the other similar logging at the referenced lines
(335-337).
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a3364a99-84b2-4ddd-b928-3d4b6cd881bb

📥 Commits

Reviewing files that changed from the base of the PR and between 7cd46ba and 27d9609.

⛔ Files ignored due to path filters (2)
  • backend/tests/mocks/i18n/mgtmock/I18nServiceInterface_mock.go is excluded by !**/*_mock.go
  • backend/tests/mocks/i18n/mgtmock/i18nStoreInterface_mock.go is excluded by !**/*_mock.go
📒 Files selected for processing (20)
  • backend/cmd/server/servicemanager.go
  • backend/internal/application/init.go
  • backend/internal/application/init_test.go
  • backend/internal/application/service.go
  • backend/internal/oauth/init.go
  • backend/internal/oauth/oauth2/dcr/DCRServiceInterface_mock_test.go
  • backend/internal/oauth/oauth2/dcr/error_constants.go
  • backend/internal/oauth/oauth2/dcr/handler.go
  • backend/internal/oauth/oauth2/dcr/init.go
  • backend/internal/oauth/oauth2/dcr/init_test.go
  • backend/internal/oauth/oauth2/dcr/model.go
  • backend/internal/oauth/oauth2/dcr/service.go
  • backend/internal/oauth/oauth2/dcr/service_test.go
  • backend/internal/system/i18n/mgt/I18nServiceInterface_mock_test.go
  • backend/internal/system/i18n/mgt/constants.go
  • backend/internal/system/i18n/mgt/file_based_store.go
  • backend/internal/system/i18n/mgt/i18nStoreInterface_mock_test.go
  • backend/internal/system/i18n/mgt/service.go
  • backend/internal/system/i18n/mgt/store.go
  • backend/internal/system/i18n/mgt/store_constants.go
✅ Files skipped from review due to trivial changes (2)
  • backend/internal/oauth/oauth2/dcr/error_constants.go
  • backend/internal/system/i18n/mgt/store_constants.go
🚧 Files skipped from review as they are similar to previous changes (8)
  • backend/internal/oauth/oauth2/dcr/init_test.go
  • backend/internal/oauth/init.go
  • backend/internal/application/init_test.go
  • backend/internal/application/init.go
  • backend/internal/system/i18n/mgt/constants.go
  • backend/internal/oauth/oauth2/dcr/service_test.go
  • backend/internal/oauth/oauth2/dcr/DCRServiceInterface_mock_test.go
  • backend/internal/system/i18n/mgt/i18nStoreInterface_mock_test.go

Comment thread backend/internal/oauth/oauth2/dcr/handler.go Outdated
Comment thread backend/internal/oauth/oauth2/dcr/service.go Outdated
@nandhu-kumar
Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 15, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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

♻️ Duplicate comments (1)
backend/internal/oauth/oauth2/dcr/handler.go (1)

76-110: ⚠️ Potential issue | 🟠 Major

🔴 Documentation Required: This PR introduces a user-facing change (the new GET /oauth2/dcr/register/{app_id} endpoint plus language-tagged DCR metadata fields like client_name#<lang>, logo_uri#<lang>, tos_uri#<lang>, and policy_uri#<lang>) but does not include corresponding documentation updates under docs/. Please update the API reference for the new GET route and the DCR docs for the request/response schema, auth requirements, and 400/401/404 responses before merging. docs/content/apis.mdx and the DCR guide under docs/content/guides/ are the likely places.

As per coding guidelines, "🔴 Documentation Required: This PR introduces a user-facing change (e.g., new/modified API endpoint, configuration option, authentication flow, or SDK behavior) but does not include corresponding documentation updates under docs/."

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

In `@backend/internal/oauth/oauth2/dcr/handler.go` around lines 76 - 110, Add
documentation for the new GET /oauth2/dcr/register/{app_id} endpoint introduced
by HandleDCRGetClient: update the API reference and the DCR guide to describe
the route, authentication requirements (when DCR.Insecure is false),
request/response schema including localized metadata fields client_name#<lang>,
logo_uri#<lang>, tos_uri#<lang>, policy_uri#<lang>, and example responses for
200, 400 (invalid request format), 401 (auth failure), and 404
(ErrorClientNotFound). Ensure the docs mention the possible server error path
(serviceerror.ServerErrorType) and include a minimal example curl request and
JSON response to show the language-tagged fields.
🧹 Nitpick comments (1)
backend/internal/oauth/oauth2/dcr/service.go (1)

144-168: Verify compensation atomicity on partial i18n write failure.

The compensation logic deletes i18n rows and then the created application on write failure. However, if the i18n write partially succeeds (e.g., writes 2 of 4 localized fields before failing), DeleteTranslationsByNamespace should clean up all partial rows. This looks correct since it deletes by namespace rather than individual keys.

One edge case: if ds.i18nService.DeleteTranslationsByNamespace itself fails (line 152-155), the code logs but continues to delete the app. This could leave orphaned i18n rows if both the cleanup and app deletion succeed partially. Consider whether this is acceptable or if the app deletion should be skipped when cleanup fails to maintain referential integrity.

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

In `@backend/internal/oauth/oauth2/dcr/service.go` around lines 144 - 168, The
compensation path after writeLocalizedVariants may leave orphaned i18n rows
because you currently log a DeleteTranslationsByNamespace failure and still
proceed to DeleteApplication; change the flow in the DCR service: in the block
following writeLocalizedVariants (the code using ds.writeLocalizedVariants,
ds.i18nService.DeleteTranslationsByNamespace, and
ds.appService.DeleteApplication), if
ds.i18nService.DeleteTranslationsByNamespace returns an error, log it and abort
further compensation (do not call ds.appService.DeleteApplication) and return an
appropriate server error; only call ds.appService.DeleteApplication when i18n
cleanup succeeded (or when ds.i18nService is nil), ensuring you reference the
same symbols (writeLocalizedVariants,
ds.i18nService.DeleteTranslationsByNamespace, ds.appService.DeleteApplication,
and ErrorServerError) to locate where to change control flow.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/integration/oauth/dcr/model.go`:
- Around line 96-137: The UnmarshalJSON for DCRRegistrationResponse currently
appends into existing LocalizedClientName, LocalizedLogoURI, LocalizedTosURI,
and LocalizedPolicyURI maps so reused instances retain stale entries; modify
UnmarshalJSON (method name UnmarshalJSON on type DCRRegistrationResponse) to
reset those localized maps before parsing the raw keys (e.g., set
r.LocalizedClientName, r.LocalizedLogoURI, r.LocalizedTosURI,
r.LocalizedPolicyURI to nil or make(map[string]string) at the top of the method
before the loop) so only keys present in the current payload are kept.

---

Duplicate comments:
In `@backend/internal/oauth/oauth2/dcr/handler.go`:
- Around line 76-110: Add documentation for the new GET
/oauth2/dcr/register/{app_id} endpoint introduced by HandleDCRGetClient: update
the API reference and the DCR guide to describe the route, authentication
requirements (when DCR.Insecure is false), request/response schema including
localized metadata fields client_name#<lang>, logo_uri#<lang>, tos_uri#<lang>,
policy_uri#<lang>, and example responses for 200, 400 (invalid request format),
401 (auth failure), and 404 (ErrorClientNotFound). Ensure the docs mention the
possible server error path (serviceerror.ServerErrorType) and include a minimal
example curl request and JSON response to show the language-tagged fields.

---

Nitpick comments:
In `@backend/internal/oauth/oauth2/dcr/service.go`:
- Around line 144-168: The compensation path after writeLocalizedVariants may
leave orphaned i18n rows because you currently log a
DeleteTranslationsByNamespace failure and still proceed to DeleteApplication;
change the flow in the DCR service: in the block following
writeLocalizedVariants (the code using ds.writeLocalizedVariants,
ds.i18nService.DeleteTranslationsByNamespace, and
ds.appService.DeleteApplication), if
ds.i18nService.DeleteTranslationsByNamespace returns an error, log it and abort
further compensation (do not call ds.appService.DeleteApplication) and return an
appropriate server error; only call ds.appService.DeleteApplication when i18n
cleanup succeeded (or when ds.i18nService is nil), ensuring you reference the
same symbols (writeLocalizedVariants,
ds.i18nService.DeleteTranslationsByNamespace, ds.appService.DeleteApplication,
and ErrorServerError) to locate where to change control flow.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6e737fec-10e9-48a4-b4ad-254676658cb7

📥 Commits

Reviewing files that changed from the base of the PR and between 27d9609 and fe54da6.

⛔ Files ignored due to path filters (2)
  • backend/tests/mocks/i18n/mgtmock/I18nServiceInterface_mock.go is excluded by !**/*_mock.go
  • backend/tests/mocks/i18n/mgtmock/i18nStoreInterface_mock.go is excluded by !**/*_mock.go
📒 Files selected for processing (28)
  • backend/cmd/server/servicemanager.go
  • backend/internal/application/init.go
  • backend/internal/application/init_test.go
  • backend/internal/application/service.go
  • backend/internal/application/service_test.go
  • backend/internal/oauth/init.go
  • backend/internal/oauth/oauth2/dcr/DCRServiceInterface_mock_test.go
  • backend/internal/oauth/oauth2/dcr/error_constants.go
  • backend/internal/oauth/oauth2/dcr/handler.go
  • backend/internal/oauth/oauth2/dcr/handler_test.go
  • backend/internal/oauth/oauth2/dcr/init.go
  • backend/internal/oauth/oauth2/dcr/init_test.go
  • backend/internal/oauth/oauth2/dcr/model.go
  • backend/internal/oauth/oauth2/dcr/model_test.go
  • backend/internal/oauth/oauth2/dcr/service.go
  • backend/internal/oauth/oauth2/dcr/service_test.go
  • backend/internal/system/i18n/mgt/I18nServiceInterface_mock_test.go
  • backend/internal/system/i18n/mgt/constants.go
  • backend/internal/system/i18n/mgt/file_based_store.go
  • backend/internal/system/i18n/mgt/file_based_store_test.go
  • backend/internal/system/i18n/mgt/i18nStoreInterface_mock_test.go
  • backend/internal/system/i18n/mgt/service.go
  • backend/internal/system/i18n/mgt/service_test.go
  • backend/internal/system/i18n/mgt/store.go
  • backend/internal/system/i18n/mgt/store_constants.go
  • backend/internal/system/i18n/mgt/store_test.go
  • tests/integration/oauth/dcr/dcr_test.go
  • tests/integration/oauth/dcr/model.go
✅ Files skipped from review due to trivial changes (5)
  • backend/internal/oauth/oauth2/dcr/error_constants.go
  • backend/internal/system/i18n/mgt/file_based_store.go
  • backend/internal/application/init_test.go
  • backend/internal/system/i18n/mgt/store_constants.go
  • backend/internal/application/service_test.go
🚧 Files skipped from review as they are similar to previous changes (8)
  • backend/cmd/server/servicemanager.go
  • backend/internal/application/init.go
  • backend/internal/oauth/init.go
  • backend/internal/system/i18n/mgt/constants.go
  • backend/internal/oauth/oauth2/dcr/init.go
  • backend/internal/oauth/oauth2/dcr/init_test.go
  • backend/internal/oauth/oauth2/dcr/DCRServiceInterface_mock_test.go
  • backend/internal/oauth/oauth2/dcr/service_test.go

Comment thread tests/integration/oauth/dcr/model.go
@nandhu-kumar
Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 15, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@nandhu-kumar nandhu-kumar changed the title WIP - Add localized client metadata support for applications and DCR Draft - Add localized client metadata support for applications and DCR Apr 15, 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

♻️ Duplicate comments (1)
backend/cmd/server/servicemanager.go (1)

269-270: ⚠️ Potential issue | 🟠 Major

🔴 Documentation Required: This PR introduces a user-facing change but does not include corresponding documentation updates under docs/.
Please document GET /oauth2/dcr/register/{app_id} and the new localized DCR metadata keys (client_name#<lang>, logo_uri#<lang>, tos_uri#<lang>, policy_uri#<lang>), including the 400 invalid-language-tag and 404 not-found cases, in docs/content/apis.mdx and the DCR guide before merge.

As per coding guidelines, "🔴 Documentation Required: This PR introduces a user-facing change (e.g., new/modified API endpoint, configuration option, authentication flow, or SDK behavior) but does not include corresponding documentation updates under docs/. Please update the relevant documentation before merging."

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

In `@backend/cmd/server/servicemanager.go` around lines 269 - 270, Add user-facing
documentation for the new OAuth DCR endpoint and localized metadata: document
the GET /oauth2/dcr/register/{app_id} endpoint (purpose, request/response,
status codes), list the new localized DCR metadata keys (client_name#<lang>,
logo_uri#<lang>, tos_uri#<lang>, policy_uri#<lang>), and explicitly document the
400 invalid-language-tag and 404 not-found error cases; add these entries to the
API reference (apis.mdx) and the Dynamic Client Registration guide so the new
behavior is fully described before merging.
🧹 Nitpick comments (1)
backend/internal/system/i18n/mgt/service.go (1)

257-276: TotalResults may be misleading after filtering.

Line 285 sets TotalResults: len(allTranslations), but for non-system namespaces with exact-match logic, some entries may be skipped (lines 274-276), causing TotalResults to exceed the actual number of entries in the result map.

Consider whether this is intentional (total stored vs. total returned) or if it should reflect the filtered count.

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

In `@backend/internal/system/i18n/mgt/service.go` around lines 257 - 276, The
reported TotalResults uses len(allTranslations) which can be larger than the
actually returned entries because non-system namespaces use exactLanguageMatch
and some translations are skipped (compositeKey, allTranslations, translation,
selectBestTranslation, exactLanguageMatch). Change TotalResults to reflect the
filtered/returned count by computing the length of the results map after the
loop (or incrementing a counter when you add a translation.Value to the result)
instead of using len(allTranslations), or if you intentionally want stored vs
returned semantics, explicitly include both a StoredTotal (len(allTranslations))
and ReturnedTotal (len(filteredResults)) in the response.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@backend/internal/oauth/oauth2/dcr/service.go`:
- Around line 153-166: The rollback currently uses the original request context
so if the caller times out the compensation (writeLocalizedVariants cleanup and
appService.DeleteApplication) may be skipped; change the compensation path in
the error branch after writeLocalizedVariants to create a bounded background
context (e.g., ctxCleanup := context.WithTimeout(context.Background(),
someReasonableTimeout) and defer cancel()) and use ctxCleanup when calling
ds.i18nService.DeleteTranslationsByNamespace(application.AppI18nNamespace(createdAppID))
and ds.appService.DeleteApplication(ctxCleanup, createdAppID); keep existing
error logging and return &ErrorServerError as before.

---

Duplicate comments:
In `@backend/cmd/server/servicemanager.go`:
- Around line 269-270: Add user-facing documentation for the new OAuth DCR
endpoint and localized metadata: document the GET /oauth2/dcr/register/{app_id}
endpoint (purpose, request/response, status codes), list the new localized DCR
metadata keys (client_name#<lang>, logo_uri#<lang>, tos_uri#<lang>,
policy_uri#<lang>), and explicitly document the 400 invalid-language-tag and 404
not-found error cases; add these entries to the API reference (apis.mdx) and the
Dynamic Client Registration guide so the new behavior is fully described before
merging.

---

Nitpick comments:
In `@backend/internal/system/i18n/mgt/service.go`:
- Around line 257-276: The reported TotalResults uses len(allTranslations) which
can be larger than the actually returned entries because non-system namespaces
use exactLanguageMatch and some translations are skipped (compositeKey,
allTranslations, translation, selectBestTranslation, exactLanguageMatch). Change
TotalResults to reflect the filtered/returned count by computing the length of
the results map after the loop (or incrementing a counter when you add a
translation.Value to the result) instead of using len(allTranslations), or if
you intentionally want stored vs returned semantics, explicitly include both a
StoredTotal (len(allTranslations)) and ReturnedTotal (len(filteredResults)) in
the response.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: cf5ba964-e166-43f8-886b-3b86d537c351

📥 Commits

Reviewing files that changed from the base of the PR and between fe54da6 and dbdfeb9.

⛔ Files ignored due to path filters (2)
  • backend/tests/mocks/i18n/mgtmock/I18nServiceInterface_mock.go is excluded by !**/*_mock.go
  • backend/tests/mocks/i18n/mgtmock/i18nStoreInterface_mock.go is excluded by !**/*_mock.go
📒 Files selected for processing (28)
  • backend/cmd/server/servicemanager.go
  • backend/internal/application/init.go
  • backend/internal/application/init_test.go
  • backend/internal/application/service.go
  • backend/internal/application/service_test.go
  • backend/internal/oauth/init.go
  • backend/internal/oauth/oauth2/dcr/DCRServiceInterface_mock_test.go
  • backend/internal/oauth/oauth2/dcr/error_constants.go
  • backend/internal/oauth/oauth2/dcr/handler.go
  • backend/internal/oauth/oauth2/dcr/handler_test.go
  • backend/internal/oauth/oauth2/dcr/init.go
  • backend/internal/oauth/oauth2/dcr/init_test.go
  • backend/internal/oauth/oauth2/dcr/model.go
  • backend/internal/oauth/oauth2/dcr/model_test.go
  • backend/internal/oauth/oauth2/dcr/service.go
  • backend/internal/oauth/oauth2/dcr/service_test.go
  • backend/internal/system/i18n/mgt/I18nServiceInterface_mock_test.go
  • backend/internal/system/i18n/mgt/constants.go
  • backend/internal/system/i18n/mgt/file_based_store.go
  • backend/internal/system/i18n/mgt/file_based_store_test.go
  • backend/internal/system/i18n/mgt/i18nStoreInterface_mock_test.go
  • backend/internal/system/i18n/mgt/service.go
  • backend/internal/system/i18n/mgt/service_test.go
  • backend/internal/system/i18n/mgt/store.go
  • backend/internal/system/i18n/mgt/store_constants.go
  • backend/internal/system/i18n/mgt/store_test.go
  • tests/integration/oauth/dcr/dcr_test.go
  • tests/integration/oauth/dcr/model.go
✅ Files skipped from review due to trivial changes (3)
  • backend/internal/system/i18n/mgt/file_based_store_test.go
  • backend/internal/oauth/oauth2/dcr/error_constants.go
  • backend/internal/system/i18n/mgt/file_based_store.go
🚧 Files skipped from review as they are similar to previous changes (13)
  • backend/internal/oauth/init.go
  • backend/internal/application/init.go
  • backend/internal/oauth/oauth2/dcr/init_test.go
  • backend/internal/system/i18n/mgt/store_test.go
  • backend/internal/oauth/oauth2/dcr/handler.go
  • backend/internal/system/i18n/mgt/store_constants.go
  • backend/internal/oauth/oauth2/dcr/handler_test.go
  • backend/internal/oauth/oauth2/dcr/init.go
  • backend/internal/application/service_test.go
  • backend/internal/system/i18n/mgt/i18nStoreInterface_mock_test.go
  • tests/integration/oauth/dcr/dcr_test.go
  • backend/internal/oauth/oauth2/dcr/service_test.go
  • backend/internal/system/i18n/mgt/I18nServiceInterface_mock_test.go

Comment thread backend/internal/oauth/oauth2/dcr/service.go Outdated
@nandhu-kumar
Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 16, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

1 similar comment
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 16, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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

♻️ Duplicate comments (1)
backend/internal/oauth/oauth2/dcr/handler.go (1)

76-110: ⚠️ Potential issue | 🟠 Major

🔴 Documentation Required: This PR introduces a user-facing change, but there are still no matching docs updates under docs/. Please document the new GET /oauth2/dcr/register/{app_id} endpoint and the localized DCR metadata fields (client_name#<lang>, logo_uri#<lang>, tos_uri#<lang>, policy_uri#<lang>) in docs/content/apis.mdx, and update the DCR guide under docs/content/guides/ with request/response examples and error cases before merge.

As per coding guidelines "🔴 Documentation Required: This PR introduces a user-facing change (e.g., new/modified API endpoint, configuration option, authentication flow, or SDK behavior) but does not include corresponding documentation updates under docs/."

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

In `@backend/internal/oauth/oauth2/dcr/handler.go` around lines 76 - 110, Add
documentation for the new GET /oauth2/dcr/register/{app_id} endpoint implemented
by HandleDCRGetClient: document the endpoint path, purpose,
authentication/authorization behavior, example request/response payloads, and
possible error cases (including ErrorClientNotFound and server errors).
Additionally, describe the localized DCR metadata fields (client_name#<lang>,
logo_uri#<lang>, tos_uri#<lang>, policy_uri#<lang>) and how they should be used,
and update the DCR guide with request/response examples and error handling;
place these docs in docs/content/apis.mdx and the DCR guide under
docs/content/guides/ per repo conventions.
🧹 Nitpick comments (1)
backend/internal/system/i18n/mgt/service_test.go (1)

620-647: Keep this coverage in the testify suite.

This is the only new test in the file using plain testing.T and manual t.Errorf checks. Please fold it into I18nMgtServiceTestSuite and use testify assertions so it stays consistent with the rest of the backend test setup.

As per coding guidelines "Applies to backend/**/*_test.go : Use stretchr/testify for tests and follow the test suite pattern".

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

In `@backend/internal/system/i18n/mgt/service_test.go` around lines 620 - 647, The
standalone TestNormaliseBCP47Tag should be moved into the
I18nMgtServiceTestSuite as a suite method (func (s *I18nMgtServiceTestSuite)
TestNormaliseBCP47Tag()) and converted to use testify assertions instead of
t.Errorf; call the existing NormaliseBCP47Tag inside the loop and use s.T().Run
for subtests if desired, and replace manual checks with s.Require().Equal /
s.Require().False / s.Require().True (or s.Assertions.Equal/True/False) to
assert got vs wantTag and valid vs wantValid; remove the original top-level
TestNormaliseBCP47Tag function after adding the suite method.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@backend/internal/oauth/init.go`:
- Line 84: Add documentation for the new DCR endpoint and localized metadata
behavior: update docs/content/apis.mdx to document GET
/oauth2/dcr/register/{app_id} (endpoint path, parameters, expected responses
including 200, 400 for invalid BCP47 tags, and 404 when app_id not found) and
add a guide under docs/content/guides/ describing request/response examples, the
allowed localized client metadata keys (e.g., client_name#<lang-tag>,
logo_uri#<lang-tag>), the BCP 47 tag validation rules and examples of
valid/invalid tags, and explicit 400/404 response bodies; reference the
implementation entry point dcr.Initialize and the localized-key naming
convention in the guide so readers can map docs to code.

In `@backend/internal/oauth/oauth2/dcr/model.go`:
- Around line 51-55: The PR adds localized DCR metadata fields
(LocalizedClientName, LocalizedLogoURI, LocalizedTosURI, LocalizedPolicyURI
exposed as client_name#<lang>, logo_uri#<lang>, tos_uri#<lang>,
policy_uri#<lang>) and a new GET endpoint GET /oauth2/dcr/register/{app_id} but
did not update documentation; update the DCR API reference to document the new
localized metadata keys and the GET /oauth2/dcr/register/{app_id} response, and
add or extend a guide that shows how to register clients with localized fields
and how to retrieve them via the new client-read API so docs and code remain in
sync.

In `@backend/internal/oauth/oauth2/dcr/service.go`:
- Around line 323-327: The loop that calls
ds.i18nService.SetTranslationOverrideForKey for each f.variants currently maps
every failure to ErrorServerError, which masks client-side validation errors;
instead, propagate the actual svcErr (or translate it to the appropriate client
error) so localized validation failures are returned as client errors rather
than 500s, or pre-validate the localized maps (fields / f.variants) before
calling CreateApplication; update the loop in service.go to check the error
returned from SetTranslationOverrideForKey and return that error (or a mapped
client validation error) instead of always returning ErrorServerError.
- Around line 144-169: The detached compensation path uses
context.WithoutCancel(ctx) (cleanupCtx) which removes deadlines and can hang;
wrap that detached context with a bounded timeout before calling
ds.appService.DeleteApplication: create cleanupCtx :=
context.WithTimeout(context.WithoutCancel(ctx), <smallDuration>) (e.g., 3-10s)
and ensure you call cancel() (defer cancel()) so DeleteApplication cannot block
forever; keep the i18n cleanup using
ds.i18nService.DeleteTranslationsByNamespace(application.AppI18nNamespace(createdAppID))
unchanged and pass the new cleanupCtx into
ds.appService.DeleteApplication(cleanupCtx, createdAppID).

---

Duplicate comments:
In `@backend/internal/oauth/oauth2/dcr/handler.go`:
- Around line 76-110: Add documentation for the new GET
/oauth2/dcr/register/{app_id} endpoint implemented by HandleDCRGetClient:
document the endpoint path, purpose, authentication/authorization behavior,
example request/response payloads, and possible error cases (including
ErrorClientNotFound and server errors). Additionally, describe the localized DCR
metadata fields (client_name#<lang>, logo_uri#<lang>, tos_uri#<lang>,
policy_uri#<lang>) and how they should be used, and update the DCR guide with
request/response examples and error handling; place these docs in
docs/content/apis.mdx and the DCR guide under docs/content/guides/ per repo
conventions.

---

Nitpick comments:
In `@backend/internal/system/i18n/mgt/service_test.go`:
- Around line 620-647: The standalone TestNormaliseBCP47Tag should be moved into
the I18nMgtServiceTestSuite as a suite method (func (s *I18nMgtServiceTestSuite)
TestNormaliseBCP47Tag()) and converted to use testify assertions instead of
t.Errorf; call the existing NormaliseBCP47Tag inside the loop and use s.T().Run
for subtests if desired, and replace manual checks with s.Require().Equal /
s.Require().False / s.Require().True (or s.Assertions.Equal/True/False) to
assert got vs wantTag and valid vs wantValid; remove the original top-level
TestNormaliseBCP47Tag function after adding the suite method.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a5b44412-6db7-4b7d-95ad-c3c063dddbc3

📥 Commits

Reviewing files that changed from the base of the PR and between dbdfeb9 and acf373d.

⛔ Files ignored due to path filters (2)
  • backend/tests/mocks/i18n/mgtmock/I18nServiceInterface_mock.go is excluded by !**/*_mock.go
  • backend/tests/mocks/i18n/mgtmock/i18nStoreInterface_mock.go is excluded by !**/*_mock.go
📒 Files selected for processing (28)
  • backend/cmd/server/servicemanager.go
  • backend/internal/application/init.go
  • backend/internal/application/init_test.go
  • backend/internal/application/service.go
  • backend/internal/application/service_test.go
  • backend/internal/oauth/init.go
  • backend/internal/oauth/oauth2/dcr/DCRServiceInterface_mock_test.go
  • backend/internal/oauth/oauth2/dcr/error_constants.go
  • backend/internal/oauth/oauth2/dcr/handler.go
  • backend/internal/oauth/oauth2/dcr/handler_test.go
  • backend/internal/oauth/oauth2/dcr/init.go
  • backend/internal/oauth/oauth2/dcr/init_test.go
  • backend/internal/oauth/oauth2/dcr/model.go
  • backend/internal/oauth/oauth2/dcr/model_test.go
  • backend/internal/oauth/oauth2/dcr/service.go
  • backend/internal/oauth/oauth2/dcr/service_test.go
  • backend/internal/system/i18n/mgt/I18nServiceInterface_mock_test.go
  • backend/internal/system/i18n/mgt/constants.go
  • backend/internal/system/i18n/mgt/file_based_store.go
  • backend/internal/system/i18n/mgt/file_based_store_test.go
  • backend/internal/system/i18n/mgt/i18nStoreInterface_mock_test.go
  • backend/internal/system/i18n/mgt/service.go
  • backend/internal/system/i18n/mgt/service_test.go
  • backend/internal/system/i18n/mgt/store.go
  • backend/internal/system/i18n/mgt/store_constants.go
  • backend/internal/system/i18n/mgt/store_test.go
  • tests/integration/oauth/dcr/dcr_test.go
  • tests/integration/oauth/dcr/model.go
✅ Files skipped from review due to trivial changes (5)
  • backend/internal/application/init_test.go
  • backend/cmd/server/servicemanager.go
  • backend/internal/system/i18n/mgt/store_constants.go
  • backend/internal/oauth/oauth2/dcr/handler_test.go
  • backend/internal/oauth/oauth2/dcr/service_test.go
🚧 Files skipped from review as they are similar to previous changes (11)
  • backend/internal/oauth/oauth2/dcr/init_test.go
  • backend/internal/oauth/oauth2/dcr/error_constants.go
  • backend/internal/system/i18n/mgt/file_based_store.go
  • backend/internal/oauth/oauth2/dcr/init.go
  • backend/internal/oauth/oauth2/dcr/model_test.go
  • backend/internal/application/service.go
  • backend/internal/application/service_test.go
  • backend/internal/system/i18n/mgt/store_test.go
  • tests/integration/oauth/dcr/dcr_test.go
  • backend/internal/system/i18n/mgt/service.go
  • backend/internal/system/i18n/mgt/I18nServiceInterface_mock_test.go

Comment thread backend/internal/oauth/init.go
Comment thread backend/internal/oauth/oauth2/dcr/model.go
Comment thread backend/internal/oauth/oauth2/dcr/service.go Outdated
Comment thread backend/internal/oauth/oauth2/dcr/service.go
Comment thread backend/internal/application/service.go Outdated
Comment thread backend/internal/application/service.go Outdated
Comment thread backend/internal/application/service.go Outdated
Comment thread backend/internal/application/service.go Outdated
Comment thread backend/internal/application/utils.go Outdated
Comment thread backend/internal/oauth/oauth2/dcr/error_constants.go
Comment thread backend/internal/oauth/oauth2/dcr/service.go Outdated
Comment thread backend/internal/oauth/oauth2/dcr/service.go
Comment thread backend/internal/system/i18n/mgt/store.go Outdated
Comment thread backend/internal/oauth/oauth2/dcr/service.go
@nandhu-kumar nandhu-kumar force-pushed the main-local-2106 branch 2 times, most recently from 41fcd8b to 48abb2b Compare April 30, 2026 10:28
Comment thread backend/internal/oauth/oauth2/dcr/service.go
Comment thread backend/internal/application/service.go Outdated
Comment thread backend/internal/application/service.go Outdated
Comment thread backend/internal/oauth/oauth2/dcr/service.go Outdated
Signed-off-by: Nandhukumar <nandhukumare@gmail.com>
@ThaminduDilshan ThaminduDilshan changed the title Draft - Add localized client metadata support for applications and DCR Add localized client metadata support for applications and DCR Apr 30, 2026
@ThaminduDilshan ThaminduDilshan added this pull request to the merge queue Apr 30, 2026
Merged via the queue into asgardeo:main with commit e403e6f Apr 30, 2026
30 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Localised Client metadata

5 participants