grant_type in GrpcMcpIntrospectDTO was a free-form string. Introduce
GrpcOAuthGrantType (GRPC_OAUTH_GRANT_TYPE_UNSPECIFIED / AUTHORIZATION_CODE
/ CLIENT_CREDENTIALS / REFRESH_TOKEN). Enum names are upper-case (Java
enum constants must be); the boundary converts to/from the lowercase
OAuth spec form (authorization_code) via toUpperCase / toLowerCase.
BO, DB and OAuth form parameter stay lowercase string.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
audit status in GrpcMcpAuditCommand was a free-form string. Introduce
GrpcMcpAuditStatus (MCP_AUDIT_STATUS_UNSPECIFIED / SUCCESS / DENIED /
POLICY_DENIED / ERROR / UNKNOWN) — names match McpAuditStatusEnum values.
Server maps proto->DTO via name(); facade maps BO string->proto via
toGrpcAuditStatus. BO and DB stay string.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
principal_type was a free-form string in GrpcMcpIntrospectDTO and
GrpcMcpAuditCommand. Introduce GrpcMcpPrincipalType
(MCP_PRINCIPAL_TYPE_UNSPECIFIED / USER / SERVICE_ACCOUNT / SYSTEM) —
names match PrincipalTypeEnum values, so the mapping is a direct
valueOf / name(). Server + facade convert at the proto boundary; BO,
gateway and HTTP header layer stay string.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
risk_level was a free-form string across GrpcMcpToolMetadataDTO,
GrpcMcpToolResolveDTO, GrpcMcpToolAuthorizeDTO and GrpcMcpAuditCommand.
Introduce GrpcMcpRiskLevel (MCP_RISK_LEVEL_UNSPECIFIED / LOW / MEDIUM /
HIGH) — names match McpRiskLevelEnum values, so the mapping is a direct
valueOf / name(). Server + facade convert at the proto boundary; the BO
and DB layer stay string.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* fix(api): correct inverted enable_flag comment and document time unit
- tenant.proto enable_flag comment said "1 enabled, 0 disabled" but the
actual EnableFlagEnum is ENABLE=0, DISABLE=1 — callers reading the
comment would invert the flag. Correct it.
- base.proto create_time/operate_time are epoch milliseconds
(LocalDateTimeUtil/Instant.toEpochMilli); document the unit so callers
don't guess seconds vs millis.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(api): carry timestamp in point-value history; explicit bool presence
#5 Point-value history: the whole chain (proto -> gRPC server ->
PointValueService -> repository -> facades -> controller -> agentic tool)
returned List<String> and dropped create_time even though the DB row
already carried it. Switch to PointValueBO / FacadePointValueBO end to
end so callers receive each value with its timestamp.
#6 Field presence: GrpcR.ok and McpIntrospectDTO.active are now optional
bool, so "unset" is distinguishable from false on the wire.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(auth): unify JWT signing key, drop salt/password from token contract
The JWT signing key was per-principal — securityKey + ":" + salt, where
salt was the credential salt also carried through the gateway and the
token RPC. That makes the JWT key weak and widens salt exposure to every
gateway hop. Sign with the single configured securityKey (HS256) instead
and remove salt from the JWT path entirely:
- KeyUtil.generateToken/parserToken drop the salt parameter; the HMAC
key is now just securityKey (must be >= 32 bytes for HS256).
- TokenService.generateToken/checkValid drop the salt parameter.
- token.proto GrpcLoginQuery drops salt and password — CheckValid only
ever needed tenant, name and token.
- gateway FilterService, TokenGrpcFacade, TokenController adapted; the
request header no longer feeds salt into validation.
The login-handshake salt (POST /token/salt, used to salt the password
client-side before verifyPassword) is unchanged — only the JWT signing
salt is removed.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* refactor(api): type MCP authorize decision as proto enum
The authorize-tool-call decision was a free-form string, so callers
could only compare it against literals with no compile-time check.
Introduce GrpcMcpDecision (MCP_DECISION_UNSPECIFIED / AUTHORIZED /
CONFIRM_REQUIRED / REJECTED) and type GrpcMcpToolAuthorizeDTO.decision
with it. Enum names match the existing auth-side literals, so the
mapping is a direct valueOf / name().
- McpRuntimeServer builds the enum via toGrpcDecision (unknown -> UNSPECIFIED).
- McpRuntimeGrpcFacade maps enum -> BO string via name().
- gateway unchanged: it receives the BO (string decision) through the facade.
The other string MCP fields (risk_level, status, grant_type,
principal_type) stay strings for now — their value sets are wider and
partly lowercase (OAuth grant_type), so they are a follow-up.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(facade): align TokenLocalFacade with 3-arg checkValid (CI compile fix)
TokenLocalFacade (local impl) was missed when TokenFacade.checkValid
dropped salt; CI compiles facade-local-auth independently and caught
it. Align it + its test.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* style(backend): reformat and rearrange java/xml sources
Apply code cleanup across dc3-common and dc3-driver: whitespace and
indent normalization, import sorting, member rearrangement, and javadoc
normalization. No semantic changes; compilation verified.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* style(docs): reformat vitepress vue diagram components
Expand compact svg templates and normalize formatting across diagram
components, the seo module, and the theme stylesheet. No behavior
changes.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* style(docs): reformat markdown pages
Normalize markdown formatting. Restore the <script setup> component
imports that an earlier unused-import pass had wrongly stripped; every
<Diagram> tag now resolves to a backing import again.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* style: reformat point view and trim pom whitespace
Normalize whitespace in the point view and drop trailing whitespace in
pom.xml. No behavior changes.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* fix(security): sanitize agentic assistant HTML with DOMPurify (XSS)
RenderedAssistantMessage rendered model output via v-html after a
hand-rolled regex sanitizer that CodeQL flagged 5 ways: bad-tag-filter,
incomplete-multi-character-sanitization (on* attributes, javascript:),
incomplete-url-scheme-check (data:/vbscript:). Replace with DOMPurify,
which covers all these plus mutation XSS. Fixes CodeQL #2146-2150.
* fix(security): harden log-injection + CAN command injection
log-injection (7): pass user-derived log args (conversationId, model,
candidate/fallback) through LogSanitizer.sanitize in AgenticChatServiceImpl,
ChatClientFactory, AgenticChatRequestPreparer — strips CR/LF that could
forge log lines.
relative-path-command / command injection (2, CanDriver): executeCommand
runs `sh -c` with a command built from driver config (interfaceName) and
request data (canId/frame), so add a CAN_COMMAND_PATTERN whitelist
(^[A-Za-z0-9 _#,.=%/-]+$) rejecting shell metacharacters, and validate
interfaceName against ^[A-Za-z0-9_]+$ at all 3 entry points. Fixes
CodeQL #2173,#2172,#2120,#1514,#1513,#1022,#1017,#1016,#1014.
Verified: mvn compile agentic+can clean.
mybatis-plus 3.5.17 fixes the JDK 9+ split-package conflict (#7027) by
relocating service classes from com.baomidou.mybatisplus.extension.service
to com.baomidou.mybatisplus.spring.service. Verified via the 3.5.17 jar:
only IService and ServiceImpl moved — Page, JacksonTypeHandler, chain
wrappers, Db, interceptors all stay in extension. Updated 112 imports.
Supersedes dependabot #141 (which failed compile on the same move).
Verified: mvn compile clean across every IService module (bacnet4j driver
excluded only due to a local mirror cache miss, unrelated to this change).
Point-value ingestion is now driven by PointValueIngestBuffer workers, so the Quartz 5s tick job is removed; ScheduleForDataServiceImpl only registers the hourly maintenance job; HourlyJobForData test migrated to its own file.
PointValueReceiver offers every message to PointValueIngestBuffer (ack on accept, nack-requeue when full) and switches to the high-throughput listener container factory; drops the speed-threshold dual path.
Bounded ArrayBlockingQueue plus worker threads draining on a size-or-time trigger; offer returns false when full so the receiver can nack-requeue; a failed save re-queues the batch for retry. PointValueServiceImpl.savePointValuesToRepository wraps failures into RepositoryException so the buffer can re-queue instead of silently dropping.
Add sqlite-jdbc 3.53.2.0 to parent pom dependencyManagement; add sqlite-jdbc and HikariCP to dc3-common-driver pom; add BufferProperties nested group to DriverProperties; add BUFFER_REPUBLISH_SCHEDULE_JOB constant to ScheduleConstant
Unify request-id and OpenTelemetry trace context across all transport layers
(HTTP, gRPC, RabbitMQ) using a three-tier priority: X-Request-Id header, OTel
Trace ID, UUID fallback. Add traceId/spanId to the logback pattern for
log-trace correlation. Configure OTLP export, sampling, and B3/W3C propagation
in application-web.yml.
Replace micrometer-tracing-bridge-brave with the full OpenTelemetry stack
(bridge-otel, OTLP exporter, SDK, trace SDK, propagators, API, context).
Add OTel BOM and semconv to the parent POM for centralized version control.
Add OTel API dependencies to dc3-common-rabbitmq and dc3-common-facade-grpc
for trace context propagation.
Add LogSanitizer and apply it to agentic conversationId/model and the listening-virtual netty deviceName so they are not emitted verbatim in log output.
Co-Authored-By: Claude <noreply@anthropic.com>
Wrap unchecked Integer/Long/Byte.parse* calls in topic/dashboard/oauth/facade and the BACnet-IP, Ethernet-IP, FINS, SNMP drivers plus the agentic action payload, so malformed values fall back to a safe default instead of aborting.
Co-Authored-By: Claude <noreply@anthropic.com>
Mark @Getter with onMethod_={@Override} on BOs/enums whose accessors override a base-class getter, and add @ToString to the ChatCompletion VOs and Pages.
Co-Authored-By: Claude <noreply@anthropic.com>
Add Javadoc to hand-written public methods/constructors (with @param/@return), injected fields, @Override methods, constants and nested types across dc3-common-driver. Also fix PointClient#getById @return type (PointDTO -> PointBO) and reorder TypedValueConverter#convert Javadoc above its @SuppressWarnings annotation. No code logic changes.
Co-Authored-By: Claude <noreply@anthropic.com>
Document the shared guardOrThrow helper (NOT_FOUND = empty outcome,
other error = service exception) on the nine grpc facade classes,
matching the two that already documented it.