Skip to content

Conversation

@marwaayache
Copy link

@marwaayache marwaayache commented Jul 4, 2025

Summary by CodeRabbit

  • New Features

    • Issue Boards to organize and track issues, with configurable columns and assignable states
    • Full CRUD for boards, columns, and board items, including precise item positioning
    • Mutations and inputs to create, update, delete, add/remove states, and manage items
  • Chores

    • Cleaned up unused imports
  • Permissions

    • Added explicit permission for managing Issue Boards

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jul 4, 2025

Walkthrough

Adds a full Issue Board feature: new domain models (IssueBoard, IssueBoardColumn, IssueBoardItem), repositories, services, GraphQL mutations and inputs, Trackable extensions and a MANAGE_ISSUE_BOARDS permission, plus import cleanups.

Changes

Cohort / File(s) Change Summary
GraphQL mutations
api-public/src/main/kotlin/gropius/schema/mutation/IssueMutations.kt
Extended constructor with IssueBoardService, IssueBoardColumnService, IssueBoardItemService. Added mutations: create/update/delete for boards, columns, items; add/remove state to column. All delegate to services using authorization context and return appropriate payloads.
Domain models
core/src/main/kotlin/gropius/model/issue/IssueBoard.kt, .../IssueBoardColumn.kt, .../IssueBoardItem.kt, core/src/main/kotlin/gropius/model/issue/Issue.kt, core/src/main/kotlin/gropius/model/template/IssueState.kt, core/src/main/kotlin/gropius/model/architecture/Trackable.kt
New domain nodes: IssueBoard, IssueBoardColumn, IssueBoardItem with relationships and GraphQL/authorization annotations. Added issueBoards on Trackable, issueBoardColumn on IssueState, and ISSUE_BOARD_ITEM constant on Issue. Configured MANAGE_ISSUE_BOARDS authorization rules tied to related Trackable.
Services
core/src/main/kotlin/gropius/service/issue/IssueBoardService.kt, .../IssueBoardColumnService.kt, .../IssueBoardItemService.kt
New services providing suspend functions for create/update/delete boards, columns, items; add/remove state on columns. Perform input validation, entity loading, permission checks (MANAGE_ISSUE_BOARDS or MANAGE_ISSUES where used), and repository persistence or batch deletion.
Repositories
core/src/main/kotlin/gropius/repository/issue/IssueBoardRepository.kt, .../IssueBoardColumnRepository.kt, .../IssueBoardItemRepository.kt
Added Spring Data repository interfaces extending GropiusRepository for IssueBoard, IssueBoardColumn, and IssueBoardItem.
Input DTOs
core/src/main/kotlin/gropius/dto/input/issue/*
Added input classes: CreateIssueBoardInput, UpdateIssueBoardInput, CreateIssueBoardColumnInput, UpdateIssueBoardColumnInput, CreateIssueBoardItemInput, UpdateIssueBoardItemInput, AddIssueStateToBoardColumnInput, RemoveIssueStateFromBoardColumnInput with GraphQL descriptions and appropriate base types.
Permissions & configuration
core/src/main/kotlin/gropius/model/user/permission/TrackablePermission.kt, .../PermissionConfiguration.kt
Added MANAGE_ISSUE_BOARDS permission constant and a corresponding PermissionEntry in trackable permission configuration.
Import / minor cleanups
api-public/src/main/kotlin/gropius/graphql/GropiusGraphQLContextFactory.kt, api-public/src/main/kotlin/gropius/schema/mutation/ArchitectureMutations.kt, core/.../dto/input/architecture/*, core/.../model/architecture/RelationPartner.kt, sync/src/main/kotlin/gropius/sync/IssueCleaner.kt
Removed unused imports and adjusted some imports/validation in one input; no behavioral changes.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant Client
    participant GraphQL as IssueMutations
    participant Auth as Authorization
    participant Service as IssueBoardService*
    participant Repo as Repositories
    participant NodeRepo as NodeRepository

    Client->>GraphQL: call mutation (e.g., createIssueBoard)
    GraphQL->>Auth: extract gropiusAuthorizationContext
    GraphQL->>Service: service.create...(authCtx, input)
    Service->>Auth: Permission(MANAGE_ISSUE_BOARDS) check on Trackable
    Auth-->>Service: allowed/denied
    Service->>Repo: validate/load related entities (Trackable, IssueBoard, IssueState, Issue, ...)
    Repo-->>Service: entities
    Service->>Repo: save/delete entities (or NodeRepository.deleteAll)
    Repo-->>Service: saved/deleted confirmation
    Service-->>GraphQL: return domain object or DeleteNodePayload
    GraphQL-->>Client: GraphQL response
Loading

Note: Service box represents any of IssueBoardService, IssueBoardColumnService, IssueBoardItemService depending on operation.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Focus review on:
    • IssueBoardColumnService.addIssueStateToBoardColumn() — ensuring duplicate-state checks across columns are correct
    • Delete cascades in IssueBoardService.deleteIssueBoard() — ensure all related nodes are collected and deletion conditions are correct
    • Permission usage consistency (MANAGE_ISSUE_BOARDS vs MANAGE_ISSUES) across services
    • Relationship annotations (incoming/outgoing) on new model classes and filter properties

Possibly related PRs

Suggested reviewers

  • chriku

Poem

🐰 I hopped into code with a hop and a bound,
Built boards and columns and items all round,
States find their homes, positions align,
Permissions secure each carrot and vine—
Hooray for boards! Now I’ll nibble a byte. 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 45.83% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'add all Entities for IssueBoard + mutations' accurately describes the main changes in this PR, which introduces new IssueBoard entities (IssueBoard, IssueBoardColumn, IssueBoardItem) along with their corresponding GraphQL mutations and supporting infrastructure.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/Issue_Board_Entities

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

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

🧹 Nitpick comments (19)
core/src/main/kotlin/gropius/model/issue/Issue.kt (1)

70-70: Verify naming / ordering of new relationship constant

ISSUE_BOARD_ITEM breaks the (mostly) alphabetical grouping that exists in this block (ASSIGNMENT, AFFECTS, …).
Aligning the order keeps navigation easy and avoids merge-time conflicts.

No functional impact, but please double-check if you want to keep the order consistent.

core/src/main/kotlin/gropius/dto/input/issue/UpdateIssueBoardColumnInput.kt (1)

6-7: Kotlin style ­– missing space before colon

Idiomatic declaration:

class UpdateIssueBoardColumnInput : UpdateNamedNodeInput()

A tiny spacing fix keeps the codebase consistent with the Kotlin style guide.

core/src/main/kotlin/gropius/dto/input/issue/UpdateIssueBoardInput.kt (1)

6-7: Kotlin style ­– missing space before colon

Same spacing nit as above:

class UpdateIssueBoardInput : UpdateNamedNodeInput()
core/src/main/kotlin/gropius/dto/input/issue/CreateIssueBoardInput.kt (1)

7-11: Minor formatting & clarity improvements

  1. Missing space after : in trackable:ID.
  2. Missing space before : after the closing parenthesis.
  3. Optional: Declare as data class to get equals/hashCode/toString for free.

Proposed diff:

-@GraphQLDescription("Input for the createIssueBoard mutation")
-class CreateIssueBoardInput(
-    @GraphQLDescription("ID of Trackable the issue board is added to")
-    val trackable:ID
-):CreateNamedNodeInput()
+@GraphQLDescription("Input for the createIssueBoard mutation")
+data class CreateIssueBoardInput(
+    @GraphQLDescription("ID of the Trackable the issue board is added to")
+    val trackable: ID
+) : CreateNamedNodeInput()
core/src/main/kotlin/gropius/repository/issue/IssueBoardRepository.kt (1)

8-12: Indentation at top level

The interface is indented by four spaces although it’s a top-level declaration.
Removing the extra indent matches the rest of the repository files.

-    /**
-     * Repository for [IssueBoard]
-     */
-    @Repository
-    interface IssueBoardRepository : GropiusRepository<IssueBoard, String>
+/**
+ * Repository for [IssueBoard]
+ */
+@Repository
+interface IssueBoardRepository : GropiusRepository<IssueBoard, String>
core/src/main/kotlin/gropius/repository/issue/IssueBoardItemRepository.kt (1)

1-13: LGTM! Standard repository implementation with minor formatting suggestion.

The interface correctly extends GropiusRepository with appropriate type parameters and includes proper Spring annotations. The implementation follows established patterns in the codebase.

Consider removing the extra blank lines for cleaner formatting:

 package gropius.repository.issue
 
-
 import gropius.model.issue.IssueBoardItem
 import gropius.repository.GropiusRepository
 import org.springframework.stereotype.Repository
 
-
 /**
  * Repository for [IssueBoardItem]
  */
core/src/main/kotlin/gropius/dto/input/issue/RemoveIssueStateFromBoardColumnInput.kt (1)

7-7: Fix typo in GraphQL description.

The description mentions "removeIssueStateToBoardColumn" but should be "removeIssueStateFromBoardColumn" to match the class name and intended functionality.

-@GraphQLDescription("Input for the removeIssueStateToBoardColumn mutation")
+@GraphQLDescription("Input for the removeIssueStateFromBoardColumn mutation")
core/src/main/kotlin/gropius/service/issue/IssueBoardService.kt (5)

27-27: Fix formatting: Add space after colon.

-):NamedNodeService<IssueBoard,IssueBoardRepository>(repository){
+) : NamedNodeService<IssueBoard, IssueBoardRepository>(repository) {

42-46: Fix indentation for consistency.

-            checkPermission(
-                trackable,
-                Permission(TrackablePermission.MANAGE_ISSUE_BOARDS, authorizationContext),
-                "create Issue Boards on ${trackable.rawId}"
-            )
+        checkPermission(
+            trackable,
+            Permission(TrackablePermission.MANAGE_ISSUE_BOARDS, authorizationContext),
+            "create Issue Boards on ${trackable.rawId}"
+        )

49-49: Remove extra space after assignment operator.

-        issueBoard.trackable().value=trackable
+        issueBoard.trackable().value = trackable

88-92: Fix indentation for consistency.

-            checkPermission(
-                trackable,
-                Permission(TrackablePermission.MANAGE_ISSUE_BOARDS, authorizationContext),
-                "manage Issue Boards in a Trackable"
-            )
+        checkPermission(
+            trackable,
+            Permission(TrackablePermission.MANAGE_ISSUE_BOARDS, authorizationContext),
+            "manage Issue Boards in a Trackable"
+        )

98-98: Add space before method call.

-       nodeRepository.deleteAll(toDelete).awaitSingleOrNull()
+        nodeRepository.deleteAll(toDelete).awaitSingleOrNull()
core/src/main/kotlin/gropius/service/issue/IssueBoardColumnService.kt (3)

26-26: Fix formatting: Add space after colon.

-):NamedNodeService<IssueBoardColumn,IssueBoardColumnRepository>(repository){
+) : NamedNodeService<IssueBoardColumn, IssueBoardColumnRepository>(repository) {

49-49: Add space around assignment operator.

-        issueBoardColumn.issueBoard().value= issueBoard
+        issueBoardColumn.issueBoard().value = issueBoard

124-129: Fix error message formatting and improve clarity.

-        val isAssigned = issueBoard.issueBoardColumns().any{column ->state in column.issueStates()}
+        val isAssigned = issueBoard.issueBoardColumns().any { column -> state in column.issueStates() }
         if (state !in column.issueStates()) {
-            if( isAssigned){
-                throw IllegalStateException("Issue State already exists  in another board column")
+            if (isAssigned) {
+                throw IllegalStateException("Issue State already exists in another board column")
             }
api-public/src/main/kotlin/gropius/schema/mutation/IssueMutations.kt (4)

28-28: Fix formatting: Remove extra spaces in class declaration.

-class         IssueMutations(
+class IssueMutations(

567-567: Add space before opening brace.

-    ): IssueBoardColumn{
+    ): IssueBoardColumn {

631-631: Add space before opening brace.

-    ): IssueBoardItem{
+    ): IssueBoardItem {

644-644: Remove extra empty line.

-
-
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between c2139dd and 2e19fa2.

📒 Files selected for processing (23)
  • api-public/src/main/kotlin/gropius/schema/mutation/IssueMutations.kt (3 hunks)
  • core/src/main/kotlin/gropius/dto/input/issue/AddIssueStateToBoardColumnInput.kt (1 hunks)
  • core/src/main/kotlin/gropius/dto/input/issue/CreateIssueBoardColumnInput.kt (1 hunks)
  • core/src/main/kotlin/gropius/dto/input/issue/CreateIssueBoardInput.kt (1 hunks)
  • core/src/main/kotlin/gropius/dto/input/issue/CreateIssueBoardItemInput.kt (1 hunks)
  • core/src/main/kotlin/gropius/dto/input/issue/RemoveIssueStateFromBoardColumnInput.kt (1 hunks)
  • core/src/main/kotlin/gropius/dto/input/issue/UpdateIssueBoardColumnInput.kt (1 hunks)
  • core/src/main/kotlin/gropius/dto/input/issue/UpdateIssueBoardInput.kt (1 hunks)
  • core/src/main/kotlin/gropius/dto/input/issue/UpdateIssueBoardItemInput.kt (1 hunks)
  • core/src/main/kotlin/gropius/model/architecture/Trackable.kt (5 hunks)
  • core/src/main/kotlin/gropius/model/issue/Issue.kt (1 hunks)
  • core/src/main/kotlin/gropius/model/issue/IssueBoard.kt (1 hunks)
  • core/src/main/kotlin/gropius/model/issue/IssueBoardColumn.kt (1 hunks)
  • core/src/main/kotlin/gropius/model/issue/IssueBoardItem.kt (1 hunks)
  • core/src/main/kotlin/gropius/model/template/IssueState.kt (3 hunks)
  • core/src/main/kotlin/gropius/model/user/permission/PermissionConfiguration.kt (1 hunks)
  • core/src/main/kotlin/gropius/model/user/permission/TrackablePermission.kt (2 hunks)
  • core/src/main/kotlin/gropius/repository/issue/IssueBoardColumnRepository.kt (1 hunks)
  • core/src/main/kotlin/gropius/repository/issue/IssueBoardItemRepository.kt (1 hunks)
  • core/src/main/kotlin/gropius/repository/issue/IssueBoardRepository.kt (1 hunks)
  • core/src/main/kotlin/gropius/service/issue/IssueBoardColumnService.kt (1 hunks)
  • core/src/main/kotlin/gropius/service/issue/IssueBoardItemService.kt (1 hunks)
  • core/src/main/kotlin/gropius/service/issue/IssueBoardService.kt (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
core/src/main/kotlin/gropius/model/template/IssueState.kt (1)
Learnt from: nk-coding
PR: ccims/gropius-backend#158
File: core/src/main/kotlin/gropius/service/architecture/ProjectService.kt:177-195
Timestamp: 2025-05-12T21:28:32.348Z
Learning: In the Gropius backend, properties annotated with `@GraphQLNullable` are only nullable in the GraphQL API due to access restrictions, but remain non-null in the actual implementation. This means null checks are unnecessary when working with these properties in the code.
🧬 Code Graph Analysis (3)
core/src/main/kotlin/gropius/service/issue/IssueBoardItemService.kt (1)
core/src/main/kotlin/gropius/dto/input/issue/CreateIssueBoardItemInput.kt (1)
  • issueBoard (7-16)
core/src/main/kotlin/gropius/service/issue/IssueBoardColumnService.kt (1)
core/src/main/kotlin/gropius/service/common/NamedNodeService.kt (1)
  • updateNamedNode (26-33)
core/src/main/kotlin/gropius/service/issue/IssueBoardService.kt (1)
core/src/main/kotlin/gropius/service/common/NamedNodeService.kt (1)
  • updateNamedNode (26-33)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Build
🔇 Additional comments (20)
core/src/main/kotlin/gropius/dto/input/issue/CreateIssueBoardColumnInput.kt (1)

1-11: LGTM! Well-structured input DTO following established patterns.

The implementation correctly extends CreateNamedNodeInput and includes the required issueBoard property with clear GraphQL documentation. The class follows the established pattern for input DTOs in the codebase.

core/src/main/kotlin/gropius/repository/issue/IssueBoardColumnRepository.kt (1)

1-12: LGTM! Standard repository implementation following Spring Data patterns.

The interface correctly extends GropiusRepository with appropriate type parameters and includes proper Spring annotations. The implementation follows established patterns in the codebase.

core/src/main/kotlin/gropius/model/user/permission/TrackablePermission.kt (2)

67-72: LGTM! Permission constant follows established patterns.

The new MANAGE_ISSUE_BOARDS permission is well-documented and follows the same naming convention and documentation pattern as other permissions in the class. The scope is clearly defined.


10-11: LGTM! Imports added for new entities.

The imports for IssueBoard and IssueBoardColumn are necessary for the new permission functionality.

core/src/main/kotlin/gropius/dto/input/issue/UpdateIssueBoardItemInput.kt (1)

1-13: LGTM! Well-designed update input DTO with appropriate optional field handling.

The implementation correctly extends UpdateNodeInput and uses OptionalInput<Double> for the position field, which is appropriate for update operations where the position might not need to be changed. The GraphQL documentation is clear and the use of Double for position allows for flexible ordering.

core/src/main/kotlin/gropius/model/user/permission/PermissionConfiguration.kt (1)

64-69: LGTM! Well-structured permission entry.

The new MANAGE_ISSUE_BOARDS permission entry follows the established pattern and includes a clear description that explains the scope of permissions and conditional deletion requirements.

core/src/main/kotlin/gropius/dto/input/issue/AddIssueStateToBoardColumnInput.kt (1)

1-14: LGTM! Well-implemented input DTO.

The class structure is consistent with other input DTOs, has clear GraphQL descriptions, and follows naming conventions properly.

core/src/main/kotlin/gropius/model/template/IssueState.kt (3)

6-6: LGTM! Proper import addition.

The import for IssueBoardColumn is correctly added to support the new relationship.


28-28: LGTM! Consistent constant naming.

The new constant ISSUE_BOARD_COLUMN follows the established naming convention for relationship constants.


41-45: LGTM! Well-implemented relationship.

The new relationship to IssueBoardColumn is properly configured with:

  • Correct incoming direction from IssueBoardColumn.ISSUE_STATE
  • Appropriate GraphQL description
  • @FilterProperty annotation for query filtering
  • NodeProperty<IssueBoardColumn>() indicating a one-to-one relationship

The implementation follows the established pattern and integrates well with the existing domain model.

core/src/main/kotlin/gropius/model/issue/IssueBoard.kt (1)

18-42: LGTM! Well-structured authorization and relationships.

The authorization annotations and relationship definitions are correctly implemented. The use of proper directions for relationships and consistent naming conventions is good.

core/src/main/kotlin/gropius/model/issue/IssueBoardItem.kt (1)

36-44: LGTM! Proper relationship definitions.

The relationships to IssueBoard and Issue are correctly defined with proper directions and GraphQL descriptions.

core/src/main/kotlin/gropius/model/issue/IssueBoardColumn.kt (1)

20-44: LGTM! Proper authorization and relationship definitions.

The authorization annotations correctly reference the issueBoard relationship, and all relationships are properly defined with appropriate directions and GraphQL descriptions.

core/src/main/kotlin/gropius/model/architecture/Trackable.kt (5)

7-7: LGTM! Proper import addition.

The import for IssueBoard is correctly added.


16-16: LGTM! Updated GraphQL description.

The description correctly includes Issue Boards alongside the existing entities.


45-47: LGTM! Consistent authorization pattern.

The authorization for MANAGE_ISSUE_BOARDS follows the same pattern as other trackable permissions.


78-78: LGTM! Proper constant addition.

The ISSUE_BOARD constant follows the existing naming convention.


90-95: LGTM! Proper relationship definition.

The issueBoards relationship is correctly defined with proper direction, GraphQL description, and filter property annotation.

core/src/main/kotlin/gropius/service/issue/IssueBoardItemService.kt (2)

50-52: LGTM! Good validation logic.

The validation that checks if the trackable is present in the issue's trackables is good business logic that prevents invalid associations.


54-60: LGTM! Proper entity creation.

The IssueBoardItem creation and relationship assignment follows the correct pattern.

@nk-coding nk-coding assigned marwaayache and unassigned nk-coding Aug 4, 2025
@nk-coding nk-coding self-requested a review August 4, 2025 10:49
Copy link
Contributor

@nk-coding nk-coding left a comment

Choose a reason for hiding this comment

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

mostly looks good

  • pls run the import cleanup from IntelliJ
  • pls run the formatter on your code files
  • at least one relation was wrongly defined, pls fix (and also check the other relations for similar issues)

Copy link
Contributor

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

🧹 Nitpick comments (10)
core/src/main/kotlin/gropius/dto/input/architecture/UpdateInterfaceSpecificationVersionInput.kt (1)

21-26: Great addition; also validate tags (uniqueness/non-blank) and version (non-blank)

To prevent duplicate/empty tags and empty versions at the boundary, extend validate().

     override fun validate() {
         super.validate()
         templatedFields.ifPresent {
             it.validateAndEnsureNoDuplicates()
         }
+        tags.ifPresent {
+            require(it.size == it.toSet().size) { "Duplicate tags are not allowed" }
+            require(it.all { tag -> tag.isNotBlank() }) { "Tags must not be blank" }
+        }
+        version.ifPresent {
+            require(it.isNotBlank()) { "version must not be blank" }
+        }
     }
core/src/main/kotlin/gropius/dto/input/issue/CreateIssueBoardItemInput.kt (1)

15-16: Remove empty class body to satisfy detekt

No body needed; constructors already define all properties.

Apply this diff:

-) : Input() {
-}
+) : Input()
core/src/main/kotlin/gropius/model/architecture/Trackable.kt (1)

16-21: Tiny doc nit: missing space after comma

Add a space after “Issues,”.

Apply this diff:

-    """An entity which can have Issues,Issue Boards, Labels and Artefacts.
+    """An entity which can have Issues, Issue Boards, Labels and Artefacts.
core/src/main/kotlin/gropius/service/issue/IssueBoardService.kt (1)

65-79: Make permission target consistent with delete flow

Use the Trackable as the target in update as well (like delete does) for consistency.

Apply this diff:

     suspend fun updateIssueBoard(
         authorizationContext: GropiusAuthorizationContext,
         input: UpdateIssueBoardInput
     ): IssueBoard {
         input.validate()
         val issueBoard = repository.findById(input.id)
-        checkPermission(
-            issueBoard,
+        val trackable = issueBoard.trackable().value
+        checkPermission(
+            trackable,
             Permission(TrackablePermission.MANAGE_ISSUE_BOARDS, authorizationContext),
             "manage Issue Boards in its Trackable"
         )
 
         updateNamedNode(issueBoard, input)
         return repository.save(issueBoard).awaitSingle()
     }
core/src/main/kotlin/gropius/service/issue/IssueBoardItemService.kt (2)

55-56: Validate position to reject NaN/Infinity.

Ensure position is finite before persisting/updating to avoid ordering anomalies.

-        val item = IssueBoardItem(
-            position = input.position
-        ).apply {
+        val item = IssueBoardItem(
+            position = input.position
+        ).apply {
             issueBoard().value = issueBoard
             issue().value = issue
         }

Add inside create before constructing IssueBoardItem and in update before assignment:

+        require(kotlin.math.isFinite(input.position)) { "position must be finite" }

and

-        input.position.ifPresent { item.position = it }
+        input.position.ifPresent {
+            require(kotlin.math.isFinite(it)) { "position must be finite" }
+            item.position = it
+        }

Outside this hunk, add:

import kotlin.math.isFinite

Also applies to: 86-86


50-52: Optional: enforce uniqueness of IssueBoardItem(issue, board)
Add an existence check in IssueBoardItemService#create (e.g. repository.existsByIssueAndIssueBoard(issue, board)) and a DB‐level unique constraint on (issue_id, issue_board_id) to prevent duplicates.

core/src/main/kotlin/gropius/service/issue/IssueBoardColumnService.kt (3)

73-77: Standardize permission checks on the Trackable (consistency with create).

create checks on trackable; these methods check on issueBoard. Prefer using the parent trackable in all places for clarity and consistency.

@@
-        val issueBoard = issueBoardColumn.issueBoard().value
-        checkPermission(
-            issueBoard,
+        val issueBoard = issueBoardColumn.issueBoard().value
+        val trackable = issueBoard.trackable().value
+        checkPermission(
+            trackable,
             Permission(TrackablePermission.MANAGE_ISSUE_BOARDS, authorizationContext),
             "manage Issue Boards in its Trackable"
         )
@@
-        val board = column.issueBoard().value
-        checkPermission(
-            board,
+        val board = column.issueBoard().value
+        val trackable = board.trackable().value
+        checkPermission(
+            trackable,
             Permission(TrackablePermission.MANAGE_ISSUE_BOARDS, authorizationContext),
             "manage Issue Boards in a Trackable"
         )
@@
-        val issueBoard = column.issueBoard().value
+        val issueBoard = column.issueBoard().value
+        val trackable = issueBoard.trackable().value
         checkPermission(
-            issueBoard,
+            trackable,
             Permission(TrackablePermission.MANAGE_ISSUE_BOARDS, authorizationContext),
             "manage Issue Boards in a Trackable"
         )
@@
-        val issueBoard = column.issueBoard().value
+        val issueBoard = column.issueBoard().value
+        val trackable = issueBoard.trackable().value
         checkPermission(
-            issueBoard,
+            trackable,
             Permission(TrackablePermission.MANAGE_ISSUE_BOARDS, authorizationContext),
             "manage Issue Boards in a Trackable"
         )

Also applies to: 96-100, 119-123, 149-153


106-109: Docs mention READ on IssueState but code doesn’t enforce it.

Either drop the READ requirement here or add the check; maintainers noted READ is universal, so trimming the doc reduces noise.

-    /**
-     * Adds an [IssueState] to an [IssueBoardColumn].
-     * Checks MANAGE_ISSUE_BOARDS on the parent trackable and READ on the state.
-     * Returns the updated column.
-     */
+    /**
+     * Adds an [IssueState] to an [IssueBoardColumn].
+     * Checks MANAGE_ISSUE_BOARDS on the parent trackable.
+     * Returns the updated column.
+     */
-    /**
-     * Removes an [IssueState] from an [IssueBoardColumn].
-     * Checks MANAGE_ISSUE_BOARDS on the parent trackable and READ on the state.
-     * Returns the updated column.
-     */
+    /**
+     * Removes an [IssueState] from an [IssueBoardColumn].
+     * Checks MANAGE_ISSUE_BOARDS on the parent trackable.
+     * Returns the updated column.
+     */

Also applies to: 137-140


125-132: Nit: fix double space in error message.

Small typo in the exception string.

-                throw IllegalStateException("Issue State already exists  in another board column")
+                throw IllegalStateException("Issue State already exists in another board column")
api-public/src/main/kotlin/gropius/schema/mutation/IssueMutations.kt (1)

592-596: Optional: remove READ-on-IssueState from docs (it’s implicitly granted).

To avoid confusion, drop the READ mention or note it’s universally granted.

-        """Adds an Issue State to a Board Column, requires MANAGE_ISSUE_BOARDS on the parent Trackable 
-        of the column the Issue State should be added to, and READ on the Issue State.
+        """Adds an Issue State to a Board Column, requires MANAGE_ISSUE_BOARDS on the parent Trackable 
+        of the column the Issue State should be added to.
         Returns the updated column (unchanged if the state was already assigned).
         """
-        """Removes an Issue State from a Board Column, requires MANAGE_ISSUE_BOARDS on the parent Trackable 
-           of the column the Issue State should be removed from, and READ on the Issue State.
+        """Removes an Issue State from a Board Column, requires MANAGE_ISSUE_BOARDS on the parent Trackable 
+           of the column the Issue State should be removed from.
            Returns the updated column.
         """

Also applies to: 606-611

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3bce8fb and 1cfafc8.

📒 Files selected for processing (31)
  • api-public/src/main/kotlin/gropius/graphql/GropiusGraphQLContextFactory.kt (0 hunks)
  • api-public/src/main/kotlin/gropius/schema/mutation/ArchitectureMutations.kt (0 hunks)
  • api-public/src/main/kotlin/gropius/schema/mutation/IssueMutations.kt (3 hunks)
  • core/src/main/kotlin/gropius/dto/input/architecture/ComponentVersionInput.kt (0 hunks)
  • core/src/main/kotlin/gropius/dto/input/architecture/UpdateComponentVersionInput.kt (0 hunks)
  • core/src/main/kotlin/gropius/dto/input/architecture/UpdateInterfaceSpecificationVersionInput.kt (1 hunks)
  • core/src/main/kotlin/gropius/dto/input/issue/AddIssueStateToBoardColumnInput.kt (1 hunks)
  • core/src/main/kotlin/gropius/dto/input/issue/CreateIssueBoardColumnInput.kt (1 hunks)
  • core/src/main/kotlin/gropius/dto/input/issue/CreateIssueBoardInput.kt (1 hunks)
  • core/src/main/kotlin/gropius/dto/input/issue/CreateIssueBoardItemInput.kt (1 hunks)
  • core/src/main/kotlin/gropius/dto/input/issue/RemoveIssueStateFromBoardColumnInput.kt (1 hunks)
  • core/src/main/kotlin/gropius/dto/input/issue/UpdateIssueBoardColumnInput.kt (1 hunks)
  • core/src/main/kotlin/gropius/dto/input/issue/UpdateIssueBoardInput.kt (1 hunks)
  • core/src/main/kotlin/gropius/dto/input/issue/UpdateIssueBoardItemInput.kt (1 hunks)
  • core/src/main/kotlin/gropius/model/architecture/RelationPartner.kt (0 hunks)
  • core/src/main/kotlin/gropius/model/architecture/Trackable.kt (5 hunks)
  • core/src/main/kotlin/gropius/model/issue/IssueBoard.kt (1 hunks)
  • core/src/main/kotlin/gropius/model/issue/IssueBoardColumn.kt (1 hunks)
  • core/src/main/kotlin/gropius/model/issue/IssueBoardItem.kt (1 hunks)
  • core/src/main/kotlin/gropius/model/template/IssueState.kt (2 hunks)
  • core/src/main/kotlin/gropius/model/user/permission/TrackablePermission.kt (2 hunks)
  • core/src/main/kotlin/gropius/service/issue/IssueBoardColumnService.kt (1 hunks)
  • core/src/main/kotlin/gropius/service/issue/IssueBoardItemService.kt (1 hunks)
  • core/src/main/kotlin/gropius/service/issue/IssueBoardService.kt (1 hunks)
  • sync-github/src/main/kotlin/gropius/sync/github/GithubTokenManager.kt (0 hunks)
  • sync-jira/src/main/kotlin/gropius/sync/jira/JiraSync.kt (0 hunks)
  • sync-jira/src/main/kotlin/gropius/sync/jira/JiraTokenManager.kt (0 hunks)
  • sync-jira/src/main/kotlin/gropius/sync/jira/model/IssueQuery.kt (0 hunks)
  • sync-jira/src/main/kotlin/gropius/sync/jira/model/ProjectQuery.kt (0 hunks)
  • sync/src/main/kotlin/gropius/sync/IssueCleaner.kt (0 hunks)
  • sync/src/main/kotlin/gropius/sync/TokenManager.kt (0 hunks)
💤 Files with no reviewable changes (12)
  • core/src/main/kotlin/gropius/model/architecture/RelationPartner.kt
  • api-public/src/main/kotlin/gropius/schema/mutation/ArchitectureMutations.kt
  • api-public/src/main/kotlin/gropius/graphql/GropiusGraphQLContextFactory.kt
  • sync-jira/src/main/kotlin/gropius/sync/jira/JiraSync.kt
  • core/src/main/kotlin/gropius/dto/input/architecture/ComponentVersionInput.kt
  • sync-github/src/main/kotlin/gropius/sync/github/GithubTokenManager.kt
  • sync-jira/src/main/kotlin/gropius/sync/jira/model/ProjectQuery.kt
  • core/src/main/kotlin/gropius/dto/input/architecture/UpdateComponentVersionInput.kt
  • sync-jira/src/main/kotlin/gropius/sync/jira/JiraTokenManager.kt
  • sync/src/main/kotlin/gropius/sync/IssueCleaner.kt
  • sync/src/main/kotlin/gropius/sync/TokenManager.kt
  • sync-jira/src/main/kotlin/gropius/sync/jira/model/IssueQuery.kt
🚧 Files skipped from review as they are similar to previous changes (7)
  • core/src/main/kotlin/gropius/dto/input/issue/UpdateIssueBoardItemInput.kt
  • core/src/main/kotlin/gropius/dto/input/issue/AddIssueStateToBoardColumnInput.kt
  • core/src/main/kotlin/gropius/model/issue/IssueBoardItem.kt
  • core/src/main/kotlin/gropius/model/issue/IssueBoard.kt
  • core/src/main/kotlin/gropius/dto/input/issue/CreateIssueBoardColumnInput.kt
  • core/src/main/kotlin/gropius/model/template/IssueState.kt
  • core/src/main/kotlin/gropius/dto/input/issue/UpdateIssueBoardColumnInput.kt
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-08-04T13:05:27.476Z
Learnt from: nk-coding
PR: ccims/gropius-backend#159
File: core/src/main/kotlin/gropius/service/issue/IssueBoardItemService.kt:103-103
Timestamp: 2025-08-04T13:05:27.476Z
Learning: In the IssueBoardItemService class in core/src/main/kotlin/gropius/service/issue/IssueBoardItemService.kt, the permission TrackablePermission.MANAGE_ISSUES is intentionally used instead of MANAGE_ISSUE_BOARDS for managing issue board items, as these operations are considered issue management rather than board structure management.

Applied to files:

  • core/src/main/kotlin/gropius/dto/input/issue/CreateIssueBoardInput.kt
  • core/src/main/kotlin/gropius/service/issue/IssueBoardService.kt
  • core/src/main/kotlin/gropius/model/architecture/Trackable.kt
  • api-public/src/main/kotlin/gropius/schema/mutation/IssueMutations.kt
  • core/src/main/kotlin/gropius/model/user/permission/TrackablePermission.kt
  • core/src/main/kotlin/gropius/service/issue/IssueBoardColumnService.kt
  • core/src/main/kotlin/gropius/service/issue/IssueBoardItemService.kt
  • core/src/main/kotlin/gropius/dto/input/issue/CreateIssueBoardItemInput.kt
📚 Learning: 2025-08-04T13:05:27.239Z
Learnt from: nk-coding
PR: ccims/gropius-backend#159
File: core/src/main/kotlin/gropius/service/issue/IssueBoardItemService.kt:79-79
Timestamp: 2025-08-04T13:05:27.239Z
Learning: IssueBoardItem operations (create, update, delete) should use TrackablePermission.MANAGE_ISSUES permission instead of TrackablePermission.MANAGE_ISSUE_BOARDS, as confirmed by the project maintainer nk-coding.

Applied to files:

  • core/src/main/kotlin/gropius/model/architecture/Trackable.kt
  • core/src/main/kotlin/gropius/model/user/permission/TrackablePermission.kt
  • core/src/main/kotlin/gropius/service/issue/IssueBoardColumnService.kt
  • core/src/main/kotlin/gropius/service/issue/IssueBoardItemService.kt
🧬 Code graph analysis (4)
core/src/main/kotlin/gropius/dto/input/issue/UpdateIssueBoardInput.kt (1)
core/src/main/kotlin/gropius/dto/input/issue/UpdateBodyInput.kt (1)
  • @GraphQLDescription("Input for the updateBody mutation") (5-6)
core/src/main/kotlin/gropius/service/issue/IssueBoardService.kt (1)
core/src/main/kotlin/gropius/service/common/NamedNodeService.kt (1)
  • updateNamedNode (26-33)
core/src/main/kotlin/gropius/service/issue/IssueBoardColumnService.kt (1)
core/src/main/kotlin/gropius/service/common/NamedNodeService.kt (1)
  • updateNamedNode (26-33)
core/src/main/kotlin/gropius/service/issue/IssueBoardItemService.kt (1)
core/src/main/kotlin/gropius/dto/input/issue/CreateIssueBoardItemInput.kt (1)
  • issueBoard (7-16)
🪛 detekt (1.23.8)
core/src/main/kotlin/gropius/dto/input/issue/CreateIssueBoardItemInput.kt

[warning] 15-16: The class or object CreateIssueBoardItemInput is empty.

(detekt.empty-blocks.EmptyClassBlock)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build
🔇 Additional comments (9)
core/src/main/kotlin/gropius/dto/input/architecture/UpdateInterfaceSpecificationVersionInput.kt (1)

5-7: Explicit imports over wildcard: LGTM

Improves clarity and avoids accidental symbol leakage.

core/src/main/kotlin/gropius/dto/input/issue/UpdateIssueBoardInput.kt (1)

6-7: LGTM

Input type correctly extends UpdateNamedNodeInput and is documented.

core/src/main/kotlin/gropius/dto/input/issue/CreateIssueBoardInput.kt (1)

7-11: LGTM

Naming and types align with create flow; trackable linkage is clear.

core/src/main/kotlin/gropius/model/architecture/Trackable.kt (1)

126-131: LGTM

Outgoing IssueBoard relationship is consistent with the model and filterable.

core/src/main/kotlin/gropius/service/issue/IssueBoardService.kt (2)

38-54: LGTM

Validation, permission check on Trackable, relation set, and save are correct.


89-105: LGTM

Deletion gathers columns, items, and board; permission is enforced on the Trackable.

core/src/main/kotlin/gropius/model/user/permission/TrackablePermission.kt (1)

66-72: LGTM; MANAGE_ISSUE_BOARDS is registered and used correctly
The permission is present in PermissionConfiguration, applied in @authorization annotations and service checks, and documented in GraphQL mutations.

core/src/main/kotlin/gropius/model/issue/IssueBoardColumn.kt (1)

17-33: Approve relation and authorization configuration NodeRelationship directions for ISSUE_BOARD_COLUMN (OUTGOING on IssueBoard ↔ INCOMING on IssueBoardColumn) and ISSUE_STATE (OUTGOING on IssueBoardColumn) and allowFromRelated authorizations align correctly.

core/src/main/kotlin/gropius/service/issue/IssueBoardItemService.kt (1)

45-49: Permission choice (MANAGE_ISSUES) is correct for board items.

Use of TrackablePermission.MANAGE_ISSUES here matches the intended model for IssueBoardItem operations (per maintainer guidance).

Also applies to: 81-84, 104-108

Comment on lines 624 to 626
"""Creates a new Issue Board Item on an Issue Board. Requires MANAGE_ISSUE_BOARDS on the parent trackable.
"""
)
Copy link
Contributor

@coderabbitai coderabbitai bot Sep 24, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue

GraphQL docs mismatch: Item ops require MANAGE_ISSUES, not MANAGE_ISSUE_BOARDS.

Service enforces TrackablePermission.MANAGE_ISSUES for IssueBoardItem (confirmed by maintainer). Update descriptions for accuracy.

-        """Creates a new Issue Board Item on an Issue Board. Requires MANAGE_ISSUE_BOARDS on the parent trackable.
+        """Creates a new Issue Board Item on an Issue Board. Requires MANAGE_ISSUES on the board’s Trackable.
         """
-    @GraphQLDescription("Updates the specified Issue Board Item, Requires MANAGE_ISSUE_BOARDS on the parent trackable.")
+    @GraphQLDescription("Updates the specified Issue Board Item, Requires MANAGE_ISSUES on the board’s Trackable.")
-        """Deletes the Issue Board Item, requires MANAGE_ISSUE_BOARDS on the parent trackable.
+        """Deletes the Issue Board Item, requires MANAGE_ISSUES on the board’s Trackable.
         """

Also applies to: 635-636, 646-647

🤖 Prompt for AI Agents
In api-public/src/main/kotlin/gropius/schema/mutation/IssueMutations.kt around
lines 624-626 (and similarly update the docstrings at 635-636 and 646-647), the
GraphQL docs incorrectly state that creating IssueBoardItems requires
MANAGE_ISSUE_BOARDS; change those descriptions to state
TrackablePermission.MANAGE_ISSUES instead so they match the service enforcement.
Update the three docstring literals to mention MANAGE_ISSUES and ensure the
wording remains consistent with other permission docs.

Copy link
Contributor

Choose a reason for hiding this comment

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

@marwaayache pls fix

Copy link
Contributor

Choose a reason for hiding this comment

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

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Comment on lines 624 to 626
"""Creates a new Issue Board Item on an Issue Board. Requires MANAGE_ISSUE_BOARDS on the parent trackable.
"""
)
Copy link
Contributor

Choose a reason for hiding this comment

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

@marwaayache pls fix

Copy link
Contributor

@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

♻️ Duplicate comments (1)
api-public/src/main/kotlin/gropius/schema/mutation/IssueMutations.kt (1)

623-655: Fix GraphQL docs: IssueBoardItem operations require MANAGE_ISSUES, not MANAGE_ISSUE_BOARDS.

The service implementation uses TrackablePermission.MANAGE_ISSUES for all IssueBoardItem operations (as confirmed by maintainer), but the GraphQL descriptions incorrectly state MANAGE_ISSUE_BOARDS. This was flagged in a previous review and still needs to be corrected.

Apply these documentation fixes:

     @GraphQLDescription(
-        """Creates a new Issue Board Item on an Issue Board. Requires MANAGE_ISSUE_BOARDS on the target Issue Board.
+        """Creates a new Issue Board Item on an Issue Board. Requires MANAGE_ISSUES on the board's Trackable.
         """
     )
-    @GraphQLDescription("Updates the specified Issue Board Item, Requires MANAGE_ISSUE_BOARDS on the parent trackable.")
+    @GraphQLDescription("Updates the specified Issue Board Item. Requires MANAGE_ISSUES on the board's Trackable.")
     @GraphQLDescription(
-        """Deletes the Issue Board Item, requires MANAGE_ISSUE_BOARDS on the parent trackable.
+        """Deletes the Issue Board Item. Requires MANAGE_ISSUES on the board's Trackable.
         """
     )
🧹 Nitpick comments (2)
core/src/main/kotlin/gropius/service/issue/IssueBoardService.kt (1)

29-35: Remove extra blank lines in constructor.

The extra blank lines between parameters and constructor body are inconsistent with typical Kotlin formatting conventions.

 @Service
 class IssueBoardService(
     repository: IssueBoardRepository,
     private val trackableRepository: TrackableRepository,
     private val nodeRepository: NodeRepository
-
-
 ) : NamedNodeService<IssueBoard, IssueBoardRepository>(repository) {
core/src/main/kotlin/gropius/service/issue/IssueBoardItemService.kt (1)

31-36: Remove extra blank line in constructor.

Minor formatting nit: remove the extra blank line before the closing parenthesis.

 @Service
 class IssueBoardItemService(
     repository: IssueBoardItemRepository,
     private val issueBoardRepository: IssueBoardRepository,
     private val issueRepository: IssueRepository
-
 ) : NodeService<IssueBoardItem, IssueBoardItemRepository>(repository) {
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1cfafc8 and bc25578.

📒 Files selected for processing (5)
  • api-public/src/main/kotlin/gropius/schema/mutation/IssueMutations.kt (3 hunks)
  • core/src/main/kotlin/gropius/dto/input/issue/RemoveIssueStateFromBoardColumnInput.kt (1 hunks)
  • core/src/main/kotlin/gropius/service/issue/IssueBoardColumnService.kt (1 hunks)
  • core/src/main/kotlin/gropius/service/issue/IssueBoardItemService.kt (1 hunks)
  • core/src/main/kotlin/gropius/service/issue/IssueBoardService.kt (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • core/src/main/kotlin/gropius/dto/input/issue/RemoveIssueStateFromBoardColumnInput.kt
  • core/src/main/kotlin/gropius/service/issue/IssueBoardColumnService.kt
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: nk-coding
Repo: ccims/gropius-backend PR: 159
File: core/src/main/kotlin/gropius/service/issue/IssueBoardItemService.kt:103-103
Timestamp: 2025-08-04T13:05:27.476Z
Learning: In the IssueBoardItemService class in core/src/main/kotlin/gropius/service/issue/IssueBoardItemService.kt, the permission TrackablePermission.MANAGE_ISSUES is intentionally used instead of MANAGE_ISSUE_BOARDS for managing issue board items, as these operations are considered issue management rather than board structure management.
Learnt from: nk-coding
Repo: ccims/gropius-backend PR: 159
File: core/src/main/kotlin/gropius/service/issue/IssueBoardItemService.kt:79-79
Timestamp: 2025-08-04T13:05:27.239Z
Learning: IssueBoardItem operations (create, update, delete) should use TrackablePermission.MANAGE_ISSUES permission instead of TrackablePermission.MANAGE_ISSUE_BOARDS, as confirmed by the project maintainer nk-coding.
📚 Learning: 2025-08-04T13:05:27.476Z
Learnt from: nk-coding
Repo: ccims/gropius-backend PR: 159
File: core/src/main/kotlin/gropius/service/issue/IssueBoardItemService.kt:103-103
Timestamp: 2025-08-04T13:05:27.476Z
Learning: In the IssueBoardItemService class in core/src/main/kotlin/gropius/service/issue/IssueBoardItemService.kt, the permission TrackablePermission.MANAGE_ISSUES is intentionally used instead of MANAGE_ISSUE_BOARDS for managing issue board items, as these operations are considered issue management rather than board structure management.

Applied to files:

  • core/src/main/kotlin/gropius/service/issue/IssueBoardItemService.kt
  • api-public/src/main/kotlin/gropius/schema/mutation/IssueMutations.kt
  • core/src/main/kotlin/gropius/service/issue/IssueBoardService.kt
📚 Learning: 2025-08-04T13:05:27.239Z
Learnt from: nk-coding
Repo: ccims/gropius-backend PR: 159
File: core/src/main/kotlin/gropius/service/issue/IssueBoardItemService.kt:79-79
Timestamp: 2025-08-04T13:05:27.239Z
Learning: IssueBoardItem operations (create, update, delete) should use TrackablePermission.MANAGE_ISSUES permission instead of TrackablePermission.MANAGE_ISSUE_BOARDS, as confirmed by the project maintainer nk-coding.

Applied to files:

  • core/src/main/kotlin/gropius/service/issue/IssueBoardItemService.kt
  • api-public/src/main/kotlin/gropius/schema/mutation/IssueMutations.kt
  • core/src/main/kotlin/gropius/service/issue/IssueBoardService.kt
🧬 Code graph analysis (2)
core/src/main/kotlin/gropius/service/issue/IssueBoardItemService.kt (1)
core/src/main/kotlin/gropius/dto/input/issue/CreateIssueBoardItemInput.kt (1)
  • issueBoard (7-16)
core/src/main/kotlin/gropius/service/issue/IssueBoardService.kt (1)
core/src/main/kotlin/gropius/service/common/NamedNodeService.kt (1)
  • updateNamedNode (26-33)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build
🔇 Additional comments (7)
core/src/main/kotlin/gropius/service/issue/IssueBoardService.kt (2)

46-62: LGTM!

The createIssueBoard method correctly validates input, checks permissions on the trackable, and associates the new board with its trackable before saving.


97-113: LGTM!

The cascade deletion approach explicitly collecting columns, items, and the board before batch deletion is clear and ensures all related entities are properly cleaned up.

core/src/main/kotlin/gropius/service/issue/IssueBoardItemService.kt (2)

46-71: LGTM!

The trackable membership validation (lines 60-62) correctly ensures the issue belongs to the board's trackable before creating the board item. The MANAGE_ISSUES permission is intentional for item operations. Based on learnings, this is the correct permission as these are considered issue management rather than board structure management.


82-121: LGTM!

Both updateIssueBoardItem and deleteIssueBoardItem follow consistent patterns with proper authorization checks using MANAGE_ISSUES permission.

api-public/src/main/kotlin/gropius/schema/mutation/IssueMutations.kt (3)

31-34: LGTM!

New service dependencies are properly injected for the Issue Board feature.


526-557: LGTM!

The IssueBoard mutations correctly document MANAGE_ISSUE_BOARDS permission requirement, which aligns with the service implementation.


559-621: LGTM!

The IssueBoardColumn mutations are well-structured with appropriate GraphQL descriptions. The permission documentation for MANAGE_ISSUE_BOARDS appears consistent with board structure management.

@nk-coding nk-coding self-requested a review December 13, 2025 16:45
Copy link
Contributor

@nk-coding nk-coding left a comment

Choose a reason for hiding this comment

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

There is still one comment which is not done
see #159 (comment)
While the text was changed, it still specifies the wrong permission (manage boards instead of manage issues), also, it now incorrectly states where the permission is required (the permission is actually required in the parent trackable, not the board itself)
pls fix

Copy link
Contributor

@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)
api-public/src/main/kotlin/gropius/schema/mutation/IssueMutations.kt (1)

644-644: Remove extra blank line.

There's an unnecessary extra blank line here. Other mutations in the file are separated by a single blank line.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bc25578 and a117c55.

📒 Files selected for processing (1)
  • api-public/src/main/kotlin/gropius/schema/mutation/IssueMutations.kt (3 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: nk-coding
Repo: ccims/gropius-backend PR: 159
File: core/src/main/kotlin/gropius/service/issue/IssueBoardItemService.kt:79-79
Timestamp: 2025-08-04T13:05:27.239Z
Learning: IssueBoardItem operations (create, update, delete) should use TrackablePermission.MANAGE_ISSUES permission instead of TrackablePermission.MANAGE_ISSUE_BOARDS, as confirmed by the project maintainer nk-coding.
Learnt from: nk-coding
Repo: ccims/gropius-backend PR: 159
File: core/src/main/kotlin/gropius/service/issue/IssueBoardItemService.kt:103-103
Timestamp: 2025-08-04T13:05:27.476Z
Learning: In the IssueBoardItemService class in core/src/main/kotlin/gropius/service/issue/IssueBoardItemService.kt, the permission TrackablePermission.MANAGE_ISSUES is intentionally used instead of MANAGE_ISSUE_BOARDS for managing issue board items, as these operations are considered issue management rather than board structure management.
📚 Learning: 2025-08-04T13:05:27.476Z
Learnt from: nk-coding
Repo: ccims/gropius-backend PR: 159
File: core/src/main/kotlin/gropius/service/issue/IssueBoardItemService.kt:103-103
Timestamp: 2025-08-04T13:05:27.476Z
Learning: In the IssueBoardItemService class in core/src/main/kotlin/gropius/service/issue/IssueBoardItemService.kt, the permission TrackablePermission.MANAGE_ISSUES is intentionally used instead of MANAGE_ISSUE_BOARDS for managing issue board items, as these operations are considered issue management rather than board structure management.

Applied to files:

  • api-public/src/main/kotlin/gropius/schema/mutation/IssueMutations.kt
📚 Learning: 2025-08-04T13:05:27.239Z
Learnt from: nk-coding
Repo: ccims/gropius-backend PR: 159
File: core/src/main/kotlin/gropius/service/issue/IssueBoardItemService.kt:79-79
Timestamp: 2025-08-04T13:05:27.239Z
Learning: IssueBoardItem operations (create, update, delete) should use TrackablePermission.MANAGE_ISSUES permission instead of TrackablePermission.MANAGE_ISSUE_BOARDS, as confirmed by the project maintainer nk-coding.

Applied to files:

  • api-public/src/main/kotlin/gropius/schema/mutation/IssueMutations.kt
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build
🔇 Additional comments (5)
api-public/src/main/kotlin/gropius/schema/mutation/IssueMutations.kt (5)

12-14: LGTM: Wildcard imports are consistent with existing file style.

The wildcard imports for model and service packages align with the existing wildcard import pattern at line 8.


31-34: LGTM: Service dependencies properly injected.

The three new Issue Board services are correctly added to the constructor and follow the established dependency injection pattern.


526-557: LGTM: IssueBoard mutations correctly implemented.

The create, update, and delete mutations for IssueBoard properly use MANAGE_ISSUE_BOARDS permission and follow the established mutation patterns in this file.


559-621: LGTM: IssueBoardColumn mutations correctly implemented.

All column-related mutations properly use MANAGE_ISSUE_BOARDS permission and follow consistent patterns. The add/remove state operations appropriately return the updated column.


623-655: Permission descriptions correctly updated per maintainer guidance.

The IssueBoardItem mutation descriptions now correctly specify MANAGE_ISSUES instead of MANAGE_ISSUE_BOARDS, which aligns with the service implementation and maintainer confirmation. The wording "parent Trackable" is clear and semantically correct.

Based on learnings, IssueBoardItem operations are considered issue management rather than board structure management, so MANAGE_ISSUES is the appropriate permission.

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.

3 participants