Closes#45969
## Summary
The `List certificate templates` API endpoint returned `null` for
certificates because the **API docs documented the wrong query parameter
name**. The docs said `fleet` but the code accepts `fleet_id` (or the
deprecated `team_id`). Customers following the docs used `?fleet=11`,
which was silently ignored, causing the endpoint to default to team 0
(unassigned) -- which typically has no certificates.
- **Docs fix**: Changed the parameter name from `fleet` (string) to
`fleet_id` (integer) in the REST API docs, matching how all other list
endpoints document this parameter.
- **API quality fix**: Initialize the `templates` slice in
`GetCertificateTemplatesByTeamID` so that when no templates exist, the
JSON response returns `"certificates": []` instead of `"certificates":
null`.
## Root cause
In `docs/REST API/rest-api.md`, the "List certificate templates"
endpoint documented the query parameter as `fleet` (string), but the
request struct accepts `fleet_id` or `team_id`:
```go
type listCertificateTemplatesRequest struct {
TeamID uint `query:"team_id,optional" renameto:"fleet_id"`
}
```
When the customer used `?fleet=11` (as documented), the parameter was
unrecognized and silently ignored. The endpoint defaulted to `team_id=0`
(unassigned), which had no certificates. The nil Go slice then
serialized to JSON `null`.
Credit to Andrey Kizimenko for identifying the docs mismatch.
## Changes
- `docs/REST API/rest-api.md` -- Fix parameter name from `fleet`
(string) to `fleet_id` (integer)
- `server/datastore/mysql/certificate_templates.go:174` -- Initialize
slice to avoid `null` in JSON
- `server/datastore/mysql/certificate_templates_test.go:489` -- Add
`require.NotNil` regression test
## Testing
All tests run locally against a real MySQL (Docker) and Redis instance:
| Test suite | Command | Result |
|---|---|---|
| Datastore integration (all certificate tests) | `MYSQL_TEST=1 go test
-run TestCertificates ./server/datastore/mysql/...` | 11 suites, 33
subtests, all PASS |
| Service unit tests | `go test -run
"TestCreateCertificateTemplate\|TestApplyCertificateTemplateSpecs\|..."`
| 4 suites, all PASS |
| Enterprise integration (full HTTP) | `MYSQL_TEST=1 REDIS_TEST=1 go
test -run "TestIntegrationsEnterprise/TestCertificatesSpecs"` | PASS |
| Enterprise integration (team delete) | `MYSQL_TEST=1 REDIS_TEST=1 go
test -run
"TestIntegrationsEnterprise/TestDeleteTeamCertificateTemplates"` | PASS
|
| Static analysis | `go build`, `go vet` | Clean |
Andrey's reproduction confirmed via screenshots:
- `?fleet_id=11` returns certificates correctly
- `?fleet=11` (the documented param) returns `null` -- the bug
- No param returns results when "unassigned" team has certificates
## QA steps
1. Follow the API docs to list certificate templates using
`?fleet_id=<id>`
2. Verify the response contains `"certificates": [...]` with the correct
data
3. Call without `fleet_id` and verify `"certificates": []` (not `null`)
for a team with no templates
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Fixed the "List certificate templates" API documentation with the
correct query parameter name, enabling proper filtering of results.
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45978?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)
<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->