// contributing
Contribute to a signer solution or the shared spec.
nSealr is a multi-repo program. Pick the area you care about,
read its README.md, and open an issue or PR.
Everything else hangs off the contracts in
nSealr/specs.
Where each kind of work lives
- Protocol & specs —
nSealr/specs. Improve a contract, add invalid vectors, document a corner case in event canonicalization or QR framing. Everything else inherits from here. - Companion (CLI, SDK, extension, app, service) —
nSealr/companion. Add a transport, improve verification, polish the CLI. TypeScript monorepo with shared validation logic. - Raspberry/Pi QR vault —
nSealr/raspberry. Python package + CLI. Air-gapped, RAM-only, SeedSigner-style. Hardware adapters welcome. - ESP32 firmware (both lines) —
nSealr/esp32. C / C++ on ESP-IDF v5+. Real signing stays disabled until hardening gates pass. - Smartcard —
nSealr/smartcard. Python APDU codec + simulator. Future JavaCard applet work. - Hardware —
nSealr/hardware. BOM, KiCad files, enclosures, provisioning jigs. - Research / lab —
nSealr/lab. Threat modelling, status tracking, source-backed notes. Lower bar than code repos.
Ground rules
These are tied to specific behaviors and exist for specific reasons.
- No production security claim before independent test evidence.
Why: Words follow vectors. Until the contract has shipped fixtures and an independent run, claims stay scoped to development evidence.
- Shared features behave the same across signer families.
Why: Parity groups in nSealr/specs are the source of truth. Diverging on a shared contract is a bug, not a feature.
- Display-less smartcards do not provide trusted event review by themselves.
Why: A card without a screen cannot bind a review it cannot show. external-review-acknowledgement-v0 covers the gap.
- TROPIC01 is not assumed to directly sign Nostr/BIP-340 until proven.
Why: The default research path is host-MCU signing; the secure element wraps key material and hardens PIN attempts.
- signing_disabled stays the default on every prototype firmware.
Why: Real signing turns on only after secure-boot / flash-encryption / debug-lock / provisioning / recovery gates pass independently.
- Public surface respects "same-behavior-when-present" wording.
Why: A user reading two signer pages must come away with the same understanding of what a shared contract does.
Dev setup
- Clone the repo for the area you want to work on.
- Run
make setup(sets up pinned tool versions; Python venv where applicable; Node 22 + pnpm for TypeScript repos). - Run
make cion a clean checkout. If this fails before you touch anything, file an issue. - Make your change. Re-run
make ci. - Open a PR. CI mirrors
make ci.
PR conventions
- One change per PR. If you find yourself splitting commits in your head, split the PR.
- Conventional-style commit subjects: feat:, fix:, docs:, test:, chore:, refactor:, build:, ci:.
- Link the spec section or contract_id the change touches (when applicable).
- Update conformance vectors in nSealr/specs in the same PR if behavior changes.
- Make make ci pass locally before pushing. CI mirrors it.
- No skip-hooks, no --force-push on main, no rewriting of merged history.
First issues
Each repo carries a good first issue label. Documentation
fixes — typo, broken link, missing cross-reference, an explanation that
should be more obvious — are always welcome and are a good way to learn
the contract vocabulary before touching firmware.
Disclosure
Security issues belong in a private GitHub security advisory on the relevant repo. nSealr does not yet make a production security claim, so most issues during this phase are functional / contract bugs — but security reports are still welcome and triaged with priority.