Withhold unsafe recipe sources from idea job results
CI / ci (push) Successful in 6m10s
CI / ci (pull_request) Successful in 7m2s

Cook from what I have and Quick dinners ideas returned the grounded
recipe's raw source_url and site_name, so a link carrying a token in its
query or userinfo, or a stored name taken from its host, reached the
client in the job response (BASE-01).

dinners.SourceOf is now the one way a fetched recipe's source reaches a
client: the dinner detail and both idea result builders use it. An
idea's source_url and site_name are null when they could leak a secret,
and a source that does not parse fails the job instead of being shown.

Task: c15ed4b5-25ae-43c6-8d36-f4a6dd51e5af

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-09 18:07:21 -04:00
co-authored by Claude Opus 5.5
parent 4b592fdbbb
commit 1eafe812ec
6 changed files with 196 additions and 28 deletions
+15 -2
View File
@@ -147,11 +147,11 @@ func readRecipe(ctx context.Context, q *db.Queries, recipeID string, d *Detail)
return fmt.Errorf("recipe %s: %w", recipeID, err)
}
if !IsManualRecipe(rec.SourceUrl) {
site, err := pageSiteName(rec.SiteName, rec.SourceUrl)
src, err := SourceOf(rec.SiteName, rec.SourceUrl)
if err != nil {
return err
}
d.Source = &Source{SiteName: site, URL: safeSourceURL(rec.SourceUrl)}
d.Source = &src
}
ings, err := q.ListRecipeIngredients(ctx, recipeID)
if err != nil {
@@ -182,6 +182,19 @@ func readRecipe(ctx context.Context, q *db.Queries, recipeID string, d *Detail)
return nil
}
// SourceOf is the Source of a recipe fetched from sourceURL whose stored
// site name is siteName: the name only when the page gave it (see
// pageSiteName) and the link only when it is free of secrets (see
// safeSourceURL). It is the one way a fetched recipe's source reaches a
// client.
func SourceOf(siteName sql.NullString, sourceURL string) (Source, error) {
site, err := pageSiteName(siteName, sourceURL)
if err != nil {
return Source{}, err
}
return Source{SiteName: site, URL: safeSourceURL(sourceURL)}, nil
}
// pageSiteName is the stored site name of a recipe fetched from sourceURL
// when it is one the page gave, else nil. A page that names no site is
// stored under recipes.HostSiteName of the URL it was served from: the