Flatten server hierarchy into groups, add notes and tags#164
Open
passcod wants to merge 8 commits into
Open
Conversation
The server tree (parent_server_id self-reference) is replaced by a first-class `server_groups` table; each server has a nullable `group_id` pointing at its group. Both servers and groups gain freeform `notes` text and a string→string `tags` map (new `commons_types::server::TagMap`). Incidents rekey from `server_id` to `server_group_id`. NewEvent::save records the issue normally for ungrouped servers but skips the incident flow until a group is assigned; Server::assign_to_group then runs re_evaluate_incident_membership across the server's open issues so the catch-up promotion happens automatically. central_public_key is removed from CanopyTicket (it only fed the old parent-link logic).
Adds the private-server `server_groups` module (CRUD + search) and a public-server `GET /tags` endpoint returning the merged server+group tags for the authenticated device. Drops `list_roots`/`search_parent` and the parent-server-derived child fan-out from the private servers handlers; `get_detail` now surfaces the server's group and siblings; `statuses` exposes `group_details` (replacing `server_details`) and buckets groups in `server_grouped_ids` by their highest-ranked member. Tests updated for the new shapes: parent_server_id / search_parent cases become group_id / notes / tags cases, the incidents test seeds a group, and new tests cover ungrouped-then-grouped issue promotion plus the public tags endpoint will follow in a separate change.
Helpers that produce a server for incident tests now also create a group and link the server to it, so the event flow can promote issues to incidents. Queries against incidents.server_id are rewritten to join via the server's group_id. Updated tests track the API rename of statuses.server_details → group_details and the shape change from CentralServerCard → ServerGroupCard. The nil-server test now verifies events on the meta server *don't* open incidents, since the nil server is intentionally ungrouped.
…d status page The /servers page now opens to a flat list of groups with a sibling "Ungrouped" tab for servers not yet placed in a group. New routes /groups/:id and /groups/:id/edit show and mutate the group's name, notes, and tag map (via a new key-value TagsEditor). ServerEdit gains a group picker, a notes textarea, and the same tags editor; the old parent-server autocomplete is gone. The status page (/) now renders one card per group: each card shows the group name, a row of StatusDots — one per member server — and the version pulled from the most-recently-pushing member. Buckets along the page are keyed by the highest rank of any member. Incidents/issues and the IncidentCard / IssueRow components track the rekey: filter rows now key on server_group_id, the issue list prefixes each row with the group's name via the new ServerNameWithGroup helper, and IncidentDetail/IncidentCard label by the group rather than reassembling a server label. Issue data picks up `server_group_name` (off a new `Server::group_names_by_server_ids` batch lookup) so the row prefix doesn't need an extra round-trip.
…pecs resetSeededTables now wipes server_groups too. New seedServerGroup helper inserts a row with name/notes/tags. seedServer accepts a groupId (string | null) and notes/tags fields; parentServerId is gone. The servers.spec.ts page tests now check the Groups + Ungrouped tabs and reach the seeded group via /groups/<id>. The status.spec.ts test seeds a group per rank and verifies the new card link points at /groups/<id>. groups.spec.ts is new: it covers detail (name, notes, tags, members), the empty-group banner, and the edit-form prefill.
…on path tests/public-server/tags.rs covers the four cases of GET /tags: group-only tags propagate, server tags overlay (winning on key collisions while non-colliding group keys carry through), an ungrouped server returns just its own map, and a device without an attached server gets a 412 (matching the events/* convention). Also fixes two issues found while exercising the e2e suite: - DeleteOutline → DeleteOutlined. The @mui/icons-material package ships the outlined variant under the …Outlined suffix; without the correct import the private-server build.rs's embedded-frontend step couldn't compile and `just test-e2e` silently ran against a stale binary, masking many failures. - Two e2e selectors needed widening: the group-edit Name field is `required` so MUI appends a `*` to the label (regex matches from the start, not the end), and the server-detail h1 now contains `<group> · <server>` so the role matcher scopes by a name regex to skip the surrounding "Canopy" app-bar h1.
Plan delivered: - server_groups + nullable servers.group_id, with notes/tags maps on both, incidents rekeyed to server_group_id, server kind decoupled from hierarchy; - ungrouped servers can record issues but don't open incidents; assigning a group re-evaluates membership and promotes any pending issues retroactively; - new public GET /tags endpoint merging the group's and server's tags; - private API server_groups CRUD + search + statuses.group_details + the Status page bucketed by the highest-ranked group member; - React UI: Groups + Ungrouped tabs, group detail/edit, TagsEditor, ServerNameWithGroup, IncidentDetail/IssueRow rebadged for groups; - Rust + e2e suites green.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
servers.parent_server_idtree with a first-classserver_groupstable; each server has a nullablegroup_id. Incidents rekey fromserver_idtoserver_group_idso the schema matches what code was already enforcing.notestext field and a string→stringtagsjsonb map (newcommons_types::server::TagMap).GET /tagsendpoint returns the merged tags for the calling device's server — the group's map overlaid by the server's, server wins on collision, ungrouped returns just the server's tags./serversopens to a Groups list with a sibling Ungrouped tab, new/groups/:iddetail +/groups/:id/editroutes, a reusableTagsEditor(key/value rows with dedup), and aServerNameWithGrouphelper that prefixes server names in lists/headers withGroup · Server(interpunct). The Status page now renders one card per group, bucketed by the highest-ranked member.CanopyTicket.central_public_keyfield and its parent-lookup inupsert_from_ticket; imported servers start ungrouped and operators assign a group from the admin UI.