- Replace all GitHub action clones (login-action, build-push-action)
with plain docker CLI commands — eliminates GitHub dependency
- Expand act_runner_config.yaml to full format (partial config was
silently falling back to defaults)
- Mount config at /etc/act_runner/ with CONFIG_FILE env var to avoid
named volume shadowing at /data/
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
CI/CD fixes (from debugger + docker specialist review):
- Add explicit GITEA_TOKEN for checkout auth
- Add act_runner_config.yaml with container.network: host so job
containers can reach git.sentinelforest.xyz (root cause of 0s
silent checkout failure)
- Mount config into act_runner container
UI: Enlarge save/close/edit/delete icons in all detail panels
(EventDetailPanel, TodoDetailPanel, ReminderDetailPanel,
TaskDetailPanel, EntityDetailPanel) from h-7/h-3.5 to h-8/h-4
for better visibility and click targets.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
SELinux in enforcing mode blocks container access to the Docker
socket. The :z flag relabels the socket for shared container access.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
group_add didn't resolve the permission issue. Running the runner
as root (user 0:0) is the standard approach for CI runners that
need Docker socket access on internal/single-user deployments.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The runner process runs as non-root but needs access to the Docker
socket owned by root:docker (GID 971). group_add grants it.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The act_runner container couldn't find the Docker socket despite the
volume mount. Adding DOCKER_HOST=unix:///var/run/docker.sock explicitly
tells the runner where to find it.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When both image: and build: are present, docker compose up --build
builds locally and tags with the image name. This allows the stack
to start before registry images exist, solving the bootstrap problem.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds a workflow that triggers on push to main: builds backend/frontend
Docker images, pushes to Gitea container registry, pulls and restarts
on the host, health checks, prunes old images, and sends ntfy notifications.
docker-compose.yaml updated to pull pre-built images from registry and
includes act_runner as a 4th service.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Phase 1 fixes:
- W-01: Add start_period: 30s to backend healthcheck for migration window
- W-03: Narrow .dockerignore *.md to specific files (preserve alembic/README)
Phase 2 fixes:
- C-01: Wrap Argon2id calls in totp.py (disable, regenerate, backup verify,
backup store) — missed in initial AC-2 pass
- S-01: Extract async wrappers (ahash_password, averify_password,
averify_password_with_upgrade) into services/auth.py, refactor all
callers to use them instead of manual run_in_executor boilerplate
- W-01: Fix ntfy dedup regression — commit per category instead of per-user
to preserve dedup records if a later category fails
Phase 4 fixes:
- C-01: Fix optimistic drag-and-drop cache key to include date range
- C-02: Replace toISOString() with format() to avoid UTC date shift in
visible range calculation
- W-02: Initialize visibleRange from current month to eliminate unscoped
first fetch + immediate refetch
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add .dockerignore for backend and frontend (DC-1: eliminates node_modules/
and .env from build context)
- Delete start.sh with --reload flag (DC-2: superseded by Dockerfile CMD)
- Create entrypoint.sh with exec uvicorn (DW-5: proper PID 1 signal handling)
- Pin base images to patch-level tags (DW-1: reproducible builds)
- Reorder Dockerfile: create appuser before COPY, use --chown (DW-2)
- Switch to npm ci for lockfile-enforced installs (DW-3)
- Add network segmentation: backend_net + frontend_net (DW-4: db unreachable
from frontend container)
- Add deploy.resources limits to all services (DW-6: OOM protection)
- Refactor proxy-params.conf to include security headers, deduplicate from
nginx.conf location blocks (DW-7)
- Add image/svg+xml to gzip_types (DS-1)
- Add wget healthcheck for frontend service (DS-2)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove external backend port 8000 exposure (VULN-01)
- Conditionally disable Swagger/ReDoc/OpenAPI in non-dev (VULN-01)
- Suppress nginx and uvicorn server version headers (VULN-07)
- Fix CSP to allow Google Fonts (fonts.googleapis.com/gstatic) (VULN-08)
- Add nginx rate limiting on auth endpoints (10r/m burst=5) (VULN-09)
- Block dotfile access (/.env, /.git) while preserving .well-known (VULN-10)
- Make CORS origins configurable, tighten methods/headers (VULN-11)
- Run both containers as non-root users (VULN-12)
- Add IP rate limit + account lockout to /change-password
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- EventForm: check event?.id instead of event to decide PUT vs POST,
fixes "unable to parse string as integer" when creating from template
- TemplateForm: add LocationPicker for setting location on templates
- docker-compose: set TZ=Australia/Perth on backend and db containers
so datetime.now() and PostgreSQL NOW() return local time
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>