135 Commits

Author SHA1 Message Date
pnoker 3c19f31652 feat(deploy): ship all 36 drivers and isolate their SQLite outboxes
- add ble, can, dlt645, dnp3, iec61850, kafka, knx, lorawan, mbus, redis, and zigbee to the k8s driver list, kustomization, helm values, and compose service stacks
- regenerate k8s driver deployments and preserve the listening-virtual ports in the generator
- replace the per-driver named volumes with one shared driver_data volume isolated by mount path, matching the scale/swarm stacks
- correct scaling docs: compose scale/swarm drivers stay at one replica because replicas would share one SQLite outbox file
2026-08-25 12:06:22 +08:00
pnoker 76ae89370b feat(db): add the mysql seed — dual-engine initdb, row-level revision triggers
R2b of docs/design/storage-abstraction.md §3:

- PostgreSQL seed: the three driver-lease sequences retire. The fencing
  token and assignment version default to 1 and advance row-locally —
  per-device / per-driver monotonicity is the property the checks rely
  on, which the global sequences only delivered incidentally, and MySQL
  has no sequence objects. The three statement-level revision triggers
  (transition tables + INSERT .. ON CONFLICT, none of which MySQL can
  express) collapse into one row-level function with row-local +1 upserts
  — a shape both engines share.

- MySQL seed under dc3/dependencies/mysql/initdb/ (00-06), derived by
  dc3/dependencies/mysql/pg2mysql_seed.py: schemas become databases,
  TIMESTAMPTZ becomes DATETIME(6), TEXT/JSON literal defaults become
  expression defaults (MySQL 8 refuses literal defaults on BLOB/TEXT/
  JSON), operate-time plpgsql triggers become the ON UPDATE column
  attribute (explicit SETs keep winning), the revision family becomes
  row-level DELIMITER triggers, keyed TEXT columns widen to VARCHAR(191),
  partial indexes drop, and the embedded-JSON seed values load under
  NO_BACKSLASH_ESCAPES (MySQL string literals eat the backslashes the
  escaped-JSON content values depend on; PostgreSQL does not). 05 is
  hand-maintained: only the dc3_point_latest projection — a MySQL core
  requires an external time-series store, so the hypertable and cagg DDL
  have no counterpart by design.

- Compose: the optional stack gains a mysql:8.4 service (utf8mb4, seed
  mounted at docker-entrypoint-initdb.d, healthcheck); the app stack
  passes DC3_DB_TYPE through.

Verified by loading all seven files into a fresh mysql:8.4 container —
zero errors, five databases, table counts aligned with the PostgreSQL
seed (manager 24 incl. common, auth 24, data 12, agentic 6, history 1),
and the revision trigger proven live: insert bumps the owning driver's
revision to 1, an enable_flag flip bumps it again to 2.
2026-08-24 17:17:45 +08:00
pnoker d83ead1f64 feat(tsdb): complete the store lineup — influxdb 3 and iotdb adapters, published capability matrix
Phase 3 of docs/design/tsdb-abstraction.md: the store family reaches four
certified adapters, the selection guide publishes the real capability
matrix, and external stores become first-class compose services.

dc3-tsdb-influxdb (3.11.2-core) talks the documented v3 HTTP APIs
directly — line protocol writes, query_sql CSV reads, zero client
dependencies. Integer fields carry the i suffix from the first write (a
bare number binds the column to Float64 forever and destroys ns
timestamps); timestamps cross the wire as CAST(... AS BIGINT)
nanoseconds because JSON renders them in scientific notation; PERCENTILE
is approximate-only and deleteRange does not exist in Core — both
declared honestly (false), the analytics facade computes exact
percentiles from bounded pulls.

dc3-tsdb-iotdb (2.0.10-standalone) maps series onto tree paths
root.dc3.t<tenant>.d<device>.p<point> — path nodes cannot be purely
numeric, so the design's raw-id mapping is amended. The server must run
with timestamp_precision=us and dn_rpc_address=0.0.0.0 (a two-line
properties override shipped under dc3/dependencies/iotdb); WHERE time
literals must use the 2026-08-20T12:59:59+00:00 form because bare epoch
numbers are parsed as milliseconds regardless of the server precision —
a microsecond literal silently matches nothing. Sessions disable
redirection: node discovery hands out internal cluster addresses that
break behind port mappings. GROUP BY LEVEL columns come back
wildcard-shaped and are parsed per column; COUNT rides the INT32 quality
measurement (never null); null measurements are omitted per record — a
null value in insertRecords makes the whole record vanish.

Capability matrix published in docs/tsdb-stores.md per adapter-declared
values (skip counts in the TCK are declared-unsupported cases, degraded
by facades, never wrong data). External store services (tdengine,
influxdb, iotdb) join the optional compose stack with healthchecks and
DC3_TSDB_* passthrough in the app stack.

Gates: timescale 24/24, tdengine 24/24 (2 skips), influxdb 24/24 (2
skips), iotdb 24/24 (3 skips); full-repo compile green.
2026-08-24 16:06:44 +08:00
pnoker 20ae3fbf33 feat(tsdb): add the tdengine adapter — second store certified against the contract suite
dc3-tsdb-tdengine maps the port onto TDengine 3.x: one supertable
point_value tagged by (tenant, device, point), one deterministic subtable
pv_<t>_<d>_<p> auto-created on first insert via USING TAGS, database
created with PRECISION 'us' and KEEP 180. Connection settings live under
dc3.tsdb.tdengine.* (REST driver, own Hikari pool); selected by
dc3.tsdb.type=tdengine. Like the broker family, only the default adapter
(timescale) ships inside consumers — switching deployments add this
dependency plus DC3_TSDB_TYPE/DC3_TSDB_TDENGINE_URL.

The supertable mapping grilled four real issues out of the port
surface, each fixed and locked by the TCK:

- Timestamps never touch string form. The REST driver serializes
  Timestamp parameters in the client JVM zone while the server parses
  them as UTC — every write would shift by the deployment zone and
  cursor pagination would drift per page without end. Instants now
  travel as epoch-micro integer literals and reads return
  CAST(ts AS BIGINT) — verified symmetric against the image.
- AS value collides with a reserved word (agg_value now);
  INTERVAL takes a bare number read in the database (micro) precision.
- PERCENTILE only runs on single tables, so single-series percentiles
  query the deterministic subtable directly; tenant-wide percentile is
  refused rather than approximated.
- REST readiness must be probed with POST /rest/sql + basic auth; the
  GET path-style route 404s even on a healthy server.

Honest capabilities: latencyHistogram=false (dashboard degrades to
zero-filled bins via a capability check) and correlation=false (future
analytics facade computes from bucketed pulls); rollups stay NONE until
S16 lands stream computing. TCK result: 23 tests, 0 failures, 0 errors,
2 capability-gated skips; the timescale suite re-ran 23/23 unchanged.

The design doc's capability matrix now reflects the adapter's declared
values instead of the pre-implementation estimates.
2026-08-21 09:01:24 +08:00
pnoker edadfa0a06 feat(tsdb): rewire the data center onto the tsdb port and retire the repository module
Phase 1b of docs/design/tsdb-abstraction.md: every point-value read and
write now flows through the dc3-tsdb port, and dc3-common-repository is
deleted outright (no compat aliases).

Write path — new PointValueIngestService orchestration in dc3-common-data:
the stale-owner lease guard leaves the history INSERT's cross-schema join
and resolves the active owner per distinct device through the existing
DeviceFacade.getActiveOwner chain; a caffeine-backed ingest idempotency
window (dc3.data.ingest.*, marked only after both writes commit) absorbs
MQ redeliveries now that the message_id unique index is retired; the
batch lands via TsdbStore.append (natural series+time upsert, INGEST_ORDER
kept for the fenced dc3_point_latest upsert).

Read path — history via last(), page() resolves name/enable filters to
series keys through relational metadata (tenant-wide when unrestricted,
cursor offset emulation capped at 10k) with count() for totals; the alarm
window backend becomes TsdbWindowDataSource over aggregate()/history().

Dashboards — all nine data-side hypertable statements move to the S13
analytics facet (count/bucketedCount/countByDimension/latencyHistogram/
lastSeenPerSeries) plus the dc3_point_latest projection for latestStream;
the manager topology statement crosses into the data center via a new
ListSeriesVolumes RPC backed by the new S13-5 seriesCounts primitive (a
point shared by several devices needs per-series counts, which
single-dimension grouping cannot reconstruct); both cross-schema joins
are gone.

Port/adapter — seriesCounts added with a TCK case (23 total); series
filters compile to row-value IN lists chunked at 500 pairs; bootstrap
adds the quality column idempotently and retires uk_point_value_event so
existing deployments converge on the new upsert; the adapter binds the
application-provided tsdbDataSource bean (the history dynamic-datasource
entry) instead of the routing primary.

Timestamps — BO<->Instant conversion is pinned to
TimeConstant.DEFAULT_ZONEID (the platform canonical zone the latest
projection type handler already writes with); the design note's "lock
UTC" is amended accordingly, together with the lease-guard and S13-5
deviations recorded in §6.2.

Seed/deploy — 05-iot-dc3-history.sql gains the quality column and swaps
the unique index; compose carries DC3_TSDB_TYPE; make deploy publishes
dc3-tsdb.

Also fixed along the way: root pom never managed dc3-mq-core (latent,
masked by full-reactor builds); PointValueMapper ran unrouted on the
master datasource (now @DS("history")); latestStream name enrichment
looked up a Long-keyed map with String keys.

Gates: tsdb TCK 23/23, dc3-common-data 262/262, e2e 26/26 including the
unmodified PostgresHypertableIT; full reactor green except dc3-mq-tck's
kafka/pulsar container-startup flake, reproduced identically twice and
unrelated to this change.
2026-08-20 21:58:01 +08:00
pnoker 1ece8d6732 docs(mq): publish broker selection guide and wire dc3.mq.type through deploy config
Close out the mq abstraction rollout:

- docs/mq-brokers.md: user-facing broker selection guide — how to pick
  (DC3_MQ_TYPE + connection settings), the six certified brokers, the
  capability matrix, and the at-least-once/outbox notes
- .env.example + dc3/env/dev.env: DC3_MQ_TYPE and the per-adapter
  connection variables with safe rabbitmq defaults
- docker-compose.yml: DC3_MQ_TYPE and adapter endpoints flow through the
  shared x-app-runtime-env anchor so every service sees the selection
- adapter configurations resolve connection settings from the canonical
  dc3.mq.* property first, then the DC3_MQ_* environment variable, then
  the transport-standard property (spring.kafka.bootstrap-servers),
  making containerized selection deterministic

The gated E2E gate passes unmodified through the port: RabbitDeliveryIT
6/6, CommandCallE2eIT 4/4, EventReportE2eIT 3/3 (full suite 24/24
including postgres and harness ITs) against testcontainers brokers.
2026-08-20 11:10:44 +08:00
pnoker 956de3dd38 feat(driver)!: enforce lease-fenced durable telemetry
Use PostgreSQL leases and fencing for distributed ownership, require a durable SQLite outbox before RabbitMQ publication, and make Data Center ingestion transactional and idempotent.

BREAKING CHANGE: drivers require mandatory durable outbox configuration and use lease-aware ownership and telemetry contracts.
2026-08-18 00:50:57 +08:00
pnoker 7bf615b3b1 feat(driver): configure driver buffer and mount container volume
28 driver application.yml add dc3.driver.buffer; Dockerfile each stage adds dc3/data dir and VOLUME; docker-compose main/dev add driver_data named volume
2026-07-26 00:13:31 +08:00
pnoker 9d69edd0c9 build: add Maven Wrapper and expand docker-compose with all driver services
- Add Maven Wrapper (mvnw, mvnw.cmd, .mvn/wrapper/) for Maven 3.9.11
- Expand docker-compose.yml from 8 to 24 driver services covering:
  industrial bus (BACnet/IP, FINS, MELSEC, EtherNet/IP),
  SCADA/power (IEC 104, SL651, SNMP, DLMS),
  IoT/wireless (CoAP, LwM2M, HTTP),
  serial/network (Serial, TCP/UDP),
  database bridges (MySQL, PostgreSQL, Oracle, SQL Server)
2026-06-28 19:57:56 +08:00
pnoker 2198d7fffe chore: merge iot-dc3-web frontend into monorepo
Merge the standalone iot-dc3-web repository into iot-dc3 as dc3-web/,
creating a single monorepo with unified versioning, CI/CD, and release
process.

- subtree-add iot-dc3-web under dc3-web/ with full commit history
- relocate nginx configs and SSL certs to dc3/dependencies/
- merge CI workflows (ci-backend.yml, ci-web.yml, docker-ci-web.yml)
- merge Issue/PR templates and dependabot config
- host frontend docs under docs/zh/frontend/
- share .husky/ hooks via root-level package.json (pnpm)
- unify versioning: single dc3/bin/tag.sh (vYYYY.M.P) for the whole repo
- update Dockerfile, docker-compose.yml, Makefile for new paths
- remove redundant directories from dc3-web/ (.claude, .github, dc3, docs, bin)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-28 14:43:22 +08:00
Vickey 5131b37568 build(deploy): add postgres/rabbitmq dependency assets and regenerate openapi snapshots 2026-06-19 16:49:01 +08:00
pnoker 1811d4f8ff fix: support reactive wildcard permissions 2026-06-12 11:26:23 +08:00
pnoker ec68f0cb7c feat(rabbitmq): expose tls configuration 2026-06-11 18:03:30 +08:00
pnoker 7a2cc9b8fa chore(compose): streamline environment defaults 2026-06-11 15:04:01 +08:00
Vickey 27bcf1383b fix: address code review — security, thread safety, performance, and null safety
Security (CRITICAL):
- KeyUtil: read JWT signing key from DC3_SECURITY_KEY env/property
- UserPasswordServiceImpl: read default password from DC3_SECURITY_DEFAULT_PASSWORD env
- KeyLoader: read OPC-UA keystore password from OPCUA_KEYSTORE_PASSWORD env
- WebFilterConfig: return 401 on malformed X-Auth-User header
- AlgorithmConstant: document deprecated hardcoded constants

Thread safety (HIGH):
- Fix TOCTOU races in 4 driver connectors (computeIfAbsent)
- Fix PlcS7 lock leak, OpcUa connect timeout (5s)
- CoapClientManager: synchronize setURI to prevent URI race
- PointValueJob, MqttScheduleJob: add @DisallowConcurrentExecution
- SystemHealthServiceImpl: preserve interrupt flag
- WindowSampleBuffer: local AtomicInteger → int

Performance (MEDIUM):
- EntityStateExpiryScanner: batch alarm saves (saveBatch)
- ImportDeviceServiceImpl: batch config saves
- ResourceRegistrySyncServiceImpl: batch-load nodes, eliminate N+1 COUNTs
- DriverSenderServiceImpl: debug-gate hot-path logging
- PointServiceImpl: stream().count() → size()

Null safety (LOW):
- RegexUtil: null guards on isName/isPhone/isMail/isPassword/isHost
- HostUtil: null-check getNetworkInterfaces() return
- TimeUtil: log parse failures instead of silent null

Infrastructure:
- Add spring-boot-starter-cache + @EnableCaching CacheConfig
- Replace embedded modbus4j/plc-s7 jars with external Maven dependencies
- Add dc3-driver-modbus-rtu module
2026-05-26 08:40:25 +08:00
pnoker cb423056c7 security(auth): enable HMAC gateway-to-service signing by default
Set AUTH_HMAC_SECRET default to "io.github.pnoker.dc3" across .env
templates, compose files, and Java config properties so that X-Auth-User
header signing is active out of the box without manual configuration.
2026-05-19 23:15:34 +08:00
pnoker 83ee84773a build: refactor Dockerfile, Makefile and compose files
Parametrize JDK/JRE base images via build args in Dockerfile, replace
hardcoded GC/dump env vars with per-service path variables, fix APM
port. Simplify Makefile registry options to global|cn, add SERVICES
and GROUP selectors for targeted compose operations.
2026-05-17 22:16:30 +08:00
pnoker b9b2a47732 feat(docker): add web frontend and consolidate compose stacks
Add dc3-web frontend service to docker-compose.yml with nginx reverse
proxy as the sole user-facing entry point. Remove backend port mappings
since web now proxies to gateway.

Merge docker-compose-elasticsearch.yml and docker-compose-grafana.yml
into a single docker-compose-optional.yml that includes EMQX, ELK+APM,
and Prometheus+Grafana stacks.
2026-05-17 19:02:52 +08:00
pnoker 7847bffbd8 fix(agentic): preserve reasoning through tool loop 2026-05-17 00:59:46 +08:00
pnoker 285ed9273f feat(agentic): configure fallback provider and profile activation 2026-05-11 18:57:53 +08:00
pnoker d65fc715ff build(deploy): add agentic memory and tool-calling env variables to docker-compose
Expose AGENTIC_MEMORY_ENABLED, AGENTIC_TOOL_CALLING_ENABLED,
AGENTIC_MEMORY_MAX_MESSAGES, and AGENTIC_ATTACHMENT_STORAGE_PATH
in development and production compose files, with defaults in dev.env.

Also mark OpenAI base-url config as deprecated in application-agentic.yml.
2026-05-11 00:44:44 +08:00
Vickey 9d7e238eb1 refactor(config): update default AI model to deepseek-v4-flash and agentic env variables 2026-05-10 21:43:58 +08:00
Vickey 0e92643d54 feat(config): add AUTH_HMAC_SECRET to all deployment configurations
The HMAC signing feature was dormant because no deployment config
set the shared secret. Add AUTH_HMAC_SECRET to .env.example, dev
env files, both compose stacks (all 12 services), and document it
in ENVIRONMENT.md.
2026-05-10 01:48:51 +08:00
pnoker 6cf9b43c30 docs(env): align runtime environment variables 2026-05-09 20:14:16 +08:00
pnoker 8fa1f0c152 refactor(container): deduplicate aliyun compose stacks 2026-05-09 18:49:52 +08:00
pnoker a45f2f5ec1 fix(container): include agentic compose service 2026-05-09 18:49:52 +08:00
pnoker ca38651909 feat: add .env file for Docker Compose configuration and update usage instructions 2026-04-21 01:11:59 +08:00
pnoker e33dcc1573 fix: update Docker images to version 2026.5 across all docker-compose files 2026-04-20 03:16:30 +08:00
Vickey a9e8d05631 feat: update version 2025-10-05 17:16:37 +08:00
Vickey 7302107c56 chore: bump all module versions to 2025.9.2 2025-09-11 17:02:24 +08:00
Vickey 2051d42847 refactor(common): remove hutool dependency and replace usages with native utilities 2025-09-11 14:57:02 +08:00
Vickey 8cc7365293 build: bump all module versions to 2025.6.6 and update compose image tags 2025-08-26 22:38:53 +08:00
Vickey 64c6f911fe chore: replace Apache-2.0 license headers with AGPL-3.0 in compose files and gateway config 2025-08-26 22:03:42 +08:00
Vickey f415207088 build: bump project version to 2025.6.5 across all modules 2025-07-15 14:58:51 +08:00
Vickey 31a6a275ed build: bump project version to 2025.6.4 across all modules 2025-07-15 12:01:43 +08:00
Vickey 886b212793 build: bump project version to 2025.6.1 across all modules 2025-06-21 16:21:18 +08:00
Vickey 877be41317 build: bump project version to 2025.6.0 and remove unused job/register dependencies 2025-06-09 15:48:22 +08:00
Vickey 6898041ab5 feat(docker): add APM agent env vars and dc3-apm service to all Dockerfiles and compose files 2025-05-06 21:19:03 +08:00
Vickey b01412f460 chore(docker): change NODE_ENV from dev to test in all Dockerfiles and compose files 2025-05-06 16:55:20 +08:00
Vickey a0ed920ba2 feat(compose): split db stack into docker-compose-db.yml and expand dev/aliyun services 2025-05-06 01:11:46 +08:00
pnoker 083a7e748c chore(docker): standardize string quotes and add new compose files
Standardized the use of double quotes in docker-compose files for consistency. Added new docker-compose files for optional and Aliyun configurations to support different deployment environments.
2025-04-25 20:46:30 +08:00
pnoker d99e0408f2 chore: update version to 2025.2.5 across multiple files
Updated the version from 2025.2.4 to 2025.2.5 in pom.xml files and various Java classes to reflect the latest release. This change ensures consistency across the codebase and aligns with the new version of the IoT DC3 Platform.
2025-04-25 16:22:39 +08:00
pnoker a49def0595 chore: update project version to 2025.2.4 across all modules
Updated the version from 2025.2.2 to 2025.2.4 in all pom.xml files, Java classes, and CI/CD configurations to reflect the latest release version. This change ensures consistency across the entire project.
2025-04-24 19:46:54 +08:00
pnoker af044ecc83 chore: bump all module versions to 2025.2.2 and update CI gateway image tag 2025-04-21 22:12:44 +08:00
Vickey 3bd3717bac build(docker): bump base image version in all Dockerfiles and slim docker-compose.yml 2025-03-05 01:13:36 +08:00
pnoker 9faa287480 build: restructure Dockerfiles and compose files for all services 2024-12-04 19:49:38 +08:00
zzi666 e3189e5926 feat(center): add dc3-center-single all-in-one service module 2024-08-31 16:35:02 +08:00
pnoker 480250f565 chore: update base image tag in all Dockerfiles and compose files 2024-06-19 00:56:17 +08:00
pnoker b52aaf550a build: remove legacy Dockerfiles, compose files, and update scripts 2024-06-11 20:15:12 +08:00
pnoker 652224eb67 feat: optimize bulk import across auth, data, and manager services 2024-05-26 17:52:48 +08:00