Context is Everything logo

5. Workflows

Overview

All core business workflows in Sasha Studio, documenting triggers, actors, preconditions, steps, state transitions, side effects, and failure handling.


1. User Registration (First User)

Trigger: POST /api/auth/register
Actor: First visitor (no users exist)
Precondition: users table is empty

Steps:

  1. Client submits username + password
  2. Server checks user count = 0 (rejects if users exist)
  3. Password hashed with bcrypt
  4. User created with is_admin = 1
  5. JWT token generated (no expiry)
  6. Token returned to client

State transitions: No users → one admin user
Side effects: None
Failure: If users already exist, returns 403


2. User Login

Trigger: POST /api/auth/login
Actor: Any registered user
Precondition: Account exists and is active

Steps:

  1. Client submits username + password
  2. Server looks up user by username
  3. bcrypt compare password against hash
  4. If match: update last_login, generate JWT, return token
  5. If no match: return 401 "Invalid credentials"

State transitions: last_login updated
Side effects: None
Failure: Invalid credentials → 401, account disabled → 403


3. Password Reset

Trigger: POST /api/auth/forgot-password
Actor: Any user (unauthenticated)
Precondition: User exists, Postmark configured

Steps:

  1. User submits email/username
  2. Server generates random token, stores SHA-256 hash in password_resets
  3. Email sent via Postmark with reset link
  4. User clicks link → GET /api/auth/reset-password/verify validates token
  5. User submits new password → POST /api/auth/reset-password
  6. Token marked as used (used_at set), password hash updated

State transitions: password_resets.used_at set, users.password_hash updated
Side effects: Email sent via Postmark
Failure: Invalid/expired token → 400, Postmark failure → 500 (logged)


4. Onboarding Flow

Trigger: First login after registration, or navigating to /onboarding
Actor: Admin user (typically)
Precondition: User authenticated, no company profile exists

Steps:

  1. Screen 1 -- Company Introduction

    • User enters company name or website URL
    • Auto-detection of company from URL (optional)
    • POST /api/profile/organization/initialize creates company_profiles record
  2. Screen 2 -- Claude API Key

    • User provides Anthropic API key
    • POST /api/setup/configure-claude stores key
    • POST /api/setup/test-claude-key validates
    • Can skip (limited functionality)
  3. Screen 3 -- Live Learning

    • POST /api/profile/organization/research/:projectId starts Claude research
    • Claude researches the company using the name/URL
    • Real-time streaming updates via GET /api/profile/organization/research/:projectId/stream
    • Results stored in research_documents table
    • POST /api/profile/onboarding/complete marks complete

State transitions:

  • company_profiles.research_status: pending → researching → completed
  • company_profiles.onboarding_completed: 0 → 1

Side effects: Claude API calls for research, files created in project directory
Failure: API key invalid → step 2 error, research fails → can retry or skip


5. Chat Session

Trigger: User sends message in chat interface
Actor: Authenticated user
Precondition: Claude CLI configured, project selected

Steps:

  1. User types message in ChatInterface
  2. Message sent via WebSocket to server
  3. Server spawns/reuses Claude CLI process via node-pty
  4. System prompt injected via --append-system-prompt:
    • Active persona context
    • Applied guides
    • Permission mode instructions
    • AskUserQuestion instructions
  5. User message piped to Claude CLI stdin
  6. Claude CLI processes request (may use tools: file read/write, bash, etc.)
  7. Response streamed token-by-token via WebSocket back to client
  8. Session recorded in sessions table
  9. Exchange recorded in raw_exchanges table
  10. Usage metrics recorded in usage_events table
  11. Response quality signals computed and stored asynchronously

State transitions: New sessions record if first message, new raw_exchanges per turn
Side effects: Claude API costs incurred, files may be modified by tool use
Failure: Claude CLI crash → error message to user, WebSocket disconnect → reconnect attempt


6. File Upload

Trigger: POST /api/files/:projectName/upload-documents
Actor: Authenticated user
Precondition: Project exists

Steps:

  1. User selects files via file picker or drag-drop
  2. Files uploaded via multipart/form-data (multer)
  3. Server validates file size against configurable limit (default 50MB)
  4. Files written to project directory using safePath()
  5. Document conversion if applicable (Word → HTML → Markdown via mammoth/turndown)
  6. File tree cache invalidated
  7. Success response with file metadata

State transitions: New files on filesystem
Side effects: Disk space consumed
Failure: File too large → 413, invalid path → 400, disk full → 500


7. Skill Execution

Trigger: POST /api/skills/:name/run or scheduled execution
Actor: Authenticated user or scheduler
Precondition: Skill exists as SKILL.md in .claude/skills/

Steps:

  1. Skill markdown loaded from filesystem
  2. If workflow (has kind: agent-flow/workflow), multi-step execution plan created
  3. On-demand schedule created if needed
  4. Claude CLI invoked with skill content as prompt
  5. Execution logged in executions table
  6. Result captured (output file, status, tokens used)
  7. Schedule updated with last_run_at and last_status

State transitions: executions record created, schedule metadata updated
Side effects: Claude API costs, possible file modifications
Failure: Skill not found → 404, execution timeout → status 'timeout', Claude error → status 'failed'


8. Scheduled Prompt Execution

Trigger: Cron expression match (evaluated by node-cron)
Actor: Scheduler service (system)
Precondition: Schedule enabled, cron expression set

Steps:

  1. Scheduler evaluates all enabled schedules every minute
  2. When cron matches: generate deterministic execution_id from sha256(schedule_id + slot)
  3. Check idempotency: UNIQUE(schedule_id, scheduled_for) prevents duplicates
  4. Create execution_history record with status 'running'
  5. POST to /api/cron/execute-prompt (localhost only)
  6. Claude CLI executes the prompt
  7. Result captured: status, tokens, output file, duration
  8. execution_history updated: status → completed/failed/timeout
  9. Schedule's last_run_at and last_status updated

State transitions: execution_history: running → completed/failed/timeout
Side effects: Claude API costs, output files created, JSONL log appended
Failure: Timeout (default 5 min) → status 'timeout', stale detection for orphaned 'running' records


9. Cloud Drive Connection

Trigger: Admin configures cloud drive in settings
Actor: Admin user
Precondition: OAuth provider configured

Steps:

  1. Admin creates cloud provider (type: onedrive/sharepoint/gdrive)
  2. Admin creates cloud connection with provider
  3. OAuth flow initiated: GET /api/auth/:provider/start
  4. User authorizes in OAuth popup
  5. Callback received: GET /api/auth/:provider/callback
  6. Tokens encrypted (AES-256-GCM) and stored in cloud_credentials
  7. Connection status: pending → authorized
  8. Admin creates mount point (path, access mode, VFS profile)
  9. rclone remote configured and mounted
  10. Mount health_status: unmounted → mounting → mounted

State transitions:

  • cloud_connections.status: pending → authorized
  • cloud_mounts.health_status: unmounted → mounting → mounted

Side effects: rclone process started, VFS cache created
Failure: OAuth denied → status remains 'pending', mount fails → health_status 'degraded'


10. Meeting Transcription

Trigger: POST /api/meetings/start
Actor: Authenticated user
Precondition: Meeting service configured

Steps:

  1. User starts meeting capture
  2. Audio segments captured and transcribed
  3. Transcript segments accumulated
  4. User can get real-time advice via POST /api/meetings/advise-now
  5. User stops meeting: POST /api/meetings/stop
  6. Full transcript available: GET /api/meetings/transcript
  7. Analysis triggered: POST /api/meetings/analyze
  8. Claude analyzes transcript content
  9. Analysis results returned

State transitions: Meeting status: idle → active → analyzing → complete
Side effects: Claude API costs for analysis
Failure: Transcription service unavailable → error status


11. User Management (Admin)

Trigger: Admin actions in user management panel
Actor: Admin user
Precondition: Admin privileges

Steps (Create User):

  1. Admin fills create user form (username, password, admin flag)
  2. POST /api/admin/users
  3. Password hashed with bcrypt
  4. User record created
  5. Optional: POST /api/admin/users/:id/welcome-email sends welcome via Postmark

Steps (Delete User):

  1. Admin clicks delete on user row
  2. Confirmation dialog shown
  3. DELETE /api/admin/users/:id
  4. User record deleted (CASCADE deletes related records)

State transitions: User created/updated/deleted
Side effects: Welcome email may be sent
Failure: Duplicate username → 409, email send failure → logged but not blocking


12. AI Provider Switch

Trigger: Admin configures AI provider in admin panel
Actor: Admin user

Steps (Bedrock Setup):

  1. Admin opens AI Provider configuration
  2. Enters AWS credentials (access key, secret key, region)
  3. POST /api/admin/bedrock/configure → credentials encrypted and stored
  4. POST /api/admin/bedrock/test → validates connection
  5. POST /api/admin/bedrock/switch-model → selects active model
  6. Optional: enable 1M context mode with acknowledgment audit

State transitions: bedrock_config single row created/updated
Side effects: bedrock_context_audit record if 1M context toggled
Failure: Invalid credentials → test fails, model unavailable → validation error


13. Git Operations

Trigger: User actions in Git panel
Actor: Authenticated user

Steps (Commit & Push):

  1. User views changed files via GET /api/git/status
  2. User views diffs via GET /api/git/diff
  3. Optional: POST /api/git/generate-commit-message for AI-generated message
  4. User writes commit message and commits: POST /api/git/commit
  5. User pushes: POST /api/git/push

State transitions: Git repository state changes
Side effects: Remote repository updated on push
Failure: Merge conflicts → shown in UI, push rejected → error message


14. CLAUDE.md Version Management

Trigger: User edits CLAUDE.md via rules panel
Actor: Authenticated user

Steps:

  1. GET /api/rules/claude-md loads current content
  2. User edits content in editor
  3. PUT /api/rules/claude-md saves new version
  4. Server computes SHA-256 hash of content
  5. New prompt_versions record created (scope: 'user' or 'project')
  6. Previous version's is_active set to 0
  7. claudeMdWatcher picks up file change for live sessions

State transitions: New prompt_versions record, old version deactivated
Side effects: Active Claude CLI sessions pick up new CLAUDE.md
Failure: Write permission error → 500


15. API Key Management

Trigger: User manages API keys in settings
Actor: Authenticated user

Steps (Create):

  1. User provides key name and optional callback URL
  2. POST /api/api-keys/
  3. Server generates random API key with sk_ prefix
  4. Key hashed with bcrypt and stored in api_keys
  5. HMAC signing secret generated for callback verification
  6. Full key returned to user (shown once, never again)

Steps (Use):

  1. External system sends request with X-API-Key: sk_... header
  2. authenticateApiKey middleware looks up key by trying bcrypt compare
  3. If valid: request proceeds, last_used_at updated
  4. If invalid: 401 returned

State transitions: api_keys record created, last_used_at updated on use
Side effects: None
Failure: Key not found → 401, key deactivated → 401