docs: roadmap index + custom-14a-command plans + backfill plan docs

- Add docs/plans/README.md as the roadmap index cataloguing all design/plan docs.
- Add the custom ISO14443-A command handling design + plan (L3 NTAG I2C
  SECTOR_SELECT / cross-sector reads + native auth; L4 static APDUs + WTX relay),
  produced from a multi-agent design workflow.
- Backfill previously-uncommitted plan docs (trace-formatter, ndef-trace-decode,
  live-sniff, firmware-upstream-rebase, 14a-live-trace) and NTAG5_SECURITY.md.
- Sync CLAUDE.md package structure with the committed transponder models.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
michael
2026-07-05 12:58:48 -07:00
parent a24f0f803f
commit 615d4a6115
12 changed files with 4673 additions and 0 deletions

View File

@@ -0,0 +1,131 @@
# Firmware Upstream Rebase Plan (2026-07-03)
Rebase the `firmware/` submodule (fork `dangerous-tac0s/proxmark3-pm3py`)
onto current RRG `upstream/master` **without losing our sim / sniff /
inventory patch**. Backed by a non-destructive dry-run (worktree + merge-tree).
## Current state (measured)
- **merge-base:** `c7086c227` (2026-02-20) — where we branched.
- **our patch:** 33 commits on top of merge-base (main == `35db99fa5`).
- **upstream ahead:** 1049 commits (tip `87388b389`, 2026-07-03) — ~4.5 months.
- Firmware is on `main`; ALM branch already scrapped.
## Dry-run findings — the conflict surface is small and concentrated
A **squash-then-rebase** (all 33 commits applied as one combined diff, per
`git merge-tree`) conflicts in **exactly 3 files**; everything else
auto-merges or is untouched:
| File | Verdict | ours vs upstream (lines) |
|------|---------|--------------------------|
| `armsrc/iso15693.c` | ⚠️ real work — 13 hunks | +599/146 vs +523/214 |
| `client/src/cmdhf15.c` | ⚠️ moderate | +372/7 vs +544/45 |
| `include/pm3_cmd.h` | ✅ trivial (textual re-append) | +21/0 vs +94/113 |
| `appmain.c`, `iclass.c`, `iso15693.h`, `iso15.h`, `Makefile` | ✅ auto-merge | — |
| `sim_table.c/h`, `sim_crypto.c/h`, `Standalone/hf_15sniff.c`, `Standalone/hf_unisniff.c` | ✅ upstream never touched | — |
A **sequential** rebase (replay 33 commits) is worse: it conflicts on
commit #1 and, because **24 of the 33 commits touch `iso15693.c`**, it
re-conflicts that file many times. → **Squash first, resolve once.**
### CMD-ID collision check — CLEAR ✅
All six IDs we added are free in upstream (upstream's `0x033x` block only
reaches `CSETUID_V2 0x0333`; `0x095x` is empty):
```
0x0336 CMD_HF_ISO15693_SIM_TRACE 0x0950 CMD_SIM_TABLE_UPLOAD
0x0337 CMD_HF_SNIFF_STREAM 0x0951 CMD_SIM_TABLE_CLEAR
0x0338 CMD_HF_SNIFF_STATUS 0x0952 CMD_SIM_TABLE_UPDATE
```
So `pm3_cmd.h` is a pure textual re-append (drop our `#define`s at a clean
spot in the churned region), **not** a semantic collision.
### `iso15693.c` hunk map (13 hunks, 2 functions)
- **15693 sniff loop (~L15981853):** our streaming-sniff feature (ring
buffer, button-toggle, idle flush) vs upstream sniff edits. Biggest hunk
~53 lines (our idle/flush block) — mostly *keep-ours-add-both*.
- **SimTag / sim loop (~L24753372):** our sim handler (table lookup,
access control, random UID, periodic field report) + the `CheckCrc15`
4-byte-frame fix vs upstream. ~10 hunks: three large (span 3643, our
inserted blocks → take-ours), the rest small (≤16) needing genuine
line-level reconciliation — notably **our `CheckCrc15` vs upstream's
`CalculateCrc15`** at ~L2591 (keep ours; it fixes 4-byte frames).
Effort estimate: **~half a day** of focused merge work, dominated by
`iso15693.c`; `cmdhf15.c` moderate; `pm3_cmd.h` ~10 min.
## Strategy: squash-to-one → rebase (single 3-file resolution) → validate → re-split
Resolve conflicts exactly once (matching the merge-tree preview), validate
the build, then restore clean per-file commits for cheap future rebases
(the design-doc "atomic single-file commit" model).
### Procedure (all in an isolated worktree — real checkout never moves)
```bash
FW=/home/work/pm3py/firmware
WT=<scratchpad>/fw-rebase
git -C $FW fetch upstream master
git -C $FW worktree add -b rebase-wip "$WT" 35db99fa5
cd "$WT"
# 1. collapse 33 commits into one diff on our base (no upstream yet → no conflicts)
MB=$(git merge-base HEAD upstream/master)
git reset --soft "$MB"
git commit -m "pm3py sim+sniff+inventory patch (squashed for rebase)"
# 2. rebase the single commit → conflicts in the 3 known files, resolved once
git rebase upstream/master # resolve iso15693.c, cmdhf15.c, pm3_cmd.h
# ... resolve, git add, git rebase --continue
# 3. re-split into logical per-file commits (soft reset + staged adds)
git reset --soft upstream/master
# commit A: sim_table.c/h + sim_crypto.c/h (new modules)
# commit B: pm3_cmd.h + iso15.h + iso15693.h (IDs + struct fields)
# commit C: appmain.c (dispatch)
# commit D: iso15693.c (sim + sniff + inventory)
# commit E: cmdhf15.c (client reader/inventory)
# commit F: Makefile + Standalone/* (build glue)
```
### Validation (all local per build-workflow — ARM builds here, not the Mac)
1. `make -C "$WT" clean && make -C "$WT" PLATFORM=PM3GENERIC` — ARM compiles.
2. `make -C "$WT" client` — validates `cmdhf15.c`.
3. `python -m pytest tests/` in pm3py — sim tests are transport-mocked, so
they stay green; confirms no Python-side regression.
4. **Hardware smoke test (user, has PM3):** flash, then `hf 15` scan +
15693 sim + a phone read (the known-good sim path). This is the only
check the dry-run can't cover — upstream may have altered 15693 wire
behavior around our insertions.
### Landing
- Show resolved `iso15693.c` diff for review **before** anything touches
`main`.
- Fast-forward `firmware` main to `rebase-wip`, bump the submodule pointer
in a pm3py commit, force-push the fork (`--force-with-lease`).
- Remove the worktree (`git worktree remove`, no `--force`).
## Risks & rollback
- **Semantic drift in `iso15693.c`:** upstream may have changed shared
helpers our sim path calls. Compile catches signature breaks; behavior
needs the hardware smoke test.
- **Rollback:** old main is preserved. Recovery ref for pre-rebase tip:
`35db99fa5`. Nothing is force-pushed until build + review pass.
- **Safety Net:** `branch -D`, `rm -rf`, `git clean -f`, `worktree remove
--force` are blocked — use `-d`/plain `rm`/`worktree remove` (no force),
or hand force-ops to the user.
## Go-forward (close the gap that let us drift 1049 commits)
From the earlier maintenance discussion, still unbuilt:
- `pm3py/firmware_compat.py` — pin `UPSTREAM_TESTED_COMMIT` = `87388b389`.
- A **real** rebase-check CI (the existing `firmware/.github/workflows/
rebase.yml` is upstream's Changelog Reminder, not ours).
```