Skip to content

fix(Navigation/AccessLog): proxify request through BFF(nodejs) [YTFRONT-5300]#1438

Merged
ma-efremoff merged 12 commits intomainfrom
ma-efremoff/accesslog
Feb 17, 2026
Merged

fix(Navigation/AccessLog): proxify request through BFF(nodejs) [YTFRONT-5300]#1438
ma-efremoff merged 12 commits intomainfrom
ma-efremoff/accesslog

Conversation

@ma-efremoff
Copy link
Copy Markdown
Collaborator

@ma-efremoff ma-efremoff commented Feb 5, 2026

https://nda.ya.ru/t/akvyyZcv7ThFSR

## Summary by Sourcery

Proxy navigation access log and accounts usage requests through the Node.js backend using configurable per-cluster UI settings and expose their availability in the UI.

New Features:

  • Introduce backend controllers and API routes that proxy Access Log and Accounts Usage endpoints through the Node.js server with auth-aware base URL resolution.
  • Add UI-side availability checks and flags for Access Log and Accounts Usage tabs, driven by backend configuration.
  • Allow cluster-specific UI settings overrides via a new ui_settings section with snake_case-to-camelCase conversion and merging.

Bug Fixes:

  • Handle string and simple object error shapes in YTErrorBlock to avoid rendering issues.

Enhancements:

  • Refine UISettings types and base URL handling to support structured configuration with testing/use_cors attributes.
  • Unify cluster-specific UI settings merging and base URL resolution on both server and client.
  • Update documentation to describe cluster-specific UI configuration and replace deprecated resource usage URL with ui_settings overrides.
  • Extend server auth headers factory to support new proxied services and align ai-chat usage with the updated type.

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented Feb 5, 2026

Reviewer's Guide

This PR routes Navigation/Access Log and Accounts/Detailed usage API calls through new Node.js proxy controllers that derive per-cluster base URLs from unified UI settings, adds availability checks that drive tab visibility in the UI, hardens error rendering, and introduces shared utilities for cluster-specific configuration merging and snake_case-to-camelCase conversion while updating related docs and dependencies.

Sequence diagram for proxied Navigation/Access Log data request

sequenceDiagram
    actor User
    participant Browser as Browser_UI
    participant AccessLogTab as AccessLogTab_fetchAccessLog
    participant Axios as Axios_in_Browser
    participant Node as Node_Server
    participant Ctrl as ytAccessLogApi_controller
    participant Config as Config_utils
    participant AccessLogSvc as AccessLog_Service

    User->>Browser: Open Navigation/Access_Log tab
    Browser->>AccessLogTab: dispatch(fetchAccessLog)
    AccessLogTab->>AccessLogTab: getAccessLogRequestParams(state)
    AccessLogTab->>Axios: GET /api/access-log/:cluster/ready
    AccessLogTab->>Axios: POST /api/access-log/:cluster/visible-time-range
    AccessLogTab->>Axios: POST /api/access-log/:cluster/access_log

    Axios->>Node: HTTP requests /api/access-log/:ytAuthCluster/:action
    Node->>Ctrl: route to ytAccessLogApi

    Ctrl->>Ctrl: validate action in ALLOWED_ACTIONS
    Ctrl->>Config: getAccessLogBaseUrl(req)
    Config->>Config: getBaseUrlFromConfiguration(req,{cluster,isDeveloper,uiSettingsFieldName})
    Config->>Config: getClusterSpecificUiSettings(req,{cluster,isDeveloper})
    Config->>Config: getPreloadedClusterUiConfig(cluster,ctx,isDeveloper)
    Config->>Config: mergeUiSettings({uiSettings,uiConfig})
    Config->>Config: getBaseUrlDetails(uiSettings,"accessLogBasePath")
    Config-->>Ctrl: {baseUrl,testing,use_cors}

    Ctrl->>Node: ServerFactory.getAuthHeaders(testing?accessLogTest:accessLogProd,req)
    Ctrl->>AccessLogSvc: axios.request(baseUrl + "/" + action)
    AccessLogSvc-->>Ctrl: streaming HTTP response
    Ctrl->>Node: pipeAxiosResponse(ctx,res,response)
    Node-->>Axios: proxied response stream
    Axios-->>AccessLogTab: data for ready/visible-time-range/access_log
    AccessLogTab-->>Browser: update Redux state and UI
Loading

Updated class diagram for UI settings, cluster config, and base URL utilities

classDiagram
    class UISettings {
      <<interface>>
      +UiConfigBaseUrl accessLogBasePath
      +UiConfigBaseUrl accountsUsageBasePath
      +string docsBaseUrl
      +string jupyterBasePath
    }

    class UiConfigBaseUrl {
      <<type>>
      +boolean @testing
      +boolean @use_cors
      +string $value
    }

    class ClusterUiConfig {
      <<interface>>
      +boolean enable_per_bundle_tablet_accounting
      +boolean enable_per_account_tablet_accounting
      +boolean enable_maintenance_api_nodes
      +boolean enable_maintenance_api_proxies
      +string chyt_controller_base_url
      +string livy_controller_base_url
      +Record~Stage,string~ query_tracker_default_aco
      +any job_trace_url_template
      +string operation_performance_url_template
      +string tablet_errors_base_url
      +string job_log_viewer_base_url
      +string job_log_viewer_tvm_key
      +Partial~UISettings~ ui_settings
    }

    class BaseUrlDetails {
      +string baseUrl
      +boolean testing
      +boolean use_cors
    }

    class mergeUiSettings {
      <<function>>
      +UISettings mergeUiSettings(uiSettings, uiConfig)
    }

    class getBaseUrlDetails {
      <<function>>
      +BaseUrlDetails getBaseUrlDetails(uiSettings,key)
    }

    class getBaseUrlFromConfiguration {
      <<function>>
      +BaseUrlDetails getBaseUrlFromConfiguration(req,cluster,isDeveloper,uiSettingsFieldName)
    }

    class getClusterSpecificUiSettings {
      <<function>>
      +getClusterSpecificUiSettings(req,cluster,isDeveloper) UISettings
    }

    class snakeToCamel {
      <<function>>
      +snakeToCamel(str) string
    }

    class snakeToCamelObject {
      <<function>>
      +snakeToCamelObject(obj) object
    }

    class outputUiSettingsToCamelCase {
      <<function>>
      +outputUiSettingsToCamelCase(obj) obj_with_camelCase_ui_settings
    }

    class getMergedUiSettings {
      <<selector>>
      +getMergedUiSettings(state) UISettings
    }

    class getBaseUrlFromConfigurationDeps {
      <<utility>>
      +getPreloadedClusterUiConfig(cluster,ctx,isDeveloper)
    }

    UISettings <|.. UiConfigBaseUrl : uses
    ClusterUiConfig --> UISettings : ui_settings
    mergeUiSettings --> UISettings : returns
    mergeUiSettings --> ClusterUiConfig : reads ui_settings
    getBaseUrlDetails --> UISettings : reads base URL fields
    getBaseUrlFromConfiguration --> getClusterSpecificUiSettings : calls
    getBaseUrlFromConfiguration --> getBaseUrlDetails : calls
    getClusterSpecificUiSettings --> mergeUiSettings : calls
    getClusterSpecificUiSettings --> getBaseUrlFromConfigurationDeps : calls
    snakeToCamelObject --> snakeToCamel : calls
    outputUiSettingsToCamelCase --> snakeToCamelObject : transforms ui_settings
    getMergedUiSettings --> mergeUiSettings : calls
    getMergedUiSettings --> ClusterUiConfig : reads clusterUiConfig
    getMergedUiSettings --> UISettings : merges global uiSettings
Loading

File-Level Changes

Change Details Files
Proxy Access Log and Accounts/Detailed usage API requests through Node.js with per-cluster configuration and availability checks.
  • Add express routes for access-log and accounts-usage endpoints and implement streaming proxy handlers with whitelisted actions, auth header selection, and error handling.
  • Introduce config-utils helpers that merge global and cluster-specific UI settings and resolve structured base URLs (with testing and CORS flags) for proxied services.
  • Switch frontend Access Log thunks to call new /api/access-log/:cluster endpoints and compute URLs via base-url helpers, removing direct use of accessLogBasePath.
  • Switch Accounts/Detailed usage actions (snapshots, list, tree, diffs, modal attributes) to call new /api/accounts-usage/:cluster endpoints built via calcAccountsUsageBaseUrl.
packages/ui/src/server/routes.ts
packages/ui/src/server/controllers/yt-access-log-api.ts
packages/ui/src/server/controllers/yt-accounts-usage.ts
packages/ui/src/server/utils/config-utils.ts
packages/ui/src/shared/utils/base-url.ts
packages/ui/src/ui/store/actions/navigation/tabs/access-log/access-log.ts
packages/ui/src/ui/store/actions/accounts/account-usage.ts
packages/ui/src/ui/store/actions/accounts/account-usage-diff.ts
packages/ui/src/ui/store/actions/accounts/accounts-usage-base-url.ts
Drive Access Log and Accounts/Detailed usage tab availability from backend checks and store flags instead of raw base-path configuration.
  • Add check-available endpoints for access-log and accounts-usage that inspect configuration and return boolean availability flags.
  • Add navigation and accounts reducer fields (is_access_log_available, is_accounts_usage_available) and wire them into selectors and mapStateToProps.
  • Render small React helpers that on mount call the check-available APIs, update the store flags, and suppress user-visible toasts on success.
  • Update supported-tabs and Accounts page logic to use the new availability flags instead of checking base URLs directly.
packages/ui/src/server/controllers/yt-access-log-api.ts
packages/ui/src/server/controllers/yt-accounts-usage.ts
packages/ui/src/ui/store/reducers/navigation/navigation.tsx
packages/ui/src/ui/store/reducers/accounts/accounts/index.js
packages/ui/src/ui/store/selectors/navigation/navigation.ts
packages/ui/src/ui/pages/navigation/Navigation/Navigation.js
packages/ui/src/ui/pages/accounts/Accounts/Accounts.tsx
packages/ui/src/ui/pages/navigation/tabs/AccessLog/UpdateAccessLogAvailability/UpdateAccessLogAvailability.tsx
packages/ui/src/ui/pages/accounts/tabs/detailed-usage/UpdateAccountsUsageAvailability/UpdateAccountsUsageAvailability.tsx
Unify UI configuration handling with typed base-URL structures, snake_case-to-camelCase conversion, and merge logic for cluster overrides.
  • Extend UISettings to store accessLogBasePath and accountsUsageBasePath as structured UiConfigBaseUrl nodes with testing and use_cors attributes.
  • Add snake-to-camel utilities and apply them to ui_settings returned from cluster-params to support snake_case keys in Cypress config while presenting camelCase in the app.
  • Introduce mergeUiSettings helper and getMergedUiSettings selector to overlay cluster ui_settings on top of global uiSettings for the current cluster.
  • Add shared base-url helper to normalize URLs, read attributes via @ytsaurus/interface-helpers/ypath, and expose UISettingsBaseUrlKeys typing, used on both server and client.
packages/ui/src/shared/ui-settings.ts
packages/ui/src/shared/yt-types.d.ts
packages/ui/src/server/components/cluster-params.ts
packages/ui/src/shared/utils/snake-to-camel.ts
packages/ui/src/shared/utils/merge-ui-settings.ts
packages/ui/src/shared/utils/base-url.ts
packages/ui/src/ui/store/selectors/global/cluster.ts
Track admin/developer mode via a cookie so backend availability and base-url resolution can distinguish dev vs non-dev configuration.
  • Add a ui-config-mode cookie utility and use it in cluster-params init and in small React components that update availability to keep the cookie in sync with isDeveloper selector.
  • Update Node.js config-utils and proxy base-URL resolvers to factor in isDeveloper (from the cookie) when loading cluster-specific UI configuration.
  • Mount a top-level App component that updates the ui_config_mode cookie whenever isDeveloper changes.
packages/ui/src/ui/utils/cookies/ui-config-mode.ts
packages/ui/src/ui/store/actions/cluster-params.ts
packages/ui/src/server/utils/config-utils.ts
packages/ui/src/ui/pages/navigation/tabs/AccessLog/UpdateAccessLogAvailability/UpdateAccessLogAvailability.tsx
packages/ui/src/ui/pages/accounts/tabs/detailed-usage/UpdateAccountsUsageAvailability/UpdateAccountsUsageAvailability.tsx
packages/ui/src/ui/containers/App/App.tsx
Harden YTErrorBlock to handle string errors and error objects with only a string error field.
  • Split YTErrorBlock props into internal and external types so the public component accepts string errors or {error: string} in addition to the existing error shape.
  • Add a type guard that detects error objects containing only an error string field and convert them into a message for rendering.
  • Wrap error normalization in useMemo and keep the inner implementation class typed with the internal props.
packages/ui/src/ui/components/Block/Block.tsx
Adjust types, selectors, and docs to reflect new configuration model and availability behavior; update dependencies and clean up unused scripts.
  • Refine KeysByType utility to exclude undefined from the resulting key union, enabling safe use in base-url helpers.
  • Remove legacy accounts usage base URL fields from ClusterUiConfig and config selectors in favor of ui_settings and merged UISettings.
  • Document cluster-specific UI configuration, admin detection, new ui_settings override mechanism, and Access Log/Accounts usage base URL options in README.
  • Update expresskit and nodekit versions, dedupe @ytsaurus/interface-helpers, and remove the unused notification script and npm script entry.
packages/ui/src/@types/types.d.ts
packages/ui/src/shared/yt-types.d.ts
packages/ui/src/ui/store/selectors/global/index.ts
packages/ui/README.md
packages/ui/package.json
packages/ui/scripts/notify.js

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Feb 5, 2026

Storybook is ready.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Feb 5, 2026

Playwright components report is ready.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Feb 5, 2026

Statoscope report is ready.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Feb 5, 2026

E2E-local report is ready.
E2E-remote report is ready.
E2E-screenshots report is ready.
E2E-passwd report is ready.

@ma-efremoff ma-efremoff force-pushed the ma-efremoff/accesslog branch 6 times, most recently from 428bff6 to 6dc6ff6 Compare February 12, 2026 10:29
@ma-efremoff ma-efremoff marked this pull request as ready for review February 12, 2026 13:37
Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey - I've found 17 issues, and left some high level feedback:

  • In the README changes, there are several typos and the options table is now split by blank lines, which likely breaks Markdown rendering; consider fixing spelling (e.g. 'optaions', 'optnos') and consolidating the rows back into a single properly formatted table, as well as correcting uiSettings/acccess_log_base_path to the right setting name.
  • In NavigationState the is_access_log_available field is typed as the literal false instead of boolean, which will make it awkward or impossible to assign true later; update the type to boolean to reflect actual usage.
  • Both UpdateAccessLogAvailability and UpdateAccountsUsageAvailability use cluster and uiConfig inside useEffect but omit cluster from the dependency array (and only partially include the objects), which can lead to stale values when the cluster changes; consider including cluster and using more stable dependencies (e.g. specific fields or serialized config) or moving the cookie update logic to a single central place (e.g. the App-level helper you introduced).
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In the README changes, there are several typos and the options table is now split by blank lines, which likely breaks Markdown rendering; consider fixing spelling (e.g. 'optaions', 'optnos') and consolidating the rows back into a single properly formatted table, as well as correcting `uiSettings/acccess_log_base_path` to the right setting name.
- In `NavigationState` the `is_access_log_available` field is typed as the literal `false` instead of `boolean`, which will make it awkward or impossible to assign `true` later; update the type to `boolean` to reflect actual usage.
- Both `UpdateAccessLogAvailability` and `UpdateAccountsUsageAvailability` use `cluster` and `uiConfig` inside `useEffect` but omit `cluster` from the dependency array (and only partially include the objects), which can lead to stale values when the cluster changes; consider including `cluster` and using more stable dependencies (e.g. specific fields or serialized config) or moving the cookie update logic to a single central place (e.g. the `App`-level helper you introduced).

## Individual Comments

### Comment 1
<location> `packages/ui/src/ui/pages/accounts/tabs/detailed-usage/UpdateAccountsUsageAvaiability/UpdateAccountsUsageAvailability.tsx:18-27` </location>
<code_context>

+function UpdateUiConfigModeCookie() {
+    const isAdmin = useSelector(isDeveloper);
+    React.useEffect(() => {
+        updateUiConfigModeCookie(isAdmin);
+    }, [isAdmin]);
</code_context>

<issue_to_address>
**issue (bug_risk):** Cluster change will not trigger availability re-check because `cluster` is missing from deps.

This effect calls `/api/accounts-usage/${cluster}/check-available`, but `cluster` is not in the dependency array, so changing cluster without a full reload will keep using the old cluster when checking availability and updating state. Add `cluster` to the dependencies so the availability flag updates when the cluster changes.
</issue_to_address>

### Comment 2
<location> `packages/ui/src/ui/pages/navigation/tabs/AccessLog/UpdateAccessLogAvailability/UpdateAccessLogAvailability.tsx:18-27` </location>
<code_context>

+function UpdateUiConfigModeCookie() {
+    const isAdmin = useSelector(isDeveloper);
+    React.useEffect(() => {
+        updateUiConfigModeCookie(isAdmin);
+    }, [isAdmin]);
</code_context>

<issue_to_address>
**issue (bug_risk):** Missing `cluster` in the effect dependencies can desynchronize access-log availability on cluster change.

This effect derives values from `cluster`, but the dependency array only includes `isAdmin`, `uiConfig`, and `dispatch`. If the cluster changes without a reload, the effect won’t re-run and `is_access_log_available` can stay tied to the previous cluster. Include `cluster` in the dependency array to keep it in sync.
</issue_to_address>

### Comment 3
<location> `packages/ui/src/ui/store/reducers/navigation/navigation.tsx:42-44` </location>
<code_context>
     sidePanelMode: 'qt' | 'yqlkit' | undefined;

     originatingQueuePath: string | undefined;
+
+    is_access_log_available: false;
 };

</code_context>

<issue_to_address>
**issue:** `is_access_log_available` is typed as `false` instead of `boolean` in `NavigationState`.

This declaration makes `is_access_log_available` a `false` literal type rather than `boolean`, while other code treats it as a boolean. Please change the type to `boolean` and keep the initial value `false` in `ephemeralState` to avoid type mismatch and unintended narrowing.
</issue_to_address>

### Comment 4
<location> `packages/ui/src/ui/store/selectors/navigation/navigation.ts:35-36` </location>
<code_context>
 export const getNavigationCheckPermissionsError = (state: RootState) =>
     state.navigation.navigation.checkPermissionsError as YTError | undefined;
 export const getMode = (state: RootState) => state.navigation.navigation.mode;
+export const getNaviagationAccessLogAvailable = (state: RootState) =>
+    state.navigation.navigation.is_access_log_available;

 export const getNavigationPathAccount = createSelector(
</code_context>

<issue_to_address>
**nitpick (typo):** Selector name contains a typo (`getNaviagationAccessLogAvailable`).

Please rename this selector to `getNavigationAccessLogAvailable` to fix the spelling and avoid spreading the typo to call sites.

Suggested implementation:

```typescript
export const getMode = (state: RootState) => state.navigation.navigation.mode;
export const getNavigationAccessLogAvailable = (state: RootState) =>
    state.navigation.navigation.is_access_log_available;

```

```typescript
export const getNavigationPathAccount = createSelector(
    [getNavigationPathAttributes],
        getTableMountConfigHasData,
        getTabletErrorsBackgroundCount,
        getNavigationOriginatingQueuePath,
        getNavigationAccessLogAvailable,
    ],

```
</issue_to_address>

### Comment 5
<location> `packages/ui/src/ui/pages/accounts/tabs/detailed-usage/UpdateAccountsUsageAvaiability/i18n/index.ts:6` </location>
<code_context>
+import en from './en.json';
+import ru from './ru.json';
+
+export default addI18Keysets('yt:update-accounts-usage-availablility', {en, ru});
</code_context>

<issue_to_address>
**nitpick (typo):** Multiple spellings of "availability" are inconsistent/misspelled in identifiers and paths.

The directory name (`UpdateAccountsUsageAvaiability`) and i18n keys (`yt:update-accounts-usage-availablility`, `yt:update-access-log-availablility`) all misspell “availability”. Please standardize these to the correct spelling (e.g., `UpdateAccountsUsageAvailability`, `...-availability`) to keep identifiers and paths consistent and searchable.

Suggested implementation:

```typescript
export default addI18Keysets('yt:update-accounts-usage-availability', {en, ru});

```

To fully apply your naming suggestion across the codebase, the following should also be done:

1. Rename the directory:
   - From: `packages/ui/src/ui/pages/accounts/tabs/detailed-usage/UpdateAccountsUsageAvaiability/`
   - To:   `packages/ui/src/ui/pages/accounts/tabs/detailed-usage/UpdateAccountsUsageAvailability/`
2. Update all imports that reference `UpdateAccountsUsageAvaiability` to `UpdateAccountsUsageAvailability`.
3. Standardize any other i18n keys with the same typo, e.g.:
   - `yt:update-access-log-availablility``yt:update-access-log-availability`
   and update all usages of these keys in the codebase and translation JSON files (`en.json`, `ru.json` and any other locales).
</issue_to_address>

### Comment 6
<location> `packages/ui/README.md:102` </location>
<code_context>
-There is yt-api command get_supported_feature and it is a good place to describe some features.
-But some cases require ability to turn on/off a feature manually on a cluster. Such feature flags are placed placed in:
+There is yt-api command get_supported_feature and it is a good place to describe API features.
+But some cases require ability to turn on/off a feature manually on a specific cluster. Such cluster specific optinos are placed placed in:

 - `//sys/@ui_config` (values affects all users)
</code_context>

<issue_to_address>
**suggestion (typo):** Fix typos and wording in the cluster-specific options sentence.

Suggest rephrasing to: “But some cases require the ability to turn on/off a feature manually on a specific cluster. Such cluster-specific options are placed in:” (fixing the typos, removing the duplicatedplaced”, and addingthebeforeability”).

```suggestion
But some cases require the ability to turn on/off a feature manually on a specific cluster. Such cluster-specific options are placed in:
```
</issue_to_address>

### Comment 7
<location> `packages/ui/README.md:104-105` </location>
<code_context>
+There is yt-api command get_supported_feature and it is a good place to describe API features.
+But some cases require ability to turn on/off a feature manually on a specific cluster. Such cluster specific optinos are placed placed in:

 - `//sys/@ui_config` (values affects all users)
-- `//sys/@ui_config_dev_overrides` (values affects only developers)
+- `//sys/@ui_config_dev_overrides` (values affects only admins)

 (see more detail in [YTFRONT-2804](https://nda.ya.ru/t/bgh9NWJ16fPRp4))
</code_context>

<issue_to_address>
**suggestion (typo):** Use correct subjectverb agreement in the bullet descriptions.

Because "values" is plural, both bullets should use "values affect", e.g. "(values affect all users)" and "(values affect only admins)".

Suggested implementation:

```
- `//sys/@ui_config` (values affect all users)

```

```
- `//sys/@ui_config_dev_overrides` (values affect only admins)

```
</issue_to_address>

### Comment 8
<location> `packages/ui/README.md:111` </location>
<code_context>
-| tablet_errors_base_url               | **null**, url as string                                                              | Base URL for tablet errors service to override uiSettings.tabletErrorsBaseUrl                                                                                                                                                                                                                                                               |
+UI determines a user as an admin on the cluster if he has `write` access to `admins` group.
+
+Available optaions (**default values** are highlighted in bold):
+
+| Option name                         | Allowed values  | Description                                                                                                          |
</code_context>

<issue_to_address>
**issue (typo):** Fix typo in "optaions".

In the “Available options…” line, replace “optaions” with “options”.

```suggestion
Available options (**default values** are highlighted in bold):
```
</issue_to_address>

### Comment 9
<location> `packages/ui/README.md:121` </location>
<code_context>
+
+| per_bundle_accounting_help_link | **null**, url as string | Help link for resources of tablets to display from AccountEditorDialog about moving the resources to bundles [YTFRONT-2851](https://nda.ya.ru/t/xnLq-3Dm6fPYPo) |
+
+| enable_maintenance_api_nodes | **null**, boolean | Allows to use `add_maintenance`/`remove_maintenance` commands from `Comopnents/Nodes` page [YTFRONT-3792](https://nda.ya.ru/t/RvueJLzN6fWx3h) |
+
+| enable_maintenance_api_proxies | **null**, boolean | Allows to use `add_maintenance`/`remove_maintenance` commands from `Components/HTTP Proxies` and `Components/RPC Proxies` pages [YTFRONT-3792](https://nda.ya.ru/t/RvueJLzN6fWx3h) |
</code_context>

<issue_to_address>
**issue (typo):** Fix the spelling of "Comopnents".

Please update this entry to say "Components/Nodes" instead of "Comopnents/Nodes".

```suggestion
| enable_maintenance_api_nodes | **null**, boolean | Allows to use `add_maintenance`/`remove_maintenance` commands from `Components/Nodes` page [YTFRONT-3792](https://nda.ya.ru/t/RvueJLzN6fWx3h) |
```
</issue_to_address>

### Comment 10
<location> `packages/ui/README.md:128` </location>
<code_context>
+| chyt_controller_base_url | **null**, url as string | Base url for chyt-controller |
+
+| livy_controller_base_url | **null**, url as string | Base url for spyt-controller |
+| job_trace_url_template | **null**, `{title: string; url_template: string; enforce_for_trees?: Array<string>}` | If defined adds `Job trace` item to meta-table on `Job/Details` page for a job with `archive_features/has_trace == true` and for jobs from a tree in `enforce_for_trees`, example: `{title: 'Open im MyProfiling', url_template: 'https://my.profiling.service/{cluster}/{operationId}/{jobId}', enforce_for_trees: ['tree-with-traces'] }` |
+
+| query_tracker_default_aco | **null**, `{stage1: string; stage2: string; }` | Sets the default ACO in Query Tracker requests for each stage |
</code_context>

<issue_to_address>
**issue (typo):** Fix the typo "Open im MyProfiling" in the example string.

In the example configuration object for `job_trace_url_template`, update the `title` value to "Open in MyProfiling".

```suggestion
| job_trace_url_template | **null**, `{title: string; url_template: string; enforce_for_trees?: Array<string>}` | If defined adds `Job trace` item to meta-table on `Job/Details` page for a job with `archive_features/has_trace == true` and for jobs from a tree in `enforce_for_trees`, example: `{title: 'Open in MyProfiling', url_template: 'https://my.profiling.service/{cluster}/{operationId}/{jobId}', enforce_for_trees: ['tree-with-traces'] }` |
```
</issue_to_address>

### Comment 11
<location> `packages/ui/README.md:138` </location>
<code_context>
+
+| tablet_errors_base_url | **null**, url as string | Base URL for tablet errors service to override `uiSettings.tabletErrorsBaseUrl` |
+
+| access_log_base_url | **null**, url as string | Base URL for `Navigation/Access Log` API endpoint, the option overrides `uiSettings/acccess_log_base_path` |

 ### Configuration
</code_context>

<issue_to_address>
**question (typo):** Double-check the spelling of the `uiSettings/acccess_log_base_path` key.

If the actual setting key is `access_log_base_path`, please update this reference to match and avoid configuration confusion.

```suggestion
| access_log_base_url | **null**, url as string | Base URL for `Navigation/Access Log` API endpoint, the option overrides `uiSettings/access_log_base_path` |
```
</issue_to_address>

### Comment 12
<location> `packages/ui/src/server/controllers/yt-access-log-api.ts:63` </location>
<code_context>
+    const {baseUrl, testing} = await getAccountsUsageBaseUrl(req);
+
+    if (!baseUrl) {
+        throw new ErrorWithCode(
+            404,
+            'The UI installation is not configured to display "Accounts/Detailed usage" tab for current cluster. Please check your configuration: config.uiSettings.accountsUsageBasePath, //sys/@ui_config/resource_usage_base_url',
</code_context>

<issue_to_address>
**suggestion (review_instructions):** The error message string is slightly ungrammatical; consider using “for the current cluster” instead of “on current cluster.”

The message

"The UI installation is not configured to display \"Navigation/Access log\" tab on current cluster."

would read more naturally as

"The UI installation is not configured to display \"Navigation/Access log\" tab for the current cluster."

<details>
<summary>Review instructions:</summary>

**Path patterns:** `packages/ui/**/*.js,packages/ui/**/*.ts,packages/ui/**/*.tsx,packages/ui/**/*.jsx`

**Instructions:**
Do not pass grammatical issues

</details>
</issue_to_address>

### Comment 13
<location> `packages/ui/src/ui/pages/accounts/Accounts/Accounts.tsx:42` </location>
<code_context>
 import './Accounts.scss';
 import UIFactory from '../../../UIFactory';
 import {UI_TAB_SIZE} from '../../../constants/global';
+import {UpdateAccountsUsageAvailability} from '../tabs/detailed-usage/UpdateAccountsUsageAvaiability/UpdateAccountsUsageAvailability';

 const b = block('accounts');
</code_context>

<issue_to_address>
**suggestion (review_instructions):** There is a spelling mistake (“Avaiability”) in the imported path segment, which should be “Availability.”

The folder segment `UpdateAccountsUsageAvaiability` is misspelled; it should be `UpdateAccountsUsageAvailability`. Even though this isn’t user-facing text, the instruction asks us not to pass grammatical/spelling issues. Renaming the directory and updating imports accordingly would improve clarity.

<details>
<summary>Review instructions:</summary>

**Path patterns:** `packages/ui/**/*.js,packages/ui/**/*.ts,packages/ui/**/*.tsx,packages/ui/**/*.jsx`

**Instructions:**
Do not pass grammatical issues

</details>
</issue_to_address>

### Comment 14
<location> `packages/ui/src/ui/store/selectors/navigation/navigation.ts:35` </location>
<code_context>
 export const getNavigationCheckPermissionsError = (state: RootState) =>
     state.navigation.navigation.checkPermissionsError as YTError | undefined;
 export const getMode = (state: RootState) => state.navigation.navigation.mode;
+export const getNaviagationAccessLogAvailable = (state: RootState) =>
+    state.navigation.navigation.is_access_log_available;

</code_context>

<issue_to_address>
**suggestion (review_instructions):** The selector name contains a spelling mistake (“Naviagation” instead of “Navigation”).

The function name `getNaviagationAccessLogAvailable` has a typo; it should be `getNavigationAccessLogAvailable`. Renaming the selector and updating its usages will keep naming consistent and avoid confusion.

<details>
<summary>Review instructions:</summary>

**Path patterns:** `packages/ui/**/*.js,packages/ui/**/*.ts,packages/ui/**/*.tsx,packages/ui/**/*.jsx`

**Instructions:**
Do not pass grammatical issues

</details>
</issue_to_address>

### Comment 15
<location> `packages/ui/src/server/controllers/yt-access-log-api.ts:26` </location>
<code_context>
+    }
+}
+
+export async function ytAccesLogCheckAvailable(req: Request, res: Response) {
+    try {
+        const {baseUrl} = await getAccessLogBaseUrl(req);
</code_context>

<issue_to_address>
**suggestion (review_instructions):** The function name is missing an “s” in “Access” (`ytAccesLogCheckAvailable`).

`ytAccesLogCheckAvailable` is missing an “s” in “Access”. Renaming it to `ytAccessLogCheckAvailable` (and updating imports/usages) would fix the spelling issue and improve readability.

<details>
<summary>Review instructions:</summary>

**Path patterns:** `packages/ui/**/*.js,packages/ui/**/*.ts,packages/ui/**/*.tsx,packages/ui/**/*.jsx`

**Instructions:**
Do not pass grammatical issues

</details>
</issue_to_address>

### Comment 16
<location> `packages/ui/src/ui/pages/accounts/tabs/detailed-usage/UpdateAccountsUsageAvaiability/i18n/index.ts:6` </location>
<code_context>
+import en from './en.json';
+import ru from './ru.json';
+
+export default addI18Keysets('yt:update-accounts-usage-availablility', {en, ru});
--- /dev/null
+++ b/packages/ui/src/ui/pages/navigation/tabs/AccessLog/UpdateAccessLogAvailability/i18n/index.ts
</code_context>

<issue_to_address>
**suggestion (review_instructions):** The i18n key contains a spelling mistake (“availablility” instead of “availability”).

The namespace string `'yt:update-accounts-usage-availablility'` has “availablility” instead of “availability”. While it’s an internal key, it’s still a spelling issue per the review instructions; consider correcting it (and corresponding usages) to avoid confusion.

<details>
<summary>Review instructions:</summary>

**Path patterns:** `packages/ui/**/*.js,packages/ui/**/*.ts,packages/ui/**/*.tsx,packages/ui/**/*.jsx`

**Instructions:**
Do not pass grammatical issues

</details>
</issue_to_address>

### Comment 17
<location> `packages/ui/src/ui/pages/navigation/tabs/AccessLog/UpdateAccessLogAvailability/i18n/index.ts:6` </location>
<code_context>
+import en from './en.json';
+import ru from './ru.json';
+
+export default addI18Keysets('yt:update-access-log-availablility', {en, ru});
--- /dev/null
+++ b/packages/ui/src/ui/pages/accounts/tabs/detailed-usage/UpdateAccountsUsageAvaiability/i18n/en.json
</code_context>

<issue_to_address>
**suggestion (review_instructions):** The i18n key contains a spelling mistake (“availablility” instead of “availability”).

The key `'yt:update-access-log-availablility'` misspells “availability” as “availablility”. Even though it’s not user-facing, this is still a spelling issue; consider renaming it and updating references to keep things consistent.

<details>
<summary>Review instructions:</summary>

**Path patterns:** `packages/ui/**/*.js,packages/ui/**/*.ts,packages/ui/**/*.tsx,packages/ui/**/*.jsx`

**Instructions:**
Do not pass grammatical issues

</details>
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread packages/ui/src/ui/store/reducers/navigation/navigation.tsx Outdated
Comment thread packages/ui/src/ui/store/selectors/navigation/navigation.ts Outdated
Comment thread packages/ui/src/ui/pages/accounts/Accounts/Accounts.tsx Outdated
Comment thread packages/ui/src/ui/store/selectors/navigation/navigation.ts Outdated
Comment thread packages/ui/src/server/controllers/yt-access-log-api.ts
@ma-efremoff ma-efremoff force-pushed the ma-efremoff/accesslog branch from 6dc6ff6 to ab6a720 Compare February 13, 2026 14:10
@ma-efremoff ma-efremoff force-pushed the ma-efremoff/accesslog branch from 9e74e9c to ab048dd Compare February 13, 2026 14:51
@ma-efremoff ma-efremoff marked this pull request as draft February 17, 2026 00:18
@ma-efremoff ma-efremoff force-pushed the ma-efremoff/accesslog branch from 9fa585c to 986d840 Compare February 17, 2026 09:21
@ma-efremoff ma-efremoff marked this pull request as ready for review February 17, 2026 09:56
Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey - I've found 4 issues, and left some high level feedback:

  • The new calcBaseUrl/calcAccountsUsageBaseUrl helpers rely on url.split('/').pop() which will misbehave for URLs with trailing slashes or query strings; consider passing the action segment explicitly or using a more robust URL builder.
  • The updateUiConfigModeCookie call is now triggered from App, UpdateAccessLogAvailability, UpdateAccountsUsageAvailability, and initClusterParams; this looks redundant and could be centralized to a single place to avoid extra cookie writes and make the logic easier to follow.
  • The updated "Cluster specific features" table in README.md is split into multiple small tables by blank lines between | rows, which likely breaks GitHub markdown rendering; it would be better to keep it as a single table and fix typos like optinos.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The new `calcBaseUrl`/`calcAccountsUsageBaseUrl` helpers rely on `url.split('/').pop()` which will misbehave for URLs with trailing slashes or query strings; consider passing the action segment explicitly or using a more robust URL builder.
- The `updateUiConfigModeCookie` call is now triggered from `App`, `UpdateAccessLogAvailability`, `UpdateAccountsUsageAvailability`, and `initClusterParams`; this looks redundant and could be centralized to a single place to avoid extra cookie writes and make the logic easier to follow.
- The updated "Cluster specific features" table in `README.md` is split into multiple small tables by blank lines between `|` rows, which likely breaks GitHub markdown rendering; it would be better to keep it as a single table and fix typos like `optinos`.

## Individual Comments

### Comment 1
<location> `packages/ui/src/ui/pages/accounts/tabs/detailed-usage/UpdateAccountsUsageAvailability/UpdateAccountsUsageAvailability.tsx:16-17` </location>
<code_context>

+function UpdateUiConfigModeCookie() {
+    const isAdmin = useSelector(isDeveloper);
+    React.useEffect(() => {
+        updateUiConfigModeCookie(isAdmin);
+    }, [isAdmin]);
+
</code_context>

<issue_to_address>
**suggestion:** Avoid updating the `ui_config_mode` cookie from multiple places to reduce duplication and potential drift.

`ui_config_mode` is now written in multiple places: here, in `App` via `UpdateUiConfigModeCookie`, and in `initClusterParams`. Multiple writers make it hard to reason about when the cookie is set or cleared and increase the risk of inconsistencies. Centralize this side effect (e.g., in a single top‑level effect keyed on `isDeveloper`) and remove the redundant updates in lower‑level components.

Suggested implementation:

```typescript

```

```typescript
    const dispatch = useDispatch();
    const cluster = useSelector(getCluster);

```

```typescript
    React.useEffect(() => {
        wrapApiPromiseByToaster(
            axios
                .get<{

```

```typescript
    }, []);

```

1. Ensure that `ui_config_mode` is updated in a single, centralized place (e.g. a top-level `UpdateUiConfigModeCookie` component or effect in `App` keyed on `isDeveloper`), and remove any remaining direct writes to `ui_config_mode` in `initClusterParams` or other lower-level modules.
2. You may want to refine the `useEffect` dependency array (`[]` above) to whatever actually drives the usage-availability fetch (for example, `cluster` or `cluster.id`) to better reflect when the data should be refreshed.
</issue_to_address>

### Comment 2
<location> `packages/ui/README.md:99` </location>
<code_context>
 - Scheduling pool: `scheduler-pool`

-### Feature flags
+### Cluster specific features

-There is yt-api command get_supported_feature and it is a good place to describe some features.
</code_context>

<issue_to_address>
**suggestion (typo):** Consider hyphenating “Cluster-specific” in the heading.

As a compound adjective before “features”, this should be written as “Cluster-specific features” for grammatical correctness.

```suggestion
### Cluster-specific features
```
</issue_to_address>

### Comment 3
<location> `packages/ui/README.md:104-105` </location>
<code_context>

 - `//sys/@ui_config` (values affects all users)
-- `//sys/@ui_config_dev_overrides` (values affects only developers)
+- `//sys/@ui_config_dev_overrides` (values affects only admins)

 (see more detail in [YTFRONT-2804](https://nda.ya.ru/t/bgh9NWJ16fPRp4))
</code_context>

<issue_to_address>
**issue (typo):** Correct subjectverb agreement invalues affects only admins”.

Usevalues affect only adminsto match the plural subjectvalues.”

```suggestion
- `//sys/@ui_config` (values affect all users)
- `//sys/@ui_config_dev_overrides` (values affect only admins)
```
</issue_to_address>

### Comment 4
<location> `packages/ui/src/shared/ui-settings.ts:7` </location>
<code_context>
+export type UiConfigBaseUrl = CypressNodeRaw<{testing: boolean; use_cors: boolean}, string>;
+
+/**
+ * It is possible to provide cluster specific overrides through `//sys/@ui_config/ui_settings`.
+ * All `snake_case`-fieldnames of `//sys/@ui_config/ui_settings` will be converted to `camelCase`.
+ */
</code_context>

<issue_to_address>
**issue (review_instructions):** The doc comment has minor grammar issues: 'cluster specific' should be hyphenated and 'fieldnames' should be written as 'field names'.

To fix the grammar, consider rephrasing the comment to something like:

`* It is possible to provide cluster-specific overrides through \\sys/@ui_config/ui_settings.`
`* All \"`snake_case\"` field names in \\sys/@ui_config/ui_settings will be converted to \"camelCase\".`

<details>
<summary>Review instructions:</summary>

**Path patterns:** `packages/ui/**/*.js,packages/ui/**/*.ts,packages/ui/**/*.tsx,packages/ui/**/*.jsx`

**Instructions:**
- Do not pass grammatical issues

</details>
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread packages/ui/README.md Outdated
Comment thread packages/ui/README.md Outdated
Comment thread packages/ui/src/shared/ui-settings.ts Outdated
Comment thread packages/ui/src/shared/utils/snake-to-camel.ts Outdated
SimbiozizV
SimbiozizV previously approved these changes Feb 17, 2026
…nfig/ui_settings' for cluster specific overrides [YTFRONT-5300,YTFRONT-5366]
@ma-efremoff ma-efremoff merged commit 50595fd into main Feb 17, 2026
8 checks passed
@ma-efremoff ma-efremoff deleted the ma-efremoff/accesslog branch February 17, 2026 10:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants