Skip to content

Add synthetic canopy: tags to the /tags endpoint#231

Open
passcod wants to merge 2 commits into
mainfrom
tags-synthetic-server-attrs
Open

Add synthetic canopy: tags to the /tags endpoint#231
passcod wants to merge 2 commits into
mainfrom
tags-synthetic-server-attrs

Conversation

@passcod

@passcod passcod commented Jun 18, 2026

Copy link
Copy Markdown
Member

🤖 The device-facing /tags endpoint now injects read-only synthetic tags describing the calling server, on top of its merged server+group tags. They live under a reserved canopy: namespace:

  • canopy:kind — the server's kind (always present)
  • canopy:rank — the server's rank, only when one is set
  • canopy:group-id — the server's group id, only when grouped
  • canopy:group-name — the server's group name, only when grouped

To guarantee these can never collide with — or be spoofed by — operator-set tags, the canopy: prefix is reserved: server and server-group tag writes now reject any key under it with 400 Bad Request. The check is enforced centrally in the database model create/update paths, so every write path is covered.

Notes

  • tags_merged_with_group (used by the healthcheck-sample and status endpoints for rule evaluation) is unchanged; the synthetic tags are added by a new Server::tags_for_device used only by /tags.
  • canopy:rank is emitted only when the server has a rank set, mirroring how an unset rank is treated as absent elsewhere rather than defaulted to dev.

Covered by new tests: synthetic tags on the /tags response (grouped + ranked, and the ungrouped/rankless case), plus reserved-prefix rejection across all four server/group create/update paths.

passcod added 2 commits June 19, 2026 00:19
The public /tags endpoint now injects read-only synthetic tags describing
the server, under a reserved "canopy:" namespace:

- canopy:kind       — the server's kind (always present)
- canopy:rank       — the server's rank, when one is set
- canopy:group-id   — the server's group id, when grouped
- canopy:group-name — the server's group name, when grouped

To guarantee these never collide with operator-set tags, the "canopy:"
prefix is reserved: server and server-group tag writes reject any key
under it (400 Bad Request), enforced centrally in the database model
create/update paths.
The committed_spec_matches_generated drift test caught the stale spec
after the /tags handler doc comment changed.
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.

1 participant