Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 17 additions & 12 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: Release
on:
push:
tags:
- "v0.1.0"
- "v*.*.*"

permissions:
contents: read
Expand Down Expand Up @@ -35,6 +35,9 @@ jobs:
test "$(git cat-file -t "refs/tags/${RELEASE_TAG}")" = "tag"
test "$(git rev-parse "refs/tags/${RELEASE_TAG}^{}")" = "${GITHUB_SHA}"

- name: Resolve release version
run: echo "RELEASE_VERSION=${GITHUB_REF_NAME#v}" >> "${GITHUB_ENV}"

- name: Set up Node.js
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5
with:
Expand All @@ -58,7 +61,7 @@ jobs:

- name: Test unpacked release bytes
env:
NARROWSLINK_RELEASE_ARCHIVE: build/release/narrowslink-0.1.0.tgz
NARROWSLINK_RELEASE_ARCHIVE: build/release/narrowslink-${{ env.RELEASE_VERSION }}.tgz
run: npm run test:release

- name: Verify published checksum set
Expand All @@ -70,9 +73,9 @@ jobs:
with:
name: narrowslink-release-${{ github.ref_name }}
path: |
build/release/narrowslink-0.1.0.tgz
build/release/narrowslink-0.1.0.release.json
build/release/narrowslink-0.1.0.cdx.json
build/release/narrowslink-*.tgz
build/release/narrowslink-*.release.json
build/release/narrowslink-*.cdx.json
build/release/SHA256SUMS
if-no-files-found: error
retention-days: 14
Expand Down Expand Up @@ -106,14 +109,16 @@ jobs:
env:
GH_TOKEN: ${{ github.token }}
run: |
test "${GITHUB_REF_NAME}" = "v0.1.0"
test -f "docs/releases/v0.1.0.md"
RELEASE_VERSION="${GITHUB_REF_NAME#v}"
test "v${RELEASE_VERSION}" = "${GITHUB_REF_NAME}"
test -f "docs/releases/${GITHUB_REF_NAME}.md"
test -f "build/release/narrowslink-${RELEASE_VERSION}.tgz"
gh release create "${GITHUB_REF_NAME}" \
build/release/narrowslink-0.1.0.tgz \
build/release/narrowslink-0.1.0.release.json \
build/release/narrowslink-0.1.0.cdx.json \
"build/release/narrowslink-${RELEASE_VERSION}.tgz" \
"build/release/narrowslink-${RELEASE_VERSION}.release.json" \
"build/release/narrowslink-${RELEASE_VERSION}.cdx.json" \
build/release/SHA256SUMS \
--repo "${GITHUB_REPOSITORY}" \
--verify-tag \
--title "NarrowsLink v0.1.0" \
--notes-file "docs/releases/v0.1.0.md"
--title "NarrowsLink ${GITHUB_REF_NAME}" \
--notes-file "docs/releases/${GITHUB_REF_NAME}.md"
8 changes: 4 additions & 4 deletions ACCESSIBILITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ The Playwright suite runs against Chromium, Firefox, and WebKit in `npm run chec
| Bundled and local replay | Pass | Pass | Pass | Invalid import recovery, playback, seeking, rate changes, and active-replay preservation |
| Local session library | Pass | Pass | Pass | Save, exact-content deduplication, reload, validated reopen, workspace restoration, guarded removal, and unavailable/quota/corruption/cleanup failures |
| Maximum-record processing | Pass | Pass | Pass | A 200,000-record replay is imported, persisted, cancelled during reopen without state loss, reopened, compared over an exact bounded range, cancelled during bundle construction without a download, rebuilt, and verified while a one-second heartbeat monitors interaction responsiveness |
| UDP capture-to-evidence loop | Pass | Pass | Pass | Real loopback NSL-01 and NMEA capture, reconciled v2 receipt, `.nlsession` download and reimport, replay, exact incident export, independent archive verification, in-application receipt, reload, and failure recovery |
| Simulated Web Serial capture-to-evidence loop | Pass | Pass | Pass | Injected browser API, fragmented reads, complete and partial NSL-01 assembly, reconciled v2 receipt, durable reopen, replay, exact authored range, `.nlb` generation, and independent archive verification |
| UDP capture-to-evidence loop | Pass | Pass | Pass | Real loopback NSL-01 and NMEA preflight, decoder-fit and mismatch states, explicit new-capture boundary, reconciled v2 receipt, `.nlsession` download and reimport, replay, exact incident export, independent archive verification, in-application receipt, reload, and failure recovery |
| Simulated Web Serial capture-to-evidence loop | Pass | Pass | Pass | Injected browser API, preflight on one selected device, future-read handler transfer without reopen, fragmented reads, complete and partial NSL-01 assembly, reconciled v2 receipt, durable reopen, replay, exact authored range, `.nlb` generation, and independent archive verification |
| Received evidence workspace | Pass | Pass | Pass | Exact bounded incident, separate verification claims, explicit unavailable groups, decoded and raw evidence, provenance, source annotations, separate receiver finding, rejected-archive recovery, reload, and unpacked-release replacement |
| Comparative replay workspace | Pass | Pass | Pass | Explicit baseline and candidate setup, validated session and verified-bundle input, aligned range control, eligibility matrix, metric selection, bounded source trace, authored conclusion, finding export, and clean state for a new comparison |
| axe rules tagged WCAG A/AA | Pass | Pass | Pass | Automated scans of the replay, receiver, and comparison workspaces plus live-capture, range, marker, bundle, comparison-setup, and long-running processing dialogs |
| Keyboard and focus handoff | Pass | Pass | Pass | Dialog entry/return, incident tabs, range deletion, incident clear/select, capture start-to-recording, captured-session replacement, comparison setup, and authored finding controls |
| Keyboard and focus handoff | Pass | Pass | Pass | Dialog entry/return, incident tabs, range deletion, incident clear/select, capture ready-to-preflight-to-recording transitions, captured-session replacement, comparison setup, and authored finding controls |
| Reflow and horizontal evidence access | Pass | Pass | Pass | Replay, receiver, and comparison workspaces at `960 × 900`, `640 × 900`, and `390 × 844`; no page-level horizontal overflow, wrapped command actions, and explicit keyboard panning for table or timeline scrollers |
| Forced-color and non-color cues | Pass | Pass | Pass | Selected incidents expose pressed state; diagnostics retain visible severity words or `C`/`W`/`I` tokens in addition to color |

Expand All @@ -27,7 +27,7 @@ Playwright's WebKit project provides browser-engine coverage. It does not by its
## Keyboard contract

- Opening a dialog moves focus to its first meaningful field or action, traps `Tab` within the modal, and returns focus to the opener when the dialog closes.
- Live capture moves focus to a valid control or status target whenever setup, recording, stopping, saving, recovery, or discard replaces the previously focused action.
- Live capture moves focus to a valid control or status target whenever ready, preflight, recording, stopping, saving, recovery, or discard replaces the previously focused action.
- Incident tabs support arrow-key navigation with one selected and tabbable tab.
- Clearing an incident focuses the empty selection state; selecting the first incident or deleting an authored range focuses the replacement selector or empty state.
- Delete and discard confirmations focus the safe action first and return focus to the initiating control when cancelled.
Expand Down
10 changes: 9 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@ All notable changes to NarrowsLink are recorded here. This is the canonical proj

## [Unreleased]

## [0.2.0] - 2026-07-25

### Added

- Added reusable local capture profiles that preserve validated UDP or serial settings and the exact decoder pack while explicitly excluding bridge credentials, browser device permission, session names, and telemetry payloads.
- Added bounded UDP and Web Serial preflight before recording, with live source state, traffic and byte rates, last-input age, valid and malformed frame counts, checksum failures, message families, endpoint observations, no-traffic guidance, and decoder-mismatch guidance.
- Added an explicit preflight-to-evidence boundary: UDP probes are stopped and discarded before a new owned capture ID begins, while serial retains the selected port but resets framing and routes only future reads into the immutable session.
- Added bounded, content-addressed decoder packs with an allowlisted parser runtime, canonical pack and schema identities, production-path conformance fixtures, local operator loading, and packaged `decoder seal` and `decoder validate` commands; new captures persist the exact pack and runtime while legacy NSL-01 sessions remain compatible and unchanged.
- Added the NMEA 0183 reference pack for checksummed GGA, RMC, and HDT sentences over one-sentence-per-datagram UDP or line-delimited serial input, including partial-tail retention, checksum diagnostics, real loopback UDP capture, local-library reopen, evidence export, and production receiver replay verification.
- Added an in-application receiver workspace for untrusted version 3 `.nlb` bundles: worker-isolated production verification now precedes inspection, the exact bounded incident is reconstructed only from included evidence, excluded context remains explicit, and internal consistency, evidence completeness, and unsigned authenticity remain separate claims.
Expand All @@ -18,6 +23,8 @@ All notable changes to NarrowsLink are recorded here. This is the canonical proj

### Changed

- Promoted decoder packs, NMEA 0183, the in-application receiver, comparative replay, worker-backed large-session processing, and field-capture preflight into the self-contained v0.2 operator distribution.
- Generalized the annotated-tag release workflow so the package version, release notes, asset names, and GitHub Release remain bound to one `v<package-version>` identity.
- Defined NarrowsLink's product goal and success criteria around reproducible constrained-telemetry incidents and independently verified handoffs; retained the strategic product directions and moonshot opportunities while keeping delivered capabilities in the changelog and current-state docs.
- Expanded UC-001 with supported radio transport capture topologies, including USB serial radio, UDP base-station output, forwarded UDP copies, and network multicast observer setup and test paths.
- Raised the imported and saved replay envelope from 32 MiB and 100,000 records to 64 MiB and 200,000 records while retaining the separate live-capture ceiling of 100,000 records, 32 MiB of retained payload bytes, 24 hours, and a canonical file within the replay limit.
Expand Down Expand Up @@ -55,5 +62,6 @@ All notable changes to NarrowsLink are recorded here. This is the canonical proj

- Restricted the UDP bridge control plane to loopback access with server-enforced capture ownership and an internal short-lived bearer credential; the browser uses a same-origin application relay, so the credential is not exposed in runtime metadata, URLs, cookies, readiness output, or logs.

[Unreleased]: https://github.com/zrack/narrowslink/compare/v0.1.0...HEAD
[Unreleased]: https://github.com/zrack/narrowslink/compare/v0.2.0...HEAD
[0.2.0]: https://github.com/zrack/narrowslink/releases/tag/v0.2.0
[0.1.0]: https://github.com/zrack/narrowslink/releases/tag/v0.1.0
5 changes: 4 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,8 @@ Changing a description, schema, fixture, or expected result changes pack identit
- Re-hash, parse, and validate every saved-session reopen. Surface corruption and storage failures without replacing the active validated replay or claiming an uncommitted save succeeded.
- Treat saved-session removal as a two-store operation: delete the IndexedDB replay, clear its per-session local-storage workspace when identifiable, keep any active replay in memory, and warn if residual operator context could not be cleared.
- Never let a control client stop or adopt a UDP capture it did not start; reconcile bridge sequence, datagram, and byte totals before claiming a capture is complete.
- Keep saved capture profiles bounded and local, bind them to an exact conformant decoder pack, and exclude credentials, browser device permission, session naming, and telemetry payloads.
- Keep preflight bounded and outside session evidence. Require confirmed UDP probe shutdown before opening a new recording identity; for serial, keep the selected port but reset framing and route only future reads to the recorder.
- New live captures must finalize as session v2 with immutable transport events and a terminal receipt. Preserve strict v1 import behavior and never infer verified integrity for legacy evidence.
- Never substitute browser or recorder counts for an unavailable transport-reported count. Preserve null observations, use the truthful incomplete assessment basis, and require explicit adapter evidence before verification.
- Preserve the bridge journal, per-datagram UDP remote endpoint, and Web Serial device and negotiated-setting evidence when changing capture code. Keep unavailable operating-system counters explicitly null with their observation source; do not convert missing evidence into a clean zero.
Expand Down Expand Up @@ -172,6 +174,7 @@ Changing a description, schema, fixture, or expected result changes pack identit
| Evidence receiver verification and CLI | `verifier/`, `scripts/narrowslink.ts`, `vite.cli.config.ts` |
| Session serialization and import behavior | `src/data/session-file.ts`, `src/data/load-session.ts` |
| Capture lifecycle and session finalization | `src/capture/CaptureDialog.tsx`, `src/capture/recorder.ts` |
| Capture profiles and bounded preflight | `src/capture/capture-profile.ts`, `src/capture/capture-preflight.ts` |
| Serial capture and runtime-selected assembly | `src/capture/web-serial.ts`, `src/capture/serial-assembler.ts`, `src/capture/nsl01-serial-assembler.ts`, `src/capture/nmea0183-serial-assembler.ts` |
| UDP browser protocol and local bridge | `src/capture/udp-bridge.ts`, `scripts/capture-bridge.mjs` |
| Durable session-document library | `src/storage/session-library.ts` |
Expand Down Expand Up @@ -206,7 +209,7 @@ Screenshots are evidence, not the review itself. Keep `design-qa.md` focused on
- For large-session changes, regenerate the 200,000-record corpus and exercise import, progress, cancellation, exact-byte persistence, reload, reopen, selected-range comparison, bundle cancellation, completed export, production verification, heartbeat gaps, and Chromium heap growth in both the source and unpacked-release matrices.
- For UI changes, exercise the bundled replay, file-import error state, saved-session save/list/reopen/remove and failure states, playback, seeking, incident switching, marker creation, note persistence, and bundle flow at desktop and narrow widths.
- Keep critical dialogs and workspace states clean under axe rules tagged WCAG A/AA. Test keyboard focus when an action, dialog phase, incident selection, or responsive layout replaces the focused element; retain visible non-color state and severity cues.
- For capture changes, exercise both the real loopback UDP path and the browser-injected Web Serial application path from start through stop, re-import, durable reopen, replay, annotation, bundle export, and production receiver verification. Include active-capture ownership, sequence gaps, zero-length datagrams, and corrupt serial-length resynchronization in automated coverage. Treat the injected serial gate as application-path evidence, not physical hardware certification.
- For capture changes, exercise both the real loopback UDP path and the browser-injected Web Serial application path from profile or direct setup through preflight, the explicit recording boundary, stop, re-import, durable reopen, replay, annotation, bundle export, and production receiver verification. Include decoder mismatch, no probe leakage, active-capture ownership, unconfirmed probe shutdown, sequence gaps, zero-length datagrams, and corrupt serial-length resynchronization in automated coverage. Treat the injected serial gate as application-path evidence, not physical hardware certification.
- For integrity changes, add a failure round trip through capture finalization, JSON serialization, replay parsing, operator-authored half-open range projection, bundle generation, and production receiver verification. Cover both a UDP and serial path when the contract affects both.

## Contribution workflow
Expand Down
7 changes: 4 additions & 3 deletions DECODER_PACKS.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ The current application ships two packs:
1. Open **Live capture**.
2. Choose a bundled pack under **Decoder pack**, or select **Load pack** and choose a local `.nldecoder` or `.json` file.
3. Wait for the loaded-pack notice. NarrowsLink validates the file shape, canonical SHA-256 identity, supported runtime, schema compatibility, and every bundled fixture before making the pack active.
4. Configure UDP or serial and start capture. The selected pack is locked for that capture.
5. Stop and save. The version 2 `.nlsession` embeds the exact pack and records its pack, schema, runtime, and revision identities.
6. Export an `.nlb` with **Decoder schema** included. The production receiver revalidates the embedded pack and reproduces decoded rows from the selected raw records.
4. Configure UDP or serial, run preflight with known traffic, and confirm that the selected pack produces the expected valid frames and message families. The pack is locked once preflight begins.
5. Select **Start recording**. UDP replaces the discarded probe with a new capture identity; serial resets framing on the already selected port so only subsequent reads enter evidence.
6. Stop and save. The version 2 `.nlsession` embeds the exact pack and records its pack, schema, runtime, and revision identities.
7. Export an `.nlb` with **Decoder schema** included. The production receiver revalidates the embedded pack and reproduces decoded rows from the selected raw records.

If pack validation or a fixture fails, capture does not start with that pack. Existing raw session records are never rewritten to fit a replacement decoder.

Expand Down
Loading