Skip to content

feat: add duplicate-transaction-scanner feature slice - #300

Merged
BigDella merged 1 commit into
Parcel-Protocol:mainfrom
Alfredzee:feat/duplicate-transaction-scanner
Oct 19, 2026
Merged

BigDella merged 1 commit into
Parcel-Protocol:mainfrom
Alfredzee:feat/duplicate-transaction-scanner

Conversation

@Alfredzee

Copy link
Copy Markdown

Implements a full vertical slice for deterministic duplicate detection and audited merge review workflow.

Detection

  • SHA-256 fingerprint over source_account + op_types_sorted + fee + memo + network + 5-minute time bucket (TIME_BUCKET_SECONDS = 300)
  • groupByFingerprint returns only groups with 2+ matches
  • Deterministic: same inputs → same group IDs across re-scans

Review workflow

  • Three actions: confirm (terminal), dismiss (terminal), defer (reversible)
  • applyReview drives a strict state machine:
    pending → confirm | dismiss | defer
    deferred → confirm | dismiss | defer
    confirmed → (no transitions)
    dismissed → (no transitions)
  • Every successful transition emits record.state_changed via core/audit
  • Every refused transition emits record.transition_denied
  • All review ops are wrapped in measure() for telemetry

Persistence

  • Groups survive page reloads via localStorage (utix:dup-scan:v1:groups)
  • mergeIntoStore preserves existing review decisions on re-scan

Tests

  • schema.test.ts — parse/validate input (10 cases)
  • fingerprint.test.ts — determinism, bucketing, grouping (15 cases)
  • review.test.ts — state machine, mergeIntoStore (15 cases)
  • scanner.test.ts — Horizon fetch + MSW (7 cases, incl. 404/429)
  • format.test.ts — presentation helpers

No shared files modified.

Summary

Describe what changed and why. One pull request must implement exactly one
issue and one independent feature slice.

Scope proof

Issue: Closes #

Feature directory: features/<slug>/

Changed file count:

git diff --name-only origin/main...HEAD | wc -l
  • This pull request changes at least 20 meaningful files (the scaffold normally creates 23)
  • Every product change is inside the feature directory above
  • This work does not require another open issue or unmerged pull request
  • No generated registry file or shared navigation/route list was edited

How to Test

Describe the exact happy path, one validation failure, one transport failure,
and the network(s) a reviewer should use.

  1. Go to ...
  2. Enter ...
  3. See ...

Evidence

Add screenshots for idle, loading, success and error states. Include the result
of the slice-specific contract check:

npm run verify:features -- <slug>

Checklist

  • npm run check passes locally
  • Logic returns Result<T, Code> for every expected failure
  • Every error code has actionable copy in copy.ts
  • Idle, loading, success and error states are implemented
  • Network requests are tested through MSW, not internal-module mocks
  • Accessibility tests cover at least two states with zero WCAG 2.1 A/AA violations
  • Amount arithmetic uses strings/BigInt, never floating point
  • No secret key is accepted, rendered, stored, logged or transmitted
  • README.md records the feature's non-obvious technical decision
  • If this changes docs/FEATURE_CONTRACT.md, it adds or supersedes an ADR in docs/adr/

Follow-Up

Call out known limitations only. Do not make this pull request depend on future
work; anything required by the acceptance criteria belongs in this slice.

closes #220

Implements a full vertical slice for deterministic duplicate detection
and audited merge review workflow.

Detection
- SHA-256 fingerprint over source_account + op_types_sorted + fee +
  memo + network + 5-minute time bucket (TIME_BUCKET_SECONDS = 300)
- groupByFingerprint returns only groups with 2+ matches
- Deterministic: same inputs → same group IDs across re-scans

Review workflow
- Three actions: confirm (terminal), dismiss (terminal), defer (reversible)
- applyReview drives a strict state machine:
    pending   → confirm | dismiss | defer
    deferred  → confirm | dismiss | defer
    confirmed → (no transitions)
    dismissed → (no transitions)
- Every successful transition emits record.state_changed via core/audit
- Every refused transition emits record.transition_denied
- All review ops are wrapped in measure() for telemetry

Persistence
- Groups survive page reloads via localStorage (utix:dup-scan:v1:groups)
- mergeIntoStore preserves existing review decisions on re-scan

Tests
- schema.test.ts  — parse/validate input (10 cases)
- fingerprint.test.ts — determinism, bucketing, grouping (15 cases)
- review.test.ts  — state machine, mergeIntoStore (15 cases)
- scanner.test.ts — Horizon fetch + MSW (7 cases, incl. 404/429)
- format.test.ts  — presentation helpers

No shared files modified.
@drips-wave

drips-wave Bot commented Oct 18, 2026

Copy link
Copy Markdown

@Alfredzee Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@BigDella
BigDella merged commit 621113f into Parcel-Protocol:main Oct 19, 2026
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.

Utix: Implement deterministic duplicate detection and merge review workflow

2 participants