Skip to content

feat(assets): add ownership navigation - #176

Merged
kl3inIT merged 7 commits into
mainfrom
feat/asset-ownership-layout
Jul 31, 2026
Merged

feat(assets): add ownership navigation#176
kl3inIT merged 7 commits into
mainfrom
feat/asset-ownership-layout

Conversation

@kl3inIT

@kl3inIT kl3inIT commented Jul 31, 2026

Copy link
Copy Markdown
Owner

Summary

  • add a server-paged My Assets workspace derived from active direct OWNER assignments and capped by live can_view
  • restructure /assets around the Onyx information hierarchy: page identity/CTA, search plus All Assets | My Assets, then compact secondary filters
  • preserve OrgMemory theme tokens, shadcn/Radix primitives, released catalog behavior, URL state, and governance links
  • add desktop/mobile browser proof, design QA, OpenAPI contract, and current Asset Registry documentation

Documentation impact

  • refreshed the generated public OpenAPI reference for GET /api/assets/owned
  • reconciled the Asset Registry domain spec and test matrix
  • archived the Onyx reference and final desktop/mobile design evidence

Reader-visible behavior changes in the authenticated product and API reference. The public product-guide information architecture does not change.

Verification

  • ./gradlew.bat --no-daemon test
  • targeted owned-Asset API integration test
  • OpenAPI contract test
  • pnpm --dir apps/web test:unit (30 tests)
  • pnpm --dir apps/web build
  • pnpm --dir apps/web test:e2e (13 tests)
  • pnpm --filter @orgmemory/docs check
  • pnpm release:check
  • git diff --check

Design evidence

See docs/increments/completed/2026-07-31-asset-ownership-navigation/ and root design-qa.md.

@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

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

Next review available in: 21 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

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

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

How do review limits work?

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

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

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: ab19f118-8a78-4eaf-baa8-4b0e9de2a1c5

📥 Commits

Reviewing files that changed from the base of the PR and between 287802d and a73f9c4.

⛔ Files ignored due to path filters (12)
  • apps/docs/generated/openapi.public.json is excluded by !**/generated/**
  • docs/increments/completed/2026-07-31-asset-ownership-navigation/asset-catalog-grid.png is excluded by !**/*.png, !docs/**
  • docs/increments/completed/2026-07-31-asset-ownership-navigation/asset-catalog-mine.png is excluded by !**/*.png, !docs/**
  • docs/increments/completed/2026-07-31-asset-ownership-navigation/asset-catalog-mobile.png is excluded by !**/*.png, !docs/**
  • docs/increments/completed/2026-07-31-asset-ownership-navigation/asset-layout-comparison.png is excluded by !**/*.png, !docs/**
  • docs/increments/completed/2026-07-31-asset-ownership-navigation/design.md is excluded by !docs/**
  • docs/increments/completed/2026-07-31-asset-ownership-navigation/onyx-agents-layout-reference.png is excluded by !**/*.png, !docs/**
  • docs/increments/completed/2026-07-31-asset-ownership-navigation/plan.md is excluded by !docs/**
  • docs/increments/completed/2026-07-31-asset-ownership-navigation/verification.md is excluded by !docs/**
  • docs/roadmap.md is excluded by !docs/**
  • docs/specs/domains/asset-registry.md is excluded by !docs/**
  • docs/tests/domains/asset-registry.md is excluded by !docs/**
📒 Files selected for processing (7)
  • .tegami/asset-ownership-navigation.md
  • apps/docs/content/docs/reference/api-reference/assets.mdx
  • apps/web/src/features/assets/components/asset-catalog-page.tsx
  • apps/web/src/features/assets/components/asset-type-filter.test.tsx
  • apps/web/test/e2e/asset-registry-golden-poc.spec.ts
  • core/src/main/java/com/orgmemory/core/assetregistry/AssetRepository.java
  • design-qa.md
📝 Walkthrough

Walkthrough

The change adds an authenticated owned-assets API, active-owner filtering, pagination, and sorting. The web catalog adds All Assets/My Assets scopes, scope-specific sorting, owned-asset rendering, governance links, responsive controls, and related integration, unit, E2E, and QA coverage.

Changes

Owned asset catalog

Layer / File(s) Summary
Owned asset retrieval
core/src/main/java/com/orgmemory/core/assetregistry/*, apps/api/src/main/java/com/orgmemory/api/assetregistry/AssetRegistryController.java, core/src/test/..., apps/api/src/test/...
The asset registry now returns paginated summaries for assets with active owner assignments and view authorization. The API exposes GET /api/assets/owned.
Catalog scope and filter state
apps/web/src/features/assets/asset-catalog-state.*, apps/web/src/features/assets/components/asset-type-filter.*, apps/web/src/routes/_authenticated/assets/index.tsx
Catalog search state supports the MINE scope and scope-specific sorting. The route updates scope URLs and resets sort and pagination. The type filter uses a select control.
Scoped catalog rendering
apps/web/src/features/assets/components/asset-catalog-page.tsx, apps/web/test/e2e/*, apps/web/test/setup.ts, design-qa.md
The catalog renders owned assets with portfolio status, updated dates, governance links, pagination, loading and empty states. E2E fixtures and responsive checks cover the new scope.

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

Sequence Diagram(s)

sequenceDiagram
  actor User
  participant AssetCatalogPage
  participant AssetRegistryController
  participant AssetRegistryService
  participant AssetRegistryCoordinator
  participant AssetRepository

  User->>AssetCatalogPage: Select My Assets
  AssetCatalogPage->>AssetRegistryController: Request owned assets
  AssetRegistryController->>AssetRegistryService: Pass filters and pagination
  AssetRegistryService->>AssetRegistryCoordinator: Resolve authorized owned assets
  AssetRegistryCoordinator->>AssetRepository: Query summaries and count
  AssetRepository-->>AssetRegistryCoordinator: Return page data
  AssetRegistryCoordinator-->>AssetRegistryController: Return AssetSummaryPage
  AssetRegistryController-->>AssetCatalogPage: Render owned assets
Loading

Possibly related PRs

  • kl3inIT/OrgMemory#62: Extends the same asset-registry owned-assets functionality and shared coordinator and integration-test areas.
  • kl3inIT/OrgMemory#94: Introduced the catalog state, page, route, and E2E harness extended by this change.
  • kl3inIT/OrgMemory#154: Changes the same catalog state, page, route, and type-filter components.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 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.
Title check ✅ Passed The title clearly identifies the main change: adding ownership navigation to the assets experience.
Description check ✅ Passed The description covers the required summary, verification evidence, documentation impact, and design evidence.
✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🛠️ Fix failing CI checks 💡
  • Fix failing CI checks
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/asset-ownership-layout

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.

@github-actions

github-actions Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Tegami

This repository uses Tegami to manage releases. When your changes affect published packages, add a changelog file under .tegami/ before merging.

Create a changelog → · Changelog format

Release preview

Package Bump Version
orgmemory patch 0.1.10.1.2

Changelogs in this PR

Changelog Title
asset-ownership-navigation.md Improvements

Run pnpm run tegami locally to create a changelog interactively.

Managed by Tegami.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 8

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

Inline comments:
In `@apps/web/src/features/assets/components/asset-catalog-page.tsx`:
- Around line 226-284: Refactor AssetGrid and OwnedAssetGrid to share a single
presentational asset-card component, parameterizing only the top-right badge,
coordinate display, link component, and action label. Extract a shared column
factory used by catalogColumns and ownedColumns, preserving all existing
headerClassName and cellClassName values and scope-specific behavior. Keep the
existing design tokens, shadcn primitives, and responsive layout unchanged.
- Around line 73-83: Update isOwnedAsset to accept summary values that are empty
strings by checking only for null or undefined, while retaining the existing
required-field checks. Validate portfolioState against the four supported
OwnedAsset states rather than relying on truthiness, and update portfolioLabel
to include an explicit exhaustive fallback for unsupported states.

In `@apps/web/src/features/assets/components/asset-type-filter.test.tsx`:
- Around line 8-14: Update the test “exposes every governed Asset profile and
the active selection” to open the combobox and assert every option declared by
AssetTypeFilter, including the active “Skills” selection; do not limit coverage
to the collapsed trigger text.

In `@apps/web/test/e2e/asset-registry-golden-poc.spec.ts`:
- Around line 308-318: Update the /api/assets/owned handler in the test mock to
inspect url.searchParams and validate the received page, sort, q, and type
values. Return page-appropriate data or record these parameters for assertions,
including verifying the MINE scope uses the expected sort and resets page after
a scope change.

In
`@core/src/main/java/com/orgmemory/core/assetregistry/AssetRegistryCoordinator.java`:
- Around line 261-278: The owner asset filtering used by
AssetRegistryCoordinator and the shared recommendationPage/summaries paths
passes an unbounded ids collection into searchOwnedSummaries, causing oversized
IN predicates per page. Replace this pattern with a database-side ownership
predicate using a join or exists against AssetRoleAssignment, or apply a
documented owner-set limit if that is the established capacity strategy, while
preserving the active OWNER and can_view intersection and pagination behavior.

In `@core/src/main/java/com/orgmemory/core/assetregistry/AssetRepository.java`:
- Around line 149-186: Extract the duplicated FROM and WHERE predicates used by
searchAuthorized, searchOwnedSummaries, and its countQuery into a single shared
constant, following the existing CATALOG_FROM_AND_PREDICATES pattern. Replace
all three inline blocks with that constant while preserving their existing
joins, filters, parameters, and query behavior.

In `@core/src/main/java/com/orgmemory/core/assetregistry/AssetSummary.java`:
- Around line 14-15: Update the MCP AssetSummary record in
AssetDeliveryApiClient to include the updatedAt field, then update every new
AssetDeliveryApiClient.AssetSummary construction in the assets tests to pass the
ninth argument using the appropriate timestamp value.

In `@design-qa.md`:
- Around line 5-11: Update the artifact references in the design-qa document to
match the outputs generated by asset-registry-golden-poc.spec.ts: use the
../output/design-qa/ directory, rename the mine capture to
asset-catalog-mine.png, remove or replace the unsupported
asset-catalog-all-desktop.png reference, and add the directory prefix to the two
bare filenames.
🪄 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: ASSERTIVE

Plan: Pro Plus

Run ID: 6950eefc-4afb-410c-9d52-6692f0fd7e8a

📥 Commits

Reviewing files that changed from the base of the PR and between fef0962 and 287802d.

⛔ Files ignored due to path filters (11)
  • contracts/openapi.json is excluded by !contracts/openapi.json
  • docs/increments/active/2026-07-31-asset-ownership-navigation/asset-catalog-all-desktop.png is excluded by !**/*.png, !docs/**
  • docs/increments/active/2026-07-31-asset-ownership-navigation/asset-catalog-mine-desktop.png is excluded by !**/*.png, !docs/**
  • docs/increments/active/2026-07-31-asset-ownership-navigation/asset-catalog-mobile.png is excluded by !**/*.png, !docs/**
  • docs/increments/active/2026-07-31-asset-ownership-navigation/asset-layout-comparison.png is excluded by !**/*.png, !docs/**
  • docs/increments/active/2026-07-31-asset-ownership-navigation/design.md is excluded by !docs/**
  • docs/increments/active/2026-07-31-asset-ownership-navigation/onyx-agents-layout-reference.png is excluded by !**/*.png, !docs/**
  • docs/increments/active/2026-07-31-asset-ownership-navigation/plan.md is excluded by !docs/**
  • docs/roadmap.md is excluded by !docs/**
  • docs/specs/domains/asset-registry.md is excluded by !docs/**
  • docs/tests/domains/asset-registry.md is excluded by !docs/**
📒 Files selected for processing (19)
  • apps/api/src/main/java/com/orgmemory/api/assetregistry/AssetRegistryController.java
  • apps/api/src/test/java/com/orgmemory/api/assetregistry/AssetRegistryIntegrationTests.java
  • apps/web/src/features/assets/asset-catalog-state.test.ts
  • apps/web/src/features/assets/asset-catalog-state.ts
  • apps/web/src/features/assets/components/asset-catalog-page.tsx
  • apps/web/src/features/assets/components/asset-type-filter.test.tsx
  • apps/web/src/features/assets/components/asset-type-filter.tsx
  • apps/web/src/routes/_authenticated/assets/index.tsx
  • apps/web/test/e2e/asset-registry-golden-poc.spec.ts
  • apps/web/test/setup.ts
  • core/src/main/java/com/orgmemory/core/assetregistry/AssetOwnedSort.java
  • core/src/main/java/com/orgmemory/core/assetregistry/AssetRegistryCoordinator.java
  • core/src/main/java/com/orgmemory/core/assetregistry/AssetRegistryService.java
  • core/src/main/java/com/orgmemory/core/assetregistry/AssetRepository.java
  • core/src/main/java/com/orgmemory/core/assetregistry/AssetRoleAssignmentRepository.java
  • core/src/main/java/com/orgmemory/core/assetregistry/AssetSummary.java
  • core/src/main/java/com/orgmemory/core/assetregistry/AssetSummaryPage.java
  • core/src/test/java/com/orgmemory/core/assetregistry/AssetRegistryServiceTests.java
  • design-qa.md
📜 Review details
⏰ Context from checks skipped due to timeout. (2)
  • GitHub Check: Backend · Java 25
  • GitHub Check: Web · Node 24
🧰 Additional context used
📓 Path-based instructions (9)
**/*

📄 CodeRabbit inference engine (CLAUDE.md)

**/*: Always read the repository guidance and relevant sections of ARCHITECTURE.md; before changing a domain, read its specification, test-coverage document, and binding decision filenames.
Treat the repository as the engineering system of record; current repository and runtime evidence take precedence over chat or Northstar.
Read docs/guidelines/agent-safety.md before retrieval, AI, MCP, permission, upload, graph, or export work. Never commit secrets or customer data.

Files:

  • apps/web/test/setup.ts
  • core/src/main/java/com/orgmemory/core/assetregistry/AssetSummaryPage.java
  • apps/api/src/main/java/com/orgmemory/api/assetregistry/AssetRegistryController.java
  • core/src/main/java/com/orgmemory/core/assetregistry/AssetRegistryService.java
  • apps/web/src/features/assets/components/asset-type-filter.test.tsx
  • design-qa.md
  • apps/web/test/e2e/asset-registry-golden-poc.spec.ts
  • core/src/main/java/com/orgmemory/core/assetregistry/AssetSummary.java
  • core/src/main/java/com/orgmemory/core/assetregistry/AssetRegistryCoordinator.java
  • apps/web/src/features/assets/asset-catalog-state.test.ts
  • apps/web/src/routes/_authenticated/assets/index.tsx
  • core/src/test/java/com/orgmemory/core/assetregistry/AssetRegistryServiceTests.java
  • apps/web/src/features/assets/asset-catalog-state.ts
  • core/src/main/java/com/orgmemory/core/assetregistry/AssetRepository.java
  • apps/web/src/features/assets/components/asset-type-filter.tsx
  • core/src/main/java/com/orgmemory/core/assetregistry/AssetOwnedSort.java
  • core/src/main/java/com/orgmemory/core/assetregistry/AssetRoleAssignmentRepository.java
  • apps/web/src/features/assets/components/asset-catalog-page.tsx
  • apps/api/src/test/java/com/orgmemory/api/assetregistry/AssetRegistryIntegrationTests.java
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{js,jsx,ts,tsx}: Frontend verification must include lint, typecheck, tests, production build, and browser verification when the flow matters.
Before using unfamiliar React, Vite, Tailwind, TypeScript, Next.js, or Fumadocs APIs, consult current official documentation, Context7, and the relevant project verification skill.

Files:

  • apps/web/test/setup.ts
  • apps/web/src/features/assets/components/asset-type-filter.test.tsx
  • apps/web/test/e2e/asset-registry-golden-poc.spec.ts
  • apps/web/src/features/assets/asset-catalog-state.test.ts
  • apps/web/src/routes/_authenticated/assets/index.tsx
  • apps/web/src/features/assets/asset-catalog-state.ts
  • apps/web/src/features/assets/components/asset-type-filter.tsx
  • apps/web/src/features/assets/components/asset-catalog-page.tsx
apps/web/**/*.{ts,tsx}

📄 CodeRabbit inference engine (apps/web/CLAUDE.md)

apps/web/**/*.{ts,tsx}: Extend the established OrgMemory product shell, design tokens, shadcn/Radix primitives, and existing layout patterns; do not introduce a separate visual system in the web application.
Generate ordinary REST clients from contracts/openapi.json using Hey API.
Use TanStack Query for server state, TanStack Router for navigation, and limit Zustand to durable or high-frequency UI state.
Preserve keyboard accessibility, light/dark theme support, loading and error states, and responsive behavior in the web application.

Files:

  • apps/web/test/setup.ts
  • apps/web/src/features/assets/components/asset-type-filter.test.tsx
  • apps/web/test/e2e/asset-registry-golden-poc.spec.ts
  • apps/web/src/features/assets/asset-catalog-state.test.ts
  • apps/web/src/routes/_authenticated/assets/index.tsx
  • apps/web/src/features/assets/asset-catalog-state.ts
  • apps/web/src/features/assets/components/asset-type-filter.tsx
  • apps/web/src/features/assets/components/asset-catalog-page.tsx
**/*.{java,gradle,gradle.kts,properties,yml,yaml}

📄 CodeRabbit inference engine (CLAUDE.md)

Before using unfamiliar Spring Boot 4, Spring Modulith 2, Spring AI 2, or Gradle APIs, consult current official documentation, Context7, and the relevant project verification skill.

Files:

  • core/src/main/java/com/orgmemory/core/assetregistry/AssetSummaryPage.java
  • apps/api/src/main/java/com/orgmemory/api/assetregistry/AssetRegistryController.java
  • core/src/main/java/com/orgmemory/core/assetregistry/AssetRegistryService.java
  • core/src/main/java/com/orgmemory/core/assetregistry/AssetSummary.java
  • core/src/main/java/com/orgmemory/core/assetregistry/AssetRegistryCoordinator.java
  • core/src/test/java/com/orgmemory/core/assetregistry/AssetRegistryServiceTests.java
  • core/src/main/java/com/orgmemory/core/assetregistry/AssetRepository.java
  • core/src/main/java/com/orgmemory/core/assetregistry/AssetOwnedSort.java
  • core/src/main/java/com/orgmemory/core/assetregistry/AssetRoleAssignmentRepository.java
  • apps/api/src/test/java/com/orgmemory/api/assetregistry/AssetRegistryIntegrationTests.java
**/*.{java,sql}

📄 CodeRabbit inference engine (CLAUDE.md)

Keep ddl-auto=validate and pair every persisted-model change with a Flyway migration.

Files:

  • core/src/main/java/com/orgmemory/core/assetregistry/AssetSummaryPage.java
  • apps/api/src/main/java/com/orgmemory/api/assetregistry/AssetRegistryController.java
  • core/src/main/java/com/orgmemory/core/assetregistry/AssetRegistryService.java
  • core/src/main/java/com/orgmemory/core/assetregistry/AssetSummary.java
  • core/src/main/java/com/orgmemory/core/assetregistry/AssetRegistryCoordinator.java
  • core/src/test/java/com/orgmemory/core/assetregistry/AssetRegistryServiceTests.java
  • core/src/main/java/com/orgmemory/core/assetregistry/AssetRepository.java
  • core/src/main/java/com/orgmemory/core/assetregistry/AssetOwnedSort.java
  • core/src/main/java/com/orgmemory/core/assetregistry/AssetRoleAssignmentRepository.java
  • apps/api/src/test/java/com/orgmemory/api/assetregistry/AssetRegistryIntegrationTests.java
**/*.{java,gradle,gradle.kts}

📄 CodeRabbit inference engine (CLAUDE.md)

Use the testing harness; a terminating clean test is the JVM context gate, and bootRun is not verification. IDE inspection applies only to edited backend Java.

Files:

  • core/src/main/java/com/orgmemory/core/assetregistry/AssetSummaryPage.java
  • apps/api/src/main/java/com/orgmemory/api/assetregistry/AssetRegistryController.java
  • core/src/main/java/com/orgmemory/core/assetregistry/AssetRegistryService.java
  • core/src/main/java/com/orgmemory/core/assetregistry/AssetSummary.java
  • core/src/main/java/com/orgmemory/core/assetregistry/AssetRegistryCoordinator.java
  • core/src/test/java/com/orgmemory/core/assetregistry/AssetRegistryServiceTests.java
  • core/src/main/java/com/orgmemory/core/assetregistry/AssetRepository.java
  • core/src/main/java/com/orgmemory/core/assetregistry/AssetOwnedSort.java
  • core/src/main/java/com/orgmemory/core/assetregistry/AssetRoleAssignmentRepository.java
  • apps/api/src/test/java/com/orgmemory/api/assetregistry/AssetRegistryIntegrationTests.java
apps/api/src/main/java/**/*.java

⚙️ CodeRabbit configuration file

apps/api/src/main/java/**/*.java: Enforce the browser-BFF and resource-server boundaries. Authentication
must resolve an active internal actor through the explicit issuer and
subject binding. Reject identity, tenant, roles, or permissions supplied
by request payloads, JWT email, or untrusted JWT role claims.

Files:

  • apps/api/src/main/java/com/orgmemory/api/assetregistry/AssetRegistryController.java
apps/web/**/*.{test,spec}.{ts,tsx}

📄 CodeRabbit inference engine (apps/web/CLAUDE.md)

Preserve the existing browser test suite when changing the web application.

Files:

  • apps/web/src/features/assets/components/asset-type-filter.test.tsx
  • apps/web/test/e2e/asset-registry-golden-poc.spec.ts
  • apps/web/src/features/assets/asset-catalog-state.test.ts
apps/web/src/**/*.{ts,tsx}

⚙️ CodeRabbit configuration file

apps/web/src/**/*.{ts,tsx}: OAuth access and refresh tokens must never enter browser JavaScript or
browser storage. Use the HttpOnly BFF session, CSRF-protected mutations,
generated Hey API data clients, accessible states, and both light and
dark themes. Handwritten transport is reserved for documented protocol
flows such as navigation redirects and streaming.

Files:

  • apps/web/src/features/assets/components/asset-type-filter.test.tsx
  • apps/web/src/features/assets/asset-catalog-state.test.ts
  • apps/web/src/routes/_authenticated/assets/index.tsx
  • apps/web/src/features/assets/asset-catalog-state.ts
  • apps/web/src/features/assets/components/asset-type-filter.tsx
  • apps/web/src/features/assets/components/asset-catalog-page.tsx
🧠 Learnings (1)
📚 Learning: 2026-07-26T05:46:47.443Z
Learnt from: kl3inIT
Repo: kl3inIT/OrgMemory PR: 61
File: apps/mcp/src/main/java/com/orgmemory/mcp/McpSecurityConfiguration.java:50-52
Timestamp: 2026-07-26T05:46:47.443Z
Learning: In OrgMemory, treat the `apps/mcp` and `apps/api` as independent protocol adapter modules. When adjusting OAuth/wire-level scopes, do not introduce a shared Java constant or create a code dependency from `apps/mcp` to `apps/api` solely to deduplicate scope values. Instead, keep OAuth/scope constants adapter-local (e.g., in the relevant adapter/security configuration classes) and ensure cross-adapter consistency via automated realm/OAuth/authorization tests, rather than via shared wiring-level constants or cross-module references.

Applied to files:

  • apps/api/src/main/java/com/orgmemory/api/assetregistry/AssetRegistryController.java
🔇 Additional comments (14)
core/src/main/java/com/orgmemory/core/assetregistry/AssetOwnedSort.java (1)

3-6: LGTM!

apps/web/test/setup.ts (1)

5-13: LGTM!

core/src/main/java/com/orgmemory/core/assetregistry/AssetRoleAssignmentRepository.java (1)

26-27: 🎯 Functional Correctness

No change needed. AssetRoleAssignment stores PrincipalRef.type() for principalType, so the inline 'user' query literal matches user assignments; UserPrincipal IDs are stored as raw UUID strings.

apps/web/src/features/assets/components/asset-catalog-page.tsx (1)

330-344: 🎯 Functional Correctness

No change needed. The assets catalog route resets page to undefined during onScopeChange, which defaults to page 1.

core/src/main/java/com/orgmemory/core/assetregistry/AssetRepository.java (1)

164-167: 🎯 Functional Correctness

No change needed; draft updates do not advance asset.updatedAt.

Asset stores the asset-level updated timestamp, while AssetDraft stores the draft-level updated timestamp. updateDraft mutates and saves only the draft, so draft edits are not asset edits. If draft edits need to appear in “RECENTLY_UPDATED,” define separate “last activity” behavior for drafts or propagate the draft timestamp to the asset.

core/src/main/java/com/orgmemory/core/assetregistry/AssetSummaryPage.java (1)

5-20: LGTM!

core/src/main/java/com/orgmemory/core/assetregistry/AssetRegistryService.java (1)

155-176: LGTM!

apps/api/src/main/java/com/orgmemory/api/assetregistry/AssetRegistryController.java (1)

7-12: LGTM!

Also applies to: 174-187

core/src/test/java/com/orgmemory/core/assetregistry/AssetRegistryServiceTests.java (1)

6-71: LGTM!

apps/web/src/features/assets/asset-catalog-state.ts (1)

3-4: LGTM!

Also applies to: 17-17, 28-45

apps/web/src/features/assets/asset-catalog-state.test.ts (1)

10-10: LGTM!

Also applies to: 22-30, 39-50

apps/web/src/routes/_authenticated/assets/index.tsx (1)

14-25: LGTM!

Also applies to: 44-54

apps/web/src/features/assets/components/asset-type-filter.tsx (1)

1-8: LGTM!

Also applies to: 22-40

apps/api/src/test/java/com/orgmemory/api/assetregistry/AssetRegistryIntegrationTests.java (1)

384-415: 🎯 Functional Correctness

No change needed.

ownedSummaryPage(...) already checks whether author_id actually has the current owner role during owned aggregation, and this test case already exercises a different actor’s assignment being excluded.

			> Likely an incorrect or invalid review comment.

Comment thread apps/web/src/features/assets/components/asset-catalog-page.tsx
Comment thread apps/web/src/features/assets/components/asset-catalog-page.tsx Outdated
Comment thread apps/web/src/features/assets/components/asset-type-filter.test.tsx Outdated
Comment thread apps/web/test/e2e/asset-registry-golden-poc.spec.ts
Comment on lines +261 to +278
var ids = new java.util.LinkedHashSet<>(roles.findActiveAssetIdsForUserRole(
organizationId,
userId.toString(),
AssetRole.OWNER,
Instant.now()));
ids.retainAll(visibleIds);
if (ids.isEmpty()) {
return AssetSummaryPage.empty(page, pageSize, sort);
}
String normalizedQuery =
query == null ? "" : query.trim().toLowerCase(java.util.Locale.ROOT);
Page<AssetSummary> result = assets.searchOwnedSummaries(
organizationId,
ids,
normalizedQuery,
type,
sort.name(),
PageRequest.of(page - 1, pageSize));

@coderabbitai coderabbitai Bot Jul 31, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🚀 Performance & Scalability | 🔵 Trivial

Plan for large owner sets in the in :ids predicate.

The intersection order is correct: active OWNER assignments are filtered down to the can_view set, so the endpoint cannot widen visibility. The remaining concern is size. ids is unbounded, and it is bound to asset.id in :ids in searchOwnedSummaries. A user who owns a large number of assets produces a very large IN list on every page request. PostgreSQL bind-parameter limits and plan quality both degrade at that scale, and the whole set is sent for each page even though one page returns at most 60 rows.

recommendationPage and summaries share this shape, so treat this as a registry-wide capacity item rather than a defect in this method. Options: cap the owner set with a documented limit, or push the ownership predicate into the query as a join or exists subquery against AssetRoleAssignment so the database performs the intersection and the pagination in one plan.

🤖 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
`@core/src/main/java/com/orgmemory/core/assetregistry/AssetRegistryCoordinator.java`
around lines 261 - 278, The owner asset filtering used by
AssetRegistryCoordinator and the shared recommendationPage/summaries paths
passes an unbounded ids collection into searchOwnedSummaries, causing oversized
IN predicates per page. Replace this pattern with a database-side ownership
predicate using a join or exists against AssetRoleAssignment, or apply a
documented owner-set limit if that is the established capacity strategy, while
preserving the active OWNER and can_view intersection and pagination behavior.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Confirmed as a registry-wide capacity concern, not an owner-workspace-specific regression. The same live OpenFGA authorized-ID set feeds the existing catalog and summary paths; replacing only the owner predicate with a database join would not remove the unbounded can_view intersection and would create inconsistent capacity behavior. Deferring this to a registry-wide capacity increment that can introduce a paged/cursored authorization-set contract or one documented global bound across every authorized collection.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@kl3inIT, agreed. The concern remains valid, but this PR does not introduce the underlying unbounded can_view authorization-set pattern.

A targeted ownership join would leave the larger authorized-ID intersection unbounded and would create inconsistent behavior across registry collection paths. A registry-wide capacity increment should define one strategy for all authorized collections, such as a paged/cursored authorization-set contract or a documented global bound.

Would you like me to create a GitHub follow-up issue for this work?


✏️ Learnings added
Learnt from: kl3inIT
Repo: kl3inIT/OrgMemory PR: 176
File: core/src/main/java/com/orgmemory/core/assetregistry/AssetRegistryCoordinator.java:261-278
Timestamp: 2026-07-31T15:55:49.093Z
Learning: In the Asset Registry, `AssetRegistryCoordinator.ownedSummaryPage`, `AssetRegistryCoordinator.recommendationPage`, and `AssetRegistryCoordinator.summaries` consume the same live OpenFGA `can_view` authorized-ID set. This set can be unbounded. Capacity remediation must apply one registry-wide strategy, such as a paged/cursored authorization-set contract or a documented global bound. Replacing only the owned-assets predicate with a database join does not resolve the unbounded `can_view` intersection and would create inconsistent capacity behavior.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

You are interacting with an AI system.

Comment thread core/src/main/java/com/orgmemory/core/assetregistry/AssetRepository.java Outdated
Comment thread design-qa.md Outdated
@kl3inIT

kl3inIT commented Jul 31, 2026

Copy link
Copy Markdown
Owner Author

CodeRabbit docstring coverage warning reviewed: the changed TypeScript helpers and package-private Java repository constants follow the repository's existing self-describing-code convention and are covered by focused tests. Adding docstrings solely to satisfy the generic percentage would create non-contract commentary, so no code change is applied for that warning.

@kl3inIT
kl3inIT merged commit af8b701 into main Jul 31, 2026
18 checks passed
@kl3inIT
kl3inIT deleted the feat/asset-ownership-layout branch July 31, 2026 16:34
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.

1 participant