# evidence 260 — messaging-admin-plane-assembly
# revision: a24ece9cf797f7ea647e33bf846b115208ed1ba5
# cwd: /shared/codebase/clean-architecture-backend-template/src/messaging
# command: grep -vE "^import " messaging-spring-boot-starter/src/main/java/dev/caskeleton/messaging/autoconfigure/MessagingAdminAutoConfiguration.java
# ---- raw output ----
package dev.caskeleton.messaging.autoconfigure;


/**
 * Wires the admin plane, and only when a deployment has explicitly asked for it.
 *
 * <p>Off unless {@code app.messaging.admin.enabled=true}. An application that acquires the admin
 * plane by adding a starter to its classpath is exactly the situation the plane's guards exist to
 * prevent — the guards would still refuse an unapproved operation, but the beans would be reachable
 * from any code in the process.
 *
 * <p>{@link dev.caskeleton.messaging.admin.runtime.DestructiveMessagingAdmin} is deliberately
 * absent from this class. No bean for it is ever auto-configured: an operator tool that needs purge
 * or delete registers one itself, with an admin credential this runtime does not hold.
 */
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(prefix = "app.messaging.admin", name = "enabled", havingValue = "true")
public class MessagingAdminAutoConfiguration {

  /**
   * Returns the guard that authorises non-destructive admin operations.
   *
   * @return the guard
   */
  @Bean
  @ConditionalOnMissingBean
  public DestructiveOperationGuard destructiveOperationGuard() {
    // false: an application runtime never holds an admin credential, so the guard refuses the
    // operations that would need one. An operator tool overrides this bean with true.
    return new DestructiveOperationGuard(false);
  }

  /**
   * Returns a single-process journal so a development runtime starts without extra wiring.
   *
   * <p>It declares itself non-durable, and {@link MessagingAdminDurabilityValidator} refuses to let
   * a production profile start on it. That pairing is deliberate: the convenient default stays
   * convenient for local work and becomes a startup failure — naming what to supply — the moment
   * the deployment claims to be production. The previous default was an indistinguishable {@code
   * ConcurrentHashMap} that silently let two replicas execute the same approval.
   *
   * @return the in-memory journal
   */
  @Bean
  @ConditionalOnMissingBean
  public AdminOperationJournal adminOperationJournal() {
    return new InMemoryAdminOperationJournal();
  }

  /**
   * Returns the validator that refuses a production profile on a non-durable journal.
   *
   * @param journal the journal in use
   * @param environment the Spring environment
   * @return the validator
   */
  @Bean
  @ConditionalOnMissingBean
  public MessagingAdminDurabilityValidator messagingAdminDurabilityValidator(
      AdminOperationJournal journal, org.springframework.core.env.Environment environment) {
    return new MessagingAdminDurabilityValidator(journal, environment);
  }

  /**
   * Returns the topology validator, when the application supplied a broker inspector.
   *
   * @param inspector reads the broker's current topology
   * @return the composite validator
   */
  @Bean
  @ConditionalOnBean(BrokerTopologyInspector.class)
  @ConditionalOnMissingBean
  public CompositeTopologyValidator compositeTopologyValidator(BrokerTopologyInspector inspector) {
    return new CompositeTopologyValidator(inspector);
  }
}
