feat(manage): vpn status shows each node's ACL tags #278

Merged
jfraeys merged 3 commits from jfraeys/feat/vpn-status-tags into main 2026-10-18 13:38:30 -04:00
Owner

`manage vpn status` now has a TAGS column (`forced_tags` + `valid_tags`, `-` when none), so after the `tag:ci` rollout (#274) a CI runner shows `tag:ci` (and a VM that joined with the old key shows `tag:web`) without a raw `headscale` command. Node count and other columns unchanged.

Test: `scripts/tests/test-vpn-status.sh` (stubbed Headscale, in lint): forced and valid tags, the dash for no tags without shifting columns, and the count. `test-vpn-revoke.sh` and the manage-bundle test still pass. The on-host copy changes only after `--tags manage_cli`; your Mac picks it up on `git pull`.

The `forced_tags`/`valid_tags` field names are Headscale's JSON; I could not read the live JSON, so the first real `./manage vpn status` is the check: if the TAGS column is empty for a node you know has a tag, paste one node's keys (not values) from `headscale nodes list --output json` and I'll adjust.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Ge5tovcwdEUBtPwUktsZZZ

\`manage vpn status\` now has a TAGS column (\`forced_tags\` + \`valid_tags\`, \`-\` when none), so after the \`tag:ci\` rollout (#274) a CI runner shows \`tag:ci\` (and a VM that joined with the old key shows \`tag:web\`) without a raw \`headscale\` command. Node count and other columns unchanged. Test: \`scripts/tests/test-vpn-status.sh\` (stubbed Headscale, in lint): forced and valid tags, the dash for no tags without shifting columns, and the count. \`test-vpn-revoke.sh\` and the manage-bundle test still pass. The on-host copy changes only after \`--tags manage_cli\`; your Mac picks it up on \`git pull\`. The \`forced_tags\`/\`valid_tags\` field names are Headscale's JSON; I could not read the live JSON, so the first real \`./manage vpn status\` is the check: if the TAGS column is empty for a node you know has a tag, paste one node's keys (not values) from \`headscale nodes list --output json\` and I'll adjust. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01Ge5tovcwdEUBtPwUktsZZZ
feat(manage): vpn status shows each node's ACL tags
Some checks failed
Lint / lint (pull_request) Has started running
Secret scan / scan (pull_request) Has been cancelled
d258f577a0
A CI runner's tag:ci (or a stale tag:web) was not visible, so checking the tag:ci rollout needed a raw
headscale command.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ge5tovcwdEUBtPwUktsZZZ
fix(manage): vpn status reads Headscale 0.29's unified tags field (plus the old two)
Some checks failed
Lint / lint (pull_request) Has started running
Secret scan / scan (pull_request) Has been cancelled
1febdb624e
The first version read only forced_tags/valid_tags; on 0.29.5 every node showed no tags.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ge5tovcwdEUBtPwUktsZZZ
Merge origin/main into jfraeys/feat/vpn-status-tags (lint.yml: keep both new test steps)
All checks were successful
Lint / lint (pull_request) Successful in 3m15s
Secret scan / scan (pull_request) Successful in 15s
26f04b9581
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ge5tovcwdEUBtPwUktsZZZ
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
jfraeys/infra!278
No description provided.