diff --git a/internal/web/uploads.go b/internal/web/uploads.go
index f4638f6..8ef6a43 100644
--- a/internal/web/uploads.go
+++ b/internal/web/uploads.go
@@ -273,12 +273,30 @@ func titleFromFilename(name string) string {
// cloudProvider names the cloud service that produced a transcript, or false when it was
// served locally (or by an unknown endpoint). "Local" is config.IsLocalModel: the same
// definition the start-up validation uses, not a second string match here (#52).
+//
+// The endpoint is one alias, except for the two-engine path (ADR-034), which writes
+// " + , reconciled by ". Every alias in it is judged on its own, so a
+// composite of local models is local and one naming a cloud alias names that provider.
func cloudProvider(endpoint string) (string, bool) {
- if endpoint == "" || config.IsLocalModel(endpoint) {
+ if strings.TrimSpace(endpoint) == "" {
return "", false
}
- provider, _, _ := strings.Cut(endpoint, "/")
- return provider, true
+ aliases := []string{}
+ for _, tok := range strings.Fields(endpoint) {
+ if tok = strings.Trim(tok, ","); strings.Contains(tok, "/") {
+ aliases = append(aliases, tok)
+ }
+ }
+ if len(aliases) == 0 {
+ aliases = append(aliases, strings.TrimSpace(endpoint))
+ }
+ for _, a := range aliases {
+ if !config.IsLocalModel(a) {
+ provider, _, _ := strings.Cut(a, "/")
+ return provider, true
+ }
+ }
+ return "", false
}
// hasNote reports whether any phase carries a note. A note is the only warning for a
diff --git a/internal/web/uploads_cloud_note_test.go b/internal/web/uploads_cloud_note_test.go
index f6ebf76..7e68187 100644
--- a/internal/web/uploads_cloud_note_test.go
+++ b/internal/web/uploads_cloud_note_test.go
@@ -53,3 +53,32 @@ func TestUploadStatus_AnEndpointThatOnlyLooksLocalIsStillNamedAsCloud(t *testing
assert.Contains(t, b, "left the homelab")
}
+
+// The two-engine path (ADR-034) writes one composite endpoint string. Every name in it is
+// a local model, so the audio never left the homelab and the note must not say it did.
+func TestUploadStatus_AReconciledAllLocalEndpointCarriesNoCloudNote(t *testing.T) {
+ for _, endpoint := range []string{
+ "iguana/kb-whisper + koala/whisper, reconciled by iguana/gemma4-26b",
+ "iguana/kb-whisper + koala/whisper, reconciled by iguana/gemma4-26b\n",
+ } {
+ t.Run(endpoint, func(t *testing.T) {
+ app, _ := newUploadApp(t, audioOK, 200<<20)
+ id := seedUpload(t, userID, "m", "done", "Synthetic transcript text.")
+ setEndpoint(t, id, endpoint)
+
+ b := body(t, do(t, app, get("/uploads/"+id+"/status")))
+
+ assert.NotContains(t, b, "left the homelab")
+ })
+ }
+}
+
+func TestUploadStatus_AReconciledEndpointNamingACloudEngineStillNamesTheCloudProvider(t *testing.T) {
+ app, _ := newUploadApp(t, audioOK, 200<<20)
+ id := seedUpload(t, userID, "m", "done", "Synthetic transcript text.")
+ setEndpoint(t, id, "iguana/kb-whisper + berget/kb-whisper, reconciled by iguana/gemma4-26b")
+
+ b := body(t, do(t, app, get("/uploads/"+id+"/status")))
+
+ assert.Contains(t, b, "cloud service (berget)")
+}