You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: federated-catalogue/src/docs/architecture/chapters/04_solution_strategy.adoc
+3-1Lines changed: 3 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -126,7 +126,9 @@ Non-RDF schemas are uploaded and managed through the same `/schemas` endpoint as
126
126
* **RDF content types** (`application/rdf+xml`, `application/ld+json`, `text/turtle`) are processed by the `SchemaStore` — parsed as RDF, type-detected, and subject to the integrity constraints described above.
127
127
* **Non-RDF content types** (`application/schema+json`, `application/xml`) bypass RDF parsing entirely. The raw file is stored in the schema File Store, and metadata (content type, upload timestamp) is persisted in the Metadata Store. An auto-generated identifier (`urn:schema:sha256:<hash>`) is assigned based on content hash, providing deduplication.
128
128
129
-
Non-RDF schemas appear in the schema listing (`GET /schemas`) under their own type categories (`jsonSchemas`, `xmlSchemas`) and can be retrieved, replaced, and deleted through the standard schema CRUD endpoints. However, they are **not used for automatic SHACL verification** of credentials — they serve as stored reference schemas for external tooling or manual validation.
129
+
Non-RDF schemas appear in the schema listing (`GET /schemas`) under their own type categories (`jsonSchemas`, `xmlSchemas`) and can be retrieved, replaced, and deleted through the standard schema CRUD endpoints. They are **not used for automatic SHACL verification** of credentials, but the on-demand validation endpoint (`POST /assets/validate`) does invoke the corresponding validator for non-RDF assets — JSON Schema for `application/json` assets, XML Schema for `application/xml` assets — when the caller selects a matching schema.
130
+
131
+
Each of the four schema languages exposed through `/schemas` (SHACL, JSON Schema, XML Schema, OWL) has an administrative on/off toggle managed through the admin schema-modules page; see ADR 16 for the toggle semantics and the asymmetric role of the OWL toggle (which gates role resolution rather than a validator).
130
132
131
133
==== Schema Validation Checks
132
134
Each schema before adding it, will be analysed. The Analysis process should check first
Copy file name to clipboardExpand all lines: federated-catalogue/src/docs/architecture/chapters/05_building_block_view.adoc
+21-3Lines changed: 21 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1549,6 +1549,8 @@ flowchart TB
1549
1549
style EXT fill:#e3f2fd,stroke:#42a5f5
1550
1550
....
1551
1551
1552
+
NOTE: The `Schema validation enabled?` branch combines two gates. The caller's `verifySchema` request parameter selects whether SHACL runs at all; the administrative SHACL module toggle (see ADR 16) then gates that branch independently. When `verifySchema=true` and SHACL is administratively disabled, the request short-circuits with `400 Bad Request` body `module_disabled:SHACL` before reaching the SHACL composite. The same pattern applies on the on-demand validation endpoint via `AssetValidationServiceImpl`.
1553
+
1552
1554
===== Docker Compose configuration
1553
1555
1554
1556
The default profile uses `docker-compose.yml` with `dev.env`. The strict profile adds the `docker-compose.strict.yml` overlay, which sets all verification flags to `true`:
@@ -1725,7 +1727,7 @@ Five delegate services in `fc-service-server` implement the admin endpoints, eac
| `TrustFrameworkAdminService` | `TrustFrameworkAdminApiDelegate` | List, toggle, and update trust frameworks; checks live connectivity per framework on list
1728
-
| `SchemaValidationAdminService` | `SchemaValidationAdminApiDelegate` | List schema modules (SHACL, JSON Schema, XML Schema, OWL) with toggle and schema counts. SHACL, JSON Schema, and XML Schema toggles are enforced by on-demand validation (`POST /assets/validate`) via `AssetValidationService`; in upload verification, only SHACL is consulted. OWL toggles persist to `admin_config` but are not yet wired to any validation pipeline
1730
+
| `SchemaValidationAdminService` | `SchemaValidationAdminApiDelegate` | List schema modules (SHACL, JSON Schema, XML Schema, OWL) with toggle and schema counts; toggle each module on/off; expose the per-ontology subclass contribution to each registered role for the OWL module. SHACL, JSON Schema, and XML Schema toggles are enforced by on-demand validation (`POST /assets/validate`) via `AssetValidationService` and return `400 module_disabled:<MODULE>` when off; in upload verification only SHACL is consulted, with the same error contract. The OWL toggle gates the runtime composite-ontology subclass walk in `CredentialVerificationStrategy.resolveRole` (see ADR 16)
1729
1731
| `GraphDatabaseAdminService` | `GraphDatabaseAdminApiDelegate` | Return current graph DB status; persist preferred backend to `admin_config` (switch takes effect on restart)
1730
1732
|===
1731
1733
@@ -1735,14 +1737,30 @@ These components in `fc-service-core` read admin-controlled settings during norm
1735
1737
|===
1736
1738
| Component | Triggered by | Effect of admin configuration
1737
1739
| `LoirePolicyEnforcer` | Loire envelope processing (per request, via `LoireCredentialProcessor`) | Consults `TrustFrameworkService.isEnabled("gaia-x")` to decide whether Loire-specific policies (issuer `did:web` restriction, trust-chain validation) apply at all; reads `trust_anchor_url` from the bundle's `properties` for `x5u` trust-chain validation
1738
-
| `AssetValidationServiceImpl` | On-demand asset validation (`POST /assets/validate`) | Checks module state via `SchemaModuleConfigService` for `SHACL`, `JSON_SCHEMA`, and `XML_SCHEMA`. If a module is disabled, the corresponding validator path is skipped or rejected.
1739
-
| `CredentialVerificationStrategy` | Credential verification | Reads SHACL module state via `SchemaModuleConfigService` (cached with `@Cacheable` — hot path). Disabling SHACL returns HTTP 400 on schema validation requests. JSON Schema, XML Schema, and OWL toggles are persisted but not yet wired to the verification pipeline. The Gaia-X enabled flag is consulted via `TrustFrameworkService` (see `LoirePolicyEnforcer` above)
1740
+
| `AssetValidationServiceImpl` | On-demand asset validation (`POST /assets/validate`) | Checks module state via `SchemaModuleConfigService` for `SHACL`, `JSON_SCHEMA`, and `XML_SCHEMA`. If a module is disabled, the request is rejected with `ClientException` → `400 Bad Request`, body `module_disabled:<MODULE>` (see ADR 16).
1741
+
| `CredentialVerificationStrategy` | Credential verification | Reads SHACL and OWL module state via `SchemaModuleConfigService` (cached with `@Cacheable` — hot path). Disabling SHACL returns the same `400 module_disabled:SHACL` contract on requests with `verifySchema=true`. Disabling OWL bypasses the runtime composite-ontology subclass walk in `resolveRole`; credentials whose type is only reachable through that walk fall through to `ResolvedRole.UNKNOWN` and are rejected by the verification entry point with `400 Bad Request` (see ADR 16). JSON Schema and XML Schema toggles do not bite on this path today — every credential is JSON-LD or JWT-wrapped JSON-LD and routes to SHACL. The Gaia-X enabled flag is consulted via `TrustFrameworkService`.
1740
1742
|===
1741
1743
1742
1744
NOTE: The graph backend switch (`graphstore.preferred.backend`) is not yet implemented in the Admin UI — the preference is persisted to `admin_config` but switching backends currently requires a manual config update and service restart.
1743
1745
1744
1746
The `trust_frameworks` and `admin_config` tables that back this configuration layer are documented under <<section-concepts,Cross-cutting Concepts — Admin Configuration Persistence>>.
1745
1747
1748
+
===== Schema-module admin toggles
1749
+
1750
+
The admin schema-modules page (proxied from the demo portal to `GET /admin/schema-validation` on the catalogue) lists four toggleable modules — SHACL, JSON Schema, XML Schema, OWL — and surfaces an additional read-only endpoint, `GET /admin/schema-validation/ontologies`, backed by `OntologyImpactService`.
1751
+
1752
+
The four toggles fall into two semantic classes (ADR 16):
1753
+
1754
+
* **Validators (SHACL, JSON Schema, XML Schema)** gate the corresponding validator wherever the catalogue would otherwise run it (on-demand validation, and credential verification with `verifySchema=true`). When off, the affected request returns `400 Bad Request` body `module_disabled:<MODULE>`. Stored schemas remain queryable regardless of toggle state.
1755
+
1756
+
* **OWL** gates the third tier of role resolution. When off, the runtime composite-ontology subclass walk in `CredentialVerificationStrategy.resolveRole` is skipped; only the registry index and `additional_roots` (ADR 10) are consulted. Credentials whose type is only reachable through the subclass walk fall through to `ResolvedRole.UNKNOWN` and are rejected by the verification entry point with `400 Bad Request`. Registry-direct types are unaffected.
1757
+
1758
+
`OntologyImpactService` parses each `ONTOLOGY`-type schema row with Jena and counts the `rdfs:subClassOf+` descendants reachable from each registered role's root URI (plus any `additional_roots`), aggregated across active trust-framework bundles. The result is a read-only map of *(ontology id, role name) → subclass count* so operators can see what the OWL toggle is gating before flipping it off.
1759
+
1760
+
The result surfaces two signals the UI uses to keep the toggle decision honest. Each ontology row carries a `parseError` flag — true when the ontology fails to parse or the per-root subclass walk exceeds its two-second SPARQL timeout. The UI shows a warning row in that case so an admin does not read "zero contributions" as "safe to disable OWL"; an unparseable ontology and a parseable-but-irrelevant ontology look identical in the contributions map otherwise. A top-level `noActiveBundles` flag is set when `TrustFrameworkRegistry.getActiveBundles()` returns empty, i.e. when no trust-framework bundle was loaded from the classpath at boot; the flag does *not* track the runtime trust-framework enabled toggle (the toggle flips the `trust_frameworks.enabled` DB row but does not unload bundles from the registry), so disabling every bundle through the admin page does not raise `noActiveBundles`. The two-second timeout is per registered role root, not per ontology, so a deeply cyclic `subClassOf` graph in one ontology cannot block the rest of the listing.
1761
+
1762
+
The SHACL toggle additionally gates the background revalidation sweep (see ADR 16): when SHACL is off, `RevalidationServiceImpl.handleTask` skips per-asset validation rather than revoke previously-conforming assets. The periodic sweep is not actively wired in the default production configuration today; the gate is pre-positioned for when it is. Re-queueing chunks skipped while SHACL was off lands together with production wiring of the sweep.
Copy file name to clipboardExpand all lines: federated-catalogue/src/docs/architecture/chapters/07_deployment_view.adoc
+6Lines changed: 6 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -66,3 +66,9 @@ Replace `<portal-origin>` with your portal URL (e.g., `http://localhost:8088` fo
66
66
==== Admin Console URL
67
67
68
68
The demo portal auto-derives the Admin Console URL from `keycloak.auth-server-url` and `keycloak.realm` (aliased as `admin.dashboard.keycloak-auth-server-url` / `admin.dashboard.keycloak-realm`). Override with `KEYCLOAK_ADMIN_CONSOLE_URL` (or `admin.dashboard.keycloak-admin-console-url`) if Keycloak is behind a different hostname.
69
+
70
+
=== Runtime Admin Configuration
71
+
72
+
Most catalogue features that an operator can flip at runtime are persisted in the `admin_config` PostgreSQL table — including the four schema-module toggles (`schema.module.SHACL.enabled`, `schema.module.JSON_SCHEMA.enabled`, `schema.module.XML_SCHEMA.enabled`, `schema.module.OWL.enabled`) and the per-framework enabled flag in `trust_frameworks`. Values written through the admin endpoints survive restarts; no new environment variables are introduced by this layer.
73
+
74
+
`federated-catalogue.verification.schema` (start-up boolean) and the four `schema.module.*.enabled` rows (admin-controlled booleans) operate at different layers. The start-up flag selects whether SHACL is consulted at all during credential upload; the admin module toggles then gate the corresponding validator wherever it would otherwise run. See ADR 16 for the toggle semantics, including the asymmetric role of the OWL toggle.
When a credential arrives, the catalogue maps its `credentialSubject` type URI to a trust-framework role through three tiers, in order:
101
+
102
+
1. **`TrustFrameworkRegistry.typeIndex`** — a hash lookup populated at boot by walking each bundle's `ontology.ttl` from every declared role down via `rdfs:subClassOf*`. Hits here cover every class statically reachable from a role at startup.
103
+
2. **`additional_roots`** — sibling URIs declared in `framework.yaml` for cases where the ontology's class graph does not connect the sibling to the role (see ADR 10 for the `gx:DigitalServiceOffering` example). Also indexed at boot.
104
+
3. **Composite-ontology subclass walk** — `ClaimValidator.resolveSubjectRole` runs a SPARQL `rdfs:subClassOf+` query against the runtime composite ontology assembled from `ONTOLOGY`-type schema rows. This is the only tier that consults schemas uploaded *after* boot.
105
+
106
+
The OWL administrative toggle (ADR 16) controls whether the catalogue admits **runtime extensions** to its registered type vocabulary.
107
+
With OWL on, custom subclasses introduced through runtime-uploaded ontologies are recognised and routed to the registered role they extend.
108
+
With OWL off, the catalogue accepts only the types statically known at boot — credentials whose type was introduced via a runtime ontology upload are rejected at the verification entry point with `400 Bad Request`.
109
+
Tiers 1 and 2 continue to run in either state; only tier 3 (the subclass walk over the runtime composite ontology) is gated.
110
+
The admin UI labels the toggle accordingly, so operators see the user-facing effect rather than the implementation tier it gates.
111
+
112
+
Disabling OWL therefore has a *narrow* but *strict* effect: framework-direct types (Participant, ServiceOffering, Resource for the Gaia-X 2511 bundle, and equivalents in any other bundle's `framework.yaml`) keep resolving and keep being accepted; custom subclasses defined exclusively in a runtime-uploaded ontology stop resolving and are rejected.
113
+
Gating role resolution is the most visible effect a toggle on a type-vocabulary input can have, and the one that satisfies the demonstrable-effect requirement for runtime toggles.
114
+
98
115
=== Admin Configuration Persistence
99
116
100
117
Admin configuration is backed by two PostgreSQL tables. The `trust_frameworks` table holds structured trust framework definitions (columns: `id`, `name`, `service_url`, `api_version`, `timeout_seconds`, `enabled`, `created_at`, `updated_at`), seeded with a single Gaia-X entry. The `admin_config` table is a generic key-value store (`config_key` PK, `config_value`) for all other runtime settings:
Copy file name to clipboardExpand all lines: federated-catalogue/src/docs/architecture/chapters/09_architecture_decisions.adoc
+36Lines changed: 36 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -551,3 +551,39 @@ Routing on `content_kind` is unambiguous and preserves backward compatibility
551
551
Overwrite semantics simplify the data model: no partial-merge conflicts, no ordering dependencies between enrichment uploads.
552
552
553
553
**Related:** ADR 4, ADR 7.
554
+
555
+
=== ADR 16: Schema-module admin toggles, with OWL gating role resolution
556
+
557
+
**Related:** ADR 10.
558
+
559
+
**Context:** Four schema languages — SHACL, JSON Schema, XML Schema, OWL — must each be enable/disable-able at runtime through the administration UI, and every toggle must have a demonstrable effect.
560
+
561
+
SHACL, JSON Schema, and XML Schema all fit a uniform validator shape: input runs against stored schemas of the matching type and a conformance verdict is returned.
562
+
OWL is different — uploaded ontologies extend the type vocabulary the role resolver consults via `rdfs:subClassOf+`; OWL has no validation step of its own.
563
+
A uniform `module_disabled` semantic therefore does not fit OWL: without separate semantics, the OWL toggle would persist in the database with no observable effect, which violates the demonstrable-effect requirement.
564
+
565
+
**Decision:** Expose all four toggles on the admin schema-modules page, but treat them as two semantic classes. The admin UI splits the two classes into separate sections so the asymmetry is visible to operators.
566
+
567
+
* **Validators (SHACL, JSON Schema, XML Schema):** the toggle gates the validator wherever the catalogue would otherwise run it — on-demand validation, and credential verification when the caller requests a schema check.
568
+
When off, the affected endpoint returns `400 Bad Request` with body `module_disabled:<MODULE>`.
569
+
Schema storage is unaffected; schemas remain queryable through the schema endpoints regardless of toggle state.
570
+
571
+
* **OWL:** the toggle gates the third tier of role resolution — the `rdfs:subClassOf+` walk over runtime-uploaded ontologies, on top of the registry index and `additional_roots` defined by ADR 10.
572
+
When off, only tiers 1 and 2 are consulted; credentials whose type is only reachable through the subclass walk resolve to `ResolvedRole.UNKNOWN`, and the verification entry point rejects them with `400 Bad Request`.
573
+
Registry-direct types (Participant, ServiceOffering, Resource for the Gaia-X 2511 bundle, and equivalents in any other bundle's `framework.yaml`) are unaffected.
574
+
575
+
**Consequences:**
576
+
577
+
* Disabling a validator is *permissive* (a check is skipped); disabling OWL is *restrictive* (the catalogue stops recognising custom subclasses).
578
+
The asymmetry is intentional: gating role resolution is the strongest demonstrable effect for a type-vocabulary input, and a uniform "skip a check" semantic does not exist for OWL.
579
+
580
+
* The OWL toggle is independent of the caller's `verifySchema` and `verifySemantics` flags.
581
+
Type dispatch is a configuration of the catalogue's type system, not a per-request validation step, so disabling OWL affects every internal caller of the verification path — asset upload, provenance ingest, asset metadata flow, base subscriber, and on-demand role resolution — independent of how those callers parameterise their request.
582
+
583
+
* The SHACL toggle also gates the periodic revalidation sweep over the existing claims graph.
584
+
When SHACL is administratively disabled, `RevalidationServiceImpl.handleTask` short-circuits — the sweep skips per-asset validation rather than revoke previously-conforming assets against shapes the operator has explicitly silenced.
585
+
The periodic sweep is not actively wired in the default production configuration today; the gate is pre-positioned for when it is.
586
+
Re-sweeping the backlog of chunks skipped while SHACL was off (re-queueing them on the false→true transition) is a follow-up that lands together with production wiring of the sweep — it is a one-liner against `RevalidationService.startValidating()` at that point.
587
+
588
+
* On-demand validation (`POST /assets/validate`) rejects with `400 Bad Request` not only for `module_disabled:<MODULE>` but also for the broader "no validation module is enabled or applicable" case.
589
+
Both are administrative-configuration mismatches under operator control, not server-side processing failures, so `ClientException` (400) is the appropriate mapping rather than `VerificationException` (422). 422 remains reserved for assets whose type is not validatable at all (not RDF, unsupported content type).
0 commit comments