Commit Graph
3626 Commits
Author SHA1 Message Date
pnokerandClaude Code 56ec00f3c8 docs(release): update generated changelog and bump to 2026.10.10
Co-Authored-By: Claude Code <noreply@anthropic.com>
v2026.10.10
2026-10-17 01:21:08 +08:00
pnokerandClaude Code 0a0ea41142 ci(native): move opc-ua off the driver native matrix after the runner oom
The opc-ua driver (Eclipse Milo + netty + jaxb universe) exhausts the
16GB hosted runner during the native-image analysis step even with
-J-Xmx10g; it builds fine on larger local machines. Its native image has
never shipped, so dropping it from the matrix removes nothing users
already have. It stays on the JVM line with dnp3/ble/opc-da until the
heap cap is property-driven or a larger runner hosts the job.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-17 01:20:24 +08:00
pnokerandClaude Code 302cef047b docs(release): update generated changelog and bump to 2026.10.10
Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-17 00:30:40 +08:00
pnokerandClaude Code cebb762804 fix(native): carry agent snapshots for the mqtt and modbus-tcp drivers
Both drivers died at boot with NoClassDefFoundError on
org.slf4j.MarkerFactory: their protocol SDKs (Paho, Modbus4J via the
mangoautomation repository) exercise ServiceLoader paths that
DriverNativeRuntimeHints does not express, and unlike the rest of the
driver line they had no agent snapshot to close the gap. The snapshots
are committed per native_agent_collect.sh's stated-reason exception:
booting each repackaged JAR with the native-image-agent records the
SLF4J/logback binding metadata the closed-world analysis needs.

Verified by rebuilding both native images from scratch and running them
bare against a live broker: both subscribe on untagged dc3.q.* queues
and stay up instead of crash-looping.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-17 00:27:08 +08:00
pnokerandClaude Code 8e558e0d74 fix(native): default spring env in native runtime so broker topology stays untagged
Native binaries cannot re-resolve the spring.profiles.active
${NODE_ENV:dev} placeholder at runtime: the AOT pass freezes the dev
profile (and application-dev.yml) into the image. RabbitEnvironmentConfig
then reads spring.env=dev and prefixes every exchange and queue with the
dev_<user> isolation tag, which silently splits the broker topology
against JVM services running with NODE_ENV=test (messages end up
NO_ROUTE between the two lines).

Build-time profile pinning does not reach the AOT snapshot (verified
with NODE_ENV, SPRING_PROFILES_ACTIVE env vars and MAVEN_OPTS system
properties). SPRING_ENV feeds the same EnvironmentPostProcessor through
the system-environment property source, which outranks profile YAML at
runtime, so one ENV default in native-runtime-base covers every native
target. Deployments that want an isolation tag can override the
variable.

Verified by rebuilding dc3-driver-virtual-native and running the image
bare: subscriptions now use untagged dc3.q.* names.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-16 10:43:01 +08:00
pnokerandClaude Code 3c43e720bd fix(native): drop the duplicated swagger pin and reword the buffer comment
Two fast CI gates caught the tail of the driver native campaign: the
root pom declared swagger-annotations-jakarta twice (the pin already
existed next to the mockito pins - Maven 4 treats the duplicate
dependencyManagement entry as an error, which killed every early plain
mvn invocation on CI while local 3.9 only warned), and the r2dbc
migration gate's literal jdbc: pattern matched the hyphenated
'sqlite-jdbc:' inside a DriverNativeRuntimeHints comment. Remove the
duplicate entry and reword the comment; no gate semantics change.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-14 08:00:41 +08:00
pnokerandClaude Code b965acd5ef feat(native): register the sl651 optional dependency bridge
Sl651DriverCustomServiceImpl reaches the SL651 stack through
Class.forName and a JDK proxy over an optional dependency. Without
registration a native image silently takes the sl651ApiMissing branch:
the driver boots and reports health but never receives a message. Add a
module-level Sl651NativeRuntimeHints registering SL651Server and
ISl651MessageListener, wire it through aot.factories, and carry the
module's tracing snapshot. Functional acceptance remains a live SL651
message round-trip on real hardware.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-14 01:34:48 +08:00
pnokerandClaude Code 9832bd6b4a feat(native): onboard the jserialcomm serial driver batch
Batch 3 joins the native line: modbus-rtu, serial, mbus, dlt645, dlms
and zigbee - the jSerialComm serial family. jSerialComm ships no
native-image configuration of its own, so DriverNativeRuntimeHints
registers the embedded per-platform JNI libraries as resources and the
SerialPort JNI surface explicitly (string-based references keep
non-serial drivers unaffected). The tracing snapshots carry the early
boot surface only - serial paths open on device access and stay covered
by the explicit registrations. zigbee is best-effort: no radio hardware
locally, gRPC registration and scheduling are the acceptance line.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-14 01:34:47 +08:00
pnokerandClaude Code b73e4cfa35 feat(native): onboard the database and messaging driver batch
Batch 2 joins the native line: mysql, postgresql, sqlserver, oracle,
redis and kafka - database dialects and messaging clients, all pure
Java. DriverNativeRuntimeHints gains the four JDBC dialect driver
constructors (string-based TypeReferences; each class exists only on
its own driver's classpath and native-image ignores hints for absent
classes). Same generated shape as the previous batches: targets, matrix
entries, compose blocks and per-driver agent snapshots.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-14 01:21:49 +08:00
pnokerandClaude Code 61420025e7 feat(native): onboard the protocol sdk driver batch
Batch 1b joins the native line: knx, bacnet-ip, melsec, plcs7, lorawan,
opc-ua, lwm2m and iec61850 - pure-Java protocol SDKs (calimero,
bacnet4j, iot-communication, milo, leshan, openiec61850). iec61850's
GOOSE raw-ethernet paths stay untested on native and are validated in
TCP mode only, as flagged in the CI matrix comment. Same shape as batch
1a: native targets, matrix entries, compose overlay blocks behind the
native-drivers profile, and per-driver agent snapshots.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-14 01:15:18 +08:00
pnokerandClaude Code 691d8a6ade feat(native): onboard the pure java protocol driver batch
Batch 1a joins the native line: tcp-udp, listening-virtual, can,
ethernet-ip, fins, http, snmp, iec104 and coap - pure-Java protocol
stacks with no JNI dependencies. Native targets mirror the jar line's
directory layout (listening-virtual keeps its TCP/UDP EXPOSEs), the CI
matrix gains the nine entries, and the compose overlay defines the nine
services behind the native-drivers profile with keys matching
docker-compose.yml so overlay semantics hold (the pilot keys are renamed
to the short main-compose form for the same reason).

Each driver carries a tracing-agent snapshot per the dual-track policy:
RuntimeHints covers the shared SDK surface, snapshots carry the
logback/logstash parsing depth and per-protocol reflective access.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-14 01:01:31 +08:00
pnokerandClaude Code 1dcb57278f fix(native): carry the virtual driver agent snapshot and declare opts arg
The first native boot of dc3-driver-virtual died in MarkerFactory's
static initializer: the SLF4J->logback binding needs the full logback
config-parsing reflection surface (TurboFilter, DefaultJoranConfigurator,
PatternLayoutEncoder, the logstash encoder family), which the bounded
RuntimeHints subset cannot express. Commit the tracing-agent snapshot -
same dual-track as the six native services - and declare the
MAVEN_OPTS_EXTRA build arg the driver stage references.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-14 00:45:00 +08:00
pnokerandClaude Code bc9144a8b0 docs(native): document the driver batches and jvm exceptions
Parameterize the agent-collection script with
DC3_NATIVE_AGENT_SERVICES and state the driver policy: snapshots are
diagnostics only, the driver line is driven by RuntimeHints. Extend the
helm README's native section with the pilot batch and the three drivers
that stay on the JVM (dnp3 Rust FFI, ble TinyB/JNA, opc-da vendored
DCOM).

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-14 00:27:09 +08:00
pnokerandClaude Code 0664fef7e2 ci(native): fan driver native builds out as a matrix
A serial driver loop cannot fit the 360-minute GitHub job cap once the
later batches join. Add a build-native-drivers matrix job (one driver
per job, fail-fast off, max-parallel five, its own gha cache scope) that
pins the NATIVE_SERVICE build arg to the matrix service, and gate the
release job on it.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-14 00:27:08 +08:00
pnokerandClaude Code 498af7f8db feat(native): add the pilot drivers to the native compose stack
Define driver-virtual (default) plus driver-mqtt and driver-modbus-tcp
behind a native-drivers profile; they need an external broker / modbus
slave to talk to. Container names, aliases and volumes match
docker-compose.yml one-for-one, so the JVM and native variants never
collide and stay freely mixable with the jar compose stack.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-14 00:27:07 +08:00
pnokerandClaude Code 4eb2515e59 feat(native): build driver native images via an arg-scoped stage
Add a driver-native-builder stage that installs and native-compiles
exactly one driver per build, selected by the NATIVE_SERVICE build arg.
Kept separate from native-builder so the center build's cached layers
stay byte-identical: ARG values participate in the BuildKit cache key,
and the CI matrix needs every job to compile only its own driver. Ship
the pilot targets dc3-driver-{virtual,mqtt,modbus-tcp}-native with the
jar line's directory layout so volumes and log paths keep matching.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-14 00:27:07 +08:00
pnokerandClaude Code 951d20bd98 feat(native): seed driver runtime hints for graalvm images
Register the driver SDK's reflective runtime paths (Quartz jobs,
@Dc3Listener receivers, Caffeine policies, sqlite-jdbc buffer resources,
logback/gRPC ServiceLoader descriptors) so driver modules can be AOT
processed like the centers.

Driver AOT processing surfaced a latent classpath bug: dc3-common-public
declared the springdoc starter but uses none of it, so its SpringDocHints
registrar (which unconditionally references spring-web) blew up AOT for
every driver - drivers have no spring-web. Drop the stale dependency and
let each real consumer declare its own: model and the gateway common
module take the annotation-only swagger-annotations-jakarta (model sits
on the driver classpath), while data/auth/agentic take the starter for
GroupedOpenApi.

Verified: process-aot on dc3-driver-virtual emits all hints into the
spring-aot reachability metadata; spotless, checkstyle and documentation
gates pass, as do the public and module test suites.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-14 00:22:21 +08:00
pnokerandClaude Code 8381741d6e fix(web): keep code comments in english for the docs gate
The card wall change quoted the Chinese auto-size label inside code
comments; check_documentation.py rejects non-English comments and the
web CI quality gate failed on it. Quote the English label in those
examples instead. The bilingual button matcher in the responsive e2e
spec is functional code (it matches either locale) and stays.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-13 01:22:06 +08:00
pnokerandClaude Code 013c9414a3 test(web): normalize guardrail walk paths for windows
Raw Windows backslash paths never matched the guardrails'
separator-agnostic directory filters, so the suite passed vacuously on
dev machines while still enforcing on POSIX CI. Normalize to POSIX
separators at the walk source so the guards actually scan everywhere.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-13 00:55:27 +08:00
pnokerandClaude Code 74abe61711 feat(web): fit card wall pages to the viewport with ghost rows
Fixed 12-per-page card walls left ragged trailing rows at wide viewports
and over-fetched on narrow ones. Derive the page size from the wall's
measured column count, pad the last row with ghost slots so the grid
never ends ragged, keep the previous page under an activity line while
revalidating (no skeleton flash), and let users pin a size via an
explicit auto/manual select beside the pager. Cursor walls keep their
prev/next controls running beside the select, and size changes reset the
cursor stack where position cannot be preserved. Ships with unit,
component, guardrail and responsive e2e coverage.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-13 00:55:20 +08:00
pnokerandClaude Code 9dfb86cfb9 fix(web): accept both salt response shapes on login
Backend versions answer /token/salt with either a {salt} envelope or a
bare salt string; the envelope-only read bricked login on the bare form
before generateToken fired. Resolve both shapes in the login flow and
keep pure payload adapters out of src/api so the transport-contract
matrix stays exact. Covers the bare-string and empty-salt shapes with
unit tests.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-13 00:55:00 +08:00
pnokerandClaude Code f7fcedeaff test(web): realign auth and dashboard contract tests with the api surface
The httpOnly-cookie auth refactor changed generateSalt and the token
endpoints to object responses, and the device dashboard wrapper now
carries device_id as a query parameter; the stale mocks, assertions,
and snapshots never ran on CI because earlier gate layers failed
first. Update them to the current contracts.

Co-Authored-By: Claude Code <noreply@anthropic.com>
v2026.10.9
2026-10-09 03:19:57 +08:00
pnokerandClaude Code 6cce14086d test(web): flush promises instead of reaching into wrapper.vm
The agentic component tests drove reactivity through
wrapper.vm.$nextTick(), which the ai-guardrails contract rejects as
coupling to component internals. Use flushPromises from the test utils
surface instead.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-09 01:48:45 +08:00
pnokerandClaude Code a47d4764a4 fix(driver): convert invalid serial port descriptors to driver failures
Linux jSerialComm throws SerialPortInvalidPortException from
getCommPort on invalid descriptors instead of returning an unopenable
port object, so every serial driver leaked a runtime exception on
adversarial configs instead of failing safe. Wrap the four serial
connection factories (dlt645, mbus, serial, modbus-rtu) and surface the
failure as a ConnectorException.

Surfaced by the adversarial contract on the Linux CI runner, where the
Windows-local run masked it.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-09 01:08:56 +08:00
pnokerandClaude Code 15897e8a58 fix(data): replace path-variable device routes with query params
The device-scoped dashboard endpoints and the device-status detail route
used @PathVariable paths, violating the route-naming contract that has
been in force since the quality-gate standardization. Move the device id
to a device_id query parameter across the ten routes and align the web
client callers.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-09 00:52:09 +08:00
pnokerandClaude Code e53023cf2a fix(ci): allow the bounded system tool bridges in the migration gate
The agentic SystemTool must expose a synchronous contract to Spring AI
(reactive returns serialize the publisher, not the result) and the
runtime drives those callbacks on the bounded elastic scheduler, so
both bridges are deliberate and bounded. Document them next to the
existing startup-validator exemption instead of weakening the scan.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-09 00:31:05 +08:00
pnokerandClaude Code 98c0f8a6c3 fix(ci): sync the mockito integrity pin and document the insight rpc
The mockito jar sha1 pin still targeted the pre-upgrade artifact while
the build resolves 5.24.0, so every CI run failed the agent-integrity
check even after refetching. Re-pin to the 5.24.0 jar sha1 verified
against Maven Central metadata.

Document the InsightApi.Invoke RPC in the dc3-api-data README so the
proto-to-documentation guard passes.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-09 00:25:11 +08:00
pnokerandClaude Code 7c044c7761 docs(release): update generated changelog and bump to 2026.10.9
Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-09 00:16:02 +08:00
pnokerandClaude Code da5d748112 fix(agentic): make system tools synchronous so spring ai serializes results
Spring AI 2.0.1's MethodToolCallback serializes the declared return
value as-is: a Mono return type serialized the publisher object, and
Jackson rendered reactor's isScanAvailable() getter as
{"scanAvailable":true}. Every SystemTool call - including the
pre-existing getSystemHealth - returned that garbage instead of data.

Rewrite SystemTool as synchronous with a bounded block, and run @Tool
callbacks on the bounded elastic scheduler in the runtime so the block
never lands on the event loop. Add a Spring AI bridge regression test
that fails if the serialized shape ever degrades again.

Found by the live agent during the status-tool end-to-end run.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-09 00:02:38 +08:00
pnokerandClaude Code fa0cf971ae fix(data): normalize agent-supplied percentiles instead of crashing
The analytics percentile helper interpreted its input strictly as a
[0,1] fraction, so agent callers spelling percentiles as percentages
(95) or drifting past the scale crashed computeStats with an
ArrayIndexOutOfBoundsException. Normalize percentage-spelled values and
clamp the remainder so the agent surface degrades gracefully.

Found by the live agent during the insight-channel end-to-end run.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-08 23:38:50 +08:00
pnokerandClaude Code a2f51fa818 fix(mq): wire the mqtt endpoints explicitly, not through dead annotations
spring boot 4.1.1 moved the integration auto-configuration out of the
main autoconfigure jar, no module pulls spring-boot-integration and
none declares @EnableIntegration, so the messaging annotation
infrastructure is absent on every consumer classpath and the
@ServiceActivator endpoints were silent no-ops: the inbound channel
had producers only and the first message killed the paho connection.
subscribe explicit EventDrivenConsumer beans for both directions
(identical to what the annotation machinery would have created),
guard with message-flow tests that reproduce the exact production
exception on the old wiring, and prove the full production path
against a real mosquitto broker via the MqttContainer IT.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-08 10:13:56 +08:00
pnokerandClaude Code 2914b09e2c test: lock tool schemas and insight routes plus fix a stale stub
Harden the agentic tool gate with two guards: every registered tool's
input schema must be parseable JSON, and every canonical insight
operation must route to its backing service without unknown-operation
errors.

Fix the pre-existing JdbcDriverCustomServiceTest failure where the
connection validity stub used isValid(5) while the production health
probe calls isValid(2), leaving the stub unmatched and the assertion
flipping to OFFLINE.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-08 09:04:00 +08:00
pnokerandClaude Code c64a292f9b feat(agentic): complete the tool surface with status insight and history tools
Register the seven implemented-but-unregistered tool methods
(command/event by-device, by-profile and batch lookups plus driver batch
lookup), expose the four idle StatusHealthFacade fleet-status reads
through SystemTool, and add InsightTool (25 operations via the insight
channel) and HistoryTool (command/event record lookups) to the reactive
registry - growing the surface from 28 to 64 tools.

Lock the exact registry tool-name set in a test so any future orphan
method fails the build instead of silently disappearing.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-08 00:08:41 +08:00
pnokerandClaude Code 812d5e97cc feat(data): add the agent-facing insight channel with history facades
Add a generalized insight channel (insight.proto + InsightDispatcher +
InsightServer) routing 25 read-only operations - alert analytics,
dashboard stats, the nine analytics agent-surface operations and the
point command status lookup - through JSON payloads so both gRPC and
local transports share one routing implementation with defensive
argument clamping.

Add strong-typed CommandHistoryFacade and EventHistoryFacade contracts
(BO, local implementation, gRPC implementation, stub beans and both
auto-configuration whitelists) so agents can trace command execution
results and reported events.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-08 00:08:24 +08:00
pnokerandClaude Code ef6f2a5d65 fix(coap): attach a started endpoint to every pooled coap client
californium 4.0.0-M6 clients never auto-create a transport endpoint,
so client.getEndpoint().getConfig() NPE'd on every read and write
before any udp packet was sent. build a started endpoint per client
with the configured timeouts (previously the write path never received
them), fail loudly if an endpoint is somehow missing, and guard with
in-jvm coap server end-to-end tests for get and put.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-07 23:34:52 +08:00
pnokerandClaude Code 0e5f2bf88e fix(mq): register the mqtt receive beans from the auto-configuration
@ConditionalOnBean on a component-scanned handler evaluates during
scanning, before the driver's MqttReceiveServiceImpl definition is
registered, so the subscriber bean was never created: the inbound
channel had producers only, the first message killed the paho
connection with no reconnect, and the mqtt driver could never deliver
data. move the handler, its @ServiceActivator, and the schedule job
into MqttConfig's auto-configuration where conditions evaluate after
all consumer definitions exist; guard with ApplicationContextRunner
tests that fail on the old arrangement (proven by stash-and-rerun).

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-07 23:34:51 +08:00
pnokerandClaude Code e834dde9cf fix(compose): sync the schema fingerprint across all six stacks
the fingerprint sync tool only knew two compose distribution points, so
native, scale, single and swarm still defaulted to the pre-attachment
hash while the running database and the other stacks moved on. register
all six compose files as distribution points and resync.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-07 23:34:35 +08:00
pnokerandClaude Code cb7980a045 fix(mq): single-source rabbitmq connection config in the sdk carrier
23 of 36 driver modules (and dc3-center-single) never shipped
application-{test,pre,pro}.yml while the compose anchor hardcodes
NODE_ENV=test, so spring.rabbitmq fell back to localhost:5672 and the
containers crash-looped out of the box. the connection placeholders now
live once in dc3-mq-rabbitmq's application-rabbitmq.yml, whose profile
ActiveRabbitProfileConfig already activates in every embedding service;
83 copy-pasted per-module blocks removed (also fixing drifted port
defaults 35672/45672 inside four modules) and a validator
(validate-driver-config) now enforces the single source.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-07 23:34:34 +08:00
pnokerandClaude Code cfa2ee75d7 docs: remove the docs directory
every remaining document was either a living deployment guide, an
active design baseline, or an unimplemented proposal - all retrievable
from git history. the open work they carried now lives in issues:
#259 r2dbc acceptance gates, #260 comparison adoption candidates, plus
the design-direction issues referenced there. all inbound references
(agents, contributing, seven multilingual readmes, compose comments,
gateway config, module readmes, source comments) updated so nothing
points at the removed tree.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-07 15:08:16 +08:00
pnokerandClaude Code 3a78079a75 docs: retire executed handoffs, fixed tech-debt audit, and open-review comparisons
the r2dbc migration handoff defined release gates that never ran - the
gate stages moved to issue #259 (full text stays in git history) and
relational-r2dbc.md remains as the semantic baseline. the ai-assistant
tech-debt audit is 10/10 fixed; its one long-term survivor (indexeddb
persistence) is recorded on issue #255. the two competitive comparisons
were open-review reference, never a roadmap; their adoption candidates
moved to issue #260.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-07 14:45:39 +08:00
pnokerandClaude Code a2a01e9155 docs: retire three landed design proposals
mq-abstraction (four broker adapters now tck-gated), storage-abstraction
(flag day, postgres-only runtime), and tsdb-abstraction (single
implementation, no historical adapters) all describe designs that live
in the code now; their semantics are enforced by tests, not prose.
relational-r2dbc stays: it is the design baseline the r2dbc migration
test handoff still validates against. cross-references in the
comparison docs and mcp-runtime-overhaul updated to plain wording.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-07 11:40:16 +08:00
pnokerandClaude Code 0a6033b816 docs: retire two one-shot review handoffs
the web low-defects handoff was fully executed (spot-verified: the
loadMessages streaming guard, menu cycle guard, paged-list clamp,
e2e port fail-fast all landed); its five human-decision items moved
to issue #257 (password-in-url split out to #256). the thing-model
review was a factual capability snapshot; its open gaps moved to
issue #258.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-07 11:35:27 +08:00
pnokerandClaude Code 0de4d941c7 docs(cli): remove the one-shot campaign report
the report served its purpose: every finding is fixed and guarded by
executable tests, the fix history lives in git, and the still-open
items moved to issues #251-#255.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-07 11:25:23 +08:00
pnokerandClaude Code e6b658be25 docs(cli): record the restack full-test epilogue
append the wsl docker rebuild campaign: 46 live checks, the two
failures root-caused (attachment identity, spa fallback), the on-disk
fixes, and the decision items observed against the real stack.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-07 08:48:33 +08:00
pnokerandClaude Code 245638d94f docs(data): match driver status casing to serialized values
the driver status endpoints serialize lowercase online/offline;
align the javadoc and openapi descriptions so consumers are not told
to expect uppercase codes.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-07 08:48:32 +08:00
pnokerandClaude Code 78f0edeba1 fix(bin): parse the json salt contract in onboard_virtual
the auth salt endpoint now answers with a json object; read the salt
field instead of stripping quotes off a bare text body.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-07 08:48:32 +08:00
pnokerandClaude Code fe57a03c4d fix(nginx): add spa history fallback to the web location
location / only had root and index, so path-shaped urls like /login
returned the default nginx 404 page instead of the app shell; hash
routing masked it, but manual and external links broke. Add try_files
$uri $uri/ /index.html.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-07 08:48:31 +08:00
pnokerandClaude Code 234b93ce5d fix(db): generate attachment ids and resync the schema fingerprint
dc3_attachment.id lacked GENERATED BY DEFAULT AS IDENTITY (unlike
dc3_session/dc3_message), so R2dbcAttachmentStore inserts without an
id violated NOT NULL and every upload failed with HTTP 500. Add the
identity clause to the canonical initdb DDL, ship idempotent migration
04 for databases initialized before the fix (with a setval guard so
pre-existing explicit ids never collide), and resync the canonical
fingerprint 0d9ad803... across the embedded hash and every distributed
default.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-07 08:48:15 +08:00
pnokerandClaude Code b588204110 feat(cli): adopt the remaining guardian tests and auth store fix
adopts the remaining uncommitted work from the parallel session:
five new guardian test files (client-errors, device-import-template,
entity-id-guard, jwt-guard, option-hygiene) that lock in the error
taxonomy, id encoding, and cli option hygiene; an attachment file
cleaner in the agentic service; attachment controller and service
tests; a salt-type fix in the auth store; ci workflow typecheck step;
and the cli test report. 818 tests total across 37 files.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-06 21:26:15 +08:00
pnokerandClaude Code 09eba4b033 fix(web): use a 3-column stat grid on the device dashboard
four columns left the sixth tile dangling on a second row alone;
three columns closes the 2x3 row math to match the point dashboard.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-06 21:17:05 +08:00