KeeperHub / KeeperHub/keeperhub

Expression-mode condition validation reads a regex pattern's own punctuation as operators

Closed Beginner friendly
#2,502 4 comments 0 reactions 0 assignees View on GitHub
accepted bug confirmed
Dominant language
TypeScript
Stars
24
Forks
93
Avg merge
1d 8h
Merged PRs (30d)
266

Description

### Before filing

- [x] Searched open and closed issues and PRs: the only related thread is #2407 (the operator itself) and its PR #2445, which is where this was found.
- [x] Checked current behaviour on `staging` at `6c8eb1b0ebe1f7ece3f7c32b324a095fee41ab39`.
- [x] This is one change: the expression-mode validator's token scan, not the evaluator.

### Reason: what you cannot do today

`validateConditionExpressionUI` tokenises the expression with the pattern literal still in it, so the pattern's own punctuation is read as expression syntax. The pattern the docs, the MCP schema string and two runtime error messages recommend is refused in expression mode:

```
^0x[0-9a-fA-F]{40}$ -> Operator "-" must have exactly one space before it
^[a-c]+$ -> same
(?:0x)?[0-9a-f]+ -> same
```

So an author who builds the condition in the visual builder gets a clean save, and the same condition typed in expression mode is rejected with a message about an operator that is not in their condition. The other four scanners in `validateConditionExpression` were fixed for this by scanning a masked copy (`validateConditionExpression` masks once and passes it down); the expression-mode tokeniser was not part of that change.

### Scope

One function and its tokeniser, and it ships on its own: the fix does not depend on the evaluator change and the evaluator change does not depend on it. Only expression mode reaches this code path, which is why the visual builder is unaffected and why it is not a blocker on #2445.

### Plan

Mask quoted literals before the expression-mode tokeniser reads the string, the way `maskStringLiterals` already does for the five scanners in `validateConditionExpression`, and keep the masked copy's length so error positions still line up with what the author typed. A test through `validateConditionExpressionUI` for `^0x[0-9a-fA-F]{40}$` and `^[a-c]+$` is the check that it landed, since expression mode is the only surface that reaches it.

Contributor guide

Open the contributing guide

Research direction

Start at validateConditionExpressionUI and compare its token scan with the masked-copy approach already used by validateConditionExpression and maskStringLiterals. Add coverage through validateConditionExpressionUI for ^0x[0-9a-fA-F]{40}$ and ^[a-c]+$, preserving the masked copy's length so error positions remain aligned.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
backend, testing
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.