- @noahtalerman: For the following story:
- https://github.com/fleetdm/fleet/issues/43557
## Summary
- Adds `bundle_identifier` as a top-level field on
`HostSoftwareWithInstaller` struct, which is the response type for all
host software API endpoints (`GET /api/v1/fleet/hosts/{id}/software`,
`GET /api/v1/fleet/device/{token}/software`, etc.)
- The value is sourced directly from `software_titles.bundle_identifier`
via the SQL query, so it is always present even when
`installed_versions` is empty (e.g., software that has never been
installed on a host)
- Falls back to `installed_versions[0].bundle_identifier` if the
title-level value is not available
- The field is retained inside `installed_versions` for full backwards
compatibility
## Changes
### `server/fleet/software_installer.go`
- Added `BundleIdentifier string` field with
`json:"bundle_identifier,omitempty" db:"-"` tag to
`HostSoftwareWithInstaller` struct
### `server/datastore/mysql/software.go`
- Added `TitleBundleIdentifier` field to internal `hostSoftware` struct
mapped to `title_bundle_identifier` DB column
- Added `software_titles.bundle_identifier AS title_bundle_identifier`
to all four SQL query branches:
- Software installers SELECT
- VPP apps SELECT
- In-house apps SELECT
- Available-for-install SELECT (`stmtAvailable`)
- Added `software_titles.bundle_identifier` to GROUP BY clauses for
software installers and VPP apps
- In the return path, populates `BundleIdentifier` from
`TitleBundleIdentifier` (with fallback to first installed version)
### `server/datastore/mysql/software_test.go`
- Added `BundleIdentifier` assertion to both `compareResults` helper
functions (macOS/Linux and iOS/iPadOS test suites)
- Added explicit top-level `BundleIdentifier` assertions in
`testListHostSoftwareWithVPPApps` where the installed version bundle
identifier is already verified
## Example response shape
```json
{
"id": 121,
"name": "Google Chrome.app",
"bundle_identifier": "com.google.Chrome",
"icon_url": null,
"software_package": { ... },
"app_store_app": null,
"source": "apps",
"status": "failed_install",
"installed_versions": [
{
"version": "121.0",
"bundle_identifier": "com.google.Chrome",
...
}
]
}
```
Built for
[ntalerman](https://fleetdm.slack.com/archives/D0AEA6U4SM9/p1774036621198819?thread_ts=1774035719.384099&cid=D0AEA6U4SM9)
by [Kilo for Slack](https://kilo.ai/features/slack-integration)
---------
Co-authored-by: kiloconnect[bot] <240665456+kiloconnect[bot]@users.noreply.github.com>
Co-authored-by: Kilo Code <kilo@kilo.ai>
Co-authored-by: Noah Talerman <47070608+noahtalerman@users.noreply.github.com>
Co-authored-by: jkatz01 <yehonatankatz@gmail.com>