# feat: compute and chart IPv6 MAAD · PR \#110 · flambo/atlantis

[View on GitCafe](https://git.cafe/flambo/atlantis/pull/110)

Repository: [flambo/atlantis](https://git.cafe/flambo/atlantis)

Visibility: public

State: merged

Source repository: flambo/atlantis

Source branch: maad/04-ipv6

Target branch: maad/03-pin-bump

Head commit: ca9b0274e7cae2c271b7495b949768eca9a303b0

[Discussion and reviews](https://git.cafe/flambo/atlantis/pull/110)

[Commits](https://git.cafe/flambo/atlantis/pull/110/commits?format=markdown)

[Files changed](https://git.cafe/flambo/atlantis/pull/110/diffs?format=markdown)

## Description

---

> [!NOTE]
> 🤖 **Claude Opus 5.5 on behalf of Oliver**

## ELI5

Runs the MAAD address-structure analysis on IPv6 traffic too, not only IPv4, and adds an IPv4/IPv6 switch to the dashboard spectrum card and the file detail page.

## Setup

This PR bumps the product contract: both family MAAD configs are part of the pipeline identity. The pipeline rejects an existing product database, so build a fresh one.

1. Build the nfdump fork (`./vendor/scripts/compile-nfdump.sh`).
2. Choose an input window that contains IPv6 flows. Any nfcapd day from a source that carries IPv6 works. To check, run `target/nfdump/libexec/nfdump -r <file> 'ipv6' -c 5` and confirm it prints flows.
3. Build a new product for one day:
   ```bash
   ./scripts/netflow-db.sh pipeline --dataset <id> --start-date <day> --end-date <day> \
     --database-path data/<id>-ipv6/netflow.sqlite --nfdump target/nfdump/libexec/nfdump
   ```
   Then point the dashboard at that database.
4. CLI-only check without captures: `./scripts/netflow-db.sh maad --ipv6 tools/netflow-db/tests/fixtures/maad-conformance/ipv6-mixed/input.txt`.

## Flows to exercise

- **Pipeline output.** `address_structure_stats` has `ip_version = 6` rows alongside the v4 rows, with prefix lengths /23–/64. `verify --require-maad-data` passes, and fails when v6 traffic exists but v6 MAAD rows are missing.
- **Dashboard.** On `/datasets/<id>`, pick IPv6 on the spectrum card:
  - The URL gains `ipVersion=6` and the card refetches.
  - Reload keeps IPv6.
  - Reset view returns to IPv4, which removes the param.
- **Drilldown.** At 5-minute grouping, click any dashboard chart. The file page opens with `ipVersion=6`, and its family switch shows IPv6.
- **File page.** Reload keeps the family, and **Next File** keeps it too. Switching the family replaces the URL (no new history entry) and refetches MAAD.
- **Validation.** `?ipVersion=5` on MAAD API routes or the file page returns 400. On the dashboard, the search-param schema rejects it and falls back to IPv4.
- **Compare.** `compare` against an older reference with no IPv6 rows now **fails** with `unexpected_candidate_only_rows`. Compare IPv6-era products only with IPv6-era references.

## Decisions and edge cases

- IP family is a URL search param (`ipVersion`, `4` or `6`, default `4`, left out of the URL when `4`). Every dashboard→file drilldown and the Next File link carry it.
- Next File is now a link instead of a GET form. The form dropped every query param (`dataset`, `direction`, `ipVersion`), because GET submission replaces the action's query string.
- `compare` has no exemption for a missing IP family. An earlier revision accepted candidate-only rows whenever the reference lacked that family, which also let unrelated-source rows through. That was removed as greenfield (no compat code).
- IPv6 uses upstream's /23–/64 range, and the nearly-full test uses `128 − pl`. IPv4 output is unchanged. The two families are separate series, not comparable points. On anonymized internal v6 sources the structure below ~/40 mostly reflects the anonymizer; that labeling question is out of scope.

## Verification

- Automated: `bun run format`, `bun run lint`, `bun run typecheck`, `bun run test:db` (v6 goldens, compare rejection tests), `bun run test:web`, `bun run test:e2e` (new `maad-ip-version.spec.ts` covers IPv6 selection → reload → drilldown → reload → next file).
- Manual, still needed: a real-capture product build with IPv6 traffic (steps above), then a visual check of the IPv6 spectrum and the file-page charts.

---
Made by Claude Opus 5.5 (with Opus 5.5 subagents) via Claude Code.

