mirror of https://github.com/docusealco/docuseal
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1011 lines
41 KiB
1011 lines
41 KiB
# <!-- Powered by BMAD™ Core -->
|
|
|
|
## Status
|
|
|
|
**Approved**
|
|
|
|
---
|
|
|
|
## Story
|
|
|
|
**As a** system administrator,
|
|
**I want** to create and manage training institutions with multiple admin users (super and regular admins),
|
|
**so that** private training institutions can manage their cohorts independently.
|
|
|
|
---
|
|
|
|
## Acceptance Criteria
|
|
|
|
1. Database schema for institutions and admin roles exists
|
|
2. Super admins can create institutions and invite other admins
|
|
3. Regular admins can manage cohorts within their institution
|
|
4. Admins cannot access other institutions' data
|
|
5. Role-based permissions are enforced at API and UI levels
|
|
|
|
---
|
|
|
|
## Tasks / Subtasks
|
|
|
|
### Database Setup (AC: #1) - WINSTON'S ARCHITECTURAL REVISION
|
|
|
|
#### **Critical: 4-Layer Data Isolation Foundation**
|
|
- [ ] **Migration 1: Add institution_id to account_access**
|
|
- [ ] Add `institution_id` reference to `account_accesses` table (nullable initially)
|
|
- [ ] Add foreign key constraint: `fk_account_accesses_to_institutions`
|
|
- [ ] Backfill existing data: Link users to their institution via account
|
|
- [ ] Make non-nullable: `change_column_null :account_access, :institution_id, false`
|
|
- [ ] Add unique index: `[user_id, institution_id]` (prevents duplicate roles)
|
|
|
|
- [ ] **Migration 2: Update institutions table**
|
|
- [ ] Add fields: account_id, name, registration_number, address, contact_email, contact_phone, super_admin_id, settings
|
|
- [ ] Add indexes: account_id (unique), registration_number (unique within account), super_admin_id
|
|
- [ ] Add foreign key: super_admin_id → users.id
|
|
|
|
- [ ] **Migration 3: Create cohort_admin_invitations table**
|
|
- [ ] Add fields: email, hashed_token, token_preview, role, institution_id, sent_at, expires_at, used_at, created_by_id
|
|
- [ ] Add indexes: institution_id, email, expires_at
|
|
- [ ] **Important:** Store SHA-256 hashed tokens, never plaintext
|
|
|
|
- [ ] **Migration 4: Update account_access roles**
|
|
- [ ] Add cohort_admin and cohort_super_admin to role enum
|
|
- [ ] Add index on role for performance
|
|
|
|
- [ ] **Rollback Strategy (CRITICAL)**
|
|
- [ ] Test rollback on production-like data
|
|
- [ ] Document step-by-step rollback procedure
|
|
- [ ] Verify no data loss during rollback
|
|
|
|
### Models (AC: #1, #2, #3, #4) - WINSTON'S 4-LAYER ISOLATION
|
|
|
|
#### **Layer 1: Institution Model (Foundation)**
|
|
- [ ] Create `app/models/institution.rb`
|
|
- [ ] Add belongs_to :account
|
|
- [ ] Add belongs_to :super_admin (class_name: 'User')
|
|
- [ ] Add has_many :cohorts
|
|
- [ ] Add has_many :sponsors
|
|
- [ ] Add has_many :account_accesses (NEW - critical for isolation)
|
|
- [ ] Add validations (name, registration_number, uniqueness within account)
|
|
- [ ] **CRITICAL SCOPE:** `scope :for_user, ->(user) { where(id: user.institutions.select(:id)) }`
|
|
- [ ] **CRITICAL SCOPE:** `scope :managed_by, ->(user) { where(super_admin_id: user.id) }`
|
|
- [ ] **CRITICAL METHOD:** `def accessible_by?(user) account_accesses.exists?(user_id: user.id) end`
|
|
|
|
#### **Layer 2: User Model Extension**
|
|
- [ ] Extend `app/models/user.rb` (add to existing)
|
|
- [ ] Add has_many :account_accesses, dependent: :destroy
|
|
- [ ] Add has_many :institutions, through: :account_accesses
|
|
- [ ] Add has_many :managed_institutions, class_name: 'Institution', foreign_key: 'super_admin_id'
|
|
- [ ] **CRITICAL METHOD:** `def can_access_institution?(institution) institutions.exists?(institution.id) || managed_institutions.exists?(institution.id) end`
|
|
- [ ] **CRITICAL METHOD:** `def cohort_super_admin? account_accesses.exists?(role: 'cohort_super_admin') end`
|
|
- [ ] **CRITICAL METHOD:** `def cohort_admin? account_accesses.exists?(role: 'cohort_admin') end`
|
|
|
|
#### **Layer 3: Account Access Model (Security Core)**
|
|
- [ ] Extend `app/models/account_access.rb`
|
|
- [ ] Add belongs_to :institution (NEW - critical for isolation)
|
|
- [ ] Add cohort_admin and cohort_super_admin to role enum
|
|
- [ ] **CRITICAL VALIDATION:** `validates :user_id, uniqueness: { scope: :institution_id }`
|
|
- [ ] Add scopes: `cohort_admins`, `cohort_super_admins`, `for_institution(institution)`
|
|
|
|
#### **Layer 4: Invitation Token Model (Cryptographic Security)**
|
|
- [ ] Create `app/models/cohort_admin_invitation.rb`
|
|
- [ ] Add belongs_to :institution
|
|
|
|
- [ ] Add belongs_to :created_by, class_name: 'User'
|
|
- [ ] **CRITICAL:** Store `hashed_token` (SHA-256), never plaintext
|
|
- [ ] Add `token_preview` for debugging (first 8 chars + '...')
|
|
- [ ] **CRITICAL METHODS:**
|
|
- `def generate_token` - uses SecureRandom.urlsafe_base64(64)
|
|
- `def valid_token?(raw_token)` - validates hash + Redis single-use
|
|
- `def expired?` - checks expires_at
|
|
- `def used?` - checks used_at
|
|
- [ ] Validations: email format, role inclusion, expires_at presence
|
|
- [ ] Scopes: `active`, `used`, `cleanup_expired`
|
|
- [ ] **Rate limiting:** Max 5 pending invitations per email
|
|
|
|
#### **Layer 5: Security Event Model (Audit Trail)**
|
|
- [ ] Create `app/models/security_event.rb`
|
|
- [ ] Add user_id, event_type, ip_address, details (jsonb)
|
|
- [ ] Add indexes: user_id, event_type, created_at
|
|
- [ ] **CRITICAL METHOD:** `def self.log(event_type, user, details = {})`
|
|
|
|
### API Controllers (AC: #2, #3, #4, #5) - WINSTON'S 4-LAYER SECURITY
|
|
|
|
#### **Layer 1: API Base Controller Security Extensions**
|
|
- [ ] Extend `app/controllers/api/api_base_controller.rb`
|
|
- [ ] **CRITICAL:** Add `verify_institution_access` before_action
|
|
```ruby
|
|
def verify_institution_access
|
|
return true unless params[:institution_id].present?
|
|
institution = Institution.find_by(id: params[:institution_id])
|
|
unless institution && current_user.can_access_institution?(institution)
|
|
log_security_event(:unauthorized_institution_access)
|
|
render json: { error: 'Access denied to this institution' }, status: :forbidden
|
|
return false
|
|
end
|
|
true
|
|
end
|
|
```
|
|
- [ ] **CRITICAL:** Add `verify_institution_role(required_role)` method
|
|
- [ ] **CRITICAL:** Add `log_security_event(event_type, details)` method
|
|
- [ ] Add security event logging for all authorization failures
|
|
|
|
#### **Layer 2: Institutions Controller**
|
|
- [ ] Create `app/controllers/api/v1/institutions_controller.rb`
|
|
- [ ] Add `before_action :verify_institution_access` (except index/create)
|
|
- [ ] **Authorization:**
|
|
- `create` - requires cohort_super_admin role on account
|
|
- `update/destroy` - requires cohort_super_admin role + ownership
|
|
- `index/show` - requires any institution access
|
|
- [ ] Implement actions with 4-layer isolation:
|
|
```ruby
|
|
def index
|
|
@institutions = Institution.for_user(current_user) # Layer 1 scope
|
|
end
|
|
|
|
def show
|
|
@institution = Institution.for_user(current_user).find(params[:id]) # Layer 1 + 2
|
|
end
|
|
```
|
|
- [ ] Add strong parameters with validation
|
|
- [ ] Add error handling with security event logging
|
|
|
|
#### **Layer 3: Admin Invitations Controller**
|
|
- [ ] Create `app/controllers/api/v1/admin/invitations_controller.rb`
|
|
- [ ] **CRITICAL:** Rate limiting - max 5 pending invitations per email
|
|
- [ ] **CRITICAL:** Redis-backed single-use token enforcement
|
|
- [ ] Actions:
|
|
- `create` - cohort_super_admin only, email validation, rate limit
|
|
- `index` - scoped to institution, cohort_admin+ access
|
|
- `revoke` - cohort_super_admin only, mark used_at
|
|
- [ ] **CRITICAL:** Use `InvitationService` for business logic
|
|
- [ ] Email delivery via `CohortAdminInvitationJob` (async)
|
|
|
|
#### **Layer 4: Invitation Acceptance Controller**
|
|
- [ ] Create `app/controllers/api/v1/admin/invitation_acceptance_controller.rb`
|
|
- [ ] **CRITICAL:** Token validation with Redis single-use check
|
|
- [ ] Email verification (token only valid for matching email)
|
|
- [ ] Create `AccountAccess` record on successful acceptance
|
|
- [ ] One-time use only - immediate invalidation
|
|
|
|
#### **Layer 5: Security Event Controller (Monitoring)**
|
|
- [ ] Create `app/controllers/api/v1/admin/security_events_controller.rb`
|
|
- [ ] cohort_super_admin only access
|
|
- [ ] Filter by user, institution, event_type, date range
|
|
- [ ] Pagination support
|
|
- [ ] Export capability for audit purposes
|
|
|
|
### Web Controllers (AC: #2, #3)
|
|
- [ ] Create `app/controllers/cohorts/admin_controller.rb`
|
|
- [ ] Add authentication and role checks
|
|
- [ ] Implement institution list, new, create, show actions
|
|
- [ ] Add invite form handling
|
|
- [ ] Add routes to `config/routes.rb`
|
|
- [ ] Add API routes under `/api/v1/cohorts/`
|
|
- [ ] Add web routes under `/cohorts/admin/`
|
|
|
|
### Frontend Components (AC: #2, #3)
|
|
- [ ] Create `app/javascript/cohorts/admin/InstitutionWizard.vue`
|
|
- [ ] Build form with all institution fields
|
|
- [ ] Add validation and error handling
|
|
- [ ] Connect to API client
|
|
- [ ] Add success/error notifications
|
|
- [ ] Create `app/javascript/cohorts/admin/AdminInviteModal.vue`
|
|
- [ ] Build invite form with role selection
|
|
- [ ] Add email validation
|
|
- [ ] Connect to invitation API
|
|
- [ ] Create `app/javascript/cohorts/admin/InstitutionList.vue`
|
|
- [ ] Display institutions table
|
|
- [ ] Add navigation to institution details
|
|
- [ ] Update `app/javascript/api/client.js`
|
|
- [ ] Add institution API methods
|
|
- [ ] Add invitation API methods
|
|
|
|
### Jobs & Mailers (AC: #2) - WINSTON'S ASYNCHRONOUS SECURITY
|
|
|
|
#### **Invitation Job Architecture**
|
|
- [ ] **Create `app/services/invitation_service.rb`**
|
|
```ruby
|
|
class InvitationService
|
|
def self.create_invitation(institution, email, role, created_by)
|
|
# Rate limiting check
|
|
pending = CohortAdminInvitation.where(email: email, institution: institution, used_at: nil)
|
|
.where('expires_at > ?', Time.current)
|
|
.count
|
|
raise RateLimit::LimitApproached if pending >= 5
|
|
|
|
invitation = CohortAdminInvitation.create!(
|
|
institution: institution,
|
|
email: email,
|
|
role: role,
|
|
created_by: created_by
|
|
)
|
|
|
|
# Async email delivery
|
|
CohortAdminInvitationJob.perform_async(invitation.id)
|
|
invitation
|
|
end
|
|
|
|
def self.accept_invitation(raw_token, accepting_user)
|
|
invitation = CohortAdminInvitation.active.find_by(token_preview: raw_token[0..8] + '...')
|
|
return nil unless invitation
|
|
return nil unless invitation.email == accepting_user.email
|
|
return nil unless invitation.valid_token?(raw_token)
|
|
|
|
# Atomic transaction
|
|
AccountAccess.create!(
|
|
account: invitation.institution.account,
|
|
user: accepting_user,
|
|
institution: invitation.institution,
|
|
role: invitation.role
|
|
)
|
|
|
|
invitation
|
|
end
|
|
end
|
|
```
|
|
|
|
- [ ] **Create `app/jobs/cohort_admin_invitation_job.rb`**
|
|
- [ ] `include Sidekiq::Job`
|
|
- [ ] `sidekiq_options queue: :mailers, retry: 5`
|
|
- [ ] Check invitation validity before sending
|
|
- [ ] Handle email delivery failures gracefully
|
|
- [ ] Log security event on successful delivery
|
|
|
|
#### **Mailer Architecture**
|
|
- [ ] **Create `app/mailers/cohort_mailer.rb`**
|
|
- [ ] Inherits from `ApplicationMailer`
|
|
- [ ] **CRITICAL:** Never include raw token in logs
|
|
- [ ] **CRITICAL:** Use HTTPS invitation URL
|
|
- [ ] **CRITICAL:** Token only in email, not in URL params
|
|
- [ ] Methods:
|
|
- `admin_invitation(invitation)` - sends invitation email
|
|
- `super_admin_demoted(user, institution)` - security notification
|
|
|
|
- [ ] **Email Templates** (`app/views/cohort_mailer/`)
|
|
- [ ] `admin_invitation.html.erb` - HTML version
|
|
- [ ] `admin_invitation.text.erb` - Plain text version
|
|
- [ ] **Security:** Include institution name, role, expiration
|
|
- [ ] **CTA:** Direct link to acceptance flow
|
|
- [ ] **Warning:** "Do not forward" disclaimer
|
|
|
|
#### **Additional Jobs**
|
|
- [ ] **Create `app/jobs/security_alert_job.rb`**
|
|
- [ ] Send immediate alerts for critical events
|
|
- [ ] Queue: `critical_security`
|
|
- [ ] Retry: 3 attempts max
|
|
|
|
- [ ] **Create `app/jobs/invitation_cleanup_job.rb`**
|
|
- [ ] Daily job to remove expired invitations
|
|
- [ ] Queue: `default`
|
|
- [ ] Retain for 1 week after expiration for audit
|
|
|
|
### Authorization & Security (AC: #4, #5) - WINSTON'S DEFENSE-IN-DEPTH
|
|
|
|
#### **4-Layer Security Architecture (MANDATORY)**
|
|
|
|
**Layer 1: Database-Level Security**
|
|
- [ ] **Foreign Key Constraints:** All relationships must have FK constraints
|
|
- [ ] **Unique Indexes:** `[user_id, institution_id]` on account_access
|
|
- [ ] **Scoped Queries:** ALL database queries use `Institution.for_user(user)`
|
|
- [ ] **Non-nullable:** institution_id on account_access after backfill
|
|
- [ ] **Test:** Verify SQL injection attempts fail
|
|
|
|
**Layer 2: Model-Level Security**
|
|
- [ ] **Update `lib/ability.rb` (Cancancan)**
|
|
```ruby
|
|
# Add to Ability.initialize
|
|
if user.cohort_super_admin?
|
|
can :manage, Institution, id: user.managed_institutions.select(:id)
|
|
can :manage, Cohort, institution_id: user.managed_institutions.select(:id)
|
|
can :manage, Sponsor, institution_id: user.managed_institutions.select(:id)
|
|
can :manage, CohortAdminInvitation, institution_id: user.managed_institutions.select(:id)
|
|
end
|
|
|
|
if user.cohort_admin?
|
|
can :read, Institution, id: user.institutions.select(:id)
|
|
can :manage, Cohort, institution_id: user.institutions.select(:id)
|
|
can :read, Sponsor, institution_id: user.institutions.select(:id)
|
|
end
|
|
```
|
|
- [ ] **User Model Methods:** Add `can_access_institution?`, `cohort_super_admin?`, `cohort_admin?`
|
|
- [ ] **Institution Model Methods:** Add `accessible_by?(user)` verification
|
|
- [ ] **Account Access Validation:** `validates :user_id, uniqueness: { scope: :institution_id }`
|
|
|
|
**Layer 3: Controller-Level Security**
|
|
- [ ] **API Base Controller Extensions:**
|
|
- [ ] `verify_institution_access` - checks institution_id parameter
|
|
- [ ] `verify_institution_role(role)` - checks role + institution
|
|
- [ ] `log_security_event(type, details)` - audit logging
|
|
- [ ] **All Controllers:** Add `before_action :verify_institution_access` where appropriate
|
|
- [ ] **Strong Parameters:** All controllers use strong params with validation
|
|
- [ ] **Error Handling:** 403 Forbidden for unauthorized access, log all attempts
|
|
|
|
**Layer 4: UI-Level Security**
|
|
- [ ] **Vue Route Guards:** Prevent manual URL navigation to unauthorized paths
|
|
- [ ] **API Client Validation:** Validate institution_id before sending requests
|
|
- [ ] **Context Storage:** Store institution context in Vuex, validate server-side
|
|
- [ ] **Role-Based UI:** Show/hide elements based on `cohort_super_admin?` / `cohort_admin?`
|
|
|
|
#### **Token Security Architecture (CRITICAL)**
|
|
|
|
**Cryptographic Token System:**
|
|
- [ ] **Token Generation:** `SecureRandom.urlsafe_base64(64)` - 512 bits entropy
|
|
- [ ] **Storage:** SHA-256 hash stored in database, never plaintext
|
|
- [ ] **Preview:** Store first 8 chars + '...' for debugging only
|
|
- [ ] **Single-Use:** Redis-backed enforcement with atomic operations
|
|
- [ ] **Expiration:** 24-hour default, configurable per invitation
|
|
- [ ] **Rate Limiting:** Max 5 pending invitations per email per institution
|
|
|
|
**Redis Enforcement:**
|
|
- [ ] **Setup:** Configure Redis connection in `config/initializers/redis.rb`
|
|
- [ ] **Atomic Operations:** Use `SET key value NX EX 86400` for single-use
|
|
- [ ] **Race Condition Prevention:** Concurrent requests handled correctly
|
|
- [ ] **TTL Management:** Automatic cleanup after expiration
|
|
|
|
**Invitation Flow Security:**
|
|
- [ ] **Email Verification:** Token only valid for matching email address
|
|
- [ ] **Domain Validation:** Optional email domain verification for institutions
|
|
- [ ] **Acceptance Controller:** One-time use, immediate invalidation
|
|
- [ ] **AccountAccess Creation:** Atomic transaction, rollback on failure
|
|
|
|
#### **Security Event Logging & Monitoring**
|
|
|
|
**Security Event Model:**
|
|
- [ ] **Create `app/models/security_event.rb`**
|
|
```ruby
|
|
class SecurityEvent < ApplicationRecord
|
|
belongs_to :user, optional: true
|
|
|
|
validates :event_type, presence: true
|
|
validates :ip_address, presence: true
|
|
|
|
def self.log(event_type, user = nil, details = {})
|
|
create!(
|
|
user: user,
|
|
event_type: event_type,
|
|
ip_address: details[:ip_address] || '0.0.0.0',
|
|
details: details.except(:ip_address)
|
|
)
|
|
end
|
|
end
|
|
```
|
|
|
|
**Event Types to Log:**
|
|
- [ ] `:unauthorized_institution_access` - Cross-institution access attempt
|
|
- [ ] `:insufficient_privileges` - Role-based access denied
|
|
- [ ] `:token_validation_failure` - Invalid/expired token attempt
|
|
- [ ] `:rate_limit_exceeded` - Too many invitation attempts
|
|
- [ ] `:invitation_accepted` - Successful admin invitation acceptance
|
|
- [ ] `:super_admin_demoted` - Role change that invalidates tokens
|
|
|
|
**Monitoring & Alerting:**
|
|
- [ ] **Alert Thresholds:**
|
|
- >5 unauthorized access attempts/hour → Security alert
|
|
- >20 token validation failures/hour → Potential attack
|
|
- Any super_admin demotion → Immediate notification
|
|
- [ ] **Dashboard:** Security events view for cohort_super_admin
|
|
- [ ] **Export:** CSV/PDF export for audit compliance
|
|
|
|
#### **Integration with Existing DocuSeal Security**
|
|
|
|
**Authentication Compatibility:**
|
|
- [ ] **Devise + JWT:** No changes to existing auth system
|
|
- [ ] **2FA Support:** Existing 2FA continues to work
|
|
- [ ] **API Tokens:** Existing access tokens unaffected
|
|
- [ ] **Session Management:** No changes to session handling
|
|
|
|
**Authorization Compatibility:**
|
|
- [ ] **Existing Abilities:** All existing CanCanCan abilities preserved
|
|
- [ ] **Additive Only:** New roles added to existing enum
|
|
- [ ] **Account Isolation:** Existing account-level isolation maintained
|
|
- [ ] **Template/Submission Access:** Existing permissions unchanged
|
|
|
|
**Data Isolation Compatibility:**
|
|
- [ ] **Account-Level:** Existing `account_id` isolation preserved
|
|
- [ ] **Institution-Level:** New `institution_id` isolation within accounts
|
|
- [ ] **Combined Scopes:** Queries must satisfy both levels
|
|
- [ ] **Backward Compatibility:** Existing data remains accessible
|
|
|
|
#### **Security Testing Requirements**
|
|
|
|
**Unit Tests:**
|
|
- [ ] **Model Scopes:** `Institution.for_user(user)` returns correct records
|
|
- [ ] **User Methods:** `can_access_institution?`, role checks work correctly
|
|
- [ ] **Token Security:** Hash generation, validation, single-use enforcement
|
|
- [ ] **Rate Limiting:** Max 5 invitations per email enforced
|
|
- [ ] **Validation:** Uniqueness constraints prevent duplicates
|
|
|
|
**Request Tests:**
|
|
- [ ] **Cross-Institution Access:** All endpoints tested with wrong institution_id
|
|
- [ ] **Role-Based Access:** Each role tested for allowed/denied actions
|
|
- [ ] **Token Security:** Reuse, expiration, wrong email scenarios
|
|
- [ ] **Security Events:** All violations logged correctly
|
|
- [ ] **Rate Limiting:** 429 responses when limit exceeded
|
|
|
|
**Integration Tests:**
|
|
- [ ] **Complete Invitation Flow:** Create → Email → Accept → Access
|
|
- [ ] **Concurrent Access:** Multiple users from different institutions
|
|
- [ ] **Race Conditions:** Token validation under load
|
|
- [ ] **Rollback Scenarios:** Migration rollback preserves security
|
|
|
|
**Security Audit:**
|
|
- [ ] **Penetration Testing:** Attempt cross-institution data access
|
|
- [ ] **Token Analysis:** Verify cryptographic strength
|
|
- [ ] **Redis Security:** Verify atomic operations prevent race conditions
|
|
- [ ] **OWASP Check:** Review for common vulnerabilities
|
|
|
|
#### **Deployment Security Checklist**
|
|
|
|
**Pre-Production:**
|
|
- [ ] **Security Audit:** Third-party review of token system
|
|
- [ ] **Penetration Test:** Attempt to breach data isolation
|
|
- [ ] **Performance Test:** Verify security doesn't degrade performance >10%
|
|
- [ ] **Rollback Test:** Verify security events persist after rollback
|
|
|
|
**Production Monitoring:**
|
|
- [ ] **Security Dashboard:** Real-time event monitoring
|
|
- [ ] **Alert System:** Immediate notification of violations
|
|
- [ ] **Audit Trail:** All events retained for compliance
|
|
- [ ] **Incident Response:** Documented procedure for security breaches
|
|
|
|
**Emergency Procedures:**
|
|
- [ ] **Token Revocation:** Ability to invalidate all pending invitations
|
|
- [ ] **Access Lockdown:** Emergency role removal capability
|
|
- [ ] **Data Breach Protocol:** Steps if isolation is compromised
|
|
- [ ] **Recovery Plan:** Restore security without data loss
|
|
|
|
### Integration Verification - WINSTON'S COMPREHENSIVE TESTING
|
|
|
|
#### **IV1: Existing DocuSeal Authentication Compatibility**
|
|
- [ ] **Test:** Existing user login flows work unchanged
|
|
- [ ] **Test:** JWT tokens work for legacy endpoints
|
|
- [ ] **Test:** 2FA continues to function normally
|
|
- [ ] **Test:** API access tokens unaffected
|
|
- [ ] **Test:** Session management unchanged
|
|
|
|
#### **IV2: Role System Compatibility**
|
|
- [ ] **Test:** Existing DocuSeal roles (member, admin) unaffected
|
|
- [ ] **Test:** New roles (cohort_admin, cohort_super_admin) are additive only
|
|
- [ ] **Test:** No conflicts between old and new role enums
|
|
- [ ] **Test:** Existing template/submission access unchanged
|
|
- [ ] **Test:** Account-level isolation preserved
|
|
|
|
#### **IV3: Performance Impact**
|
|
- [ ] **Benchmark:** Existing user operations before/after
|
|
- [ ] **Target:** <10% performance degradation on existing flows
|
|
- [ ] **Test:** Query performance with 1000+ institutions
|
|
- [ ] **Test:** Concurrent user load (100+ simultaneous)
|
|
- [ ] **Test:** Database query optimization (EXPLAIN ANALYZE)
|
|
|
|
#### **IV4: New Architecture Security (WINSTON'S MANDATORY)**
|
|
- [ ] **Test:** 4-layer isolation with malicious inputs
|
|
- [ ] Attempt cross-institution access via altered institution_id
|
|
- [ ] Test SQL injection attempts on scoped queries
|
|
- [ ] Verify 403 responses for all unauthorized attempts
|
|
- [ ] **Test:** Redis token enforcement under concurrent load
|
|
- [ ] 50 concurrent token validation attempts
|
|
- [ ] Race condition prevention verified
|
|
- [ ] Single-use enforcement works correctly
|
|
- [ ] **Test:** Security event logging captures all violations
|
|
- [ ] All 6 event types logged correctly
|
|
- [ ] IP address captured accurately
|
|
- [ ] Details JSON contains relevant information
|
|
- [ ] **Test:** Rate limiting prevents invitation spam
|
|
- [ ] 6th invitation attempt returns 429
|
|
- [ ] Counter resets correctly
|
|
- [ ] Per-email limit enforced per institution
|
|
- [ ] **Test:** Token security scenarios
|
|
- [ ] Token reuse attempts fail
|
|
- [ ] Expired tokens rejected
|
|
- [ ] Wrong email address rejected
|
|
- [ ] Concurrent same-token validation handled correctly
|
|
|
|
#### **IV5: Integration with Existing Features**
|
|
- [ ] **Test:** Template sharing works with new institutions
|
|
- [ ] **Test:** Submission workflows integrate correctly
|
|
- [ ] **Test:** Webhook delivery unaffected
|
|
- [ ] **Test:** Email notifications work for new roles
|
|
- [ ] **Test:** Export functionality includes new data
|
|
|
|
### Testing
|
|
- [ ] **Model Tests:** `spec/models/institution_spec.rb`
|
|
- [ ] Validations
|
|
- [ ] Associations
|
|
- [ ] Scopes (for_user)
|
|
- [ ] Data isolation
|
|
- [ ] **Request Tests:** `spec/requests/api/v1/institutions_spec.rb`
|
|
- [ ] Authentication requirements
|
|
- [ ] Authorization (super_admin only)
|
|
- [ ] Success/failure scenarios
|
|
- [ ] Error responses
|
|
- [ ] **System Tests:** `spec/system/institution_management_spec.rb`
|
|
- [ ] Institution creation flow
|
|
- [ ] Admin invitation flow
|
|
- [ ] Data isolation verification
|
|
- [ ] Role-based access control
|
|
|
|
---
|
|
|
|
## Dev Notes
|
|
|
|
### Overview
|
|
This is the **foundation story** for the entire 3-portal cohort management system. All subsequent stories depend on the institution and admin management infrastructure created here.
|
|
|
|
### Key Integration Points
|
|
|
|
**Existing DocuSeal Systems to Reference:**
|
|
- `app/models/user.rb` - Authentication patterns (Devise + 2FA)
|
|
- `app/models/account.rb` - Multi-tenancy structure
|
|
- `app/models/account_access.rb` - Role-based permissions (extend this)
|
|
- `app/controllers/api/api_base_controller.rb` - API authentication
|
|
- `lib/ability.rb` - Cancancan authorization rules
|
|
- `app/javascript/template_builder/` - Form builder integration patterns
|
|
|
|
**Critical Files for Implementation:**
|
|
- `config/routes.rb` - Add cohort management routes
|
|
- `app/javascript/api/client.js` - Add API methods
|
|
- `app/views/mailers/` - Email templates location
|
|
|
|
### Winston's Architecture Requirements (MANDATORY)
|
|
|
|
#### **4-Layer Data Isolation Foundation**
|
|
This is the **cornerstone** of the entire architecture. Without this, the story cannot proceed safely.
|
|
|
|
**Layer 1: Database Constraints**
|
|
- `account_access.institution_id` with FK constraint
|
|
- Unique index `[user_id, institution_id]`
|
|
- Non-nullable after backfill
|
|
|
|
**Layer 2: Model Scopes**
|
|
- `Institution.for_user(user)` - used in ALL queries
|
|
- `User.can_access_institution?(institution)` - verification method
|
|
- `Institution.accessible_by?(user)` - security check
|
|
|
|
**Layer 3: Controller Authorization**
|
|
- `verify_institution_access` before_action
|
|
- `verify_institution_role(role)` for role checks
|
|
- `log_security_event` for audit trail
|
|
|
|
**Layer 4: UI Validation**
|
|
- Vue route guards
|
|
- API client pre-validation
|
|
- Context-based access control
|
|
|
|
#### **Cryptographic Token Security**
|
|
- **Generation:** `SecureRandom.urlsafe_base64(64)` (512 bits)
|
|
- **Storage:** SHA-256 hash only, never plaintext
|
|
- **Enforcement:** Redis-backed single-use with atomic operations
|
|
- **Expiration:** 24-hour default, strict validation
|
|
|
|
#### **Security Event Logging**
|
|
- **Model:** `SecurityEvent` with user, event_type, ip_address, details
|
|
- **Events:** 6 types covering all security violations
|
|
- **Monitoring:** Real-time alerts for critical thresholds
|
|
- **Audit:** Export capability for compliance
|
|
|
|
#### **Integration Compatibility**
|
|
- **Additive Only:** No changes to existing DocuSeal schemas
|
|
- **Authentication:** Devise + JWT unchanged
|
|
- **Authorization:** Existing CanCanCan abilities preserved
|
|
- **Performance:** <10% degradation on existing operations
|
|
|
|
#### **Implementation Sequence (CRITICAL)**
|
|
1. ✅ **Database migrations** (institution_id on account_access)
|
|
2. ✅ **Model layer** (4-layer isolation foundation)
|
|
3. ✅ **Security layer** (token system + event logging)
|
|
4. ✅ **Controller layer** (authorization + validation)
|
|
5. ✅ **UI layer** (route guards + context management)
|
|
6. ✅ **Testing** (comprehensive security tests)
|
|
7. ✅ **Features** (invitation flow, CRUD operations)
|
|
|
|
**⚠️ DO NOT implement features before security foundation is complete and tested.**
|
|
|
|
### Technical Constraints (from Architecture)
|
|
|
|
**Must Follow:**
|
|
- Ruby 3.4.2, Rails 7.x exact versions
|
|
- Vue 3.3.2 with Composition API (`<script setup>`)
|
|
- TailwindCSS 3.4.17 (no DaisyUI for new portals)
|
|
- Existing RuboCop and ESLint configurations
|
|
- Additive database changes only (no modifications to existing tables)
|
|
- Follow existing naming conventions and patterns
|
|
|
|
**Integration Requirements:**
|
|
- **Authentication:** Extend existing Devise + JWT without modification
|
|
- **Database:** Additive schema changes only, maintain 100% backward compatibility
|
|
- **API:** Extend existing v1 endpoints, follow RESTful patterns
|
|
- **Authorization:** Use existing Cancancan, extend abilities
|
|
- **Email:** Leverage existing DocuSeal email infrastructure via Sidekiq
|
|
|
|
### Data Model Integration
|
|
|
|
**New Tables:**
|
|
```sql
|
|
institutions
|
|
- account_id (FK to accounts)
|
|
- name, registration_number, address
|
|
- contact_email, contact_phone
|
|
- super_admin_id (FK to users)
|
|
- settings (jsonb)
|
|
- timestamps
|
|
|
|
cohort_admin_invitations
|
|
- email, token, role
|
|
- institution_id (FK to institutions)
|
|
- sent_at, expires_at
|
|
- timestamps
|
|
```
|
|
|
|
**Modified Tables:**
|
|
```ruby
|
|
# account_access - extend enum
|
|
enum role: {
|
|
# Existing
|
|
member: 'member',
|
|
admin: 'admin',
|
|
# New
|
|
cohort_admin: 'cohort_admin',
|
|
cohort_super_admin: 'cohort_super_admin'
|
|
}
|
|
```
|
|
|
|
**Foreign Key Relationships:**
|
|
- institutions.account_id → accounts.id
|
|
- institutions.super_admin_id → users.id
|
|
- cohort_admin_invitations.institution_id → institutions.id
|
|
- account_access.account_id → accounts.id (existing)
|
|
|
|
### Performance Considerations
|
|
|
|
**Expected Query Patterns:**
|
|
- `Institution.for_user(user)` - scoped query
|
|
- `AccountAccess.cohort_admins` - role filtering
|
|
- `user.institutions` - association access
|
|
|
|
**Index Strategy:**
|
|
- institutions.account_id (unique)
|
|
- institutions.registration_number (unique)
|
|
- institutions.super_admin_id
|
|
- cohort_admin_invitations.token (unique, for lookup)
|
|
- account_access.role (for role queries)
|
|
|
|
### Security Requirements
|
|
|
|
**Data Isolation:**
|
|
- All queries must be scoped to current user's institution
|
|
- API endpoints must enforce institution-based authorization
|
|
- Cross-institution access attempts logged as security events
|
|
- Token-based invitations with expiration (24 hours recommended)
|
|
|
|
**Role Enforcement:**
|
|
- Super admins: institution creation, admin management, all cohorts
|
|
- Regular admins: cohort management within their institution only
|
|
- Unauthorized access returns 403 Forbidden
|
|
|
|
### Testing Standards
|
|
|
|
**Test File Locations:**
|
|
- Models: `spec/models/`
|
|
- Request/API: `spec/requests/api/v1/`
|
|
- System/Feature: `spec/system/`
|
|
- Jobs: `spec/jobs/`
|
|
- Mailers: `spec/mailers/`
|
|
|
|
**Test Frameworks:**
|
|
- RSpec for all tests
|
|
- FactoryBot for test data
|
|
- Capybara for system tests
|
|
- Shoulda matchers for model validations
|
|
|
|
**Test Requirements:**
|
|
- 80% minimum coverage on new code
|
|
- Test happy paths and error scenarios
|
|
- Test authorization at all levels
|
|
- Test data isolation thoroughly
|
|
- Include performance tests for large datasets
|
|
|
|
**Specific Test Scenarios:**
|
|
1. **Authentication:** Existing DocuSeal users unaffected
|
|
2. **Authorization:** Role-based access enforced
|
|
3. **Data Isolation:** No cross-institution access
|
|
4. **Validation:** All business rules enforced
|
|
5. **Integration:** Works with existing DocuSeal features
|
|
|
|
### Rollback Strategy
|
|
|
|
**Database:**
|
|
```bash
|
|
# Rollback migrations
|
|
bin/rails db:rollback STEP=2
|
|
# Migrations: institutions + cohort_admin_invitations
|
|
```
|
|
|
|
**Code:**
|
|
```bash
|
|
# Git revert
|
|
git revert <commit-hash>
|
|
```
|
|
|
|
**Routes:**
|
|
- Remove cohort routes from `config/routes.rb`
|
|
|
|
**Verification:**
|
|
- Run existing test suite to ensure no impact
|
|
- Verify existing DocuSeal features still work
|
|
|
|
**Feature Flag (Optional):**
|
|
```ruby
|
|
# config/initializers/features.rb
|
|
Docuseal.enable_cohort_management = ENV['ENABLE_COHORT_MANAGEMENT'] == 'true'
|
|
|
|
# In controllers:
|
|
before_action :require_cohort_feature!
|
|
def require_cohort_feature!
|
|
redirect_to root_path unless Docuseal.enable_cohort_management?
|
|
end
|
|
```
|
|
|
|
### Dependencies & Sequencing
|
|
|
|
**This Story Blocks:**
|
|
- Story 1.2 (Cohort Creation) - requires institutions
|
|
- Story 1.3 (Student Enrollment) - requires institutions
|
|
- Story 1.4 (Admin Verification) - requires institutions
|
|
- All portal stories require admin role system
|
|
|
|
**Can Run Parallel:**
|
|
- Story 1.8 (Notifications) - can start once email templates ready
|
|
- Story 1.10 (State Management) - can design while this is implemented
|
|
|
|
### Critical Success Factors
|
|
|
|
1. **Data Isolation Must Be Perfect** - Any breach here is a security issue
|
|
2. **Role System Must Be Extensible** - Future roles may be added
|
|
3. **Performance Cannot Degrade** - Existing features must remain fast
|
|
4. **Integration Must Be Seamless** - No breaking changes to DocuSeal
|
|
5. **Rollback Must Be Clean** - Must be able to revert without data loss
|
|
|
|
### Winston's Critical Success Factors
|
|
|
|
1. **4-Layer Isolation Implementation** - Database → Model → Controller → UI
|
|
2. **Cryptographic Token Security** - SHA-256 + Redis + atomic operations
|
|
3. **Comprehensive Security Logging** - All violations captured and alerted
|
|
4. **Zero Impact on Existing Features** - IV1-IV5 tests must all pass
|
|
5. **Security-First Implementation Sequence** - Foundation before features
|
|
6. **Developer Understanding** - Team must understand 4-layer architecture
|
|
7. **Production Monitoring** - Real-time security event dashboard
|
|
|
|
### Implementation Phases (Winston's Recommendation)
|
|
|
|
**Phase 1: Foundation (Week 1)**
|
|
- Database migrations (institution_id on account_access)
|
|
- Model layer with 4-layer isolation scopes
|
|
- Basic ability rules and user extensions
|
|
|
|
**Phase 2: Security Core (Week 2)**
|
|
- Token generation and validation system
|
|
- Redis single-use enforcement
|
|
- Security event model and logging
|
|
- API base controller extensions
|
|
|
|
**Phase 3: Controllers & Services (Week 3)**
|
|
- Institution and invitation controllers
|
|
- InvitationService for business logic
|
|
- Mailer jobs and email templates
|
|
- Rate limiting implementation
|
|
|
|
**Phase 4: Testing & Validation (Week 4)**
|
|
- Comprehensive security tests (IV4 mandatory)
|
|
- Penetration testing of data isolation
|
|
- Performance benchmarking
|
|
- Security audit review
|
|
|
|
**Phase 5: Features & UI (Week 5)**
|
|
- Frontend components (only after security passes)
|
|
- Integration with existing DocuSeal features
|
|
- Final integration verification (IV1-IV3, IV5)
|
|
|
|
**⚠️ NO feature work until Phase 4 security tests pass**
|
|
|
|
### Known Risks & Mitigations
|
|
|
|
**Risk:** Authentication conflicts between new and existing roles
|
|
**Mitigation:** Extensive testing of login flows, JWT token compatibility
|
|
|
|
**Risk:** Performance impact on existing user operations
|
|
**Mitigation:** Benchmark before/after, add indexes, optimize queries
|
|
|
|
**Risk:** Data isolation bugs leading to cross-institution access
|
|
**Mitigation:** Thorough testing, security audit, logging of unauthorized attempts
|
|
|
|
**Risk:** Migration failures on production data
|
|
**Mitigation:** Test on production-like data, have rollback plan ready
|
|
|
|
### Testing Standards
|
|
|
|
**Location:** All tests in `spec/` directory following existing patterns
|
|
**Framework:** RSpec + FactoryBot + Capybara
|
|
**Coverage:** 80% minimum on new code
|
|
**Patterns:** Follow existing test helpers and matchers
|
|
**Integration:** Must pass existing DocuSeal test suite
|
|
|
|
---
|
|
|
|
## Change Log
|
|
|
|
| Date | Version | Description | Author |
|
|
|------|---------|-------------|--------|
|
|
| 2025-01-03 | 1.0 | Initial story creation following BMAD template | Bob (Scrum Master) |
|
|
|
|
---
|
|
|
|
## Dev Agent Record
|
|
|
|
*This section will be populated by the development agent during implementation*
|
|
|
|
### Agent Model Used
|
|
*To be filled by dev agent*
|
|
|
|
### Debug Log References
|
|
*To be filled by dev agent*
|
|
|
|
### Completion Notes List
|
|
*To be filled by dev agent*
|
|
|
|
### File List
|
|
*To be filled by dev agent*
|
|
|
|
---
|
|
|
|
## QA Results
|
|
|
|
**Reviewer:** Quinn (Test Architect)
|
|
**Architect:** Winston (System Architect)
|
|
**Review Date:** 2025-01-03
|
|
**Risk Assessment:** [docs/qa/assessments/1.1.institution-admin-risk-20250103.md](../qa/assessments/1.1.institution-admin-risk-20250103.md)
|
|
**Quality Gate:** [docs/qa/gates/1.1.institution-admin.yml](../qa/gates/1.1.institution-admin.yml)
|
|
|
|
### Overall Assessment: ⚠️ **CONDITIONAL PASS** (Implementation-Dependent)
|
|
|
|
**Updated Risk Score:** 18/100 (Medium Risk) → **Architecturally Mitigated**
|
|
**Critical Risks:** 2 → **Architecturally Addressed** (reduced to Medium with proper implementation)
|
|
**High Risks:** 4 → **Require Execution Excellence**
|
|
|
|
### Architectural Review Status: ✅ **COMPLETE**
|
|
|
|
#### **Winston's 4-Layer Security Architecture** ✅
|
|
- **Layer 1: Database-Level** - Foreign keys, unique indexes, non-nullable constraints
|
|
- **Layer 2: Model-Level** - `Institution.for_user(user)` scopes, security methods
|
|
- **Layer 3: Controller-Level** - `verify_institution_access` before_action, authorization
|
|
- **Layer 4: UI-Level** - Vue route guards, API client pre-validation
|
|
|
|
#### **Cryptographic Token System** ✅
|
|
- **Generation:** `SecureRandom.urlsafe_base64(64)` - 512 bits entropy
|
|
- **Storage:** SHA-256 hash only, `token_preview` for debugging
|
|
- **Enforcement:** Redis `SET key NX EX 86400` for atomic single-use
|
|
- **Validation:** Email matching, expiration, hash verification
|
|
|
|
#### **Security Event Logging** ✅
|
|
- **Model:** `SecurityEvent` with user, event_type, ip_address, details
|
|
- **Events:** 6 types defined (unauthorized access, insufficient privileges, token failures, rate limits, acceptance, demotion)
|
|
- **Monitoring:** Alert thresholds configured (>5 unauthorized/hour, >20 token failures/hour)
|
|
|
|
### Risk Profile Update: From High → Medium Risk
|
|
|
|
#### ✅ **Critical Risks Now Architecturally Mitigated**
|
|
|
|
| Risk | Before | After Winston's Architecture | New Status |
|
|
|------|--------|------------------------------|------------|
|
|
| **SEC-001** Cross-institution access | 9 (Critical) | 4-layer defense-in-depth | ✅ **Mitigated** → 3* |
|
|
| **SEC-002** Token security flaws | 9 (Critical) | SHA-256 + Redis + atomic ops | ✅ **Mitigated** → 3* |
|
|
|
|
*Reduced score = Architecture reduces probability/impact when implemented correctly
|
|
|
|
#### ⚠️ **High Risks Requiring Execution Excellence**
|
|
|
|
| Risk | Score | Challenge | Mitigation | Testing Required |
|
|
|------|-------|-----------|------------|------------------|
|
|
| **SEC-003** Role authorization bypass | 6 | Complex dual-role system | Cancancan + controller checks | Role escalation attempts |
|
|
| **DATA-001** Migration rollback | 6 | Zero-downtime complexity | Winston's backfill pattern | Production-like data testing |
|
|
| **PERF-001** Performance degradation | 6 | 10% threshold is strict | Indexing + query optimization | Benchmark before/after |
|
|
| **TECH-001** Integration conflicts | 6 | Additive changes only | IV1-IV5 integration tests | Existing test suite |
|
|
|
|
#### 🔍 **Medium Risks - Implementation Details**
|
|
|
|
| Risk | Score | Winston's Specification | Implementation Gap |
|
|
|------|-------|------------------------|-------------------|
|
|
| **OPS-001** Security logging | 4 | 6 event types + alerts | Real-time alert system |
|
|
| **PERF-002** Rate limiting | 4 | 5 invites/email/inst | Concurrent edge cases |
|
|
| **TECH-002** Email delivery | 4 | Sidekiq retry logic | Failure handling |
|
|
| **DATA-002** Token cleanup | 4 | Daily job, 1-week retention | Implementation needed |
|
|
|
|
### Updated Gate Decision: ⚠️ **CONDITIONAL PASS** (Improved)
|
|
|
|
**Status:** **READY FOR DEVELOPMENT** → **READY FOR PRODUCTION** (with conditions)
|
|
|
|
**Key Change:** Story evolved from "high risk design" to "architecturally sound but execution-critical"
|
|
|
|
### Implementation Phases (MANDATORY)
|
|
|
|
#### **Phase 1: Foundation** (Week 1) ✅ Ready
|
|
- Database migrations: `institution_id` on `account_access`
|
|
- Model layer: 4-layer isolation scopes
|
|
- Basic ability rules
|
|
|
|
#### **Phase 2: Security Core** (Week 2) ✅ Ready
|
|
- Token system: SHA-256 + Redis enforcement
|
|
- Security events: 6 types + logging
|
|
- API base controller extensions
|
|
|
|
#### **Phase 3: Controllers & Services** (Week 3) ✅ Ready
|
|
- Institution & invitation controllers
|
|
- `InvitationService` with rate limiting
|
|
- Mailer jobs + email templates
|
|
|
|
#### **Phase 4: Testing & Validation** (Week 4-5) ⚠️ **NON-NEGOTIABLE**
|
|
- **IV4 Security Tests** (Critical):
|
|
- [ ] Cross-institution access attempts (all endpoints)
|
|
- [ ] Token reuse/expiration/race conditions (50 concurrent)
|
|
- [ ] Role authorization bypass tests
|
|
- [ ] SQL injection on scoped queries
|
|
- [ ] Performance benchmarks (<10% degradation)
|
|
- [ ] Migration rollback verification
|
|
- [ ] Existing DocuSeal test suite (IV1-IV3, IV5)
|
|
|
|
#### **Phase 5: Features & UI** (Week 5+) ⚠️ **ONLY AFTER PHASE 4 PASSES**
|
|
- Frontend components
|
|
- Integration with existing features
|
|
- Security audit review
|
|
|
|
### Prerequisites for Production
|
|
|
|
#### **MUST PASS Phase 4 Testing:**
|
|
- [ ] **IV4 Security Tests**: All scenarios pass with malicious inputs
|
|
- [ ] **Performance**: <10% degradation on existing operations
|
|
- [ ] **Integration**: IV1-IV5 tests all pass
|
|
- [ ] **Rollback**: Verified on production-like data
|
|
|
|
#### **MUST COMPLETE:**
|
|
- [ ] **Security Audit**: Third-party review of token system
|
|
- [ ] **Team Understanding**: 4-layer architecture review with developers
|
|
- [ ] **Redis Infrastructure**: Properly configured for token enforcement
|
|
- [ ] **Monitoring**: Security event dashboard deployed
|
|
|
|
### Critical Success Factors
|
|
|
|
1. **✅ Architecture is Sound**: Winston's 4-layer design addresses all critical risks
|
|
2. **⚠️ Execution is Critical**: Implementation must be perfect
|
|
3. **⚠️ Testing is Extensive**: IV4 security tests represent significant burden
|
|
4. **⚠️ Performance is Strict**: 10% degradation threshold is challenging
|
|
|
|
### Remaining Risk: Implementation Execution
|
|
|
|
**Primary concerns:**
|
|
- **Developer Understanding**: Team must grasp 4-layer architecture conceptually
|
|
- **Redis Infrastructure**: Token enforcement requires proper Redis setup
|
|
- **Performance Budget**: 10% target may be hard to guarantee
|
|
- **Test Complexity**: IV4 tests require sophisticated concurrency/race condition testing
|
|
|
|
### Recommendations
|
|
|
|
1. **✅ APPROVED FOR DEVELOPMENT**: Story is architecturally sound and comprehensive
|
|
2. **⚠️ PHASE 4 IS MANDATORY**: No shortcuts on security testing
|
|
3. **⚠️ TEAM KICKOFF REQUIRED**: Ensure understanding of 4-layer architecture
|
|
4. **⚠️ PERFORMANCE BASELINE**: Benchmark existing operations before changes
|
|
5. **⚠️ SECURITY AUDIT**: Third-party review before production deployment
|
|
|
|
### Next Steps
|
|
|
|
1. **✅ Story Ready**: Winston's architecture complete and documented
|
|
2. **✅ QA Updated**: Risk profile reflects architectural improvements
|
|
3. **⏳ Team Kickoff**: Review 4-layer architecture + Phase 1 start
|
|
4. **⏳ Phase 1-3**: Implement foundation, security core, controllers
|
|
5. **⏳ Phase 4 Testing**: Comprehensive IV4 security tests (CRITICAL)
|
|
6. **⏳ Final Gate**: Quinn's production approval after Phase 4 passes
|
|
|
|
**Note:** Story evolved from **HIGH RISK** to **ARCHITECTURALLY MITIGATED** thanks to Winston's comprehensive design. The primary remaining risk is **execution excellence** - the 4-layer architecture must be implemented perfectly, and IV4 security tests must pass completely before production. This is now a **high-complexity, security-critical implementation** requiring disciplined execution.
|
|
|
|
---
|
|
|
|
**Story Status:** ✅ **APPROVED FOR DEVELOPMENT** (Architecture Complete)
|
|
**Production Gate:** ⚠️ **CONDITIONAL** (Pending Phase 4 Security Tests)
|
|
**Next Action:** Team kickoff → Phase 1 implementation → Phase 4 security validation |