Skip to content

Add comprehensive ticket validation with controlTicket() function - #22

Merged
chtitux merged 4 commits into
mainfrom
claude/plan-ticket-validation-9FP6r
Feb 15, 2026
Merged

Add comprehensive ticket validation with controlTicket() function#22
chtitux merged 4 commits into
mainfrom
claude/plan-ticket-validation-9FP6r

Conversation

@chtitux

@chtitux chtitux commented Feb 15, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR introduces a new ticket validation system via the controlTicket() function, which performs comprehensive checks on decoded UIC barcode tickets. The implementation provides structured validation results across 13 distinct check categories, supporting all ticket variants including FDC1 dynamic content, Intercode 6 extensions, and multiple FCB versions.

Key Changes

  • New src/control.ts module: Implements controlTicket() as the main entry point for ticket validation, along with 13 focused check helper functions:

    • Structural checks: checkDecode, checkHeader, checkSecurityInfo, checkIssuingDetail, checkTransportDocument
    • Signature verification: checkLevel2Signature, checkLevel1Signature
    • Temporal validation: checkNotExpired, checkDynamicContentFreshness
    • Ticket state checks: checkNotSpecimen, checkActivated
    • Extension/dynamic data: checkIntercodeExtension, checkDynamicData
  • New types in src/types.ts: Added ControlOptions, CheckResult, and ControlResult interfaces to support flexible validation configuration and structured result reporting

  • Updated src/index.ts: Exported controlTicket function and new validation types for public API

  • Comprehensive test suite in tests/control.test.ts: Tests covering all check functions across multiple ticket variants (SAMPLE, Soléa, CTS, SNCF TER, Grand Est) with scenarios for expiry, specimen detection, tampering, and missing keys

Notable Implementation Details

  • Severity levels: Checks are categorized as error (makes ticket invalid), warning (informational), or info (purely informational)
  • Graceful degradation: Level 1 signature verification is optional and skipped with an info message if no key is provided; v1 header tickets don't require level 2 signatures
  • Dynamic content freshness: Supports both FDC1 and Intercode ID1 formats with configurable max age (default 60 minutes)
  • Async-ready: controlTicket() is async to support future key provider implementations
  • Reuses existing verification: Leverages existing verifyLevel2Signature() and verifyLevel1Signature() from verifier.ts for cryptographic validation

https://claude.ai/code/session_017YdSb7Xi9oSFKsXYa67bKy

Design a controlTicket() function and 13 focused check helpers for
comprehensive ticket validation: decode, header, security, signatures
(L1/L2), expiry, specimen, activation, issuing detail, transport
documents, Intercode extension, dynamic data, and content freshness.

https://claude.ai/code/session_017YdSb7Xi9oSFKsXYa67bKy
- Remove level1PublicKey option, keep only level1KeyProvider callback
- Level 1 signature is mandatory (error severity, not warning/skip)
- Level 2 signature is conditional on level2SigningAlg being set
- Validate L1 and L2 security fields independently in checkSecurityInfo
- Add expectedIntercodeNetworkIds option (Set<string> of hex IDs)
  for network ID validation in checkIntercodeExtension
- Remove dynamicContentMaxAge option, derive freshness window
  from security.validityDuration instead

https://claude.ai/code/session_017YdSb7Xi9oSFKsXYa67bKy
- Remove level1KeyAlg from mandatory L1 security fields (only
  level1SigningAlg and level1Signature are required)
- Clarify that intercodeIssuing.networkId is always a 3-byte
  Uint8Array, converted to a 6-character hex string for comparison

https://claude.ai/code/session_017YdSb7Xi9oSFKsXYa67bKy
FDC1: day is absolute day-of-year, time is seconds of day.
Intercode ID1: day is offset from issuing date, time is seconds
since midnight (local), UTCOffset in 15-min steps, and
dynamicContentDuration (seconds) takes precedence over
security.validityDuration when present.

https://claude.ai/code/session_017YdSb7Xi9oSFKsXYa67bKy
@chtitux
chtitux merged commit 3159ffd 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