Hartmut
1a8ed97d5e
Merge branch 'worktree-agent-a2939317'
2026-04-09 14:44:51 +02:00
Hartmut
b2c8d98b25
refactor(api): reorganise allocation router into allocation/ subdirectory
...
Moves read, assignment-procedures, assignment-mutations, and demand
procedures into allocation/ so the domain boundary is discoverable
without grep.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-09 14:44:17 +02:00
Hartmut
1df208dbcc
feat(timeline): add pulse animation for in-flight drag mutations
...
Allocation bars that have active optimistic overrides (post-drag,
awaiting server confirmation) now pulse subtly via animate-pulse.
The pending set is derived from the existing optimisticAllocations
map keys, requiring no additional state.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-09 13:28:46 +02:00
Hartmut
8c5be51251
feat(platform): checkpoint current implementation state
2026-04-01 07:42:03 +02:00
Hartmut
bcfb18393e
refactor(api): extract assistant vacation entitlement slice
2026-03-30 23:09:32 +02:00
Hartmut
45c25b17c1
refactor(api): extract assistant country read slice
2026-03-30 22:53:59 +02:00
Hartmut
0cc7b9805a
refactor(api): extract assistant planning navigation slice
2026-03-30 22:51:39 +02:00
Hartmut
aed99cb894
refactor(api): extract assistant import export dispo slice
2026-03-30 22:45:00 +02:00
Hartmut
4d8c91d705
refactor(api): extract assistant scenario rate-analysis slice
2026-03-30 22:38:01 +02:00
Hartmut
d55ab67e04
refactor(api): extract assistant audit-history slice
2026-03-30 22:30:51 +02:00
Hartmut
ab32c7804b
refactor(api): extract assistant comments slice
2026-03-30 22:29:07 +02:00
Hartmut
73fdf1c6ab
refactor(api): extract assistant dashboard insights slice
2026-03-30 22:23:05 +02:00
Hartmut
6c6afdd059
refactor(api): extract assistant blueprint rate-card slice
2026-03-30 22:17:41 +02:00
Hartmut
e1496064e0
refactor(api): extract assistant resource slice
2026-03-30 22:13:42 +02:00
Hartmut
279eb24e5a
refactor(api): extract assistant staffing demand slice
2026-03-30 22:07:44 +02:00
Hartmut
1568efab30
refactor(api): extract assistant project slice
2026-03-30 22:04:28 +02:00
Hartmut
91ab7898e9
refactor(api): extract assistant estimate slice
2026-03-30 21:57:16 +02:00
Hartmut
18ba6fff9a
refactor(api): extract assistant notifications slice
2026-03-30 21:49:49 +02:00
Hartmut
fec4aa2e23
refactor(api): extract assistant user admin slice
2026-03-30 21:33:49 +02:00
Hartmut
7d3c6d978e
refactor(api): extract assistant self-service slice
2026-03-30 21:31:06 +02:00
Hartmut
72394747f9
refactor(api): extract assistant config readmodels
2026-03-30 21:27:23 +02:00
Hartmut
9571d454d4
refactor(api): extract assistant chargeability and country slices
2026-03-30 21:19:16 +02:00
Hartmut
447d42acb8
refactor(api): extract assistant tool admin slices
2026-03-30 20:56:00 +02:00
Hartmut
a19d2cbae0
refactor(settings): adopt environment-only runtime secret flow
2026-03-30 19:55:06 +02:00
Hartmut
f0bea6235d
fix(web): reuse project combobox in timeline popovers
2026-03-30 13:34:59 +02:00
Hartmut
58824545fc
fix(assistant): align tool metadata with router audiences
2026-03-30 13:18:00 +02:00
Hartmut
019c267435
test(api): harden estimate races and user auth boundaries
2026-03-30 12:32:51 +02:00
Hartmut
649c8feb22
fix(api): harden broadcast transactions and estimate fallbacks
2026-03-30 12:18:10 +02:00
Hartmut
6a6e98b5f7
fix(api): harden broadcast and assistant fallback errors
2026-03-30 12:03:27 +02:00
Hartmut
7aa32f8a5c
test(api): harden assistant tool error handling
2026-03-30 11:51:59 +02:00
Hartmut
978cd9184d
test(assistant): align admin tool descriptions
2026-03-30 11:45:29 +02:00
Hartmut
819345acfa
feat(platform): harden access scoping and delivery baseline
2026-03-30 00:27:31 +02:00
Hartmut
00b936fa1f
feat(assistant): extend audit and import parity
2026-03-29 12:56:29 +02:00
Hartmut
47e4d701ff
chore(repo): checkpoint current capakraken implementation state
2026-03-29 12:47:12 +02:00
Hartmut
beae1a5d6e
feat(assistant): add approval inbox and e2e hardening
2026-03-29 10:10:59 +02:00
Hartmut
4f48afe7b4
feat(planning): ship holiday-aware planning and assistant upgrades
2026-03-28 22:49:28 +01:00
Hartmut
1fc1e9f24c
feat: AI security controls + PostgreSQL hardening (Week 1 Quick Wins)
...
AI Security (EGAI 4.3.1.3, 4.3.1.4, 4.1.3.1, IAAI 3.6.26):
- AI Disclaimer banner in ChatPanel: "AI responses may be inaccurate"
- "AI Generated" violet badge on: chat messages, AI summaries,
project narratives, AI-generated cover images
- HITL: system prompt now requires explicit user confirmation
before any data mutation (strongly worded instruction)
- Mutation tool audit logging: all 31 write tools logged with
tool name, params, userId, userRole via Pino
PostgreSQL Hardening (PG Standard V1.6):
- Audit logging: log_connections, log_disconnections, log_statement=ddl,
log_min_duration_statement=1000 in docker-compose
- SUPERUSER removal script: scripts/harden-postgres.sh
(NOSUPERUSER + minimal GRANT for app user)
- Health check: pg_isready -U capakraken -d capakraken
- Documentation: security-architecture.md Section 12 updated
Controls closed: EGAI 4.1.3.1, 4.3.1.3, 4.3.1.4, PG 3.3, 3.5
Co-Authored-By: claude-flow <ruv@ruv.net >
2026-03-27 16:18:35 +01:00
Hartmut
9d43e4b113
feat: ACN Application Security Standard V7.30 compliance (19/23 items)
...
CRITICAL — Authentication & Access:
- TOTP MFA: otpauth-based, QR setup UI, sign-in flow integration,
admin disable override, /account/security self-service page
- Session Timeouts: 8h absolute (maxAge), 30min idle (updateAge)
- Failed Auth Logging: Pino warn for invalid password/user/totp,
info for successful login, audit entries for all auth events
- Concurrent Session Limit: ActiveSession model, oldest-kick strategy,
max 3 per user (configurable in SystemSettings)
CRITICAL — HTTP Security:
- HSTS: max-age=31536000; includeSubDomains
- CSP: script/style/img/font/connect-src with Gemini/OpenAI whitelist
- X-XSS-Protection: 0 (CSP replaces legacy)
- Auth page cache: no-store, no-cache, must-revalidate
- Rate Limiting: 100/15min general API, 5/15min auth (Map-based)
Data Protection:
- XSS Sanitization: DOMPurify on comment bodies
- autocomplete="new-password" on all password/secret fields
- SameSite=Strict on all cookies (Credentials-only, no OAuth)
- File Upload Magic Bytes validation (PNG/JPEG/WebP/GIF/BMP/TIFF)
Logging & Monitoring:
- Login/Logout audit entries (Auth entityType)
- External API call logging with timing (OpenAI, Gemini)
- Input validation failure logging at warn level
- Concurrent session tracking in ActiveSession table
Documentation:
- docs/security-architecture.md (11 sections)
- docs/sdlc.md (CI pipeline, security gates, incident response)
- .gitea/PULL_REQUEST_TEMPLATE.md (security checklist)
Schema: User.totpSecret/totpEnabled, SystemSettings.sessionMaxAge/
sessionIdleTimeout/maxConcurrentSessions, ActiveSession model
Tests: 310 engine + 37 staffing pass. TypeScript clean.
Co-Authored-By: claude-flow <ruv@ruv.net >
2026-03-27 14:16:39 +01:00
Hartmut
cd78f72f33
chore: full technical rename planarchy → capakraken
...
Complete rename of all technical identifiers across the codebase:
Package names (11 packages):
- @planarchy/* → @capakraken/* in all package.json, tsconfig, imports
Import statements: 277 files, 548 occurrences replaced
Database & Docker:
- PostgreSQL user/db: planarchy → capakraken
- Docker volumes: planarchy_pgdata → capakraken_pgdata
- Connection strings updated in docker-compose, .env, CI
CI/CD:
- GitHub Actions workflow: all filter commands updated
- Test database credentials updated
Infrastructure:
- Redis channel: planarchy:sse → capakraken:sse
- Logger service name: planarchy-api → capakraken-api
- Anonymization seed updated
- Start/stop/restart scripts updated
Test data:
- Seed emails: @planarchy.dev → @capakraken.dev
- E2E test credentials: all 11 spec files updated
- Email defaults: @planarchy.app → @capakraken.app
- localStorage keys: planarchy_* → capakraken_*
Documentation: 30+ .md files updated
Verification:
- pnpm install: workspace resolution works
- TypeScript: only pre-existing TS2589 (no new errors)
- Engine: 310/310 tests pass
- Staffing: 37/37 tests pass
Co-Authored-By: claude-flow <ruv@ruv.net >
2026-03-27 13:18:09 +01:00
Hartmut
bf3751f667
fix: invert shoring ratio logic — higher offshore = better
...
The shoring indicator logic was backwards. In the business context,
higher offshore = more cost-efficient = GOOD.
Inverted logic:
- Green: offshore >= threshold (target met, e.g. >= 55%)
- Yellow: offshore close to threshold (threshold-10 to threshold)
- Red: offshore below threshold (too little offshore, too expensive)
Updated:
- ShoringIndicator: getSeverity() inverted, badge text updated
- ProjectModal: "Max Offshore" renamed to "Min Offshore" with new tooltip
- AI Tool: status text reflects "target met" vs "below target"
- Tool description: "higher offshore is better, threshold is minimum"
Co-Authored-By: claude-flow <ruv@ruv.net >
2026-03-26 13:07:36 +01:00
Hartmut
92a982b151
feat: Nearshore-Ratio indicator per project
...
Engine (packages/engine):
- calculateShoringRatio() pure function: onshore/offshore hours,
country breakdown, threshold check, weighted by hours not headcount
- 12 unit tests: empty, 100% onshore/offshore, mixed ratios,
custom threshold, case-insensitive, unknown country, FTE weighting
Schema:
- Project.shoringThreshold (default 55%) — per-project configurable
- Project.onshoreCountryCode (default "DE") — configurable onshore country
API (project router):
- getShoringRatio query: loads assignments with resource.country,
computes ratio, returns full breakdown
- update mutation: accepts shoringThreshold + onshoreCountryCode
UI:
- ShoringIndicator: stacked horizontal bar with country segments,
severity badge (green/yellow/red), hover tooltip, dark theme
- ShoringBadge: mini colored dot + % for project list column
- ProjectModal: "Max Offshore %" number input
- Project detail: indicator after budget status card
- Project list: "Shoring" column (default hidden, toggleable)
AI Assistant:
- get_shoring_ratio tool: human-readable breakdown with threshold alert
Colors: green (<threshold-10), yellow (threshold-10 to threshold), red (>=threshold)
Default: 55% offshore threshold, "DE" as onshore country
Co-Authored-By: claude-flow <ruv@ruv.net >
2026-03-26 11:45:50 +01:00
Hartmut
e5d7ca1293
refactor: rename Planarchy to CapaKraken (branding only)
...
User-facing rename across 20 files:
- Layout title/meta: "CapaKraken — Resource & Capacity Planning"
- Sidebar logo: "CapaKraken" with "RESOURCE & CAPACITY PLANNING"
- Sign-in page: "CapaKraken Control Center", "Sign in to CapaKraken"
- PWA manifest: name + short_name
- PDF reports: footer text
- Install prompt: "Install CapaKraken"
- AI assistant system prompt
- Webhooks test payload
- Email subject lines
- Tooltips, descriptions, empty states
NOT changed (technical identifiers):
- Package names (@planarchy/*)
- Import paths
- Database names
- Docker container names
- localStorage keys
- Domain URLs
- CLAUDE.md
Co-Authored-By: claude-flow <ruv@ruv.net >
2026-03-25 21:46:15 +01:00
Hartmut
cb46bfbd85
fix: cap AI tool result size to prevent JSON parse errors
...
When generating multiple cover images in one conversation, the
accumulated tool results (each ~400KB base64) caused the OpenAI
conversation payload to exceed JSON parsing limits in the browser.
Fix:
- Strip coverImageUrl from invalidate action results (not needed by AI)
- Cap invalidate results to 4KB
- Cap all tool results to 8KB
- Prevents "JSON.parse: unexpected character" errors during batch ops
Co-Authored-By: claude-flow <ruv@ruv.net >
2026-03-23 18:35:57 +01:00
Hartmut
e766309c6c
fix: AI assistant generate_project_cover now uses configured provider
...
The tool was hardcoded to only check isDalleConfigured(), ignoring
Gemini even when it was the configured image provider. This caused
"DALL-E is not configured" errors for all 13 projects.
Fix: reads imageProvider from SystemSettings and routes to Gemini
or DALL-E accordingly (same logic as the generateCover mutation).
Co-Authored-By: claude-flow <ruv@ruv.net >
2026-03-23 18:01:16 +01:00
Hartmut
835ed6ef27
fix: correct Gemini model names + add model dropdown
...
Corrected model names (per Google AI docs):
- gemini-2.5-flash-image (was gemini-2.0-flash-preview-image-generation)
- gemini-3-pro-image-preview (Nano Banana Pro)
- gemini-3.1-flash-image-preview (Nano Banana 2)
UI: replaced text input with dropdown selector showing all 3 models
with human-readable descriptions.
Default changed to gemini-2.5-flash-image (fast, high-volume).
AI Assistant: generate_project_cover tool description updated to be
provider-agnostic (works with both DALL-E and Gemini).
Co-Authored-By: claude-flow <ruv@ruv.net >
2026-03-23 17:46:41 +01:00
Hartmut
47b2aeec72
feat: prevent duplicate resource-project assignments
...
Engine (packages/engine):
- New checkDuplicateAssignment() pure function: detects same resource
assigned to same project with overlapping dates
- 15 unit tests covering: overlap, no-overlap, cancelled, self-exclude,
string dates, PROPOSED status
Application layer (packages/application):
- createAssignment: throws CONFLICT before DB write if duplicate found
- fillDemandRequirement: same check before entering transaction
AI Assistant (packages/api/router/assistant-tools.ts):
- create_allocation: checks before creating, returns helpful error message
- fill_demand: same check using demand's projectId
UI (apps/web):
- AllocationModal: amber warning when resource already assigned to
selected project with overlapping dates (non-blocking)
Database cleanup:
- Found and merged 1 duplicate: Wong Wong on Porsche Taycan Sport Film
(2 overlapping PROPOSED assignments merged into 1)
Regression: 298 engine tests pass (283 + 15 new). TypeScript clean.
Co-Authored-By: claude-flow <ruv@ruv.net >
2026-03-23 08:51:49 +01:00
Hartmut
66878f18f4
feat: Activity History system — full audit coverage, UI, AI tools
...
Infrastructure (Phase 1):
- AuditLog schema: add source, entityName, summary fields + index
- createAuditEntry() helper: auto-diff, auto-summary, fire-and-forget
- auditLog query router: list, getByEntity, getTimeline, getActivitySummary
Audit Coverage (Phase 2 — 14 routers, 50+ mutations):
- vacation: create, approve, reject, cancel, batch ops (8 mutations)
- user: create, updateRole, setPermissions, resetPermissions (5 mutations)
- entitlement: set, bulkSet (3 mutations)
- client: create, update, delete, batchUpdateSortOrder
- org-unit: create, update, deactivate
- country: create, update, createCity, updateCity, deleteCity
- management-level: createGroup, updateGroup, createLevel, updateLevel, deleteLevel
- settings: updateSystemSettings (sensitive fields sanitized), testSmtp
- blueprint: create, update, updateRolePresets, delete, batchDelete, setGlobal
- rate-card: create, update, deactivate, addLine, updateLine, deleteLine, replaceLines
- calculation-rules: create, update, delete
- effort-rule: create, update, delete
- experience-multiplier: create, update, delete
- utilization-category: create, update
Admin UI (Phase 3):
- /admin/activity-log page with global searchable timeline
- Filters: entity type, action, user, date range, text search
- Expandable before/after diff view per entry
- Summary cards showing top entity types by change count
- EntityHistory reusable component for entity detail pages
- Sidebar nav link with clock icon
AI Assistant (Phase 4):
- query_change_history tool: "Who changed project X?"
- get_entity_timeline tool: "What happened to resource Y?"
Regression: 283 engine + 37 staffing tests pass. TypeScript clean.
Co-Authored-By: claude-flow <ruv@ruv.net >
2026-03-22 22:39:30 +01:00
Hartmut
046d16dd97
feat: add 12 new AI assistant tools for Sprint 1-5 features
...
New HartBOT tools:
- detect_anomalies: budget burn, staffing gaps, utilization, timeline risks
- get_skill_gaps: skill supply vs demand analysis
- get_project_health: 3-dimension health scoring per project
- get_budget_forecast: burn rate + exhaustion date per project
- get_insights_summary: anomaly counts by category
- run_report: dynamic report queries (resource/project/assignment)
- list_comments / create_comment / resolve_comment: collaboration
- lookup_rate: rate card lookup by client/chapter/level
- simulate_scenario: what-if staffing simulation (read-only)
- generate_project_narrative: AI executive summary generation
All tools follow existing patterns: assertPermission() gating,
ctx.db for Prisma queries, __action: "invalidate" for mutations.
Co-Authored-By: claude-flow <ruv@ruv.net >
2026-03-20 07:45:56 +01:00
Hartmut
e7b74f13bd
refactor: consolidate duplicated code across web and API packages
...
- Extract shared render helpers (vacation blocks, range overlay, overbooking blink) into renderHelpers.tsx
- Centralize status badge styles and vacation color maps into status-styles.ts
- Extract dragMath.ts utility from useTimelineDrag for reuse
- Split useInvalidatePlanningViews into useInvalidateTimeline (4 queries) + useInvalidatePlanningViews (8 queries)
- Adopt findUniqueOrThrow() and Prisma select constants across API routers
- Add shared fmtEur() helper for API-side money formatting
- Wrap TimelineResourcePanel and TimelineProjectPanel with React.memo
- Fix pre-existing TS2589 deep type errors in TeamCalendar and VacationModal
- 38 files changed, reducing ~400 lines of duplicated code
Co-Authored-By: claude-flow <ruv@ruv.net >
2026-03-19 00:10:08 +01:00
Hartmut
d0f04f13f8
feat: enterprise notification & task management system
...
Phase N.1 — Data Model:
- Extend Notification model with category, priority, task fields (status, action,
assignee, dueDate, completedAt/By), reminder fields (remindAt, recurrence,
nextRemindAt), and targeting metadata (sourceId, senderId, channel)
- Add NotificationCategory, NotificationPriority, TaskStatus enums
- Add NotificationBroadcast model for group notifications
- Shared types with parseTaskAction()/buildTaskAction() helpers
Phase N.2 — API:
- Extend notification router: listTasks, taskCounts, updateTaskStatus,
createReminder/update/delete/list, createBroadcast/listBroadcasts,
createTask, assignTask, delete
- Broadcast targeting: resolve recipients by user/role/project/orgUnit/all
- Task-action registry: approve_vacation, reject_vacation, confirm_assignment
- Reminder scheduler: 60s poll interval, recurring support, catch-up on start
- SSE events: TASK_ASSIGNED, TASK_COMPLETED, TASK_STATUS_CHANGED,
REMINDER_DUE, BROADCAST_SENT
Phase N.3 — AI Assistant:
- 7 new tools: list_tasks, get_task_detail, update_task_status,
execute_task_action, create_reminder, create_task_for_user, send_broadcast
- execute_task_action dispatches to task-action registry with per-action
permission checks, marks tasks as completed by AI
Phase N.4 — Frontend:
- Enhanced NotificationBell with task badge, tabs (All/Tasks/Reminders)
- TaskCard component with priority badges, due dates, action buttons
- ReminderModal for creating/editing personal reminders
- BroadcastModal for targeted group notifications (manager+)
- NotificationCenter full-page with 5 tabs and bulk actions
- TaskWidget dashboard widget showing open tasks
- Admin broadcast management page
- AppShell nav links for Notifications and Broadcasts
- SSE hook handlers for task/reminder events
Phase N.5 — Auto-Tasks:
- Vacation create → APPROVAL tasks for all managers
- Vacation approve/reject → mark approval tasks as DONE
- Demand create → TASK for managers to fill staffing needs
Co-Authored-By: claude-flow <ruv@ruv.net >
2026-03-18 11:51:49 +01:00