D-1's fail-closed TenantLineHandler rejects unscoped queries, but gRPC
server threads bypass BaseController.async so no tenant was ever bound —
every query against a tenant-scoped table silently failed.
- proto: add tenant_id to manager/driver single & batch query messages
- facade: drop single-param abstract + default matchesTenant filter,
promote the tenantId-bearing overload (all callers already pass it)
- GrpcFacade/LocalFacade: carry tenant into request / onto ThreadLocal
- 9 manager+driver servers (27 RPCs): setTenantId + finally clear
- data servers: setTenantId on tenant-bearing RPCs; runIgnore for
getByRecordId (record_id globally unique, no tenant in payload)
- TokenServer.checkValid: runIgnore (dc3_tenant_membership, pre-login)
- driver clients (Device/Driver/Point): set tenant on getById queries
- alarm: drop tenant reverse-resolve (D-1 leftover the fail-closed
interceptor forbids); tenant now required from upstream, else drop
- add TenantLineInterceptorIntegrationTest (H2) covering scoped filter,
fail-closed, and runIgnore through the real MyBatis-Plus pipeline
M1: OAuthMcpRuntimeServiceImpl.registerClient runIgnore lambda body
re-indented from 8-space to 12-space base to match jwks/token/
authorize/revoke/introspect blocks (cosmetic, no logic change).
M2: TenantLineHandlerImpl Javadoc + inline comments now mention both
TenantContextHolder.runIgnore (returning) and runIgnoreAction (void),
since OAuth/MCP callers predominantly use runIgnore.
M3: TenantLineHandlerImplTest.ignoreTableTrueForWhitelistedTables now
asserts all 11 IGNORE_TABLES entries (was 3/11) — guards the
tenant-line whitelist against silent removal.
- introduce TenantContextHolder holding tenantId with a runIgnore closure
- bind/clear the holder in BaseController.async from the reactive security context
- add unit tests for set/get and runIgnore semantics
Refresh module READMEs, AGENTS.md, CONTRIBUTING.md, and dc3/doc/
guides to reflect the unified Dockerfile, consolidated compose stacks,
and updated build instructions.
Update @since from 2022.1.0 to 2016.10.1 and @version from 2026.5.5
to 2026.5.17 across all Java source files to reflect the actual
project start date.
Each common module previously declared its EnvironmentPostProcessor
classes twice — via the new META-INF/spring/...EnvironmentPostProcessor.imports
file *and* via the legacy spring.factories — and decorated the classes
with @Configuration even though Spring Boot loads them through
SpringFactoriesLoader, not through the application context.
Drop the @Configuration noise on every Active*ProfileConfig and on the
Driver / Mqtt / Rabbitmq EnvironmentConfig classes, and delete the
duplicate .imports files in agentic, auth, data, driver, gateway,
manager, mqtt, postgres, quartz, rabbitmq, repository, thread, and web.
The remaining META-INF/spring.factories in each module is the single
registration entry point.
Spring Boot 4.0.6 still loads EnvironmentPostProcessor implementations
via SpringFactoriesLoader from META-INF/spring.factories, not from the
new .imports file. The .imports mechanism only applies to
AutoConfiguration classes.
The previous commit incorrectly deleted all spring.factories files,
which broke profile activation for every service (auth, data, manager,
gateway, etc.). Restore them with only the EnvironmentPostProcessor
entries (EnableAutoConfiguration entries remain removed since those
use AutoConfiguration.imports).
Auto-configuration:
- Replace @Configuration with @AutoConfiguration on 21 classes listed
in AutoConfiguration.imports (InitRunners, topic configs, DalConfig,
MqttConfig, ThreadPoolConfig, RabbitConfig, ExchangeConfig, etc.)
- Add @AutoConfiguration to ExceptionConfig alongside @RestControllerAdvice
WebFlux fixes:
- Replace getServlet().getContextPath() with getReactive().getContextPath()
in WebFilterConfig (servlet API in reactive context)
- Remove redundant @EnableWebFlux and @Slf4j from WebFluxConfig
- Replace deprecated customCodecs().registerWithDefaultConfig() with
defaultCodecs().jacksonJsonEncoder/Decoder()
Driver lifecycle:
- Replace System.exit(1) in DriverRegisterServiceImpl with
ServiceException to allow Spring graceful shutdown
Resource leaks:
- Wrap FileOutputStream in try-with-resources in DeviceServiceImpl
- Wrap BufferedWriter in try-with-resources in CmdUtil
- Rewrite X509Util.loadCertificateWithPassword with try-with-resources
and remove dead if/else branches
Standardize on Objects.isNull() and Objects.nonNull() for null checks
across agentic, auth, data, facade, manager, postgres, public, and web
modules for consistency with the project's established convention.
Spring Boot 4.x removed the spring.factories mechanism entirely. The
EnableAutoConfiguration entries were already migrated to
AutoConfiguration.imports, but the EnvironmentPostProcessor
registrations were only in the now-defunct spring.factories, meaning
all profile activation and environment configuration was broken.
- Delete all 15 spring.factories files (dead code in Boot 4.x)
- Create EnvironmentPostProcessor.imports for 12 modules, registering
16 EnvironmentPostProcessor implementations that were previously
unreachable
Group dependencies in each module POM using a standard category order:
Spring Boot → Spring Cloud → gRPC → Data Access → Messaging → IoT → AI
→ Serialization → Utility → Security → Observability → DC3 API → DC3 Common
DC3 Common dependencies sorted alphabetically within their group.
- Bump all module versions from 2025.11.1 to 2026.4.18.3
- Remove orphaned dc3-common-influx dependency and property from root pom.xml
- Standardize dependency comment style in dc3-common/pom.xml
- Merge gRPC dependency groups into single section in dc3-common-api
- Restructure Spring Integration MQTT and Eclipse Paho groups in dc3-common-mqtt
- Fix incorrect comment 'DC3 Common Exception' to 'DC3 Common Related' in dc3-common-postgres
- Add missing blank line before </dependencies> in dc3-common-driver
- Remove stray blank line in root pom.xml dependencyManagement