Disables dependency lifecycle scripts by default via .npmrc
(ignore-scripts=true) so arbitrary packages cannot execute code at
install time. An explicit allowlist in web/package.json opts specific
packages back in, and CI/Docker/Taskfile now run allow-scripts after
npm install to apply it.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Scan datetime columns directly into time.Time instead of strings in the
timeoff store — the intermediate string parse silently failed with
parseTime=true, producing zero-value dates. Display dates with month
names and filter admin's own entry from the volunteer dropdown.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add full time-off lifecycle: create/edit/delete with shift conflict
detection, auto-removal from conflicting shifts with admin notification,
shift restoration on admin delete, and hard block on assigning volunteers
with approved time off to shifts.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The project moved from SQLite to MySQL but docs still referenced
DATABASE_DSN and old version requirements. Updated requirements,
env vars, and STATIC_DIR default to match current state.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The edit form now fetches approved time-off requests and excludes
volunteers whose time off overlaps the shift date from the
selectable list. Unavailable volunteers are shown below the picker
in a "On approved time off" note.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The edit form now loads the volunteer list and groups them by
operational role. Template role requirements are shown with a
count indicator (selected/required) that turns green when filled.
Volunteers are selected via checkboxes instead of typing IDs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- /schedules?year=2026&month=4 for the shifts view
- /schedules/templates for the templates view
- Month navigation updates search params via useNavigate
- Reloading or sharing a URL restores the exact view
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace bare http.FileServer with an SPA-aware handler that tries to
serve the requested static file and falls back to index.html when
the path doesn't match a real file. This lets React Router handle
client-side routes like /schedules on page reload.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Initialize slice helpers with make() instead of var declaration so
empty results serialize as [] instead of null in JSON, fixing the
frontend TypeError on the schedules page.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When the database has no users, the UI redirects to /setup and prompts
for creation of the first admin account. The setup endpoints are
self-disabling — once any user exists, POST /setup/admin returns 403
and the frontend redirects /setup back to /login. The backend uses an
atomic transaction to prevent race conditions on concurrent requests.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace removed Schedule type and api.listSchedules() with
ShiftInstance and api.listShifts() after the schedule rewrite.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
npm ci fails when the lock file is missing platform-specific packages
(yaml@2.8.3) that only get resolved on Linux. Switch to npm install
which resolves dependencies at runtime rather than strictly validating
the lock file.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Admin-only account creation (no self-registration); invite-token flow
replaces the public /auth/register endpoint
- New volunteer fields: phone, is_trainee, operational_roles,
notification_preference, admin_notes, last_login, completed_shifts
- Role-scoped profile editing: volunteers update name/phone only;
admins update all fields including notes and trainee flag
- /auth/activate endpoint for invite-token-based account activation
- /api/v1/volunteers/{id}/invite for admin to resend invite links
- last_login recorded on each successful authentication
Tests:
- Go: handler tests (auth rules, create, activate, update scoping) via
Storer/AuthServicer interfaces and fake store; auth unit tests for
HashPassword, IssueToken, and Parse
- Frontend: RTL tests for Activate, Profile, and Volunteers pages
- Fixed CRA 5 + React Router v7 Jest compatibility (moduleNameMapper +
TextEncoder polyfill)
- Replaced stale CRA App.test.tsx placeholder with real tests
CI:
- .gitea/workflows/ci.yml runs go vet, go test, tsc, and npm test on
every push and pull request
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Propagate context.Context through all exported store/service methods
that perform I/O; use QueryContext/ExecContext/QueryRowContext throughout
- Add package-level sentinel errors (ErrNotFound, ErrAlreadyCheckedIn,
ErrNotCheckedIn) and replace nil,nil returns with explicit errors
- Update handlers to use errors.Is() instead of nil checks, with correct
HTTP status codes per error type
- Fix SQLite datetime('now') → MySQL NOW() in volunteer, schedule,
timeoff, and checkin stores
- Refactor db.Migrate to execute schema statements individually (MySQL
driver does not support multi-statement Exec)
- Fix import grouping in handler files (stdlib, external, internal)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Go backend with domain-based packages (volunteer, schedule, timeoff,
checkin, notification), SQLite storage, JWT auth, and chi router.
React TypeScript frontend with routing, auth context, and pages for
all core features. Multi-stage Dockerfile and docker-compose included.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>