@stacksjs/defaults 0.75.59 → 0.75.61

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -168,10 +168,36 @@ export function responseMayUseCsrfToken(response: Response): boolean {
168
168
  || type.endsWith('+json')
169
169
  }
170
170
 
171
+ /**
172
+ * Whether a response told shared caches they may keep it: its `Cache-Control`
173
+ * says `public` or gives an `s-maxage`, and says neither `private` nor
174
+ * `no-store`.
175
+ *
176
+ * Such a response is, by its own account, the same for everyone, so it must
177
+ * not carry a per-visitor cookie. A CDN refuses to store a response that sets
178
+ * one (Cloudflare answers `cf-cache-status: BYPASS`), so seeding here kept
179
+ * every shareable API read out of the edge; and a cache that stored it anyway
180
+ * would hand one visitor's token to everybody behind it.
181
+ */
182
+ export function responseDeclaresShared(response: Response): boolean {
183
+ const value = (response.headers.get('cache-control') || '').toLowerCase()
184
+ if (!value || /\b(?:private|no-store)\b/.test(value))
185
+ return false
186
+ return /\bpublic\b/.test(value) || /\bs-maxage\s*=/.test(value)
187
+ }
188
+
171
189
  export function seedCsrfCookieIfMissing(req: Request, response: Response, minted?: string, responseHasNoCookies = false): Response {
172
190
  if (!responseMayUseCsrfToken(response))
173
191
  return response
174
192
 
193
+ // Nothing depends on a shareable response seeding the cookie: a page that
194
+ // carries forms is per-visitor and never says `public`, and a client about to
195
+ // submit without a cookie can ask for one from a response that is not shared.
196
+ // This holds for every layer that seeds - the API router, and the page server
197
+ // that proxies `/api` to it - because they all come through here.
198
+ if (responseDeclaresShared(response))
199
+ return response
200
+
175
201
  // A token the router minted before rendering wins over "the header already
176
202
  // has one", because it put that value in the header itself - and the page
177
203
  // has already embedded it in every form it drew. Generating a second token
@@ -2,7 +2,7 @@
2
2
  "publisher": "Stacks",
3
3
  "name": "vscode-stacks",
4
4
  "displayName": "Stacks",
5
- "version": "0.75.59",
5
+ "version": "0.75.61",
6
6
  "description": "Stacks, built into VS Code: stx templates, pickier linting and formatting, encrypted env files, the dev server preview and every buddy command. No other extensions required.",
7
7
  "license": "MIT",
8
8
  "funding": "https://github.com/sponsors/chrisbbreuer",
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@stacksjs/defaults",
3
3
  "type": "module",
4
4
  "sideEffects": false,
5
- "version": "0.75.59",
5
+ "version": "0.75.61",
6
6
  "repository": {
7
7
  "type": "git",
8
8
  "url": "git+https://github.com/stacksjs/stacks.git",
@@ -55,7 +55,7 @@
55
55
  "dependencies": {
56
56
  "@iconify-json/f7": "^1.2.2",
57
57
  "@iconify-json/hugeicons": "^1.2.35",
58
- "@stacksjs/mobile": "^0.75.59",
58
+ "@stacksjs/mobile": "^0.75.61",
59
59
  "@stacksjs/sanitizer": "^0.2.348",
60
60
  "ts-qr-codes": "^0.1.8"
61
61
  }
@@ -148,6 +148,7 @@ jobs:
148
148
  chmod 644 ~/.ssh/id_ed25519.pub
149
149
 
150
150
  - name: Deploy
151
+ id: deploy
151
152
  if: steps.check.outputs.configured == 'true'
152
153
  run: ./buddy deploy --${{ github.event.inputs.environment == 'staging' && 'staging' || github.event.inputs.environment == 'development' && 'dev' || 'prod' }} --yes
153
154
  env:
@@ -165,3 +166,23 @@ jobs:
165
166
  # macOS resource forks in a tarball built on a developer machine make
166
167
  # the extraction on the server noisy and occasionally fatal.
167
168
  COPYFILE_DISABLE: '1'
169
+
170
+ # A deploy that failed half way must not leave the half it finished live.
171
+ #
172
+ # Each site's own cutover already refuses a release that crashes, never
173
+ # takes its port or fails its health path, and puts the previous release
174
+ # back. What it cannot undo is the site deployed before the one that
175
+ # failed, left on a different commit from the rest. This rolls back every
176
+ # site whose live release is this commit, and only those, then fails the
177
+ # job. Add a smoke check after Deploy (give it `id: smoke`) and include it
178
+ # in the condition to roll back releases that are up but wrong as well.
179
+ #
180
+ # Needs @stacksjs/ts-cloud 0.16.34 or newer for --all and --only-if-live.
181
+ - name: Roll back what this deploy made live
182
+ if: failure() && steps.deploy.outcome == 'failure'
183
+ run: |
184
+ ./buddy deploy:rollback --env ${{ github.event.inputs.environment || 'production' }} --all --only-if-live "$GITHUB_SHA" || echo "::error::The rollback did not complete; check which release each site serves."
185
+ echo "::error::Deploy of ${GITHUB_SHA::7} failed; sites it had switched were rolled back."
186
+ exit 1
187
+ env:
188
+ DOTENV_PRIVATE_KEY_PRODUCTION: ${{ secrets.DOTENV_PRIVATE_KEY_PRODUCTION }}