Skip to content

Improve overall agent friendliness and footprint#695

Open
pcnfernando wants to merge 6 commits into
wso2:devant-migrationfrom
pcnfernando:devant-migration
Open

Improve overall agent friendliness and footprint#695
pcnfernando wants to merge 6 commits into
wso2:devant-migrationfrom
pcnfernando:devant-migration

Conversation

@pcnfernando

Copy link
Copy Markdown

Purpose

Describe the problems, issues, or needs driving this feature/fix and include links to related issues in the following format: Resolves issue1, issue2, etc.

Goals

Describe the solutions that this feature/fix will introduce to resolve the problems described above

Approach

Describe how you are implementing the solutions. Include an animated GIF or screenshot if the change affects the UI (email documentation@wso2.com to review all UI text). Include a link to a Markdown file or Google doc if the feature write-up is too long to paste here.

User stories

Summary of user stories addressed by this change>

Release note

Brief description of the new feature or bug fix as it will appear in the release notes

Documentation

Link(s) to product documentation that addresses the changes of this PR. If no doc impact, enter “N/A” plus brief explanation of why there’s no doc impact

Training

Link to the PR for changes to the training content in https://github.com/wso2/WSO2-Training, if applicable

Certification

Type “Sent” when you have provided new/updated certification questions, plus four answers for each question (correct answer highlighted in bold), based on this change. Certification questions/answers should be sent to certification@wso2.com and NOT pasted in this PR. If there is no impact on certification exams, type “N/A” and explain why.

Marketing

Link to drafts of marketing content that will describe and promote this feature, including product page changes, technical articles, blog posts, videos, etc., if applicable

Automation tests

  • Unit tests

    Code coverage information

  • Integration tests

    Details about the test cases and coverage

Security checks

Samples

Provide high-level details about the samples related to this feature

Related PRs

List any other related PRs

Migrations (if applicable)

Describe migration steps and platforms on which migration has been tested

Test environment

List all JDK versions, operating systems, databases, and browser/versions on which this feature/fix was tested

Learning

Describe the research phase and any blog posts, patterns, libraries, or add-ons you used to solve the problem.

pcnfernando and others added 2 commits June 21, 2026 15:58
Pages, components, layouts, and contexts may no longer import #api/* or
auth/tokenManager directly (no-restricted-imports), mechanizing the rule
already documented in AGENTS.md. The three documented OAuth-CSRF-helper
call sites keep a narrow, named exception.

Fixes the two existing violations this surfaced: OIDCCallback.tsx and
OrgHome.tsx called #api/projects directly instead of going through a
hook (new useFetchProjects), and AppLayout.tsx called tokenManager's
switchOrgToken directly instead of through a hook (new useSwitchOrgToken).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
CodeViewer.tsx and ApiChatMessage.tsx imported react-syntax-highlighter's
full Prism build, which eagerly registers ~250 language grammars. Switch
to prism-light with explicit registerLanguage calls for just the
languages each component actually renders (markup/json/yaml/javascript/
typescript, and json respectively); 'text' needs no registration since
the library already special-cases it as plain output.

ApiChatMessage sits behind AppLayout -> CopilotDrawer -> CopilotChatWindow
-> CopilotMessage, and AppLayout wraps every authenticated route, so the
full Prism build was previously loaded on every session regardless of
whether the copilot was opened. Lazy-load CopilotDrawer itself so none of
that chain — including the syntax highlighter — loads until a user
actually opens the drawer.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 21, 2026 10:43
@coderabbitai

coderabbitai Bot commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9ea4d8e7-890e-4101-b19e-e19723beca4f

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR introduces two new React Query hooks: useSwitchOrgToken in useOrg.ts and useFetchProjects in useProjects.ts. AppLayout is updated to use useSwitchOrgToken for async org switching and to lazy-load the CopilotDrawer component via React.lazy and Suspense. OIDCCallback and OrgHome replace direct fetchProjectsApi(0) calls with the new useFetchProjects hook. ESLint configuration gains scoped no-restricted-imports rules enforcing #api alias usage and blocking direct auth/tokenManager imports from UI-layer code, with a narrow exception for OAuth CSRF helpers. The react-syntax-highlighter usage in ApiChatMessage and CodeViewer is switched from the full Prism build to the lighter prism-light ESM build with explicit language registration.

Suggested Reviewers

  • SandaminiM
  • gabilang
🚥 Pre-merge checks | ✅ 2 | ❌ 3

❌ Failed checks (2 warnings, 1 inconclusive)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description is completely unfilled template placeholder text with no actual content addressing purpose, goals, approach, or any required sections. Complete all required sections with specific details: Purpose (with issue links), Goals, Approach, User stories, Release notes, Documentation, and Testing information for the ESLint rules and syntax highlighter optimizations.
Docstring Coverage ⚠️ Warning Docstring coverage is 22.22% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title is vague and overly broad, using non-descriptive terms that do not convey specific information about the changes. Replace with a more specific title that captures the main change, such as 'Enforce API/auth layering rules via ESLint and optimize bundle footprint' or focus on the primary objective.
✅ Passed checks (2 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ 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.

@pcnfernando

Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 21, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

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.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR tightens the UI→hooks→API layering (reducing direct data/token access from UI code), and reduces the UI footprint by deferring/downsizing heavy modules (Copilot drawer + syntax highlighting).

Changes:

  • Replaced direct #api/* usage in UI pages with hook-based imperative fetchers (useFetchProjects, useFetchProjectsByOrgId).
  • Lazy-loaded the WIP Copilot drawer and wrapped org-token switching behind a hook (useSwitchOrgToken).
  • Switched syntax highlighting to Prism “light” builds with explicit language registration to reduce bundle size.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
ipaas/src/pages/OrgHome.tsx Uses hook-based imperative project fetch instead of direct API import.
ipaas/src/pages/OIDCCallback.tsx Uses hook-based project fetch to avoid direct API access.
ipaas/src/layouts/AppLayout.tsx Lazy-loads Copilot drawer; routes org token switching through a hook.
ipaas/src/hooks/useProjects.ts Adds useFetchProjects() imperative fetcher that shares React Query cache.
ipaas/src/hooks/useOrg.ts Adds useSwitchOrgToken() wrapper around token exchange.
ipaas/src/components/CodeViewer.tsx Uses prism-light and registers only supported languages.
ipaas/src/components/AiCopilot/ApiChatMessage.tsx Uses prism-light and registers only JSON highlighting.
ipaas/eslint.config.js Adds architectural guardrails via no-restricted-imports for UI layer.

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

Comment thread ipaas/eslint.config.js Outdated
Comment on lines +121 to +128
patterns: [NO_DIRECT_API_PATTERN],
paths: [
{
name: '../auth/tokenManager',
importNames: TOKEN_MANAGER_DATA_ACCESS_EXPORTS,
message: 'Only the OAuth CSRF helpers (generateAndSaveGitHubState, validateAndClearGitHubState, validateAndClearOIDCState, getAndClearRedirectUrl) may be imported directly here — everything else must go through a hook. See src/pages/AGENTS.md.',
},
],

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

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

Inline comments:
In `@ipaas/eslint.config.js`:
- Around line 83-111: The UI-layer rule configuration for src/pages,
src/components, src/layouts, and src/contexts files does not include the product
API folder restrictions that are defined in the earlier rule. Add the product
folder pattern (the group with patterns for **/api/wip/*, **/api/cloud/*, and
**/api/icp/*) to the patterns array in the UI-layer no-restricted-imports rule
alongside NO_DIRECT_API_PATTERN so that UI-layer files cannot import directly
from literal product folders, maintaining consistency with the earlier
restriction.
- Around line 116-127: The tokenManager import restriction in the file override
for OIDCCallback.tsx, Project.tsx, and CreateIntegrationOptions.tsx uses a
denylist approach (TOKEN_MANAGER_DATA_ACCESS_EXPORTS) which implicitly allows
the four approved helpers and creates maintenance risk for future exports.
Replace the denylist with an explicit allowlist by changing the importNames
configuration from TOKEN_MANAGER_DATA_ACCESS_EXPORTS to an array containing only
the four approved helper function names: generateAndSaveGitHubState,
validateAndClearGitHubState, validateAndClearOIDCState, and
getAndClearRedirectUrl. This ensures only these specific functions are allowed
and any future additions to tokenManager will not be automatically permitted.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 29990699-0ff2-4e79-b1bc-d8ae43ccbcf8

📥 Commits

Reviewing files that changed from the base of the PR and between dc5dabd and da996aa.

📒 Files selected for processing (8)
  • ipaas/eslint.config.js
  • ipaas/src/components/AiCopilot/ApiChatMessage.tsx
  • ipaas/src/components/CodeViewer.tsx
  • ipaas/src/hooks/useOrg.ts
  • ipaas/src/hooks/useProjects.ts
  • ipaas/src/layouts/AppLayout.tsx
  • ipaas/src/pages/OIDCCallback.tsx
  • ipaas/src/pages/OrgHome.tsx

Comment thread ipaas/eslint.config.js Outdated
Comment on lines +83 to +111
files: ['src/**/*.{ts,tsx}'],
ignores: ['src/api/**'],
rules: {
'no-restricted-imports': [
'error',
{
patterns: [{ group: ['**/api/wip/*', '**/api/cloud/*', '**/api/icp/*'], message: "Import product API functions via the '#api/<domain>' alias, never a literal product folder — see AGENTS.md." }],
},
],
},
},
// UI layer (pages/components/layouts/contexts): no direct api/ access and no
// direct auth/tokenManager data access — all server state and token data
// must flow through src/hooks/. See AGENTS.md, src/pages/AGENTS.md,
// src/components/AGENTS.md.
{
files: ['src/pages/**/*.{ts,tsx}', 'src/components/**/*.{ts,tsx}', 'src/layouts/**/*.{ts,tsx}', 'src/contexts/**/*.{ts,tsx}'],
rules: {
'no-restricted-imports': [
'error',
{
patterns: [
NO_DIRECT_API_PATTERN,
{ group: ['**/auth/tokenManager'], message: 'auth/tokenManager is raw token/data access — use a hook (useAuth, useOrgUuid, ...) instead. Only the documented OAuth CSRF helpers may bypass this (src/pages/AGENTS.md) — add a file-scoped override below if you add one.' },
],
},
],
},
},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, let's check the full eslint.config.js to understand the complete configuration structure
cat -n ipaas/eslint.config.js | head -150

Repository: wso2/integration-control-plane

Length of output: 6025


🌐 Web query:

ESLint flat config overlapping files patterns rule override behavior FlatConfig

💡 Result:

In ESLint flat config, when multiple configuration objects have overlapping file patterns, ESLint resolves the final configuration by merging all matching objects in order from the top of the array to the bottom [1]. If multiple objects match a file, their configurations are combined, and the last matching configuration in the array takes precedence in the event of a conflict [1][2]. Key behaviors regarding overlapping patterns and precedence include: 1. Cascading Merge: When a file matches multiple configuration objects in the array, ESLint creates a single configuration for that file by merging properties [1]. If two objects define the same rule, the value from the object defined later in the array overrides the earlier one [1]. 2. Object Matching: A configuration object applies to a file if the file matches at least one pattern in the object's files array [1][3]. If a configuration object does not specify a files property, it applies to all files being linted [1][3]. 3. Ignores: Within a single configuration object, ignores patterns take priority over files patterns [4][3]. If a file matches both an include pattern and an ignore pattern within the same object, it is ignored [3]. 4. Extended Configs: When using extends within a configuration object, if both the base object and the extended configuration contain files, ESLint calculates the intersection (AND operation) of these patterns [5][6]. If they contain ignores, the patterns are merged (OR operation) [6]. Because the flat config system evaluates the array linearly, the order of objects in your eslint.config.js is critical for achieving the desired override behavior [1]. Configuration objects defined earlier in the array serve as the baseline, while objects defined later provide specific overrides [1]. Top results: [1][6][3][2]

Citations:


Consolidate product API folder restrictions into the UI-layer rule.

The no-restricted-imports rule at line 99 overrides the rule at line 83 for files matching src/pages|components|layouts|contexts. However, line 99's patterns omit the literal product folder restriction (**/api/wip/*, **/api/cloud/*, **/api/icp/*) defined at line 89, meaning UI-layer files can import directly from those folders without triggering the rule. Add the product folder pattern to the UI-layer rule configuration to enforce the "never a literal product folder" constraint consistently across all src code.

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

In `@ipaas/eslint.config.js` around lines 83 - 111, The UI-layer rule
configuration for src/pages, src/components, src/layouts, and src/contexts files
does not include the product API folder restrictions that are defined in the
earlier rule. Add the product folder pattern (the group with patterns for
**/api/wip/*, **/api/cloud/*, and **/api/icp/*) to the patterns array in the
UI-layer no-restricted-imports rule alongside NO_DIRECT_API_PATTERN so that
UI-layer files cannot import directly from literal product folders, maintaining
consistency with the earlier restriction.

Source: Coding guidelines

Comment thread ipaas/eslint.config.js Outdated
Comment on lines +116 to +127
files: ['src/pages/OIDCCallback.tsx', 'src/pages/Project.tsx', 'src/pages/CreateIntegrationOptions.tsx'],
rules: {
'no-restricted-imports': [
'error',
{
patterns: [NO_DIRECT_API_PATTERN],
paths: [
{
name: '../auth/tokenManager',
importNames: TOKEN_MANAGER_DATA_ACCESS_EXPORTS,
message: 'Only the OAuth CSRF helpers (generateAndSaveGitHubState, validateAndClearGitHubState, validateAndClearOIDCState, getAndClearRedirectUrl) may be imported directly here — everything else must go through a hook. See src/pages/AGENTS.md.',
},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Locate tokenManager module =="
fd -i 'tokenManager.ts$' src

echo
echo "== Exported symbols from tokenManager (for drift check) =="
rg -nP --type=ts '^\s*export\s+(const|function|async function|class|type|interface)\s+([A-Za-z0-9_]+)' src | rg 'tokenManager\.ts'

echo
echo "== Imports of tokenManager in exception pages =="
rg -nP --type=ts 'from\s+[\"\x27].*auth/tokenManager[\"\x27]' src/pages/OIDCCallback.tsx src/pages/Project.tsx src/pages/CreateIntegrationOptions.tsx

echo
echo "== Current restricted list in eslint config =="
rg -n 'TOKEN_MANAGER_DATA_ACCESS_EXPORTS|importNames|name:\s*[\"\x27]\.\./auth/tokenManager[\"\x27]' ipaas/eslint.config.js

Repository: wso2/integration-control-plane

Length of output: 216


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Repository structure (top-level) =="
ls -la

echo
echo "== Check for src directory and ipaas directory =="
find . -maxdepth 2 -type d -name 'src' -o -name 'ipaas' 2>/dev/null | head -20

echo
echo "== List ipaas directory =="
ls -la ipaas/ 2>/dev/null || echo "ipaas directory not found"

Repository: wso2/integration-control-plane

Length of output: 2299


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Relevant lines from ipaas/eslint.config.js (110-135) =="
sed -n '110,135p' ipaas/eslint.config.js

echo
echo "== Search for TOKEN_MANAGER_DATA_ACCESS_EXPORTS definition =="
rg -n 'TOKEN_MANAGER_DATA_ACCESS_EXPORTS' ipaas/eslint.config.js

echo
echo "== Locate tokenManager module =="
find ipaas/src -name '*tokenManager*' -type f 2>/dev/null

echo
echo "== Exported symbols from tokenManager =="
rg -nP --type=ts '^\s*export\s+(const|function|async function|class|type|interface)\s+([A-Za-z0-9_]+)' ipaas/src | grep -i 'tokenmanager' || echo "No matches found"

echo
echo "== All content of tokenManager.ts =="
find ipaas/src -name '*tokenManager.ts' -type f -exec cat {} \;

Repository: wso2/integration-control-plane

Length of output: 21281


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== TOKEN_MANAGER_DATA_ACCESS_EXPORTS definition (lines 25-40) =="
sed -n '25,40p' ipaas/eslint.config.js

echo
echo "== Check actual imports in OIDCCallback.tsx =="
rg -n 'from.*tokenManager' ipaas/src/pages/OIDCCallback.tsx

echo
echo "== Check actual imports in Project.tsx =="
rg -n 'from.*tokenManager' ipaas/src/pages/Project.tsx

echo
echo "== Check actual imports in CreateIntegrationOptions.tsx =="
rg -n 'from.*tokenManager' ipaas/src/pages/CreateIntegrationOptions.tsx

Repository: wso2/integration-control-plane

Length of output: 1100


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Full TOKEN_MANAGER_DATA_ACCESS_EXPORTS definition (lines 25-50) =="
sed -n '25,50p' ipaas/eslint.config.js

echo
echo "== Count of exports in TOKEN_MANAGER_DATA_ACCESS_EXPORTS =="
sed -n '28,50p' ipaas/eslint.config.js | grep -c "'" || true

echo
echo "== All exported symbols from tokenManager for comparison =="
rg -nP '^\s*export\s+(const|function|async function)\s+([A-Za-z0-9_]+)' ipaas/src/auth/tokenManager.ts | wc -l

echo
echo "== Exported symbols not in denylist =="
rg -oP '^\s*export\s+(const|function|async function)\s+\K([A-Za-z0-9_]+)' ipaas/src/auth/tokenManager.ts > /tmp/all_exports.txt
sed -n '28,50p' ipaas/eslint.config.js | grep -oP "'\K[^']+" > /tmp/denylist.txt
echo "All exports:"
cat /tmp/all_exports.txt
echo
echo "Denylist:"
cat /tmp/denylist.txt

Repository: wso2/integration-control-plane

Length of output: 1958


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Understanding ESLint no-restricted-imports behavior =="
echo "The 'importNames' array in ESLint's no-restricted-imports is a DENYLIST:"
echo "- It blocks imports of the listed names"
echo "- Unlisted names are implicitly allowed"
echo

echo "== Exported symbols NOT in the denylist (implicitly allowed) =="
comm -23 <(sort /tmp/all_exports.txt) <(grep -oP "'\K[^']+" ipaas/eslint.config.js | sort -u) | sort

echo
echo "== Verify: These 4 should be the approved helpers =="
echo "Expected approved helpers:"
echo "  generateAndSaveGitHubState"
echo "  validateAndClearGitHubState"
echo "  validateAndClearOIDCState"
echo "  getAndClearRedirectUrl"

Repository: wso2/integration-control-plane

Length of output: 412


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== All exported symbols from tokenManager =="
rg -oP '^\s*export\s+(const|function|async function)\s+\K([A-Za-z0-9_]+)' ipaas/src/auth/tokenManager.ts | sort > /tmp/all_exports.txt
cat /tmp/all_exports.txt

echo
echo "== Names in the denylist =="
sed -n '28,50p' ipaas/eslint.config.js | grep -oP "'\K[^']+" | grep -v '^,$' | sort > /tmp/denylist.txt
cat /tmp/denylist.txt

echo
echo "== Exported symbols NOT in the denylist (these are allowed) =="
grep -v -f /tmp/denylist.txt /tmp/all_exports.txt || echo "(none)"

echo
echo "== These 4 should be implicitly allowed =="
echo "generateAndSaveGitHubState"
echo "validateAndClearGitHubState"
echo "validateAndClearOIDCState"
echo "getAndClearRedirectUrl"

Repository: wso2/integration-control-plane

Length of output: 1316


Denylist approach to tokenManager imports in these pages creates maintenance risk; prefer an allowlist for the four approved helpers.

The importNames: TOKEN_MANAGER_DATA_ACCESS_EXPORTS denylist blocks 21 known exports, leaving the four approved helpers (generateAndSaveGitHubState, validateAndClearGitHubState, validateAndClearOIDCState, getAndClearRedirectUrl) implicitly allowed. Any new exports added to tokenManager.ts in the future will automatically be permitted in these three pages unless the denylist is explicitly maintained. Switch to an allowlist that explicitly permits only these four names to enforce the intended boundary without relying on ongoing denylist updates.

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

In `@ipaas/eslint.config.js` around lines 116 - 127, The tokenManager import
restriction in the file override for OIDCCallback.tsx, Project.tsx, and
CreateIntegrationOptions.tsx uses a denylist approach
(TOKEN_MANAGER_DATA_ACCESS_EXPORTS) which implicitly allows the four approved
helpers and creates maintenance risk for future exports. Replace the denylist
with an explicit allowlist by changing the importNames configuration from
TOKEN_MANAGER_DATA_ACCESS_EXPORTS to an array containing only the four approved
helper function names: generateAndSaveGitHubState, validateAndClearGitHubState,
validateAndClearOIDCState, and getAndClearRedirectUrl. This ensures only these
specific functions are allowed and any future additions to tokenManager will not
be automatically permitted.

Source: Coding guidelines

pcnfernando and others added 4 commits June 21, 2026 16:26
Adds a unit test runner (none existed — only e2e Playwright, which needs
a live backend and credentials) and covers the four pure-logic modules
flagged in the architecture report: identifyIntegration.ts (including
the componentSubType-overrides-displayType precedence rules),
componentType.ts, nav.ts's scope/URL helpers and matrix-driven routing
(generateMatrixRoutes/resourceUrl/sidebarItems), and runtimeConfig.ts's
config.json merge/trim/fallback logic.

#api/#product resolve to wip in tests (vitest.config.ts), matching
tsconfig.app.json's IDE default. Tests import vitest's API explicitly
(no injected globals), consistent with the rest of the codebase.

Note: pnpm-lock.yaml is not yet updated for the new vitest/jsdom
devDependencies — this sandbox's pnpm requires Node >=22.13 and the repo
has Node 20.20.2, so `pnpm install` couldn't be run here. Run `pnpm
install` and commit the resulting lockfile before relying on
--frozen-lockfile (CI, Dockerfile) for installs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Flat config doesn't merge no-restricted-imports option objects across
matching blocks for the same file — the last matching block's value
replaces the earlier one entirely, it doesn't union the `patterns`
arrays. The UI-layer block (pages/components/layouts/contexts) and the
named OAuth-CSRF-exception block both redefined no-restricted-imports
without the repo-wide "never a literal product folder" pattern, so
those files could import src/api/wip/cloud/icp directly and lint would
pass. Factor the pattern into a shared constant and include it in every
block that sets the rule.

Verified by reproducing the gap (an import from '../api/wip/components'
in a pages/ file passed lint before this fix) and confirming it's now
caught in all three affected blocks, with no false positives on the
existing exception files.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
A denylist (importNames: TOKEN_MANAGER_DATA_ACCESS_EXPORTS) silently
permits any future tokenManager.ts export by default — exactly the
maintenance risk flagged in review. ESLint's no-restricted-imports has
no "allow only these names" mode, so fix this structurally instead of
in config: move the six pure OAuth CSRF state helpers (no token/network
access) into their own module, src/auth/oauthState.ts.

The UI-layer ESLint block now blocks auth/tokenManager outright for
pages/components/layouts/contexts, with no per-file exception — the
three documented pages (and useGitHubAuth.ts, ProtectedRoute.tsx,
AuthContext.tsx) import the CSRF helpers from oauthState.ts instead,
which the rule doesn't restrict. A new tokenManager.ts export is now
blocked from UI code by default; it would have to be added to
oauthState.ts first to become reachable there. Updated AGENTS.md and
src/pages/AGENTS.md to describe the new module instead of the old
exception list.

Verified: a page importing a never-seen-before tokenManager export
(simulating a future addition) is now rejected; the three real pages
still pass with their actual oauthState imports; the full lint, the
81-test unit suite, and a scoped tsc check of every touched file are
all clean.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Runs pnpm lint, pnpm test (Vitest), and pnpm build:check (tsc -b + a
real PRODUCT=wip build) on every PR touching ipaas/** and on push to
main/devant-migration. None of this needs live credentials or a
reachable backend, unlike the existing E2E workflows, so it also runs
on push for branch-health visibility.

Mirrors e2e-pr-check.yml's pnpm/Node setup (pnpm 9, Node 20) for
consistency with the one CI workflow already proven to work in this
repo. Not wired into branch protection as a required check — same
opt-in posture as the existing E2E checks; the comment in the workflow
explains how to make it required.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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