feat(core): add entity graph endpoint and service#56
Conversation
add include data parameter for showing properties in node
add include flag for getting properties or not in graph repository call
|
| GitGuardian id | GitGuardian status | Secret | Commit | Filename | |
|---|---|---|---|---|---|
| 30005138 | Triggered | Generic Password | 1c6cca0 | src/test/java/com/decathlon/idp_core/AbstractIntegrationTest.java | View secret |
🛠 Guidelines to remediate hardcoded secrets
- Understand the implications of revoking this secret by investigating where it is used in your code.
- Replace and store your secret safely. Learn here the best practices.
- Revoke and rotate this secret.
- If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.
To avoid such incidents in the future consider
- following these best practices for managing and storing secrets including API keys and other credentials
- install secret detection on pre-commit to catch secret before it leaves your machine and ease remediation.
🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.
Code Coverage OverviewLanguages: Java Java / code-coverage/jacocoThe overall coverage in the branch is 89%. Coverage data for the branch is not yet available. Show a code coverage summary of the most covered files.
Updated |
|



PR Description
What this PR Provides
This pull request introduces add new domain models and ports for entity graph traversal. Additionally, the package structure is refined to organize exceptions and services by subdomain.
Entity Graph Modeling
EntityGraphNodeandEntityGraphRelation, supporting hierarchical visualization and traversal of entity relationships.EntityGraphRepositoryPort, defines the contract for retrieving entity relationship graphs with support for depth, property inclusion, and efficient lookups.Domain Model Enhancements
Code Consistency
These changes collectively improve the robustness, clarity, and scalability of the domain layer.
Fixes
Review
The reviewer must double-check these points:
!after the type/scope to identify the breakingchange in the release note and ensure we will release a major version.
How to test
This guide explains how to manually test the entity graph feature without assuming any pre-existing data. You will set up a 5-node graph structure to validate all filtering capabilities and the edge-case boundaries of the Traversal Mode mechanics.
Graph Structure Required
To thoroughly test all directionality modes—especially the sibling-exclusion rules of DIRECT_LINEAGE—you need a graph with the following characteristics:
Entities
Create 5 entities:
Entity X (Upstream Parent/Consumer) - points into our root node, and also points into a sibling node.
Entity A (Root Node) - the designated entry point for your test queries.
Entity B (Middle Downstream Node) - connected downstream from A, upstream from C.
Entity C (Leaf Downstream Node) - furthest downstream node from the root path.
Entity Y (Sibling Node) - an independent downstream node also connected to Entity X. This node must be excluded during Direct Lineage queries from Entity A.
Properties
Each entity should have 2 properties to test property filtering:
Property 1 - e.g., tier, environment, status
Property 2 - e.g., version, owner, region
Use different values for each entity so you can verify that property data maps accurately.
Relations
Create 2 types of relations to test relation filtering and directionality:
Relation Type 1 - forward dependency chain (X → A → B → C) and the sibling link (X → Y).
Relation Type 2 - a secondary alternative forward path (A → B).
Graph topology:
Plaintext
+--[Relation-Type-1]----> Entity Y (Should be excluded in DIRECT_LINEAGE from A)
|
Entity X ---+--[Relation-Type-1]----> Entity A --[Relation-Type-1]----> Entity B --[Relation-Type-1]----> Entity C
Entity A --[Relation-Type-2]----> Entity B
✅ Scenario 1: Traversal Mode = BIDIRECTIONAL
Goal: Walk full relationships recursively across all nodes, collecting every forward (outbound) and backward (inbound) edge adjacent to any discovered node in the tree pool.
Request:
HTTP GET /api/v1/entities/{template}/{entityA}/graph?depth=3&include_data=false&traversal_mode=BIDIRECTIONAL
Expected Behavior:
Returns all 5 nodes (A, B, C, X, and Y).
From Entity A: Returns outbound links to B (type-1 & type-2) and its inbound link from X (type-1).
From Entity X: Returns outbound links to both A and Y. Because it goes bidirectional, it discovers Entity Y.
From Entity Y: Returns its inbound link from X.
What to verify:
Full global network transparency: relations (outbound) and relationsAsTarget (inbound) fields are populated for every node within the matching depth radius, including the sibling branch (Entity Y).
✅ Scenario 2: Traversal Mode = OUTBOUND_ONLY
Goal: Strictly follow forward dependency links downstream from the root entity. Upstream consumers and side branches must be entirely omitted.
Request:
HTTP GET /api/v1/entities/{template}/{entityA}/graph?depth=3&include_data=false&traversal_mode=OUTBOUND_ONLY
Expected Behavior:
Returns 3 nodes (A, B, C).
Excludes Entity X and Entity Y entirely (since they do not sit downstream from A).
From Entity A: Returns outbound edges to B.
From Entity B: Returns outbound edge to C.
The relationsAsTarget (inbound) arrays are completely empty for all nodes in the response.
What to verify:
Node count = 3 (Entity X and Y are missing).
No inbound array properties are populated anywhere in the payload.
✅ Scenario 3: Traversal Mode = DIRECT_LINEAGE
Goal: Isolate explicit routing paths by keeping outbound lines downstream and inbound lines upstream. This scenario explicitly validates that sideways/sibling "noise" (Entity Y) is pruned out.
Request:
HTTP GET /api/v1/entities/{template}/{entityA}/graph?depth=3&include_data=false&traversal_mode=DIRECT_LINEAGE
Expected Behavior:
Returns 4 nodes (A, B, C, X).
CRITICAL EXCLUSION: Entity Y is completely excluded from the response. Even though Entity X is fetched (as A's inbound parent), the engine does not follow X's other outbound paths down to sibling nodes.
From Entity A (Root): Shows both its outbound paths (to B) and its inbound paths (from X).
From Entity X: Shows outbound to A, but its relationship array to Y is omitted or ignored for traversal.
From Entity B & C: Evaluates only their outbound paths further down.
What to verify:
High-fidelity lineage line tracing: Node count = 4. Verify Entity Y is completely absent from the graph array pool.
🔍 Relation & Property Filtering Testing
✅ Scenario 4: Full Graph (No Filters)
Goal: Return nodes and edges using default traversal context.
Request:
HTTP GET /api/v1/entities/{template}/{entityA}/graph?depth=3&include_data=false
What to verify:
Each edge has correct source, target, and type based on the system's default mode.
✅ Scenario 5: Filter by Relation Type 1
Goal: Only traverse edges of Relation-Type-1.
Request:
HTTP GET /api/v1/entities/{template}/{entityA}/graph?depth=3&include_data=false&relations=relation-type-1
Expected Behavior:
Traverses along the type-1 network route chain.
Excludes the A→B type-2 edge from the resulting structures.
✅ Scenario 6: Filter by Relation Type 2
Goal: Only traverse edges of Relation-Type-2 out from the root.
Request:
HTTP GET /api/v1/entities/{template}/{entityA}/graph?depth=3&include_data=false&relations=relation-type-2
Expected Behavior:
Returns 2 nodes (A, B only).
Returns 1 edge (A→B type-2).
Excludes Entities C, X, and Y (since they are not linked via type-2 relations from the root traversal track).
✅ Scenario 7: Include All Properties
Goal: Return property data for all discovered nodes.
Request:
HTTP GET /api/v1/entities/{template}/{entityA}/graph?depth=3&include_data=true
Expected Behavior:
Discovered nodes contain a populated data object with both property-1 and property-2 keys.
Example node structure:
{ "id": "template:entityA", "templateIdentifier": "template", "identifier": "entityA", "name": "Entity A Name", "data": { "property-1": "value-a-1", "property-2": "value-a-2" } }✅ Scenario 8: Filter Property 1 Only
Goal: Return only property-1 in node data payloads.
Request:
HTTP GET /api/v1/entities/{template}/{entityA}/graph?depth=3&include_data=true&properties=property-1
Expected Behavior:
Each node's data object contains only property-1.
property-2 is completely excluded from the response object keys (not set to null).
✅ Scenario 9: Non-Existent Property Filter
Goal: Request a property key name that doesn't exist on any system template definition.
Request:
HTTP GET /api/v1/entities/{template}/{entityA}/graph?depth=3&include_data=true&properties=non-existent-property
Expected Behavior:
Returns matching nodes without a data field block. The data key is entirely omitted from the JSON dictionary.
✅ Scenario 10: Combine Relation + Property Filters
Goal: Apply both relation type and property selection restrictions simultaneously.
Request:
HTTP GET /api/v1/entities/{template}/{entityA}/graph?depth=3&include_data=true&relations=relation-type-1&properties=property-1
Expected Behavior:
Returns only nodes and edges found along the relation-type-1 path.
Each returned node contains a data block containing only property-1.
❌ Error Boundary Validation
❌ Scenario 11: Entity Not Found
Request:
HTTP GET /api/v1/entities/{template}/non-existent-entity/graph?depth=3&include_data=false
Expected Behavior:
HTTP 404 Not Found with a clear response body stating the entity identifier does not exist.
❌ Scenario 12: Template Not Found
Request:
HTTP GET /api/v1/entities/non-existent-template/{entityA}/graph?depth=3&include_data=false
Expected Behavior:
HTTP 404 Not Found. Fail-fast validation catches that the template does not exist before executing any database lookups.
Breaking changes (if any)