Skip to content

Conversation

@Askir
Copy link
Member

@Askir Askir commented Dec 21, 2025

Summary

Implements automatic role synchronization between identity providers (SAML, OIDC, LDAP) and Kviklet roles based on IdP group memberships.

  • Three sync modes:
    • FULL_SYNC - Roles exactly match IdP group mappings (removes unmapped roles)
    • ADDITIVE - IdP groups add roles without removing existing ones
    • FIRST_LOGIN_ONLY - Roles only set on first login, not updated on subsequent logins
  • All IdP types supported: OIDC, SAML, and LDAP
  • Admin UI: Settings page for configuring group-to-role mappings
  • Documentation: Keycloak setup guide included

Architecture

All IdP services (OidcUserService, SamlUserService, LdapUserDetailsService) extract groups from their respective attributes and pass them to UserAuthService.findOrCreateUser(), which delegates to RoleSyncService for role resolution.

Key Files

Backend:

  • RoleSyncService.kt - Core sync logic
  • RoleSyncConfigService.kt + RoleSyncConfigController.kt - Config CRUD
  • RoleSyncConfig.kt (db/) - Entities and repository
  • UserAuthService.kt - Integration point for all IdPs

Frontend:

  • RoleSyncSettings.tsx - Settings UI
  • RoleSyncConfigApi.ts - API client
  • roleSyncConfig.ts - Hook

Important

Adds role synchronization feature for IdP group-to-role mapping with backend logic, database changes, and frontend UI for configuration.

  • Behavior:
    • Adds automatic role synchronization between IdPs (SAML, OIDC, LDAP) and Kviklet roles based on group memberships.
    • Supports FULL_SYNC, ADDITIVE, and FIRST_LOGIN_ONLY sync modes.
    • Role sync is disabled without a valid license.
  • Backend:
    • Implements RoleSyncService for role resolution and RoleSyncConfigService for configuration management.
    • Adds RoleSyncConfigController for API endpoints.
    • Updates UserAuthService, LdapUserDetailsService, OidcUserService, and SamlUserService to integrate role sync.
    • Database changes in 036-add-role-sync-config.yaml to add role_sync_config and role_sync_mapping tables.
  • Frontend:
    • Adds RoleSyncSettings.tsx for UI configuration.
    • Implements API client in RoleSyncConfigApi.ts and hook in roleSyncConfig.ts.
    • Updates Settings.tsx to include Role Sync settings.

This description was created by Ellipsis for 16a8200. You can customize this summary. It will automatically update as commits are pushed.

Allows automatic synchronization of user roles based on IdP group memberships.
Supports OIDC, SAML, and LDAP with three sync modes: FULL_SYNC, ADDITIVE, and
FIRST_LOGIN_ONLY. Includes admin UI for configuring mappings and Keycloak
setup documentation.
@Askir Askir force-pushed the feature/role-sync branch from b632774 to c42edf7 Compare December 21, 2025 11:14
Copy link
Contributor

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

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

Caution

Changes requested ❌

Reviewed everything up to b632774 in 1 minute and 37 seconds. Click for details.
  • Reviewed 1531 lines of code in 17 files
  • Skipped 0 files when reviewing.
  • Skipped posting 6 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. backend/src/main/kotlin/dev/kviklet/kviklet/controller/RoleSyncConfigController.kt:70
  • Draft comment:
    Controller code is clear and uses appropriate annotations. Consider adding logging for update and delete operations for easier debugging.
  • Reason this comment was not posted:
    Confidence changes required: 50% <= threshold 50% None
2. backend/src/main/kotlin/dev/kviklet/kviklet/db/RoleSyncConfig.kt:60
  • Draft comment:
    Ensure that the unique constraint on 'idp_group_name' aligns with business logic. Duplicate mappings will fail.
  • Reason this comment was not posted:
    Comment looked like it was already resolved.
3. backend/src/main/kotlin/dev/kviklet/kviklet/security/saml/SamlLoginSuccessHandler.kt:72
  • Draft comment:
    Hard-coded port ':5173' in getBaseUrl may not be appropriate in production. Consider making it configurable.
  • Reason this comment was not posted:
    Comment was not on a location in the diff, so it can't be submitted as a review comment.
4. frontend/src/hooks/roleSyncConfig.ts:20
  • Draft comment:
    Consider error handling improvements (e.g., try-catch) or leveraging a data-fetching library to simplify state management.
  • Reason this comment was not posted:
    Confidence changes required: 50% <= threshold 50% None
5. frontend/src/routes/settings/RoleSyncSettings.tsx:140
  • Draft comment:
    In the groups attribute input, updateConfig is called onChange and onBlur. Confirm if immediate updates on every keystroke are desired.
  • Reason this comment was not posted:
    Comment did not seem useful. Confidence is useful = 0% <= threshold 50% The comment is asking the PR author to confirm their intention regarding the use of updateConfig on onChange and onBlur. This violates the rule against asking the author to confirm their intention or ensure behavior is intended.
6. frontend/src/routes/settings/Settings.tsx:130
  • Draft comment:
    Sidebar tabs correctly disable enterprise features when license is invalid. Verify that route paths used (e.g., '/roles/new') are consistent with app routing.
  • Reason this comment was not posted:
    Confidence changes required: 30% <= threshold 50% None

Workflow ID: wflow_HU3VBVnOaMEjdTKl

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

.mapNotNull { mapping ->
try {
roleAdapter.findById(RoleId(mapping.roleId))
} catch (e: EntityNotFound) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Silently ignoring missing roles in the catch block may hide configuration issues. Consider logging a warning with exception details.

Copy link
Contributor

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

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

Important

Looks good to me! 👍

Reviewed c42edf7 in 37 seconds. Click for details.
  • Reviewed 1513 lines of code in 17 files
  • Skipped 0 files when reviewing.
  • Skipped posting 2 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. backend/src/main/kotlin/dev/kviklet/kviklet/db/RoleSyncConfig.kt:63
  • Draft comment:
    Verify the unique constraint on idp_group_name. It prevents mapping the same IdP group to multiple roles.
  • Reason this comment was not posted:
    Comment did not seem useful. Confidence is useful = 0% <= threshold 50% The comment is asking the author to verify a unique constraint, which is similar to asking them to double-check something. This violates the rule against asking the author to confirm or verify intentions. The comment does not provide a specific suggestion or point out a clear issue with the code.
2. backend/src/main/kotlin/dev/kviklet/kviklet/security/saml/SamlLoginSuccessHandler.kt:72
  • Draft comment:
    Hardcoded port ':5173' in getBaseUrl may not reflect actual serverPort. Consider using the dynamic serverPort value.
  • Reason this comment was not posted:
    Comment was not on a location in the diff, so it can't be submitted as a review comment.

Workflow ID: wflow_jPClt2peDPVAndoz

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

Copy link
Contributor

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

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

Important

Looks good to me! 👍

Reviewed d37f2ca in 31 seconds. Click for details.
  • Reviewed 13 lines of code in 1 files
  • Skipped 0 files when reviewing.
  • Skipped posting 1 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. frontend/src/routes/settings/RoleSyncSettings.tsx:106
  • Draft comment:
    Good use of an arrow function to wrap the async handler. Consider handling errors within handleToggleEnabled (e.g., try/catch) so that any update failures are logged or communicated to the user.
  • Reason this comment was not posted:
    Confidence changes required: 33% <= threshold 50% None

Workflow ID: wflow_wpdnyjvQSXuvdl8B

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

Copy link
Contributor

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

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

Caution

Changes requested ❌

Reviewed dc0c978 in 2 minutes and 7 seconds. Click for details.
  • Reviewed 1084 lines of code in 4 files
  • Skipped 0 files when reviewing.
  • Skipped posting 5 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. backend/src/main/kotlin/dev/kviklet/kviklet/db/RoleSyncConfig.kt:159
  • Draft comment:
    Ensure bulk delete (deleteAllMappings) is wrapped in a transactional context if atomicity is required in production.
  • Reason this comment was not posted:
    Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 10% vs. threshold = 50% This comment starts with "Ensure" which is a red flag according to the rules - "Do NOT ask the PR author to confirm their intention, to explain, to double-check things, to ensure the behavior is intended". The comment is also conditional ("if atomicity is required"), making it speculative. Spring Data JPA repository methods like deleteAll() are already transactional by default. The existing deleteMapping() method doesn't have an explicit @Transactional annotation either, suggesting the codebase relies on the default transactional behavior. The comment doesn't provide strong evidence that there's actually a problem - it's just asking the author to "ensure" something "if" it's needed. Could there be a legitimate concern about transactional behavior in this specific context that I'm missing? Perhaps there are complex cascading operations or specific requirements in this codebase that make explicit transactions necessary? Even if there were specific transactional requirements, the comment is phrased as a conditional request ("if atomicity is required") rather than identifying a definite issue. If the automated tool had evidence that atomicity was definitely required and missing, it should have stated that clearly. The comment violates the "Ensure that..." rule and is speculative. This comment should be deleted. It starts with "Ensure" and is conditional ("if atomicity is required"), making it speculative rather than identifying a definite issue. It's asking the author to double-check something rather than pointing out a clear problem.
2. backend/src/test/kotlin/dev/kviklet/kviklet/OIDCRoleSyncTest.kt:427
  • Draft comment:
    Avoid relying on substring checks of exception messages; catch the specific HttpHostConnectException instead for better robustness.
  • Reason this comment was not posted:
    Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 30% vs. threshold = 50% This is a new file being added (the diff shows it's a new file with all lines starting with +). The comment is about code quality - suggesting to catch HttpHostConnectException specifically instead of catching RuntimeException and checking the message string. This is generally good advice as string matching on exception messages is brittle and can break if the message format changes. However, I need to consider: 1) Is this actionable? Yes, the author could catch the specific exception type. 2) Is this clearly correct? The issue is that HttpHostConnectException might be wrapped in other exceptions, so catching it directly might not work. The current approach catches RuntimeException which might wrap the HttpHostConnectException. 3) Is this about a change? Yes, it's new code. 4) Does it require more context? Possibly - I'd need to know the exception hierarchy to be certain this would work. The comment assumes that HttpHostConnectException can be caught directly, but it might be wrapped in other exceptions (like RuntimeException or other wrapper exceptions from the HtmlUnit library). Without seeing the actual exception hierarchy or testing this, we can't be certain that catching HttpHostConnectException directly would work. The current approach might be intentionally defensive. While the suggestion is theoretically better practice, the current implementation might be necessary if HttpHostConnectException is wrapped in other exceptions. The comment doesn't provide strong evidence that the suggested approach would actually work in this context. This is speculative advice without proof that it would improve the code. This comment suggests a code quality improvement but lacks strong evidence that the suggested approach would work. The current implementation might be intentionally handling wrapped exceptions. Without proof that catching HttpHostConnectException directly would work, this is speculative advice.
3. backend/src/test/kotlin/dev/kviklet/kviklet/OIDCRoleSyncTest.kt:87
  • Draft comment:
    Consider extracting the Keycloak setup logic into shared utilities to reduce duplication in test setup.
  • Reason this comment was not posted:
    Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 10% vs. threshold = 50% This is a new file being added, so there's no duplication within this diff. The comment talks about "reducing duplication in test setup" but I can only see this one test file. Without seeing other test files that might have similar Keycloak setup code, I cannot verify if duplication actually exists. The comment is speculative - it assumes there might be other tests that could benefit from shared utilities, but there's no evidence of that in this diff. According to the rules, I should not keep speculative comments and should only keep comments with strong evidence. This appears to be a general code quality suggestion without concrete evidence of duplication. Perhaps there are other test files in the codebase (not shown in this diff) that also set up Keycloak, which would make this a valid suggestion. The comment might be based on knowledge of the broader codebase that I don't have access to. Even if there are other files with similar setup, the rules explicitly state to "ignore cross-file issues" and "only think about the file you are reviewing." Without evidence of duplication within this specific file or diff, and given that this is a brand new file, I cannot verify the claim of duplication. This is a speculative refactoring suggestion without concrete evidence in the changes shown. This comment should be deleted. It's a speculative refactoring suggestion about potential duplication across multiple files, but the diff only shows a new file being added with no evidence of duplication. The rules state to ignore cross-file issues and only keep comments with strong evidence.
4. backend/src/test/kotlin/dev/kviklet/kviklet/SAMLTest.kt:660
  • Draft comment:
    Extract the duplicate SAML login flow logic into a common helper to improve maintainability.
  • Reason this comment was not posted:
    Comment looked like it was already resolved.
5. backend/src/test/kotlin/dev/kviklet/kviklet/SAMLTest.kt:460
  • Draft comment:
    Avoid hard-coding the frontend URL (e.g. 'localhost:5173') in assertions; externalize this configuration to improve test flexibility.
  • Reason this comment was not posted:
    Comment was not on a location in the diff, so it can't be submitted as a review comment.

Workflow ID: wflow_L5AI5EEIYxja6CNN

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

olcModuleLoad: memberof
""".trimIndent()

val tempFile = Files.createTempFile("memberof-module", ".ldif")
Copy link
Contributor

Choose a reason for hiding this comment

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

Refactor repeated LDIF file operations (temp file creation, copying, deletion) into a shared test utility to reduce duplication.

try {
submitBtn.click<HtmlPage>()
} catch (e: RuntimeException) {
if (!e.message.orEmpty().contains("HttpHostConnectException: Connect to localhost:5173")) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Avoid using string matching on exception messages (e.g. for HttpHostConnectException); instead, catch the specific exception type.

Copy link
Contributor

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

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

Important

Looks good to me! 👍

Reviewed db6d5c7 in 35 seconds. Click for details.
  • Reviewed 68 lines of code in 1 files
  • Skipped 0 files when reviewing.
  • Skipped posting 4 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. backend/src/test/kotlin/dev/kviklet/kviklet/LDAPRoleSyncTest.kt:131
  • Draft comment:
    Formatting change: splitting out each parameter for execInContainer improves readability without altering functionality.
  • Reason this comment was not posted:
    Confidence changes required: 0% <= threshold 50% None
2. backend/src/test/kotlin/dev/kviklet/kviklet/LDAPRoleSyncTest.kt:161
  • Draft comment:
    Consistent reformatting for the ldapmodify command call aids in clarity; no functional change.
  • Reason this comment was not posted:
    Confidence changes required: 0% <= threshold 50% None
3. backend/src/test/kotlin/dev/kviklet/kviklet/LDAPRoleSyncTest.kt:192
  • Draft comment:
    Reformatted parameter list for the ldapadd command (memberof-overlay) to enhance readability.
  • Reason this comment was not posted:
    Confidence changes required: 0% <= threshold 50% None
4. backend/src/test/kotlin/dev/kviklet/kviklet/LDAPRoleSyncTest.kt:222
  • Draft comment:
    Consistent formatting applied to the ldapmodify command for the modify-group ldif improves code clarity.
  • Reason this comment was not posted:
    Confidence changes required: 0% <= threshold 50% None

Workflow ID: wflow_DgjnFHVr590wvvoK

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

Changed roleAdapter.delete(it.getId()!!) to
roleAdapter.delete(RoleId(it.getId()!!)) since delete()
expects a RoleId, not a String. Also added the RoleId import.
Copy link
Contributor

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

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

Important

Looks good to me! 👍

Reviewed 9b19794 in 1 minute and 2 seconds. Click for details.
  • Reviewed 63 lines of code in 3 files
  • Skipped 0 files when reviewing.
  • Skipped posting 3 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. backend/src/test/kotlin/dev/kviklet/kviklet/LDAPRoleSyncTest.kt:300
  • Draft comment:
    Wrap role ID in RoleId for type safety is a good improvement. Note that use of '!!' may be risky – acceptable in tests but consider safer null handling in production.
  • Reason this comment was not posted:
    Comment was on unchanged code.
2. backend/src/test/kotlin/dev/kviklet/kviklet/OIDCRoleSyncTest.kt:314
  • Draft comment:
    Using RoleId wrapper improves consistency and type safety. Consider reviewing the use of '!!' for potential null issues, even in test code.
  • Reason this comment was not posted:
    Comment was on unchanged code.
3. backend/src/test/kotlin/dev/kviklet/kviklet/SAMLTest.kt:392
  • Draft comment:
    Refactoring to delete roles using RoleId enhances type safety. Ensure that using '!!' is acceptable here or consider safer null handling.
  • Reason this comment was not posted:
    Comment was on unchanged code.

Workflow ID: wflow_fvxx85WEDsIja6KH

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

Copy link
Contributor

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

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

Important

Looks good to me! 👍

Reviewed 3d9756b in 25 seconds. Click for details.
  • Reviewed 10 lines of code in 1 files
  • Skipped 0 files when reviewing.
  • Skipped posting 1 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. .github/workflows/backend.yml:52
  • Draft comment:
    Updated ktlint_version from 1.3.0 to 1.8.0. Please ensure that this version change is compatible with your lint rules.
  • Reason this comment was not posted:
    Comment did not seem useful. Confidence is useful = 0% <= threshold 50% The comment is about a version change of a dependency, which is not something I should comment on according to the rules. The comment also asks the PR author to ensure compatibility, which is not allowed.

Workflow ID: wflow_VCoCW6iKxzqMfEPQ

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

Copy link
Contributor

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

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

Important

Looks good to me! 👍

Reviewed e3c8741 in 46 seconds. Click for details.
  • Reviewed 48 lines of code in 1 files
  • Skipped 0 files when reviewing.
  • Skipped posting 3 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. Readme.md:359
  • Draft comment:
    Clear new 'Role Sync (Enterprise)' section. Emphasize the enterprise license requirement, ensuring users know this feature isn’t available in the open-source version.
  • Reason this comment was not posted:
    Confidence changes required: 0% <= threshold 50% None
2. Readme.md:367
  • Draft comment:
    The sync mode descriptions are concise. Verify consistency between these documented modes and backend implementation, especially regarding role removal behavior in FULL_SYNC.
  • Reason this comment was not posted:
    Confidence changes required: 33% <= threshold 50% None
3. Readme.md:373
  • Draft comment:
    The OIDC, LDAP, and SAML setup instructions are well-structured. Consider adding any specific caveats (if applicable) on attribute extraction nuances for LDAP and SAML configurations.
  • Reason this comment was not posted:
    Confidence changes required: 33% <= threshold 50% None

Workflow ID: wflow_IDzj3v80feT6jXe6

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

Copy link
Contributor

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

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

Important

Looks good to me! 👍

Reviewed a792d3d in 1 minute and 24 seconds. Click for details.
  • Reviewed 170 lines of code in 4 files
  • Skipped 0 files when reviewing.
  • Skipped posting 4 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. backend/build.gradle.kts:27
  • Draft comment:
    Updated testcontainers version to 1.21.3. Please verify that this version is fully compatible with our integration tests.
  • Reason this comment was not posted:
    Confidence changes required: 33% <= threshold 50% None
2. frontend/src/routes/settings/LicenseSettings.tsx:115
  • Draft comment:
    Nice enhancement adding drag event handlers and conditional styling for file upload. Ensure mobile accessibility is verified.
  • Reason this comment was not posted:
    Confidence changes required: 33% <= threshold 50% None
3. frontend/src/routes/settings/RoleSyncSettings.tsx:160
  • Draft comment:
    Added a helpful note for LDAP users indicating that the groups attribute is ignored. This clarification improves UX.
  • Reason this comment was not posted:
    Confidence changes required: 33% <= threshold 50% None
4. frontend/src/routes/settings/Settings.tsx:155
  • Draft comment:
    The Role Sync tab has been repositioned. Confirm that its new ordering and enterprise feature toggle align with the intended UI flow.
  • Reason this comment was not posted:
    Confidence changes required: 33% <= threshold 50% None

Workflow ID: wflow_G1FEDEU1IwtHm1st

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

- Use integer ID with CHECK constraint for singleton pattern instead of
  varchar "default" ID
- Remove config_id foreign key from role_sync_mapping since there's only
  one config and no join is needed
- Fix role_id type to CHAR(22) to match role table
- Query mappings directly from repository instead of through config entity
Copy link
Contributor

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

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

Important

Looks good to me! 👍

Reviewed 39f8fb2 in 2 minutes and 17 seconds. Click for details.
  • Reviewed 218 lines of code in 2 files
  • Skipped 0 files when reviewing.
  • Skipped posting 8 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. backend/src/main/kotlin/dev/kviklet/kviklet/db/RoleSyncConfig.kt:32
  • Draft comment:
    Removed the one-to-many mapping association from RoleSyncConfigEntity. Ensure that mapping lifecycle is now fully managed via mappingRepository and that no dependent logic was relying on cascading.
  • Reason this comment was not posted:
    Comment did not seem useful. Confidence is useful = 0% <= threshold 50% The comment is asking the author to ensure that the mapping lifecycle is managed correctly and that no dependent logic was relying on cascading. This is a request for confirmation and verification, which violates the rules.
2. backend/src/main/kotlin/dev/kviklet/kviklet/db/RoleSyncConfig.kt:56
  • Draft comment:
    Removed the reference to RoleSyncConfigEntity from RoleSyncMappingEntity. Confirm that no business logic still depends on a bidirectional link between mappings and config.
  • Reason this comment was not posted:
    Comment did not seem useful. Confidence is useful = 0% <= threshold 50% The comment is asking the PR author to confirm that no business logic depends on a removed reference. This is asking for confirmation of intention, which violates the rules.
3. backend/src/main/kotlin/dev/kviklet/kviklet/db/RoleSyncConfig.kt:127
  • Draft comment:
    In addMapping, the config linkage is omitted. Consider checking for duplicates (based on idpGroupName) before saving to proactively handle unique constraint violations.
  • Reason this comment was not posted:
    Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 20% vs. threshold = 50% The comment mentions "the config linkage is omitted" which refers to a change in the diff (removal of the config relationship). However, the main suggestion is about checking for duplicates. Looking at the diff, the addMapping function existed before and didn't check for duplicates then either - this isn't a new issue introduced by the changes. The unique constraint on idpGroupName existed before (line 47 shows it's still there). The comment is suggesting a code quality improvement that isn't directly related to the changes made in this PR. The removal of the config linkage doesn't make the duplicate checking more or less necessary than it was before. The comment does reference a change ("config linkage is omitted"), so it could be argued that it's about the diff. Perhaps the removal of the config relationship changes the context in a way that makes duplicate checking more important? Maybe the previous implementation had some implicit duplicate prevention through the config relationship? Looking at the old code in the diff, the config relationship was just a reference (var config: RoleSyncConfigEntity? = null) and didn't provide any duplicate prevention mechanism. The unique constraint on idpGroupName existed both before and after. The duplicate checking suggestion is a general code quality improvement that would have applied equally to the old code, not something specifically introduced by these changes. This comment should be deleted. While it mentions the config linkage removal, the actual suggestion (checking for duplicates) is a general code quality improvement that isn't specifically related to the changes in this PR. The duplicate issue existed before and after the changes, and the removal of the config linkage doesn't make it more or less relevant.
4. backend/src/main/kotlin/dev/kviklet/kviklet/db/RoleSyncConfig.kt:76
  • Draft comment:
    The custom repository method findByIdpGroupNameIn is used for filtering mappings. Ensure that the underlying database has an index on idp_group_name (likely created by the unique constraint) to avoid performance issues with large lists.
  • Reason this comment was not posted:
    Confidence changes required: 50% <= threshold 50% None
5. backend/src/main/resources/changelog/036-add-role-sync-config.yaml:35
  • Draft comment:
    The SQL change sets a check constraint enforcing a singleton config record with id=1. Ensure this design intent is clearly documented to avoid confusion in future migrations or development.
  • Reason this comment was not posted:
    Comment did not seem useful. Confidence is useful = 0% <= threshold 50% The comment is asking the PR author to ensure that the design intent is documented, which violates the rule against asking for confirmation or documentation updates. It does not provide a specific code suggestion or identify a specific issue with the code itself.
6. backend/src/main/resources/changelog/036-add-role-sync-config.yaml:70
  • Draft comment:
    Verify that the role_id column type (CHAR(22)) in role_sync_mapping matches the RoleEntity id type and any indexing requirements, to prevent potential type mismatches.
  • Reason this comment was not posted:
    Comment did not seem useful. Confidence is useful = 0% <= threshold 50% The comment is asking the PR author to verify a potential issue with type mismatches, which is against the rules. It does not provide a specific suggestion or ask for a specific test to be written. Therefore, it should be removed.
7. backend/src/main/kotlin/dev/kviklet/kviklet/db/RoleSyncConfig.kt:43
  • Draft comment:
    There appears to be an extraneous '@entity' annotation at the end of the file (line 43). This might be a leftover from a previous change. Please remove it if it is not needed.
  • Reason this comment was not posted:
    Comment was not on a location in the diff, so it can't be submitted as a review comment.
8. backend/src/main/resources/changelog/036-add-role-sync-config.yaml:47
  • Draft comment:
    It looks like the new column block at line 47 is incomplete (only - column: appears without further properties). Please verify if this is intentional or if additional details are missing.
  • Reason this comment was not posted:
    Comment was not on a location in the diff, so it can't be submitted as a review comment.

Workflow ID: wflow_sUkZPFjYKITVUEVA

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

Copy link
Contributor

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

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

Important

Looks good to me! 👍

Reviewed 047ffc4 in 1 minute and 56 seconds. Click for details.
  • Reviewed 278 lines of code in 4 files
  • Skipped 0 files when reviewing.
  • Skipped posting 4 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. backend/src/main/kotlin/dev/kviklet/kviklet/service/RoleSyncService.kt:27
  • Draft comment:
    Changing log level from info to debug seems appropriate for detailed tracing; just ensure no sensitive info is exposed in production.
  • Reason this comment was not posted:
    Comment did not seem useful. Confidence is useful = 50% <= threshold 50% The comment suggests a change in log level from info to debug, which is a specific code suggestion. However, it also includes a caution about exposing sensitive information, which is a general warning rather than a specific code suggestion. The first part of the comment is useful, but the second part violates the rule against asking the author to ensure behavior is intended or tested.
2. backend/src/main/kotlin/dev/kviklet/kviklet/service/RoleSyncService.kt:51
  • Draft comment:
    Good handling of missing role (catching EntityNotFound). Optionally consider logging exception details if needed for debugging.
  • Reason this comment was not posted:
    Comment was not on a location in the diff, so it can't be submitted as a review comment.
3. backend/src/test/kotlin/dev/kviklet/kviklet/SAMLTest.kt:625
  • Draft comment:
    Test now verifies no user is created when license is missing. Consider if a failure via an explicit fail() call is desired when no exception is thrown to catch unexpected success.
  • Reason this comment was not posted:
    Comment looked like it was already resolved.
4. frontend/src/routes/settings/RoleSyncSettings.tsx:39
  • Draft comment:
    The debounced save logic for the groups attribute is well implemented. Using a ref to hold updateConfig avoids recreating the debounced function – ensure that this design matches your expected update frequency.
  • Reason this comment was not posted:
    Comment did not seem useful. Confidence is useful = 0% <= threshold 50% The comment is suggesting that the use of a ref to hold updateConfig is a design choice to avoid recreating a debounced function. However, it asks the author to ensure that this design matches their expected update frequency, which is a form of asking for confirmation or verification of intent. This violates the rule against asking the PR author to confirm their intention or ensure behavior is intended.

Workflow ID: wflow_4USVEzejk8QVaXzC

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

Copy link
Contributor

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

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

Important

Looks good to me! 👍

Reviewed aec6723 in 2 minutes and 39 seconds. Click for details.
  • Reviewed 69 lines of code in 1 files
  • Skipped 0 files when reviewing.
  • Skipped posting 7 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. Readme.md:223
  • Draft comment:
    Updated message now indicates role sync is available in the enterprise edition. Consider adding a note about any license or pricing requirements.
  • Reason this comment was not posted:
    Confidence changes required: 33% <= threshold 50% None
2. Readme.md:379
  • Draft comment:
    The step-by-step Keycloak instructions look clear. Confirm that the dedicated scope (e.g. 'kviklet-dedicated') is always the correct scope to use or mention if it can vary.
  • Reason this comment was not posted:
    Confidence changes required: 33% <= threshold 50% None
3. Readme.md:413
  • Draft comment:
    The LDAP extraction note was simplified from parsing the CN in the DN to a generic extraction from the 'memberOf' attribute. Please ensure this reflects the actual extraction logic and consider clarifying if parsing is still performed.
  • Reason this comment was not posted:
    Confidence changes required: 33% <= threshold 50% None
4. Readme.md:421
  • Draft comment:
    The SAML extraction note now states that group names are extracted from the SAML attribute. Ensure this generic description covers cases (like Google Workspace) that previously had special instructions.
  • Reason this comment was not posted:
    Confidence changes required: 33% <= threshold 50% None
5. Readme.md:405
  • Draft comment:
    Typographical error: Consider using the possessive form "Kviklet's side" instead of "Kviklets side".
  • Reason this comment was not posted:
    Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 20% vs. threshold = 50% This is a minor typo/grammar correction. While technically correct, it falls into the category of "obvious or unimportant" comments. The meaning is completely clear without the apostrophe, and this is documentation text, not code. The rules explicitly state "Do NOT make comments that are obvious or unimportant." A missing apostrophe in a possessive noun is a very minor issue that doesn't affect functionality or clarity. This type of nitpicky grammar correction is exactly what the rules are trying to filter out. However, documentation quality matters, and proper grammar makes the project look more professional. Some teams have high standards for documentation and would want even minor typos fixed. The comment is actionable and clear. While documentation quality does matter, the rules explicitly prioritize filtering out obvious and unimportant comments. A missing apostrophe in a possessive form is a very minor grammatical issue that doesn't impede understanding. If every minor typo warranted a comment, the review process would be cluttered with trivial feedback. The rules are designed to focus on substantive issues. This comment should be deleted. It's a minor grammatical correction that falls under "obvious or unimportant" per the review guidelines. While technically correct, it doesn't meet the threshold for requiring a review comment.
6. Readme.md:413
  • Draft comment:
    Typographical suggestion: Instead of "in the users attributes", consider using "from the user's attributes" or "from user attributes".
  • Reason this comment was not posted:
    Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 30% vs. threshold = 50% This is a typographical/grammatical comment pointing out that "users" should be "user's" (possessive). The comment is about code that was actually changed in the diff (lines 413 and 421 are new lines). The suggestion is clear and actionable - it's a legitimate grammar fix. However, I need to consider the rules: the instructions say "Do NOT comment unless there is clearly a code change required" and "Do NOT make comments that are obvious or unimportant." This is documentation, not code, and it's a minor grammatical issue. The meaning is still clear despite the missing apostrophe. This might fall under "obvious or unimportant" - it's a very minor typo that doesn't affect understanding. While this is a legitimate grammatical error, it's quite minor and the meaning is still perfectly clear. The rules emphasize not making comments that are "obvious or unimportant" - a missing apostrophe in documentation might fall into this category. Additionally, there are actually TWO instances of this same error (lines 413 and 421), but the comment only addresses one of them, which suggests inconsistency. However, documentation quality matters, especially in a README that users will read. The comment is actionable, specific, and points to a real grammatical error in newly added content. It's not speculative or asking for confirmation - it's a clear fix. The fact that it appears twice actually strengthens the case that it should be fixed. While minor, fixing it improves professionalism. This is a legitimate grammatical correction to newly added documentation. While minor, it's actionable and improves quality. However, given the emphasis on not making "obvious or unimportant" comments, and that this is a very minor typo that doesn't affect comprehension, I lean toward removing it. The bar for keeping comments should be high.
7. Readme.md:421
  • Draft comment:
    Typographical suggestion: Instead of "in the users attributes", consider using "from the user's attributes" or "from user attributes".
  • Reason this comment was not posted:
    Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 20% vs. threshold = 50% This is a minor grammatical/stylistic suggestion. The rules state that I should keep comments that "suggest code quality refactors" if they are "actionable and clear." However, this is documentation text, not code. The comment is about a very minor grammatical issue - "in the users attributes" vs "from the user's attributes". While the suggestion is technically correct (it should be "user's" with an apostrophe, or the phrasing could be improved), this is an extremely minor issue. The rules emphasize not making comments that are "obvious or unimportant." A minor grammatical issue in documentation seems to fall into the "unimportant" category, especially since the meaning is still clear. The rules also say to only keep comments with "STRONG EVIDENCE" that they are correct, and by default assume comments are incorrect or not useful. While the grammatical suggestion is technically correct, documentation typos and minor style issues are typically low priority. The meaning is clear despite the grammatical imperfection. This could be considered an "obvious or unimportant" issue that doesn't warrant a review comment. The comment is indeed about a minor grammatical issue. While it's technically correct, it's not a significant problem that needs to be addressed in a code review. The rules explicitly state not to make comments that are "obvious or unimportant," and a minor grammatical issue in documentation falls into this category. This comment should be deleted. It's about a minor grammatical/stylistic issue in documentation that is not important enough to warrant a review comment. The meaning is clear, and this falls under the "obvious or unimportant" category that should be avoided.

Workflow ID: wflow_dsSDQykeR0qEJVWa

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

Previously role sync would continue working after license expiration,
only the settings UI was gated. Now resolveRoles() checks for a valid
license and falls back to default behavior if none exists.
Copy link
Contributor

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

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

Important

Looks good to me! 👍

Reviewed 16a8200 in 45 seconds. Click for details.
  • Reviewed 34 lines of code in 1 files
  • Skipped 0 files when reviewing.
  • Skipped posting 2 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. backend/src/main/kotlin/dev/kviklet/kviklet/service/RoleSyncService.kt:16
  • Draft comment:
    Ensure that LicenseService is properly imported and registered in the DI container.
  • Reason this comment was not posted:
    Confidence changes required: 0% <= threshold 50% None
2. backend/src/main/kotlin/dev/kviklet/kviklet/service/RoleSyncService.kt:35
  • Draft comment:
    If getActiveLicense() is expensive, consider caching its result to improve performance.
  • Reason this comment was not posted:
    Confidence changes required: 33% <= threshold 50% None

Workflow ID: wflow_OFMTIICP9uhvuFA0

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

@Askir Askir merged commit 740deb2 into main Jan 8, 2026
9 checks passed
@Askir Askir deleted the feature/role-sync branch January 8, 2026 23:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants