Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -472,14 +472,12 @@ Validation is delegated to a list of `ValidationStrategy` implementations select
| `XmlSchemaValidationStrategy` | XML | `XML_SCHEMA`
|===

`ShaclValidationStrategy` delegates to `ShaclValidationExecutor` β€” the same SHACL evaluation engine used during the upload verification path. This ensures consistent SHACL results across both flows.
`ShaclValidationStrategy` evaluates SHACL constraints directly via the TopBraid SHACL engine β€” the same engine invoked by `SchemaValidationServiceImpl` on the upload verification path. Both paths run the engine in-line on the request thread.

RDF asset content is parsed by `RdfAssetParser`, which unwraps Loire JWTs before parsing and delegates format detection to `CredentialFormatDetector` (JSON-LD, Turtle, N-Triples, RDF/XML). Validation results are persisted via `ValidationResultStore` (see <<_validation_result_storage>>).

Multi-asset requests (`assetIds` with more than one entry) are restricted to SHACL validation: all asset models are merged into a single data graph before evaluation. Single-asset requests dispatch to all applicable enabled strategies. The maximum number of assets per request is controlled by `federated-catalogue.validation.max-assets-per-request` (default: 20).

`ShaclValidationExecutor` runs TopBraid SHACL in an isolated fixed-size thread pool and enforces a hard timeout. Both are configurable: `federated-catalogue.validation.shacl.timeout-seconds` (default: 10) and `federated-catalogue.validation.shacl.pool-size` (default: 4). Requests that exceed the timeout receive a `TimeoutException` (HTTP 504).

Validation results are persisted in the `validation_result` table.
Results carry an `outdated` flag and an `OutdatedReason` that records why a result is no longer current:

Expand Down Expand Up @@ -803,7 +801,7 @@ The `AssetStore` provides two parallel access paths: **hash-based** methods (int
| `storeUnverified(metadata, filename)` | Store a non-RDF asset; IRI is pre-assigned by `IriGenerator`
|===

The `deleteAsset(hash)` and `changeLifeCycleStatus(hash, status)` methods are the deliberate exceptions β€” both remain hash-based to guarantee unambiguous single-row targeting. See ADR 7, Hash-Based Mutation Operations Exception. `deleteAsset` publishes an `AssetDeletedEvent` after the row deletion, triggering cascade cleanup of all associated validation results (see <<_validation_result_storage>>).
The `deleteAsset(hash)` and `changeLifeCycleStatus(hash, status)` methods are the deliberate exceptions β€” both remain hash-based to guarantee unambiguous single-row targeting. See ADR 7, Hash-Based Mutation Operations Exception. `deleteAsset` publishes an `AssetDeletedEvent` after the row deletion, triggering cascade cleanup of associated validation results and provenance credentials (see <<_validation_result_storage>>).

The `IriGenerator` assigns IRIs before storage: it extracts IRIs from RDF content (`credentialSubject.id`, `@id`, ontology/shapes/vocabulary IRIs) or generates UUID URNs (RFC 4122) for non-RDF assets and as fallback. The `IriValidator` checks all assigned IRIs against supported formats (DIDs, UUID URNs, generic URNs, HTTP/HTTPS IRIs) β€” returning `true`/`false`. Callers decide how to handle invalid IRIs (fallback to UUID URN, or reject the request).

Expand Down Expand Up @@ -908,7 +906,12 @@ The two REST endpoints for validation result retrieval are:

After a graph backend reset, `GraphRebuilder.rebuildValidationResults()` re-projects all validation result records as `fcmeta:` triples from PostgreSQL, restoring graph state without re-running verification. Each record is updated to `SYNCED` on success or `FAILED` if the graph write fails.

**Asset deletion cascade:** When an asset is deleted, `AssetStoreImpl` publishes an `AssetDeletedEvent`. `ValidationResultCleanupListener` handles this event at `BEFORE_COMMIT`, deleting all validation result rows that reference the asset from both the relational DB and the graph store. The cleanup runs inside the same transaction as the asset deletion β€” either both the asset row and its validation results are removed, or neither is. The `ValidationResultStore.deleteByAssetId()` method handles the graph triple removal best-effort: a failed graph cleanup is logged but does not abort the transaction.
**Asset deletion cascade:** When an asset is deleted, `AssetStoreImpl` publishes an `AssetDeletedEvent`. Two `@TransactionalEventListener(BEFORE_COMMIT)` consumers run inside the same transaction as the asset deletion:

* `ValidationResultCleanupListener` invokes `ValidationResultStore.deleteByAssetId()` to remove validation result rows from the relational DB and best-effort cascade-delete the associated graph triples (a failed graph cleanup is logged but does not abort the transaction).
* `ProvenanceCleanupListener` invokes `ProvenanceService.deleteByAssetId()` to remove provenance credential rows from `provenance_credentials`.

Either all three (asset row, validation results, provenance credentials) are removed, or none is. The listener pattern keeps the `assetstore` bounded context free of direct dependencies on the validation and provenance services.

==== Schema Management Store

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ Notes:
Parti ->> + AssetStore: deleteAsset(assetHash)
AssetStore ->> + Graph: deleteClaims()
Graph -->> - AssetStore:Null
Note over AssetStore: AssetDeletedEvent is published before commit;<br/>ValidationResultCleanupListener cascades<br/>removal of validation results β€” see _validation_result_storage.
Note over AssetStore: AssetDeletedEvent is published before commit;<br/>ValidationResultCleanupListener cascades removal of validation results<br/>and ProvenanceCleanupListener cascades removal of provenance credentials β€”<br/>see _validation_result_storage.
AssetStore -->> - Parti: Null

Parti ->> + Keycloak: DELETE /realms/gaia-x/groups/{partID}
Expand Down Expand Up @@ -1325,7 +1325,7 @@ Besides verifying the credential, additional tasks are executed (e.g., format de

**Schema validation** (when enabled) checks the uploaded credentials against a composite schema of type SHACL.
If a credential does not conform to the composite schema, a verification exception is thrown with a message containing the validation report. In that case, the verification process does not proceed, and claims are not extracted.
Automatic schema validation against stored SHACL shapes is **disabled by default in the upload verification flow** and is gated by `federated-catalogue.verification.schema`. When enabled, upload verification still routes through `SchemaValidationService` (see <<_schema_validation_service>>). On-demand validation of stored assets β€” covering SHACL, JSON Schema, and XML Schema β€” is provided by the dedicated `AssetValidationService` (see <<_on_demand_asset_validation>>); both flows share the same `ShaclValidationExecutor` for SHACL evaluation.
Automatic schema validation against stored SHACL shapes is **disabled by default in the upload verification flow** and is gated by `federated-catalogue.verification.schema`. When enabled, upload verification still routes through `SchemaValidationService` (see <<_schema_validation_service>>). On-demand validation of stored assets β€” covering SHACL, JSON Schema, and XML Schema β€” is provided by the dedicated `AssetValidationService` (see <<_on_demand_asset_validation>>); both flows evaluate SHACL via the same TopBraid SHACL engine.

NOTE: For backward compatibility, automatic schema validation during upload can be re-enabled via the configuration property `federated-catalogue.verification.schema=true`.

Expand Down