Governance Controller
The HTTP half of the schema governance operator surface: read the drift log and the current declaration, run a check, release a quarantined proposition.
It carries no logic of its own. Every route calls GovernanceOperationsService, the same object GovernanceTools calls, so an operator working over HTTP and an agent working through tools see one answer. Only the leak-free governance DTOs cross this boundary.
Paths sit under /api/v1/metamodel, matching the embabel.dice.metamodel prefix the module's settings use, and a per-context operation names its context in the path the way DiscoveryController does. GET reads, POST runs a check or performs a release.
How it switches on
This controller is not component-scanned, and it has no auto-configuration of its own. It goes on the context through DiceRestConfiguration, the one import a host uses to open any DICE REST surface, and only when a GovernanceOperationsService bean is there to answer the routes. Two decisions, both the host's: import DICE REST, and wire the governance loop.
So a host that imports DiceRestConfiguration and declared no schema resolves zero /api/v1/metamodel URLs and starts cleanly, and a host that wants the governance loop through agent tools or its own code with no endpoint open leaves the import out. See ConditionalControllerImport for why the condition is asked late enough to see a service the auto-configuration built.
@ConditionalOnMissingBean lets a host put these operations somewhere else — a different path, extra authorization, a shape of its own — by declaring its own GovernanceController bean and still importing DiceRestConfiguration for the other controllers. This one then backs off.
Every read is bounded. limit is clamped by the service, and a value outside its range answers 400 with the bound named in the body, so an operator who asked for too much can see what to ask for. Any other failure — a driver timeout, a store error — answers a generic 500 whose body carries a fixed message, with the cause logged server-side.
Parameters
The single governance service every route delegates to.
Functions
What the application declares right now, and where it sits against what governance recorded.
Sanitize any other failure into a generic 500. The cause is logged server-side; the response body carries a fixed message, so driver or store detail never reaches a caller whatever the consumer's global error config does.
Answer a refused request with 400 carrying the check's own message, so the bound that was broken reaches the caller.
The most recent whole-graph drift checks, newest first. Context-scoped checks are excluded.
Let one quarantined proposition back into use, answering where it stands afterwards.
The most recent drift checks scoped to one context, newest first.
Run a whole-graph drift check. It writes a report and moves no proposition, so the response is the full impact a sweep would evaluate.
The same check scoped to one context.