Widget diagnostics: per-intent beacons (keychain slots + relay query)

The single-slot beacon couldn't distinguish small vs medium (last writer
wins). Beacon keychain service now embeds the intent type name so small
and medium never overwrite each other; the relay GET now carries the
intent type + entry state as query params so the access log shows exactly
which widget kind ran makeEntry, when, and with what. Diagnostics screen
shows SMALL and MEDIUM beacons side by side — a missing SMALL beacon
after adding the small widget proves its timeline never reaches the
provider (system-level config resolution failure).
This commit is contained in:
FuelBoard Contributor
2026-08-13 20:13:24 +01:00
parent 335a9751dc
commit 3cf1d5c9af
3 changed files with 50 additions and 23 deletions
+10 -8
View File
@@ -697,15 +697,17 @@ struct FuelStore {
writeKeychain(data: Data(value.utf8), service: service)
}
// Widget diagnostics beacon the widget extension writes its last
// makeEntry state here (keychain survives on free SideStore accounts where
// the app-group container isn't provisioned); the app's Debug section
// reads it to see whether a widget timeline ran and what it produced.
static func saveWidgetDiag(_ json: String) {
saveString(json, service: "widget.diag")
// Widget diagnostics beacons the widget extension writes its last
// makeEntry state PER INTENT TYPE (keychain survives on free SideStore
// accounts where the app-group container isn't provisioned); the app's
// Debug section reads them to see whether each widget kind's timeline
// actually ran and what it produced. Service key embeds the intent type
// so small and medium widgets never overwrite each other.
static func saveWidgetDiag(_ json: String, intentType: String) {
saveString(json, service: "widget.diag.\(intentType)")
}
static func loadWidgetDiag() -> String? {
loadString(service: "widget.diag")
static func loadWidgetDiag(intentType: String) -> String? {
loadString(service: "widget.diag.\(intentType)")
}
}