Command: printf '%s\n' '--- support config annotations ---'; grep -n -E '@Configuration|@Bean|@Conditional' src/adapter/outbound/support/src/main/java/dev/caskeleton/adapter/outbound/support/OutboundSupportConfig.java; printf '%s\n' '--- app component scan/exclusions ---'; sed -n '35,125p' src/app-bootstrap/src/main/java/dev/caskeleton/bootstrap/CaSkeletonApplication.java; printf '%s\n' '--- registry support membership/consumers ---'; python3 - <<'PY'
import json
mods=json.load(open('src/config/architecture/modules.json'))['modules']
for m in mods:
    if m['id']=='adapter-outbound-support' or 'adapter-outbound-support' in m.get('allowed_dependencies',[]):
        print(m['id'],m['gradle_path'],'runtime=',m.get('runtime_memberships'),'allows=',m.get('allowed_dependencies'))
PY
printf '%s\n' '--- explicit support config references ---'; git grep -n -w 'OutboundSupportConfig' -- 'src/**' ':!src/adapter/outbound/support/**'; echo "git-grep-exit=$?"
Working directory: /shared/codebase/clean-architecture-backend-template
Executed at: 2026-08-29T07:19:26Z
Source revision: a24ece9cf797f7ea647e33bf846b115208ed1ba5
Observation boundary: Shows support configuration annotations, composition-root component-scan ownership, optional-adapter config references, and registry runtime membership; it does not boot the application.
--- stdout/stderr ---
--- support config annotations ---
10: * {@code @ConditionalOnMissingBean} lets a fork override it.
12:@Configuration
15:  @Bean
16:  @ConditionalOnMissingBean
--- app component scan/exclusions ---
 * component scanner discover each child configuration on its own and assemble the capability
 * whatever that switch said. Registering them as auto-configuration instead makes "off" a
 * structural fact rather than a condition every future bean has to remember to repeat.
 */
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    basePackages = {
      "dev.caskeleton.bootstrap",
      "dev.caskeleton.adapter",
      "dev.caskeleton.application",
      "dev.caskeleton.domain",
      "dev.caskeleton.shared"
    },
    excludeFilters = {
      @ComponentScan.Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
      @ComponentScan.Filter(
          type = FilterType.CUSTOM,
          classes = AutoConfigurationExcludeFilter.class),
      @ComponentScan.Filter(
          type = FilterType.REGEX,
          pattern = CaSkeletonApplication.AUTO_CONFIGURED_PACKAGES)
    })
@ConfigurationPropertiesScan(
    basePackages = {
      "dev.caskeleton.bootstrap.async",
      "dev.caskeleton.bootstrap.autoconfigure.fileserver",
      "dev.caskeleton.bootstrap.autoconfigure.httpclient",
      "dev.caskeleton.bootstrap.concurrency",
      "dev.caskeleton.bootstrap.idempotency",
      "dev.caskeleton.bootstrap.outbox",
      "dev.caskeleton.bootstrap.redis",
      "dev.caskeleton.bootstrap.runtime",
      "dev.caskeleton.bootstrap.security",
      "dev.caskeleton.bootstrap.settings",
      "dev.caskeleton.bootstrap.tracing",
      "dev.caskeleton.adapter.inbound.grpc",
      "dev.caskeleton.adapter.inbound.web",
      "dev.caskeleton.adapter.inbound.websocket",
      "dev.caskeleton.adapter.outbound.cache.redis",
      "dev.caskeleton.adapter.outbound.fileserver",
      "dev.caskeleton.adapter.outbound.objectstorage",
      "dev.caskeleton.application",
      "dev.caskeleton.domain",
      "dev.caskeleton.shared"
    })
public class CaSkeletonApplication {

  /**
   * Packages owned by an auto-configuration entry rather than by the component scan.
   *
   * <p>A package prefix rather than a class list: a new configuration added to an optional
   * capability must not become active merely because nobody remembered to exclude it.
   *
   * <p>The Fileserver admin package is here for a different reason: those routes belong to the
   * management context, and a component scan that also found them would publish the management
   * plane on the public connector — the exposure the separate context exists to remove.
   *
   * <p>The web platform's error, budget and operation packages are here for a third reason. Their
   * advices and controllers need beans that only exist when the corresponding platform
   * auto-configuration is active, and a component scan finds them regardless — so an all-off or
   * partially configured deployment failed to start on an unsatisfied dependency rather than simply
   * not installing the control. Ownership by auto-configuration is what ties a control's presence
   * to its dependency's.
   */
  static final String AUTO_CONFIGURED_PACKAGES =
      "dev\\.caskeleton\\.bootstrap\\.autoconfigure\\..*"
          + "|dev\\.caskeleton\\.bootstrap\\.notification\\..*"
          + "|dev\\.caskeleton\\.adapter\\.inbound\\.web\\.fileserver\\.admin\\..*"
          + "|dev\\.caskeleton\\.adapter\\.outbound\\.mongo\\..*"
          + "|dev\\.caskeleton\\.adapter\\.outbound\\.messaging\\..*"
          + "|dev\\.caskeleton\\.adapter\\.outbound\\.notification\\..*"
          + "|dev\\.caskeleton\\.adapter\\.outbound\\.persistence\\..*"
          + "|dev\\.caskeleton\\.adapter\\.inbound\\.graphql\\..*"
          + "|dev\\.caskeleton\\.adapter\\.inbound\\.web\\.mvc\\.error\\..*"
          + "|dev\\.caskeleton\\.adapter\\.inbound\\.web\\.mvc\\.budget\\..*"
          + "|dev\\.caskeleton\\.adapter\\.inbound\\.web\\.mvc\\.operation\\..*"
          + "|dev\\.caskeleton\\.adapter\\.inbound\\.web\\.webflux\\.error\\..*"
          + "|dev\\.caskeleton\\.adapter\\.inbound\\.web\\.webflux\\.operation\\..*"
          + "|dev\\.caskeleton\\.messaging\\..*";

  public static void main(String[] args) {
    SpringApplication.run(CaSkeletonApplication.class, args);
  }
}
--- registry support membership/consumers ---
adapter-outbound-support :adapter:outbound:support runtime= ['app-bootstrap'] allows= ['domain-core', 'application-core', 'shared-contract']
adapter-outbound-cache-redis :adapter:outbound:cache-redis runtime= ['app-bootstrap'] allows= ['domain-core', 'application-core', 'shared-contract', 'adapter-outbound-support']
adapter-outbound-httpclient :adapter:outbound:httpclient runtime= ['app-bootstrap'] allows= ['domain-core', 'application-core', 'shared-contract', 'adapter-outbound-support']
adapter-outbound-messaging :adapter:outbound:messaging runtime= ['app-bootstrap'] allows= ['domain-core', 'application-core', 'shared-contract', 'adapter-outbound-support']
adapter-outbound-notification :adapter:outbound:notification runtime= ['app-bootstrap'] allows= ['domain-core', 'application-core', 'shared-contract', 'adapter-outbound-support']
app-bootstrap :app-bootstrap runtime= ['app-bootstrap'] allows= ['domain-core', 'application-core', 'adapter-outbound-persistence-jpa', 'adapter-outbound-support', 'adapter-outbound-messaging', 'adapter-outbound-cache-redis', 'adapter-outbound-notification', 'adapter-outbound-fileserver', 'adapter-outbound-httpclient', 'adapter-outbound-identifier', 'adapter-inbound-web', 'shared-contract', 'adapter-outbound-persistence-mongo', 'adapter-inbound-graphql', 'messaging-spring-boot-starter']
--- explicit support config references ---
src/app-bootstrap/src/test/java/dev/caskeleton/adapter/outbound/OptionalAdapterBeanGatingTest.java:27:import dev.caskeleton.adapter.outbound.support.OutboundSupportConfig;
src/app-bootstrap/src/test/java/dev/caskeleton/adapter/outbound/OptionalAdapterBeanGatingTest.java:66:              OutboundSupportConfig.class,
git-grep-exit=0

Exit code: 0
