• v4.0.0 48302b235c

    v4.0.0
    All checks were successful
    Publish (NPM) / publish (release) Successful in 9s
    Publish (JSR) / publish (release) Successful in 13s
    Publish (Maven) / publish (release) Successful in 1m0s
    ci-orchestrator / provision running on cpx42 in fsn1
    Publish (crates.io) / publish (release) Successful in 23s
    Stable

    hloth released this 2026-10-04 15:06:17 +02:00 | 0 commits to main since this release

    Signed by hloth
    GPG key ID: 299E9A450132A28C

    v4.0.0

    Full changelog

    JavaScript, TypeScript lib

    • decodeCard reads Lazo cards with a 4-byte UID. A 4K chip can carry a 4-byte UID, so the chip and the UID length are detected separately from block 0, and Card.uid is 4 or 7 bytes on a 4K chip
    • CardType.LazoTopUp → CardType.LazoTopUp371F
    • CardType.LazoTopUp375F added for the second Lazo card type, 0D375F
    • Card.journeySummary → JourneySummarySlot, either { state: "read", summary } or { state: "unknown", error }, so a block 10 that does not decode no longer throws away the whole card. decodeJourneySummary still throws on it
    • JourneySummary.transfersLeft → paidMarker, since byte [13] is only known as 0x63 after a paid journey and 0x62 after a free transfer
    • The block 0 error names the bytes it read

    Rust lib

    • Card::decode reads Lazo cards with a 4-byte UID. A 4K chip can carry a 4-byte UID, so Uid::decode returns (Uid, Chip) and Uid::chip is removed
    • Card::chip, CardType::chip() and Chip::sectors() added
    • CardType::LazoTopUp → CardType::LazoTopUp371F
    • CardType::LazoTopUp375F added for the second Lazo card type, 0D375F, so CardType::ALL is now [Self; 5]
    • Card::journey_summary → Option<Result<JourneySummary>>, so a block 10 that does not decode no longer throws away the whole card. JourneySummary::decode still returns the error
    • JourneySummary::transfers_left → paid_marker, since byte [13] is only known as 0x63 after a paid journey and 0x62 after a free transfer
    • Error::Sak → Error::Sak { byte_5, byte_7 }, the bytes it read

    Java, Kotlin lib

    • Card.decode reads Lazo cards with a 4-byte UID. A 4K chip can carry a 4-byte UID, so Uid.of(byte[]) → Uid.of(byte[], Chip), and Chip.uidLength() and Chip.ofUidLength(int) are removed
    • CardType.LAZO_TOP_UP → CardType.LAZO_TOP_UP_371F
    • CardType.LAZO_TOP_UP_375F added for the second Lazo card type, 0D375F
    • Card.journeySummary() → Optional<JourneySummarySlot>, either Read or Unknown carrying the CardFormatException, so a block 10 that does not decode no longer throws away the whole card. JourneySummary.decode still throws on it
    • The JourneySummary component transfersLeft → paidMarker, since byte [13] is only known as 0x63 after a paid journey and 0x62 after a free transfer
    • The block 0 error names the bytes it read