Skip to content

feat: add port forward inventory - #7

Open
Kampe wants to merge 1 commit into
rvben:mainfrom
Kampe:agent/port-forward-inventory
Open

feat: add port forward inventory#7
Kampe wants to merge 1 commit into
rvben:mainfrom
Kampe:agent/port-forward-inventory

Conversation

@Kampe

@Kampe Kampe commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

What

Add read-only unifi port-forwards list and unifi port-forwards show <name-or-id> commands with text, JSON, and schema support.

Why

Port-forward exposure and WAN/interface scoping currently require controller UI inspection. This makes those controls auditable and scriptable.

Safety

The legacy resource is decoded into a narrow typed record. Unknown vendor fields are discarded, and regression fixtures inject secret-like fields and verify they never appear in output.

Checks

  • env -u UNIFI_API_KEY -u UNIFI_HOST make check
  • Live read-only validation against a UniFi controller, including WAN-scoped TCP 32400 forwarding

@rvben

rvben commented Aug 14, 2026

Copy link
Copy Markdown
Owner

This one is in good shape. I confirmed the field mapping against a real record on my controller rather than trusting the mock: I created a disabled port forward, read it back, and deleted it, and every field your struct allowlists came back exactly as you typed it, log included via the serde default. One formatting fix and I will take it.

port-forwards show builds its rows from row.as_object(), and serde_json here is built without preserve_order, so the map is a BTreeMap. The result is alphabetical fields and a literal null for anything absent. On that real record:

destination          192.0.2.10
destination port     32400
enabled              false
external port        32400
id                   <redacted>
interface            wan
logging              false
name                 temp-probe
protocol             tcp
source               any
source port          null

Elsewhere the codebase prints - for absent values in a fixed, meaningful order. networks show in #5 is a good model: an explicit array of label and value pairs. The list output is already fine as it is.

Worth noting for context: the empty result on my controller is honest rather than a dead endpoint. rest/portforward still answers 200 on Network 10.5.67 and there is no v2 replacement, unlike the firewall case in #6.

These four PRs overlap in client.rs and mock_server.rs, so whichever lands first makes the others conflict. That is my sequencing problem more than yours: I am landing #5 first, and if you would rather not chase rebases across three branches, say so and I will resolve the conflicts on merge.

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