Docs & rules
jdubois/boot-uiGitHub
This is a public, read-only report. Striff reads this repository's docs, turns each sentence that makes a claim about the code into a rule, and checks the rule against the code on the default branch. How this works
maind290c7cLast read 10h ago
Is this yours? Install to manage it
Once installed, Striff checks every pull request.
Documents
Rules
25 docs
jdubois/boot-uiOpen repository
jdubois/boot-ui — documented rules
69 of 69 rules, printed October 12, 2026.
| The sentence in your docs | |||
|---|---|---|---|
| Read Oct 11 | The QuarkusRestClientTraceListener (registered via ServiceProviderBuildItem when the capability is present) attaches a QuarkusRestClientTraceFilter on every proxy. | QuarkusRestClientTraceListener depends on QuarkusRestClientTraceFilter | Holds |
| Read Oct 11 | Each check is a small class registered in PentestingCheckRegistry and implemented in PentestingChecks.java. | PentestingCheckRegistry is in bootui-engine | Holds |
| Read Oct 11 | QuarkusPentestingObservationCollector deliberately supplies a neutral PentestingSecurityStatus (securityClassPresent=false, chainsWithCsrf=-1) because Quarkus has no Spring Security equivalent to inspect. | QuarkusPentestingObservationCollector depends on PentestingSecurityStatus | Holds |
| Read Oct 11 | It also includes the per-panel access keys — bootui.panels.<id>.enabled / .read-only and the global bootui.read-only — which are enforced on Quarkus by QuarkusPanelAccessFilter at full behavioral parity with Spring's PanelAccessFilter (same config keys, same BootUiPanels path resolution, same canonical JSON 403 body); | QuarkusPanelAccessFilter depends on BootUiPanels | Holds |
PanelAccessFilter depends on BootUiPanels | Holds | ||
| Read Oct 11 | @CircuitBreaker, @Retry, @Timeout, @Bulkhead, @RateLimit, and @Fallback declarations are scanned from the build-time Jandex index by a registerFaultTolerancePolicies build step + @Recorder into a synthetic bean, then mapped onto the same FaultTolerancePolicyProvider SPI and DTO contract Spring's Resilience4j/Spring Retry providers use. | FaultTolerancePolicyProvider is a contract | Holds |
| Read Oct 11 | It is computed by the shared engine SqlTraceGrouping helper — the identical code path Spring's LiveActivityService uses — so flagging and call-site aggregation are byte-identical across adapters. | LiveActivityService depends on SqlTraceGrouping | Holds |
| Read Oct 11 | Captured email ( MAIL). LiveActivityResource reads the same framework-neutral EmailCaptureService the standalone Email panel uses directly, with no separate Quarkus capture instrumentation, and feeds its merged SSE stream identically to Spring, nesting as a REQUEST child via the same trace-id join. | LiveActivityResource depends on EmailCaptureService | Holds |
| Read Oct 11 | Capture is done by two @ApplicationScoped interceptors — QuarkusKafkaProducerCapture (OutgoingInterceptor) and QuarkusKafkaConsumerCapture (IncomingInterceptor) — that read Kafka record metadata into the shared, framework-neutral KafkaActivityRecorder. | QuarkusKafkaProducerCapture is annotated with ApplicationScoped | Holds |
QuarkusKafkaConsumerCapture is annotated with ApplicationScoped | Holds | ||
QuarkusKafkaProducerCapture depends on KafkaActivityRecorder | Holds | ||
QuarkusKafkaConsumerCapture depends on KafkaActivityRecorder | Holds | ||
| Read Oct 11 | RabbitMQ follows the same SmallRye pattern. QuarkusRabbitProducerCapture/QuarkusRabbitConsumerCapture feed the shared RabbitActivityRecorder, are class-presence-gated on quarkus-messaging-rabbitmq, stop capture whenever the dedicated RabbitMQ panel is disabled, and are excluded from Arc when the connector is absent. | QuarkusRabbitProducerCapture depends on RabbitActivityRecorder | Holds |
QuarkusRabbitConsumerCapture depends on RabbitActivityRecorder | Holds | ||
| Read Oct 11 | A servlet request runs start-to-finish on one worker thread that serves only one request at a time, so SQL, exceptions, and security events observed on that thread within its time window belong to it exactly, even with no distributed tracing at all ( threadMatched is a first-class field on RequestProfileSecurityDto/carried by RequestProfileExceptionDto's thread). | RequestProfileSecurityDto has a threadMatched field | Holds |
| Read Oct 11 | threadMatched always reports false (Quarkus has no thread-identity concept), while principalMatched on RequestProfileSecurityDto is honestly computed by comparing principals. | RequestProfileSecurityDto has principalMatched | Holds |
| Read Oct 11 | In the main feed, ActivityEntryDto.profileable is computed adapter-side in LiveActivityResource: true for request entries with a resolvable trace id, false otherwise; | ActivityEntryDto has profileable | Holds |
LiveActivityResource depends on ActivityEntryDto | Holds | ||
| Read Oct 11 | Because both beans always exist, LiveActivityResource injects ActivityStore and ActivityPersistenceSettings directly (no Instance<> wrapper) and branches its activity() method on persistenceSettings.enabled() exactly like Spring's controller. | LiveActivityResource depends on ActivityStore | Holds |
LiveActivityResource depends on ActivityPersistenceSettings | Holds | ||
LiveActivityResource has an activity method | Holds | ||
| Read Oct 11 | The opaque ServiceMapInteractionDto.flowId needed no Quarkus-specific work. ServiceMapAssembler derives it one-way from whatever distributed-trace id was already captured on the HttpExchangeBuffer/RestClientTraceRecorder/ SqlTraceRecorder entries this resource reads — the same capability-gated QuarkusOtelTraceIdProvider stamping. | ServiceMapInteractionDto has flowId | Holds |
| Read Oct 11 | BootUiEngineProducer @Produces a SwitchableActivityStore in front of it, rather than producing ActivityStore directly. | BootUiEngineProducer depends on SwitchableActivityStore | Holds |
| Read Oct 11 | A thin LiveActivityResource#useExistingDatasource mirrors Spring's controller method: 404 when no DataSource is present, 400 when the request is not explicitly confirmed, 200-and-no-op when persistence is already active, and 200 with the store swapped and capturing on success — all behind the shared LocalhostGuard write floor. | LiveActivityResource has an useExistingDatasource method | Holds |
| Read Oct 11 | BootUiProdShellGuardFilter is a CDI Vert.x filter registered by its own always-on @BuildStep (deliberately not launch-mode-gated, the opposite polarity from every other build step in the extension). Its handle() method reads a CDI-injected LaunchMode and answers a plain 404 for the configured UI/API surface and the private /bootui classpath mount only when it is LaunchMode.NORMAL — an immediate no-op pass-through otherwise, so dev/@QuarkusTest behavior is unaffected. | BootUiProdShellGuardFilter has a handle method | Holds |
| Read Oct 11 | They needed zero changes beyond adding one new platform constant ( PanelsReport.PLATFORM_SPRING_BOOT_REACTIVE). | PanelsReport has PLATFORM_SPRING_BOOT_REACTIVE | Holds |
| Read Oct 11 | BootUiAutoConfiguration (servlet) and BootUiReactiveAutoConfiguration (reactive) are two separate autoconfigurations in the same bootui-spring-autoconfigure module — not two modules — because nearly all of the underlying @RestControllers, safety decisions, and engine wiring are identical. | BootUiAutoConfiguration is in bootui-spring-autoconfigure | Holds |
BootUiReactiveAutoConfiguration is in bootui-spring-autoconfigure | Holds | ||
| Read Oct 11 | Resilience4j's event publishers plus the additive BootUiRetryListener bean feed the shared FaultToleranceEventRecorder from whatever thread the protected call runs on, so the panel and its Live Activity FAULT_TOLERANCE entries work with zero adapter-specific code. | BootUiRetryListener depends on FaultToleranceEventRecorder | Holds |
| Read Oct 11 | Panel MCP Server, Reactive binding ReactiveBootUiMcpController — same BootUiMcpService , McpServerState , and McpProtocol as the servlet BootUiMcpController only the transport differs ( DataBuffer payload assembly with the same bootui.mcp.max-payload-bytes limit, and tool execution offloaded to Schedulers.boundedElastic() ) | ReactiveBootUiMcpController depends on BootUiMcpService | Holds |
ReactiveBootUiMcpController depends on McpProtocol | Holds | ||
ReactiveBootUiMcpController depends on McpServerState | Holds | ||
BootUiMcpController depends on BootUiMcpService | Holds | ||
BootUiMcpController depends on McpProtocol | Holds | ||
BootUiMcpController depends on McpServerState | Holds | ||
| Read Oct 11 | Panel Command Line, Reactive binding ReactiveBootUiCliController — same CliService and the same /bootui/api/cli contract and statuses as the servlet BootUiCliController , with tool invocation offloaded to Schedulers.boundedElastic() because BootUI's tools call blocking diagnostics | ReactiveBootUiCliController depends on CliService | Holds |
BootUiCliController depends on CliService | Holds | ||
| Read Oct 11 | Panel SQL Trace, Reactive source ReactiveSqlTraceController over the new shared ReactiveBootUiChangeStream SSE primitive ( Flux<ServerSentEvent<T>> ), feeding the same SqlTraceRecorder See the fidelity note below | ReactiveSqlTraceController depends on ReactiveBootUiChangeStream | Holds |
ReactiveSqlTraceController depends on SqlTraceRecorder | Holds | ||
| Read Oct 11 | Panel Transactions, Reactive source ReactiveTransactionsController over ReactiveBootUiChangeStream , feeding the same TransactionRecorder See the fidelity note below | ReactiveTransactionsController depends on ReactiveBootUiChangeStream | Holds |
ReactiveTransactionsController depends on TransactionRecorder | Holds | ||
| Read Oct 11 | Panel Log Tail, Reactive source ReactiveLogTailController — same LogTailBuffer /Logback appender, SSE via ReactiveBootUiChangeStream | ReactiveLogTailController depends on LogTailBuffer | Holds |
| Read Oct 11 | Panel REST Client, Reactive source ReactiveRestClientTraceController — same RestClientTraceRecorder , SSE via ReactiveBootUiChangeStream See the fidelity note below | ReactiveRestClientTraceController depends on RestClientTraceRecorder | Holds |
ReactiveRestClientTraceController depends on ReactiveBootUiChangeStream | Holds | ||
| Read Oct 11 | Panel WebSockets, Reactive source ReactiveWebSocketController + ReactiveWebSocketMetadataProvider — same WebSocketService , SSE via ReactiveBootUiChangeStream See the fidelity note below | ReactiveWebSocketController depends on WebSocketService | Holds |
ReactiveWebSocketController depends on ReactiveBootUiChangeStream | Holds | ||
| Read Oct 11 | ReactiveBootUiChangeStream is a small shared Sinks.Many-backed SSE broadcaster (open() / signal() / close()) used by every "push an update when something changes" panel above, instead of each controller hand-rolling its own sink. | ReactiveBootUiChangeStream has an open method | Holds |
ReactiveBootUiChangeStream has a signal method | Holds | ||
ReactiveBootUiChangeStream has a close method | Holds | ||
| Read Oct 11 | REST Client. Availability is gated on RestClientTraceRecorder#hasInstrumentedClient() (a WebClient.Builder auto-configured with the BootUI customizer must have been built). | RestClientTraceRecorder has a hasInstrumentedClient method | Holds |
| Read Oct 11 | REST/WebClient calls are read from the same RestClientTraceRecorder fed by BootUiEngineConfiguration's WebClientCustomizer; | BootUiEngineConfiguration depends on RestClientTraceRecorder | Holds |
| Read Oct 11 | The servlet adapter's LiveActivityController additionally depends on two things with no reactive equivalent. One is a ServletRequestHandledEvent listener, which exists purely as an SSE-refresh trigger, not a data source. The other is a thread-based LiveActivityCorrelator that stitches a request to its downstream activity via serving-thread identity — meaningless on Reactor Netty, where a request is not served start-to-finish on one dedicated worker thread. | LiveActivityController depends on LiveActivityCorrelator | Holds |
| Read Oct 11 | LiveServiceMapController injects only beans both stacks register — the shared HttpExchangesController plus the engine's ConnectionPoolService, SqlTraceRecorder, RestClientTraceRecorder, KafkaActivityRecorder, RabbitActivityRecorder, and CacheActivityRecorder. | LiveServiceMapController depends on HttpExchangesController | Holds |
LiveServiceMapController depends on ConnectionPoolService | Holds | ||
LiveServiceMapController depends on SqlTraceRecorder | Holds | ||
LiveServiceMapController depends on RestClientTraceRecorder | Holds | ||
LiveServiceMapController depends on KafkaActivityRecorder | Holds | ||
LiveServiceMapController depends on RabbitActivityRecorder | Holds | ||
LiveServiceMapController depends on CacheActivityRecorder | Holds | ||
| Read Oct 11 | LiveServiceMapController injects only beans both stacks register — the shared HttpExchangesController plus the engine's ConnectionPoolService, SqlTraceRecorder, RestClientTraceRecorder, KafkaActivityRecorder, RabbitActivityRecorder, and CacheActivityRecorder. It returns a stable core DTO, so one class registered in both BootUiAutoConfiguration and BootUiReactiveAutoConfiguration makes Spring MVC and WebFlux serve a byte-identical map, including its cache dependency and opaque flow correlation. | BootUiAutoConfiguration depends on LiveServiceMapController | Holds |
BootUiReactiveAutoConfiguration depends on LiveServiceMapController | Holds | ||
| Read Oct 11 | BootUiReactiveAutoConfiguration already installs the same ReactiveOtelTraceIdProvider on the HTTP exchange, SQL, REST-client, and cache recorders. | BootUiReactiveAutoConfiguration depends on ReactiveOtelTraceIdProvider | Holds |
| Read Oct 11 | ReactiveActivitySignalFilter takes an ObjectProvider<ReactiveLiveActivityController> rather than a direct reference. | ReactiveActivitySignalFilter depends on ReactiveLiveActivityController | Holds |
| Read Oct 11 | WebFilter beans are eagerly resolved by WebFlux at startup to build the filter chain, so a direct constructor dependency would force-eager the controller and defeat its place in BootUiReactiveAutoConfiguration.LAZY_CONTROLLER_CLASS_NAMES. | BootUiReactiveAutoConfiguration has LAZY_CONTROLLER_CLASS_NAMES | Holds |
| Read Oct 11 | HTTP exchange (via a new ReactiveHttpExchangeTraceFilter feeding a side-buffer HttpExchangeTraceRegistry, since Actuator's HttpExchange model has no trace-id field), SQL (SqlTraceRecorder.setTraceIdProvider), exceptions (ReactiveBootUiExceptionHandler.setTraceIdProvider), and security events (ReactiveSecurityLogsController.setTraceIdProvider | ReactiveHttpExchangeTraceFilter depends on HttpExchangeTraceRegistry | Holds |
SqlTraceRecorder has setTraceIdProvider | Holds | ||
ReactiveBootUiExceptionHandler has setTraceIdProvider | Holds | ||
ReactiveSecurityLogsController has setTraceIdProvider | Holds | ||
| Read Oct 11 | HttpExchangeTraceRegistry#match (and its servlet sibling RequestCorrelationRegistry) deliberately requires a unique method+path+time-window candidate. | HttpExchangeTraceRegistry has match | Holds |
69 rules from 5 docs
See these where the change is. The browser extension puts a pull request's doc findings, and a diagram of what it changed, on the GitHub page itself, so the code and what your docs say about it are side by side.