Skip to content

validate StartTransaction.meterStart against previous meterStop (part…#1989

Open
rishabhvaish wants to merge 2 commits into
steve-community:masterfrom
rishabhvaish:fix/start-transaction-meter-regression-1963
Open

validate StartTransaction.meterStart against previous meterStop (part…#1989
rishabhvaish wants to merge 2 commits into
steve-community:masterfrom
rishabhvaish:fix/start-transaction-meter-regression-1963

Conversation

@rishabhvaish

Copy link
Copy Markdown
Contributor

The meter-start value of a new StartTransaction wasn't validated against the previous transaction on the same connector. If a charger reports a meterStart lower than the last meterStop, the energy register has regressed — either from a meter reset, firmware bug, or data integrity issue. This should be flagged as suspect.

I've added a getLastTransactionStopValue(chargeBoxId, connectorId) query to the repository layer and wired it into the existing CentralSystemService16_ServiceValidator.validateStart() method. The check runs after the existing validations (positive connectorId, non-negative meterStart, non-future timestamp) and logs a warning when meterStart < previousMeterStop. When there's no previous completed transaction (first session on a connector), the check is skipped.

This addresses rule 5 ("Meter regression") from #1963.

Tests added for: regression detected, equal values allowed, no previous transaction.

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Review Summary by Qodo

Validate StartTransaction meter against previous transaction stop value

🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Add meter regression validation to StartTransaction
• Query last transaction stop value from repository
• Compare meterStart against previous meterStop value
• Log warning when meter value decreases between transactions
Diagram
flowchart LR
  A["StartTransaction Request"] --> B["Query Last Stop Value"]
  B --> C["Validate Meter Regression"]
  C --> D{Meter Start >= Previous Stop?}
  D -->|Yes| E["Transaction Allowed"]
  D -->|No| F["Return Error Exception"]
Loading

Grey Divider

File Changes

1. src/main/java/de/rwth/idsg/steve/repository/OcppServerRepository.java ✨ Enhancement +1/-0

Add repository interface for last transaction stop value

• Add new interface method getLastTransactionStopValue() to query previous transaction's stop
 meter value
• Method accepts chargeBoxId and connectorId parameters
• Returns nullable String representing the last stop value

src/main/java/de/rwth/idsg/steve/repository/OcppServerRepository.java


2. src/main/java/de/rwth/idsg/steve/repository/impl/OcppServerRepositoryImpl.java ✨ Enhancement +14/-0

Implement meter stop value database query

• Implement getLastTransactionStopValue() method with database query
• Query joins TRANSACTION and CONNECTOR tables
• Filters by chargeBoxId and connectorId with non-null stop values
• Orders by stop timestamp descending and limits to 1 result

src/main/java/de/rwth/idsg/steve/repository/impl/OcppServerRepositoryImpl.java


3. src/main/java/de/rwth/idsg/steve/service/CentralSystemService16_Service.java ✨ Enhancement +4/-1

Fetch and pass previous stop value to validator

• Fetch previous transaction stop value before validation
• Pass previousStopValue to validator's validateStart method
• Retrieve value using ocppServerRepository query

src/main/java/de/rwth/idsg/steve/service/CentralSystemService16_Service.java


View more (2)
4. src/main/java/de/rwth/idsg/steve/service/CentralSystemService16_ServiceValidator.java 🐞 Bug fix +5/-1

Add meter regression validation logic

• Add previousStopValue parameter to validateStart() method
• Add meter regression check comparing meterStart to previousStopValue
• Return error when meterStart is less than previous stop value
• Check executes after existing validations

src/main/java/de/rwth/idsg/steve/service/CentralSystemService16_ServiceValidator.java


5. src/test/java/de/rwth/idsg/steve/service/CentralSystemService16ServiceValidatorTest.java 🧪 Tests +26/-4

Add meter regression validation tests

• Update all existing validateStart test calls to pass null previousStopValue
• Add test for meter regression detection when meterStart < previousStop
• Add test for equal meter values allowed scenario
• Add test for no previous transaction scenario

src/test/java/de/rwth/idsg/steve/service/CentralSystemService16ServiceValidatorTest.java


Grey Divider

Qodo Logo

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Mar 20, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0) 📎 Requirement gaps (1) 📐 Spec deviations (0)

Grey Divider


Action required

1. StartTransaction inserts despite validation 📎 Requirement gap ⛯ Reliability
Description
Even when validateStart(...) returns an exception (including meter regression), the code only logs
a warning and still calls insertTransaction, so the event is not flagged/recorded as suspect and
side effects still occur. This violates the requirement to mark meter regression as suspect and to
avoid side effects after validation failure.
Code

src/main/java/de/rwth/idsg/steve/service/CentralSystemService16_Service.java[R233-239]

+        String previousStopValue = ocppServerRepository.getLastTransactionStopValue(
+            chargeBoxIdentity, parameters.getConnectorId()
+        );
+        var exception = serviceValidator.validateStart(parameters, previousStopValue);
       if (exception != null) {
           log.warn("StartTransaction validation failed", exception);
       }
Evidence
Compliance requires suspect-flagging on meter regression and no side effects after validation
failure. The validator returns a SteveException on meter regression, but startTransaction(...)
does not branch on exception and still inserts the transaction into the DB.

Flag StartTransaction as suspect when meterStart regresses below last completed transaction meterStop on same connector
src/main/java/de/rwth/idsg/steve/service/CentralSystemService16_Service.java[233-242]
src/main/java/de/rwth/idsg/steve/service/CentralSystemService16_ServiceValidator.java[69-71]
Best Practice: Learned patterns

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`startTransaction(...)` continues with `insertTransaction(...)` even when `validateStart(...)` returns a non-null exception (including the new meter-regression exception). This means the event is not actually flagged/recorded as suspect, and DB writes occur after validation failure.
## Issue Context
The meter regression check currently returns a `SteveException`, but the caller only logs and proceeds. To meet compliance, the system must deterministically record/flag the StartTransaction as suspect (or otherwise prevent normal processing) and avoid normal state mutation after validation failure.
## Fix Focus Areas
- src/main/java/de/rwth/idsg/steve/service/CentralSystemService16_Service.java[233-242]
- src/main/java/de/rwth/idsg/steve/service/CentralSystemService16_ServiceValidator.java[69-71]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. previousStopValue parsed unsafely📘 Rule violation ⛯ Reliability
Description
Integer.parseInt(previousStopValue) is performed without validating that previousStopValue is
numeric, which can throw at runtime on corrupted/unexpected values. Additionally, the DB lookup for
previousStopValue is executed before validating externally supplied connectorId (used in the
query predicate).
Code

src/main/java/de/rwth/idsg/steve/service/CentralSystemService16_ServiceValidator.java[R69-70]

+        if (previousStopValue != null && params.getMeterStart() < Integer.parseInt(previousStopValue)) {
+            return new SteveException("StartTransaction.meterStart is less than previous transaction's meterStop");
Evidence
The checklist requires validating externally supplied inputs before using them in comparisons and
query predicates. The code parses and compares previousStopValue without numeric validation, and
it also queries by connectorId before validating that connectorId is semantically valid.

src/main/java/de/rwth/idsg/steve/service/CentralSystemService16_ServiceValidator.java[69-70]
src/main/java/de/rwth/idsg/steve/service/CentralSystemService16_Service.java[233-236]
Best Practice: Learned patterns

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`previousStopValue` is parsed via `Integer.parseInt(...)` without checking that it is a valid integer, and the repository lookup is executed before validating `connectorId`. This can cause runtime exceptions or incorrect query behavior for invalid/edge-case inputs.
## Issue Context
Although `previousStopValue` is read from the DB, it is still an externally-derived value from prior station data and may be missing/corrupt. `connectorId` comes from the inbound StartTransaction request and should be validated before it is used in a query predicate.
## Fix Focus Areas
- src/main/java/de/rwth/idsg/steve/service/CentralSystemService16_ServiceValidator.java[56-71]
- src/main/java/de/rwth/idsg/steve/service/CentralSystemService16_Service.java[233-236]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

3. Noisy regression stack traces 🐞 Bug ✓ Correctness
Description
startTransaction logs any validateStart result as "StartTransaction validation failed" with the
exception object, which emits stack traces even though the flow continues to insert the transaction.
Adding meter regression to this path will increase log noise and make suspect-data cases
indistinguishable from actual invalid requests.
Code

src/main/java/de/rwth/idsg/steve/service/CentralSystemService16_Service.java[R233-239]

+        String previousStopValue = ocppServerRepository.getLastTransactionStopValue(
+            chargeBoxIdentity, parameters.getConnectorId()
+        );
+        var exception = serviceValidator.validateStart(parameters, previousStopValue);
       if (exception != null) {
           log.warn("StartTransaction validation failed", exception);
       }
Evidence
The new regression condition is represented as a SteveException in validateStart, and
startTransaction logs warnings with the exception object but does not gate insertion on it (it
always calls insertTransaction). This makes the exception primarily a logging signal, and logging it
as an exception produces stack traces for a non-blocking condition.

src/main/java/de/rwth/idsg/steve/service/CentralSystemService16_Service.java[233-248]
src/main/java/de/rwth/idsg/steve/service/CentralSystemService16_ServiceValidator.java[56-73]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Meter regression is currently surfaced as a `SteveException` and logged with `log.warn(..., exception)` while StartTransaction continues. This produces stack traces and mixes suspect-data warnings with real validation failures.
## Issue Context
`startTransaction(..)` does not abort on validation failures; it logs and continues to `insertTransaction(..)`. For non-blocking checks like meter regression, logging stack traces reduces signal quality.
## Fix Focus Areas
- Log meter regression as a single-line warning **without** passing an exception object.
- Keep other hard validation errors (connectorId &amp;lt;= 0, negative meterStart, future timestamp) as exception logs if desired.
- Option: return a structured validation result (severity + message) rather than using exceptions for non-fatal findings.
## Fix Focus Areas (code references)
- src/main/java/de/rwth/idsg/steve/service/CentralSystemService16_Service.java[233-241]
- src/main/java/de/rwth/idsg/steve/service/CentralSystemService16_ServiceValidator.java[56-73]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

Comment on lines +233 to 239
String previousStopValue = ocppServerRepository.getLastTransactionStopValue(
chargeBoxIdentity, parameters.getConnectorId()
);
var exception = serviceValidator.validateStart(parameters, previousStopValue);
if (exception != null) {
log.warn("StartTransaction validation failed", exception);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Starttransaction inserts despite validation 📎 Requirement gap ⛯ Reliability

Even when validateStart(...) returns an exception (including meter regression), the code only logs
a warning and still calls insertTransaction, so the event is not flagged/recorded as suspect and
side effects still occur. This violates the requirement to mark meter regression as suspect and to
avoid side effects after validation failure.
Agent Prompt
## Issue description
`startTransaction(...)` continues with `insertTransaction(...)` even when `validateStart(...)` returns a non-null exception (including the new meter-regression exception). This means the event is not actually flagged/recorded as suspect, and DB writes occur after validation failure.

## Issue Context
The meter regression check currently returns a `SteveException`, but the caller only logs and proceeds. To meet compliance, the system must deterministically record/flag the StartTransaction as suspect (or otherwise prevent normal processing) and avoid normal state mutation after validation failure.

## Fix Focus Areas
- src/main/java/de/rwth/idsg/steve/service/CentralSystemService16_Service.java[233-242]
- src/main/java/de/rwth/idsg/steve/service/CentralSystemService16_ServiceValidator.java[69-71]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

already handled — dcc77ccb gates side effects on validation result so insertTransaction is skipped when validateStart returns an exception

Wrap Integer.parseInt(previousStopValue) in a try-catch to gracefully
handle corrupted or non-numeric stop values from the database instead
of throwing NumberFormatException at runtime.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Rishabh Vaish <rishabhvaish.904@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant