Skip to content

Feat/marketplace pull aaas#1089

Merged
coodos merged 5 commits into
mainfrom
feat/marketplace-pull-aaas
Jul 16, 2026
Merged

Feat/marketplace pull aaas#1089
coodos merged 5 commits into
mainfrom
feat/marketplace-pull-aaas

Conversation

@coodos

@coodos coodos commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Description of change

Issue Number

Type of change

  • Breaking (any change that would cause existing functionality to not work as expected)
  • New (a change which implements a new feature)
  • Update (a change which updates existing functionality)
  • Fix (a change which fixes an issue)
  • Docs (changes to the documentation)
  • Chore (refactoring, build scripts or anything else that isn't user-facing)

How the change has been tested

Change checklist

  • I have ensured that the CI Checks pass locally
  • I have removed any unnecessary logic
  • My code is well documented
  • I have signed my commits
  • My code follows the pattern of the application
  • I have self reviewed my code

Summary by CodeRabbit

  • New Features

    • Marketplace home and app detail pages now display live platform listings alongside curated apps.
    • Added loading states while live platform data is being retrieved.
    • Marketplace categories now automatically include categories from available platforms.
    • Platform profiles now include website, logo, and category information for richer marketplace presentation.
  • Bug Fixes

    • Improved fallback behavior when live platform data is unavailable or an app cannot be found.

@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

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

Next review available in: 44 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 229999b7-66eb-4733-8b23-b9ef1a430327

📥 Commits

Reviewing files that changed from the base of the PR and between e49ff80 and 851550d.

📒 Files selected for processing (1)
  • docs/docs/Post Platform Guide/platform-evault-registration.md
📝 Walkthrough

Walkthrough

Platform profile metadata now includes URL, logo URL, and category across five services. The marketplace server retrieves active platform profiles from AaaS, exposes them through /api/platforms, and the client combines live data with static marketplace entries.

Changes

Platform profile metadata

Layer / File(s) Summary
Profile metadata propagation
platforms/{cerberus,dreamsync,ecurrency,esigner,file-manager}/.../PlatformEVaultService.ts
Platform profile types and local/eVault payloads now include url, logoUrl, and category.

AaaS platform API

Layer / File(s) Summary
AaaS retrieval and API route
platforms/marketplace/client/server/aaas.ts, platforms/marketplace/client/server/routes.ts
The server fetches paginated platform packets, filters inactive profiles, deduplicates by ename, and exposes the results through GET /api/platforms.
Environment initialization
platforms/marketplace/client/server/env.ts, platforms/marketplace/client/server/index.ts, platforms/marketplace/client/package.json
The repository .env file is loaded before server startup, with dotenv added as a dependency.

Marketplace live data integration

Layer / File(s) Summary
Home page platform merge
platforms/marketplace/client/client/src/pages/home-page.tsx
Live platforms are merged with static apps, static entries take precedence on collisions, and categories are derived from the merged data.
App detail resolution
platforms/marketplace/client/client/src/pages/app-detail.tsx
App details resolve from static or live platform data and show a loading state while the platform query is pending.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Visitor
  participant HomePage
  participant MarketplaceServer
  participant AaaS
  Visitor->>HomePage: Open marketplace
  HomePage->>MarketplaceServer: GET /api/platforms
  MarketplaceServer->>AaaS: Fetch paginated platform packets
  AaaS-->>MarketplaceServer: Active platform profiles
  MarketplaceServer-->>HomePage: Platform cards and count
  HomePage-->>Visitor: Merged static and live marketplace entries
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description is only the template and contains no issue number, testing details, or filled-in change information. Add the issue number, select the change type, describe how it was tested, and complete the checklist with concrete details.
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 (3 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and points to the main change: pulling AAAS data for the marketplace.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/marketplace-pull-aaas

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.

@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: 1

🧹 Nitpick comments (4)
platforms/marketplace/client/client/src/pages/app-detail.tsx (2)

141-163: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove unnecessary any casts.

Once app is properly typed as App, these explicit any casts can be cleanly removed.

♻️ Proposed refactor
-            {(app as any).appStoreUrl && (app as any).playStoreUrl ? (
+            {app.appStoreUrl && app.playStoreUrl ? (
               <>
-                <a href={(app as any).appStoreUrl} target="_blank" rel="noopener noreferrer" className="flex-1">
+                <a href={app.appStoreUrl} target="_blank" rel="noopener noreferrer" className="flex-1">
                   <Button className="w-full text-black font-bold px-8 py-4 rounded-full hover:scale-105 transition-all duration-200" style={{ backgroundColor: 'hsl(85, 100%, 85%)' }}>
                     <ExternalLink className="w-5 h-5 mr-3" />
                     App Store
                   </Button>
                 </a>
-                <a href={(app as any).playStoreUrl} target="_blank" rel="noopener noreferrer" className="flex-1">
+                <a href={app.playStoreUrl} target="_blank" rel="noopener noreferrer" className="flex-1">
                   <Button className="w-full text-black font-bold px-8 py-4 rounded-full hover:scale-105 transition-all duration-200" style={{ backgroundColor: 'hsl(270, 100%, 85%)' }}>
                     <ExternalLink className="w-5 h-5 mr-3" />
                     Play Store
                   </Button>
                 </a>
               </>
             ) : (
-              <a href={(app as any).url} target="_blank" rel="noopener noreferrer" className="flex-1">
+              <a href={app.url} target="_blank" rel="noopener noreferrer" className="flex-1">
                 <Button className="w-full text-black font-bold px-8 py-4 rounded-full hover:scale-105 transition-all duration-200" style={{ backgroundColor: 'hsl(85, 100%, 85%)' }}>
                   <ExternalLink className="w-5 h-5 mr-3" />
                   Visit Website
                 </Button>
               </a>
             )}
🤖 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 `@platforms/marketplace/client/client/src/pages/app-detail.tsx` around lines
141 - 163, Remove the unnecessary any casts from the appStoreUrl, playStoreUrl,
and url references in the app detail rendering block. Use the existing App
typing for app directly, preserving the current conditional logic and link
behavior.

65-67: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Define and use the App type instead of any.

Typing app as any removes type safety for the rest of the component and leads to unnecessary type casts later in the file. Consider exporting the App interface from home-page.tsx (or extracting it to a shared types file) and using it here.

♻️ Proposed refactor
-  const staticApp = appsData.find(a => a.id === appId);
-  const dynamicApp = platformsData?.platforms?.find((p: any) => p.id === appId);
-  const app: any = staticApp ?? dynamicApp;
+  const staticApp = appsData.find(a => a.id === appId);
+  const dynamicApp = platformsData?.platforms?.find((p: App) => p.id === appId);
+  const app: App | undefined = staticApp ?? dynamicApp;
🤖 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 `@platforms/marketplace/client/client/src/pages/app-detail.tsx` around lines 65
- 67, Replace the any typing in the app selection flow with a shared App type:
export or extract the existing App interface from home-page.tsx, import it into
app-detail.tsx, and type staticApp, dynamicApp, and app consistently. Remove
downstream casts that are only needed because app is typed as any.
platforms/marketplace/client/client/src/pages/home-page.tsx (1)

174-210: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove unnecessary any casts.

Since app is strongly typed as App (and the App interface includes appStoreUrl and playStoreUrl), casting app to any bypasses TypeScript's safety checks unnecessarily and introduces code smell.

♻️ Proposed refactor
-                      {(app as any).appStoreUrl && (app as any).playStoreUrl ? (
+                      {app.appStoreUrl && app.playStoreUrl ? (
                         <>
                           <a
-                            href={(app as any).appStoreUrl}
+                            href={app.appStoreUrl}
                             target="_blank"
                             rel="noopener noreferrer"
                             className="flex-1"
                             onClick={(e) => e.stopPropagation()}
                           >
                             <Button className="w-full text-black font-bold px-4 py-3 rounded-full hover:opacity-90" style={{ backgroundColor: 'hsl(85, 100%, 85%)' }}>
                               App Store
                             </Button>
                           </a>
                           <a
-                            href={(app as any).playStoreUrl}
+                            href={app.playStoreUrl}
                             target="_blank"
                             rel="noopener noreferrer"
                             className="flex-1"
                             onClick={(e) => e.stopPropagation()}
                           >
                             <Button className="w-full text-black font-bold px-4 py-3 rounded-full hover:opacity-90" style={{ backgroundColor: 'hsl(270, 100%, 85%)' }}>
                               Play Store
                             </Button>
                           </a>
                         </>
                       ) : (
                         <a
-                          href={(app as any).url || '#'}
+                          href={app.url || '#'}
                           target="_blank"
                           rel="noopener noreferrer"
                           onClick={(e) => e.stopPropagation()}
                         >
🤖 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 `@platforms/marketplace/client/client/src/pages/home-page.tsx` around lines 174
- 210, Remove the unnecessary `(app as any)` casts throughout the store-link
conditional and anchor hrefs in the app rendering block. Access
`app.appStoreUrl`, `app.playStoreUrl`, and `app.url` directly using the existing
`App` type, preserving the current conditional and fallback behavior.
platforms/cerberus/client/src/services/PlatformEVaultService.ts (1)

138-141: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Extract duplicated PlatformEVaultService into a shared library.

The PlatformEVaultService class implementation is completely duplicated across these service packages. The only variations are the hardcoded platform names and profile metadata (e.g., URL, logo, category). To drastically improve maintainability and enforce DRY principles, consider extracting this logic into a shared core library and parameterizing it with the platform-specific metadata during initialization.

  • platforms/cerberus/client/src/services/PlatformEVaultService.ts#L138-L141: extract the duplicated service logic into a shared package, taking this platform-specific metadata as configuration.
  • platforms/dreamsync/api/src/services/PlatformEVaultService.ts#L138-L141: replace the duplicated class with the shared service implementation.
  • platforms/ecurrency/api/src/services/PlatformEVaultService.ts#L138-L141: replace the duplicated class with the shared service implementation.
  • platforms/esigner/api/src/services/PlatformEVaultService.ts#L138-L141: replace the duplicated class with the shared service implementation.
🤖 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 `@platforms/cerberus/client/src/services/PlatformEVaultService.ts` around lines
138 - 141, Extract the duplicated PlatformEVaultService implementation into a
shared library and parameterize initialization with each platform’s name and
profile metadata. Update
platforms/cerberus/client/src/services/PlatformEVaultService.ts:138-141,
platforms/dreamsync/api/src/services/PlatformEVaultService.ts:138-141,
platforms/ecurrency/api/src/services/PlatformEVaultService.ts:138-141, and
platforms/esigner/api/src/services/PlatformEVaultService.ts:138-141 to use the
shared implementation while preserving their platform-specific URL, logo, and
category values.
🤖 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 `@platforms/marketplace/client/client/src/pages/home-page.tsx`:
- Around line 38-46: Update the dynamic platform processing around the platforms
filter and category construction to safely handle missing id, name, description,
and category fields from the external payload. Guard lowercase operations in the
search-related logic, exclude or safely handle incomplete platform records
without crashing rendering, and only add defined category values to the
categories list so no "undefined" entry is produced.

---

Nitpick comments:
In `@platforms/cerberus/client/src/services/PlatformEVaultService.ts`:
- Around line 138-141: Extract the duplicated PlatformEVaultService
implementation into a shared library and parameterize initialization with each
platform’s name and profile metadata. Update
platforms/cerberus/client/src/services/PlatformEVaultService.ts:138-141,
platforms/dreamsync/api/src/services/PlatformEVaultService.ts:138-141,
platforms/ecurrency/api/src/services/PlatformEVaultService.ts:138-141, and
platforms/esigner/api/src/services/PlatformEVaultService.ts:138-141 to use the
shared implementation while preserving their platform-specific URL, logo, and
category values.

In `@platforms/marketplace/client/client/src/pages/app-detail.tsx`:
- Around line 141-163: Remove the unnecessary any casts from the appStoreUrl,
playStoreUrl, and url references in the app detail rendering block. Use the
existing App typing for app directly, preserving the current conditional logic
and link behavior.
- Around line 65-67: Replace the any typing in the app selection flow with a
shared App type: export or extract the existing App interface from
home-page.tsx, import it into app-detail.tsx, and type staticApp, dynamicApp,
and app consistently. Remove downstream casts that are only needed because app
is typed as any.

In `@platforms/marketplace/client/client/src/pages/home-page.tsx`:
- Around line 174-210: Remove the unnecessary `(app as any)` casts throughout
the store-link conditional and anchor hrefs in the app rendering block. Access
`app.appStoreUrl`, `app.playStoreUrl`, and `app.url` directly using the existing
`App` type, preserving the current conditional and fallback behavior.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: ab9d4aad-82a6-4bca-a9aa-1d8c7edd5f8d

📥 Commits

Reviewing files that changed from the base of the PR and between 91bf719 and e49ff80.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (12)
  • platforms/cerberus/client/src/services/PlatformEVaultService.ts
  • platforms/dreamsync/api/src/services/PlatformEVaultService.ts
  • platforms/ecurrency/api/src/services/PlatformEVaultService.ts
  • platforms/esigner/api/src/services/PlatformEVaultService.ts
  • platforms/file-manager/api/src/services/PlatformEVaultService.ts
  • platforms/marketplace/client/client/src/pages/app-detail.tsx
  • platforms/marketplace/client/client/src/pages/home-page.tsx
  • platforms/marketplace/client/package.json
  • platforms/marketplace/client/server/aaas.ts
  • platforms/marketplace/client/server/env.ts
  • platforms/marketplace/client/server/index.ts
  • platforms/marketplace/client/server/routes.ts

Comment on lines +38 to +46
const dynamicApps = (platformsData?.platforms ?? []).filter(
(p) => !staticIds.has(p.id.toLowerCase()) && !staticNames.has(p.name.toLowerCase()),
);
const apps: App[] = [...staticApps, ...dynamicApps];

const categories = ["All Apps", "Identity", "Social", "Governance", "Wellness", "Finance", "Storage", "Productivity"];
const categories = [
"All Apps",
...Array.from(new Set([...BASE_CATEGORIES, ...apps.map((a) => a.category)])),
];

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.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Add defensive checks for external API payload fields.

Data retrieved from external APIs may be missing expected fields. If an item in platformsData.platforms lacks an id, name, or description (used in the search filter logic later), calling .toLowerCase() on them will crash the React render cycle. Additionally, undefined categories will be added as "undefined" string literals to the filter list.

🛡️ Proposed defensive guards
-  const dynamicApps = (platformsData?.platforms ?? []).filter(
-    (p) => !staticIds.has(p.id.toLowerCase()) && !staticNames.has(p.name.toLowerCase()),
-  );
+  const dynamicApps = (platformsData?.platforms ?? []).filter(
+    (p) => p?.id && p?.name && p?.description && !staticIds.has(p.id.toLowerCase()) && !staticNames.has(p.name.toLowerCase()),
+  );
   const apps: App[] = [...staticApps, ...dynamicApps];

   const categories = [
     "All Apps",
-    ...Array.from(new Set([...BASE_CATEGORIES, ...apps.map((a) => a.category)])),
+    ...Array.from(new Set([...BASE_CATEGORIES, ...apps.map((a) => a.category).filter(Boolean)])),
   ];
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const dynamicApps = (platformsData?.platforms ?? []).filter(
(p) => !staticIds.has(p.id.toLowerCase()) && !staticNames.has(p.name.toLowerCase()),
);
const apps: App[] = [...staticApps, ...dynamicApps];
const categories = ["All Apps", "Identity", "Social", "Governance", "Wellness", "Finance", "Storage", "Productivity"];
const categories = [
"All Apps",
...Array.from(new Set([...BASE_CATEGORIES, ...apps.map((a) => a.category)])),
];
const dynamicApps = (platformsData?.platforms ?? []).filter(
(p) => p?.id && p?.name && p?.description && !staticIds.has(p.id.toLowerCase()) && !staticNames.has(p.name.toLowerCase()),
);
const apps: App[] = [...staticApps, ...dynamicApps];
const categories = [
"All Apps",
...Array.from(new Set([...BASE_CATEGORIES, ...apps.map((a) => a.category).filter(Boolean)])),
];
🤖 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 `@platforms/marketplace/client/client/src/pages/home-page.tsx` around lines 38
- 46, Update the dynamic platform processing around the platforms filter and
category construction to safely handle missing id, name, description, and
category fields from the external payload. Guard lowercase operations in the
search-related logic, exclude or safely handle incomplete platform records
without crashing rendering, and only add defined category values to the
categories list so no "undefined" entry is produced.

@coodos
coodos merged commit 0d96270 into main Jul 16, 2026
3 of 4 checks passed
@coodos
coodos deleted the feat/marketplace-pull-aaas branch July 16, 2026 12:17
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