Commit Graph

70 Commits

Author SHA1 Message Date
Paperclip CTO
aabb58e042 Harden frontend entrypoint script for Windows/Linux line endings
All checks were successful
CI Build / Build Container (push) Successful in 6s
CI Quality / Ruff Lint (push) Successful in 6s
CI Security / Bandit + pip-audit (push) Successful in 27s
CI Tests / Django Tests (push) Successful in 35s
CI Tests / OpenAPI Schema (push) Successful in 11s
2026-05-19 22:52:25 +02:00
Paperclip CTO
1bb4f4c3e3 Fix docker env defaults and clarify frontend entrypoints
All checks were successful
CI Build / Build Container (push) Successful in 5s
CI Quality / Ruff Lint (push) Successful in 7s
CI Security / Bandit + pip-audit (push) Successful in 26s
CI Tests / Django Tests (push) Successful in 39s
CI Tests / OpenAPI Schema (push) Successful in 13s
2026-05-19 22:29:47 +02:00
Paperclip CTO
581d18c497 Fix frontend API defaults for internal Docker networks
All checks were successful
CI Build / Build Container (push) Successful in 9s
CI Quality / Ruff Lint (push) Successful in 9s
CI Security / Bandit + pip-audit (push) Successful in 25s
CI Tests / Django Tests (push) Successful in 41s
CI Tests / OpenAPI Schema (push) Successful in 13s
2026-05-19 22:20:36 +02:00
Paperclip CTO
96ead0a82a chore(ci): retry gitea pipeline for TRA-409 verification
All checks were successful
CI Build / Build Container (push) Successful in 6s
CI Quality / Ruff Lint (push) Successful in 6s
CI Security / Bandit + pip-audit (push) Successful in 23s
CI Tests / Django Tests (push) Successful in 40s
CI Tests / OpenAPI Schema (push) Successful in 13s
2026-05-19 14:48:18 +02:00
Paperclip CTO
dc1bc863e9 TRA-408 mark remaining compose internal networks as private
All checks were successful
CI Build / Build Container (push) Successful in 5s
CI Quality / Ruff Lint (push) Successful in 6s
CI Security / Bandit + pip-audit (push) Successful in 20s
CI Tests / Django Tests (push) Successful in 35s
CI Tests / OpenAPI Schema (push) Successful in 11s
2026-05-19 14:26:33 +02:00
Paperclip CTO
9f40658fab TRA-408 isolate internal services in backend-only network
All checks were successful
CI Build / Build Container (push) Successful in 6s
CI Quality / Ruff Lint (push) Successful in 6s
CI Security / Bandit + pip-audit (push) Successful in 21s
CI Tests / Django Tests (push) Successful in 35s
CI Tests / OpenAPI Schema (push) Successful in 12s
2026-05-19 14:24:56 +02:00
Paperclip CTO
94bba1ec5d TRA-408 isolate certificate rendering in internal service
All checks were successful
CI Build / Build Container (push) Successful in 5s
CI Quality / Ruff Lint (push) Successful in 6s
CI Security / Bandit + pip-audit (push) Successful in 21s
CI Tests / Django Tests (push) Successful in 35s
CI Tests / OpenAPI Schema (push) Successful in 16s
2026-05-19 14:23:20 +02:00
Paperclip CTO
47fe6ba0e9 ci: restore build-only workflow without deploy
All checks were successful
CI Build / Build Container (push) Successful in 6s
CI Quality / Ruff Lint (push) Successful in 6s
CI Security / Bandit + pip-audit (push) Successful in 21s
CI Tests / Django Tests (push) Successful in 34s
CI Tests / OpenAPI Schema (push) Successful in 11s
2026-05-19 14:11:30 +02:00
Paperclip CTO
3c8863949a ci: remove deploy workflows and keep testing pipelines only
All checks were successful
CI Quality / Ruff Lint (push) Successful in 6s
CI Security / Bandit + pip-audit (push) Successful in 23s
CI Tests / Django Tests (push) Successful in 34s
CI Tests / OpenAPI Schema (push) Successful in 11s
2026-05-19 14:07:42 +02:00
Paperclip CTO
d2b673cc0f ci: fix migration check order and harden security workflow
All checks were successful
CI Deploy Checks / Build Container (push) Successful in 8s
CI Quality / Ruff Lint (push) Successful in 8s
CI Security / Bandit + pip-audit (push) Successful in 21s
CI Tests / Django Tests (push) Successful in 38s
CI Tests / OpenAPI Schema (push) Successful in 10s
2026-05-19 13:58:21 +02:00
Paperclip CTO
b6e5e2cc14 ci(gitea): remove setup-python cache options for runner compatibility
Some checks failed
CI Deploy Checks / Build Container (push) Successful in 6s
CI Quality / Ruff Lint (push) Successful in 5s
CI Security / Bandit + pip-audit (push) Failing after 9s
CI Tests / Django Tests (push) Failing after 8s
CI Tests / OpenAPI Schema (push) Has been skipped
2026-05-19 13:49:28 +02:00
Paperclip CTO
d868a04032 ci: split workflows into quality, tests, security, deploy checks
Some checks failed
CI Deploy Checks / Build Container (push) Successful in 6s
CI Quality / Ruff Lint (push) Failing after 6s
CI Tests / Django Tests (push) Has been cancelled
CI Tests / OpenAPI Schema (push) Has been cancelled
CI Security / Bandit + pip-audit (push) Has been cancelled
2026-05-19 13:46:33 +02:00
Paperclip CTO
3c2cbb6e39 Apply FRONTEND_API_BASE_URL across compose profiles
All checks were successful
CI / lint (push) Successful in 13s
CI / test (push) Successful in 24s
CI / build-container (push) Successful in 6s
2026-05-19 13:32:22 +02:00
Paperclip CTO
4709794301 Add local docker frontend runtime API env configuration
All checks were successful
CI / lint (push) Successful in 7s
CI / test (push) Successful in 23s
CI / build-container (push) Successful in 12s
2026-05-19 13:26:03 +02:00
Paperclip CTO
679732de7d feat(security): add modsecurity paranoia level 4 ruleset for nginx
All checks were successful
CI / lint (push) Successful in 7s
CI / test (push) Successful in 21s
CI / build-container (push) Successful in 6s
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-19 10:27:48 +02:00
Paperclip CTO
d54aff5db8 TRA-403 use .env env_file across compose stacks
All checks were successful
CI / lint (push) Successful in 7s
CI / test (push) Successful in 22s
CI / build-container (push) Successful in 6s
2026-05-19 10:18:51 +02:00
Paperclip CTO
f15bdb295a TRA-403 use local Docker build context image paths
All checks were successful
CI / lint (push) Successful in 6s
CI / test (push) Successful in 22s
CI / build-container (push) Successful in 6s
2026-05-19 10:11:02 +02:00
Paperclip CTO
6cfeeff0f9 feat(deploy): add compose profile with dedicated frontend container for reverse-proxy setups
All checks were successful
CI / lint (push) Successful in 6s
CI / test (push) Successful in 21s
CI / build-container (push) Successful in 6s
2026-05-19 09:12:04 +02:00
Paperclip CTO
4a46c14857 feat(frontend): add theming, branding sync, and improved frontend error UX
All checks were successful
CI / lint (push) Successful in 10s
CI / test (push) Successful in 23s
CI / build-container (push) Successful in 8s
2026-05-19 09:09:04 +02:00
Paperclip CTO
5ed7cf2225 fix(api): close contract gaps identified in TRA-398 API review
- EmployeeAttendanceSerializer: add meeting_title (source: meeting.title)
  fixes attendance.js rendering r.meeting_title as undefined
- MeetingParticipantSerializer: add user_email and user_display_name
  so meeting detail participant list shows human-readable identity
- OrganizationProfileListCreateView: add GET handler to list org profiles
  (previously POST-only, returning 405 on GET)
- UserProfileSerializer: add org_ids derived from role_bindings
  so frontend can resolve which org profile to load for branding

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-19 08:57:59 +02:00
Paperclip CTO
333c7b8e11 fix(ci): run tests without redis and align permission/upload expectations
All checks were successful
CI / lint (push) Successful in 6s
CI / test (push) Successful in 22s
CI / build-container (push) Successful in 1m21s
2026-05-18 15:09:16 +02:00
Paperclip CTO
80df6d4baf fix(tests): align dwell tracking user creation with email-only account model
Some checks failed
CI / lint (push) Successful in 5s
CI / test (push) Failing after 29s
CI / build-container (push) Has been skipped
2026-05-18 15:07:37 +02:00
Paperclip CTO
7e7e094fb7 fix(tests): unblock sqlite CI failures in mocks, helpers, and legacy cms route
Some checks failed
CI / lint (push) Successful in 6s
CI / test (push) Failing after 26s
CI / build-container (push) Has been skipped
2026-05-18 15:05:47 +02:00
Paperclip CTO
62e14cda87 fix(gitea-ci): remove pre-migrate check on fresh sqlite database
Some checks failed
CI / lint (push) Successful in 5s
CI / test (push) Failing after 27s
CI / build-container (push) Has been skipped
2026-05-18 15:02:20 +02:00
Paperclip CTO
ba83660990 fix(gitea-ci): use sqlite test workflow and explicit django settings
Some checks failed
CI / lint (push) Successful in 6s
CI / test (push) Failing after 8s
CI / build-container (push) Has been skipped
2026-05-18 15:01:04 +02:00
Paperclip CTO
bf96b7b018 ci: inline django/db env in test and schema commands
Some checks failed
CI / lint (push) Successful in 6s
CI / test (push) Failing after 9s
CI / build-container (push) Has been skipped
2026-05-18 15:00:17 +02:00
Paperclip CTO
b07d8e056d ci: switch tests and schema jobs to sqlite-backed workflow
Some checks failed
CI / lint (push) Successful in 6s
CI / test (push) Failing after 9s
CI / build-container (push) Has been skipped
2026-05-18 14:59:10 +02:00
Paperclip CTO
7ed33ffc08 fix(ci): force test settings module in migrate and pytest commands
Some checks failed
CI / lint (push) Successful in 6s
CI / test (push) Failing after 9s
CI / build-container (push) Has been skipped
2026-05-18 14:58:06 +02:00
Paperclip CTO
ec61d2ab99 fix(test-settings): use postgres service as DATABASE_URL fallback
Some checks failed
CI / lint (push) Successful in 6s
CI / test (push) Failing after 9s
CI / build-container (push) Has been skipped
2026-05-18 14:57:23 +02:00
Paperclip CTO
348aecbead fix(test-settings): honor DATABASE_URL in test configuration
Some checks failed
CI / lint (push) Successful in 6s
CI / test (push) Failing after 9s
CI / build-container (push) Has been skipped
2026-05-18 14:56:37 +02:00
Paperclip CTO
8b2ac6b52b fix(ci): use service hostnames for postgres and redis
Some checks failed
CI / lint (push) Successful in 7s
CI / test (push) Failing after 9s
CI / build-container (push) Has been skipped
2026-05-18 14:55:27 +02:00
Paperclip CTO
1e74090e17 fix(ci): add daphne runtime dependency for django app loading
Some checks failed
CI / lint (push) Successful in 6s
CI / test (push) Failing after 19s
CI / build-container (push) Has been skipped
2026-05-18 14:54:23 +02:00
Paperclip CTO
01661bf5a8 fix: restore CI by fixing lint, test collection, and notification syntax
Some checks failed
CI / lint (push) Successful in 6s
CI / test (push) Failing after 7s
CI / build-container (push) Has been skipped
2026-05-18 14:53:29 +02:00
Paperclip CTO
1e886f2022 fix(TRA-379): generate missing migrations and fix daphne INSTALLED_APPS ordering
Some checks failed
CI / lint (push) Failing after 8s
CI / test (push) Failing after 8s
CI / build-container (push) Has been skipped
- Move daphne before django.contrib.staticfiles in INSTALLED_APPS so Daphne
  system check passes and makemigrations --check can run cleanly
- Generate tracking/0002: rename auto-generated AuditEvent index names to
  match Django 5.2 format
- Generate accounts/0005: sync AccountUser managers and ManyToMany field
  help_text to match current Django/guardian defaults

The CallSession / CallParticipant / CallEvent migration (training/0004)
already existed from the groupcall backend commit; this commit ensures
makemigrations --check reports no pending migrations across all apps.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-18 14:44:51 +02:00
Paperclip CTO
1527c649e6 feat(TRA-373): permission management for meeting moderation
- Add meeting:moderate capability to trainer role in ROLE_CAPABILITIES
- IsMeetingModerator permission class already in place from TRA-372 (training:signoff or meeting:moderate)
- Moderation endpoints (mute/unmute/kick, screen-share, session lifecycle) restricted to meeting:moderate
- Add migration 0003 for MeetingParticipant.attendance_session FK
- Add integration tests: 18 cases covering trainer allowed / learner 403 / unauthenticated 401
  for mute, unmute, kick, screen share (start/stop), call session (start/end/view), audit log

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-18 14:17:11 +02:00
Paperclip CTO
dafbfa2bc4 feat(TRA-372): live groupcall backend — WebRTC signaling + session control
- Add Django Channels 4 + channels-redis to requirements and INSTALLED_APPS
- Upgrade ASGI config to ProtocolTypeRouter with JWT-authenticated WebSocket routing
- Add JWTAuthMiddleware for WebSocket token auth via query param
- Add CallSession, CallParticipant, CallEvent models with migration 0004
- MeetingCallConsumer: join/leave, P2P SDP/ICE relay via per-user groups,
  instructor mute/unmute/kick with DB audit and WS broadcast
- REST endpoints: GET/POST/DELETE /meetings/{id}/call/ (session lifecycle),
  POST /moderate/ (mute/unmute/kick), POST /screen-share/, GET /events/ (audit log)
- IsMeetingModerator permission (accepts training:signoff or meeting:moderate)
- Services: get_or_create_call_session, end_call_session, apply_moderation_action,
  toggle_screen_share with full CallEvent audit trail
- Integration tests covering REST lifecycle, moderation, and WebSocket signaling

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-18 14:12:48 +02:00
Paperclip CTO
7225775e12 feat(TRA-370): attendance UI, API endpoints, and migration
Backend:
- Add migration 0002 for Meeting, MeetingParticipant, EmployeeAttendance models
- Add EmployeeAttendanceSerializer with meeting_title helper field
- Add MeetingDetailView (GET /meetings/{id}/ with participants embedded)
- Add EmployeeAttendanceListView (GET /training/attendance/) with
  role-based access: own records always visible; other users require
  progress:view_all / progress:view_team / users:manage capability
- Register meeting-detail and attendance-list routes in urls.py

Frontend:
- attendance.html + attendance.js: JWT login flow, attendance history
  table with status badges, token refresh via sessionStorage only
  (no localStorage for access tokens)
- meetings.html + meetings.js: meeting list, create-meeting form,
  per-meeting participant management, inline attendance recording
  with select + save per row; UUID input validated before submit
- attendance.css: shared stylesheet for both pages

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-18 12:12:05 +02:00
Paperclip CTO
72e319767f feat(TRA-368): add attendance app with check-in/check-out core
Some checks failed
CI / lint (push) Failing after 46s
CI / test (push) Failing after 11s
CI / build-container (push) Has been skipped
- AttendanceSession model with open/closed status, org_id, timestamps
- POST /api/v1/attendance/check-in/ – creates session, rejects duplicate open check-ins (409)
- POST /api/v1/attendance/check-out/ – closes open session, validates checkout > checkin
- GET /api/v1/attendance/status/ – current open session for requesting user
- GET /api/v1/attendance/history/ – paginated session history per user
- GET /api/v1/attendance/admin/sessions/ – admin view for managers/admins with filters
- Initial migration with composite indexes on (user, status) and (user, checked_in_at)
- 18 test cases covering core flows and edge cases

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-18 12:11:16 +02:00
Paperclip CTO
e92ae6c136 feat(TRA-362): add docker-compose.prod.yml with nginx as web server
Introduces a production Docker Compose stack that places nginx in front
of gunicorn. nginx serves the frontend SPA and Django static files
directly, and proxies all backend routes (/api, /admin, /healthz, etc.)
to the Django container. SECURE_SSL_REDIRECT is now env-configurable so
plain-HTTP nginx deployments work without separate settings files.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 08:08:52 +02:00
Paperclip CTO
9e3c28b191 feat(TRA-360): enforce license_user_limit when assigning users to an org
Some checks failed
CI / lint (push) Failing after 6s
CI / test (push) Failing after 10s
CI / build-container (push) Has been skipped
Before creating a UserRoleBinding for a specific org_id, check whether
the org's OrganizationProfile.license_user_limit has been reached. New
users attempting to join a full org receive HTTP 403 with a descriptive
message. Re-assigning a user already in the org (role change) is
unaffected, as is assignment to an org with no OrganizationProfile.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-08 07:54:22 +02:00
Paperclip CTO
e711519413 feat(TRA-359): add POST /api/v1/accounts/organizations/ to create OrganizationProfile
Some checks failed
CI / lint (push) Failing after 11s
CI / test (push) Failing after 10s
CI / build-container (push) Has been skipped
- OrganizationProfileListCreateView (admin-only) handles POST
- OrganizationProfileCreateSerializer drops auto UniqueValidator so the
  view can return 409 (instead of 400) for duplicate org_id
- Returns 201 on success, 400 on validation errors, 409 on duplicate
- Tests: create success, defaults, duplicate 409, missing field 400, non-admin 403

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-08 07:52:08 +02:00
Paperclip CTO
22a472b72e fix(TRA-335): make license_user_limit a free-form integer, not fixed tiers
Replace the choices-constrained field (20/50/100/1000 only) with a plain
PositiveIntegerField so any positive integer is accepted. Adds migration
0004 to apply the schema change. Adds a test asserting arbitrary values
(e.g. 75) are accepted. Updates README with a field table and curl example
that documents common values without enforcing them.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-08 07:52:08 +02:00
Paperclip CTO
ca0352fa33 fix(ci): resolve ruff lint violations blocking CI pipeline
- Move `from datetime import timedelta` to top of base.py (E402)
- Add `# noqa: E402` to conditional sentry imports in prod.py (E402)
- Remove unused `import time` and `IsAdminUser` from api/views.py (F401)
- Remove unused `NoReverseMatch` import from tests/test_smoke.py (F401)

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-08 07:52:08 +02:00
Paperclip CTO
295ac1c31f feat(TRA-335): license limits, per-customer branding, frontend, Gitea CI, and deployment README
- Added OrganizationProfile model with license_user_limit choices (20/50/100/1000), company_name, brand_logo_url
- Added migration 0003_organization_profile
- Admin-only REST endpoint GET/PATCH /api/v1/accounts/organizations/{org_id}/profile/
- OrganizationProfileSerializer, OrganizationProfileAdmin, factory, and integration tests
- Static Nginx-hostable frontend under frontend/public with configurable API_BASE_URL via config.js
- frontend/nginx.conf reference server config
- .gitea/workflows/ci.yml: ruff lint, pytest with Postgres/Redis services, docker build
- README.md: English deployment guide covering env vars, Docker Compose, migration, org profile API, frontend deploy

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-08 07:52:08 +02:00
403dcb1d05 chore(TRA-306): trigger deploy via push path (add comment)
Co-Authored-By: Paperclip <noreply@paperclip.ai>
2026-05-07 11:57:41 +00:00
fa74f87fbe fix(TRA-306): use docker exec python for health checks, runner can't reach container IPs directly
Co-Authored-By: Paperclip <noreply@paperclip.ai>
2026-05-07 11:55:10 +00:00
d9a24112a3 fix(TRA-306): remove migrate from startup cmd, workflow handles it via docker exec
Some checks failed
Deploy Waitlist / Deploy to VPS (push) Failing after 3m9s
Co-Authored-By: Paperclip <noreply@paperclip.ai>
2026-05-07 11:49:16 +00:00
518bdf0d9f fix(TRA-306): run migrations via docker exec, separate from gunicorn startup
Some checks failed
Deploy Waitlist / Deploy to VPS (push) Has been cancelled
- Release stale Django migration advisory locks before migrating
- Run migrate via docker exec (not in container startup command)
- Update container CMD to start gunicorn directly (no migrate)
- This unblocks the 15-min migrate hang caused by leftover pg advisory lock

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-07 11:46:06 +00:00
df8fcc7322 fix(TRA-306): improve deploy workflow health polling and diagnostics
Some checks failed
Deploy Waitlist / Deploy to VPS (push) Has been cancelled
- Replace single healthz curl (no timeout) with polling loop (30x10s)
- Add --connect-timeout and --max-time to all curl calls
- Print container logs when gunicorn fails to start
- Print container logs in always() step for visibility

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-07 11:39:17 +00:00
ba3fa67194 fix(TRA-306): make celery import conditional in config/__init__.py
Waitlist deployment uses requirements/waitlist.txt which does not include celery.
Making the import conditional allows the app to start without celery installed.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-07 11:31:54 +00:00