]> Piment Noir Git Repositories - e-mobility-charging-stations-simulator.git/log
e-mobility-charging-stations-simulator.git
8 days agorefactor(ui-common): generic WebSocket adapter factory with converter injection
Jérôme Benoit [Thu, 16 Apr 2026 20:39:18 +0000 (22:39 +0200)] 
refactor(ui-common): generic WebSocket adapter factory with converter injection

Create ui/common/src/client/adapter.ts — a generic createWsAdapter(ws, options)
factory that implements all WebSocketLike callback boilerplate once. Both adapters
become thin wrappers specifying only their platform-specific data converter:

- createBrowserWsAdapter: data => data as string, errorDefault: 'WebSocket error'
- createWsAdapter (CLI): toDataString() for Buffer/ArrayBuffer, errorDefault: 'Unknown error'

Net reduction: ~143 lines of duplicated boilerplate eliminated.
Add DataConverter type and tests for the generic factory.

8 days agorefactor(cli): extract extractErrorMessage utility
Jérôme Benoit [Thu, 16 Apr 2026 20:26:06 +0000 (22:26 +0200)] 
refactor(cli): extract extractErrorMessage utility

Create ui/cli/src/utils/errors.ts with extractErrorMessage(error: unknown): string
and replace 3 inline occurrences of the pattern across formatter.ts, json.ts,
and loader.ts.

8 days agorefactor(ui-common): derive ClientConfig and AuthenticationConfig from Zod schemas
Jérôme Benoit [Thu, 16 Apr 2026 20:22:56 +0000 (22:22 +0200)] 
refactor(ui-common): derive ClientConfig and AuthenticationConfig from Zod schemas

Replace two hand-written interfaces in client/types.ts with type aliases
derived from the Zod-inferred UIServerConfigurationSection:
- AuthenticationConfig = NonNullable<UIServerConfigurationSection['authentication']>
- ClientConfig = Omit<UIServerConfigurationSection, 'name'>

This eliminates duplication: protocol/version now carry enum types (Protocol,
ProtocolVersion) instead of loose strings. Update WebSocketClient.test.ts to
use Protocol.UI and ProtocolVersion['0.0.1'] enum values accordingly.

8 days agorefactor(ui): consolidate constants — remove timeout duplicate, centralize defaults
Jérôme Benoit [Thu, 16 Apr 2026 19:39:21 +0000 (21:39 +0200)] 
refactor(ui): consolidate constants — remove timeout duplicate, centralize defaults

- Remove dead duplicate UI_WEBSOCKET_REQUEST_TIMEOUT_MS from ui/web/src/composables/Constants.ts
- Add DEFAULT_HOST ('localhost') and DEFAULT_PORT (8080) to ui/common/src/constants.ts
- Update ui/cli/src/config/defaults.ts and loader.ts to import from ui-common
- Update ui/web/tests/unit/constants.ts to use DEFAULT_HOST/DEFAULT_PORT from ui-common
- Update ui/cli/tests/config.test.ts to import from ui-common

8 days agorefactor(ui-common): remove UIServerConfig alias, single canonical name
Jérôme Benoit [Thu, 16 Apr 2026 17:07:53 +0000 (19:07 +0200)] 
refactor(ui-common): remove UIServerConfig alias, single canonical name

UIServerConfigurationSection is the only exported name for the UI server
config type. The UIServerConfig alias added for backward compat is removed;
CLI consumers (loader.ts, lifecycle.ts) migrated to the canonical name.
README updated accordingly.

8 days agotest: add enum rejection tests and fix dynamic import in CLI test
Jérôme Benoit [Thu, 16 Apr 2026 16:33:37 +0000 (18:33 +0200)] 
test: add enum rejection tests and fix dynamic import in CLI test

- Add 2 edge-case tests for invalid protocol/version enum values
  (protocol: 'ws' and version: '2.0' are now correctly rejected)
- Replace unnecessary dynamic import with static import in
  lifecycle.test.ts for consistency with other test files

8 days agorefactor(ui-common): derive UIServerConfigurationSection from Zod schema
Jérôme Benoit [Thu, 16 Apr 2026 16:20:47 +0000 (18:20 +0200)] 
refactor(ui-common): derive UIServerConfigurationSection from Zod schema

Make uiServerConfigSchema the single source of truth for the UI server
configuration shape. The hand-written interface in ConfigurationType.ts
is removed; UIServerConfigurationSection is now inferred via z.infer<>.

- Tighten schema: protocol and version use z.enum() instead of z.string()
  (follows existing z.enum(AuthenticationType) pattern, Zod v4)
- Export UIServerConfigurationSection as the primary inferred type
- Export UIServerConfig as a backward-compat alias
- ConfigurationType.ts imports UIServerConfigurationSection from schema.ts
  and re-exports only ConfigurationData
- CLI defaults.ts uses Protocol.UI and ProtocolVersion['0.0.1'] enum values
  instead of plain string literals to satisfy the tightened type
- CLI lifecycle.test.ts updated to use enum values in typed config literal

Zero duplicate field definitions. All quality gates pass.

9 days agotest(web): cover abort branches in UIClient to meet coverage threshold
Jérôme Benoit [Thu, 16 Apr 2026 14:46:01 +0000 (16:46 +0200)] 
test(web): cover abort branches in UIClient to meet coverage threshold

9 days agorefactor: fix phantom errorMessage, merge imports, harmonize Docker configs
Jérôme Benoit [Thu, 16 Apr 2026 13:27:13 +0000 (15:27 +0200)] 
refactor: fix phantom errorMessage, merge imports, harmonize Docker configs

- stopTransaction: use responsesFailed instead of phantom errorMessage field
- ConfigurationType: merge duplicate imports from UIProtocol
- Docker: remove pnpm@latest (use packageManager field), remove depth 0 no-op
- Docker: add EXPOSE to both Dockerfiles (8080 simulator, 3030 dashboard)
- Docker: exec in run.sh for proper signal propagation

9 days agofix(common): restore wsState type as numeric literal union
Jérôme Benoit [Thu, 16 Apr 2026 01:41:34 +0000 (03:41 +0200)] 
fix(common): restore wsState type as numeric literal union

9 days ago[autofix.ci] apply automated fixes
autofix-ci[bot] [Thu, 16 Apr 2026 01:33:25 +0000 (01:33 +0000)] 
[autofix.ci] apply automated fixes

9 days agorefactor: consolidate all types into ui-common — single import source
Jérôme Benoit [Thu, 16 Apr 2026 01:30:18 +0000 (03:30 +0200)] 
refactor: consolidate all types into ui-common — single import source

9 days agofix(web): copy workspace node_modules, harmonize browser adapter, add frozen-lockfile
Jérôme Benoit [Thu, 16 Apr 2026 01:10:16 +0000 (03:10 +0200)] 
fix(web): copy workspace node_modules, harmonize browser adapter, add frozen-lockfile

9 days agofix(deps): update dependency basic-ftp to ^5.3.0 (#1795)
renovate[bot] [Thu, 16 Apr 2026 01:02:16 +0000 (03:02 +0200)] 
fix(deps): update dependency basic-ftp to ^5.3.0 (#1795)

* fix(deps): update dependency basic-ftp to ^5.3.0

* [autofix.ci] apply automated fixes

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
9 days agorefactor(common): portable btoa, eliminate UIClient duplication, fix Docker deps
Jérôme Benoit [Thu, 16 Apr 2026 00:59:20 +0000 (02:59 +0200)] 
refactor(common): portable btoa, eliminate UIClient duplication, fix Docker deps

9 days agofix(web): widen Docker context to monorepo root for ui-common workspace dep
Jérôme Benoit [Thu, 16 Apr 2026 00:19:36 +0000 (02:19 +0200)] 
fix(web): widen Docker context to monorepo root for ui-common workspace dep

9 days agofix(common): include Date in JsonPrimitive, restore Date fields
Jérôme Benoit [Wed, 15 Apr 2026 23:54:33 +0000 (01:54 +0200)] 
fix(common): include Date in JsonPrimitive, restore Date fields

9 days agorefactor(web): eliminate type barrel — direct imports from ui-common and source modules
Jérôme Benoit [Wed, 15 Apr 2026 23:43:43 +0000 (01:43 +0200)] 
refactor(web): eliminate type barrel — direct imports from ui-common and source modules

9 days agofix(web): prevent ghost events after server switch, fix CloseEvent type, improve...
Jérôme Benoit [Wed, 15 Apr 2026 23:14:24 +0000 (01:14 +0200)] 
fix(web): prevent ghost events after server switch, fix CloseEvent type, improve error extraction

9 days ago[autofix.ci] apply automated fixes
autofix-ci[bot] [Wed, 15 Apr 2026 22:55:02 +0000 (22:55 +0000)] 
[autofix.ci] apply automated fixes

9 days agorefactor(web): migrate types to ui-common + UIClient internals to WebSocketClient
Jérôme Benoit [Wed, 15 Apr 2026 22:48:39 +0000 (00:48 +0200)] 
refactor(web): migrate types to ui-common + UIClient internals to WebSocketClient

9 days agorefactor(common): export browser adapter from barrel
Jérôme Benoit [Wed, 15 Apr 2026 21:03:38 +0000 (23:03 +0200)] 
refactor(common): export browser adapter from barrel

9 days agofeat(common): add notification callback support to WebSocketClient
Jérôme Benoit [Wed, 15 Apr 2026 21:02:00 +0000 (23:02 +0200)] 
feat(common): add notification callback support to WebSocketClient

9 days agofeat(common): add browser WebSocket adapter
Jérôme Benoit [Wed, 15 Apr 2026 20:46:47 +0000 (22:46 +0200)] 
feat(common): add browser WebSocket adapter

9 days agofix(cli): validate connect timeout budget — reject NaN/0/negative before race
Jérôme Benoit [Wed, 15 Apr 2026 20:15:42 +0000 (22:15 +0200)] 
fix(cli): validate connect timeout budget — reject NaN/0/negative before race

9 days agochore(deps): lock file maintenance (#1794)
renovate[bot] [Wed, 15 Apr 2026 20:11:49 +0000 (22:11 +0200)] 
chore(deps): lock file maintenance (#1794)

* chore(deps): lock file maintenance

* [autofix.ci] apply automated fixes

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
9 days agorefactor(cli): complete remaining audit items — validate status, extract helpers...
Jérôme Benoit [Wed, 15 Apr 2026 19:50:17 +0000 (21:50 +0200)] 
refactor(cli): complete remaining audit items — validate status, extract helpers, add 8 test cases

- Fix #28: Validate ResponsePayload status is string before cast in handleMessage()
- Fix #43: Extract settleHandler() private method to reduce duplication
- Fix #41: Normalize createMockWS → createMockWs for consistency
- Fix #39: Extract captureStream() parameterized helper to replace captureStdout/captureStderr
- Fix #47: Filter empty arrays in displayGenericPayload to avoid spurious output
- Test #21-#22: Add ConnectionError edge cases (empty cause, non-Error cause)
- Test #23: Add ServerFailureError without hashIdsFailed
- Test #24: Add post-connect onerror rejection test
- Test #25: Add displayGenericPayload failure path test
- Test #26: Add NaN and Infinity timeout validation tests

All tests pass, zero lint warnings.

9 days agofix(deps): update all non-major dependencies (#1792)
renovate[bot] [Wed, 15 Apr 2026 19:47:13 +0000 (21:47 +0200)] 
fix(deps): update all non-major dependencies (#1792)

* fix(deps): update all non-major dependencies

* [autofix.ci] apply automated fixes

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
9 days agorefactor(cli): fix onerror ErrorEvent handling, DRY adapter types, simplify factory
Jérôme Benoit [Wed, 15 Apr 2026 19:39:12 +0000 (21:39 +0200)] 
refactor(cli): fix onerror ErrorEvent handling, DRY adapter types, simplify factory

9 days agorefactor(cli): second-pass audit fixes — DRY table helper, remove slop, strengthen...
Jérôme Benoit [Wed, 15 Apr 2026 19:23:52 +0000 (21:23 +0200)] 
refactor(cli): second-pass audit fixes — DRY table helper, remove slop, strengthen assertions

9 days agorefactor(cli): audit fixes — validate timeoutMs, extract mock factory, add comments
Jérôme Benoit [Wed, 15 Apr 2026 19:09:36 +0000 (21:09 +0200)] 
refactor(cli): audit fixes — validate timeoutMs, extract mock factory, add comments

9 days ago[autofix.ci] apply automated fixes
autofix-ci[bot] [Wed, 15 Apr 2026 18:13:28 +0000 (18:13 +0000)] 
[autofix.ci] apply automated fixes

9 days agotest(cli): fix lifecycle test structure — single top-level describe
Jérôme Benoit [Wed, 15 Apr 2026 18:06:40 +0000 (20:06 +0200)] 
test(cli): fix lifecycle test structure — single top-level describe

9 days agofix(cli): replace unsafe WebSocket double cast with typed adapter
Jérôme Benoit [Wed, 15 Apr 2026 17:56:08 +0000 (19:56 +0200)] 
fix(cli): replace unsafe WebSocket double cast with typed adapter

9 days agofix(cli): replace unsafe WebSocket double cast with typed adapter
Jérôme Benoit [Wed, 15 Apr 2026 17:53:17 +0000 (19:53 +0200)] 
fix(cli): replace unsafe WebSocket double cast with typed adapter

9 days agofeat(cli): display failure reasons in human-readable table output
Jérôme Benoit [Wed, 15 Apr 2026 17:53:08 +0000 (19:53 +0200)] 
feat(cli): display failure reasons in human-readable table output

9 days agofix(deps): update dependency ora to v9 (#1793)
renovate[bot] [Wed, 15 Apr 2026 17:11:24 +0000 (19:11 +0200)] 
fix(deps): update dependency ora to v9 (#1793)

* fix(deps): update dependency ora to v9

* [autofix.ci] apply automated fixes

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
9 days agofeat(ui): add CLI client and shared UI common library (#1789)
Jérôme Benoit [Wed, 15 Apr 2026 16:59:22 +0000 (18:59 +0200)] 
feat(ui): add CLI client and shared UI common library (#1789)

* feat(ui): scaffold ui/common and ui/cli workspaces

- Add ui/common workspace with shared protocol types, SRPC WebSocket client,
  UUID utilities, config types, and Zod validation schemas (21 tests, 0 errors)
- Add ui/cli workspace scaffolding with all configuration files
- Register both workspaces in pnpm-workspace.yaml
- Update .prettierignore, release-please config and manifest
- Add build-common (library, single env) and build-cli (3x3 matrix) CI jobs
- Add formatting steps for new workspaces in autofix.yml
- Add sonar-project.properties for both workspaces

* feat(cli): implement CLI core infrastructure

- Commander.js entry point with 10 subcommand groups (simulator, station,
  template, connection, connector, atg, transaction, ocpp, performance,
  supervision)
- Config loading with lilconfig + Zod validation + merge precedence
  (defaults < config file < CLI flags)
- Output formatters: JSON (--json flag) and table (human-readable)
- WS client lifecycle: executeCommand() connects, sends, receives,
  disconnects; registerSignalHandlers() for SIGINT/SIGTERM
- Typed error classes: ConnectionError, AuthenticationError,
  TimeoutError, ServerError
- esbuild bundle with version injection and shebang
- 23 unit tests passing, zero lint warnings

* feat(cli): implement all 35 UI protocol command groups

All 35 ProcedureName procedures exposed as CLI subcommands:
- simulator: state, start, stop (3)
- station: list, start, stop, add, delete (5)
- template: list (1)
- connection: open, close (2)
- connector: lock, unlock (2)
- atg: start, stop (2)
- transaction: start, stop (2)
- ocpp: authorize, boot-notification, data-transfer, heartbeat,
  meter-values, status-notification, firmware-status-notification,
  diagnostics-status-notification, security-event-notification,
  sign-certificate, notify-report, notify-customer-information,
  log-status-notification, get-15118-ev-certificate,
  get-certificate-status, transaction-event (16)
- performance: stats (1)
- supervision: set-url (1)

Shared runAction() helper DRYs up all command action handlers.

* test(cli): add integration tests

- 8 integration tests covering --help, --version, subcommand help,
  connection error handling, JSON mode, and missing required options
- Separate test:integration script targeting tests/integration/
- Unit tests narrowed to tests/*.test.ts (no integration overlap)

* docs(cli): add README for ui/cli and ui/common

- ui/cli/README.md: installation, configuration, all command groups
  with examples, global options, exit codes, environment variables,
  available scripts
- ui/common/README.md: exported API reference (types, WebSocketClient,
  config validation, UUID utilities)

* [autofix.ci] apply automated fixes

* fix(cli): improve error handling for config and connection failures

- Catch config file ENOENT in loader.ts and throw clean error message
- Move loadConfig inside try/catch in runAction to prevent stack traces
- Use event.error in WebSocketClient onerror for better error propagation
- Separate connect errors from request errors in lifecycle.ts
- Include cause message in ConnectionError for descriptive output

* fix(cli): address PR review feedback

- Fix onerror stale after connect: replace with persistent error handler
  that fails all pending sendRequest promises immediately on WS error
- Fix dead code: call registerSignalHandlers() in cli.ts for SIGINT/SIGTERM
- Fix JSON error output: write to stdout (not stderr) in --json mode to
  match documented contract and enable scripting with 2>/dev/null
- Fix process.exit() in action.ts: use process.exitCode for proper async
  cleanup and testability
- Fix Map iteration: use snapshot+clear pattern in clearHandlers/failAllPending
- Fix empty array edge case in table formatter: check .length === 0
- Fix README: merge exit codes 1+2 into single row (Commander uses 1)
- Fix CI: add needs: build-common to build-cli job

* fix(cli): address second round of PR review feedback

- Fix ServerFailureError: WebSocketClient.handleMessage now rejects
  with a typed Error (carrying the ResponsePayload) instead of a raw
  object, preventing [object Object] in CLI output
- Fix table formatter: FAILURE responses now display hashIdsFailed/
  hashIdsSucceeded tables instead of early-returning with minimal info
- Fix auth schema: Zod refinement requires username+password when
  authentication enabled with protocol-basic-auth
- Fix AuthenticationConfig.type: use AuthenticationType enum instead
  of plain string for compile-time safety
- Fix signal handlers: use process.exitCode instead of process.exit()
  so finally blocks in executeCommand can run cleanup

* fix(cli): restore process.exit in signal handlers, fix type mismatch, remove dead code

- Signal handlers: restore process.exit() — setting only process.exitCode
  keeps the process alive since registering SIGINT listener removes Node's
  default termination behavior
- BroadcastChannelResponsePayload: align field name with server wire format
  (hashId: string | undefined, not id: string)
- Remove unused DEFAULT_TIMEOUT_MS export from defaults.ts

* refactor(ui-common): extract WS timeout to shared constant

Move UI_WEBSOCKET_REQUEST_TIMEOUT_MS from a private constant in
WebSocketClient.ts to ui/common/src/constants.ts as a single source
of truth, exported via barrel for consumers.

* refactor(cli): merge duplicate ui-common and commander imports

Consolidate split type/value imports from the same module into single
import statements using inline type syntax (`import { type X, Y }`).
Resolves SonarCloud 'imported multiple times' warning.

* refactor(cli): use Number.parseInt instead of parseInt

Resolves SonarCloud 'Prefer Number.parseInt over parseInt' warning.

* refactor(cli): remove unnecessary Command alias from commander import

Use import { Command } from 'commander' directly instead of aliasing
to Cmd. Single import serves both type and value usage.

* chore: reorder ui workspaces consistently (common, cli, web)

Apply dependency-first ordering across all config files:
pnpm-workspace.yaml, .prettierignore, release-please config/manifest,
ci.yml job order, and autofix.yml step order.

* refactor(ui-common): widen validateUUID to accept unknown

Align with ui/web pattern — move typeof string check into validateUUID
itself, removing redundant guard at call sites. Add tests for
non-string inputs (number, null, undefined, object, boolean).

* fix(cli): use Vercel CLI pattern for graceful signal shutdown

Replace AbortController with module-level activeClient/activeSpinner
refs + cleanupInProgress guard (Vercel CLI pattern). Signal handler
stops spinner, disconnects WS, then process.exit(130/143). Simpler,
battle-tested, correct for batch request-response CLI.

* chore: reorder linked-versions components (common, cli, web)

* style(ci): add blank line between all job definitions in ci.yml

* refactor(cli): rename parseIntList to parseCommaSeparatedInts

* fix(cli): validate connector IDs input and wrap config search errors

- parseCommaSeparatedInts now rejects NaN values with a clear error
  message instead of silently sending garbage to the server
- lilconfig search() path now wrapped in try/catch like the explicit
  config path, giving consistent error messages for malformed configs

* feat(cli): standalone build + XDG-only config + install script

- Bundle all dependencies into single 504KB dist/cli.js (no node_modules
  needed at runtime). Only ws native addons (bufferutil, utf-8-validate)
  are external — ws falls back to pure JS automatically.
- Replace lilconfig with direct XDG config file reading:
  ${XDG_CONFIG_HOME:-~/.config}/evse-cli/config.json
- Remove lilconfig dependency
- Add install.sh: builds CLI, copies to ~/.local/bin/evse-cli, creates
  default XDG config, warns if ~/.local/bin not in PATH
- Isolate ALL config tests from host env via XDG_CONFIG_HOME in
  beforeEach/afterEach + add XDG auto-discovery happy path test
- Guard against JSON array in config file
- Update README: standalone install instructions + XDG config location

* [autofix.ci] apply automated fixes

* fix(cli): address review feedback round 3

WebSocketClient:
- Validate responsePayload shape before casting (guard against [uuid, null])
- Reject connect() Promise if socket closes before onopen fires
- Add tests for both edge cases

CLI:
- Validate ws:/wss: URL scheme in parseServerUrl
- Output ServerFailureError.payload via formatter (show hashIdsFailed details)
- Extract shared parseInteger() validator — reject NaN with clear error
- Remove dead error types (AuthenticationError, ServerError, TimeoutError)
- Chain build in test:integration script
- Remove unreachable FAILURE branch in outputTable

Schema:
- Require password.length > 0 in auth refinement (reject empty string)

* ci: remove redundant lint:fix from autofix workflow

pnpm format already runs eslint --cache --fix, making the separate
pnpm lint:fix step redundant in all three ui workspaces.

* refactor(cli): remove unnecessary comment in outputTable

* fix(cli): don't override template defaults in station add, reject array config

- station add: only include autoStart, persistentConfiguration,
  ocppStrictCompliance, deleteConfiguration in payload when explicitly
  passed — lets server use template defaults otherwise
- config loader: reject uiServer array with clear error instead of
  silently spreading array keys into object

* refactor(cli): remove unused terminal-link dep and dead exports

- Remove terminal-link from dependencies (never imported)
- Remove unused exports: printSuccess, printWarning, printInfo (human.ts),
  outputTableList (table.ts)
- Remove corresponding test for printSuccess

* [autofix.ci] apply automated fixes

* fix(ui-common): reject malformed payloads, replace ReadyState with enum

- handleMessage: reject pending handler immediately when server sends
  response with matching UUID but missing status field, instead of
  silently dropping and waiting for 60s timeout
- Replace ReadyState type alias with WebSocketReadyState const enum
- Remove redundant ReadyState type (duplicated enum semantics)

* fix(cli): add connection timeout, remove dead defaultUIServerConfig

- Wrap client.connect() with Promise.race timeout to prevent infinite
  hang when server accepts TCP but never completes WS handshake
- Remove unused defaultUIServerConfig export from defaults.ts

* fix(cli): clear connection timeout timer on success

* refactor(ui-common): expose url getter, remove duplicate ConfigurationType

- WebSocketClient: make buildUrl() a public url getter so consumers
  use the canonical URL instead of reconstructing it
- lifecycle.ts: use client.url instead of building URL independently
- Remove ConfigurationType.ts: UIServerConfigurationSection is now
  a type alias for the Zod-inferred UIServerConfig (single source)

* fix(cli): display failure status instead of misleading Success

displayGenericPayload now checks payload.status before printing — a
failure response without hashIds shows the red status line instead of
a green checkmark.

* fix: align ui/web ResponsePayload with server, reject non-object config

- ui/web ResponsePayload: replace incorrect hashIds with
  hashIdsFailed/hashIdsSucceeded/responsesFailed matching server schema
- cli config loader: reject non-object uiServer values with clear error
  instead of silently falling back to defaults

* fix: reject non-object config files, merge duplicate import

- Config loader: throw on primitive JSON config values (42, "hello")
  instead of silently falling back to defaults
- Merge duplicate UIProtocol.ts import in ui/common/src/client/types.ts

* fix: suppress dangling connect rejection, remove dead Zod defaults

- Attach .catch() to connect() promise to prevent unhandled rejection
  when the timeout wins Promise.race and disconnect triggers onclose
- Remove .default() calls from Zod schema — the CLI loader always
  provides all fields via its canonical defaults map, making Zod
  defaults dead code paths

* fix(cli): preserve error cause in config loader for debuggability

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
10 days agochore(deps): lock file maintenance (#1790)
renovate[bot] [Tue, 14 Apr 2026 20:05:30 +0000 (22:05 +0200)] 
chore(deps): lock file maintenance (#1790)

* chore(deps): lock file maintenance

* [autofix.ci] apply automated fixes

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
11 days agochore(deps): update all non-major dependencies (#1791)
renovate[bot] [Tue, 14 Apr 2026 14:19:14 +0000 (16:19 +0200)] 
chore(deps): update all non-major dependencies (#1791)

* chore(deps): update all non-major dependencies

* [autofix.ci] apply automated fixes

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2 weeks agochore(deps): update pnpm/action-setup action to v6 (#1788)
renovate[bot] [Sat, 11 Apr 2026 14:04:50 +0000 (16:04 +0200)] 
chore(deps): update pnpm/action-setup action to v6 (#1788)

* chore(deps): update pnpm/action-setup action to v6

* [autofix.ci] apply automated fixes

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2 weeks agofix(deps): update all non-major dependencies to ^6.6.13 (#1787)
renovate[bot] [Sat, 11 Apr 2026 11:28:44 +0000 (13:28 +0200)] 
fix(deps): update all non-major dependencies to ^6.6.13 (#1787)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2 weeks agodocs: clean up agent memories — declarative facts only, no narrative justifications
Jérôme Benoit [Fri, 10 Apr 2026 18:11:42 +0000 (20:11 +0200)] 
docs: clean up agent memories — declarative facts only, no narrative justifications

2 weeks agorefactor: use charging-station barrel for buildConfigKey in OCPPServiceUtils
Jérôme Benoit [Fri, 10 Apr 2026 16:58:41 +0000 (18:58 +0200)] 
refactor: use charging-station barrel for buildConfigKey in OCPPServiceUtils

2 weeks agorefactor(tests): replace re-export hub with direct imports
Jérôme Benoit [Fri, 10 Apr 2026 16:27:37 +0000 (18:27 +0200)] 
refactor(tests): replace re-export hub with direct imports

Remove ChargingStationTestUtils.ts re-export hub and update all 73
test files to import directly from their defining modules
(StationHelpers, TestLifecycleHelpers, MockCaches, MockWebSocket).

Fix __testable__ barrel bypass in OCPP20RequestService-CallChain test.

Harmonize Web UI test imports to use composables/types barrels
consistently and export validateUUID from composables barrel.

Add 'Direct Imports' convention to TEST_STYLE_GUIDE.md §6.

2 weeks agodocs: update AuthHelpers description in project overview memory
Jérôme Benoit [Fri, 10 Apr 2026 16:03:50 +0000 (18:03 +0200)] 
docs: update AuthHelpers description in project overview memory

2 weeks agofeat(ocpp): implement Local Auth List Management Profile (GetLocalListVersion, SendLo...
Jérôme Benoit [Fri, 10 Apr 2026 15:58:43 +0000 (17:58 +0200)] 
feat(ocpp): implement Local Auth List Management Profile (GetLocalListVersion, SendLocalList) (#1782)

* feat(ocpp): add local auth list types for OCPP 1.6 and 2.0

* feat(ocpp): add InMemoryLocalAuthListManager implementation

* feat(ocpp): export local auth list types from main types barrel

* feat(ocpp): wire LocalAuthListManager into auth subsystem

* feat(ocpp/2.0): implement GetLocalListVersion and SendLocalList handlers

* docs: mark Local Auth List Management commands as implemented

* style: apply formatting to local auth list test file

* [autofix.ci] apply automated fixes

* fix(ocpp): enforce VersionMismatch and size limits in SendLocalList handlers

* fix(ocpp): address PR review feedback on local auth list implementation

* fix(ocpp): improve robustness and consistency in local auth list handlers

* fix(ocpp): fix config key, atomicity, and version validation in local auth list

* fix(ocpp): harmonize validation ordering and improve type safety in local auth list

* fix(ocpp): add error logging to OCPP 1.6 local auth list catch blocks

* fix(ocpp): use enum values for auth status and fix OCPP 2.0 config key semantics

* refactor(ocpp): rename DEFAULT_IDTAG to OCPP_DEFAULT_IDTAG for consistent naming

* fix(test): use convertToBoolean in mock getLocalAuthListEnabled for production parity

* fix(ocpp): align OCPP16UpdateStatus naming and add maxLocalAuthListEntries validation

* fix(ocpp): gate maxLocalAuthListEntries validation on localAuthListEnabled, not cache

* refactor(ocpp): convert LocalAuthListManager interface from async to sync

* refactor(ocpp): remove redundant async from OCPPAuthServiceImpl.authorize()

* fix(ocpp): remove stale LocalAuthListManager implementation note in RemoteAuthStrategy

* refactor(ocpp): use barrel imports for cross-component boundaries

Replace direct file imports with barrel (index.ts) imports when crossing
component boundaries (ocpp/ → charging-station/, auth/ → ocpp/).
Add Entries to OCPP20RequiredVariableName enum.
Sync LocalAuthListCtrlr.Entries variable after SendLocalList.

* fix(ocpp): update stale JSDoc in MockFactories and AuthComponentFactory

* feat(ocpp-server): add GetLocalListVersion and SendLocalList command support

* fix(test): reuse getConfigurationKey in mock getLocalAuthListEnabled

* refactor(test): use upsertConfigurationKey in OCPP 2.0 local auth list tests

* refactor(ocpp): move readMaxLocalAuthListEntries to AuthHelpers

* refactor(ocpp): move maxLocalAuthListEntries reading to version adapters

* docs: update agent memories with local auth list, QMD integration, and convention fixes

* refactor(ocpp): widen AuthStrategy.authenticate to allow sync return and remove eslint-disable

* fix(test): remove unnecessary async from LocalAuthStrategy test callbacks

* fix(ocpp): address review feedback on volatile Entries, circular dep, and interface

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2 weeks agodocs: update agent memories with local auth list, QMD integration, and convention...
Jérôme Benoit [Fri, 10 Apr 2026 14:27:22 +0000 (16:27 +0200)] 
docs: update agent memories with local auth list, QMD integration, and convention fixes

2 weeks agofix(deps): update all non-major dependencies (#1785)
renovate[bot] [Fri, 10 Apr 2026 09:32:13 +0000 (11:32 +0200)] 
fix(deps): update all non-major dependencies (#1785)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2 weeks agochore(deps): update dependency basic-ftp to v5.2.1 [security] (#1784)
renovate[bot] [Wed, 8 Apr 2026 20:51:53 +0000 (20:51 +0000)] 
chore(deps): update dependency basic-ftp to v5.2.1 [security] (#1784)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2 weeks agochore(deps): update all non-major dependencies (#1781)
renovate[bot] [Wed, 8 Apr 2026 20:34:46 +0000 (20:34 +0000)] 
chore(deps): update all non-major dependencies (#1781)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2 weeks agochore: release main (#1780) ocpp-server@v4.4.0 simulator@v4.4.0 v4 v4.4 webui@v4.4.0
Jérôme Benoit [Tue, 7 Apr 2026 23:07:30 +0000 (01:07 +0200)] 
chore: release main (#1780)

* chore: release main

* [autofix.ci] apply automated fixes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2 weeks agorefactor(tests): harmonize crypto test data and improve test quality
Jérôme Benoit [Tue, 7 Apr 2026 22:52:42 +0000 (00:52 +0200)] 
refactor(tests): harmonize crypto test data and improve test quality

- Reorganize OCPP20CertificateTestData: move CA/leaf certificates into
  Real X.509 section, simplify JSDoc to consistent one-line format
- Add round-trip tests (derLength → readDerLength) replacing duplicate
  raw byte assertions
- Add semantic test for extractDerIssuer (DER hash vs string DN hash)
- Replace eslint-disable || workaround with assert.match regex
- Update Asn1DerUtils @description to cover parsing functions

2 weeks agofix(ocpp): use Volatile instead of invented Ephemeral for CertificatePrivateKey persi...
Jérôme Benoit [Tue, 7 Apr 2026 22:39:21 +0000 (00:39 +0200)] 
fix(ocpp): use Volatile instead of invented Ephemeral for CertificatePrivateKey persistence

Remove non-spec PersistenceEnumType.Ephemeral value. Use existing
Volatile which correctly prevents disk persistence and is already
used for ~25 other runtime-only variables in the registry.

2 weeks agorefactor(crypto): modernize crypto APIs and harden certificate handling
Jérôme Benoit [Tue, 7 Apr 2026 22:30:11 +0000 (00:30 +0200)] 
refactor(crypto): modernize crypto APIs and harden certificate handling

- Migrate createHash() to crypto.hash() one-shot API (Node.js 22+)
- Migrate createSign() to crypto.sign() one-shot API
- Add derLength() bounds check for lengths > 0xFFFF
- Change CertificatePrivateKey persistence to Ephemeral
- Add logger.debug in deriveSigningMethodFromPublicKeyHex catch block
- Harden validateCertificatePath with async realpath for symlink
  protection (falls back to resolve for not-yet-created paths)
- Add X.509 chain validation in validateCertificateX509: verify issuer
  linkage and signatures for all certificates, validate validity
  period for entire chain (not just leaf), document leaf-first ordering
- Implement RFC 6960 §4.1.1 compliant issuerNameHash via DER issuer
  extraction from certificate raw bytes (extractDerIssuer)
- Move DER parsing functions (readDerLength, skipDerElement,
  extractDerIssuer) to Asn1DerUtils with proper JSDoc
- Rename readDerTagLength to readDerLength for accuracy
- Add unit tests for DER parsing functions and chain validation
- Add real CA + leaf certificate test fixtures

2 weeks agorefactor(ocpp): use Node.js crypto for EC curve derivation
Jérôme Benoit [Tue, 7 Apr 2026 20:57:22 +0000 (22:57 +0200)] 
refactor(ocpp): use Node.js crypto for EC curve derivation

Replace manual ASN.1 OID hex substring matching with
crypto.createPublicKey which parses the DER structure via OpenSSL,
validates the EC point, and returns the named curve directly. Map
Node.js curve names (e.g. prime256v1) to SigningMethodEnumType.

2 weeks agofeat(ocpp): add signing prerequisites validation and EC curve auto-derivation
Jérôme Benoit [Tue, 7 Apr 2026 20:42:02 +0000 (22:42 +0200)] 
feat(ocpp): add signing prerequisites validation and EC curve auto-derivation

- Add deriveSigningMethodFromPublicKeyHex: extracts EC curve OID from
  ASN.1 DER public key and maps to SigningMethodEnumType
- Add validateSigningPrerequisites: checks public key presence, curve
  detection, and config/key curve consistency
- Integrate validation in OCPP 2.0 (OCPPServiceUtils.buildMeterValue)
  and OCPP 1.6 (readSigningConfigForConnector) signing paths
- On validation failure: log warning and gracefully fallback to unsigned
  meter values instead of producing invalid signed data
- Add unit tests for deriveSigningMethodFromPublicKeyHex and
  validateSigningPrerequisites covering all paths

2 weeks agofeat(ocpp): auto-derive signing method from EC public key curve
Jérôme Benoit [Tue, 7 Apr 2026 20:08:55 +0000 (22:08 +0200)] 
feat(ocpp): auto-derive signing method from EC public key curve

- Add deriveSigningMethodFromPublicKeyHex that extracts EC curve OID
  from ASN.1 DER public key and maps to SigningMethodEnumType
- Add validateSigningPrerequisites that validates public key presence,
  curve detection, and config consistency — returns enabled/disabled
  with reason
- Integrate validation in OCPP 2.0 (OCPPServiceUtils.buildMeterValue)
  and OCPP 1.6 (readSigningConfigForConnector) signing paths
- On validation failure: log error and gracefully fallback to unsigned
  meter values instead of producing invalid signed data
- Move TEST_PUBLIC_KEY_HEX to ChargingStationTestConstants for reuse
- Update test fixtures to use valid secp256k1 ASN.1 EC public key

2 weeks agofix(ocpp): conform signingMethod to OCA spec and fix template curve mismatch
Jérôme Benoit [Tue, 7 Apr 2026 19:30:56 +0000 (21:30 +0200)] 
fix(ocpp): conform signingMethod to OCA spec and fix template curve mismatch

- Set signingMethod to empty string when using OCMF encoding per OCA
  Application Note Table 11: SA field already in signedMeterData
- Add FiscalMetering.SigningMethod=ECDSA-secp256k1-SHA256 to
  keba-ocpp2-signed template to match the secp256k1 public key from
  OCA spec §5.3 example
- Update tests to expect empty signingMethod for OCMF payloads
- Remove unused SigningMethodEnumType imports from test files

2 weeks agorefactor(tests): harmonize test file names and @file descriptions
Jérôme Benoit [Tue, 7 Apr 2026 19:07:33 +0000 (21:07 +0200)] 
refactor(tests): harmonize test file names and @file descriptions

- Rename test files to follow Source-Focus.test.ts convention:
  OCPP16SignedMeterValues → OCPP16ServiceUtils-SignedMeterValues
  OCPP20SignedMeterValues → OCPP20RequestBuilders-SignedMeterValues
  OCPP16SchemaValidation → OCPP16ServiceUtils-SchemaValidation
  OCPP20SchemaValidation → OCPP20IncomingRequestService-SchemaValidation
  OCPP16VendorParametersKey → Configuration (in tests/types/)
- Harmonize all @file tags to 'Tests for <SourceModule> [focus]' pattern
- Fix module name mismatches, dot notation, and inverted descriptions
- Integration tests use descriptive 'Tests for OCPP X.Y <feature>' style

2 weeks agorefactor(tests): rename OCPP16VendorParametersKey test to match source file
Jérôme Benoit [Tue, 7 Apr 2026 18:46:56 +0000 (20:46 +0200)] 
refactor(tests): rename OCPP16VendorParametersKey test to match source file

Rename to Configuration.test.ts to follow the established convention
where test file names match their corresponding source file names.

2 weeks agofeat(ocpp): add EncodingMethodEnumType enum for signed meter value encoding methods
Jérôme Benoit [Tue, 7 Apr 2026 18:39:26 +0000 (20:39 +0200)] 
feat(ocpp): add EncodingMethodEnumType enum for signed meter value encoding methods

- Add EncodingMethodEnumType enum with OCMF and EDL values based on
  OCA Application Note and OCPP 2.0.1/2.1 specs
- Use enum in SignedMeterData interface and wire types (with string
  union for extensibility)
- Replace hardcoded 'OCMF' string constant with enum value
- Update all tests to use EncodingMethodEnumType consistently

2 weeks agofix(ocpp): populate signingMethod field and add SigningMethodEnumType enum
Jérôme Benoit [Tue, 7 Apr 2026 18:20:34 +0000 (20:20 +0200)] 
fix(ocpp): populate signingMethod field and add SigningMethodEnumType enum

- Fix signingMethod being empty string in SignedMeterValueType payload
- Add SigningMethodEnumType enum per OCA Application Note Table 12 and
  OCPP 2.1 Appendix 7.4 with all 7 standardized values
- Propagate FiscalMetering.SigningMethod config variable to the signed
  meter data generator with fallback to ECDSA-secp256r1-SHA256
- Add OCPP 1.6 vendor key SigningMethod and read it in
  readSigningConfigForConnector
- Add MeterPublicKey and SigningMethod mappings to OCPP2_PARAMETER_KEY_MAP
- Use SigningMethodEnumType in all interfaces and type definitions
- Update README vendor-specific keys documentation

2 weeks agofeat(ocpp): add signed meter values support for OCPP 1.6 and 2.0.x (#1775)
Jérôme Benoit [Tue, 7 Apr 2026 17:05:43 +0000 (19:05 +0200)] 
feat(ocpp): add signed meter values support for OCPP 1.6 and 2.0.x (#1775)

* feat(types): export OCPP16MeterValueFormat and add OCPP16SignedMeterValue

* feat(ocpp1.6): add vendor configuration keys for signed meter values

* feat(ocpp2.0): add variable registry entries for signed meter readings

* feat(mock-server): handle signed meter value payloads

* feat(ocpp): add simulated signed meter data generator

* feat(ocpp): add PublicKeyWithSignedMeterValue enum and state tracking

* feat(ocpp2.0): populate signedMeterValue in sampled value building

* feat(ocpp1.6): add signed meter value support to sampled value building

* feat(templates): add station templates with signed meter value config

* docs: document signed meter values configuration

* fix(lint): apply formatter fixes to signed meter value files

* fix(ocpp): fix publicKey state tracking and reset in signed meter values

* fix(ocpp): fix OCMF payload, hash, and public key encoding

* fix(ocpp): add defensive guards and improve signing code quality

* fix(ocpp2.0): respect SignStartedReadings and SignUpdatedReadings sub-switches

* [autofix.ci] apply automated fixes

* fix(ocpp): consistent publicKey state update, version-gated vendor keys, use enum constants

* [autofix.ci] apply automated fixes

* refactor(ocpp): use union types in common code and correct enum classification per OCPP specs

- Use VendorParametersKey (union) in ChargingStation.ts, not OCPP16VendorParametersKey
- Remove VERSION_16 guard: OCPP2_PARAMETER_KEY_MAP resolves keys per version
- Add 6 mapping entries to OCPP2_PARAMETER_KEY_MAP for signed MV config keys
- Classify enums per OCPP 2.0.1 base spec: SignReadings and
  PublicKeyWithSignedMeterValue in OCPP20OptionalVariableName (Required: no)
- Classify Application Note-only variables (SignStartedReadings,
  SignUpdatedReadings, PublicKey, SigningMethod) in OCPP20VendorVariableName
- Replace all string literals with enum references in variable registry

* [autofix.ci] apply automated fixes

* fix(ocpp): fix corrupted Measurands entry, Wh/kWh unit handling, context mapping, and enum validation

- Fix AlignedDataCtrlr.Measurands variable corrupted by lint auto-sort (was SignUpdatedReadings)
- Add meterValueUnit to SignedMeterDataParams to handle kWh input without double-division
- Replace unsafe context cast with explicit OCPP20-to-generator context mapping
- Extract parsePublicKeyWithSignedMeterValue helper (hoisted Set, shared across OCPP versions)
- Use MeterValueUnit enum constant instead of string literal for kWh comparison

* [autofix.ci] apply automated fixes

* refactor(ocpp): use MeterValueContext/MeterValueUnit enums and barrel imports instead of string literals

* style: apply prettier formatting to SignedMeterDataGenerator test

* fix(ocpp): add vendorSpecific flag, guard publicKey inclusion on key availability, add kWh test

* refactor(ocpp): use PublicKeyWithSignedMeterValueEnumType.Never instead of string literal

* test(ocpp): add JSDoc header, TX=P/Clock tests, non-energy measurand and transactionData force tests

* test(ocpp1.6): add periodic signing tests with mock timers for startUpdatedMeterValues

* refactor(test): use beforeEach for station creation in OCPP16SignedMeterValues per style guide

* fix(ocpp): treat undefined context as periodic for SignUpdatedReadings, conditional try/catch for signing-forced transactionData, use node:assert/strict import

* refactor(ocpp2.0): add defaultValue and enumeration to PublicKeyWithSignedMeterValue registry entry

* refactor(ocpp1.6): remove redundant nullish coalescing on publicKeyHex

* refactor(ocpp): use BaseError, return tuple in OCPP 2.0 builder, extract config reading in OCPP 1.6

* refactor(ocpp): harmonize naming, signatures, and data structures across signing paths

- SignedMeterData extends JsonObject: eliminates as-cast to OCPP16SignedMeterValue
- Rename publicKeyConfig to publicKeyWithSignedMeterValue: consistent with OCPP 2.0 interface
- Rename meterValueWh to meterValue: unit-agnostic (generator handles via meterValueUnit)
- Remove unused OCPP16SignedMeterValue import

* fix(mock-server): log signed meter values in TransactionEvent.Ended and add test

* fix(ocpp): include Transaction.Begin MV in TransactionEvent(Ended) per spec §4.1.2, set signingMethod to empty string per spec §3.2.1

* refactor(ocpp): rename SignedMeter* files to follow OCPP* naming convention

* refactor(ocpp): extract generic SignedSampledValueResult<T> to shared utils

* refactor(ocpp): extract shared SigningConfig interface, OCPP20SampledValueSigningConfig extends it

* refactor(ocpp): use roundTo helper instead of Number/toFixed for kWh conversion

* style(mock-server): reorder signed MV tests to follow Started/Updated/Ended lifecycle

* refactor(ocpp): move SampledValueSigningConfig to shared utils, remove version-specific type import from common code

* fix(ocpp): map StartTxnSampledData to SampledDataCtrlr.TxStartedMeasurands, remove VERSION_16 guard

* [autofix.ci] apply automated fixes

* style: remove unnecessary parenthetical from eslint cspell comment

* style: rename Configuration.test.ts to OCPP16VendorParametersKey.test.ts to reflect content

* refactor(ocpp): rename ocpp20SigningConfig/State to signingConfig/State (version-agnostic)

* style: harmonize blank lines in OCPP20VariableRegistry between component sections

* [autofix.ci] apply automated fixes

* style: remove unjustified blank lines before inline comments within same component section

* fix(ocpp2.0): add missing DeviceDataCtrlr section comment in variable registry

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2 weeks agochore(deps): update dependency @cspell/eslint-plugin to v10 (#1779)
renovate[bot] [Tue, 7 Apr 2026 11:56:56 +0000 (11:56 +0000)] 
chore(deps): update dependency @cspell/eslint-plugin to v10 (#1779)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2 weeks agochore(deps): update all non-major dependencies (#1778)
renovate[bot] [Tue, 7 Apr 2026 11:41:14 +0000 (13:41 +0200)] 
chore(deps): update all non-major dependencies (#1778)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2 weeks agochore(deps): lock file maintenance (#1777)
renovate[bot] [Mon, 6 Apr 2026 17:57:25 +0000 (19:57 +0200)] 
chore(deps): lock file maintenance (#1777)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2 weeks agochore(deps): lock file maintenance
Jérôme Benoit [Mon, 6 Apr 2026 17:03:06 +0000 (19:03 +0200)] 
chore(deps): lock file maintenance

Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>
2 weeks agochore(deps): update all non-major dependencies (#1776)
renovate[bot] [Mon, 6 Apr 2026 11:45:11 +0000 (13:45 +0200)] 
chore(deps): update all non-major dependencies (#1776)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2 weeks agochore: release main (#1773) ocpp-server@v4.3.1 simulator@v4.3.1 v4.3 webui@v4.3.1
Jérôme Benoit [Sun, 5 Apr 2026 15:57:05 +0000 (17:57 +0200)] 
chore: release main (#1773)

* chore: release main

* [autofix.ci] apply automated fixes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2 weeks agotest: harmonize RemoteStartTransaction tests across OCPP stacks
Jérôme Benoit [Sun, 5 Apr 2026 15:46:39 +0000 (17:46 +0200)] 
test: harmonize RemoteStartTransaction tests across OCPP stacks

OCPP 1.6:
- Remove fabricated TC_0XX_CS codes (no official 1.6 test case spec)
- Reorder tests by category: happy path, input validation, availability,
  transaction state, event listeners

OCPP 2.0:
- Add 2 EVSE availability tests (skip inoperative, all inoperative)
- Add official TC refs where tests match Part 6 spec (TC_F_02_CS,
  TC_F_03_CS, TC_K_37_CS)
- Harmonize FR comment format on new tests

2 weeks agofix(ocpp): check connector availability in RemoteStartTransaction auto-selection...
Rishabh Vaish [Sun, 5 Apr 2026 15:08:24 +0000 (08:08 -0700)] 
fix(ocpp): check connector availability in RemoteStartTransaction auto-selection (#1774)

* fix(ocpp): check connector availability in RemoteStartTransaction auto-selection

The OCPP 1.6 RemoteStartTransaction handler's connector auto-selection
(when connectorId is omitted) only checked transactionStarted and
reservation status but not administrative availability. This meant an
Inoperative connector could be selected, causing the request to be
rejected even when other Operative connectors were free.

Added isConnectorAvailable() check to the auto-selection loop, matching
the behavior already present in the OCPP 2.0 selectAvailableEvse().

* [autofix.ci] apply automated fixes

* Update tests/charging-station/ocpp/1.6/OCPP16IncomingRequestService-RemoteStartTransaction.test.ts

* Apply suggestion from @jerome-benoit

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
3 weeks agodocs: restructure memories for logical coherence
Jérôme Benoit [Sat, 4 Apr 2026 13:14:44 +0000 (15:14 +0200)] 
docs: restructure memories for logical coherence

- code_style_conventions: reorder sections (general TS → domain → process
  → other → pitfalls), deduplicate BaseError constraint and payload
  validation, move Utility Usage Rules next to other TS patterns
- task_completion_checklist: add inline comments to all 3 sections

3 weeks agochore: release main (#1771) ocpp-server@v4.3.0 simulator@v4.3.0 webui@v4.3.0
Jérôme Benoit [Sat, 4 Apr 2026 12:59:53 +0000 (14:59 +0200)] 
chore: release main (#1771)

* chore: release main

* [autofix.ci] apply automated fixes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
3 weeks agodocs: remove standalone ruff hint from checklist memory
Jérôme Benoit [Sat, 4 Apr 2026 01:13:38 +0000 (03:13 +0200)] 
docs: remove standalone ruff hint from checklist memory

3 weeks agodocs: remove barrel workaround hint from conventions memory
Jérôme Benoit [Sat, 4 Apr 2026 01:13:01 +0000 (03:13 +0200)] 
docs: remove barrel workaround hint from conventions memory

3 weeks agodocs: update serena memories after full codebase audit
Jérôme Benoit [Sat, 4 Apr 2026 01:07:14 +0000 (03:07 +0200)] 
docs: update serena memories after full codebase audit

- code_style_conventions: add constant unit suffixes, BaseError import
  constraint, utility usage rules, Vue UI conventions, Python conventions,
  testing patterns (AAA, __testable__, flushMicrotasks), enum merging,
  console.* rules, fix WeakMap description accuracy
- project_overview: add auth subsystem, UI server transports, design
  patterns table, coverage thresholds, update tech stack versions
- task_completion_checklist: add ruff standalone commands for Python

3 weeks agorefactor(ui): use EMPTY_VALUE_PLACEHOLDER in Utils.ts and test assertions
Jérôme Benoit [Fri, 3 Apr 2026 23:15:41 +0000 (01:15 +0200)] 
refactor(ui): use EMPTY_VALUE_PLACEHOLDER in Utils.ts and test assertions

Replace remaining hardcoded 'Ø' in getWebSocketStateName() and 4 test
assertions with the centralized EMPTY_VALUE_PLACEHOLDER constant.
Consolidate duplicate Constants import in Utils.ts.

3 weeks agofix(ui): enable authorize for all OCPP versions in StartTransaction
Jérôme Benoit [Fri, 3 Apr 2026 21:43:43 +0000 (23:43 +0200)] 
fix(ui): enable authorize for all OCPP versions in StartTransaction

The OCPP 2.0.x authorize restriction was a UI-only limitation — the
simulator stack already handles Authorize for both 1.6 and 2.0.x.
Remove the isOCPP20x guard so the checkbox is available for all versions.

3 weeks agorefactor(ocpp-server): inline _parse_set/get_variable_specs thin wrappers
Jérôme Benoit [Fri, 3 Apr 2026 21:08:11 +0000 (23:08 +0200)] 
refactor(ocpp-server): inline _parse_set/get_variable_specs thin wrappers

Remove redundant _parse_set_variable_specs and _parse_get_variable_specs
one-liner wrappers — call _parse_variable_specs(specs, require_value=...)
directly at all call sites

3 weeks agorefactor: enforce utility usage and centralize constants across all components
Jérôme Benoit [Fri, 3 Apr 2026 20:56:28 +0000 (22:56 +0200)] 
refactor: enforce utility usage and centralize constants across all components

- Replace .length/.size checks with isEmpty/isNotEmptyArray in 7 src/ files
- Replace Number.parseInt/parseFloat with convertToInt in OCPPServiceUtils
  (intentional fail-fast: malformed templates now throw instead of silent NaN)
- Keep Number.parseFloat in getLimitFromSampledValueTemplateCustomValue
  (NaN fallback contract requires it)
- Centralize route names (ROUTE_NAMES), placeholder (EMPTY_VALUE_PLACEHOLDER),
  and localStorage key in Vue UI (11 files)
- Extract 13 magic values to constants in Python ocpp-server
- Rename constants: WORKER_SET_VERSION, DEFAULT_RATE_WINDOW_MS, MS_PER_HOUR,
  DEFAULT_*_SECONDS in Python, DEFAULT_*_BYTES in UIServerSecurity

3 weeks agorefactor: add unit suffixes to time-related constants and fix heartbeat unit mismatch
Jérôme Benoit [Fri, 3 Apr 2026 20:06:40 +0000 (22:06 +0200)] 
refactor: add unit suffixes to time-related constants and fix heartbeat unit mismatch

- Rename 19 constants to include _MS or _SECONDS suffix (Constants, OCPPConstants, WorkerConstants)
- Remove redundant // Ms and // Seconds comments from definitions
- Fix pre-existing bug: resetLimits set HeartbeatInterval to 60000 seconds instead of 60
- Remove 97 redundant heartbeatInterval overrides in tests (mock default already correct)

3 weeks agorefactor: improve helper/utility usage consistency across codebase
Jérôme Benoit [Fri, 3 Apr 2026 19:23:45 +0000 (21:23 +0200)] 
refactor: improve helper/utility usage consistency across codebase

- Make worker module standalone by inlining mergeDeepRight in WorkerUtils
- Replace console/chalk with structured logger calls in Bootstrap
- Extract magic numbers to named constants (auth cache, WS reconnect)
- Use setupConnectorWithTransaction helper in transaction tests
- Remove dead test helper OCPPAuthIntegrationTest
- Fix 'shutdowning' typo in graceful shutdown log message

3 weeks agorefactor(tests): extract hardcoded values to constants
Jérôme Benoit [Fri, 3 Apr 2026 17:36:08 +0000 (19:36 +0200)] 
refactor(tests): extract hardcoded values to constants

- extract TEST_TIMEOUT_MS constant for 9 setTimeout(30000) calls in
  UIMCPServer.test.ts
- use Constants.DEFAULT_ATG_CONFIGURATION instead of inline ATG config
  objects in SharedLRUCache, ChargingStationConfigurationUtils, and
  AutomaticTransactionGenerator tests
- add TEST_RESERVATION_EXPIRY_MS constant and replace 6 hardcoded
  3600000 values in reservation and transaction tests

3 weeks ago[autofix.ci] apply automated fixes
autofix-ci[bot] [Fri, 3 Apr 2026 17:05:49 +0000 (17:05 +0000)] 
[autofix.ci] apply automated fixes

3 weeks agorefactor: dry improvements in web UI and OCPP mock server
Jérôme Benoit [Fri, 3 Apr 2026 17:02:57 +0000 (19:02 +0200)] 
refactor: dry improvements in web UI and OCPP mock server

Web UI:
- extract localStorage key constants (UI_SERVER_CONFIGURATION_INDEX_KEY,
  TOGGLE_BUTTON_KEY_PREFIX, SHARED_TOGGLE_BUTTON_KEY_PREFIX)
- add deleteLocalStorageByKeyPattern() utility with safe collect-then-
  delete iteration
- add getWebSocketStateName() utility replacing duplicated switch
- remove redundant .trim() calls (already handled by v-model.trim)

OCPP mock server:
- extract FALLBACK_TRANSACTION_ID constant and shared helper method
- replace 20-case match/case with _COMMAND_HANDLERS dict dispatch
- unify _parse_set/get_variable_specs into shared _parse_variable_specs
- add ClassVar annotation for proper mypy typing

3 weeks agorefactor: use utility functions consistently across codebase
Jérôme Benoit [Fri, 3 Apr 2026 16:33:14 +0000 (18:33 +0200)] 
refactor: use utility functions consistently across codebase

Replace manual patterns with existing utility functions to improve DRY
compliance:

- Use isEmpty/isNotEmptyArray/isNotEmptyString instead of .length checks
- Use convertToInt/convertToFloat instead of Number.parseInt/Number
- Use roundTo instead of Math.round(x * N) / N
- Use ensureError in catch blocks for proper error type narrowing
- Add UNIT_DIVIDER_KILO, MILLISECONDS_PER_HOUR and
  DEFAULT_EXPONENTIAL_BACKOFF_JITTER_MS to Constants

Note: isEmpty/isNotEmptyString apply whitespace trimming, which
tightens validation for identifiers and configuration values.

3 weeks agorefactor: use getErrorMessage helper and extract auth cache constant
Jérôme Benoit [Fri, 3 Apr 2026 15:42:38 +0000 (17:42 +0200)] 
refactor: use getErrorMessage helper and extract auth cache constant

Replace 7 instanceof Error ternary patterns with getErrorMessage()
for consistent error message extraction. Extract hardcoded
maxEntries 1000 to Constants.DEFAULT_AUTH_CACHE_MAX_ENTRIES
across InMemoryAuthCache, AuthComponentFactory, and
OCPPAuthServiceImpl.

3 weeks agofix(tests): use version-agnostic StandardParametersKey
Jérôme Benoit [Fri, 3 Apr 2026 15:17:43 +0000 (17:17 +0200)] 
fix(tests): use version-agnostic StandardParametersKey

Replace OCPP16StandardParametersKey import in common test
with version-agnostic StandardParametersKey union type.

3 weeks agorefactor: replace string literals with OCPP enum constants
Jérôme Benoit [Fri, 3 Apr 2026 15:09:52 +0000 (17:09 +0200)] 
refactor: replace string literals with OCPP enum constants

Add AllowReset and MasterPassGroupId to OCPP20OptionalVariableName
enum. Replace all hardcoded OCPP variable name strings with enum
references in source and test files. Move EVSE Component section
comment to correct position.

3 weeks agorefactor: use string/array helper functions consistently
Jérôme Benoit [Fri, 3 Apr 2026 14:27:05 +0000 (16:27 +0200)] 
refactor: use string/array helper functions consistently

Replace 9 manual .trim().length checks with isEmpty() and
isNotEmptyString() helpers. Replace Array.isArray+length
guards with isNotEmptyArray() in StatisticUtils. Simplify
isValidIdentifierValue to delegate to isNotEmptyString.
Replace hardcoded SecurityCtrlr.OrganizationName string
with OCPP20ComponentName/RequiredVariableName enums.

3 weeks agofix(deps): update all non-major dependencies (#1772)
renovate[bot] [Fri, 3 Apr 2026 13:53:47 +0000 (15:53 +0200)] 
fix(deps): update all non-major dependencies (#1772)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
3 weeks agorefactor: use utility helpers consistently across codebase
Jérôme Benoit [Fri, 3 Apr 2026 13:41:36 +0000 (15:41 +0200)] 
refactor: use utility helpers consistently across codebase

Replace manual * 1000 with secondsToMilliseconds() in auth
cache, remote strategy, and OCPP20 incoming request. Replace
manual / 1000 with millisecondsToSeconds() in auth helpers,
auth service, and cert signing retry. Replace 'in' operator
with has() in auth service. Replace configurationKey find
with getConfigurationKey() in OCPP20RequestService. Use
formatDurationMilliSeconds for reconnect delay log. Keep
ms precision in auth service logs (sub-second durations).

3 weeks agorefactor(webui): remove redundant CSTable re-mount on toggle
Jérôme Benoit [Fri, 3 Apr 2026 12:50:27 +0000 (14:50 +0200)] 
refactor(webui): remove redundant CSTable re-mount on toggle

The @clicked handler on the Add Charging Stations toggle
forced a CSTable re-mount on every click. This is unnecessary
since watch($chargingStations) already handles re-renders
when data changes via WS server notifications.

3 weeks ago[autofix.ci] apply automated fixes
autofix-ci[bot] [Fri, 3 Apr 2026 12:45:51 +0000 (12:45 +0000)] 
[autofix.ci] apply automated fixes

3 weeks agofeat(webui): remove reload button (auto-refresh via WebSocket)
Jérôme Benoit [Fri, 3 Apr 2026 12:42:46 +0000 (14:42 +0200)] 
feat(webui): remove reload button (auto-refresh via WebSocket)

The WS server pushes refresh notifications on state changes,
making the manual reload button redundant. Remove ReloadButton
component, its styles, tests, and stub. Simplify need-refresh
handler to only reset add-stations toggle (data refresh and
CSTable re-render handled by server notification + watcher).
Remove dead --spacing-xl CSS variable from all themes.

3 weeks agorefactor(webui): migrate globalProperties to provide/inject
Jérôme Benoit [Fri, 3 Apr 2026 11:57:37 +0000 (13:57 +0200)] 
refactor(webui): migrate globalProperties to provide/inject

Replace Vue 2-style app.config.globalProperties with Vue 3
provide/inject using typed InjectionKeys. Create useConfiguration
and useTemplates composables. Remove dead globalProperties
fallback paths and refreshChargingStations no-op. Update test
mounts to use provide. Clean ComponentCustomProperties from
shims-vue.d.ts.

3 weeks agorefactor(webui): align $ prefix convention on composable locals
Jérôme Benoit [Fri, 3 Apr 2026 11:00:52 +0000 (13:00 +0200)] 
refactor(webui): align $ prefix convention on composable locals

Rename uiClient to $uiClient in 4 components (convention:
composable-returned Vue service instances use $ prefix).
Rename ref to $chargingStations in Utils.ts (was shadowing
Vue ref import). Keep chargingStationsRef unchanged in
ChargingStationsView (would shadow globalProperty in template).

3 weeks agofix: restrict test coverage to src/ runtime code only
Jérôme Benoit [Thu, 2 Apr 2026 22:47:34 +0000 (00:47 +0200)] 
fix: restrict test coverage to src/ runtime code only

Add --test-coverage-include glob to exclude tests, scripts,
package.json and other non-runtime files from coverage report.
Aligns with web UI vitest coverage config pattern.

3 weeks agorefactor(tests): migrate hardcoded test tags to shared constants
Jérôme Benoit [Thu, 2 Apr 2026 21:48:18 +0000 (23:48 +0200)] 
refactor(tests): migrate hardcoded test tags to shared constants

Replace 41 hardcoded tag/token strings across 13 test files
with imports from ChargingStationTestConstants. Includes
test utility factories. Normalize import paths to shortest
relative form and merge duplicate imports.