mirror of
https://github.com/johannesjo/super-productivity.git
synced 2026-07-18 00:46:45 +00:00
* fix(sync): redact WebSocket auth token from Caddy access logs (#8343) The WS endpoint authenticates via ?token=<JWT> (browsers can't set headers on a WebSocket), and that JWT is valid for 365 days with no rotation. The shipped Caddyfile enables access logging, so every WS upgrade wrote a year-valid, full-sync credential to stdout / docker logs. Use a filter log encoder to redact the token query param from the logged URI while keeping the request line for observability. * fix(sync): retry failed remote ops as one seq-ordered batch (#8305) retryFailedRemoteOps applied each failed op in its own single-op applyOperations call. That turned every retry into a single-op batch, so the same-batch archive pre-scan (collectArchivingOrDeletingEntityIdsFrom Batch) no-op'd and silently weakened the #7330 orphan-resurrection guard. Retry all failed ops as one batch instead, ordered by seq, and mirror the primary remote-apply path's applied/slice-from-failure result handling (keeping the MAX_CONFLICT_RETRY_ATTEMPTS reject cap). * fixup! fix(sync): redact WebSocket auth token from Caddy access logs (#8343) * refactor(sync): share slice-from-failure op-id logic across apply paths Extract getFailedOpIdsFromBatch() — the 'failed op plus every op after it' slice that retryFailedRemoteOps, ConflictResolutionService, and the sync-core remote-apply path each derived inline. Removes the app-side duplication flagged in review and fixes a latent bug: conflict-resolution sliced from the findIndex result with no -1 guard, so an unfound failed op would slice(-1) and mark only the last op failed. The shared helper guards that case (marks just the failed op). Behavior is otherwise unchanged. * test(sync): integration-test failed-op retry against real IndexedDB (#8305) The retryFailedRemoteOps unit spec mocks the store, so it can't verify the real status transitions the retry relies on. Add an integration spec that drives retryFailedRemoteOps through the real OperationLogStoreService with only the applier controlled, asserting: full-batch success clears ops to applied, the batch is applied in one call, partial failure re-marks the failed op plus every op after it, and a permanently-failing op is rejected at MAX_CONFLICT_RETRY_ATTEMPTS across reboots and then no longer returned.
48 lines
1.7 KiB
Caddyfile
48 lines
1.7 KiB
Caddyfile
# NOTE: docker-compose.yml healthcheck probes the Caddy admin API at
|
|
# 127.0.0.1:2019 (Caddy's default admin listen is `localhost:2019`, i.e.
|
|
# IPv4 loopback; the probe uses the literal IP so busybox wget can't try
|
|
# ::1 first). Do NOT add a global `{ admin off }` block or rebind admin
|
|
# without also updating the healthcheck, or Caddy will restart-loop.
|
|
|
|
{$DOMAIN} {
|
|
reverse_proxy supersync:1900 {
|
|
# Allow up to 85 seconds for long-running operations
|
|
# (snapshot generation, large imports)
|
|
# MUST be greater than Fastify timeout (80s) but less than client timeout (90s)
|
|
transport http {
|
|
dial_timeout 10s
|
|
response_header_timeout 85s
|
|
}
|
|
}
|
|
|
|
# Security headers
|
|
header {
|
|
X-Content-Type-Options nosniff
|
|
X-Frame-Options DENY
|
|
Referrer-Policy strict-origin-when-cross-origin
|
|
-Server
|
|
}
|
|
|
|
# Enable compression
|
|
encode gzip zstd
|
|
|
|
# Logging
|
|
#
|
|
# Redact the `token` query param from the logged URI. The WebSocket endpoint
|
|
# authenticates via `?token=<JWT>` (browsers can't set headers on a
|
|
# WebSocket), and that JWT is valid for 365 days with no rotation — so
|
|
# without this filter every WS upgrade writes a year-valid, full-sync
|
|
# credential to stdout / `docker logs`. `token` is only ever a query param
|
|
# carrying an auth secret (the WS JWT, plus the email-verification,
|
|
# passkey-recovery and magic-login links), never a benign field, so
|
|
# redacting it across this site block is targeted and safe. See #8343.
|
|
log {
|
|
output stdout
|
|
format filter {
|
|
wrap console
|
|
request>uri query {
|
|
replace token REDACTED
|
|
}
|
|
}
|
|
}
|
|
}
|