team_id is kept in all three tables — drop deferred until app code
is fully migrated off team_id references.
Tables: script_builder_sessions, script_templates, script_generations
Backfill: user_id/created_by → users.account_id
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
psa_post_log: backfill via psa_connection, fallback to posted_by user
psa_member_mappings: backfill via psa_connection
notification_logs: backfill via notification_config
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Backfill from rater/user's account_id (not the step's account_id).
This is an explicit design decision — step rating data is attributed
to the account that performed the rating.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs: add tenant data isolation design spec
Complete architecture plan for multi-tenant data isolation across
all layers (PostgreSQL RLS, application-layer filtering, schema
migration, testing strategy, and phased rollout checklist).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs: add background job isolation policy to tenant isolation spec
Documents policy for all 5 existing background jobs:
- Knowledge Flywheel and PSA Retry flagged for account_id threading
- Chat Retention already follows correct pattern (model for others)
- Maintenance Schedule Firing needs account_id in queries + Session creation
- AI Conversation Expiry approved as cross-tenant with justification
Adds approved cross-tenant query registry and Phase 2 checklist items.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs: add tenant isolation Phase 0 implementation plan
8 tasks covering: CRITICAL copilot hotfix, tenant_filter() helper,
get_tenant_context dependency, analytics/category/AI session gap fixes,
full UUID endpoint audit, TargetList dead code audit, teams orphan
check, and CI grep check for missing tenant filters.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: add tenant_filter() helper and get_tenant_context dependency
tenant_filter(model, account_id) is the canonical app-layer tenant
scoping expression. Every query on a tenant table must use it.
build_tree_access_filter and build_step_visibility_filter updated
to call tenant_filter() internally for the account_id match.
get_tenant_context is a FastAPI dependency that returns account_id
or raises 403 if the user has no account — prevents raw access to
current_user.account_id and centralises the null check.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: scope analytics/flows/{tree_id} to requesting account
Any authenticated user could read flow analytics (session counts,
completion rates, CSAT) for any tree UUID. Now returns 404 if the
tree doesn't belong to the requesting account.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: scope category tree_count to requesting account
tree_count on GET /categories/{id} was including trees from all
accounts, leaking cross-tenant row counts.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: restrict AI session search to current user only
Search endpoint used OR(user_id, account_id), exposing other users'
problem_summary and problem_domain within the same account. Sessions
are user-scoped only — cross-user access requires explicit escalation
or sharing. List and search endpoints now behave consistently.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: add ownership check and 404 responses to ai-sessions endpoints
Cross-tenant isolation audit found:
- retry-psa-push had NO ownership check (CRITICAL) — any user could retry any session's PSA push
- save_task_lane used db.get() without ownership filter, returned 403 revealing existence
- get_session returned 403 instead of 404 for unauthorized access
- stream_documentation returned 403 instead of 404
All now use query-level user_id filtering and return 404 to avoid revealing existence.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: return 404 instead of 403 for cross-tenant session access
All session endpoints (get, update, complete, scratchpad, variables, export,
ticket-link) now return 404 instead of 403 when a user tries to access
another user's session. This prevents confirming existence of resources
across tenant boundaries.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: return 404 instead of 403 for cross-tenant tree access
get_tree and update_tree now return 404 when a user cannot access a tree
(private tree from another account). Prevents confirming resource existence
across tenant boundaries.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: return 404 instead of 403 for cross-tenant step access
get_step_or_404 now returns 404 when can_view_step or can_edit_step fails,
preventing confirmation of step existence across tenant boundaries.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: return 404 instead of 403 for cross-tenant upload access
get_upload_url and delete_upload now return 404 when the upload belongs to
a different account/user, preventing resource existence confirmation.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: return 404 instead of 403 for cross-tenant share access
revoke_share and create_share now return 404 when the caller is not the
owner, preventing resource existence confirmation across users.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: return 404 instead of 403 for cross-team tree access in maintenance schedules
_get_tree_or_403 now returns 404 when the user's team does not match,
preventing confirmation of tree existence across teams.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: return 404 instead of 403 for cross-account tag access
get_tag now returns 404 for account-specific tags that belong to another
account, preventing resource existence confirmation.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: return 404 instead of 403 for cross-account step category access
get_step_category now returns 404 for account-specific categories that
belong to another account, preventing resource existence confirmation.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* test: add cross-tenant isolation tests for Task 6 UUID audit
Tests cover:
- Tree GET/PUT returns 404 for cross-account access
- Session GET returns 404 for cross-user access
- AI session GET returns 404 for cross-user access
- AI session retry-psa-push requires ownership
- Upload URL returns 404 for cross-account access
- Share revoke returns 404 for cross-user access
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: return 404 (not 403) for get_documentation cross-user access; add missing Task 6 tests
get_documentation was revealing session existence via 403. Added pre-check
query filtering by session_id AND user_id before calling the engine.
Also add cross-tenant isolation tests for steps, tags, step_categories,
and maintenance_schedules endpoints fixed in Task 6 (TDD was skipped).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: address Task 6 quality review — rename helper, restore 403 for intra-account, add docs test
- Rename _get_tree_or_403 → _get_tree_or_404 in maintenance_schedules.py
(function now raises 404, old name was misleading)
- Restore HTTP 403 for intra-account permission failures in update_tree:
same-account users who can see a tree but can't edit it got 404 (wrong);
only cross-account lookups should return 404 to avoid confirming existence
- Apply same 403/404 distinction to update_tree_visibility
- Add test: get_documentation must return 404 for cross-user session access
- Add comment documenting owner-only design for documentation endpoints
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore: Task 7+8 — TargetList audit, CI tenant-filter grep check
Task 7: TargetList dead code audit
- Found active code references in 12+ files across backend and frontend
(full CRUD API + frontend page + MaintenanceScheduleSection + BatchLaunchModal)
- Decision: migrate to account_id in Phase 1 (cannot drop)
- DB row count not available from code-server — must verify from VPS SSH
before Phase 1 migration
- Teams orphan check query documented; must run from VPS SSH before Phase 1
- Results documented in spec Section 9
Task 8: CI tenant-filter enforcement check (warn mode)
- Create backend/scripts/check_tenant_filters.py
Scans endpoint and service files for select() on tenant tables without
tenant_filter/account_id/user_id in surrounding context. Currently
reports 109 warnings (Phase 1 backlog). Exits 0 (warn mode).
- Add Check tenant filter enforcement step to backend CI job
Add --fail flag after Phase 1 backlog clears to make it blocking.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs: record Phase 0 audit results — 0 orphaned teams, 0 target_list rows
Both checks confirmed 2026-04-09 from production DB.
Phase 1 migration is safe to proceed.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs: add tenant data isolation design spec
Complete architecture plan for multi-tenant data isolation across
all layers (PostgreSQL RLS, application-layer filtering, schema
migration, testing strategy, and phased rollout checklist).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs: add background job isolation policy to tenant isolation spec
Documents policy for all 5 existing background jobs:
- Knowledge Flywheel and PSA Retry flagged for account_id threading
- Chat Retention already follows correct pattern (model for others)
- Maintenance Schedule Firing needs account_id in queries + Session creation
- AI Conversation Expiry approved as cross-tenant with justification
Adds approved cross-tenant query registry and Phase 2 checklist items.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs: add tenant isolation Phase 0 implementation plan
8 tasks covering: CRITICAL copilot hotfix, tenant_filter() helper,
get_tenant_context dependency, analytics/category/AI session gap fixes,
full UUID endpoint audit, TargetList dead code audit, teams orphan
check, and CI grep check for missing tenant filters.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: CRITICAL — scope copilot tree query to current account
A user who knew another account's tree UUID could start a copilot
conversation, causing the tree's full node structure, names, and
descriptions to be sent to the AI as part of the system prompt.
Fix: add account_id (or is_default / visibility='public') filter to
the tree SELECT in copilot_service.start_conversation(). Returns 404
for inaccessible trees. Test added in test_tenant_isolation_p0.py.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add DOCX MIME type to ALLOWED_DOCUMENT_TYPES in storage_service.py
- Add python-docx text extraction in _generate_ai_description
- Extract shared _store_document_content helper for PDF/DOCX
- Add python-docx>=1.1.0 to requirements.txt
- Add tests for docx upload acceptance and document fetch
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
PDF uploads were stored in S3 and had text extracted during upload, but
fetch_upload_images() filtered exclusively for image MIME types, so
document content never reached the AI.
- Add fetch_upload_documents() in storage_service.py to retrieve
extracted_content for PDFs and text files
- Update ai_sessions.py chat endpoint to call both fetch_upload_images
and fetch_upload_documents, injecting document text as context
- Add PDF text extraction in _generate_ai_description (pypdf)
- Add pypdf>=4.0.0 to requirements.txt
- Fix test_db teardown to avoid connection pool issues
- Add 5 tests for fetch_upload_documents
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The test was inserting a "Team Script" with team_id=NULL (since the
test user has no team), then expecting shared=true to return it.
SQL NULL=NULL is falsy, so the query correctly returned nothing.
Fix: create a team, assign it to the user, then test the filter.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- script_template.py: add server_default to ALL NOT NULL columns so
Base.metadata.create_all matches Alembic behavior for raw SQL INSERTs
- test_session_branches_api.py: fork_reason needs 5+ chars ("test" → "testing fork")
- test_scripts.py: engineers CAN create templates (assert 201, not 403)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- script_template.py: add server_default for requires_elevation,
is_gallery_featured, gallery_sort_order so Base.metadata.create_all
emits proper SQL DEFAULTs (test fixtures use raw SQL INSERT)
- session_branches.py: refresh fork_point after commit so JSONB options
field is loaded before Pydantic serialization
- test_session_branches_api.py: add status assertion on fork response
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Backend conftest.py was hardcoded to patherly_test but CI creates
resolutionflow_test — now reads DATABASE_URL env var first. E2E tests
had stale placeholder text, heading, and landing page assertions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds GET /outputs, PATCH /outputs/{id}, and POST /outputs/{id}/push
endpoints under /ai-sessions/{session_id}/, plus integration tests.
Router registered before ai_sessions to avoid path conflict.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds ResolutionOutputGenerator service that generates PSA ticket notes,
knowledge base article draft, and client summary on session resolve, plus
integration tests for generate_all and edit_output.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Four endpoints: create handoff (park/escalate), list handoff history,
claim session, and team queue. Two routers: session-scoped router with
prefix /ai-sessions/{session_id} and queue_router with prefix /ai-sessions.
queue_router registered before ai_sessions.router to avoid /{session_id}
path conflict on GET /ai-sessions/queue.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Unified park/escalate handoff management with snapshot generation,
AI diagnostic assessment for escalations (via _call_ai), claim workflow
that reactivates sessions, PSA push via existing psa_documentation_service,
and team queue query. Dual-writes to ai_sessions.escalation_package for
backward compatibility.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Pure function that assembles system prompt, cross-branch context,
history, and images for _call_ai — no DB access, no LLM calls.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implements branch lifecycle management for conversational branching:
create_root_branch, create_fork, switch_branch, mark_branch_status,
revive_branch, get_branch_tree, and build_cross_branch_context.
Five integration tests cover the full lifecycle from root creation
through forking, switching, dead-end marking, and tree retrieval.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Also fix bug in save_to_library: remove invalid 'language' kwarg
passed to ScriptTemplate constructor (column doesn't exist on model).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- POST /uploads: multipart upload with content-type/size validation, per-session limits, S3 storage
- GET /uploads/{id}/url: presigned download URL with account ownership check
- GET /uploads: list uploads for a session
- DELETE /uploads/{id}: delete with ownership enforcement (403 for non-owners)
- Returns 503 gracefully when STORAGE_ENDPOINT is not configured
- 15 integration tests covering auth, validation, 503 behavior, and ownership
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add super-admin-only backend endpoints for toggling is_gallery_featured and
gallery_sort_order on flows and scripts, plus a frontend GalleryManagementPage
with toggle switches, editable sort order fields, and name/featured filters.
13 integration tests; all pass.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implements a no-auth read-only API for the public templates gallery page:
- Schemas in schemas/public_templates.py (PublicFlowTemplate, PublicScriptTemplate, PublicGalleryResponse, PublicFlowDetail, PublicScriptDetail)
- Five endpoints under /api/v1/public/templates: listing, flow detail, script detail, categories with counts, full-text search
- Tree preview truncated to 3 levels max; script_body never exposed
- Rate limited at 30/minute; paginated with category/type/sort filters
- 25 passing integration tests covering feature flags, truncation, script body protection, search, categories, and 404 behavior
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: add 5 sidebar icon color concepts for UX review
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(ui): add semantic icon colors and updated icons to sidebar nav
Swap generic icons for more descriptive alternatives (Network, Wrench,
FileOutput, Library, Code2, Lightbulb) and assign each nav item a unique
semantic color for instant visual landmarks.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(ui): default Sessions page to Active tab, reorder tabs
Active sessions are what engineers care about most. Tab order is now
Active, Prepared, Completed, All.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: add sidebar grouping and AI naming concept mockups
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: add sidebar redesign context and decision summary
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: add sidebar redesign spec and implementation plan
Design spec covers: activity zone with daily stats + session feed,
nav grouping (Resolve/Build/Insights), AI split (FlowPilot + Flow Assist),
pinned flows removal. Implementation plan has 5 chunks, 12 tasks, 39 steps.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add sidebar stats Pydantic schemas
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* test: add failing tests for sidebar stats endpoint
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add sidebar stats endpoint with daily stats and activity feed
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add sidebar API client, stats bar, activity feed components
New components: SidebarStatsBar, SidebarActivityFeed, ActivityItem.
New API client for sidebar stats endpoint. Pulse-dot CSS animation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: restructure sidebar with stats bar, activity feed, and grouped nav
Dashboard-first layout with Resolve/Build/Insights groups.
AI split: FlowPilot (Resolve) + Flow Assist (Build).
Stats bar: Resolved/Active/In Session daily counters.
Activity feed: active sessions with CW ticket #, recent completions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor: remove pinned flows frontend (PinnedFlowsSection, store, API, pin buttons)
Removed: PinnedFlowsSection component, pinnedFlowsStore, pinnedFlows API client.
Cleaned: pin buttons from TreeGridView, TreeListView, TreeTableView.
Cleaned: favorites section from QuickStartPage, pin props from TreeLibraryPage.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add FlowAssistPage placeholder and /flow-assist route
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: real-time sidebar stats via session-changed events
Sidebar now refreshes stats when sessions are created or completed,
not just on page navigation. Uses window event bus pattern (same as
folder-changed events in codebase).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: live-ticking In Session timer using active session start times
SidebarStatsBar now computes active session elapsed time client-side
from started_at timestamps, ticking every 60s. Backend only returns
completed session minutes to avoid double-counting.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: sidebar In Session timer ticks every second and shows seconds
Timer now uses 1s interval (not 60s) and displays seconds when under
a minute so it matches the session timer in the flow UI.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: trigger PR environment redeploy
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* debug: add console.log to SidebarStatsBar for timer investigation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: parse sidebar timestamps as UTC (append Z suffix)
Backend returns naive UTC timestamps without timezone indicator.
JS Date() treats bare ISO strings as local time, causing the timer
to compute negative elapsed time (future timestamps). Appending 'Z'
forces UTC parsing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: rename 'In Session' to 'Total Time' for clarity
Makes it clear the timer is an aggregate of all sessions today,
not just the current one.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Complete Script Generator feature including:
Backend:
- ScriptCategory, ScriptTemplate, ScriptGeneration models
- ScriptTemplateEngine with substitution, filters, sanitization
- CRUD + share API endpoints with permission checks
- Integration tests for permissions and sharing
- Migration 057 with AD User Management seed templates
Frontend — Script Library:
- Browse templates with category tabs and search
- Configure pane with parameter form and script generation
- Script preview with live substitution and copy/download
- scriptGeneratorStore Zustand store
Frontend — Template Editor:
- Full CRUD form with metadata, script body (Monaco Editor), parameters
- ParameterSchemaBuilder with visual builder + JSON toggle
- ScriptManagePage with routing and nav link
Frontend — Parameter Detector:
- Client-side PowerShell parameter detection engine
- Detects script-level param() blocks and variable assignments
- Type inference from PS type annotations and value patterns
- ParameterDetectorStepper one-by-one review UI with accept/skip
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add _repair_tree() post-build pass that fixes structural issues caused by
placed-set race conditions: demotes decisions with <2 children to actions,
hoists orphaned children as siblings, converts dead-end actions to solutions
- Add validation gate at commit endpoint — rejects trees that fail validation
with a 422 and descriptive error messages instead of saving invalid trees
- Update test fixtures to create valid multi-node tree structures
- Frontend: initialize currentNodeId from tree's actual root ID instead of
hardcoded 'root', fixing "Invalid tree structure" for KB-generated trees
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add ability to close active sessions directly from the Session History
page via an inline popover with outcome selection and optional notes.
Adds two new outcomes: cancelled and resolved_externally.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: flexible intake — deferred variables + prepared sessions
Remove blocking intake form modal. Variables are now filled inline during
flow execution or pre-filled via prepared sessions. Adds PATCH /sessions/{id}/variables
endpoint, POST /sessions/prepare for session pre-staging, inline variable prompts
in StepDetail, editable Session Variables panel, and "Prepared for You" dashboard section.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: pass treeData directly to startSession to avoid stale state
setTree(treeData) hasn't committed when startSession runs immediately
after, so tree is still null and getStepsFromTree returns []. This
caused the step detail area to render empty on new session start.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: wire PrepareSessionModal entry point in Flow Library
Add "Prepare session" button (clipboard icon) to grid, list, and table
views for procedural/maintenance flows. Clicking fetches tree intake
fields and account members, then opens PrepareSessionModal.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add flow export/import backend (migration, endpoints, schemas)
Add .rfflow file export/import support:
- Migration 050: import_metadata JSONB column on trees
- GET /trees/{id}/export?format=json|xml endpoint
- POST /trees/import endpoint (creates draft, resolves categories/tags)
- FlowExportEnvelope, FlowImportRequest/Response schemas
- import_metadata field on TreeResponse
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add flow export/import frontend + backend tests
Frontend:
- ExportFlowModal with JSON/XML format selection + download
- ImportFlowModal with drag-drop file picker + preview step
- rfflowParser for client-side JSON/XML .rfflow parsing
- Export buttons on editor toolbar and library action menus
- Import button on library page next to Create New
- Provenance display for imported flows in editor
- flowTransfer API client + types
Backend:
- Fix regex->pattern deprecation in export endpoint
- 12 integration tests covering export, import, round-trip,
access control, tag/category creation, version validation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: remove XML export, JSON-only for .rfflow files
- Remove XML builder, format query param, and XML tests
- Simplify ExportFlowModal (no format picker)
- Simplify rfflowParser (JSON-only)
- Remove format field from schemas and types
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: match Flow Assist chat input to AI Assistant styling + strengthen one-question prompt
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add procedural flow support to AI chat builder (Flow Assist)
- Add procedural-specific system prompts (schema, interview protocol, response format)
- Dispatch prompts by flow_type: procedural/maintenance use flat steps schema, troubleshooting uses decision tree schema
- Parse [STEPS_UPDATE] and [INTAKE_FORM] markers in AI responses
- Add validate_generated_procedural_steps() validator
- Handle intake form extraction in AI chat import endpoint
- Add StaticStepsPreview component for procedural flow preview
- Update store and page to render correct preview by flow type
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add flow type selection to Flow Assist entry points
- CreateFlowDropdown now shows "Build with Flow Assist" under each flow type
- Library page "Flow Assist" button respects current type filter
- Clean up unused AIFlowBuilderModal references
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: update CLAUDE.md with AI chat builder and intake form learnings
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: refine assistant chat prompt for concise answers and focused questions
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: switch AI provider to Claude Sonnet 4.6 + add shift+enter hint to chat inputs
- Default AI_PROVIDER changed from gemini to anthropic
- AI_MODEL and AI_MODEL_ANTHROPIC updated to claude-sonnet-4-6
- Added "Shift + Enter for a new line" hint below all chat textareas
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: update CLAUDE.md with AI provider and chat input learnings
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: add editor-embedded Flow Assist design document
Design for replacing the standalone /ai/chat page with context-aware
AI side panels embedded in each editor (Troubleshooting + Procedural).
Covers ghost node suggestion system, output-based thresholds,
config-driven model routing, knowledge integration, and per-flow
chat persistence.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: add editor-embedded Flow Assist implementation plan
25-task plan across 9 phases covering backend foundation, frontend
infrastructure, tree/procedural editor integration, AI-assisted create,
old code removal, action-type dispatch, suggestion audit trail, and
build verification.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: use actual root node ID in orphan validation check
AI-generated trees use descriptive IDs (e.g., "verify-account-exists")
instead of "root", causing the root node to be falsely flagged as orphaned.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add config-driven AI model tier routing
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: extend AI chat session with tree_id and archived_at
Add tree_id FK (CASCADE) for editor-embedded sessions and archived_at
timestamp column to ai_chat_sessions table.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add AI suggestion audit trail table
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add action_type and focal_node_id to AI chat message API
- Add VALID_ACTION_TYPES literal and action_type/focal_node_id fields to
AIChatMessageRequest schema
- Add tree_id field to AIChatStartRequest schema for editor-embedded sessions
- Update send_message() signature with action_type and focal_node_id params
- Update start_chat_session() signature with tree_id param
- Pass new params through endpoints to service functions
- All new params have defaults so existing behavior is unchanged
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: route AI model selection through action-type config
Update get_ai_provider() to accept an optional model override parameter
(applied only to AnthropicProvider; Gemini always uses its own model).
Thread action_type-based model resolution through send_message() and
generate_final_tree() in the AI chat service.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add TypeScript types for editor-embedded AI
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add shared ContextMenu component
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add useEditorAI hook and editorAI API client
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add EditorAIPanel component with Chat and Suggestions tabs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: integrate AI panel, context menu, and ghost nodes in tree editor
- Add AI Assist panel toggle button to tree editor toolbar
- Wire EditorAIPanel alongside TreeEditorLayout with single-panel rule
- Thread onNodeContextMenu through TreeEditorLayout → FlowCanvas → FlowCanvasNode
- Add right-click context menu with Generate Branch, Explain Node, Delete actions
- Add ghost node detection (_suggestion flag) with dashed border + opacity styling
- Add Accept/Dismiss overlay buttons on ghost nodes for future suggestion handling
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: integrate AI panel, context menu, and ghost steps in procedural editor
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add AI prompt dialog and wire into CreateFlowDropdown
Replace navigation to /ai/chat with an inline AIPromptDialog modal
that collects a single prompt, generates a flow via the editor AI API,
imports it, and navigates to the editor with the AI panel open.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: add glassmorphism to AI prompt dialog + maintenance Flow Assist button
- Use .glass-card-static on AIPromptDialog card for consistent design system
- Add "Build with Flow Assist" button to maintenance section in CreateFlowDropdown
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: remove standalone Flow Assist page and old AI chat components
Remove the old /ai/chat page, AI wizard modal, and all associated
components/stores/types now replaced by the editor-embedded AI panel.
Deleted:
- AIChatBuilderPage, ai-chat/ components, aiChatStore, aiChat API, ai-chat types
- AIFlowBuilderModal, ai-builder/ components, aiFlowBuilderStore
Cleaned up:
- Router (removed /ai/chat route)
- Sidebar (removed Flow Assist nav item)
- MyTreesPage (removed AI builder modal and button)
- TreeLibraryPage (removed Flow Assist button)
- API and type barrel exports
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add delta response parsing and action-type prompt dispatch
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add AI suggestion audit trail endpoints
Create/list/resolve endpoints for tracking AI-applied changes to flows.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add APScheduler task to auto-archive stale AI chat sessions
Archives AI chat sessions with no activity for 30 days, runs daily at 3 AM.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: update project status for editor-embedded Flow Assist
- Add Editor-Embedded Flow Assist to CURRENT-STATE.md in-progress items
- Update CLAUDE.md: fix stale lessons (#41, #46), add new patterns (#47 editor AI architecture, #48 orphan validation)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: use correct model alias in AI_MODEL_TIERS standard tier
The dated model ID `claude-sonnet-4-6-20250514` was causing 502 errors.
Use the alias `claude-sonnet-4-6` which matches AI_MODEL_ANTHROPIC.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: send live flow context to AI Assist for full editor awareness
The AI panel now sends the current tree structure (troubleshooting) or
steps + intake form (procedural/maintenance) with each message. This
gives the AI full visibility into node details, questions, descriptions,
options, and intake form fields — not just the node ID.
- Backend: add flow_context param to schema, endpoint, and service
- Frontend: add getFlowContext callback to useEditorAI hook
- TreeEditorPage: passes treeStructure as flow context
- ProceduralEditorPage: passes steps + intakeForm as flow context
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: include flow name and description in AI Assist context
Both editors now send name and description alongside the flow structure,
so the AI can reference what the flow is about when responding.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: increase AI timeout to 120s and limit retries to 1
The 45s timeout was too short for generation tasks with full flow
context in the system prompt. The Anthropic SDK's default 2 retries
caused requests to hang for ~136s before failing. Now: 120s timeout
with max 1 retry = faster failure if it does timeout.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: wire AI-generated flow structures into editor stores
The useEditorAI hook was ignoring result.working_tree from AI responses,
so generated steps/trees never appeared in the editor. Now:
- useEditorAI calls onFlowUpdate when working_tree is present in response
- ProceduralEditorPage handles steps + intake form updates via replaceSteps
- TreeEditorPage handles tree structure updates via replaceTreeStructure
- Both stores have new bulk-replace methods for AI integration
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: add lessons learned for full-stack integration, Anthropic retries, model tiers
#49 Always verify frontend consumes backend response fields
#50 Anthropic SDK max_retries=1 to avoid 3× timeout
#51 AI model tier routing via settings.get_model_for_action()
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: move AI Assist panel to full-height side layout in both editors
The AI panel was nested inside the content area, only spanning the
step list / canvas section. Now it sits at the outermost flex level,
spanning the full page height alongside all content (toolbar,
collapsible sections, steps/canvas). This prevents the panel from
overlapping content and lets the editor area properly shrink.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: AI Assist panel as fixed right drawer (matching Copilot/Scratchpad)
Convert EditorAIPanel from in-flow flex child to fixed right-side drawer
overlay, same pattern as CopilotPanel and ScratchpadSidebar. The panel
is fixed at right:0 spanning full viewport height, and editor pages add
pr-[380px] padding when open so content shifts left without overlap.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: AI Assist panel sits below topbar with slide-in animation
- Panel now uses top:56px to sit below the app shell topbar instead of
covering it (matches the main-content grid cell area)
- Added slideInRight CSS animation for smooth drawer entrance
- Editor pages use dynamic paddingRight via PANEL_WIDTH constant
- ChatTab upgraded: markdown rendering, CopilotPanel-style message
bubbles, auto-focus input, Shift+Enter hint
- All borders use --glass-border for consistent glassmorphism
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: AI Assist panel as in-flow flex sibling (not fixed/overlay)
Replace fixed positioning with in-flow flex layout. The outermost div
is now a horizontal flex row: content column (flex-1 min-w-0) + panel
(w-[380px] shrink-0). When the panel opens, the content column
automatically shrinks — no padding hacks or z-index stacking needed.
This guarantees the content shifts left and stays fully visible.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: AI Copilot panel as in-flow flex sibling in session navigation pages
Changed CopilotPanel from fixed overlay to flex layout sibling so it
pushes main content instead of covering it during active sessions.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: remove duplicate CLAUDE.md lessons #47-48
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* chore: update Google Fonts to Bricolage Grotesque, IBM Plex Sans, JetBrains Mono
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: update Tailwind config to Slate & Ice theme colors and fonts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: update CSS variables and glass-card utilities for Slate & Ice theme
- Replace all color variables with Slate & Ice palette
- Add glass system vars (--glass-bg, --glass-blur, --shadow-float)
- Replace legacy glass-card with new variable-driven glass classes
- Add breatheGlow, bellWobble, slideDown, fadeInRight keyframes
- Update font references to IBM Plex Sans and Bricolage Grotesque
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: recolor BrandLogo to cyan gradient, split BrandWordmark for gradient Flow text
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: update TopBar with glassmorphism backdrop and cyan accent styling
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: update Sidebar with glassmorphism backdrop
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add ambient atmosphere gradient orbs behind app shell
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: update QuickStats and SessionsPanel with glass-card styling
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add WeeklyCalendar, QuickActions, OpenSessions, RecentActivity dashboard components
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: redesign dashboard layout with calendar, open sessions, and glass-card panels
New layout: greeting → calendar+actions → sessions+stats → activity
Replaces old QuickStats and SessionsPanel with new dashboard components
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: replace remaining purple hex references with ice-cyan accent
Sweep of hardcoded purple hex values (#818cf8, #6366f1) replaced with
new cyan accent (#06b6d4) in QuickActions, RecentActivity, QuickLaunch,
and SVG brand assets.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: update CLAUDE.md branding and design system for Slate & Ice Modern
Updated Last Updated date, branding section (fonts, colors, glass
utilities, atmosphere orbs), component styling rules, and Design System
section to reflect the new ice-cyan glassmorphism theme.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: add Slate & Ice Modern design doc and implementation plan
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: redesign login page with Slate & Ice Modern design system
Apply glassmorphism styling, atmosphere orbs, branded wordmark, and
consistent design tokens to match the updated app shell aesthetic.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: raise TopBar z-index so profile dropdown renders above main content
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add AI assistant with in-session copilot and standalone chat with RAG
Implements three-phase AI assistant feature:
- Phase 0: RAG infrastructure with pgvector embeddings, Voyage AI integration,
tree chunking service, and semantic search over team's flow library
- Phase 1: In-session copilot panel during flow navigation with contextual
AI help, current step awareness, and suggested related flows
- Phase 2: Standalone AI chat page with persistent conversation history,
pin/delete, and configurable retention policies (account-level)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add account management, email verification, AI fixes, and user guides
- Profile settings, account transfer, delete/leave account flows
- Email verification with JWT tokens and Resend integration
- AI assistant/copilot fixes: markdown rendering, shared RAG helpers,
token tracking, input refocus, model_validate usage
- User guides hub + detail pages with 13 topic guides
- Sidebar and top bar navigation for guides
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: prevent stale chunk errors after deployments
- Set Cache-Control no-cache on index.html in nginx so browsers always
fetch fresh chunk references after a deploy
- Auto-reload on chunk load failures (stale deploy detection) with
loop prevention via sessionStorage
- Show friendly "App Updated" message if auto-reload doesn't resolve it
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add email verification toggle to admin settings
Adds platform-level toggle to enable/disable email verification.
When disabled, the verification banner is hidden and the send
endpoint returns 403.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Frontend: suppress unused-vars ESLint errors for callback params in
MaintenanceFlowDetailPage and StepLibraryPage.
Backend: add autouse fixture to mock settings.ai_enabled=True in
test_ai_chat.py so tests pass in CI where no ANTHROPIC_API_KEY is set.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tests cover session create, send message with tree update, get session,
abandon, 404 on missing session, and 503 when AI disabled.
Fixed: ai_usage.conversation_id has FK to ai_conversations, not
ai_chat_sessions. Chat builder now passes conversation_id=None and
tracks session reference in extra_data.chat_session_id.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The google-genai SDK uses `client.aio.models.generate_content()` for
async calls, not `client.models.generate_content_async()` which doesn't
exist. Also removes the temporary /ai/provider-debug endpoint.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>