Skip to content

feat: selectable and searchable only-to-customer (OTC) field - #151

Merged
digizeph merged 2 commits into
mainfrom
feat/only-to-customer
Aug 17, 2026
Merged

feat: selectable and searchable only-to-customer (OTC) field#151
digizeph merged 2 commits into
mainfrom
feat/only-to-customer

Conversation

@digizeph

Copy link
Copy Markdown
Member

Summary

  • Makes the RFC 9234 only-to-customer (OTC) attribute a first-class display field in monocle parse, monocle search, and monocle rib, on top of the existing --otc filter from feat: add bgpkit-parser v0.19 extended filters, remove unused deps #148.
  • Renames the user-facing naming from otc to only-to-customer consistently (CLI flag, --fields value, server DTO), keeping --otc as a CLI alias.
  • Adds a runnable example with real Route Views data proving value / * presence / !* absence filtering works end to end.

Motivation

Monocle could filter by OTC but could not select it for display (--fields otc was rejected, and monocle rib's local store dropped the attribute entirely). One Route Views updates file alone carries 17k+ real OTC-tagged elements (peer AS37100 tagging AS12654 announcements), so this is useful for route-leak and RFC 9234 role analysis.

Changes

  • src/bin/commands/elem_format.rs: only-to-customer added to AVAILABLE_FIELDS with value and JSON match arms; custom JSON projection emits the only_to_customer key to match native BgpElem serde.
  • src/lens/parse/mod.rs: ParseFilters field otc -> only_to_customer; CLI flag --only-to-customer (visible alias --otc); the bgpkit-parser filter key stays otc.
  • src/server/search.rs: SSE SearchStreamFilters field otc -> only_to_customer for consistent snake_case wire naming.
  • src/database/session/rib_store.rs: persist OTC in StoredRibEntry / StoredRibUpdate and the ribs / updates SQLite tables.
  • src/bin/commands/rib.rs: only-to-customer default field plus JSON / PSV / table / markdown arms.
  • examples/only_to_customer.rs + examples/README.md: new example and CLI usage docs.
  • CHANGELOG.md: entries for the above; drops stale v0.19 parser version references under Unreleased (monocle is on parser 0.20.0).

Test Plan

  • cargo fmt -- --check
  • cargo clippy --all-features -- -D warnings
  • cargo test --features cli (elem_format 7/7, extended filters 3/3, rib_store 2/2)
  • Live CLI on real Route Views updates: --only-to-customer 6777 -> 1098 hits, * -> 17264, !* -> 167764
  • --fields timestamp,prefix,only-to-customer JSON emits only_to_customer key
  • cargo run --example only_to_customer --features lib

Notes for Reviewers

  • bgpkit-parser is pinned at 0.20.0 (latest on crates.io) and already fully supports OTC (Filter::OnlyToCustomer, AttributeValue::OnlyToCustomer); no parser change needed.
  • otc survives only as the internal bgpkit-parser filter key and the CLI alias; not as the primary user-facing name.
  • Pre-existing, out of scope: clippy --all-targets flags items_after_test_module in bin/commands/search.rs and a test unwrap in database/core/connection.rs; these are outside the documented CI gate (clippy --all-features -D warnings).

- parse/search: the --only-to-customer filter (alias --otc) is now joined by
  --fields only-to-customer display support in JSON, table, PSV, and markdown
  formats; the JSON key is only_to_customer, matching native BgpElem serde.
- rib: persist the OTC attribute in StoredRibEntry and StoredRibUpdate plus the
  ribs and updates SQLite tables, and expose it as a default output field.
- server: rename the SSE SearchStreamFilters field from otc to
  only_to_customer for consistent snake_case wire naming.
- examples: add only_to_customer example demonstrating value ('*' presence and
  '!*' absence) filters on real Route Views data.
- changelog: drop stale v0.19 parser version references under Unreleased.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds first-class only-to-customer filtering, display, and RIB persistence.

Changes:

  • Renames OTC interfaces to only-to-customer.
  • Adds OTC output formatting and RIB storage.
  • Adds documentation and a runnable Route Views example.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/server/search.rs Renames the SSE filter field.
src/lens/parse/mod.rs Renames and maps the OTC parser filter.
src/database/session/rib_store.rs Persists OTC values in RIB tables.
src/bin/commands/rib.rs Adds OTC to RIB output.
src/bin/commands/elem_format.rs Adds OTC field formatting and tests.
examples/README.md Documents OTC usage.
examples/only_to_customer.rs Demonstrates OTC filtering.
CHANGELOG.md Records the feature.
Cargo.toml Registers the new example.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/server/search.rs
// --- bgpkit-parser extended element filters ---
#[serde(default)]
pub otc: Option<String>,
pub only_to_customer: Option<String>,
Comment on lines +251 to +252
origin_asns TEXT,
only_to_customer INTEGER
Comment thread examples/README.md
Comment on lines +63 to +64
# Select the attribute as an output column (JSON key: only_to_customer)
monocle parse <mrt-file> --fields timestamp,prefix,only-to-customer
origin_asns: elem
.origin_asns
.map(|asns| asns.into_iter().map(|asn| asn.to_u32()).collect::<Vec<_>>()),
only_to_customer: elem.only_to_customer.map(|asn| asn.to_u32()),
- remote search: forward --only-to-customer to the server via the
  RemoteSearchFilters wire DTO (search_remote.rs and the
  run_remote_search_wrapper conversion in search.rs), with a wire-JSON test.
- rib sqlite: auto-migrate databases created before the only_to_customer column
  existed by adding it via PRAGMA table_info + ALTER TABLE ADD COLUMN when
  opening without reset; regression test covers both ribs and updates tables.
- rib store tests: use a non-NULL OTC value and assert it survives BgpElem
  conversion and both SQLite inserts instead of only counting rows.
- docs: align README available-fields list with only-to-customer and clarify
  the JSON/PSV key; CHANGELOG updated.
@digizeph

Copy link
Copy Markdown
Member Author

Addressed all 4 review points in commit b3c1e3c (CI: build job green):

  1. Remote search drops the OTC filterRemoteSearchFilters now carries only_to_customer (search_remote.rs) and run_remote_search_wrapper copies filters.parse_filters.only_to_customer into the wire DTO (search.rs). Added test_remote_filters_serialize_only_to_customer covering the wire JSON.

  2. RIB SQLite schema migrationRibSqliteStore::initialize now calls ensure_column (PRAGMA table_info + ALTER TABLE ... ADD COLUMN only_to_customer INTEGER) on both ribs and updates when opening without reset. New test_sqlite_store_migrates_old_schema recreates the pre-column schema and verifies inserts succeed with values persisted.

  3. README inconsistencies — the parse --fields list now includes only-to-customer (and the previously omitted path_id/origin_asns), and the output-field table row clarifies the CLI selector vs the only_to_customer JSON/PSV key.

  4. Tests with no real OTC valuetest_elem() now sets only_to_customer: Some(64497); test_rib_state_store_round_trip asserts the value survives conversion, and test_sqlite_store_two_tables asserts both SQLite inserts persist it instead of NULL.

@digizeph
digizeph merged commit 8284997 into main Aug 17, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants