14 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Overview
This is DocuSeal - an open-source document filling and signing platform built with Ruby on Rails. The codebase is a brownfield Rails 7 application that provides secure digital document signing with PDF form building, multi-signer workflows, and API/webhook integrations.
Tech Stack
Backend:
- Ruby 3.4.2, Rails 7.x
- PostgreSQL/MySQL/SQLite (via DATABASE_URL)
- Sidekiq for background jobs
- Devise for authentication with 2FA support
- Cancancan for authorization
- HexaPDF for PDF generation and signing
Frontend:
- Vue.js 3 with Composition API
- TailwindCSS 3.4.17 + DaisyUI 3.9.4
- Shakapacker 8.0 (Webpack)
- Hotwire Turbo for Rails UJS
Storage:
- Active Storage with S3, Google Cloud, Azure, or local disk
- Supports multiple storage backends simultaneously
Common Commands
Development
# Start development server
bin/rails server
# Start with foreman (includes Sidekiq)
bundle exec foreman start -f Procfile.dev
# Run specific test
bundle exec rspec spec/path/to/spec.rb:line_number
# Run all tests
bundle exec rspec
# Lint Ruby
bundle exec rubocop -A
# Lint JavaScript/Vue
yarn eslint app/javascript/**/*.{js,vue} --fix
# Run database migrations
bin/rails db:migrate
# Setup database from scratch
bin/rails db:setup
Production
# Precompile assets
bin/rails assets:precompile
# Start production server
bundle exec puma -C config/puma.rb
# With Docker
docker run --name docuseal -p 3000:3000 -v.:/data docuseal/docuseal
Architecture
Core Models Hierarchy
Account (Tenant/Organization)
├── Users (Devise authentication)
├── Templates (Document templates with form fields)
│ ├── TemplateDocuments (PDF files)
│ └── TemplateFolders (Organization)
├── Submissions (Completed document workflows)
│ ├── Submitters (Signers/participants)
│ ├── CompletedDocuments (Final PDFs)
│ └── SubmissionEvents (Audit trail)
└── AccountConfig (Settings)
Key Concepts
Templates:
- WYSIWYG PDF form builder with 12 field types (Signature, Date, File, Checkbox, etc.)
- Supports PDF upload or HTML-based template creation
- Multiple submitters per template
- Field tagging system for dynamic content
Submissions:
- Multi-signer document workflows
- State tracking (pending → completed)
- Email notifications and reminders
- Document generation and signing
Submitters:
- Individual participants in a submission
- Can fill and sign specific fields
- Receive email invitations and reminders
- Support for 2FA and identity verification
Directory Structure
app/models/ - Core business logic
submission.rb,submitter.rb,template.rb- Main entitiesuser.rb,account.rb- Authentication and multi-tenancy- All models inherit from
ApplicationRecordwithstrip_attributes
app/controllers/ - Request handling
- RESTful controllers for templates, submissions, submitters
- API controllers under
app/controllers/api/ - Settings controllers for user/account configuration
app/javascript/ - Frontend code
application.js- Main entry point with Vue app initializationtemplate_builder/- PDF form builder UIelements/- Custom web components (Web Components + Vue)submission_form/- Multi-step signing interface
lib/ - Utility modules
submissions.rb,submitters.rb- Business logic helperspdf_utils.rb,pdfium.rb- PDF processingsend_webhook_request.rb- Webhook handling
config/ - Rails configuration
routes.rb- Main routing (includes API routes)database.yml- Database configurationshakapacker.yml- Webpack configuration
Authentication & Authorization
Authentication:
- Devise with modules: database_authenticatable, registerable, recoverable, rememberable, validatable, omniauthable, two_factor_authenticatable
- JWT tokens for API access
- OAuth support via omniauth
Authorization:
- Cancancan with
Abilityclass - Role-based access control via
AccountAccessmodel - Template and submission sharing via
TemplateSharing
PDF Processing
HexaPDF is used for:
- PDF generation from templates
- Form field rendering
- Digital signature embedding
- Signature verification
PDFium provides:
- PDF rendering and preview
- Document manipulation
- Multi-page handling
API Structure
Base URL: /api/v1/
Key Endpoints:
POST /templates- Create templatePOST /submissions- Start submission workflowGET /submissions/:id- Get submission statusPOST /submitters/:id/complete- Complete submitter workflowPOST /webhooks- Webhook events
Authentication: Bearer token in Authorization header
Webhooks
Events:
submission.created- New submission startedsubmission.completed- All signers finishedsubmitter.completed- Individual signer finishedtemplate.created- New template
Delivery: POST to configured URLs with JSON payload, retry with exponential backoff
Background Jobs (Sidekiq)
Queues:
default- General tasksmailers- Email deliverywebhooks- Webhook deliverypdf- PDF generation
Key Jobs:
SubmissionEmailJob- Send submission invitationsReminderJob- Send reminder emailsWebhookDeliveryJob- Deliver webhook eventsDocumentGenerationJob- Generate final PDFs
Database Schema
Core Tables:
accounts- Multi-tenancy rootusers- Devise authenticationtemplates- Document templatessubmissions- Document workflowssubmitters- Signers/participantscompleted_documents- Final signed PDFstemplate_documents- Template PDF files
Supporting Tables:
account_access- User permissionstemplate_sharing- Template sharing linkssubmission_events- Audit trailwebhook_events- Webhook delivery trackingemail_events- Email delivery tracking
Configuration
Environment Variables:
DATABASE_URL- Database connectionSECRET_KEY_BASE- Rails secretsAWS_*,GOOGLE_*,AZURE_*- Storage configsSMTP_*- Email deliveryREDIS_URL- Sidekiq backend
Feature Flags:
Docuseal.multitenant?- Multi-tenant modeDocuseal.pro?- Pro features enabled
Testing
RSpec with:
spec/models/- Model specsspec/requests/- API/request specsspec/system/- System/feature specsspec/factories/- FactoryBot factories
Helpers:
signing_form_helper.rb- Form signing utilitiesrails_helper.rb- Rails test configuration
BMAD Core Integration
This repository uses BMAD Core for AI-assisted development:
- Configuration:
.bmad-core/core-config.yaml - Tasks:
.bmad-core/tasks/(e.g.,create-doc.md,document-project.md) - Templates:
.bmad-core/templates/(e.g.,brownfield-prd-tmpl.yaml) - Agents:
.bmad-core/agent-teams/
Slash Commands:
/BMad:agents:pm- Product Manager agent/BMad:agents:dev- Developer agent
FloDoc Enhancement (Current Work)
Context: Transforming DocuSeal into a 3-portal cohort management system for training institutions.
Key Changes:
- New models:
Cohort,CohortEnrollment,Institution,Sponsor - Three portals: Admin, Student, Sponsor
- Workflow: Admin creates cohort → Students enroll → Admin verifies → Sponsor signs → Admin finalizes
- Excel export for cohort data (FR23)
- Custom UI/UX (not DaisyUI)
PRD Location: docs/prd.md
Important Files
README.md- Project overview and deploymentSECURITY.md- Security policyGemfile- Ruby dependenciespackage.json- JavaScript dependenciesconfig/routes.rb- All routes including APIapp/models/user.rb- Authentication modelapp/javascript/application.js- Frontend entry point
Gotchas
- Multi-tenancy: Check
Docuseal.multitenant?before assuming single-account mode - Storage: Active Storage configs in
config/storage.ymlandlib/load_active_storage_configs.rb - PDF Processing: HexaPDF requires proper license for commercial use
- Sidekiq: Requires Redis connection, configured via
REDIS_URL - Devise 2FA: Requires
devise-two-factorsetup per user - Vue + Rails: Uses Shakapacker, not standard Webpack config
- Email Templates: Stored in
app/views/mailers/, use ERB variables
Common Issues
Database errors: Run bin/rails db:setup or check DATABASE_URL
Asset compilation: Run bin/rails assets:precompile for production
Sidekiq not processing: Check Redis connection and config/sidekiq.yml
PDF generation fails: Verify HexaPDF installation and PDF permissions
Webhook delivery fails: Check network access and SSL certificates
FloDoc Enhancement - Current Development Workflow
Current Task: Creating comprehensive PRD for 3-portal cohort management system
Workflow Process:
- Section-by-Section PRD Creation - Following BMAD brownfield-prd-tmpl.yaml
- Advanced Elicitation - Each section requires user approval before proceeding
- Iterative Development - No implementation until complete PRD approval
Current Status: Starting fresh PRD creation
Section Sequence:
- ✅ Intro Analysis & Context (pending)
- ✅ Requirements (pending)
- ✅ Technical Constraints & Integration (pending)
- ✅ UI Enhancement Goals (pending)
- ✅ Epic & Story Structure (pending)
- ✅ Epic Details (pending)
Key Principles:
- No code changes until PRD is complete and approved
- Each section must be explicitly approved before moving to next
- BMAD template guides all sections
- Advanced elicitation for every section
Next Steps for FloDoc Enhancement
- Complete PRD - Section-by-section with user approval
- Architect Review - Winston reviews authentication strategy
- Database Migrations - Create cohorts, enrollments, institutions tables
- Portal Development - Build three Vue portals
- Workflow Integration - Connect to DocuSeal submission system
- Excel Export - Implement using rubyXL gem
- Testing - Add specs for cohort workflows
Brownfield PRD Story Structure
When writing stories in docs/prd.md during brownfield mode, STRICTLY adhere to Story 4.6 structure:
#### Story X.X: [Descriptive Title]
**Status**: Draft/Pending
**Priority**: High/Medium/Low
**Epic**: [Epic Name]
**Estimated Effort**: [X days]
**Risk Level**: Low/Medium/High
##### User Story
**As a** [role],
**I want** [action],
**So that** [benefit].
##### Background
[Context, requirements, and rationale for this story]
##### Technical Implementation Notes
**Vue 3 Component Structure:**
```vue
<!-- app/javascript/[portal]/views/[Component].vue -->
<template>
<!-- Component markup -->
</template>
<script setup>
// Component logic
</script>
<style scoped>
/* Component styles */
</style>
Pinia Store:
// app/javascript/[portal]/stores/[store].ts
import { defineStore } from 'pinia'
export const use[Store]Store = defineStore('[store]', {
state: () => ({
// State properties
}),
actions: {
// Async actions
},
getters: {
// Computed properties
}
})
API Layer:
// app/javascript/[portal]/api/[resource].ts
export const [Resource]API = {
async get[Resource](token: string): Promise<[Type]> {
// API implementation
}
}
Type Definitions:
export interface [Type] {
// Type properties
}
Design System Compliance:
Per FR28, all components must use design system assets from:
@.claude/skills/frontend-design/SKILL.md@.claude/skills/frontend-design/design-system/
Specifically: colors, icons, typography, and layout patterns from the design system.
Acceptance Criteria
Functional:
- ✅ [Functional requirement]
- ✅ [Functional requirement]
UI/UX:
- ✅ [UI/UX requirement]
- ✅ [UI/UX requirement]
Integration:
- ✅ [Integration requirement]
- ✅ [Integration requirement]
Security:
- ✅ [Security requirement]
- ✅ [Security requirement]
Quality:
- ✅ [Quality requirement]
- ✅ [Quality requirement]
Integration Verification (IV1-4)
IV1: API Integration
- [Verification steps]
IV2: Pinia Store
- [Verification steps]
IV3: Getters
- [Verification steps]
IV4: Token Routing
- [Verification steps]
Test Requirements
Component Specs:
// spec/javascript/[portal]/views/[Component].spec.js
import { mount, flushPromises } from '@vue/test-utils'
import [Component] from '@/[portal]/views/[Component].vue'
import { createPinia, setActivePinia } from 'pinia'
describe('[Component]', () => {
beforeEach(() => {
setActivePinia(createPinia())
})
it('[test description]', async () => {
// Test implementation
})
})
Integration Tests:
- [Integration test requirements]
E2E Tests:
- [E2E test requirements]
Rollback Procedure
If [failure scenario]:
- [Rollback step]
- [Rollback step]
Data Safety: [Explanation of atomic operations]
Risk Assessment
[Risk Level] because:
- [Risk reason 1]
- [Risk reason 2]
Specific Risks:
- [Risk Name]: [Risk description]
- [Risk Name]: [Risk description]
Mitigation:
- [Mitigation strategy 1]
- [Mitigation strategy 2]
Success Metrics
- [Metric 1]
- [Metric 2]
- [Metric 3]
**Key Rules:**
1. **Always** use `#####` (H5) for all story subsections (User Story, Background, etc.)
2. **Always** include Status, Priority, Epic, Estimated Effort, Risk Level
3. **Always** include Integration Verification section (IV1-4)
4. **Always** include Test Requirements with code examples
5. **Always** include Rollback Procedure
6. **Always** include Risk Assessment with specific risks and mitigations
7. **Always** include Success Metrics
8. **Never** embed Acceptance Criteria inside User Story - use separate `##### Acceptance Criteria` section
9. **Always** use code blocks for Vue components, Pinia stores, API layers, and type definitions
10. **Always** reference design system compliance per FR28