Skip to content

Conversation

basmasking
Copy link
Member

Fixes #375

Changes proposed in this pull request:

  • multi-tenancy support
  • moved bff before the gateway to reduce gateway traffic

@MaskingTechnology/comify

All bff functions with requester and the ripples it created.
The origin contains the protocol of the incoming request as well. We need the origin so we can pass this to the authentication service as a redirect url.

Authentication is updated to configure paths, and dynamically get the origin passed in.
Introduces a new origin creation flow with validation, error handling, and database insertion. Refactors the origin 'get' logic to 'find', updates related tenant/origin lookups, and adds comprehensive tests and fixtures for origin and tenant modules. Also includes minor improvements and bug fixes in authentication, middleware, and utility code.
@basmasking basmasking requested a review from petermasking as a code owner July 22, 2025 14:55
@basmasking basmasking linked an issue Jul 22, 2025 that may be closed by this pull request
Copy link

coderabbitai bot commented Jul 22, 2025

Summary by CodeRabbit

  • New Features

    • Introduced multi-tenant support throughout the platform, enabling tenant-specific data isolation and processing.
    • Added tenant-aware middleware for origin validation and tenant context management.
    • New tenant-aware endpoints and error handling for tenant retrieval by origin.
    • UI now dynamically loads tenant-specific styles and context via a new TenantContainer component and hook.
  • Enhancements

    • All major domain functions and hooks updated to require and propagate tenant context.
    • Authentication and OpenID flows now support origin-based redirect and validation.
    • Expanded access control and middleware configuration for improved security and flexibility.
  • Bug Fixes

    • Corrected copyright year in legal info.
    • Various minor formatting and import improvements.
  • Documentation

    • Updated environment variable documentation for authentication and tenant configuration.
  • Tests

    • All relevant tests updated to include tenant context and new fixtures for multi-tenant scenarios.
  • Chores

    • Dependency versions updated.
    • Linting and configuration files adjusted for new structure and directories.

"""

Walkthrough

This update introduces comprehensive multitenancy support across the application, focusing on URL-based tenant identification, tenant-scoped data access, and dynamic tenant-specific styling. It adds new middleware for origin and tenant management, modifies domain logic to propagate tenant context, updates configuration and environment variables, and enhances the frontend to load tenant-specific assets.

Changes

File(s) / Path(s) Change Summary
docker-compose.yml, docker/mongodb/init.js, example.env, eslint.config.js Docker Compose and MongoDB initialization updated for tenant setup; environment/config updates; ESLint ignores docker directory.
docs/integrations/AUTHENTICATION.md, src/integrations/authentication/definitions/interfaces.ts, src/integrations/authentication/implementations/openid/*, src/integrations/runtime/authenticationMiddleware.ts OpenID and authentication config refactored: absolute URIs replaced by paths, origin-awareness added, interface and env updates.
package.json Updated "jitar" and "@jitar/plugin-vite" dependencies to v0.10.0.
segments/.json, services/.json Access control and middleware configuration updated for tenant and origin middleware, setup/teardown logic refactored.
src/assets/localhost.css Added empty CSS file for tenant-specific styling.
src/domain/creator/, src/domain/post/, src/domain/relation/, src/domain/notification/ Domain logic refactored: all relevant functions updated to accept and propagate tenant context (tenantId or Tenant object).
src/domain/tenant/* New tenant domain: types, error classes, data access, validation, and conversion utilities for tenant management.
src/integrations/runtime/middlewares/OriginMiddleware.ts, src/integrations/runtime/middlewares/TenantMiddleware.ts New origin and tenant middleware introduced for extracting, validating, and caching tenant info based on request origin.
src/integrations/runtime/originMiddleware.ts, src/integrations/runtime/tenantMiddleware.ts Export default instances of new middleware for integration.
src/integrations/runtime/authenticationMiddleware.ts, src/integrations/runtime/setUpBff.ts, src/integrations/runtime/tearDownBff.ts Authentication and setup/teardown logic updated to handle tenant-aware flows and new middleware.
src/integrations/runtime/setUpGateway.ts (deleted), src/integrations/runtime/tearDownGateway.ts (deleted) Removed gateway setup and teardown scripts.
src/webui/components/common/TenantContainer.tsx, src/webui/components/common/hooks/useTenant.ts, src/webui/components/index.ts New React component and hook for loading and providing tenant context and dynamic CSS; exported centrally.
src/webui/features/hooks/* All hooks updated to pass tenant context to domain/data functions, ensuring tenant-specific data fetching.
src/webui/main.tsx App rendering tree wrapped in new TenantContainer for tenant context and styling.
src/webui/components/application/LegalInfo.tsx, src/webui/contexts/AppContext.tsx Minor updates: copyright year, whitespace.

Sequence Diagram(s)

sequenceDiagram
    participant Browser
    participant WebUI
    participant OriginMiddleware
    participant TenantMiddleware
    participant BFF/Domain
    participant MongoDB

    Browser->>WebUI: Request with Origin header
    WebUI->>OriginMiddleware: Handle request
    OriginMiddleware->>WebUI: Validates/extracts origin, sets cookie/header
    WebUI->>TenantMiddleware: Handle request
    TenantMiddleware->>BFF/Domain: Fetch tenant by origin (cache or DB)
    BFF/Domain->>MongoDB: Query tenant by origin
    MongoDB-->>BFF/Domain: Tenant data
    BFF/Domain-->>TenantMiddleware: Tenant info
    TenantMiddleware->>WebUI: Attach tenant to request context
    WebUI->>WebUI: Load tenant-specific CSS, fetch tenant-scoped data
    WebUI-->>Browser: Render tenant-specific UI and data
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~90–120 minutes

Suggested reviewers

  • petermasking

Poem

In a warren of code, each tenant has a door,
Now rabbits can style, and data is more!
With origins checked and cookies in tow,
Each bunny finds home wherever they go.
Multitenant dreams, CSS anew—
Hop, hop, hooray, this release is for you!
🐇✨
"""

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

npm error Exit handler never called!
npm error This is an error with npm itself. Please report this error at:
npm error https://github.com/npm/cli/issues
npm error A complete log of this run can be found in: /.npm/_logs/2025-07-26T21_37_46_433Z-debug-0.log

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 375-multitenancy-support

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 17

🧹 Nitpick comments (14)
src/webui/main.tsx (1)

14-18: Consider error boundary for tenant loading.

The component hierarchy looks good, but consider whether TenantContainer should have its own error boundary to handle tenant loading failures gracefully without breaking the entire application.

Consider wrapping TenantContainer with an error boundary:

  <StrictMode>
+   <ErrorBoundary fallback={<div>Failed to load tenant configuration</div>}>
      <TenantContainer>
        <AppContextProvider>
          <App />
        </AppContextProvider>
      </TenantContainer>
+   </ErrorBoundary>
  </StrictMode>
docker/mongodb/init.js (1)

1-14: Consider environment-specific configuration for tenant origins.

The script hard-codes localhost origins for ports 3000 and 5173. While appropriate for development, consider:

  1. Making origins configurable via environment variables for different deployment scenarios
  2. Adding validation for origin URL formats
  3. Ensuring this initialization script is only used in development environments

Consider this approach for more flexible configuration:

+const origins = process.env.TENANT_ORIGINS ? 
+    process.env.TENANT_ORIGINS.split(',') : 
+    ['http://localhost:3000', 'http://localhost:5173'];
+
 db = db.getSiblingDB('comify');
 db.tenant.updateOne(
     { _id: 'localhost' },
     {
         $set: {
-            origins: [
-                'http://localhost:3000',
-                'http://localhost:5173'
-            ]
+            origins: origins
         }
     },
     { upsert: true }
 );
src/integrations/runtime/tenantMiddleware.ts (1)

4-4: Consider using a constant for the tenant path.

The hardcoded string 'domain/tenant/getByOriginConverted' could be error-prone if the path changes. Consider defining this as a constant or importing it from a configuration module to improve maintainability.

+import { TENANT_BY_ORIGIN_PATH } from '^/domain/tenant/constants';
+
-const tenantPath = 'domain/tenant/getByOriginConverted';
+const tenantPath = TENANT_BY_ORIGIN_PATH;
src/domain/tenant/getByOrigin/getByOrigin.ts (1)

23-23: Consider safer type conversion.

The type assertion as DataModel bypasses TypeScript's type safety. Consider adding runtime validation to ensure the database record structure matches the expected DataModel interface.

-    return record as DataModel;
+    // Validate record structure matches DataModel interface
+    if (!record || typeof record.origins !== 'object' || !Array.isArray(record.origins)) {
+        throw new Error('Invalid tenant record structure');
+    }
+    
+    return record as DataModel;
src/webui/features/hooks/useHighlight.ts (1)

11-11: Clarify naming inconsistency between file and export.

The file is named useHighlight.ts but exports useReaction. Consider aligning the naming for better code maintainability.

src/webui/components/common/hooks/useTenant.ts (1)

11-15: Consider adding tenant.origin to the dependency array.

The useCallback has an empty dependency array, but it references tenant.origin. If tenant.origin can change during the component's lifecycle, this could lead to stale closures.

    const getTenant = useCallback(async () =>
    {
        return await getByOriginConverted(tenant.origin);

-    }, []);
+    }, [tenant.origin]);
src/domain/tenant/getByOriginConverted/getByOriginConverted.ts (1)

8-8: Consider async validation if needed.

The current validation is synchronous, which works well for URL validation. However, if future requirements include async validation (e.g., checking origin against external services), consider making validateData async and awaiting it.

src/domain/creator/generateNickname/retrieveByStartNickname.ts (1)

8-13: Consider adding tenantId validation.

While the database query correctly filters by tenantId, consider adding validation to ensure the tenantId parameter is not empty or malformed before constructing the query.

 export default async function retrieveByStartNickname(nickname: string, tenantId: string): Promise<DataModel | undefined>
 {
+    if (!tenantId?.trim()) {
+        throw new Error('tenantId is required');
+    }
+
     const query = {
         nickname: { 'STARTS_WITH': nickname },
         tenantId: { 'EQUALS': tenantId }
     };
src/webui/components/common/TenantContainer.tsx (1)

26-28: Consider improving loading state and error handling.

The component returns null during tenant loading, which might cause layout shifts. Additionally, there's no error handling if the tenant-specific CSS fails to load.

-if (tenant === undefined) return null;
-
-return children;
+if (tenant === undefined) {
+    // Consider showing loading indicator or rendering with default styles
+    return <div className="loading-tenant">{children}</div>;
+}
+
+return children;

For CSS error handling, consider adding an onError handler:

 const link = document.createElement('link');
 link.setAttribute('rel', 'stylesheet');
 link.setAttribute('href', `/assets/${tenant.id}.css`);
 link.setAttribute('data-tenant-css', 'true');
+link.onerror = () => {
+    console.warn(`Failed to load tenant CSS for: ${tenant.id}`);
+};

 document.head.appendChild(link);
src/integrations/runtime/middlewares/OriginMiddleware.ts (3)

23-49: Consider removing unnecessary type assertion.

The logic flow is excellent and properly handles origin extraction, validation, and cookie management. However, the type assertion on line 39 is unnecessary since validation ensures the value is defined.

-        request.setHeader('origin', origin as string);
+        request.setHeader('origin', origin!);

65-73: Improve cookie parsing robustness.

The current cookie parsing has potential issues:

  1. Splitting on '=' could break if the cookie value contains '=' characters
  2. Cookie values should be URL-decoded
  3. Manual parsing is error-prone

Consider using a more robust approach:

-        for (const cookie of header.split(';'))
-        {
-            const [key, value] = cookie.split('=');
-
-            if (key.trim() === TENANT_COOKIE_NAME) 
-            {
-                return value?.trim();
-            }
-        }
+        for (const cookie of header.split(';'))
+        {
+            const [key, ...valueParts] = cookie.split('=');
+            
+            if (key.trim() === TENANT_COOKIE_NAME) 
+            {
+                const value = valueParts.join('=');
+                return value ? decodeURIComponent(value.trim()) : undefined;
+            }
+        }

86-89: Consider cookie encoding and development environment compatibility.

The security attributes are excellent, but consider:

  1. URL-encode the cookie value to handle special characters
  2. The Secure flag requires HTTPS and may break in development environments
-        response.setHeader('Set-Cookie', `${TENANT_COOKIE_NAME}=${origin}; Path=/; HttpOnly=true; SameSite=Strict; Secure`);
+        response.setHeader('Set-Cookie', `${TENANT_COOKIE_NAME}=${encodeURIComponent(origin)}; Path=/; HttpOnly=true; SameSite=Strict; Secure`);

Consider making the Secure flag configurable for development environments.

src/integrations/authentication/implementations/openid/OpenID.ts (1)

75-78: Consider more robust query parameter handling.

The URL construction is correct, but consider using URLSearchParams for safer query parameter handling:

-        const currentUrl = new URL(`${this.#providerConfiguration.redirectPath}?session_state=${data.session_state}&iss=${data.iss}&code=${data.code}`, origin);
+        const url = new URL(this.#providerConfiguration.redirectPath, origin);
+        url.searchParams.set('session_state', data.session_state as string);
+        url.searchParams.set('iss', data.iss as string);
+        url.searchParams.set('code', data.code as string);
+        const currentUrl = url;

This approach handles URL encoding automatically and is more maintainable.

src/integrations/runtime/middlewares/TenantMiddleware.ts (1)

23-43: Consider cache expiration and error handling strategy.

The caching logic is solid, but consider these improvements:

  1. Cache expiration: The cache has no TTL, which could lead to stale tenant data
  2. Memory management: No cache size limits could cause memory issues
  3. Error caching: Client errors (4xx) are cached, which may not be desired

Consider implementing:

  • Cache TTL with timestamps
  • LRU cache with size limits
  • More selective caching (e.g., only cache 200 responses)
-            if (response.status < 500)
+            if (response.status === 200)
             {
                 this.#cache.set(origin, response);
             }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d0aa9c4 and 00263af.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (107)
  • docker-compose.yml (1 hunks)
  • docker/mongodb/init.js (1 hunks)
  • docs/integrations/AUTHENTICATION.md (1 hunks)
  • eslint.config.js (1 hunks)
  • example.env (2 hunks)
  • package.json (2 hunks)
  • segments/bff.json (1 hunks)
  • segments/reads.json (1 hunks)
  • services/bff.json (1 hunks)
  • services/gateway.json (0 hunks)
  • services/proxy.json (1 hunks)
  • services/standalone.json (2 hunks)
  • src/assets/localhost.css (1 hunks)
  • src/domain/authentication/login/login.ts (1 hunks)
  • src/domain/creator/aggregate/types.ts (1 hunks)
  • src/domain/creator/create/create.ts (1 hunks)
  • src/domain/creator/create/createData.ts (1 hunks)
  • src/domain/creator/create/types.ts (1 hunks)
  • src/domain/creator/create/validateData.ts (2 hunks)
  • src/domain/creator/generateNickname/generateNickname.ts (1 hunks)
  • src/domain/creator/generateNickname/retrieveByNickname.ts (1 hunks)
  • src/domain/creator/generateNickname/retrieveByStartNickname.ts (1 hunks)
  • src/domain/creator/getByEmail/getByEmail.ts (1 hunks)
  • src/domain/creator/getById/CreatorNotFound.ts (1 hunks)
  • src/domain/creator/getById/getById.ts (1 hunks)
  • src/domain/creator/getByIdAggregated/getByIdAggregated.ts (1 hunks)
  • src/domain/creator/getByNickname/getByNickname.ts (1 hunks)
  • src/domain/creator/getByNicknameAggregated/getByNicknameAggregated.ts (1 hunks)
  • src/domain/creator/getMe/getMe.ts (1 hunks)
  • src/domain/creator/getMeAggregated/getMeAggregated.ts (1 hunks)
  • src/domain/creator/getOthers/getOthers.ts (1 hunks)
  • src/domain/creator/register/register.ts (1 hunks)
  • src/domain/creator/types.ts (1 hunks)
  • src/domain/notification/aggregate/aggregate.ts (1 hunks)
  • src/domain/notification/getByIdAggregated/getByIdAggregated.ts (1 hunks)
  • src/domain/notification/getRecentAggregated/getRecentAggregated.ts (1 hunks)
  • src/domain/post/aggregate/aggregate.ts (1 hunks)
  • src/domain/post/create/InvalidPost.ts (1 hunks)
  • src/domain/post/create/create.ts (1 hunks)
  • src/domain/post/create/createData.ts (1 hunks)
  • src/domain/post/create/types.ts (1 hunks)
  • src/domain/post/create/validateData.ts (2 hunks)
  • src/domain/post/createWithComic/createWithComic.ts (1 hunks)
  • src/domain/post/createWithComment/createWithComment.ts (1 hunks)
  • src/domain/post/explore/explore.ts (1 hunks)
  • src/domain/post/explore/retrieveData.ts (1 hunks)
  • src/domain/post/exploreAggregated/exploreAggregated.ts (1 hunks)
  • src/domain/post/getByCreatorAggregated/getByCreatorAggregated.ts (1 hunks)
  • src/domain/post/getByFollowingAggregated/getByFollowingAggregated.ts (1 hunks)
  • src/domain/post/getByIdAggregated/getByIdAggregated.ts (1 hunks)
  • src/domain/post/getByParentAggregated/getByParentAggregated.ts (1 hunks)
  • src/domain/post/getRecommended/getRecommended.ts (1 hunks)
  • src/domain/post/getRecommendedAggregated/getRecommendedAggregated.ts (1 hunks)
  • src/domain/post/types.ts (1 hunks)
  • src/domain/relation/aggregate/aggregate.ts (1 hunks)
  • src/domain/relation/explore/explore.ts (1 hunks)
  • src/domain/relation/exploreAggregated/exploreAggregated.ts (1 hunks)
  • src/domain/relation/getAggregated/getAggregated.ts (1 hunks)
  • src/domain/relation/getFollowersAggregated/getFollowersAggregated.ts (1 hunks)
  • src/domain/relation/getFollowingAggregated/getFollowingAggregated.ts (1 hunks)
  • src/domain/tenant/definitions.ts (1 hunks)
  • src/domain/tenant/getByOrigin/TenantNotFound.ts (1 hunks)
  • src/domain/tenant/getByOrigin/getByOrigin.ts (1 hunks)
  • src/domain/tenant/getByOrigin/index.ts (1 hunks)
  • src/domain/tenant/getByOriginConverted/InvalidOrigin.ts (1 hunks)
  • src/domain/tenant/getByOriginConverted/getByOriginConverted.ts (1 hunks)
  • src/domain/tenant/getByOriginConverted/index.ts (1 hunks)
  • src/domain/tenant/getByOriginConverted/types.ts (1 hunks)
  • src/domain/tenant/getByOriginConverted/validateData.ts (1 hunks)
  • src/domain/tenant/index.ts (1 hunks)
  • src/domain/tenant/tenant.ts (1 hunks)
  • src/domain/tenant/types.ts (1 hunks)
  • src/integrations/authentication/definitions/interfaces.ts (1 hunks)
  • src/integrations/authentication/implementations/openid/OpenID.ts (3 hunks)
  • src/integrations/authentication/implementations/openid/create.ts (1 hunks)
  • src/integrations/runtime/authenticationMiddleware.ts (1 hunks)
  • src/integrations/runtime/middlewares/AuthenticationMiddleware.ts (4 hunks)
  • src/integrations/runtime/middlewares/OriginMiddleware.ts (1 hunks)
  • src/integrations/runtime/middlewares/TenantMiddleware.ts (1 hunks)
  • src/integrations/runtime/originMiddleware.ts (1 hunks)
  • src/integrations/runtime/setUpBff.ts (1 hunks)
  • src/integrations/runtime/setUpGateway.ts (0 hunks)
  • src/integrations/runtime/tearDownBff.ts (1 hunks)
  • src/integrations/runtime/tearDownGateway.ts (0 hunks)
  • src/integrations/runtime/tenantMiddleware.ts (1 hunks)
  • src/webui/components/application/LegalInfo.tsx (1 hunks)
  • src/webui/components/common/TenantContainer.tsx (1 hunks)
  • src/webui/components/common/hooks/useTenant.ts (1 hunks)
  • src/webui/components/index.ts (1 hunks)
  • src/webui/contexts/AppContext.tsx (1 hunks)
  • src/webui/features/hooks/useAddComicPost.ts (2 hunks)
  • src/webui/features/hooks/useCreatePostComicReaction.ts (1 hunks)
  • src/webui/features/hooks/useCreatePostCommentReaction.ts (1 hunks)
  • src/webui/features/hooks/useCreator.ts (2 hunks)
  • src/webui/features/hooks/useCreatorFollowers.ts (2 hunks)
  • src/webui/features/hooks/useCreatorFollowing.ts (2 hunks)
  • src/webui/features/hooks/useCreatorPosts.ts (2 hunks)
  • src/webui/features/hooks/useExploreCreators.ts (2 hunks)
  • src/webui/features/hooks/useExplorePosts.ts (2 hunks)
  • src/webui/features/hooks/useHighlight.ts (2 hunks)
  • src/webui/features/hooks/useIdentify.ts (2 hunks)
  • src/webui/features/hooks/useNotifications.ts (2 hunks)
  • src/webui/features/hooks/usePost.ts (2 hunks)
  • src/webui/features/hooks/usePostReactions.ts (2 hunks)
  • src/webui/features/hooks/usePostsFollowing.ts (2 hunks)
  • src/webui/features/hooks/usePostsRecommended.ts (2 hunks)
  • src/webui/main.tsx (1 hunks)
⛔ Files not processed due to max files limit (29)
  • test/domain/authentication/fixtures/index.ts
  • test/domain/authentication/fixtures/records.fixture.ts
  • test/domain/authentication/fixtures/tenants.fixture.ts
  • test/domain/authentication/login.spec.ts
  • test/domain/notification/fixtures/index.ts
  • test/domain/notification/fixtures/records.fixture.ts
  • test/domain/notification/fixtures/tenants.fixture.ts
  • test/domain/notification/getRecentAggregated.spec.ts
  • test/domain/post/createWithComic.spec.ts
  • test/domain/post/fixtures/databases.fixture.ts
  • test/domain/post/fixtures/index.ts
  • test/domain/post/fixtures/records.fixture.ts
  • test/domain/post/fixtures/tenants.fixture.ts
  • test/domain/post/getByFollowingAggregated.spec.ts
  • test/domain/post/getRecommendedAggregated.spec.ts
  • test/domain/relation/exploreAggregated.spec.ts
  • test/domain/relation/fixtures/index.ts
  • test/domain/relation/fixtures/records.fixture.ts
  • test/domain/relation/fixtures/tenants.fixture.ts
  • test/domain/relation/getFollowersAggregated.spec.ts
  • test/domain/relation/getFollowingAggregated.spec.ts
  • test/domain/tenant/fixtures/databases.fixtures.ts
  • test/domain/tenant/fixtures/index.ts
  • test/domain/tenant/fixtures/records.fixtures.ts
  • test/domain/tenant/fixtures/values.fixtures.ts
  • test/domain/tenant/getByOrigin.spec.ts
  • test/domain/tenant/getByOriginConverted.spec.ts
  • test/integrations/database/implementation.spec.ts
  • vite.config.ts
🧠 Learnings (2)
src/domain/tenant/getByOriginConverted/index.ts (1)

Learnt from: basmasking
PR: #412
File: segments/writes.json:23-23
Timestamp: 2025-05-23T20:57:56.396Z
Learning: Segmentation files in the Comify project support index resolution. When a path like ./domain/post.metrics/update is referenced in segment configuration files, it implicitly refers to ./domain/post.metrics/update/index.ts (or similar extension).

segments/bff.json (1)

Learnt from: basmasking
PR: #412
File: segments/writes.json:23-23
Timestamp: 2025-05-23T20:57:56.396Z
Learning: Segmentation files in the Comify project support index resolution. When a path like ./domain/post.metrics/update is referenced in segment configuration files, it implicitly refers to ./domain/post.metrics/update/index.ts (or similar extension).

🧬 Code Graph Analysis (35)
src/domain/tenant/definitions.ts (1)
src/domain/tenant/index.ts (1)
  • RECORD_TYPE (2-2)
src/domain/relation/getAggregated/getAggregated.ts (3)
src/domain/authentication/types.ts (1)
  • Requester (8-8)
src/domain/tenant/types.ts (1)
  • Tenant (13-13)
src/domain/relation/aggregate/aggregate.ts (1)
  • aggregate (8-18)
src/domain/post/createWithComment/createWithComment.ts (2)
src/domain/authentication/types.ts (1)
  • Requester (8-8)
src/domain/tenant/types.ts (1)
  • Tenant (13-13)
src/domain/tenant/getByOriginConverted/getByOriginConverted.ts (3)
src/domain/tenant/types.ts (1)
  • Tenant (13-13)
src/domain/tenant/getByOriginConverted/validateData.ts (1)
  • validateData (20-28)
src/domain/tenant/getByOrigin/getByOrigin.ts (1)
  • getByOrigin (9-24)
src/integrations/runtime/authenticationMiddleware.ts (1)
src/integrations/runtime/middlewares/AuthenticationMiddleware.ts (1)
  • AuthenticationMiddleware (20-232)
src/domain/tenant/getByOrigin/TenantNotFound.ts (1)
src/integrations/runtime/errors/NotFound.ts (1)
  • NotFound (4-7)
src/domain/creator/generateNickname/generateNickname.ts (3)
src/domain/creator/cleanNickname/cleanNickname.ts (1)
  • cleanNickname (5-11)
src/domain/creator/generateNickname/retrieveByNickname.ts (1)
  • retrieveByNickname (7-15)
src/domain/creator/generateNickname/retrieveByStartNickname.ts (1)
  • retrieveByStartNickname (8-18)
src/domain/notification/getRecentAggregated/getRecentAggregated.ts (3)
src/domain/common/validateRange/validateRange.ts (1)
  • validateRange (31-39)
src/domain/notification/getRecent/getRecent.ts (1)
  • getRecent (8-19)
src/domain/notification/aggregate/aggregate.ts (1)
  • aggregate (10-24)
src/domain/post/explore/retrieveData.ts (3)
src/domain/relation/getFollowing/retrieveData.ts (1)
  • retrieveData (8-16)
src/domain/relation/getFollowers/retrieveData.ts (1)
  • retrieveData (8-16)
src/integrations/database/definitions/types.ts (1)
  • RecordQuery (20-20)
src/webui/main.tsx (2)
src/webui/contexts/AppContext.tsx (1)
  • AppContextProvider (29-36)
src/webui/App.tsx (1)
  • App (10-26)
src/domain/post/exploreAggregated/exploreAggregated.ts (5)
src/domain/authentication/types.ts (1)
  • Requester (8-8)
src/domain/tenant/types.ts (1)
  • Tenant (13-13)
src/domain/common/validateRange/validateRange.ts (1)
  • validateRange (31-39)
src/domain/post/explore/explore.ts (1)
  • explore (9-17)
src/domain/post/aggregate/aggregate.ts (1)
  • aggregate (13-34)
src/integrations/runtime/middlewares/AuthenticationMiddleware.ts (4)
src/integrations/authentication/definitions/interfaces.ts (1)
  • IdentityProvider (4-19)
src/integrations/runtime/middlewares/OriginMiddleware.ts (2)
  • request (51-54)
  • request (56-74)
src/integrations/runtime/middlewares/TenantMiddleware.ts (3)
  • request (23-43)
  • request (45-56)
  • request (58-61)
src/integrations/utilities/crypto.ts (1)
  • generateKey (24-32)
src/domain/creator/getByNickname/getByNickname.ts (1)
src/domain/creator/getByNickname/NicknameNotFound.ts (1)
  • NicknameNotFound (4-10)
src/domain/relation/getFollowingAggregated/getFollowingAggregated.ts (6)
src/domain/authentication/types.ts (1)
  • Requester (8-8)
src/domain/tenant/index.ts (1)
  • Tenant (4-4)
src/domain/tenant/types.ts (1)
  • Tenant (13-13)
src/domain/creator/aggregate/types.ts (1)
  • AggregatedData (13-13)
src/domain/common/validateRange/validateRange.ts (1)
  • validateRange (31-39)
src/domain/relation/aggregate/aggregate.ts (1)
  • aggregate (8-18)
src/integrations/runtime/originMiddleware.ts (1)
src/integrations/runtime/middlewares/OriginMiddleware.ts (1)
  • OriginMiddleware (21-90)
src/integrations/runtime/tenantMiddleware.ts (1)
src/integrations/runtime/middlewares/TenantMiddleware.ts (1)
  • TenantMiddleware (6-62)
src/domain/tenant/tenant.ts (2)
src/domain/tenant/index.ts (1)
  • Tenant (4-4)
src/domain/tenant/types.ts (1)
  • Tenant (13-13)
src/domain/creator/create/types.ts (1)
src/domain/creator/types.ts (1)
  • DataModel (14-14)
src/domain/creator/create/createData.ts (3)
src/domain/post/create/createData.ts (1)
  • createData (6-17)
src/domain/creator/types.ts (1)
  • DataModel (14-14)
src/integrations/utilities/crypto.ts (1)
  • generateId (19-22)
src/webui/features/hooks/useIdentify.ts (1)
src/domain/creator/getMe/getMe.ts (1)
  • getMe (8-11)
src/domain/post/getByCreatorAggregated/getByCreatorAggregated.ts (4)
src/domain/authentication/types.ts (1)
  • Requester (8-8)
src/domain/tenant/types.ts (1)
  • Tenant (13-13)
src/domain/common/validateRange/validateRange.ts (1)
  • validateRange (31-39)
src/domain/post/aggregate/aggregate.ts (1)
  • aggregate (13-34)
src/webui/features/hooks/useCreatorFollowing.ts (1)
src/domain/relation/getFollowing/getFollowing.ts (1)
  • getFollowing (8-13)
src/domain/creator/getMe/getMe.ts (1)
src/domain/creator/getById/getById.ts (1)
  • getById (8-24)
src/domain/post/create/validateData.ts (2)
src/domain/definitions.ts (2)
  • requiredIdValidation (9-17)
  • optionalIdValidation (19-27)
src/domain/post/create/types.ts (1)
  • ValidationModel (6-6)
src/domain/creator/getById/CreatorNotFound.ts (1)
src/integrations/runtime/errors/NotFound.ts (1)
  • NotFound (4-7)
src/domain/post/getByParentAggregated/getByParentAggregated.ts (1)
src/domain/post/aggregate/aggregate.ts (1)
  • aggregate (13-34)
src/webui/components/common/TenantContainer.tsx (1)
src/webui/components/common/hooks/useTenant.ts (1)
  • useTenant (9-18)
src/domain/tenant/types.ts (2)
src/domain/tenant/index.ts (2)
  • DataModel (4-4)
  • Tenant (4-4)
src/domain/types.ts (1)
  • BaseDataModel (8-8)
src/domain/creator/generateNickname/retrieveByStartNickname.ts (3)
src/integrations/database/implementations/mongodb/MongoDb.ts (1)
  • sort (256-272)
src/integrations/database/definitions/types.ts (1)
  • RecordSort (23-23)
src/integrations/database/definitions/constants.ts (1)
  • SortDirections (10-14)
src/domain/tenant/getByOrigin/getByOrigin.ts (4)
src/domain/tenant/index.ts (2)
  • DataModel (4-4)
  • RECORD_TYPE (2-2)
src/domain/tenant/types.ts (1)
  • DataModel (13-13)
src/integrations/database/definitions/types.ts (1)
  • RecordQuery (20-20)
src/domain/tenant/getByOrigin/TenantNotFound.ts (1)
  • TenantNotFound (4-10)
src/domain/relation/exploreAggregated/exploreAggregated.ts (3)
src/domain/common/validateRange/validateRange.ts (1)
  • validateRange (31-39)
src/domain/relation/explore/explore.ts (1)
  • explore (10-22)
src/domain/relation/aggregate/aggregate.ts (1)
  • aggregate (8-18)
src/domain/relation/getFollowersAggregated/getFollowersAggregated.ts (3)
src/domain/common/validateRange/validateRange.ts (1)
  • validateRange (31-39)
src/domain/relation/getFollowers/getFollowers.ts (1)
  • getFollowers (8-13)
src/domain/relation/aggregate/aggregate.ts (1)
  • aggregate (8-18)
src/integrations/runtime/middlewares/OriginMiddleware.ts (4)
src/integrations/validation/definitions/types.ts (1)
  • ValidationSchema (55-55)
src/integrations/runtime/middlewares/TenantMiddleware.ts (3)
  • request (23-43)
  • request (45-56)
  • request (58-61)
src/integrations/runtime/middlewares/AuthenticationMiddleware.ts (12)
  • request (51-58)
  • request (60-87)
  • request (89-105)
  • request (107-130)
  • request (132-139)
  • request (194-211)
  • request (213-216)
  • request (228-231)
  • response (218-221)
  • response (223-226)
  • key (151-154)
  • key (156-166)
src/integrations/runtime/errors/BadRequest.ts (1)
  • BadRequest (4-7)
src/domain/tenant/getByOriginConverted/validateData.ts (3)
src/integrations/validation/definitions/types.ts (1)
  • ValidationSchema (55-55)
src/domain/tenant/getByOriginConverted/types.ts (1)
  • ValidationModel (4-4)
src/domain/tenant/getByOriginConverted/InvalidOrigin.ts (1)
  • InvalidOrigin (4-7)
src/integrations/runtime/middlewares/TenantMiddleware.ts (2)
src/integrations/runtime/middlewares/OriginMiddleware.ts (2)
  • request (51-54)
  • request (56-74)
src/integrations/runtime/middlewares/AuthenticationMiddleware.ts (8)
  • request (51-58)
  • request (60-87)
  • request (89-105)
  • request (107-130)
  • request (132-139)
  • request (194-211)
  • request (213-216)
  • request (228-231)
🪛 Biome (1.9.4)
src/assets/localhost.css

[error] 1-2: An empty block isn't allowed.

Consider removing the empty block or adding styles inside it.

(lint/suspicious/noEmptyBlock)

💤 Files with no reviewable changes (3)
  • services/gateway.json
  • src/integrations/runtime/tearDownGateway.ts
  • src/integrations/runtime/setUpGateway.ts
🧰 Additional context used
🧠 Learnings (2)
src/domain/tenant/getByOriginConverted/index.ts (1)

Learnt from: basmasking
PR: #412
File: segments/writes.json:23-23
Timestamp: 2025-05-23T20:57:56.396Z
Learning: Segmentation files in the Comify project support index resolution. When a path like ./domain/post.metrics/update is referenced in segment configuration files, it implicitly refers to ./domain/post.metrics/update/index.ts (or similar extension).

segments/bff.json (1)

Learnt from: basmasking
PR: #412
File: segments/writes.json:23-23
Timestamp: 2025-05-23T20:57:56.396Z
Learning: Segmentation files in the Comify project support index resolution. When a path like ./domain/post.metrics/update is referenced in segment configuration files, it implicitly refers to ./domain/post.metrics/update/index.ts (or similar extension).

🧬 Code Graph Analysis (35)
src/domain/tenant/definitions.ts (1)
src/domain/tenant/index.ts (1)
  • RECORD_TYPE (2-2)
src/domain/relation/getAggregated/getAggregated.ts (3)
src/domain/authentication/types.ts (1)
  • Requester (8-8)
src/domain/tenant/types.ts (1)
  • Tenant (13-13)
src/domain/relation/aggregate/aggregate.ts (1)
  • aggregate (8-18)
src/domain/post/createWithComment/createWithComment.ts (2)
src/domain/authentication/types.ts (1)
  • Requester (8-8)
src/domain/tenant/types.ts (1)
  • Tenant (13-13)
src/domain/tenant/getByOriginConverted/getByOriginConverted.ts (3)
src/domain/tenant/types.ts (1)
  • Tenant (13-13)
src/domain/tenant/getByOriginConverted/validateData.ts (1)
  • validateData (20-28)
src/domain/tenant/getByOrigin/getByOrigin.ts (1)
  • getByOrigin (9-24)
src/integrations/runtime/authenticationMiddleware.ts (1)
src/integrations/runtime/middlewares/AuthenticationMiddleware.ts (1)
  • AuthenticationMiddleware (20-232)
src/domain/tenant/getByOrigin/TenantNotFound.ts (1)
src/integrations/runtime/errors/NotFound.ts (1)
  • NotFound (4-7)
src/domain/creator/generateNickname/generateNickname.ts (3)
src/domain/creator/cleanNickname/cleanNickname.ts (1)
  • cleanNickname (5-11)
src/domain/creator/generateNickname/retrieveByNickname.ts (1)
  • retrieveByNickname (7-15)
src/domain/creator/generateNickname/retrieveByStartNickname.ts (1)
  • retrieveByStartNickname (8-18)
src/domain/notification/getRecentAggregated/getRecentAggregated.ts (3)
src/domain/common/validateRange/validateRange.ts (1)
  • validateRange (31-39)
src/domain/notification/getRecent/getRecent.ts (1)
  • getRecent (8-19)
src/domain/notification/aggregate/aggregate.ts (1)
  • aggregate (10-24)
src/domain/post/explore/retrieveData.ts (3)
src/domain/relation/getFollowing/retrieveData.ts (1)
  • retrieveData (8-16)
src/domain/relation/getFollowers/retrieveData.ts (1)
  • retrieveData (8-16)
src/integrations/database/definitions/types.ts (1)
  • RecordQuery (20-20)
src/webui/main.tsx (2)
src/webui/contexts/AppContext.tsx (1)
  • AppContextProvider (29-36)
src/webui/App.tsx (1)
  • App (10-26)
src/domain/post/exploreAggregated/exploreAggregated.ts (5)
src/domain/authentication/types.ts (1)
  • Requester (8-8)
src/domain/tenant/types.ts (1)
  • Tenant (13-13)
src/domain/common/validateRange/validateRange.ts (1)
  • validateRange (31-39)
src/domain/post/explore/explore.ts (1)
  • explore (9-17)
src/domain/post/aggregate/aggregate.ts (1)
  • aggregate (13-34)
src/integrations/runtime/middlewares/AuthenticationMiddleware.ts (4)
src/integrations/authentication/definitions/interfaces.ts (1)
  • IdentityProvider (4-19)
src/integrations/runtime/middlewares/OriginMiddleware.ts (2)
  • request (51-54)
  • request (56-74)
src/integrations/runtime/middlewares/TenantMiddleware.ts (3)
  • request (23-43)
  • request (45-56)
  • request (58-61)
src/integrations/utilities/crypto.ts (1)
  • generateKey (24-32)
src/domain/creator/getByNickname/getByNickname.ts (1)
src/domain/creator/getByNickname/NicknameNotFound.ts (1)
  • NicknameNotFound (4-10)
src/domain/relation/getFollowingAggregated/getFollowingAggregated.ts (6)
src/domain/authentication/types.ts (1)
  • Requester (8-8)
src/domain/tenant/index.ts (1)
  • Tenant (4-4)
src/domain/tenant/types.ts (1)
  • Tenant (13-13)
src/domain/creator/aggregate/types.ts (1)
  • AggregatedData (13-13)
src/domain/common/validateRange/validateRange.ts (1)
  • validateRange (31-39)
src/domain/relation/aggregate/aggregate.ts (1)
  • aggregate (8-18)
src/integrations/runtime/originMiddleware.ts (1)
src/integrations/runtime/middlewares/OriginMiddleware.ts (1)
  • OriginMiddleware (21-90)
src/integrations/runtime/tenantMiddleware.ts (1)
src/integrations/runtime/middlewares/TenantMiddleware.ts (1)
  • TenantMiddleware (6-62)
src/domain/tenant/tenant.ts (2)
src/domain/tenant/index.ts (1)
  • Tenant (4-4)
src/domain/tenant/types.ts (1)
  • Tenant (13-13)
src/domain/creator/create/types.ts (1)
src/domain/creator/types.ts (1)
  • DataModel (14-14)
src/domain/creator/create/createData.ts (3)
src/domain/post/create/createData.ts (1)
  • createData (6-17)
src/domain/creator/types.ts (1)
  • DataModel (14-14)
src/integrations/utilities/crypto.ts (1)
  • generateId (19-22)
src/webui/features/hooks/useIdentify.ts (1)
src/domain/creator/getMe/getMe.ts (1)
  • getMe (8-11)
src/domain/post/getByCreatorAggregated/getByCreatorAggregated.ts (4)
src/domain/authentication/types.ts (1)
  • Requester (8-8)
src/domain/tenant/types.ts (1)
  • Tenant (13-13)
src/domain/common/validateRange/validateRange.ts (1)
  • validateRange (31-39)
src/domain/post/aggregate/aggregate.ts (1)
  • aggregate (13-34)
src/webui/features/hooks/useCreatorFollowing.ts (1)
src/domain/relation/getFollowing/getFollowing.ts (1)
  • getFollowing (8-13)
src/domain/creator/getMe/getMe.ts (1)
src/domain/creator/getById/getById.ts (1)
  • getById (8-24)
src/domain/post/create/validateData.ts (2)
src/domain/definitions.ts (2)
  • requiredIdValidation (9-17)
  • optionalIdValidation (19-27)
src/domain/post/create/types.ts (1)
  • ValidationModel (6-6)
src/domain/creator/getById/CreatorNotFound.ts (1)
src/integrations/runtime/errors/NotFound.ts (1)
  • NotFound (4-7)
src/domain/post/getByParentAggregated/getByParentAggregated.ts (1)
src/domain/post/aggregate/aggregate.ts (1)
  • aggregate (13-34)
src/webui/components/common/TenantContainer.tsx (1)
src/webui/components/common/hooks/useTenant.ts (1)
  • useTenant (9-18)
src/domain/tenant/types.ts (2)
src/domain/tenant/index.ts (2)
  • DataModel (4-4)
  • Tenant (4-4)
src/domain/types.ts (1)
  • BaseDataModel (8-8)
src/domain/creator/generateNickname/retrieveByStartNickname.ts (3)
src/integrations/database/implementations/mongodb/MongoDb.ts (1)
  • sort (256-272)
src/integrations/database/definitions/types.ts (1)
  • RecordSort (23-23)
src/integrations/database/definitions/constants.ts (1)
  • SortDirections (10-14)
src/domain/tenant/getByOrigin/getByOrigin.ts (4)
src/domain/tenant/index.ts (2)
  • DataModel (4-4)
  • RECORD_TYPE (2-2)
src/domain/tenant/types.ts (1)
  • DataModel (13-13)
src/integrations/database/definitions/types.ts (1)
  • RecordQuery (20-20)
src/domain/tenant/getByOrigin/TenantNotFound.ts (1)
  • TenantNotFound (4-10)
src/domain/relation/exploreAggregated/exploreAggregated.ts (3)
src/domain/common/validateRange/validateRange.ts (1)
  • validateRange (31-39)
src/domain/relation/explore/explore.ts (1)
  • explore (10-22)
src/domain/relation/aggregate/aggregate.ts (1)
  • aggregate (8-18)
src/domain/relation/getFollowersAggregated/getFollowersAggregated.ts (3)
src/domain/common/validateRange/validateRange.ts (1)
  • validateRange (31-39)
src/domain/relation/getFollowers/getFollowers.ts (1)
  • getFollowers (8-13)
src/domain/relation/aggregate/aggregate.ts (1)
  • aggregate (8-18)
src/integrations/runtime/middlewares/OriginMiddleware.ts (4)
src/integrations/validation/definitions/types.ts (1)
  • ValidationSchema (55-55)
src/integrations/runtime/middlewares/TenantMiddleware.ts (3)
  • request (23-43)
  • request (45-56)
  • request (58-61)
src/integrations/runtime/middlewares/AuthenticationMiddleware.ts (12)
  • request (51-58)
  • request (60-87)
  • request (89-105)
  • request (107-130)
  • request (132-139)
  • request (194-211)
  • request (213-216)
  • request (228-231)
  • response (218-221)
  • response (223-226)
  • key (151-154)
  • key (156-166)
src/integrations/runtime/errors/BadRequest.ts (1)
  • BadRequest (4-7)
src/domain/tenant/getByOriginConverted/validateData.ts (3)
src/integrations/validation/definitions/types.ts (1)
  • ValidationSchema (55-55)
src/domain/tenant/getByOriginConverted/types.ts (1)
  • ValidationModel (4-4)
src/domain/tenant/getByOriginConverted/InvalidOrigin.ts (1)
  • InvalidOrigin (4-7)
src/integrations/runtime/middlewares/TenantMiddleware.ts (2)
src/integrations/runtime/middlewares/OriginMiddleware.ts (2)
  • request (51-54)
  • request (56-74)
src/integrations/runtime/middlewares/AuthenticationMiddleware.ts (8)
  • request (51-58)
  • request (60-87)
  • request (89-105)
  • request (107-130)
  • request (132-139)
  • request (194-211)
  • request (213-216)
  • request (228-231)
🪛 Biome (1.9.4)
src/assets/localhost.css

[error] 1-2: An empty block isn't allowed.

Consider removing the empty block or adding styles inside it.

(lint/suspicious/noEmptyBlock)

🔇 Additional comments (145)
src/webui/components/application/LegalInfo.tsx (1)

11-11: LGTM! Copyright year updated correctly.

Simple and appropriate copyright year update for 2025.

eslint.config.js (1)

18-19: LGTM! Docker directory appropriately excluded from linting.

Adding the "docker" directory to the ignore patterns is the correct approach for excluding infrastructure files from linting processes.

src/domain/tenant/definitions.ts (1)

2-2: LGTM! Clean domain constant definition.

The RECORD_TYPE constant provides a centralized identifier for tenant records, following good domain-driven design practices.

src/webui/contexts/AppContext.tsx (1)

2-2: LGTM! Minor formatting improvement.

Good formatting correction adding proper spacing in the import statement.

package.json (1)

41-41: Verify jitar v0.10.0 for potential breaking changes

The bump from 0.9.3 to 0.10.0 for both jitar and @jitar/plugin-vite aligns with your tenant-aware implementation. However, no detailed changelog was found via web search, and pre-1.0 semver allows breaking changes in minor releases.

Action items:

  • Confirm jitar@0.10.0 is published on npm.
  • Review the official changelog or GitHub releases for breaking changes between v0.9.3 and v0.10.0.
  • Test all tenant-aware functionality with the upgraded versions.

Also applies to: lines 54-54

src/domain/post/create/InvalidPost.ts (1)

4-4: Approval: InvalidReaction references replaced with InvalidPost

Verified that:

  • No occurrences of InvalidReaction remain in the codebase.
  • InvalidPost is defined in src/domain/post/create/InvalidPost.ts, imported and thrown in validateData.ts, and re-exported in index.ts.

All references have been correctly updated. Great semantic improvement—approving these changes.

src/domain/tenant/getByOriginConverted/index.ts (1)

2-2: LGTM! Follows established project patterns.

This barrel file correctly follows the project's convention for index resolution, as confirmed by the retrieved learning. The re-export pattern provides a clean interface for the tenant origin conversion functionality.

docs/integrations/AUTHENTICATION.md (1)

36-36: Documentation correctly reflects the multi-tenant authentication changes.

The change from OPENID_REDIRECT_URI to OPENID_REDIRECT_PATH with a relative path aligns well with the multi-tenancy implementation where redirect URLs need to be constructed dynamically based on the request origin/tenant.

src/domain/post/types.ts (1)

11-11: Excellent addition of tenantId for multi-tenant data isolation.

The tenantId field is correctly implemented as a required readonly property, ensuring proper tenant scoping for all post data. This foundational change supports the multi-tenancy architecture effectively.

src/domain/tenant/getByOriginConverted/InvalidOrigin.ts (1)

1-7: Well-structured error class for tenant origin validation.

The InvalidOrigin error class is properly implemented, extending ValidationError and serving as a semantic marker for origin validation failures. The empty class body is appropriate for this specialized error type.

src/integrations/runtime/tearDownBff.ts (2)

2-2: Proper consolidation of identity provider lifecycle management.

The import addition correctly brings the identity provider into the BFF teardown process, aligning with the architectural shift away from separate gateway lifecycle management.


8-8: Consistent disconnection pattern implementation.

The identity provider disconnection logic follows the same robust pattern as the existing event broker disconnection, with proper connection state checking and concurrent execution via Promise.allSettled.

src/integrations/runtime/setUpBff.ts (3)

2-2: Correct integration of identity provider into BFF setup.

The import properly brings the identity provider into the BFF setup process, supporting the consolidated authentication architecture for multi-tenancy.


8-10: Robust concurrent connection implementation.

The identity provider connection is properly added to the Promise.allSettled array, ensuring efficient concurrent initialization alongside the event broker.


17-17: Proper error handling with cleanup logic.

The error handling correctly includes identity provider disconnection, maintaining consistency with the connection attempt and ensuring proper cleanup on setup failure.

docker-compose.yml (1)

12-12: MONGO_INIT_PATH configuration verified

  • MONGO_INIT_PATH is defined in example.env.
  • The docker/mongodb/ directory exists and can be mounted.

No further action required.

src/integrations/runtime/originMiddleware.ts (1)

2-4: Well-implemented singleton pattern for middleware.

The singleton export pattern is appropriate for middleware and the implementation follows good practices. The actual middleware logic (from the relevant code snippets) includes proper origin validation, secure cookie handling, and error management.

src/webui/main.tsx (1)

6-6: Import statement follows proper conventions.

The import statement correctly imports TenantContainer from the components index file, maintaining consistency with the existing import patterns.

segments/reads.json (2)

31-31: Proper JSON formatting with trailing comma.

Good addition of the trailing comma to maintain proper JSON syntax for the new entry.


33-33: ✅ Tenant access entry validated

  • Verified that src/domain/tenant/getByOrigin/getByOrigin.ts exists.
  • The "protected" access level is consistent with other domain resource entries and appropriate for tenant data.

No changes required.

src/domain/tenant/getByOriginConverted/types.ts (1)

2-4: Clean type definition for tenant origin validation.

The ValidationModel type properly uses the Pick utility to extract only the origin property from Tenant, which is appropriate for validation scenarios where only the origin needs to be validated.

src/webui/components/index.ts (1)

22-22: Properly integrated component export.

The TenantContainer export follows the established pattern and maintains alphabetical ordering with other component exports.

src/domain/tenant/getByOrigin/TenantNotFound.ts (1)

4-10: Well-structured error class for tenant resolution failures.

The TenantNotFound error class properly extends the NotFound base class and provides a descriptive error message that includes the origin context, which will be helpful for debugging tenant resolution issues.

src/integrations/authentication/implementations/openid/create.ts (1)

9-12: Consistent refactoring for origin-aware authentication.

The change from OPENID_REDIRECT_URI to OPENID_REDIRECT_PATH and corresponding variable renaming is well-coordinated, supporting the multitenancy architecture where redirect URLs are dynamically constructed based on request origin.

src/domain/creator/create/types.ts (1)

4-4: Proper integration of tenant context in creator validation.

Adding tenantId to the ValidationModel type appropriately extends creator validation to support multitenancy, ensuring that creator creation operations are tenant-scoped.

src/webui/features/hooks/useCreator.ts (1)

5-5: Parameter consistency and initialization verified.

  • getByNicknameAggregated(requester, tenant, nickname) and getAggregated(requester, tenant, followerId, followingId) both accept requester and tenant in the correct order.
  • All other domain hooks follow the same (requester, tenant, …) signature.
  • The imported requester and tenant are the initialized defaults from domain/authentication and domain/tenant, respectively.

No further changes required.

src/integrations/runtime/tenantMiddleware.ts (1)

1-6: Clean and effective middleware configuration.

The approach of exporting a pre-configured middleware instance is clean and follows good separation of concerns. The middleware will handle tenant resolution and caching based on request origins as intended for the multi-tenancy implementation.

src/webui/features/hooks/useNotifications.ts (1)

16-16: Correct tenant parameter integration.

The addition of the tenant parameter to getRecentNotifications correctly implements tenant-scoped data retrieval while maintaining the hook's existing API.

src/domain/creator/getMeAggregated/getMeAggregated.ts (2)

3-3: Proper tenant type integration.

The addition of the Tenant type import correctly supports the tenant-aware refactoring.


9-11: Correct tenant parameter propagation.

The function signature and internal call to getMe properly propagate the tenant context, maintaining the aggregation logic while adding tenant scoping for multi-tenant support.

src/domain/creator/getMe/getMe.ts (2)

3-3: Proper tenant type integration.

The Tenant type import correctly supports the tenant-aware functionality.


8-11: Correct tenant-scoped data retrieval.

The function properly passes tenant.id to getById, which ensures tenant isolation by filtering records based on both creator ID and tenant ID. This correctly implements multi-tenant data scoping.

src/domain/post/create/createData.ts (2)

6-6: Logical parameter ordering for tenant integration.

The placement of tenantId as the second parameter (after creatorId) follows a logical hierarchy where core identity parameters come first, followed by optional content parameters.


8-16: Proper tenant association in post data.

The tenantId is correctly included in the returned DataModel, ensuring all created posts are properly associated with their tenant for multi-tenant data isolation.

src/domain/tenant/getByOrigin/index.ts (1)

2-3: LGTM! Clean barrel export pattern.

The re-export structure provides a clean API surface for the tenant domain's origin-based lookup functionality.

src/domain/creator/getById/CreatorNotFound.ts (1)

4-10: LGTM! Consistent tenant-scoped error handling.

The error class correctly implements tenant-aware error handling with a descriptive message format that includes both the creator ID and tenant context.

src/domain/tenant/types.ts (1)

4-11: Well-designed tenant type definitions.

The type structure effectively supports multi-domain tenancy:

  • DataModel with origins[] allows tenants to have multiple domains
  • Tenant with single origin represents the resolved tenant for a specific request
  • Readonly properties ensure immutability of domain objects
src/domain/post/aggregate/aggregate.ts (1)

13-13: LGTM! Consistent tenant parameter addition.

The function signature correctly adds tenant context for tenant-scoped aggregation.

src/domain/tenant/getByOrigin/getByOrigin.ts (1)

11-14: CONTAINS operator support confirmed

The CONTAINS operator is implemented in both database drivers:

  • MongoDB (src/integrations/database/implementations/mongodb/MongoDb.ts): mapped to $regex
  • In-memory (src/integrations/database/implementations/memory/Memory.ts): uses String.includes()

No changes required.

src/domain/creator/generateNickname/retrieveByNickname.ts (1)

7-12: LGTM: Proper tenant isolation implemented.

The addition of tenantId parameter and corresponding database query filter correctly implements tenant-scoped data access. This ensures nickname lookups are isolated within tenant boundaries, preventing potential cross-tenant data leakage.

src/webui/features/hooks/usePostsFollowing.ts (1)

16-16: LGTM: Consistent tenant parameter propagation.

The function call correctly passes the tenant context as the second parameter, maintaining consistency with the tenant-aware architecture.

src/webui/features/hooks/useHighlight.ts (2)

7-7: LGTM: Consistent tenant import pattern.

The tenant import follows the established pattern for tenant-aware data fetching.


18-18: LGTM: Proper tenant context propagation.

The function call correctly includes tenant parameter in the expected position.

src/webui/features/hooks/useCreatorPosts.ts (2)

7-7: LGTM: Consistent tenant import.

The tenant import follows the established pattern for tenant context access.


17-17: LGTM: Proper tenant-aware creator posts fetching.

The function call correctly includes tenant context while maintaining the logical parameter order: requester, tenant, creator ID, and options.

src/webui/features/hooks/useIdentify.ts (2)

8-8: LGTM: Consistent tenant import pattern.

The tenant import maintains consistency with the established multi-tenant architecture.


30-30: LGTM: Secure tenant-scoped identity retrieval.

The function call correctly passes tenant context to getMe, which according to the relevant code snippet (src/domain/creator/getMe/getMe.ts) uses tenant.id to scope the identity lookup. This ensures users can only access their identity within the correct tenant context, providing proper tenant isolation.

src/domain/notification/aggregate/aggregate.ts (1)

5-5: LGTM! Tenant context properly added and propagated.

The tenant parameter addition follows the consistent pattern across the codebase. The function correctly:

  • Imports the Tenant type
  • Updates the function signature to include the tenant parameter
  • Propagates tenant context to both getRelationData and getPostData calls

This ensures proper tenant scoping for notification aggregation.

Also applies to: 10-10, 13-14

src/domain/creator/getByNicknameAggregated/getByNicknameAggregated.ts (2)

2-4: LGTM! Proper imports for tenant-aware function signature.

The import statements correctly add the required types for the updated function signature.


9-9: Incorrect assumption about aggregate signature

The aggregate function in src/domain/creator/aggregate/aggregate.ts is declared as:

export default async function aggregate(data: DataModel): Promise<AggregatedData>

—so it only requires the data parameter. All three callers in the creator domain correctly invoke aggregate(data). No changes are needed.

Likely an incorrect or invalid review comment.

src/domain/post/getByCreatorAggregated/getByCreatorAggregated.ts (1)

6-6: LGTM! Correct tenant context propagation throughout the function.

The implementation properly:

  • Imports the Tenant type
  • Updates the function signature to include the tenant parameter
  • Passes all required parameters (requester, tenant, item) to the aggregate function, which matches the expected signature from src/domain/post/aggregate/aggregate.ts

This ensures consistent tenant-scoped post aggregation.

Also applies to: 14-14, 20-20

src/domain/creator/getByEmail/getByEmail.ts (1)

7-7: LGTM! Proper tenant-scoped database query implementation.

The function correctly implements tenant isolation by:

  • Adding tenantId parameter to the function signature
  • Including both email and tenantId conditions in the database query with EQUALS comparisons
  • Ensuring creators can only be retrieved within their tenant scope

This prevents cross-tenant data access and maintains proper data isolation.

Also applies to: 9-12

src/domain/creator/create/validateData.ts (1)

5-5: LGTM! Comprehensive tenant validation implementation.

The validation logic correctly incorporates tenant context by:

  • Importing requiredIdValidation for consistent ID validation patterns
  • Adding tenantId as a required field in the validation schema
  • Updating the function signature to accept tenantId from the ValidationModel
  • Including tenantId in the validator call to ensure it's validated alongside other fields

This ensures creators cannot be created without a valid tenant context, maintaining proper multi-tenant data integrity.

Also applies to: 22-22, 26-26, 28-28

src/domain/creator/getById/getById.ts (2)

8-14: Excellent tenant isolation implementation.

The addition of tenantId parameter and filtering ensures proper tenant data isolation, which is critical for multi-tenant security. The query structure correctly enforces that records can only be accessed within their tenant scope.


16-21: Good error handling with tenant context.

Using database.findRecord with the tenant-scoped query and including both id and tenantId in the error message provides clear debugging information while maintaining security boundaries.

src/domain/tenant/getByOriginConverted/validateData.ts (2)

8-18: Strong origin validation for tenant security.

The validation schema properly enforces URL format and required constraints, which is critical for secure tenant resolution. This prevents potential injection attacks and ensures only valid origins are processed.


20-28: Appropriate error handling for validation failures.

The function correctly throws a custom InvalidOrigin error with validation messages, providing clear feedback while maintaining security boundaries for tenant origin validation.

src/domain/tenant/index.ts (1)

1-7: Clean domain module organization.

The barrel export pattern provides a clean API surface for the tenant domain, making it easy for other modules to consume tenant-related types and constants.

src/domain/post/create/create.ts (2)

10-16: Proper tenant integration in post creation.

The addition of tenantId parameter and its propagation to createData ensures tenant-scoped post creation. The parameter placement is logical and maintains the existing function contract pattern.


26-37: Excellent error handling preservation.

The error handling logic correctly maintains data consistency by cleaning up the post on failure, while the tenant context doesn't interfere with the cleanup process.

src/domain/relation/getFollowingAggregated/getFollowingAggregated.ts (1)

11-17: Effective tenant integration in aggregation.

The addition of the tenant parameter and its propagation to the aggregate function ensures tenant-scoped data access during relation aggregation. The concurrent processing with Promise.all maintains performance efficiency.

src/webui/components/common/hooks/useTenant.ts (2)

9-18: Well-structured tenant data fetching hook.

The hook properly encapsulates tenant data fetching logic with appropriate memoization and state management. The integration with useLoadData provides a consistent loading state pattern.


4-4: I couldn’t locate src/webui/components/common/hooks/useTenant.ts in the repo—no files match “useTenant.ts”. Can you please confirm the path or filename?

src/domain/post/explore/explore.ts (1)

9-16: Excellent tenant-aware implementation.

The function correctly integrates tenant context by:

  • Adding the Tenant parameter in the appropriate position
  • Passing tenant.id to the data retrieval function
  • Maintaining the existing business logic while adding tenant scoping

This follows the established multi-tenancy pattern consistently.

src/webui/features/hooks/useCreatorFollowing.ts (2)

7-7: Tenant integration follows established pattern.

The tenant import and usage aligns with the multi-tenancy architecture being implemented across the application.


17-17: Verified getFollowingAggregated signature matches tenant parameter. No changes required.

The call in useCreatorFollowing.ts correctly passes (requester, tenant, creator.id, { limit, offset: page * limit }) to:

export default async function getFollowingAggregated(
  requester: Requester,
  tenant: Tenant,
  followerId: string,
  range: Range
): Promise<AggregatedData[]>

Everything aligns—tenant integration is correct.

src/webui/features/hooks/usePost.ts (1)

7-18: Consistent tenant-aware implementation.

The hook properly integrates tenant context by:

  • Adding the tenant import
  • Passing tenant parameter to the get function call
  • Maintaining the existing conditional logic

This follows the established multi-tenancy pattern consistently across the codebase.

src/domain/relation/aggregate/aggregate.ts (1)

8-10: Proper tenant-scoped aggregation implementation.

The function correctly implements tenant-aware aggregation by:

  • Adding the Tenant parameter to the function signature
  • Passing tenant.id to the getCreatorData call for proper tenant scoping
  • Preserving the existing aggregation logic

This ensures that relation aggregation respects tenant boundaries.

src/webui/features/hooks/useCreatePostComicReaction.ts (2)

8-8: LGTM: Tenant import added correctly.

The tenant import follows the established pattern for multi-tenancy support integration.


14-15: LGTM: Consistent tenant parameter propagation.

Both createComicReaction and getReaction function calls have been updated consistently to include the tenant parameter, ensuring proper tenant scoping for comic reaction operations.

src/integrations/runtime/authenticationMiddleware.ts (3)

12-12: LGTM: Environment variable updated for path-based redirects.

The change from AUTHENTICATION_CLIENT_URI to AUTHENTICATION_CLIENT_PATH and corresponding variable rename aligns with the architectural shift to path-based redirects, as confirmed by the AuthenticationMiddleware implementation expecting a redirectPath parameter.


14-14: LGTM: Whitelist updated for tenant functionality.

Adding 'domain/tenant/getByOriginConverted' to the whitelist is necessary to allow tenant origin resolution to bypass authentication, which is essential for the multi-tenancy support.


16-16: LGTM: Constructor call updated consistently.

The parameter name change to redirectPath maintains consistency with the environment variable renaming and the AuthenticationMiddleware constructor signature.

src/webui/features/hooks/usePostsRecommended.ts (2)

6-6: LGTM: Tenant import added correctly.

The tenant import follows the established pattern for multi-tenancy support integration.


16-16: LGTM: Tenant parameter added to domain function call.

The getPostsRecommended call has been updated to include the tenant parameter, ensuring proper tenant scoping for recommended posts retrieval while maintaining the hook's existing API.

src/domain/relation/getAggregated/getAggregated.ts (3)

2-4: LGTM: Type imports added correctly.

The Requester and Tenant type imports are properly added to support the new function signature parameters.


9-9: LGTM: Function signature updated for multi-tenancy.

The function signature has been properly extended to include requester and tenant parameters, enabling tenant-aware relation aggregation.


13-13: LGTM: Tenant parameter propagated to aggregate function.

The aggregate function call correctly passes the tenant parameter, as confirmed by the relevant code snippet showing aggregate(tenant: Tenant, data: DataModel) signature. The get function call appropriately remains unchanged as it appears to be a simple data retrieval operation.

src/domain/post/exploreAggregated/exploreAggregated.ts (3)

6-6: LGTM: Tenant type import added correctly.

The Tenant type import is properly added to support the new function parameter.


12-12: LGTM: Function signature updated for tenant awareness.

The function signature has been properly extended to include the tenant parameter, enabling tenant-scoped post exploration and aggregation.


16-16: LGTM: Tenant parameter propagated consistently.

Both the explore and aggregate function calls have been updated to include the tenant parameter, as confirmed by the relevant code snippets. This ensures proper tenant scoping throughout the post exploration and aggregation pipeline while preserving the existing range validation logic.

Also applies to: 18-18

src/domain/tenant/getByOriginConverted/getByOriginConverted.ts (1)

6-16: Verify that getByOrigin always returns an object with an id property

Before merging, please confirm that the return type of getByOrigin(origin) includes a non-optional id field to avoid runtime errors in getByOriginConverted. If the underlying type is missing or marks id as optional, you’ll need to:

  • Update the type/interface for the tenant data model in
    src/domain/tenant/getByOrigin.ts (or its associated types file) to include id: string (or appropriate type).
  • Or add a runtime null/undefined check on tenant.id before returning from getByOriginConverted.

Files to review:

  • src/domain/tenant/getByOriginConverted/getByOriginConverted.ts (calls getByOrigin)
  • src/domain/tenant/getByOrigin.ts (implementation and return type)
  • Any types.ts or models.ts defining the tenant DataModel or interface
src/webui/features/hooks/useCreatorFollowers.ts (1)

7-7: Ignore tenant availability and dependency concerns.

The tenant import is a module‐level constant of type Tenant (always defined) and cannot be undefined. You’re calling the correct overload—getFollowersAggregated(requester, tenant, creator.id, {…})—which matches its signature. Since tenant never changes at runtime, it doesn’t need to be in the hook’s dependency array. No updates are required here.

Likely an incorrect or invalid review comment.

src/domain/creator/generateNickname/retrieveByStartNickname.ts (1)

8-8: All retrieveByStartNickname call sites have been updated

I searched for every call to retrieveByStartNickname and confirmed they all pass both nickname and tenantId. The only usage is in:

  • src/domain/creator/generateNickname/generateNickname.ts
    const foundData = await retrieveByStartNickname(
      `${existingData.nickname}_`,
      tenantId
    );

No other invocations exist. This breaking change is already handled; no further updates are needed.

services/standalone.json (2)

5-5: Gateway setup/teardown removal verified

No occurrences of setupGateway or tearDownGateway remain in the codebase. The removal of gateway initialization is intentional and does not introduce any breakages.


15-19: Middleware execution order verified

Both new middleware files are present and correctly interdependent:

  • src/integrations/runtime/originMiddleware.ts exists.
  • src/integrations/runtime/tenantMiddleware.ts exists and calls #getOrigin(request) before resolving or caching tenants.

The sequence origin → authentication → tenant matches the intended request flow. No further changes needed.

src/webui/features/hooks/useExplorePosts.ts (1)

16-16: Verify explorePosts signature includes tenant
I wasn’t able to locate the explorePosts declaration in the repo—please confirm that its signature has been updated to accept tenant as the second argument to match this call and avoid runtime errors:

return explorePosts(requester, tenant, { limit, offset: page * limit });

Key locations to check:

  • The file under which explorePosts is defined (e.g. in src/domain/post/ or its index/export file)
  • Ensure the signature reads:
    function explorePosts(requester, tenant, options) {  }
src/domain/relation/explore/explore.ts (3)

4-4: LGTM: Tenant type import added correctly.

The import for the Tenant type is properly added to support the multi-tenancy implementation.


10-10: LGTM: Function signature updated for tenant awareness.

The function signature correctly includes the new tenant: Tenant parameter, maintaining the logical parameter order.


16-16: LGTM: Tenant ID properly propagated to getOtherCreators.

The tenant context is correctly passed by extracting tenant.id and placing it as the first argument to getOtherCreators, which aligns with the multi-tenant architecture pattern.

src/domain/post/getByParentAggregated/getByParentAggregated.ts (3)

5-5: LGTM: Tenant type import added correctly.

The import for the Tenant type is properly added to support the tenant-aware aggregation.


11-11: LGTM: Function signature updated consistently.

The function signature correctly includes the tenant: Tenant parameter, maintaining proper parameter ordering between requester and business logic parameters.


15-15: LGTM: Tenant context properly propagated to aggregate function.

The tenant parameter is correctly passed to the aggregate function for each item. This aligns with the updated aggregate function signature shown in the relevant code snippet from src/domain/post/aggregate/aggregate.ts (lines 12-33).

src/domain/notification/getRecentAggregated/getRecentAggregated.ts (3)

6-6: LGTM: Tenant type import added correctly.

The import for the Tenant type is properly added to support tenant-aware notification aggregation.


12-12: LGTM: Function signature updated consistently.

The function signature correctly includes the tenant: Tenant parameter with proper parameter ordering.


18-18: LGTM: Tenant context properly propagated to aggregate function.

The tenant parameter is correctly passed to the aggregate function for each notification item. This aligns with the updated notification aggregate function signature shown in the relevant code snippet from src/domain/notification/aggregate/aggregate.ts (lines 9-23).

src/webui/features/hooks/useExploreCreators.ts (1)

16-16: LGTM: Tenant parameter correctly added to exploreRelations call.

The tenant parameter is properly passed to the exploreRelations function call, maintaining the correct parameter order as expected by the backend domain function.

src/domain/post/getByIdAggregated/getByIdAggregated.ts (3)

3-3: LGTM: Tenant type import added correctly.

The import for the Tenant type is properly added to support tenant-aware post aggregation.


11-11: LGTM: Function signature updated consistently.

The function signature correctly includes the tenant: Tenant parameter, following the established pattern for tenant-aware domain functions.


15-15: LGTM: Tenant context properly passed to aggregate function.

The tenant parameter is correctly passed to the aggregate function, ensuring tenant-scoped data aggregation for individual post retrieval.

src/domain/post/create/validateData.ts (1)

13-13: LGTM: Consistent tenant integration in validation schema.

The addition of tenantId as a required field follows the established validation pattern and maintains consistency with other ID fields. The function signature and validation call are properly updated to include tenant context.

Also applies to: 19-19, 30-30

src/domain/creator/generateNickname/generateNickname.ts (1)

9-9: LGTM: Proper tenant scoping for nickname generation.

The function correctly integrates tenant context by passing tenantId to both retrieval functions. This ensures nickname uniqueness is scoped per tenant while maintaining the existing collision resolution logic.

Also applies to: 13-13, 20-20

src/domain/creator/getByNickname/getByNickname.ts (1)

8-8: LGTM: Solid tenant-scoped nickname lookup implementation.

The function properly integrates tenant context in the database query and improves code clarity by renaming the variable from data to creator. The compound query ensures proper tenant isolation while maintaining existing error handling patterns.

Also applies to: 10-13, 15-15, 17-17, 22-22

src/domain/creator/aggregate/types.ts (1)

7-7: LGTM! Proper separation of tenant context from aggregated data.

The exclusion of tenantId from AggregatedData follows good design patterns by keeping tenant context separate from core business data. This aligns with the explicit tenant parameter approach used throughout the domain functions.

services/bff.json (1)

9-13: LGTM! Middleware pipeline order is logically structured.

The middleware processing order correctly establishes the multi-tenant request pipeline:

  1. originMiddleware - extracts request origin (foundational)
  2. authenticationMiddleware - handles origin-aware authentication
  3. tenantMiddleware - manages tenant context based on origin

Each middleware builds upon the context established by the previous one.

src/domain/creator/getByIdAggregated/getByIdAggregated.ts (1)

6-8: Parameter order is correct; no changes needed.

I verified that getById in src/domain/creator/getById/getById.ts is declared as:

export default async function getById(id: string, tenantId: string): Promise<DataModel>

so calling getById(id, tenantId) from getByIdAggregated matches its signature.

src/domain/post/createWithComment/createWithComment.ts (2)

4-4: LGTM! Proper tenant type import.

The import of the Tenant type from the tenant domain is correctly added to support the new tenant parameter.


8-12: LGTM! Tenant context properly propagated.

The function signature correctly includes the tenant parameter, and tenant.id is properly passed to createPost, replacing the previous undefined value. This ensures tenant-scoped post creation.

src/integrations/authentication/definitions/interfaces.ts (1)

12-14: LGTM! Origin-aware authentication interface properly defined.

The addition of the origin parameter to both getLoginUrl and login methods enables dynamic authentication flows based on request origin. This properly supports the multi-tenant architecture by allowing tenant-specific authentication handling.

src/domain/creator/create/create.ts (1)

7-9: LGTM! Tenant context properly integrated.

The function signature correctly adds tenantId as the first parameter and properly passes it to createData. This follows the consistent pattern established across the multi-tenancy refactoring.

src/domain/post/explore/retrieveData.ts (1)

8-16: LGTM! Tenant-scoped querying implemented correctly.

The function properly adds tenantId parameter and includes it in the query filter using the EQUALS condition. This ensures that only posts belonging to the specified tenant are retrieved, which is essential for proper multi-tenant data isolation.

src/domain/creator/create/createData.ts (1)

6-14: LGTM! Tenant context correctly added to data creation.

The function properly adds tenantId as the first parameter and includes it in the returned data model. This follows the same pattern established in other domain createData functions and ensures all creator records are properly associated with their tenant.

src/webui/features/hooks/usePostReactions.ts (1)

7-17: Approved: tenant context integration verified

Verified that:

  • src/domain/tenant/index.ts exports a default tenant object of type Tenant.
  • getByParentAggregated (imported as getReactionsByPost) signature is async function(requester, tenant, postId, range).
  • usePostReactions correctly imports tenant and passes it as the second argument, matching other hooks’ patterns.

No further changes needed.

src/domain/post/createWithComic/createWithComic.ts (1)

4-12: LGTM! Tenant context correctly propagated to post creation.

The function properly adds the tenant parameter with correct typing and passes tenant.id to the createPost function. This maintains the tenant context throughout the post creation flow while preserving the existing comic creation logic.

src/domain/post/getRecommended/getRecommended.ts (2)

8-8: LGTM: Function signature correctly updated for multi-tenancy.

The parameter decomposition from Requester object to separate requesterId and tenantId strings aligns well with the tenant-aware refactoring pattern seen throughout the codebase.


14-16: LGTM: Proper tenant filtering implemented.

The query correctly filters posts by tenant using the EQUALS operator on tenantId, ensuring proper tenant isolation. The creatorId filter change from requester to requesterId is also correct.

src/webui/features/hooks/useCreatePostCommentReaction.ts (2)

8-8: LGTM: Tenant import correctly added.

The import statement properly brings in the tenant context needed for the hook's functionality.


14-15: LGTM: Tenant context properly propagated to domain functions.

Both createCommentReaction and getReaction calls correctly include the tenant parameter, ensuring tenant-aware comment reaction operations. The parameter ordering (requester, tenant, then function-specific params) is consistent with the multi-tenancy pattern.

src/domain/post/getRecommendedAggregated/getRecommendedAggregated.ts (3)

6-6: LGTM: Tenant type import and parameter addition.

The Tenant type import is properly added, and the function signature correctly includes the tenant parameter in a logical position after the requester.

Also applies to: 12-12


16-16: LGTM: Correct parameter decomposition for getRecommended call.

The call properly destructures the requester and tenant objects to pass requester.id and tenant.id as separate parameters, aligning with the updated getRecommended function signature.


18-18: LGTM: Tenant context propagated through aggregation.

The aggregate function call correctly includes the tenant parameter, ensuring that tenant context is maintained throughout the data aggregation process.

src/domain/relation/getFollowersAggregated/getFollowersAggregated.ts (2)

5-5: LGTM: Tenant type import and parameter addition.

The Tenant type import is properly added, and the function signature correctly includes the tenant parameter in a logical position after the requester.

Also applies to: 11-11


17-17: LGTM: Tenant context correctly passed to aggregate function.

The aggregate function call properly passes the tenant parameter as the first argument, which aligns with the updated function signature shown in the relevant code snippets from src/domain/relation/aggregate/aggregate.ts.

src/domain/creator/register/register.ts (2)

12-12: LGTM: Function signature correctly updated with tenantId parameter.

The addition of tenantId as the first parameter ensures tenant context is properly established for creator registration operations.


19-19: LGTM: Tenant context properly propagated to dependent functions.

Both generateNickname and create function calls correctly pass the tenantId parameter, ensuring tenant-scoped nickname uniqueness and proper data association. The parameter ordering (tenantId first) is consistent with the multi-tenancy pattern.

Also applies to: 25-25

example.env (2)

26-26: Well-designed change for multi-tenancy support.

Converting from absolute URIs to relative paths enables dynamic URL construction based on tenant origins, which is essential for multi-tenant applications where different tenants may have different base URLs.

Also applies to: 31-31


66-66: Good addition for tenant-specific database initialization.

The new MONGO_INIT_PATH supports tenant-specific MongoDB initialization, which aligns perfectly with the multi-tenancy objectives.

src/domain/notification/getByIdAggregated/getByIdAggregated.ts (1)

3-3: Consistent tenant-aware implementation.

The addition of the tenant parameter and its propagation to the aggregate function follows the established pattern for multi-tenancy support. The getById call appropriately remains unchanged as it likely fetches by unique identifier rather than requiring tenant scoping.

Also applies to: 9-9, 13-13

src/domain/creator/getOthers/getOthers.ts (1)

9-9: Critical tenant isolation implementation.

The addition of tenantId parameter and the corresponding database query filtering is essential for preventing cross-tenant data leakage. The AND logic properly combines tenant scoping with the existing ID exclusion, ensuring creators can only access others within their tenant boundary.

Also applies to: 11-16

src/domain/relation/exploreAggregated/exploreAggregated.ts (1)

5-5: Proper tenant context propagation.

The tenant parameter is correctly added to the function signature and properly propagated to both explore and aggregate functions. The parameter ordering is consistent with the established pattern shown in the relevant code snippets.

Also applies to: 12-12, 16-16, 18-18

src/domain/authentication/login/login.ts (2)

2-2: Good practice with explicit type imports.

Converting to explicit type imports improves clarity and helps with build optimization by clearly distinguishing runtime imports from type-only imports.

Also applies to: 6-6, 8-8


10-10: Critical tenant-aware authentication implementation.

The addition of the tenant parameter and its proper usage in both getCreatorByEmail and registerCreator ensures that user lookup and registration are properly scoped to the tenant boundary. This prevents cross-tenant user access and maintains proper data isolation in the authentication flow.

Also applies to: 12-12, 15-15

src/integrations/runtime/middlewares/OriginMiddleware.ts (2)

1-19: LGTM: Well-structured imports and validation schema.

The imports are properly organized, the cookie name follows conventions, and the URL validation schema is correctly configured with the required flag.


76-84: LGTM: Proper validation implementation.

The validation logic correctly uses the schema and throws appropriate errors for invalid origins.

src/integrations/authentication/implementations/openid/OpenID.ts (2)

19-19: LGTM: Configuration property renamed for clarity.

The rename from redirectUri to redirectPath better reflects the usage of relative paths in the multi-tenant architecture.


55-57: LGTM: Proper URL construction for multi-tenant support.

The addition of the origin parameter and URL construction using new URL() correctly handles dynamic redirect URLs for different tenants.

src/integrations/runtime/middlewares/TenantMiddleware.ts (4)

6-14: LGTM: Clean middleware structure with configurable tenant path.

The class structure is well-designed with appropriate caching mechanism and configurable tenant resolution path.


16-21: LGTM: Clear request routing logic.

The conditional routing between tenant fetching and regular request handling is well-implemented and easy to understand.


45-56: LGTM: Proper tenant context injection.

The method correctly injects cached tenant data into request arguments when available, allowing graceful degradation when tenant data isn't cached.


58-61: LGTM: Consistent origin extraction pattern.

The method follows the same pattern as other middleware files. The type assertion is safe given that OriginMiddleware validates and sets the origin header before this middleware runs.

src/integrations/runtime/middlewares/AuthenticationMiddleware.ts (5)

24-32: LGTM: Parameter naming updated for consistency.

The rename from redirectUrl to redirectPath aligns with the multi-tenant architecture changes and maintains consistency across the codebase.


51-57: LGTM: Origin-aware login URL generation.

The method correctly extracts the origin and passes it to the identity provider for dynamic login URL generation based on the requesting tenant.


63-76: LGTM: Improved session management with proper cleanup.

Excellent improvements:

  1. Origin-aware session creation
  2. Proper session cleanup on failure (logout if response is not 200)
  3. Early return prevents processing failed authentications

These changes improve error handling and prevent orphaned sessions.


223-226: LGTM: Proper origin-aware redirect URL construction.

The method correctly constructs redirect URLs using the origin and relative path with proper URL handling via the URL constructor.


228-231: LGTM: Consistent origin extraction pattern.

The new method follows the established pattern for origin extraction across middleware files and safely assumes the header is present due to OriginMiddleware validation.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
test/domain/authentication/login.spec.ts (1)

21-21: Fix test description to match actual function signature.

The test description shows .login(identity, tenant) but the actual function signature is login(tenant: Tenant, identity: Identity) with tenant as the first parameter.

-    describe('.login(identity, tenant)', () =>
+    describe('.login(tenant, identity)', () =>
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9340c75 and 24714d9.

📒 Files selected for processing (86)
  • docker/mongodb/init.js (1 hunks)
  • src/domain/authentication/login/login.ts (1 hunks)
  • src/domain/creator/aggregate/types.ts (1 hunks)
  • src/domain/creator/create/types.ts (1 hunks)
  • src/domain/creator/create/validateData.ts (2 hunks)
  • src/domain/creator/generateNickname/generateNickname.ts (1 hunks)
  • src/domain/creator/generateNickname/retrieveByNickname.ts (1 hunks)
  • src/domain/creator/generateNickname/retrieveByStartNickname.ts (1 hunks)
  • src/domain/creator/getByEmail/getByEmail.ts (1 hunks)
  • src/domain/creator/getById/CreatorNotFound.ts (1 hunks)
  • src/domain/creator/getById/getById.ts (1 hunks)
  • src/domain/creator/getByIdAggregated/getByIdAggregated.ts (1 hunks)
  • src/domain/creator/getByNickname/getByNickname.ts (1 hunks)
  • src/domain/creator/getByNicknameAggregated/getByNicknameAggregated.ts (1 hunks)
  • src/domain/creator/getMe/getMe.ts (1 hunks)
  • src/domain/creator/getMeAggregated/getMeAggregated.ts (1 hunks)
  • src/domain/creator/getOthers/getOthers.ts (1 hunks)
  • src/domain/creator/register/register.ts (1 hunks)
  • src/domain/creator/types.ts (1 hunks)
  • src/domain/creator/updateNickname/retrieveByNickname.ts (1 hunks)
  • src/domain/creator/updateNickname/updateNickname.ts (1 hunks)
  • src/domain/notification/aggregate/aggregate.ts (1 hunks)
  • src/domain/notification/getByIdAggregated/getByIdAggregated.ts (1 hunks)
  • src/domain/notification/getRecentAggregated/getRecentAggregated.ts (1 hunks)
  • src/domain/post/aggregate/aggregate.ts (1 hunks)
  • src/domain/post/create/create.ts (1 hunks)
  • src/domain/post/create/createData.ts (1 hunks)
  • src/domain/post/create/types.ts (1 hunks)
  • src/domain/post/create/validateData.ts (2 hunks)
  • src/domain/post/createWithComic/createWithComic.ts (1 hunks)
  • src/domain/post/createWithComment/createWithComment.ts (1 hunks)
  • src/domain/post/explore/explore.ts (1 hunks)
  • src/domain/post/explore/retrieveData.ts (1 hunks)
  • src/domain/post/exploreAggregated/exploreAggregated.ts (1 hunks)
  • src/domain/post/getByCreatorAggregated/getByCreatorAggregated.ts (1 hunks)
  • src/domain/post/getByFollowingAggregated/getByFollowingAggregated.ts (1 hunks)
  • src/domain/post/getById/getById.ts (1 hunks)
  • src/domain/post/getByIdAggregated/getByIdAggregated.ts (1 hunks)
  • src/domain/post/getByParent/getByParent.ts (1 hunks)
  • src/domain/post/getByParentAggregated/getByParentAggregated.ts (1 hunks)
  • src/domain/post/getRecommended/getRecommended.ts (1 hunks)
  • src/domain/post/getRecommendedAggregated/getRecommendedAggregated.ts (1 hunks)
  • src/domain/post/remove/remove.ts (3 hunks)
  • src/domain/post/types.ts (1 hunks)
  • src/domain/rating/toggle/toggle.ts (1 hunks)
  • src/domain/relation/establish/establish.ts (1 hunks)
  • src/domain/relation/explore/explore.ts (1 hunks)
  • src/domain/relation/exploreAggregated/exploreAggregated.ts (1 hunks)
  • src/domain/relation/getAggregated/getAggregated.ts (1 hunks)
  • src/domain/relation/getFollowersAggregated/getFollowersAggregated.ts (1 hunks)
  • src/domain/relation/getFollowingAggregated/getFollowingAggregated.ts (1 hunks)
  • src/domain/tenant/getByOriginConverted/types.ts (1 hunks)
  • src/domain/tenant/getByOriginConverted/validateData.ts (1 hunks)
  • src/webui/editor/model/Bubble.ts (1 hunks)
  • src/webui/features/hooks/useAddComicPost.ts (2 hunks)
  • src/webui/features/hooks/useCreatePostComicReaction.ts (1 hunks)
  • src/webui/features/hooks/useCreatePostCommentReaction.ts (1 hunks)
  • src/webui/features/hooks/useCreator.ts (2 hunks)
  • src/webui/features/hooks/useCreatorFollowers.ts (2 hunks)
  • src/webui/features/hooks/useCreatorFollowing.ts (2 hunks)
  • src/webui/features/hooks/useCreatorPosts.ts (2 hunks)
  • src/webui/features/hooks/useEstablishRelation.ts (1 hunks)
  • src/webui/features/hooks/useExploreCreators.ts (2 hunks)
  • src/webui/features/hooks/useExplorePosts.ts (2 hunks)
  • src/webui/features/hooks/useHighlight.ts (2 hunks)
  • src/webui/features/hooks/useIdentify.ts (2 hunks)
  • src/webui/features/hooks/useNotifications.ts (2 hunks)
  • src/webui/features/hooks/usePost.ts (2 hunks)
  • src/webui/features/hooks/usePostReactions.ts (2 hunks)
  • src/webui/features/hooks/usePostsFollowing.ts (2 hunks)
  • src/webui/features/hooks/usePostsRecommended.ts (2 hunks)
  • src/webui/features/hooks/useRemovePost.ts (2 hunks)
  • src/webui/features/hooks/useTogglePostRating.ts (1 hunks)
  • src/webui/features/hooks/useUpdateNickname.ts (2 hunks)
  • test/domain/authentication/login.spec.ts (2 hunks)
  • test/domain/creator/updateNickname.spec.ts (2 hunks)
  • test/domain/notification/getRecentAggregated.spec.ts (3 hunks)
  • test/domain/post/createWithComic.spec.ts (2 hunks)
  • test/domain/post/getByFollowingAggregated.spec.ts (2 hunks)
  • test/domain/post/getRecommendedAggregated.spec.ts (2 hunks)
  • test/domain/post/remove.spec.ts (2 hunks)
  • test/domain/rating/toggle.spec.ts (2 hunks)
  • test/domain/relation/establish.spec.ts (2 hunks)
  • test/domain/relation/exploreAggregated.spec.ts (3 hunks)
  • test/domain/relation/getFollowersAggregated.spec.ts (2 hunks)
  • test/domain/relation/getFollowingAggregated.spec.ts (2 hunks)
✅ Files skipped from review due to trivial changes (2)
  • src/webui/editor/model/Bubble.ts
  • src/domain/tenant/getByOriginConverted/validateData.ts
🚧 Files skipped from review as they are similar to previous changes (75)
  • src/domain/creator/types.ts
  • src/domain/tenant/getByOriginConverted/types.ts
  • src/domain/creator/generateNickname/retrieveByNickname.ts
  • src/domain/authentication/login/login.ts
  • src/domain/post/exploreAggregated/exploreAggregated.ts
  • src/webui/features/hooks/useCreator.ts
  • src/domain/post/aggregate/aggregate.ts
  • src/domain/post/getByCreatorAggregated/getByCreatorAggregated.ts
  • src/webui/features/hooks/useExplorePosts.ts
  • src/webui/features/hooks/useAddComicPost.ts
  • test/domain/creator/updateNickname.spec.ts
  • src/webui/features/hooks/useUpdateNickname.ts
  • src/webui/features/hooks/useCreatorFollowers.ts
  • src/webui/features/hooks/usePost.ts
  • src/domain/creator/create/types.ts
  • src/domain/post/getById/getById.ts
  • src/domain/post/explore/retrieveData.ts
  • src/webui/features/hooks/useRemovePost.ts
  • src/domain/creator/getByNickname/getByNickname.ts
  • src/domain/notification/aggregate/aggregate.ts
  • src/domain/creator/getMe/getMe.ts
  • src/domain/creator/getByEmail/getByEmail.ts
  • src/domain/creator/create/validateData.ts
  • src/domain/creator/getById/CreatorNotFound.ts
  • src/webui/features/hooks/useCreatorPosts.ts
  • test/domain/post/remove.spec.ts
  • src/domain/creator/generateNickname/retrieveByStartNickname.ts
  • src/webui/features/hooks/useEstablishRelation.ts
  • src/domain/creator/register/register.ts
  • src/domain/post/types.ts
  • src/webui/features/hooks/useExploreCreators.ts
  • src/domain/creator/getMeAggregated/getMeAggregated.ts
  • src/domain/relation/getFollowingAggregated/getFollowingAggregated.ts
  • src/domain/creator/getOthers/getOthers.ts
  • src/webui/features/hooks/useCreatorFollowing.ts
  • src/webui/features/hooks/useHighlight.ts
  • src/domain/creator/updateNickname/updateNickname.ts
  • src/domain/post/getRecommended/getRecommended.ts
  • src/domain/creator/getByIdAggregated/getByIdAggregated.ts
  • src/domain/relation/establish/establish.ts
  • src/domain/notification/getRecentAggregated/getRecentAggregated.ts
  • src/domain/creator/aggregate/types.ts
  • src/webui/features/hooks/useIdentify.ts
  • src/domain/post/create/types.ts
  • src/webui/features/hooks/usePostsFollowing.ts
  • src/webui/features/hooks/useCreatePostCommentReaction.ts
  • src/webui/features/hooks/usePostsRecommended.ts
  • src/webui/features/hooks/useNotifications.ts
  • src/domain/creator/getById/getById.ts
  • src/domain/relation/getAggregated/getAggregated.ts
  • test/domain/rating/toggle.spec.ts
  • src/domain/post/getRecommendedAggregated/getRecommendedAggregated.ts
  • test/domain/relation/establish.spec.ts
  • src/domain/creator/getByNicknameAggregated/getByNicknameAggregated.ts
  • src/domain/post/create/validateData.ts
  • src/domain/relation/getFollowersAggregated/getFollowersAggregated.ts
  • src/domain/post/getByParentAggregated/getByParentAggregated.ts
  • src/domain/rating/toggle/toggle.ts
  • src/domain/creator/updateNickname/retrieveByNickname.ts
  • src/domain/post/create/createData.ts
  • src/webui/features/hooks/useCreatePostComicReaction.ts
  • src/domain/post/createWithComment/createWithComment.ts
  • src/domain/creator/generateNickname/generateNickname.ts
  • src/domain/post/create/create.ts
  • src/domain/post/createWithComic/createWithComic.ts
  • src/domain/relation/explore/explore.ts
  • src/domain/relation/exploreAggregated/exploreAggregated.ts
  • src/domain/post/remove/remove.ts
  • src/domain/post/getByParent/getByParent.ts
  • src/domain/post/explore/explore.ts
  • src/webui/features/hooks/usePostReactions.ts
  • src/webui/features/hooks/useTogglePostRating.ts
  • src/domain/post/getByFollowingAggregated/getByFollowingAggregated.ts
  • src/domain/notification/getByIdAggregated/getByIdAggregated.ts
  • src/domain/post/getByIdAggregated/getByIdAggregated.ts
🧰 Additional context used
🧠 Learnings (7)
📓 Common learnings
Learnt from: basmasking
PR: MaskingTechnology/comify#428
File: src/webui/components/common/TenantContainer.tsx:20-20
Timestamp: 2025-07-23T11:11:01.974Z
Learning: In the Comify multi-tenant application, tenant IDs used in file paths (like CSS stylesheets in /assets/${tenant.id}.css) are protected by the repository architecture. Manipulating tenant IDs will either return no file or another legitimate tenant's stylesheet, but cannot be used for path traversal attacks since tenant IDs are controlled and validated at the domain level.
Learnt from: basmasking
PR: MaskingTechnology/comify#428
File: src/domain/post/aggregate/aggregate.ts:16-16
Timestamp: 2025-07-22T20:42:32.320Z
Learning: In the Comify application, only Creator, Post, and Notification domains have tenantId fields. Comics and Comments are not directly accessible from the frontend and are only retrieved as part of post aggregation. Tenant scoping is enforced at the aggregate root level (Posts) rather than requiring every related entity to have tenant fields. This architectural pattern maintains tenant isolation at the entry point boundaries.
Learnt from: basmasking
PR: MaskingTechnology/comify#428
File: src/domain/creator/types.ts:10-10
Timestamp: 2025-07-22T17:39:34.327Z
Learning: In multi-tenant creator domain operations, the update function is intentionally designed to be requester-scoped (self-update only) rather than tenant-scoped. Creators cannot switch tenants, and updates are performed by authenticated users on their own records only, eliminating the need for explicit tenant filtering in update operations.
Learnt from: basmasking
PR: MaskingTechnology/comify#428
File: src/domain/creator/types.ts:10-10
Timestamp: 2025-07-22T17:39:34.327Z
Learning: In the creator domain, the base update function is designed as a low-level utility that performs database operations without tenant scoping. Security and tenant isolation are enforced at higher-level domain functions (like updateFullName, updateNickname) which ensure requesters can only modify their own records. The tenantId field is readonly to prevent modifications, and this separation of concerns creates a cleaner, more secure architecture.
Learnt from: basmasking
PR: MaskingTechnology/comify#428
File: src/webui/components/common/TenantContainer.tsx:14-24
Timestamp: 2025-07-23T11:08:07.428Z
Learning: In the TenantContainer component, the tenant CSS link is only added once per application session since the tenant is static and bound to the URL. The tenant only changes with full page reloads, so there's no need for cleanup logic to prevent CSS link accumulation within a single session.
Learnt from: basmasking
PR: MaskingTechnology/comify#428
File: segments/bff.json:48-48
Timestamp: 2025-07-22T21:11:15.693Z
Learning: The tenant domain uses a two-tier data model: the database `DataModel` contains an `id` and an array of valid `origins`, while the public `Tenant` type returned by `getByOriginConverted` contains only `id` and `origin` (singular). This conversion serves as data minimization, where `id` is needed for stylesheet retrieval and `origin` is the validated browser-sent origin. This architecture implements proper security through data filtering at the public interface level.
Learnt from: basmasking
PR: MaskingTechnology/comify#428
File: src/webui/features/hooks/usePostsFollowing.ts:6-6
Timestamp: 2025-07-22T20:29:33.566Z
Learning: In Jitar applications, static imports of context objects like `tenant` from `^/domain/tenant` and `requester` from `^/domain/authentication` are intentionally static placeholders that serve as type-safe function signature matches. At runtime, these are dynamically replaced through Jitar's parameter injection mechanism via middleware (TenantMiddleware and AuthenticationMiddleware) using special parameter keys like `*tenant`. This allows for compile-time type safety while providing runtime flexibility for multi-tenant and authentication contexts.
Learnt from: basmasking
PR: MaskingTechnology/comify#428
File: src/webui/features/hooks/useExplorePosts.ts:14-18
Timestamp: 2025-07-23T08:26:06.202Z
Learning: In Jitar applications, the tenant context remains static throughout the application session lifecycle. It's determined by the URL/domain at application load time and only changes when the domain changes, which triggers a full application reload. Therefore, tenant dependencies in React hooks like useCallback don't need to be included in dependency arrays since they don't change during the component's lifecycle.
docker/mongodb/init.js (7)

Learnt from: basmasking
PR: #428
File: segments/bff.json:48-48
Timestamp: 2025-07-22T21:11:15.693Z
Learning: The tenant domain uses a two-tier data model: the database DataModel contains an id and an array of valid origins, while the public Tenant type returned by getByOriginConverted contains only id and origin (singular). This conversion serves as data minimization, where id is needed for stylesheet retrieval and origin is the validated browser-sent origin. This architecture implements proper security through data filtering at the public interface level.

Learnt from: basmasking
PR: #428
File: src/domain/post/aggregate/aggregate.ts:16-16
Timestamp: 2025-07-22T20:42:32.320Z
Learning: In the Comify application, only Creator, Post, and Notification domains have tenantId fields. Comics and Comments are not directly accessible from the frontend and are only retrieved as part of post aggregation. Tenant scoping is enforced at the aggregate root level (Posts) rather than requiring every related entity to have tenant fields. This architectural pattern maintains tenant isolation at the entry point boundaries.

Learnt from: basmasking
PR: #428
File: src/webui/components/common/TenantContainer.tsx:20-20
Timestamp: 2025-07-23T11:11:01.974Z
Learning: In the Comify multi-tenant application, tenant IDs used in file paths (like CSS stylesheets in /assets/${tenant.id}.css) are protected by the repository architecture. Manipulating tenant IDs will either return no file or another legitimate tenant's stylesheet, but cannot be used for path traversal attacks since tenant IDs are controlled and validated at the domain level.

Learnt from: basmasking
PR: #428
File: src/domain/tenant/getByOrigin/getByOrigin.ts:9-9
Timestamp: 2025-07-22T20:53:29.380Z
Learning: In the tenant domain, getByOrigin is an internal utility function that is not directly callable from external code. It can only be accessed through the public getByOriginConverted function, which performs proper input validation using a schema that requires the origin to be a valid URL. This follows an architectural pattern where validation occurs at the public interface level rather than being duplicated in internal utility functions.

Learnt from: basmasking
PR: #428
File: src/domain/creator/types.ts:10-10
Timestamp: 2025-07-22T17:39:34.327Z
Learning: In the creator domain, the base update function is designed as a low-level utility that performs database operations without tenant scoping. Security and tenant isolation are enforced at higher-level domain functions (like updateFullName, updateNickname) which ensure requesters can only modify their own records. The tenantId field is readonly to prevent modifications, and this separation of concerns creates a cleaner, more secure architecture.

Learnt from: basmasking
PR: #428
File: src/webui/features/hooks/useAddComicPost.ts:7-7
Timestamp: 2025-07-22T21:04:44.466Z
Learning: The Comify project uses index resolution extensively with index.ts files for each domain feature. These index files commonly re-export default exports from internal modules as named exports (e.g., export { default as tenant } from './tenant'), allowing for consistent named import syntax like import { tenant } from '^/domain/tenant' while maintaining modular organization.

Learnt from: basmasking
PR: #428
File: src/webui/features/hooks/useAddComicPost.ts:7-7
Timestamp: 2025-07-22T21:04:44.466Z
Learning: The Comify project uses index resolution extensively with index.ts files for each domain feature. These index files commonly re-export default exports from internal modules as named exports (e.g., export { default as tenant } from './tenant'), allowing for consistent named import syntax like import { tenant } from '^/domain/tenant' while maintaining modular organization.

test/domain/post/getRecommendedAggregated.spec.ts (3)

Learnt from: basmasking
PR: #428
File: src/webui/features/hooks/useAddComicPost.ts:7-7
Timestamp: 2025-07-22T21:04:44.466Z
Learning: The Comify project uses index resolution extensively with index.ts files for each domain feature. These index files commonly re-export default exports from internal modules as named exports (e.g., export { default as tenant } from './tenant'), allowing for consistent named import syntax like import { tenant } from '^/domain/tenant' while maintaining modular organization.

Learnt from: basmasking
PR: #428
File: src/webui/features/hooks/useAddComicPost.ts:7-7
Timestamp: 2025-07-22T21:04:44.466Z
Learning: The Comify project uses index resolution extensively with index.ts files for each domain feature. These index files commonly re-export default exports from internal modules as named exports (e.g., export { default as tenant } from './tenant'), allowing for consistent named import syntax like import { tenant } from '^/domain/tenant' while maintaining modular organization.

Learnt from: basmasking
PR: #428
File: src/domain/post/aggregate/aggregate.ts:16-16
Timestamp: 2025-07-22T20:42:32.320Z
Learning: In the Comify application, only Creator, Post, and Notification domains have tenantId fields. Comics and Comments are not directly accessible from the frontend and are only retrieved as part of post aggregation. Tenant scoping is enforced at the aggregate root level (Posts) rather than requiring every related entity to have tenant fields. This architectural pattern maintains tenant isolation at the entry point boundaries.

test/domain/post/getByFollowingAggregated.spec.ts (1)

Learnt from: basmasking
PR: #428
File: src/domain/post/aggregate/aggregate.ts:16-16
Timestamp: 2025-07-22T20:42:32.320Z
Learning: In the Comify application, only Creator, Post, and Notification domains have tenantId fields. Comics and Comments are not directly accessible from the frontend and are only retrieved as part of post aggregation. Tenant scoping is enforced at the aggregate root level (Posts) rather than requiring every related entity to have tenant fields. This architectural pattern maintains tenant isolation at the entry point boundaries.

test/domain/post/createWithComic.spec.ts (5)

Learnt from: basmasking
PR: #428
File: src/domain/post/aggregate/aggregate.ts:16-16
Timestamp: 2025-07-22T20:42:32.320Z
Learning: In the Comify application, only Creator, Post, and Notification domains have tenantId fields. Comics and Comments are not directly accessible from the frontend and are only retrieved as part of post aggregation. Tenant scoping is enforced at the aggregate root level (Posts) rather than requiring every related entity to have tenant fields. This architectural pattern maintains tenant isolation at the entry point boundaries.

Learnt from: basmasking
PR: #428
File: src/webui/features/hooks/useAddComicPost.ts:7-7
Timestamp: 2025-07-22T21:04:44.466Z
Learning: The Comify project uses index resolution extensively with index.ts files for each domain feature. These index files commonly re-export default exports from internal modules as named exports (e.g., export { default as tenant } from './tenant'), allowing for consistent named import syntax like import { tenant } from '^/domain/tenant' while maintaining modular organization.

Learnt from: basmasking
PR: #428
File: src/webui/features/hooks/useAddComicPost.ts:7-7
Timestamp: 2025-07-22T21:04:44.466Z
Learning: The Comify project uses index resolution extensively with index.ts files for each domain feature. These index files commonly re-export default exports from internal modules as named exports (e.g., export { default as tenant } from './tenant'), allowing for consistent named import syntax like import { tenant } from '^/domain/tenant' while maintaining modular organization.

Learnt from: basmasking
PR: #428
File: segments/bff.json:48-48
Timestamp: 2025-07-22T21:11:15.693Z
Learning: The tenant domain uses a two-tier data model: the database DataModel contains an id and an array of valid origins, while the public Tenant type returned by getByOriginConverted contains only id and origin (singular). This conversion serves as data minimization, where id is needed for stylesheet retrieval and origin is the validated browser-sent origin. This architecture implements proper security through data filtering at the public interface level.

Learnt from: basmasking
PR: #428
File: src/webui/features/hooks/usePostsFollowing.ts:6-6
Timestamp: 2025-07-22T20:29:33.566Z
Learning: In Jitar applications, static imports of context objects like tenant from ^/domain/tenant and requester from ^/domain/authentication are intentionally static placeholders that serve as type-safe function signature matches. At runtime, these are dynamically replaced through Jitar's parameter injection mechanism via middleware (TenantMiddleware and AuthenticationMiddleware) using special parameter keys like *tenant. This allows for compile-time type safety while providing runtime flexibility for multi-tenant and authentication contexts.

test/domain/authentication/login.spec.ts (4)

Learnt from: basmasking
PR: #428
File: src/webui/features/hooks/useAddComicPost.ts:7-7
Timestamp: 2025-07-22T21:04:44.466Z
Learning: The Comify project uses index resolution extensively with index.ts files for each domain feature. These index files commonly re-export default exports from internal modules as named exports (e.g., export { default as tenant } from './tenant'), allowing for consistent named import syntax like import { tenant } from '^/domain/tenant' while maintaining modular organization.

Learnt from: basmasking
PR: #428
File: src/webui/features/hooks/useAddComicPost.ts:7-7
Timestamp: 2025-07-22T21:04:44.466Z
Learning: The Comify project uses index resolution extensively with index.ts files for each domain feature. These index files commonly re-export default exports from internal modules as named exports (e.g., export { default as tenant } from './tenant'), allowing for consistent named import syntax like import { tenant } from '^/domain/tenant' while maintaining modular organization.

Learnt from: basmasking
PR: #428
File: src/webui/features/hooks/usePostsFollowing.ts:6-6
Timestamp: 2025-07-22T20:29:33.566Z
Learning: In Jitar applications, static imports of context objects like tenant from ^/domain/tenant and requester from ^/domain/authentication are intentionally static placeholders that serve as type-safe function signature matches. At runtime, these are dynamically replaced through Jitar's parameter injection mechanism via middleware (TenantMiddleware and AuthenticationMiddleware) using special parameter keys like *tenant. This allows for compile-time type safety while providing runtime flexibility for multi-tenant and authentication contexts.

Learnt from: basmasking
PR: #428
File: segments/bff.json:48-48
Timestamp: 2025-07-22T21:11:15.693Z
Learning: The tenant domain uses a two-tier data model: the database DataModel contains an id and an array of valid origins, while the public Tenant type returned by getByOriginConverted contains only id and origin (singular). This conversion serves as data minimization, where id is needed for stylesheet retrieval and origin is the validated browser-sent origin. This architecture implements proper security through data filtering at the public interface level.

test/domain/relation/exploreAggregated.spec.ts (2)

Learnt from: basmasking
PR: #428
File: src/webui/features/hooks/useAddComicPost.ts:7-7
Timestamp: 2025-07-22T21:04:44.466Z
Learning: The Comify project uses index resolution extensively with index.ts files for each domain feature. These index files commonly re-export default exports from internal modules as named exports (e.g., export { default as tenant } from './tenant'), allowing for consistent named import syntax like import { tenant } from '^/domain/tenant' while maintaining modular organization.

Learnt from: basmasking
PR: #428
File: src/webui/features/hooks/useAddComicPost.ts:7-7
Timestamp: 2025-07-22T21:04:44.466Z
Learning: The Comify project uses index resolution extensively with index.ts files for each domain feature. These index files commonly re-export default exports from internal modules as named exports (e.g., export { default as tenant } from './tenant'), allowing for consistent named import syntax like import { tenant } from '^/domain/tenant' while maintaining modular organization.

🧬 Code Graph Analysis (8)
test/domain/post/getRecommendedAggregated.spec.ts (2)
src/domain/post/getRecommendedAggregated/getRecommendedAggregated.ts (1)
  • getRecommendedAggregated (12-21)
test/domain/post/fixtures/tenants.fixture.ts (1)
  • TENANTS (4-4)
test/domain/notification/getRecentAggregated.spec.ts (2)
src/domain/notification/getRecentAggregated/getRecentAggregated.ts (1)
  • getRecentAggregated (12-21)
test/domain/notification/fixtures/tenants.fixture.ts (1)
  • TENANTS (4-4)
test/domain/post/getByFollowingAggregated.spec.ts (3)
src/domain/post/getByFollowingAggregated/getByFollowingAggregated.ts (1)
  • getByFollowingAggregated (12-21)
test/domain/post/fixtures/tenants.fixture.ts (1)
  • TENANTS (4-4)
test/domain/post/fixtures/requesters.fixture.ts (1)
  • REQUESTERS (7-14)
test/domain/relation/getFollowersAggregated.spec.ts (2)
test/domain/relation/fixtures/tenants.fixture.ts (1)
  • TENANTS (4-4)
test/domain/relation/fixtures/values.fixture.ts (1)
  • VALUES (2-23)
test/domain/post/createWithComic.spec.ts (2)
src/domain/post/createWithComic/createWithComic.ts (1)
  • createWithComic (8-13)
test/domain/post/fixtures/tenants.fixture.ts (1)
  • TENANTS (4-4)
test/domain/authentication/login.spec.ts (5)
src/domain/authentication/login/login.ts (1)
  • login (10-27)
test/domain/authentication/fixtures/tenants.fixture.ts (1)
  • TENANTS (4-4)
test/domain/authentication/fixtures/identities.fixture.ts (1)
  • IDENTITIES (6-64)
test/domain/authentication/fixtures/values.fixture.ts (1)
  • VALUES (2-81)
src/domain/creator/generateNickname/TooManySimilarNicknames.ts (1)
  • TooManySimilarNicknames (4-10)
test/domain/relation/exploreAggregated.spec.ts (5)
src/domain/relation/explore/explore.ts (1)
  • explore (10-22)
test/domain/relation/fixtures/tenants.fixture.ts (1)
  • TENANTS (4-4)
src/domain/definitions.ts (1)
  • SortOrders (6-9)
src/domain/relation/definitions.ts (1)
  • SortOrders (8-8)
test/domain/relation/fixtures/values.fixture.ts (1)
  • VALUES (2-23)
test/domain/relation/getFollowingAggregated.spec.ts (2)
test/domain/relation/fixtures/tenants.fixture.ts (1)
  • TENANTS (4-4)
test/domain/relation/fixtures/values.fixture.ts (1)
  • VALUES (2-23)
🔇 Additional comments (19)
docker/mongodb/init.js (2)

2-2: LGTM! Correct database switching syntax.

The use of getSiblingDB('comify') properly switches to the application database for initialization.


3-9: LGTM! Well-structured tenant initialization for local development.

The tenant document correctly follows the established two-tier data model with _id and origins array. Including both ports 3000 and 5173 effectively supports different local development scenarios (Node.js server and Vite dev server).

test/domain/notification/getRecentAggregated.spec.ts (3)

6-6: LGTM! Import updated correctly for tenant support.

The addition of TENANTS to the imports is consistent with the multi-tenancy implementation and aligns with the function signature changes.


20-20: LGTM! Function call updated correctly for tenant-first signature.

The parameter order correctly reflects the updated function signature with tenant as the first parameter.


39-39: LGTM! Consistent parameter ordering maintained.

The second function call correctly follows the same tenant-first parameter pattern, maintaining consistency across the test cases.

test/domain/post/getByFollowingAggregated.spec.ts (2)

4-4: Import update correctly adds TENANTS fixture.

The addition of TENANTS to the import statement properly supports the tenant-aware function signature.


18-18: Function call correctly updated for tenant-aware signature.

The getByFollowingAggregated call now properly passes TENANTS.default as the first parameter, matching the new function signature that requires a tenant context.

test/domain/post/getRecommendedAggregated.spec.ts (2)

5-5: Import statement properly updated for tenant support.

The addition of TENANTS to the fixtures import correctly provides the tenant context needed for the updated function signature.


19-19: Function call correctly updated with tenant parameter.

The getRecommendedAggregated call now properly includes TENANTS.default as the first argument, aligning with the tenant-aware function signature.

test/domain/post/createWithComic.spec.ts (2)

9-9: Import correctly extended to include tenant fixtures.

The addition of TENANTS to the import statement properly supports the tenant-aware createWithComic function.


23-23: Function call updated correctly for tenant context.

The createWithComic call now properly passes TENANTS.default as the first parameter, matching the updated function signature that requires tenant context.

test/domain/authentication/login.spec.ts (2)

7-7: Import statement correctly updated with TENANTS fixture.

The addition of TENANTS to the import supports the tenant-aware login function signature.


25-68: All login function calls correctly updated with tenant parameter.

All test cases properly pass TENANTS.default as the first argument to the login function, correctly implementing the tenant-aware function signature.

test/domain/relation/getFollowersAggregated.spec.ts (2)

6-6: Import statement properly updated to include TENANTS.

The addition of TENANTS to the fixtures import correctly provides tenant context for the function call.


17-17: Function call correctly updated with tenant parameter.

The getFollowers call now properly includes TENANTS.default as the first argument, implementing the tenant-aware function signature.

test/domain/relation/getFollowingAggregated.spec.ts (2)

6-6: LGTM: Tenant fixture import added correctly.

The addition of TENANTS to the import statement is consistent with the multi-tenancy refactor and provides the necessary tenant context for the updated test.


17-17: LGTM: Function call updated correctly for tenant-aware architecture.

The addition of TENANTS.default as the first parameter correctly implements the updated function signature that requires tenant context for proper data scoping. The parameter order follows the expected pattern of tenant, requester, and other arguments.

test/domain/relation/exploreAggregated.spec.ts (2)

7-7: LGTM: Tenant fixture import added correctly.

The addition of TENANTS to the import statement properly provides the tenant context fixture needed for the updated test cases.


18-18: LGTM: All function calls updated consistently for tenant-aware architecture.

All test cases correctly add TENANTS.default as the first parameter to the explore function calls, properly implementing the updated function signature that requires tenant context. The parameter positioning is consistent and preserves the original test logic across all test scenarios.

Also applies to: 27-27, 33-33, 40-40, 47-47

Copy link

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
src/integrations/runtime/middlewares/OriginMiddleware.ts (2)

23-49: LGTM! Solid middleware logic with proper validation flow.

The middleware correctly implements the origin extraction and validation flow. The non-null assertion on line 39 is safe since validateOriginValue would throw if origin is undefined.

Consider adding a comment to clarify the non-null assertion:

        this.#validateOriginValue(origin);

+        // Origin is guaranteed to be defined after validation
        request.setHeader('origin', origin!);

56-74: Consider using more robust cookie parsing.

The manual cookie parsing works for basic cases but could be improved for edge cases where cookie values contain special characters.

Consider using a more robust approach:

    #getOriginFromCookie(request: Request): string | undefined
    {
        const header = request.getHeader('cookie');

        if (header === undefined)
        {
            return;
        }

-        for (const cookie of header.split(';'))
-        {
-            const [key, value] = cookie.split('=');
-
-            if (key.trim() === ORIGIN_COOKIE_NAME) 
-            {
-                return value?.trim();
-            }
-        }
+        for (const cookie of header.split(';'))
+        {
+            const equalIndex = cookie.indexOf('=');
+            if (equalIndex === -1) continue;
+            
+            const key = cookie.substring(0, equalIndex).trim();
+            const value = cookie.substring(equalIndex + 1).trim();
+
+            if (key === ORIGIN_COOKIE_NAME) 
+            {
+                return value;
+            }
+        }
    }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2832763 and 3797ad5.

📒 Files selected for processing (9)
  • docker-compose.yml (1 hunks)
  • example.env (2 hunks)
  • segments/bff.json (3 hunks)
  • segments/notification.json (0 hunks)
  • src/domain/notification/getById/getById.ts (0 hunks)
  • src/domain/notification/getById/index.ts (0 hunks)
  • src/domain/notification/getByIdAggregated/getByIdAggregated.ts (0 hunks)
  • src/domain/notification/getByIdAggregated/index.ts (0 hunks)
  • src/integrations/runtime/middlewares/OriginMiddleware.ts (1 hunks)
💤 Files with no reviewable changes (5)
  • segments/notification.json
  • src/domain/notification/getById/index.ts
  • src/domain/notification/getByIdAggregated/index.ts
  • src/domain/notification/getById/getById.ts
  • src/domain/notification/getByIdAggregated/getByIdAggregated.ts
✅ Files skipped from review due to trivial changes (1)
  • docker-compose.yml
🚧 Files skipped from review as they are similar to previous changes (2)
  • example.env
  • segments/bff.json
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: basmasking
PR: MaskingTechnology/comify#428
File: src/webui/components/common/TenantContainer.tsx:20-20
Timestamp: 2025-07-23T11:11:01.974Z
Learning: In the Comify multi-tenant application, tenant IDs used in file paths (like CSS stylesheets in /assets/${tenant.id}.css) are protected by the repository architecture. Manipulating tenant IDs will either return no file or another legitimate tenant's stylesheet, but cannot be used for path traversal attacks since tenant IDs are controlled and validated at the domain level.
Learnt from: basmasking
PR: MaskingTechnology/comify#428
File: src/domain/post/aggregate/aggregate.ts:16-16
Timestamp: 2025-07-22T20:42:32.320Z
Learning: In the Comify application, only Creator, Post, and Notification domains have tenantId fields. Comics and Comments are not directly accessible from the frontend and are only retrieved as part of post aggregation. Tenant scoping is enforced at the aggregate root level (Posts) rather than requiring every related entity to have tenant fields. This architectural pattern maintains tenant isolation at the entry point boundaries.
Learnt from: basmasking
PR: MaskingTechnology/comify#428
File: src/domain/creator/types.ts:10-10
Timestamp: 2025-07-22T17:39:34.327Z
Learning: In multi-tenant creator domain operations, the update function is intentionally designed to be requester-scoped (self-update only) rather than tenant-scoped. Creators cannot switch tenants, and updates are performed by authenticated users on their own records only, eliminating the need for explicit tenant filtering in update operations.
Learnt from: basmasking
PR: MaskingTechnology/comify#428
File: src/domain/creator/types.ts:10-10
Timestamp: 2025-07-22T17:39:34.327Z
Learning: In the creator domain, the base update function is designed as a low-level utility that performs database operations without tenant scoping. Security and tenant isolation are enforced at higher-level domain functions (like updateFullName, updateNickname) which ensure requesters can only modify their own records. The tenantId field is readonly to prevent modifications, and this separation of concerns creates a cleaner, more secure architecture.
Learnt from: basmasking
PR: MaskingTechnology/comify#428
File: src/webui/components/common/TenantContainer.tsx:14-24
Timestamp: 2025-07-23T11:08:07.428Z
Learning: In the TenantContainer component, the tenant CSS link is only added once per application session since the tenant is static and bound to the URL. The tenant only changes with full page reloads, so there's no need for cleanup logic to prevent CSS link accumulation within a single session.
Learnt from: basmasking
PR: MaskingTechnology/comify#428
File: segments/bff.json:48-48
Timestamp: 2025-07-22T21:11:15.693Z
Learning: The tenant domain uses a two-tier data model: the database `DataModel` contains an `id` and an array of valid `origins`, while the public `Tenant` type returned by `getByOriginConverted` contains only `id` and `origin` (singular). This conversion serves as data minimization, where `id` is needed for stylesheet retrieval and `origin` is the validated browser-sent origin. This architecture implements proper security through data filtering at the public interface level.
Learnt from: basmasking
PR: MaskingTechnology/comify#428
File: src/webui/features/hooks/usePostsFollowing.ts:6-6
Timestamp: 2025-07-22T20:29:33.566Z
Learning: In Jitar applications, static imports of context objects like `tenant` from `^/domain/tenant` and `requester` from `^/domain/authentication` are intentionally static placeholders that serve as type-safe function signature matches. At runtime, these are dynamically replaced through Jitar's parameter injection mechanism via middleware (TenantMiddleware and AuthenticationMiddleware) using special parameter keys like `*tenant`. This allows for compile-time type safety while providing runtime flexibility for multi-tenant and authentication contexts.
Learnt from: basmasking
PR: MaskingTechnology/comify#428
File: src/webui/features/hooks/useExplorePosts.ts:14-18
Timestamp: 2025-07-23T08:26:06.202Z
Learning: In Jitar applications, the tenant context remains static throughout the application session lifecycle. It's determined by the URL/domain at application load time and only changes when the domain changes, which triggers a full application reload. Therefore, tenant dependencies in React hooks like useCallback don't need to be included in dependency arrays since they don't change during the component's lifecycle.
src/integrations/runtime/middlewares/OriginMiddleware.ts (3)

Learnt from: basmasking
PR: #428
File: src/domain/tenant/getByOrigin/getByOrigin.ts:9-9
Timestamp: 2025-07-22T20:53:29.380Z
Learning: In the tenant domain, getByOrigin is an internal utility function that is not directly callable from external code. It can only be accessed through the public getByOriginConverted function, which performs proper input validation using a schema that requires the origin to be a valid URL. This follows an architectural pattern where validation occurs at the public interface level rather than being duplicated in internal utility functions.

Learnt from: basmasking
PR: #428
File: segments/bff.json:48-48
Timestamp: 2025-07-22T21:11:15.693Z
Learning: The tenant domain uses a two-tier data model: the database DataModel contains an id and an array of valid origins, while the public Tenant type returned by getByOriginConverted contains only id and origin (singular). This conversion serves as data minimization, where id is needed for stylesheet retrieval and origin is the validated browser-sent origin. This architecture implements proper security through data filtering at the public interface level.

Learnt from: basmasking
PR: #428
File: src/domain/post/create/types.ts:6-6
Timestamp: 2025-07-22T20:50:22.314Z
Learning: The Comify application uses a custom validation architecture where domain validation logic is decoupled from external validation libraries through an integrations layer. The current implementation uses Zod (src/integrations/validation/implementations/zod/Zod.ts) but can be easily switched to other validation libraries. Domain validation requirements remain consistent regardless of the underlying validation library, with validation schemas defined using custom validation functions like requiredIdValidation.

🔇 Additional comments (2)
src/integrations/runtime/middlewares/OriginMiddleware.ts (2)

1-19: LGTM! Well-structured imports and validation schema.

The imports are appropriate, the cookie name follows conventions, and the validation schema correctly enforces URL validation for the origin parameter.


86-89: Verify cookie security settings work in all environments.

The cookie security settings are appropriate for production but may cause issues in development environments without HTTPS due to the SameSite=None; Secure combination.

Consider adding environment-specific cookie settings or ensure development uses HTTPS. You may want to verify this works correctly in your development setup.

@petermasking petermasking merged commit 7007f94 into main Jul 26, 2025
7 checks passed
@petermasking petermasking deleted the 375-multitenancy-support branch July 26, 2025 22:01
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.

Multitenancy support
2 participants