HTTP Caching
============

This specification defines the expected HTTP caching behavior for all wilco
bridges and implementations. Implementations **must** follow the requirements
marked with *must*, *must not*, *should*, and *should not* (per :rfc:`2119`).

Overview
--------

wilco serves several categories of content, each with different caching
requirements. Aggressive caching of static assets is critical for performance
— without it, every page navigation re-fetches JavaScript loaders and component
bundles, causing visible "Loading component..." placeholders on each click.

Asset Categories
----------------

Component Bundles
^^^^^^^^^^^^^^^^^

**URL pattern**: ``/api/bundles/{name}.js``

Component bundles **must** return::

    Cache-Control: public, max-age=31536000, immutable

Bundles are content-addressed: the loader appends a hash query parameter
(e.g., ``?v=abc123``) for cache busting when content changes. This makes
immutable caching safe — a changed bundle gets a new URL.

Wilco Static Assets
^^^^^^^^^^^^^^^^^^^

**URL pattern**: ``/wilco-static/wilco/loader.js``, ``/wilco-static/wilco/live-loader.js``

Wilco static assets **must** return::

    Cache-Control: public, max-age=31536000, immutable

These files are versioned with the wilco package itself. When the package is
upgraded, the file content changes and the HTML references are updated by the
new version, effectively busting the cache.

Application Static Assets
^^^^^^^^^^^^^^^^^^^^^^^^^

**URL pattern**: ``/static/`` (CSS, fonts, favicon, etc.)

Application static assets **should** return appropriate cache headers with at
least::

    Cache-Control: public, max-age=3600

Implementations may use longer durations with cache-busting strategies (hashed
filenames, query parameters).

Media Files
^^^^^^^^^^^

**URL pattern**: ``/media/`` (user uploads, product images, etc.)

Media files **should** return::

    Cache-Control: public, max-age=86400

or use ``ETag``-based validation caching. Media content changes infrequently
but is not versioned, so a moderate ``max-age`` balances performance with
freshness.

HTML Pages
^^^^^^^^^^

HTML pages **must not** be cached with long ``max-age`` values. They **should**
use ``no-cache`` or a short ``max-age`` to ensure the browser always receives
fresh content with up-to-date component references.

API Metadata
^^^^^^^^^^^^

**URL pattern**: ``/api/bundles/{name}/metadata``

API metadata responses **should not** be cached with long ``max-age`` values.
Component metadata may change during development as schemas evolve.

Summary Table
-------------

.. list-table::
   :widths: 30 40 30
   :header-rows: 1

   * - Asset Type
     - Cache-Control
     - Requirement Level
   * - Component bundles (``.js``)
     - ``public, max-age=31536000, immutable``
     - **must**
   * - Wilco static (``loader.js``)
     - ``public, max-age=31536000, immutable``
     - **must**
   * - App static (CSS, fonts)
     - ``public, max-age=3600`` (minimum)
     - **should**
   * - Media files (images)
     - ``public, max-age=86400``
     - **should**
   * - HTML pages
     - ``no-cache`` or short ``max-age``
     - **must not** cache long
   * - API metadata
     - no long ``max-age``
     - **should not** cache long
   * - Pre-built bundles (static)
     - ``public, max-age=31536000, immutable``
     - **must**
   * - Build manifest (``manifest.json``)
     - no long ``max-age``
     - **should not** cache long

Static Mode (Pre-built Bundles)
-------------------------------

When components are pre-compiled with ``wilco build``, bundles are served as
static files instead of through the API. This changes the URL pattern but not
the caching requirements:

**URL pattern**: ``/static/wilco/bundles/{name}.{hash}.js``

Pre-built bundles **must** be served with::

    Cache-Control: public, max-age=31536000, immutable

This is safe because filenames include a content hash. When a component changes,
the build produces a new filename, effectively busting the cache.

Static file servers (WhiteNoise, nginx, CDN) **should** be configured to serve
these files with immutable caching. WhiteNoise does this automatically for
hashed filenames.

The ``manifest.json`` file **should not** be cached with long ``max-age``
values, as it changes with each build.

Implementation Notes
--------------------

The ``CACHE_CONTROL_IMMUTABLE`` constant is defined in
``wilco.bridges.base`` and **should** be reused by all implementations
for component bundles and wilco static assets::

    from wilco.bridges.base import CACHE_CONTROL_IMMUTABLE
    # Value: "public, max-age=31536000, immutable"
