Files
summercms/docs/setup/upgrading.md
Jakub Zych f3e8a984b0 docs(quick-261015-w7f): docs since v0.1.14 and the Upgrading to 0.2 notes
- new setup/upgrading.md: version rule, the two 0.2 boot refusals with
  their fixes, behaviour changes, and what 0.2 adds since 0.1
- architecture module table lists all 28 modules
- WinterCMS map: cache and reorder are provided; rows for field types,
  sanitizing, singletons, API tokens, CORS, Turnstile, menu item types
- configuration keys for CORS profiles, api_docs, auth.cookie, turnstile
- index, setup intro and frontend page link the new topics
2026-10-15 23:24:56 +02:00

74 lines
8.9 KiB
Markdown

---
title: Upgrading
description: Move an application to a newer framework release, what the version numbers promise, and the config to check before you take 0.2.
section: setup
order: 60
---
# Upgrading
An application created by `summer new` builds against a framework checkout next to it; the update script moves that checkout to the newest release tag, reinstalls the `summer` tool and rebuilds the application (see [Updating an application](installation.md#updating-an-application)). An application or plugin that requires a tagged framework version in its `go.mod` moves with the go command instead:
```sh
go get git.golem15.com/golem15/summercms@v0.2.0
go mod tidy
```
Then rebuild, run `migrate` with the new binary and restart it.
## Version numbers
SummerCMS is in the 0.x series, and the version tells you whether to read before you upgrade:
- The minor version (0.1 to 0.2) goes up when an upgrade can refuse a configuration that the previous release accepted, or changes a documented behaviour. Read the section for that version below before you deploy it.
- A patch version (0.2.0 to 0.2.1) is safe to take without reading: it fixes bugs and adds features, and an application that started on the previous patch starts on it too.
Applications pin exact versions, so a new release never reaches an application until it moves its `go.mod` or its checkout.
## Upgrading to 0.2
0.2 tightens two configuration checks so that settings which leaked credentials stop the start-up instead. Most applications are not affected: the first concerns applications that load an `auth.cookie` block, the second applications that send credentialed CORS answers. Start the new binary once in each environment before you switch traffic to it; a refused configuration fails `serve` at start-up with an error that names the key.
### Boot refusals
**A token cookie that is not Secure in production.** In the production environment, `bouncer.LoadCookieConfig` refuses a token cookie whose `Secure` attribute resolves to false. That covers `auth.cookie.secure: false` and, since 0.2, an unset `auth.cookie.secure` with an http or empty `app.url`, from which the cookie inherited `Secure=false` before. The error names `auth.cookie.secure` and `app.url`.
It affects applications whose plugins load an `auth.cookie` block for a browser frontend (the cookie transport). To fix it, set `app.url` to the application's public https URL, or set `auth.cookie.secure: true` explicitly. See [Cookie transport](../services/authentication.md#cookie-transport).
**Credentialed CORS with a wildcard host or an unanchored pattern.** With `supports_credentials: true`, globally under `http.cors` or in any profile under `http.cors_profiles.<name>`, these entries now fail the start-up, and the error names the key with its index, such as `http.cors.allowed_origins[1]` or `http.cors_profiles.spa.allowed_origins_patterns[0]`:
- an `allowed_origins` entry with a `*` that is not the whole leftmost host label after a literal scheme, such as `https://*`, `*://*`, `https://*example.com` or `http*://www.example.com` (`https://*.example.com` stays valid);
- an `allowed_origins_patterns` entry not anchored with `^` and `$`, in every alternative of the expression;
- any origin rule that matches an origin outside the configured domains, such as `https://*.com` or `^https?://.*$`.
It affects applications that send credentialed CORS answers, to a browser frontend on another origin that calls the API with cookies. To fix it, list the frontend's exact origins, or write anchored patterns such as `^https://[a-z]+\.example\.com$`. Without credentials these entries load as before. See [CORS](../services/routing.md#cors) and [CORS profiles](../services/routing.md#cors-profiles).
### Behaviour changes
These need no configuration change, but a test or an operator may notice them:
- **Site-cache purges are queued.** After an admin save commits, the purge request to the site is queued and sent by a background worker, with at most one request in flight per purger; saves committed meanwhile collapse into one follow-up request. The save no longer waits for the site. A test that asserts a purge calls `cooler.SiteCachePurger.Wait` first, and `serve` drains the queue on shutdown. See [Site cache purge](../services/caching.md#site-cache-purge).
- **Protected uploads need a private bucket.** While `storage.uploads.public_url` is set, `attach.Store` refuses a protected (`is_public` false) upload with `attach.ErrProtectedNeedsPrivateBucket` before it writes anything, and `serve` logs one warning at start-up that the bucket must hold public files only. Keep protected relations on a bucket without `public_url`, or make the relation public. See [Public URL base](../services/storage.md#public-url-base).
- **The Journal plugin's purge keys are deprecated.** `golem15.journal.site_cache.purge_url` and `golem15.journal.site_cache.purge_token` still work as aliases of the framework's `site_cache.purge_url` and `site_cache.purge_token`, which win when both are set; the plugin logs a deprecation warning. Move the values to the `site_cache` keys.
- **Cookie defaults.** A `bouncer.CookieConfig` built by hand with every field zero writes `SameSite=Lax` and `Secure`; a config with any field set keeps its own `Secure` value.
- **The API documentation page** at `/api-docs` runs only scripts that carry the page's per-request nonce. See [API documentation page](../services/routing.md#api-documentation-page).
- **Turnstile without a secret.** When `turnstile.secret` is empty and routes name `turnstile:open` or `turnstile:closed`, the start-up logs one warning with the number of such routes. See [Turnstile](../services/authentication.md#turnstile).
- **CORS profile headers on every answer.** A route that names `cors:<profile>` carries the profile's headers on every response, including refusals from guards, throttle, Turnstile and the body limit, and recovered panics.
## What 0.2 adds since 0.1
The 0.1 series grew through many patch releases. These are the larger features that arrived after its first public releases, with the page that documents each:
- Caching with memory and Redis drivers, and a Redis store that shares `throttle` counters between instances: [Caching](../services/caching.md), [Rate limiting](../services/rate-limiting.md).
- The site-cache purge after admin saves, including reorder saves through `pact.ReorderAfterSave`: [Site cache purge](../services/caching.md#site-cache-purge).
- Token cookies with ready-made refresh and logout handlers, and Turnstile bot protection: [Cookie transport](../services/authentication.md#cookie-transport), [Turnstile](../services/authentication.md#turnstile).
- Credentialed CORS, per-route CORS profiles (`cors:<profile>`) and the opt-in API documentation page: [CORS](../services/routing.md#cors), [CORS profiles](../services/routing.md#cors-profiles), [API documentation page](../services/routing.md#api-documentation-page).
- Go build tags in `summer.yaml` (`build.tags`), S3 uploads buckets behind the `summercms_s3` tag and a public URL base for a bucket or CDN: [The summer.yaml manifest](../architecture/go-modules-and-workspaces.md#the-summeryaml-manifest), [S3 and S3-compatible buckets](../services/storage.md#s3-and-s3-compatible-buckets), [Public URL base](../services/storage.md#public-url-base).
- Serving uploads from the application and a per-request access log: [Serving files](../services/storage.md#serving-files), [Request log](../services/logging.md#request-log).
- Plugin-provided admin field types: [Plugin field types](../backend/field-types.md).
- Rich text, repeater, money, password and taglist fields, and dependent dropdowns: [Rich text](../backend/forms.md#rich-text), [Repeater](../backend/forms.md#repeater), [Money](../backend/forms.md#money), [Form-only fields](../backend/forms.md#form-only-fields), [Taglist](../backend/forms.md#taglist), [Dependent dropdowns](../backend/forms.md#dependent-dropdowns).
- Record reordering as a tree or a flat list: [Tree reorder](../backend/lists-and-filters.md#tree-reorder), [Flat reorder](../backend/lists-and-filters.md#flat-reorder).
- Singleton controllers, record actions and write-only settings secrets: [Singleton controllers](../backend/admin-controllers.md#singleton-controllers), [Record actions](../backend/admin-controllers.md#record-actions), [Write-only secrets](../backend/settings.md#write-only-secrets).
- Personal API tokens for administrators and the `admin:token:*` commands: [API tokens](../backend/users-and-permissions.md#api-tokens), [Admin accounts](../console/setup-and-maintenance.md#admin-accounts).
- Menu item types that content plugins register for menus and sitemaps: [Menu item types](../plugins/menu-item-types.md).
- New framework modules: [cooler](../../modules/cooler/README.md) (caches, shared counters and the site-cache purge), [seaglass](../../modules/seaglass/README.md) (the rich text sanitizer), [sieve](../../modules/sieve/README.md) (collection helpers) and [signpost](../../modules/signpost/README.md) (the menu item type registry).