Skip to content

Font plan sends unproven CSS families to Google Fonts #1102

Description

@chubes4

Problem

FontMaterializationPlanBuilder::fromWebFontSources() merges every parsed CSS font-family into a google_fonts plan. It then emits one Google CSS2 request containing those families, even when only a subset came from a Google <link> or @import.

A three-route acceptance artifact with one declared Google family (Poppins) produced a request containing 23 unrelated system/custom tokens, including %2309152B, Consolas, Helvetica Neue, Wix-generated names, and Japanese メイリオ. Google returned HTTP 400, and downstream transactional materialization rolled back.

The source document metadata correctly retained only:

https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700;800&display=swap

The generated materialization request incorrectly included all parsed CSS usage.

Root cause

fromWebFontSources() combines provider-backed usage with fontUsageFromCssDeclarations() and inline-body usage, then passes that entire set to googleFonts(). CSS usage proves a desired family, not that Google hosts it.

Expected contract

  • Google materialization requests contain only families proven by supported Google stylesheet links/imports.
  • CSS-only system/custom families may remain typography roles or unresolved diagnostics, but are not synthesized into Google URLs.
  • A mixed fixture proves the emitted URL keeps the declared Google family and excludes colors, system fonts, and custom-hosted names.

Acceptance evidence

The failure is deterministic: the malformed stylesheet response had 6,322 bytes under the 262,144-byte cap but returned a non-200 response, producing stylesheet_fetch_failed.

AI assistance

GPT-5.6-sol via OpenCode traced the compiled plan and materialization receipt, identified the provider-provenance conflation, and drafted this report. Chris Huber reviewed and remains responsible for the issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions