Incorrect inverse relationship type in CRE internal-link export
Los mantenedores suelen responder en 1 día
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 2/5
- Tiempo estimado
- 1-3 horas
- Aptitud para principiantes
- 78/100
Línea de trabajo
Empieza con Node_collection.export() en application/database/db.py y compara cómo maneja los enlaces del lado hijo con _assemble_cre_internal_links() y LinkTypes.opposite() en application/defs/cre_defs.py. Actualiza test_export() en application/tests/db_test.py para que espere PartOf y compare los valores anidados de ambos documentos exportados. La tarea estará terminada cuando el enlace del hijo sea PartOf, el del padre siga siendo Contains y la prueba específica de exportación verifique ambos.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Description
In application/database/db.py, Node_collection.export() serializes child-to-parent internal CRE links with the same Contains relationship type as the parent-to-child direction, rather than serializing the inverse relationship type (Is Part Of).
As a result, exported child CRE YAML files claim to "Contain" their parent CRE instead of stating that they are "Part Of" their parent.
Expected Behavior
When an internal parent-child relationship is exported:
- Parent CRE → Child CRE:
Contains(ltype: Contains) - Child CRE → Parent CRE:
Is Part Of(ltype: Is Part Of, representingLinkTypes.PartOf)
A parent contains a child, and the child is part of the parent.
Actual Behavior
Both exported YAML files are serialized with ltype: Contains. The child document's link back to its parent explicitly states ltype: Contains.
Reproduction Steps
-
Check out the current upstream commit:
- Repository:
OWASP/OpenCRE - Commit:
ace5f0bdc4031ed805fd550d13f6a5931a91606d(main)
- Repository:
-
Run the existing database export unit test:
python -m unittest application.tests.db_test.TestDB.test_export -v -
Observe test result:
The test passes (Ran 1 test in ... OK). -
Inspect the generated YAML files written to the temporary directory (
111-000.yamland111-001.yaml). -
Observe the child-side relationship in
111-000.yaml:
Its link to parent111-001(GroupName) is serialized asltype: Contains.
Evidence
Parent File (111-001.yaml) — Line 6
description: Groupdesc
doctype: CRE
id: 111-001
links:
- document:
description: CREdesc
doctype: CRE
id: 111-000
name: CREname
ltype: Contains
name: GroupName
Child File (111-000.yaml) — Line 6 (Defect)
description: CREdesc
doctype: CRE
id: 111-000
links:
- document:
description: Groupdesc
doctype: CRE
id: 111-001
name: GroupName
ltype: Contains
name: CREname
Technical Analysis
1. Database Storage vs. Export Logic
In application/database/db.py:
- Internal CRE relationships are stored in the
cre_linkstable (InternalLinksmodel), wheregroupstores the parent ID,crestores the child ID, andtypeis"Contains". - In
Node_collection.export()(lines 2210–2236), the internal link loop handles both directions:- Parent side (lines 2218–2222):
grp.add_link( cre_defs.Link( ltype=cre_defs.LinkTypes.from_str(type), document=CREfromDB(cre) ) ) - Child side (lines 2232–2236):
c.add_link( cre_defs.Link( ltype=cre_defs.LinkTypes.from_str(type), document=CREfromDB(group) ) )
typeis passed directly without inverting, both documents receiveContains. - Parent side (lines 2218–2222):
2. Inconsistency with Hydration Path
In the same file, the read/hydration method _assemble_cre_internal_links() (lines 2162–2172) already implements the correct inverse mapping when reading internal links for a child CRE:
if internal_link.cre == cre.id:
linked_cre = cres_by_id.get(internal_link.group)
if not linked_cre:
continue
if link_type == cre_defs.LinkTypes.Contains:
links.append(
cre_defs.Link(
ltype=cre_defs.LinkTypes.PartOf,
document=CREfromDB(linked_cre),
)
)
The export path diverges from this existing hydration logic.
3. Enum Mapping Available
application/defs/cre_defs.py defines LinkTypes.opposite() (lines 219–235), which explicitly defines Contains and PartOf as mutual inverses:
if typ == cls.Contains:
return cls.PartOf
elif typ == cls.PartOf:
return cls.Contains
However, export() never calls this helper.
4. Why test_export() Misses the Issue
The test test_export() in application/tests/db_test.py passes due to two factors:
- Fixture expectation (line 263):
expected[1]explicitly specifiesltype=defs.LinkTypes.Containsfor the child's link back to the parent, encoding the defect into the expected test data. - Assertion method (line 321): While the parent document is checked using
self.assertDictEqual(group, doc)(line 311), the child document is checked usingself.assertCountEqual(cre, doc)(line 321). In Python'sunittest, callingassertCountEqualon dictionaries compares dictionary keys (['doctype', 'id', 'description', 'name', 'links']) rather than nested values. As long as top-level keys match, the assertion succeeds without validating link types.
Suggested Fix
- Update
Node_collection.export()to serialize the reverse side of directional internal relationships using the corresponding inverse relationship type. For example,Containsshould becomePartOfwhen exporting the child-to-parent link. - Preserve relationship types that are symmetric, according to their defined semantics.
- Update
test_export()to expectLinkTypes.PartOffor the child-to-parent relationship. - Use deep dictionary comparisons for both exported documents so that nested relationship types are validated.
- Lenguaje dominante
- Python
- Estrellas
- 210
- Forks
- 167
- Merge medio
- 4 d 12 h
- PR fusionados (30 d)
- 28
Preparar el entorno
Inicia el contenedor de desarrollo del proyecto en tu navegador, con tu propia cuenta de GitHub.
- Incluye un Dockerfile o un archivo de Docker Compose
- Sin plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de OWASP/OpenCRE
-
Map Analysis continues polling after a background job failsPosiblemente ocupada @amantebriwal4321 la tomó hace 4 días. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 84/100
OWASP/OpenCRE#1211 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
OSCAL Compass adopterAbierto
Dificultad 1/5 Menos de una hora Aptitud para principiantes 66/100
Los mantenedores suelen responder en 1 día
-
MCP tools return "Internal MCP tool error." when OpenCRE is unreachable or times outPosiblemente ocupada @ShaanGS la tomó hace 23 días. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
OWASP/OpenCRE#1163 · 5 comentarios ·
Los mantenedores suelen responder en 1 día
-
find_node_by_name endpoint does not enforce MAX_ITEMS_PER_PAGE, allowing unbounded pagination queries`Posiblemente ocupada @Jeffy123-zhu la tomó hace 26 días. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 88/100
OWASP/OpenCRE#1149 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
Information disclosure via filesystem existence oracle in web_main.py catch-all routePosiblemente ocupada @0x5t4l1n la tomó hace 39 días. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
OWASP/OpenCRE#1112 · 2 comentarios ·
Los mantenedores suelen responder en 1 día
Todos los issues de OWASP/OpenCRE
Issues similares
-
Unknown stop ID in slow zone data crashes post formatting and skips the rest of that day's postsAbiertobackend bug tm-new-volunteer
Dificultad 2/5 1-3 horas Aptitud para principiantes 84/100
transitmatters/mbta-slow-zone-bot#81 · 1 comentario ·
-
area:schema documentation
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
Los mantenedores suelen responder en 1 día
-
risk:high type:ci
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 64/100
spacetelescope/rdmt-spire#49 ·
Los mantenedores suelen responder en 1 día