Skip to content

Add comprehensive ticket validation with controlTicket function - #25

Merged
chtitux merged 2 commits into
mainfrom
claude/implement-control-page-YhcgA
Feb 15, 2026
Merged

Add comprehensive ticket validation with controlTicket function#25
chtitux merged 2 commits into
mainfrom
claude/implement-control-page-YhcgA

Conversation

@chtitux

@chtitux chtitux commented Feb 15, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR introduces a complete ticket validation system for dosipas tickets, including a new controlTicket() function that performs comprehensive validation checks, a web UI component for ticket control, and supporting infrastructure.

Key Changes

Core Validation (src/control.ts)

  • New controlTicket() function: Decodes a ticket once and runs 13 focused validation checks covering:

    • Header format and version validation
    • Security metadata completeness (Level 1 & 2)
    • Level 1 and Level 2 signature verification (async)
    • Ticket expiry validation (supports both U1 and U2 header formats)
    • Specimen/test ticket detection
    • Activation status verification
    • Issuing detail validation (year, day, issuer presence)
    • Transport document presence and validity
    • Intercode extension validation with optional network ID matching
    • Dynamic data format detection (FDC1, Intercode _RICS.ID1)
    • Dynamic content freshness checks with UTC offset support
  • Check result aggregation: Each check returns a CheckResult with name, pass/fail status, severity level (error/warning/info), and optional message. Overall validity is determined by whether all error-severity checks pass.

  • Flexible options: ControlOptions supports custom reference time, Level 1 key provider callback, and expected Intercode network ID validation.

Type Definitions (src/types.ts)

  • Added ControlOptions, CheckResult, and ControlResult interfaces
  • Added Level1KeyProvider interface for async key retrieval

Testing (tests/control.test.ts)

  • Comprehensive test suite covering:
    • Decode failures and error handling
    • Real-world tickets (SNCF TER, Soléa, CTS, Grand Est)
    • Signature verification (Level 1 & 2)
    • Expiry validation with past/future dates
    • Specimen ticket detection
    • Tampered ticket detection
    • Network ID validation (matching and mismatches)
    • Dynamic content freshness calculations
    • Edge cases (missing issuer, no transport documents, etc.)

Web UI Components

  • ControlTab.tsx: New tab component featuring:

    • Hex input with camera scanner integration
    • Overall status banner (valid/invalid with error/warning counts)
    • Traveler information display with formatted birthdates
    • Validation checks list grouped by severity
    • Check badges with icons and detailed messages
    • FIPS key trust toggle for Level 1 verification
  • useTicketControl.ts: React hook for async ticket control with:

    • Debounced validation (200ms)
    • Key provider integration
    • Loading and error state management

App Integration

  • Updated App.tsx to add Control tab navigation
  • Added #control&hex=... URL hash support for sharing control results
  • Integrated navigation between Decode, Encode, and Control tabs

Exports

  • Exported controlTicket from main src/index.ts

Notable Implementation Details

  • Expiry calculation: Handles both U1 headers (issuing date + duration) and U2 headers (end-of-validity year/day + time + duration)
  • Dynamic content freshness: Supports FDC1 timestamps and Intercode dynamic data with UTC offset calculations
  • Async signature verification: Level 1 verification requires a key provider callback; Level 2 uses embedded public key
  • Severity-based validation: Distinguishes between critical errors, warnings, and informational checks for flexible validation policies
  • Network ID validation: Optional Intercode network ID matching with hex string comparison

https://claude.ai/code/session_01E6k4nTRriYRsm3eAbyv4gd

Add comprehensive ticket validation with 13 checks (decode, header,
security info, L1/L2 signatures, expiry, specimen, activated, issuing
detail, transport document, Intercode extension, dynamic data, dynamic
content freshness). The controlTicket() function returns a ControlResult
with individual CheckResult entries and an overall valid flag.

Website additions:
- New Control tab with same input methods as Decode (fixtures, file, camera)
- Clear valid/invalid status banner with error and warning counts
- Ticket holder names and birthdates display
- All 13 validation checks shown grouped by status
- FIPS public key trust option for RICS 9999, key id 0
- "Control" button added to both Decode and Encode pages

https://claude.ai/code/session_01E6k4nTRriYRsm3eAbyv4gd
Update controlTicket() and tests to use the new decoded output structure
where ticket data follows the UicBarcodeHeader ASN.1 schema:
- ticket.security -> ticket.level2SignedData.level1Data
- ticket.railTickets[i] -> dataSequence[i].decoded
- ticket.dynamicData/dynamicContentData -> level2Data.decoded
- ticket.level2DataBlock -> level2SignedData.level2Data
- headerVersion inferred from format string (U1->1, U2->2)
- transportDocument ticketType -> ticket.key

Add accessor helpers (firstRailTicket, fdc1Data, intercodeDynamic) to
cleanly navigate the nested schema hierarchy.

https://claude.ai/code/session_01E6k4nTRriYRsm3eAbyv4gd
@chtitux
chtitux force-pushed the claude/implement-control-page-YhcgA branch from 0e49bdc to aa7f72b Compare February 15, 2026 20:12
@chtitux
chtitux merged commit c0e6830 into main Feb 15, 2026
4 checks passed
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.

2 participants