Skip to content

v0.1.0

Choose a tag to compare

@0x00001312 0x00001312 released this 30 Jun 10:15

Added

  • Security: optional duress password (Settings > Security > Duress
    Password). Entering it at the boot unlock screen instead of the real
    password wipes the identity, messages, contacts, and settings on every
    storage tier (NVS, SD, flash), then reboots straight into the normal
    first-time-setup screen with no "wiped" indicator shown. The new
    Duress module stores a verifier blob in NVS and checks candidate
    passwords by reusing IdentityCrypto's wrap/unwrap envelope, so a
    wrong guess never derives a real key. The wipe routine itself is a new
    shared FactoryWipe module, also used by the existing manual Factory
    Reset. Configured via a small popup (Enable/Disable/Reset), with
    validation that the duress password differs from the real one. See
    docs/duress-password.md.
  • Security: optional auto-lock (Settings > Security > Auto-Lock).
    Pick an idle timeout — 30 min, 1h, 4h, 8h, 12h, or Disabled (the
    default) — and once the device has been idle that long it reboots
    back to the at-rest password screen, discarding the decrypted identity
    from RAM until the real password is re-entered.
  • Messaging: anti-spam proof-of-work stamps (LXStamper), for peers
    that require one before accepting a message. Stamps generate in the
    background on their own task so sending stays responsive while the
    device grinds the proof of work; a confirm overlay asks first if the
    required cost is high enough to take a while. Settings > Messaging
    gets a stamp cost ceiling editor — stamps above it prompt instead of
    generating silently. See docs/lxmf-stamps.md.
  • Radio: new Diagnostics screen (Settings > Radio > Diagnostics),
    separate from the existing Frequency/SF/BW/CR/TX Power editor (now
    under Settings > Radio > Config). Three pages, cycled with ;/.:
    Live (TX/RX throughput graph, RSSI/SNR/noise floor, airtime usage,
    chip/link status, time since last RX/TX), Counters (packet/failure/
    CRC-fail/queue-drop counts and decoded radio device errors, clearable),
    and Network (current PHY config, Reticulum path/link counts, last
    announce time, known peers, LXMF outbox depth, heap/loop health).
    Backed by new packet/error counters on SX1262/LoRaInterface and a new
    reusable StatGraph widget.
  • GPS: system clock now syncs to UTC directly from the GPS RMC
    sentence instead of relying on a user-picked timezone. For local time
    display, GPSManager checks the GPS fix's coordinates against a new
    TimeZoneDB table of real POSIX TZ rules covering major regions, so
    DST transitions land on the correct date; positions outside the table
    fall back to a longitude/season estimate. Settings > Time adds a
    manual override (toggle + UTC offset field) for when the automatic
    estimate is wrong. The status bar clock now has its own permanent
    spot instead of alternating with battery percentage, and dims until
    GPS confirms a real satellite fix.

Fixed

  • LoRa: the radio had no collision avoidance at all — it keyed up
    immediately whenever it wasn't itself mid-TX/RX, with no notion of
    another node transmitting on the same channel. On a shared
    half-duplex channel with more than one active node, this was a direct
    cause of delayed/dropped/reordered delivery. Added listen-before-talk:
    SX1262::dcd() detects an in-progress carrier/header via the modem's
    PREAMBLE_DET/HEADER_DET IRQ flags, and LoRaInterface now queues
    instead of transmitting into a busy channel, draining the queue once
    the channel clears after a randomized contention window sized from
    the radio's own symbol time.
  • LoRa: fixed a duplicate-detection bug in microReticulum's
    packet-hashlist eviction — it's a std::set<Bytes> ordered by hash
    value, but eviction was erasing from .begin() as if that were
    insertion order, so culling discarded whichever hashes were
    numerically smallest instead of the actually-oldest ones. Under
    sustained traffic this silently undermined duplicate detection. Now
    tracks real insertion order separately
    (0x00001312/microReticulum@3481921).
  • Routing: routing and reply targets broke across every reboot —
    the message store was initialized before the identity was loaded, and
    saved conversation directories were keyed by a truncated hash too
    short to address a reply back to. Fixed by initializing the message
    store with the loaded identity before refresh, and resolving saved
    conversation directories to full peer hashes for reply targets.
  • LXMF: sends to a peer with no known path were gated on a flat
    10s retry timer even after the path had already arrived, so the best
    case was a full 10-20s wait. sendDirect() now re-checks
    recall()/has_path() every queue-drain pass (10Hz) and only
    throttles the actual network-touching request_path()/
    ensureOutboundLink() calls to the 10s interval.
  • LXMF: replaced the reactive, one-shot path nudge for single-hop
    peers (raced the reply it was meant to fix, and missed any relayed
    message) with a durable per-peer preferred-interface record in
    AnnounceManager, persisted across reboots alongside saved contacts.
  • LXMF: peer names could go stale or vanish after a reboot, or even
    mid-session, because names were only ever learned from
    AnnounceManager's own rate-limited, debounced announce handler. Name
    lookups now fall back to RNS's own Identity::recall_app_data()
    cache — populated for every announce Transport validates, independent
    of AnnounceManager — and opportunistically backfill the on-disk name
    cache when they resolve a name from it.
  • LXMF: a peer name change never marked the UI dirty, so
    MessagesScreen wouldn't pick up an updated name while idle on
    screen; a name-change callback now calls ui.markContentDirty()
    directly.
  • microReticulum: picked up two upstream fixes via dependency pin
    bumps: the previously-stubbed Link retransmission watchdog plus two
    resource-transfer bugs (windowed part requests, and outbound/inbound
    resource slots never freeing after a transfer concludes;
    a71a676); and a RequestReceipt constructor that threw
    new std::invalid_argument(...) (a pointer, not a value), which
    silently slipped past any upstream catch (const std::exception&)
    and leaked the heap-allocated exception (72bdc81).

Changed

  • Settings > Wi-Fi > Mode now opens a popup listing OFF/AP/STA with the
    active mode marked, instead of silently cycling to the next mode on
    every Enter press.
  • Unified every small fixed-choice setting (Audio, Time Source,
    Auto-discover LAN, Theme input mode, Auto-Lock, WiFi Mode, Duress
    Password) onto one shared OptionPopup widget, replacing a mix of
    silent cycle-on-Enter toggles, a dedicated full-screen page, and an
    ad-hoc popup. Full-screen lists are now reserved for genuinely
    open-ended choices (WiFi scan, TCP connections, Theme presets). Also
    cleaned up unclear labels (Radio Config's SF/BW/CR, SD Card's
    "Initialize Standalone", TCP's "+ Add Connection", Display's bare
    "Name:") and moved SD Card to sit with About/Factory Reset instead of
    next to frequently-tuned settings. No stored values, validation, or
    applied behavior changed — UI/IA only.
  • Duress Password moved from a dedicated settings page into the same
    popup style, with Enable/Disable/Reset rows.

Removed

  • LXMF propagation node (offline messaging via PN) client, added
    earlier in this cycle and fully removed before release: PN sync kept
    crashing and destabilizing routing on real hardware, and chasing it
    down kept colliding with the parts of this firmware that need to be
    solid — delivery, routing, the radio link. PropagationClient is
    deleted along with every call site, Settings UI screen, and config
    field that existed only to support it. Direct LXMF delivery, anti-spam
    stamps, routing/interface stickiness, and announce handling are
    unaffected — a message either reaches its recipient directly now, or
    it fails, same as before PN existed. docs/propagation-nodes.md kept
    as a short note on why this was dropped.
  • Dead radio-preset code on the Home screen, and the status card it fed.

Build

  • microReticulum dependency now points at a personal fork (pinned
    commit) so the stamp/field support LXStamper needs, plus the
    reliability fixes above, can land as real commits there instead of
    local patches.
  • The packaged factory .bin now lands in the .pio build dir instead
    of the project root.

Docs

  • New docs/duress-password.md and docs/lxmf-stamps.md, plus
    docs/propagation-nodes.md explaining why propagation-node support
    was attempted and then removed. Cross-linked from the boot sequence,
    threat model, encryption overview, and UI framework docs.
  • Noted a one-time UX side effect for installs migrating from upstream
    ratspeak/rsCardputer configs: the old boot-time timezone picker is
    gone (superseded by GPS time sync), so first boot after migrating
    re-runs LoRa region/frequency setup via the new RadioSetupScreen
    instead of inheriting it from a timezone pick.

Full diff: https://github.com/0x00001312/rsCardputer-CE/compare/v0.0.5...v0.1.0