Skip to content

fix(web): enforce project prefix boundaries#1601

Merged
ashish921998 merged 1 commit into
mainfrom
codex/fix-project-prefix-boundaries
May 1, 2026
Merged

fix(web): enforce project prefix boundaries#1601
ashish921998 merged 1 commit into
mainfrom
codex/fix-project-prefix-boundaries

Conversation

@ashish921998

Copy link
Copy Markdown
Contributor

Summary

  • enforce session prefix boundary matching for project resolution and filtering
  • prevent longer prefixes like appx-* from leaking into app views
  • add regression coverage for resolveProject and filterProjectSessions

Tests

  • pnpm --filter @aoagents/ao-web test -- src/lib/tests/project-utils.test.ts src/lib/tests/serialize.test.ts

@github-actions

github-actions Bot commented May 1, 2026

Copy link
Copy Markdown
Contributor

Test Coverage Report

Changed files have no coverage data (not instrumented or no tests ran).

@greptile-apps

greptile-apps Bot commented May 1, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a prefix-boundary bug where a session like appx-1 would incorrectly match the app project because "appx-1".startsWith("app") is true. The fix introduces a matchesSessionPrefix helper that requires the session ID to either equal the prefix exactly or start with prefix + "-", and adds regression tests in both project-utils and serialize.

Confidence Score: 5/5

Safe to merge — the fix is minimal, well-tested, and correctly scoped.

All findings are P2. The logic change is correct and both affected code paths are covered by new regression tests. The only remaining concern is that matchesSessionPrefix is duplicated across two files, which is a maintainability issue but not a correctness problem.

No files require special attention.

Important Files Changed

Filename Overview
packages/web/src/lib/project-utils.ts Adds matchesSessionPrefix helper and applies it in matchesProject; correctly guards with project?.sessionPrefix && since local ProjectWithPrefix type marks the field optional.
packages/web/src/lib/serialize.ts Adds an identical matchesSessionPrefix helper and applies it in resolveProject; ProjectConfig.sessionPrefix is non-optional so no null-guard needed, but the function is a duplicate of the one in project-utils.ts.
packages/web/src/lib/tests/project-utils.test.ts New test file; adds regression coverage for the app / appx prefix-containment bug in filterProjectSessions.
packages/web/src/lib/tests/serialize.test.ts Adds a regression test for resolveProject that verifies appx-1 resolves to the appx project and not app; also imports the previously-unused enrichSessionIssue.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["Session ID: appx-1\nprojectId: unknown"] --> B{Direct projectId\nmatch in projects?}
    B -- No --> C{matchesSessionPrefix\nfor each project}
    C --> D["app: 'appx-1' === 'app'?\nOR 'appx-1'.startsWith('app-')?"]
    D -- "false / false → NO MATCH" --> E["appx: 'appx-1' === 'appx'?\nOR 'appx-1'.startsWith('appx-')?"]
    E -- "false / true → MATCH" --> F["✅ Resolves to appx project"]
    B -- Yes --> G["✅ Return direct match"]

    style D fill:#f9c,stroke:#c66
    style E fill:#cfc,stroke:#6a6
    style F fill:#cfc,stroke:#6a6
Loading
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
packages/web/src/lib/serialize.ts:44-46
**Duplicated helper across modules**

`matchesSessionPrefix` is now defined identically in both `serialize.ts` and `project-utils.ts`. If the boundary-matching logic ever needs to change again (e.g. supporting slash-delimited prefixes or case-insensitive matching), it will need to be updated in two places — exactly the kind of drift that caused the original bug. Consider extracting it to a shared utility (e.g. `lib/session-utils.ts`) and importing it in both files.

Reviews (1): Last reviewed commit: "fix(qa): ISSUE-001 — enforce project pre..." | Re-trigger Greptile

Comment thread packages/web/src/lib/serialize.ts Outdated
@ashish921998

Copy link
Copy Markdown
Contributor Author

This fixes a QA-discovered dashboard regression, not an existing GitHub issue.

It is related to multi-project prefix handling, but distinct from #1323 / #1356:

@ashish921998 ashish921998 force-pushed the codex/fix-project-prefix-boundaries branch from 90a64a9 to 06c5519 Compare May 1, 2026 10:00

@i-trytoohard i-trytoohard 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.

Review: fix(web): enforce project prefix boundaries

Fix is correct — startsWith('app') matching appx-1 was a real prefix containment bug. The sessionId === prefix || sessionId.startsWith(prefix + "-") logic is right, and both affected code paths are updated consistently. Tests cover both paths. No security or perf concerns.

Actionable items

  1. P2 — Duplicated helper. matchesSessionPrefix is copy-pasted identically into both serialize.ts and project-utils.ts. This is the same drift pattern that caused the original bug. Recommend extracting to a shared utility (e.g. lib/session-utils.ts) and importing in both places.

  2. P3 — Unused import. enrichSessionIssue is imported in serialize.test.ts but never used — minor lint noise, worth cleaning up.

Approved. Consolidate that helper before or right after merge.

@ashish921998

Copy link
Copy Markdown
Contributor Author

Review: fix(web): enforce project prefix boundaries

Fix is correct — startsWith('app') matching appx-1 was a real prefix containment bug. The sessionId === prefix || sessionId.startsWith(prefix + "-") logic is right, and both affected code paths are updated consistently. Tests cover both paths. No security or perf concerns.

Actionable items

  1. P2 — Duplicated helper. matchesSessionPrefix is copy-pasted identically into both serialize.ts and project-utils.ts. This is the same drift pattern that caused the original bug. Recommend extracting to a shared utility (e.g. lib/session-utils.ts) and importing in both places.
  2. P3 — Unused import. enrichSessionIssue is imported in serialize.test.ts but never used — minor lint noise, worth cleaning up.

Approved. Consolidate that helper before or right after merge.

P2 is correct.
matchesSessionPrefix is duplicated in both:

packages/web/src/lib/serialize.ts
packages/web/src/lib/project-utils.ts
The reviewer’s point is fair: since both places implement the same project-prefix rule, extracting it to something like packages/web/src/lib/session-utils.ts would reduce drift risk.

P3 is not correct.
enrichSessionIssue is imported in serialize.test.ts, but it is used later in the file:

enrichSessionIssue(dashboard, tracker, testProject);
So that import is not unused. The reviewer may have looked only at the diff hunk and missed the existing usage lower down.

@ashish921998 ashish921998 merged commit ac9ab7d into main May 1, 2026
10 checks passed
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