Skip to content

Streaming cold loads violate progressive-enhancement (no-JS users see skeleton forever); inline script has no nonce #6

Description

@thinkter

Summary

Streaming cold loads violate the progressive-enhancement promise. A no-JS cold load of a route with loading.tsx flushes the skeleton, then delivers the real content as an inline <script> (src/core/render.ts:130-132) — no-JS users see the skeleton forever.

This is also CSP-hostile: the inline script has no nonce support.

Impact

  • Progressive enhancement broken: no-JS users never see the actual page content, only the skeleton
  • CSP: inline scripts without nonces are blocked by any sane Content-Security-Policy, and there is no mechanism to emit/whitelist a nonce

Evidence

  • src/core/render.ts:130-132 — skeleton then inline-<script> content delivery

Suggested decision

The PRD's risk register flagged the no-JS guarantee as the top risk. This is either a scoped exception (and the PRD should say so) or a bug. The project needs to decide:

  • Is streaming content delivery allowed to assume JS?
  • If yes, what's the fallback for no-JS users — render the final content server-side and swap without the skeleton?

Suggested fix

One of:

  1. Stream the real content as HTML chunks (not an inline script), so no-JS users get it
  2. Add nonce support to the inline script and document the JS-required assumption in the PRD
  3. Skip the skeleton on cold load and only render the final content (defer streaming to subsequent navigations)

From the AUDIT.md "Serious concerns" list. Also referenced in the philosophy scorecard as risk (a): "the no-JS guarantee has a hole under streaming with no decision on whether that's a scoped exception or a bug."

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: streamingrenderPipelineStreaming / progressive enhancement under streamsbugSomething isn't workingseverity: seriousSecurity/correctness risk — fix before any real deployment

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions