Drop cached dinner responses and keep link tokens out of names (PR #97 review F1, F2)
CI / ci (push) Successful in 2m37s
CI / ci (pull_request) Successful in 2m40s

F1: bump the service worker cache version to v2 so activate deletes the
v1 API cache, whose dinner responses still carried the pasted recipe_url
and could be served offline.

F2: nameFromURL now drops words holding a digit and ends the name at the
first credential word (token, access, secret, ...), so a token in the
link's last path segment never reaches the public dinner name.
/recipes/beef-stew is still "Beef stew".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-06 20:45:37 -04:00
co-authored by Claude Opus 5.5
parent c15c8ec284
commit 903a332375
7 changed files with 77 additions and 9 deletions
+30
View File
@@ -266,6 +266,36 @@ func TestDinnerResponsesHideRecipeURL(t *testing.T) {
}
}
// TestDinnerResponsesHideTokenInLinkPath: a personal token can sit in the
// link's last path segment, which names the dinner, so the name stops before
// it and neither the create response nor a later list read shows it.
func TestDinnerResponsesHideTokenInLinkPath(t *testing.T) {
t.Parallel()
router, _ := newDinnersRouter(t)
const link = "https://c.example/recipes/stew-access_token-personaltokenabc123"
rec, body := callDinners(t, router, http.MethodPost, dinnersPath, `{"recipe_url":"`+link+`"}`)
if rec.Code != http.StatusCreated {
t.Fatalf("status = %d, want 201: %s", rec.Code, rec.Body)
}
if body["name"] != "Stew" {
t.Errorf("name = %v, want Stew", body["name"])
}
created := rec.Body.String()
rec, _ = callDinners(t, router, http.MethodGet, dinnersPath+"?status=regular", "")
if rec.Code != http.StatusOK {
t.Fatalf("GET status=regular = %d: %s", rec.Code, rec.Body)
}
for _, resp := range []struct{ name, body string }{{"create", created}, {"list", rec.Body.String()}} {
lower := strings.ToLower(resp.body)
for _, secret := range []string{"personaltokenabc123", "abc123", "access", "token"} {
if strings.Contains(lower, secret) {
t.Errorf("%s response contains %q: %s", resp.name, secret, resp.body)
}
}
}
}
func TestCreateDinnerDuplicate(t *testing.T) {
t.Parallel()
router, st := newDinnersRouter(t)