Private
Public Access
1
0
Commit Graph

62 Commits

Author SHA1 Message Date
Catherine Renelle f641e65c1f Add cross-origin isolation security headers
- Cross-Origin-Embedder-Policy: credentialless (allows Google Fonts)
- Cross-Origin-Opener-Policy: same-origin (isolates browsing context)
- Cross-Origin-Resource-Policy: same-origin (prevents cross-origin loads)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 08:17:29 -04:00
Catherine Renelle 2d4c3a57da Replace unsafe-inline with CSP nonces for script-src
SvelteKit now handles script-src with automatic nonces via its
built-in CSP support. The hooks handler merges extra directives
(style-src, font-src, img-src, etc.) onto SvelteKit's nonce-based
policy for page responses, and sets a full CSP for API responses.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 08:16:45 -04:00
Catherine Renelle b05521add6 Add Permissions-Policy security header
Disables browser APIs not needed by the app: camera, microphone,
geolocation, payment, USB, magnetometer, gyroscope, accelerometer.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 08:15:27 -04:00
Catherine Renelle 827f0394ef Add API key management UI to account settings
Users can create, view, and delete API keys from their profile.
Keys are shown once on creation with a copy button. List shows
key prefix, creation date, and last used date.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 11:44:16 -04:00
Catherine Renelle d8b3935fc5 Add API key authentication for programmatic access
- New ApiKey model in Prisma schema (tenant + user scoped)
- Keys are SHA-256 hashed, only shown once on creation
- Bearer token auth in hooks.server.ts (alongside session cookies)
- CRUD endpoint at /api/account/api-keys (max 10 per user)
- Keys prefixed with pnc_ for easy identification

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 11:34:56 -04:00
Catherine Renelle 44e5af6c2b Enrich Discord webhook embeds with move details and card links
Card moved events now show from/to column names. Card created/updated
embeds link directly to the card. Card updated shows which fields
changed. Card deleted shows the card title. Base URL resolved from
tenant hostname for full links.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 11:05:17 -04:00
Catherine Renelle b6d65b7c31 Add Discord webhook formatting and dispatch logging
Discord webhooks require a specific payload format (embeds), not raw
JSON. Auto-detect Discord URLs and send colored embeds with card/board
details. Also adds logging for webhook dispatch debugging.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 11:00:06 -04:00
Catherine Renelle a57f83c5cd Wire up webhook dispatch for all board/column/card events
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 10:41:47 -04:00
Catherine Renelle e8c70bde87 Add missing favicon.svg
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 10:15:20 -04:00
Catherine Renelle 15f8e8218a Allow Google Fonts in CSP for Tailwind's Inter font
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 10:14:15 -04:00
Catherine Renelle 0852d5a804 Add CSP/HSTS headers, attachment extension whitelist, and upload rate limiting
- Add Content-Security-Policy and Strict-Transport-Security headers
- Whitelist allowed file extensions on attachment uploads
- Add rate limiting to password change (5/5min) and file uploads (20/60s)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 19:25:02 -05:00
Catherine Renelle d418c367cb Security hardening and fix all compile warnings
Security fixes:
- Validate theme background image URLs against whitelist pattern
- Add board permission check to Socket.IO join-board handler
- Disable raw HTML passthrough in markdown parser (XSS prevention)
- Add UUID validation on avatar and branding route params (path traversal)
- Add security headers (X-Frame-Options, X-Content-Type-Options, Referrer-Policy)
- Validate webhook URLs (HTTPS only, block internal addresses)
- Add import payload size limit (5MB)
- Remove server uptime from health endpoint
- Make seed password configurable via SEED_ADMIN_PASSWORD env var
- Patch DOMPurify dependency vulnerability via npm audit fix

Warning fixes:
- Convert $state(prop) to $effect.pre sync pattern (state_referenced_locally)
- Add for/id pairings to form labels (a11y_label_has_associated_control)
- Add svelte-ignore for intentional autofocus usage (a11y_autofocus)
- Add ARIA roles to interactive/overlay divs (a11y_no_static_element_interactions)
- Add aria-label to icon-only buttons (a11y_consider_explicit_label)
- Add keyboard handler alongside click events (a11y_click_events_have_key_events)
- Fix non-reactive fileInput declaration

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 18:36:47 -05:00
Catherine Renelle 8f79de1df6 Remove background picker from board settings
Background customization is available in the Branding section.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 10:15:41 -05:00
Catherine Renelle 55c9a60a0e Fix tab switcher text size consistency across Board/Calendar/Gantt
Calendar and Gantt used text-sm while Board used text-xs, causing
the tab container to change size when switching views.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 10:07:32 -05:00
Catherine Renelle 2fbd3bc93d Add Gantt chart view with card dependencies and start dates
Adds a new Gantt chart board view with custom SVG timeline rendering,
card-to-card dependency tracking with cycle detection, and a startDate
field on cards. Includes zoom controls (day/week/month), dependency
arrows, column-grouped task list, today marker, and real-time updates.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 10:03:11 -05:00
Catherine Renelle 85bda718cc Fix dark mode text color in tag picker dropdown
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 23:54:59 -05:00
Catherine Renelle df0e8909f2 Fix checklist item ordering and add move up/down buttons
The BASE_CHARS in fractional-index.ts had digits after letters
(A-Za-z0-9), but PostgreSQL sorts digits before letters (0-9A-Za-z),
causing items to appear out of order once positions reached the digit
range. Reordered BASE_CHARS to match DB collation.

Also added up/down arrow buttons on checklist items so users can
reorder them within the list.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 23:43:38 -05:00
Catherine Renelle bbc95a5bfc Fix dark mode prose text color in card descriptions
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 23:21:48 -05:00
Catherine Renelle df602ab559 Fix branding page 500 on hard refresh: guard document access during SSR
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 22:20:04 -05:00
Catherine Renelle 8590fb0126 Center search bar to page midpoint in nav header
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 20:58:30 -05:00
Catherine Renelle 0e77c50411 Add board settings modal for editing board properties and deleting boards
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 18:35:00 -05:00
Catherine Renelle faa2608a47 Fix ColorPicker solid color issues, add per-field reset, regroup accents
ColorPicker fixes:
- Color picker now initializes to default color instead of black when
  field is cleared/empty
- Switching Solid<>Gradient no longer emits black; restores default color
  when switching back to Solid from a gradient value
- No-op guard prevents re-emitting when clicking the already-active mode
- Reset button now says "Reset to default" when a default is available
- Text input placeholder shows the default value

Branding page:
- Accent Colors regrouped: Primary+hover and Danger+hover are stacked
  together, Success and Warning standalone in a 4-column grid
- Mini preview fallbacks now use getDefault() helper instead of
  hardcoded values, keeping them in sync with the defaults map

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 17:52:52 -05:00
Catherine Renelle 8c9a5abc5a Fix branding: live updates on save, reset clears everything, show defaults
- Clear inline preview styles before persisting CSS on save to avoid
  specificity conflicts that required Ctrl+Shift+R
- Reset to Defaults now deletes uploaded images and clears logoText
- ColorPicker emits value on Solid/Gradient toggle for instant preview
- Show default color swatch with dashed border when field is cleared
- persistThemeCSS now handles background-image rules like server-side

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 17:33:34 -05:00
Catherine Renelle 795e7c14ff Fix branding page 500 error and make theme changes instant
1. Fix 500 on hard refresh: branding page load was querying tenant
   for logoUrl/logoText fields that may not exist in DB yet. Now
   uses locals.tenant data (from resolver) instead of a separate query.

2. Instant theme application: after saving, persistThemeCSS() generates
   CSS from the draft and writes it into the <style id="tenant-theme">
   element in the DOM. This means navigating to any page after saving
   immediately shows the new theme without a hard refresh.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 14:58:32 -05:00
Catherine Renelle b1d994c9e4 Condense nav: profile dropdown replaces inline nav items
Desktop nav now shows only: theme toggle, notification bell, and
avatar+name. Clicking avatar opens a dropdown menu with My Work,
Profile, Admin, Site Admin, and Logout. Logged-out users see only
the theme toggle and a Login button.

Mobile nav mirrors the same menu items in the hamburger dropdown.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 14:47:13 -05:00
Catherine Renelle ecd037ce5c Rearrange nav: logo left, search centered, nav items right
Use a 3-column CSS grid on desktop (auto | 1fr | auto) so the search
bar stays centered in the viewport while logo and nav items pin to
the edges. Mobile layout unchanged (logo left, hamburger right).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 14:39:39 -05:00
Catherine Renelle ce5310e7a0 Fix gradient backgrounds being overridden by background-image property
The layout had `background: var(--color-page-bg); background-image: ...`
which meant that when --color-page-bg was a gradient (which sets
background-image via the shorthand), the subsequent background-image
declaration would reset it to none.

Fix: use `background` shorthand only via CSS classes (.layout-page-bg,
.layout-nav-bg), and handle uploaded background images via class-level
overrides in generateTenantCSS instead of CSS vars.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 14:27:10 -05:00
Catherine Renelle 95ec8f30dd Fix branding not applying: move CSS vars out of @theme, inject after Tailwind
Tailwind v4's @theme block outputs CSS that came after the tenant theme
<style> tag, causing the defaults to win by source order. Two fixes:
- Move custom property defaults from @theme {} to :root {} so they're
  at the same cascade level as tenant overrides
- Inject tenant CSS before </head> instead of after <head> so it comes
  after all Tailwind output in the cascade

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 12:46:15 -05:00
Catherine Renelle 986c88143a Replace bulk select button with hover checkboxes, remove board background override
- Cards now show a checkbox on hover (top-right) for bulk selection,
  removing the need for a separate "Select" toggle button
- Removed BoardBackgroundPicker from board header since per-board
  backgrounds were overriding tenant branding
- Removed inline background style from board area so branding page
  backgrounds apply correctly

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 10:58:46 -05:00
Catherine Renelle 8c41b33313 Add 17 features: My Work view, card copy/numbering, calendar, bulk ops, custom fields, automations, webhooks, invites, import/export, and more
Features implemented across 6 batches:
- Batch A: Fix ColorPicker gradient sync, tenant custom logo, unarchive cards, board backgrounds
- Batch B: My Work view, card copy/duplicate, card numbering (BOARD-123)
- Batch C: Due date reminders (cron), card watching with notifications
- Batch D: Bulk card operations, column sorting, calendar view
- Batch E: Invite by link, board import/export (Pounce + Trello JSON)
- Batch F: Webhooks with HMAC signing, custom fields, automation rules engine

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 08:50:15 -05:00
Catherine Renelle 3a11ed01e9 Add tenant branding & theming system with admin UI
Tenant admins can now customize their workspace appearance: page/nav
backgrounds (solid, gradient, or image), column/card colors, borders,
text, opacity with glass blur, card corner radius, and accent colors.
Light and dark mode are configured separately. Theme CSS is injected
server-side via transformPageChunk to prevent FOUC.

Includes avatar components, account page updates, and pre-existing
type error fixes (Buffer, async onMount, InputJsonValue).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 21:56:39 -05:00
Catherine Renelle 029b467eae Fix stale nav after login/register: use full page navigation
goto() does client-side navigation which caches the layout data
(user is still null). Using window.location.href forces a full
server round-trip so the nav bar reflects the authenticated user.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 20:28:48 -05:00
Catherine Renelle 80641b6058 Fix deploy: add --accept-data-loss for search_vector column
prisma db push refuses to sync when the search_vector generated
column exists in the DB but not in the schema. The column is
managed by setup-search.sql which runs immediately after.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 20:12:46 -05:00
Catherine Renelle 420ff1e715 Hide SITE_ADMIN from tenant admin, add Site Admin nav link
- Tenant admin user list filters out SITE_ADMIN users (server-side)
- API guard prevents tenant admins from modifying SITE_ADMIN users
- Tenant admins cannot change their own role (prevents self-demotion)
- Nav bar shows separate "Site Admin" link for SITE_ADMIN users
- Both desktop and mobile nav updated

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 20:00:51 -05:00
Catherine Renelle 8c150e5c24 Allow SITE_ADMIN to login across all tenants
Login now falls back to a cross-tenant lookup for SITE_ADMIN users
when the email isn't found in the current tenant. Regular users
remain scoped to their own tenant.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 19:52:18 -05:00
Catherine Renelle 04f5786cf6 Fix psql URI in entrypoint: strip Prisma query params
psql doesn't understand ?schema=public in the DATABASE_URL.
Strip query parameters before passing to psql for RLS, collation,
and search index scripts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 19:46:14 -05:00
Catherine Renelle 5f552a9883 Fix account settings: add invalidateAll, robust error handling
- Add invalidateAll() after profile save so nav bar updates immediately
- Wrap all async handlers in try/finally to prevent stuck loading states
- Make form onsubmit handlers async to properly propagate errors

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 19:31:02 -05:00
Catherine Renelle 1419300baa Add account settings page with profile, password, and session management
- /account page: edit name/email, change password, view/revoke sessions
- PATCH /api/account: update profile or change password (verifies current)
- DELETE /api/account: revoke all other sessions
- Password change auto-revokes other sessions for security
- Username in nav now links to /account (desktop + mobile)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 08:22:34 -05:00
Catherine Renelle f91b8a4bd4 Fix tenant resolution: use Host header instead of ORIGIN-derived URL
SvelteKit's event.url.hostname is always derived from the ORIGIN env
var, so all requests resolved to the same tenant regardless of which
domain the user visited. Now reads X-Forwarded-Host or Host header
to get the actual domain for multi-tenant hostname isolation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 08:01:40 -05:00
Catherine Renelle 606c1b0652 Add drag handle icon to column headers
Shows a grip dots icon in the column header when the user can edit,
making it visually clear that columns are draggable. Also adds
cursor-grab/grabbing styles to the header.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 07:45:58 -05:00
Catherine Renelle 95f8e9a70b Fix column/card ordering: set COLLATE C on position columns
Postgres en_US.utf8 collation sorts case-insensitively, breaking the
lexicographic fractional indexing. Setting COLLATE "C" ensures pure
byte-order sorting. Applied via setup-collation.sql in entrypoint
after prisma db push.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 07:40:13 -05:00
Catherine Renelle 8a97d354fa Add system board templates seeded at startup
Four templates (Kanban, Simple, Sprint, Bug Tracking) with tenantId=null
are auto-seeded on first startup if none exist. Available to all tenants
in the board creation dropdown.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 07:33:08 -05:00
Catherine Renelle 9b5459fa49 Seed default tags and categories for new tenants
New tenants auto-provisioned via hostname get 5 default tags (Bug,
Feature, Enhancement, Urgent, Documentation) and 4 categories
(Frontend, Backend, Design, Infrastructure).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 07:28:06 -05:00
Catherine Renelle 062832a1e3 Fix $state runtime error: rename rune stores to .svelte.ts
$state runes only work in .svelte and .svelte.ts files. The toasts and
theme stores used $state in plain .ts files, which compiled in dev but
crashed in production SSR. Renamed and updated all imports.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 01:33:15 -05:00
Catherine Renelle 1ec64e4ad5 Update docker-compose.yml for git-based Portainer deployment
Switch from hardcoded credentials to env var substitution (DB_PASSWORD,
SESSION_SECRET, ORIGIN). Use production ports (3200:3000, 3201:5432) and
host.docker.internal for DB connectivity.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 01:27:20 -05:00
Catherine Renelle 0bba161c12 Phase 9: Admin & DevOps — health check, rate limiting, logging, site admin, Docker healthcheck
- Health check endpoint (GET /api/health) with DB probe and uptime
- In-memory sliding window rate limiting on login (10/60s) and register (5/3600s)
- Structured logging with pino (request timing in hooks, Socket.IO events in server.js)
- Site admin dashboard with tenant stats, CRUD, and requireSiteAdmin guard
- Tenant admin enhanced with tag and category management UI
- Docker HEALTHCHECK in Dockerfile and docker-compose.yml
- Backup documentation (docs/backup.md)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 01:24:24 -05:00
Catherine Renelle 7559102479 Phase 8: Polish & UX — dark mode, toasts, keyboard shortcuts, responsive, accessibility
- Add dark mode with theme toggle, localStorage/cookie persistence, anti-FOUC script
- Add toast notification system with auto-dismiss and color-coded types
- Add api() fetch wrapper with auto JSON, X-Socket-ID, and error toasts
- Add keyboard shortcuts (/ search, b boards, ? help, n new card, Esc close)
- Add error page with status code and navigation
- Add focus trap utility and apply to CardModal with full ARIA dialog support
- Add hamburger menu for mobile, responsive columns, fullscreen card modal on mobile
- Add aria-labels to icon-only buttons and DnD live region
- Migrate all ~30 fetch calls to api() wrapper with success toasts
- Add dark: Tailwind variants to all 20+ pages and components

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 01:09:17 -05:00
Catherine Renelle 6ed0349507 Phase 7: Search, filters, templates, and archive UI
Add full-text card search (PostgreSQL tsvector + GIN index) with navbar
SearchBar, client-side board filters (label/assignee/due date), board
templates (3 system templates + save-as-template API), and archive
toggle for both board listing and board view.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 00:42:20 -05:00
Catherine Renelle e5f2c64e14 Phase 6: Activity log and notifications
Add activity logging to all write API routes, notification system with
real-time delivery via Socket.IO, @mention parsing in comments, activity
feed sidebar on board page, per-card activity in card modal, and
notification bell with unread badge in the navbar.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 00:26:15 -05:00
Catherine Renelle e61c549ddb Phase 5: Real-time updates via Socket.IO
Wire Socket.IO broadcast from all write API routes so board changes
propagate instantly to other connected clients. Add session-based auth
on socket connections, in-memory presence tracking, and a presence UI
in the board header showing who else is viewing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 00:03:13 -05:00