Add development artifacts and backlog documentation

pull/565/head
NeoSkosana 2 months ago
parent 223101b247
commit 06c88e2fcb

@ -0,0 +1,11 @@
# Ralph TUI Configuration
# Generated by setup wizard
# See: ralph-tui config help
tracker = "json"
agent = "claude"
maxIterations = 50
autoCommit = false
[trackerOptions]
[agentOptions]

@ -0,0 +1,184 @@
# GitHub Projects Integration - Summary
## ✅ What Was Created
I've created a complete GitHub Projects integration system that will populate your project board with all 42 FloDoc user stories.
## 📁 Files Created
### 1. **populate_github_project.sh** (Shell Script - RECOMMENDED)
- **Location:** `docs/backlog/populate_github_project.sh`
- **Size:** 7.6KB
- **Purpose:** Uses GitHub CLI to create issues and add to project board
- **Best for:** Quick setup, easy to use
### 2. **populate_github_project.py** (Python Script)
- **Location:** `docs/backlog/populate_github_project.py`
- **Size:** 13KB
- **Purpose:** Uses GitHub API directly to create issues
- **Best for:** Advanced users, custom modifications
### 3. **GITHUB_PROJECT_SETUP.md** (Complete Guide)
- **Location:** `docs/backlog/GITHUB_PROJECT_SETUP.md`
- **Size:** 8KB
- **Contents:**
- Prerequisites for both scripts
- Step-by-step setup instructions
- Troubleshooting guide
- Customization options
- Example workflow
### 4. **QUICKSTART_GITHUB_PROJECTS.md** (Quick Reference)
- **Location:** `docs/backlog/QUICKSTART_GITHUB_PROJECTS.md`
- **Size:** 3.8KB
- **Contents:**
- One-command setup
- 5-minute prerequisites
- Troubleshooting
- Quick reference
### 5. **Updated README.md**
- **Location:** `docs/backlog/README.md`
- **Changes:**
- Added GitHub Projects Integration section
- Added quick start guide
- Added output description
- Added contact section for GitHub help
## 🎯 How to Use (30-Second Guide)
```bash
# 1. Install GitHub CLI (if needed)
# https://cli.github.com/
# 2. Authenticate
gh auth login
# 3. Install extension
gh extension install mislav/gh-project
# 4. Run the script
cd docs/backlog
./populate_github_project.sh NeoSkosana floDoc-v3 6
```
## 📊 What You'll Get
### GitHub Issues (42 total)
Each issue includes:
- **Title:** `[1.1] Database Schema Extension`
- **User Story:** Full "As a... I want... So that..." format
- **Background:** Context and rationale
- **Acceptance Criteria:** All requirements
- **Metadata:** Story number, epic, priority, effort, risk, status
- **Labels:** For filtering and organization
### Labels Applied
- `story:X.X` - Story identifier
- `epic:phase-X-name` - Epic/phase
- `priority:critical/high/medium/low` - Priority
- `risk:low/medium/high` - Risk level
- `status:draft/in-progress/etc` - Current status
- `portal:admin/student/sponsor/backend/qa/infrastructure` - Portal type
### Generated Files
- **`github_project_summary.md`** - Complete reference with all stories and links
## 🎨 Example Output
### Issue Title
```
[1.1] Database Schema Extension
```
### Issue Body
```
## 📖 User Story
**As a** system architect,
**I want** to create the database schema for FloDoc's new models,
**So that** the application has the foundation to support cohort management.
## 📋 Background
Based on the PRD analysis, we need three new tables:
- institutions
- cohorts
- cohort_enrollments
## ✅ Acceptance Criteria
**Functional:**
1. ✅ All three tables created with correct schema
2. ✅ Foreign key relationships established
...
## 📊 Metadata
- **Story Number**: 1.1
- **Epic**: Phase 1 - Foundation
- **Priority**: Critical
- **Estimated Effort**: 2-3 days
- **Risk Level**: Low
- **Status**: Draft
```
## 🏗️ Project Board Setup
Your project board should have these columns:
1. **Todo** - Stories not started
2. **In Progress** - Active work
3. **In Review** - Awaiting review
4. **Done** - Completed
After running the script, drag issues from "Todo" to other columns as work progresses.
## 🔍 Troubleshooting
| Problem | Solution |
|---------|----------|
| `gh: command not found` | Install from https://cli.github.com/ |
| Not authenticated | Run `gh auth login` |
| Permission denied | `chmod +x populate_github_project.sh` |
| Can't add to project | Issues still created; add manually via UI |
| Rate limit hit | Wait 60 minutes or use Python script with token |
## 📚 Reference Files
| File | Purpose |
|------|---------|
| `STORIES_INDEX.md` | All 42 stories by phase |
| `STORIES_SUMMARY.md` | Quick story reference |
| `stories-presentation.html` | Interactive presentation |
| `6-epic-details.md` | Full story details (source) |
## 🎯 Next Steps After Running Script
1. **Review** the summary file
```bash
cat docs/backlog/github_project_summary.md
```
2. **Visit** your project board
```
https://github.com/users/NeoSkosana/projects/6
```
3. **Organize** issues into columns
4. **Start** with Story 1.1 (Database Schema Extension)
5. **Follow** the BMad workflow from CLAUDE.md
## 📞 Need Help?
- **Full Guide:** `docs/backlog/GITHUB_PROJECT_SETUP.md`
- **Quick Start:** `docs/backlog/QUICKSTART_GITHUB_PROJECTS.md`
- **Story Details:** `docs/backlog/STORIES_INDEX.md`
---
**Ready to go?** Just run:
```bash
./populate_github_project.sh NeoSkosana floDoc-v3 6
```

@ -0,0 +1,319 @@
# GitHub Projects Populator - Setup & Usage Guide
This document explains how to use the scripts to populate your GitHub Projects board with user stories from the FloDoc backlog.
## Overview
You have two options for populating your GitHub project board:
1. **Python Script** (`populate_github_project.py`) - Uses GitHub API directly
2. **Shell Script** (`populate_github_project.sh`) - Uses GitHub CLI (recommended for simplicity)
## Prerequisites
### Option 1: Python Script (GitHub API)
1. **GitHub Personal Access Token**
- Go to GitHub Settings → Developer settings → Personal access tokens → Tokens (classic)
- Generate a new token with these scopes:
- `repo` (Full control of private repositories)
- `project` (Access to project boards)
- Save the token securely
2. **Python Dependencies**
```bash
pip install requests
```
### Option 2: Shell Script (GitHub CLI) - RECOMMENDED
1. **Install GitHub CLI**
```bash
# Ubuntu/Debian
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null
sudo apt update
sudo apt install gh
# macOS
brew install gh
# Or download from: https://cli.github.com/
```
2. **Authenticate with GitHub**
```bash
gh auth login
```
- Select: GitHub.com
- Select: HTTPS
- Select: Yes (authenticate with Git)
- Select: Login with a web browser
- Copy the authentication code and complete in browser
3. **Install gh-project extension**
```bash
gh extension install mislav/gh-project
```
## Usage
### Using Shell Script (Recommended)
1. **Make the script executable**
```bash
chmod +x docs/backlog/populate_github_project.sh
```
2. **Run the script**
```bash
./docs/backlog/populate_github_project.sh <owner> <repo> [project_number]
```
**Example:**
```bash
./docs/backlog/populate_github_project.sh NeoSkosana floDoc-v3 6
```
**Parameters:**
- `<owner>`: Your GitHub username or organization name
- `<repo>`: Your repository name
- `[project_number]`: Your project number (from URL: `https://github.com/users/NeoSkosana/projects/6` → number is `6`)
3. **What the script does:**
- Parses all 42 stories from `docs/prd/6-epic-details.md`
- Creates a GitHub issue for each story
- Adds labels (epic, priority, risk, status, portal type)
- Adds issues to your project board
- Generates a summary file: `docs/backlog/github_project_summary.md`
### Using Python Script
1. **Run the script**
```bash
python docs/backlog/populate_github_project.py \
--token YOUR_GITHUB_TOKEN \
--owner NeoSkosana \
--repo floDoc-v3 \
--project 6
```
2. **Dry run (test without creating issues)**
```bash
python docs/backlog/populate_github_project.py \
--token YOUR_GITHUB_TOKEN \
--owner NeoSkosana \
--repo floDoc-v3 \
--dry-run
```
## Project Board Configuration
Your GitHub project board should be configured with these columns:
1. **Todo** - Stories not yet started
2. **In Progress** - Stories being worked on
3. **In Review** - Stories awaiting review
4. **Done** - Completed stories
### Setting Up Custom Fields (Optional)
For better organization, you can add custom fields to your project:
1. **Priority** (Single Select)
- Critical
- High
- Medium
- Low
2. **Epic** (Single Select)
- Phase 1 - Foundation
- Phase 2 - Backend Logic
- Phase 3 - API Layer
- Phase 4 - Admin Portal
- Phase 5 - Student Portal
- Phase 6 - Sponsor Portal
- Phase 7 - Testing & QA
- Phase 8 - Infrastructure & Documentation
3. **Portal** (Single Select)
- Admin
- Student
- Sponsor
- Backend
- QA
- Infrastructure
4. **Risk Level** (Single Select)
- Low
- Medium
- High
## Generated Output
### Summary File
The script generates `docs/backlog/github_project_summary.md` with:
- Total story count
- Stories grouped by epic/phase
- Quick reference table with all metadata
- Links to created issues
### Issue Format
Each issue includes:
```
[Story Number] Story Title
## 📖 User Story
[User story text]
## 📋 Background
[Background context]
## ✅ Acceptance Criteria
[Acceptance criteria]
## 📝 Tasks / Subtasks
[Task list if available]
## 📊 Metadata
- Story Number: X.X
- Epic: [Epic name]
- Priority: [Priority]
- Estimated Effort: [Effort]
- Risk Level: [Risk]
- Status: [Status]
```
### Labels Applied
Each issue gets these labels:
- `story:X.X` - Story number
- `epic:[epic-name]` - Phase/epic identifier
- `priority:[priority]` - Priority level
- `risk:[risk]` - Risk level
- `status:[status]` - Current status
- `portal:[portal-type]` - Portal type (admin/student/sponsor/backend/qa/infrastructure)
## Troubleshooting
### Authentication Issues
**Problem:** `gh auth status` shows not authenticated
**Solution:**
```bash
gh auth login
# Follow the interactive prompts
```
### Permission Issues
**Problem:** `gh issue create` fails with permission error
**Solution:**
- Ensure your token has `repo` scope
- Verify you have write access to the repository
- Check that the repository exists and is accessible
### Project Add Issues
**Problem:** Cannot add issues to project board
**Solution:**
- Verify project number is correct
- Ensure you have admin access to the project
- Try adding manually via GitHub UI
- The script will still create issues even if project add fails
### Rate Limiting
**Problem:** GitHub API rate limit exceeded
**Solution:**
- The script includes a 1-second delay between requests
- For 42 stories, this takes ~1 minute
- If you hit limits, wait 60 minutes and try again
- Consider using a personal access token with higher rate limits
## Manual Project Board Setup
If the script cannot automatically add issues to your project, you can do it manually:
1. Go to your project board: `https://github.com/users/<owner>/projects/<number>`
2. Click "Add items"
3. Search for issues by title: `[1.1]`, `[1.2]`, etc.
4. Drag and drop issues into appropriate columns
## Customization
### Modifying Issue Body
Edit the `create_issue()` method in `populate_github_project.py` to change the issue format.
### Changing Labels
Edit the `_get_labels()` method to customize label generation.
### Filtering Stories
To create only specific stories, modify the script to filter by:
- Epic/Phase
- Priority
- Portal type
- Risk level
## Example Workflow
```bash
# 1. Authenticate with GitHub CLI
gh auth login
# 2. Run the populator script
./docs/backlog/populate_github_project.sh NeoSkosana floDoc-v3 6
# 3. Review the summary
cat docs/backlog/github_project_summary.md
# 4. Go to your project board
# https://github.com/users/NeoSkosana/projects/6
# 5. Organize issues into columns (Todo, In Progress, Done)
# 6. Start working on Story 1.1 (Database Schema Extension)
```
## Next Steps
After populating the project board:
1. **Review all stories** - Ensure they're correctly categorized
2. **Prioritize work** - Assign stories to sprints or milestones
3. **Start with Phase 1** - Foundation stories (1.1, 1.2, 1.3)
4. **Create branches** - Use `git checkout -b story/1.1-database-schema` for each story
5. **Follow the development workflow** - See CLAUDE.md for BMad Core cycle
## Additional Resources
- **Story Details**: `docs/prd/6-epic-details.md`
- **Story Index**: `docs/backlog/STORIES_INDEX.md`
- **Story Summary**: `docs/backlog/STORIES_SUMMARY.md`
- **Presentation**: `docs/backlog/stories-presentation.html`
- **Project Board**: `https://github.com/users/NeoSkosana/projects/6`
## Support
For issues with the scripts:
1. Check the troubleshooting section above
2. Review the script output/logs
3. Verify all prerequisites are installed
4. Check GitHub API status: https://www.githubstatus.com/
---
**Generated:** 2026-01-15
**Version:** 1.0

@ -0,0 +1,256 @@
# JSONBin Setup Guide for Shared Kanban Board
## 🎯 What is JSONBin?
JSONBin is a free service that lets you store JSON data in the cloud and update it via API calls. This allows your Kanban board state to be **shared across all users** in real-time.
## 📋 Setup Steps (5 minutes)
### Step 1: Sign Up for JSONBin
1. Go to **https://jsonbin.io/**
2. Click **Sign Up** (free tier available)
3. Verify your email address
4. Log in to your dashboard
### Step 2: Get Your API Key
1. After logging in, click on your profile icon (top right)
2. Select **"API Keys"**
3. Copy your **Master Key** (starts with `$2b$`)
4. Keep this key secure - don't share it publicly!
### Step 3: Create a New Bin
**Option A: Create via Dashboard (Easiest)**
1. Click **"Create Bin"** on your dashboard
2. In the content area, paste this initial data:
```json
{
"1.1": "backlog",
"1.2": "backlog",
"1.3": "backlog",
"2.1": "backlog",
"2.2": "backlog",
"2.3": "backlog",
"2.4": "backlog",
"2.5": "backlog",
"2.6": "backlog",
"2.7": "backlog",
"2.8": "backlog",
"3.1": "backlog",
"3.2": "backlog",
"3.3": "backlog",
"3.4": "backlog",
"4.1": "backlog",
"4.2": "backlog",
"4.3": "backlog",
"4.4": "backlog",
"4.5": "backlog",
"4.6": "backlog",
"4.7": "backlog",
"4.8": "backlog",
"4.9": "backlog",
"4.10": "backlog",
"5.1": "backlog",
"5.2": "backlog",
"5.3": "backlog",
"5.4": "backlog",
"5.5": "backlog",
"6.1": "backlog",
"6.2": "backlog",
"7.1": "backlog",
"7.2": "backlog",
"7.3": "backlog",
"7.4": "backlog",
"7.5": "backlog",
"8.0": "backlog",
"8.0.1": "backlog",
"8.5": "backlog",
"8.6": "backlog",
"8.7": "backlog"
}
```
3. Click **"Create"**
4. Copy the **Bin ID** from the URL (e.g., `abc123xyz`)
**Option B: Create via API (Advanced)**
Use the "Create New Bin" button in the Kanban board config modal.
### Step 4: Configure the Kanban Board
1. Open `stories-kanban-shared.html`
2. Click the **"Config"** button (⚙️)
3. Paste your **API Key** and **Bin ID**
4. Click **"Save Configuration"**
5. The board will automatically load the shared state
## 🚀 Deploying to tiiny.host
### Option 1: Upload Shared Version
```bash
# Upload stories-kanban-shared.html to tiiny.host
# This version requires JSONBin configuration
```
### Option 2: Upload with Pre-configured API Key (Advanced)
⚠️ **SECURITY WARNING**: Only do this if you control access to the board!
1. Edit `stories-kanban-shared.html`
2. Find the `config` object in the script
3. Add your API key and Bin ID:
```javascript
let config = {
apiKey: 'YOUR_API_KEY_HERE',
binId: 'YOUR_BIN_ID_HERE'
};
```
4. Save and upload to tiiny.host
5. Users won't need to configure anything
## 💡 Usage Tips
### For Team Leaders
1. **Share the URL** with your team
2. **Everyone can drag and drop** stories
3. **Changes sync automatically** when you click Save
4. **Refresh the page** to see others' changes
### For Daily Standups
1. Open the board on a shared screen
2. Move stories as team members report progress
3. Click **Save** after the meeting
4. Everyone sees the updated board
### For Sprint Planning
1. Start with all stories in **Backlog**
2. Drag stories to **To Do** for the sprint
3. Assign stories to team members (use the View button to add notes)
4. Save and share the URL
## 🔒 Security Considerations
### API Key Security
- **Never commit** your API key to public repositories
- **Use environment variables** for production deployments
- **Consider using a proxy** for API calls in production
- **Rotate your API key** if it's exposed
### Access Control
JSONBin free tier doesn't offer access control. For sensitive projects:
1. **Use a private bin** (paid feature)
2. **Implement a backend proxy** that handles authentication
3. **Use JWT tokens** for user authentication
## 💰 Pricing
JSONBin offers:
- **Free tier**: 10,000 requests/month, 100MB storage
- **Pro tier**: $15/month, unlimited requests
- **Enterprise**: Custom pricing
For most teams, the **free tier is sufficient** for Kanban board usage.
## 🔄 Sync Flow
```
User A moves story → Local state updated → Click Save → API call to JSONBin
User B refreshes page ← API call to JSONBin ← State saved to cloud
```
## 🐛 Troubleshooting
### "No config" error
- Click **Config** and enter your API Key and Bin ID
- Make sure you're using the correct Bin ID
### "Failed to load from cloud" error
- Check your API Key is correct
- Verify the Bin ID exists
- Check your internet connection
- Try refreshing the page
### Changes not saving
- Click **Save** button (not just drag and drop)
- Check sync status shows "Synced"
- Look for error messages in the browser console
### Multiple users seeing different states
- Each user needs to click **Refresh** to see latest changes
- Changes only sync when **Save** is clicked
- Consider implementing auto-refresh every 30 seconds
## 📊 Monitoring Usage
1. Go to your JSONBin dashboard
2. Click on your bin
3. View **Request Count** and **Last Updated**
4. Monitor for unusual activity
## 🎯 Alternative: Self-Hosted Backend
If you need more control, consider:
1. **Firebase Firestore** (free tier available)
2. **Supabase** (free tier available)
3. **Your own API** with Rails backend
4. **WebSocket server** for real-time sync
## 📚 Example: Firebase Alternative
If you prefer Firebase over JSONBin:
```javascript
// Firebase configuration
const firebaseConfig = {
apiKey: "YOUR_API_KEY",
authDomain: "YOUR_PROJECT.firebaseapp.com",
projectId: "YOUR_PROJECT",
storageBucket: "YOUR_PROJECT.appspot.com",
messagingSenderId: "YOUR_SENDER_ID",
appId: "YOUR_APP_ID"
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
const db = firebase.firestore();
// Save to Firebase
async function saveToFirebase() {
await db.collection('kanban').doc('board').set(storyStates);
}
// Load from Firebase
async function loadFromFirebase() {
const doc = await db.collection('kanban').doc('board').get();
if (doc.exists) {
storyStates = doc.data();
}
}
```
## 🎉 Success!
Once configured, your Kanban board will:
- ✅ Sync across all users
- ✅ Persist state in the cloud
- ✅ Allow real-time collaboration
- ✅ Work from any device
- ✅ Update instantly when saved
---
**Need help?** Contact your team lead or check JSONBin documentation at https://docs.jsonbin.io/
**Generated:** 2026-01-15

@ -0,0 +1,193 @@
# FloDoc Stories Kanban Board
## 🎯 Overview
The **Kanban Board** is an interactive story management tool that allows you to visually organize and track all 42 FloDoc user stories across 5 workflow columns.
## 📊 Columns
| Column | Color | Purpose |
|--------|-------|---------|
| **Backlog** | Gray | Stories not yet started |
| **To Do** | Yellow | Stories ready to be worked on |
| **In Progress** | Blue | Stories currently being developed |
| **Review** | Red | Stories awaiting QA/review |
| **Done** | Green | Completed stories |
## 🎨 Features
### Core Functionality
- ✅ **Drag & Drop**: Move stories between columns by dragging
- ✅ **State Persistence**: Your board state is saved automatically in browser storage
- ✅ **Search**: Find stories by number, title, epic, or content
- ✅ **Story Details**: Click "View" to see full story information in a modal
- ✅ **Quick Actions**: Move stories to next column with one click
- ✅ **Progress Tracking**: Real-time statistics showing total and completed stories
### Design
- ✅ **FloDoc Design System**: Purple (#784DC7) theme
- ✅ **Visual Indicators**: Priority badges, effort tags, epic names
- ✅ **Responsive**: Works on desktop and tablet
- ✅ **Keyboard Friendly**: Escape to close modals
## 🚀 How to Use
### Opening the Board
```bash
cd docs/backlog
xdg-open stories-kanban.html
```
### Basic Operations
1. **View a Story**: Click the "View" button on any card
2. **Move a Story**: Drag a card to a different column
3. **Quick Move**: Click the "→" button to move to the next column
4. **Search**: Type in the search box to filter stories
5. **Save**: Click "Save" to persist your current board state
6. **Reset**: Click "Reset" to move all stories back to Backlog
### Workflow Example
```
Backlog → To Do → In Progress → Review → Done
```
1. Start with all stories in **Backlog**
2. Move stories to **To Do** when planning Sprint 1
3. Drag to **In Progress** when development starts
4. Move to **Review** when ready for QA
5. Complete by moving to **Done**
## 💾 Data Persistence
- **Automatic Save**: Board state saves to browser localStorage after each change
- **Manual Save**: Use the "Save" button to explicitly save
- **Reset**: Use "Reset" to clear all progress and start fresh
- **No Server Required**: All data stays in your browser
## 🎨 Design System
The Kanban board follows the FloDoc design system:
- **Primary Color**: `#784DC7` (Purple)
- **Column Colors**: Match FloDoc status indicators
- **Typography**: Segoe UI / System fonts
- **Shadows**: Subtle elevation with purple tint
- **Radius**: 7.5px for cards, 12px for columns
## 📱 Responsive Design
- **Desktop**: Full 5-column layout
- **Tablet**: Scrollable horizontal board
- **Mobile**: Optimized for touch interactions
## 🎯 Use Cases
### Sprint Planning
1. Move stories from Backlog to To Do
2. Prioritize within To Do column
3. Start development by moving to In Progress
### Daily Standups
1. Review In Progress column
2. Move completed work to Review
3. Discuss blockers visually
### Sprint Review
1. Filter by Done column
2. Review all completed stories
3. Generate summary from completed work
### Backlog Grooming
1. Search for specific stories
2. View details to understand requirements
3. Reorganize based on new priorities
## 🔧 Technical Details
### Storage
- **Key**: `flodoc-kanban-state`
- **Format**: JSON object mapping story numbers to column IDs
- **Example**: `{"1.1": "done", "1.2": "progress", ...}`
### State Structure
```javascript
{
"1.1": "backlog",
"1.2": "todo",
"1.3": "progress",
"2.1": "review",
"2.2": "done"
}
```
### Events
- `dragstart`: Story picked up
- `dragover`: Hovering over column
- `drop`: Story dropped in column
- `click`: View story details
## 📚 Related Files
- `stories-kanban.html` - The Kanban board application
- `stories-viewer-enhanced.html` - Alternative viewer with navigation
- `stories-presentation.html` - Original full-screen slides
- `STORIES_SUMMARY.md` - Quick story reference
- `STORIES_INDEX.md` - Complete story index
## 🚀 Deployment
### Local Development
```bash
python3 -m http.server 8000
# Access: http://localhost:8000/stories-kanban.html
```
### GitHub Pages
1. Push to GitHub repository
2. Enable GitHub Pages
3. Access: `https://username.github.io/repo/stories-kanban.html`
### Netlify
1. Drag `stories-kanban.html` to Netlify Drop
2. Get instant URL
3. Share with team
### CodePen
1. Copy HTML content
2. Paste into CodePen
3. Save and share link
## 🎯 Tips
1. **Use with Team**: Share your screen during planning meetings
2. **Save Frequently**: Click Save before closing browser
3. **Search First**: Use search to find stories quickly
4. **Keyboard Shortcuts**: Use Escape to close modals
5. **Mobile Friendly**: Works great on tablets for standups
## 🐛 Troubleshooting
**Stories not dragging?**
- Ensure you're dragging the card body, not buttons
- Try refreshing the page
**State not saving?**
- Check browser localStorage is enabled
- Try manual Save button
**Search not working?**
- Clear search box to show all stories
- Check for typos
**Modal won't close?**
- Click outside the modal
- Press Escape key
---
**Generated:** 2026-01-15
**Stories:** 42
**Columns:** 5
**File Size:** 130KB

@ -0,0 +1,164 @@
# Quick Start Guide - FloDoc Stories Presentation
## 🚀 Quick Launch
### ⭐⭐ NEW: Interactive Kanban Board (BEST CHOICE)
**Option 1: Open Kanban Board**
```bash
# Navigate to the backlog directory
cd docs/backlog
# Open the Kanban board
xdg-open stories-kanban.html
# Or on macOS
open stories-kanban.html
```
**Option 2: Serve Kanban Board**
```bash
cd docs/backlog
python3 -m http.server 8000
# Then open: http://localhost:8000/stories-kanban.html
```
### ⭐ Enhanced Viewer with Navigation Panel
**Option 3: Open Enhanced Viewer**
```bash
cd docs/backlog
xdg-open stories-viewer-enhanced.html
```
**Option 4: Serve Enhanced Viewer**
```bash
python3 -m http.server 8000
# Then open: http://localhost:8000/stories-viewer-enhanced.html
```
### Alternative: Original Full-Screen Presentation
**Option 5: Open Original Presentation**
```bash
cd docs/backlog
xdg-open stories-presentation.html
```
**Option 6: Serve Original Presentation**
```bash
python3 -m http.server 8000
# Then open: http://localhost:8000/stories-presentation.html
```
### Quick Reference
**Option 7: Just Read the Summary**
```bash
cat docs/backlog/STORIES_SUMMARY.md
# or
less docs/backlog/STORIES_SUMMARY.md
```
## 📊 What You'll See
### Presentation Website (`stories-presentation.html`)
- **42 full-viewport slides** - one per user story
- **Professional design** with gradient background
- **Keyboard navigation** - Arrow keys or Space
- **Progress bar** - Shows completion percentage
- **Clean layout** - User Story, Background, Acceptance Criteria per slide
### Summary Document (`STORIES_SUMMARY.md`)
- **Quick reference** with all 42 stories
- **User stories only** - Easy to scan
- **Markdown format** - Works in any editor
## 🎯 Navigation Controls
| Action | Keyboard | Mouse |
|--------|----------|-------|
| Next slide | `→` or `Space` | Click "Next" button |
| Previous slide | `←` | Click "Previous" button |
| First/Last | - | Use buttons |
## 📋 Story Breakdown
| Phase | Stories | Focus |
|-------|---------|-------|
| **1. Foundation** | 3 | Database & Models |
| **2. Backend Logic** | 8 | Workflows & Business Logic |
| **3. API Layer** | 4 | REST APIs & Webhooks |
| **4. Admin Portal** | 10 | TP/TP Portal UI |
| **5. Student Portal** | 5 | Student-facing UI |
| **6. Sponsor Portal** | 2 | Sponsor-facing UI |
| **7. Testing & QA** | 5 | Quality assurance |
| **8. Infrastructure** | 4 | Deployment & Docs |
**Total: 42 stories**
## ⏱️ Time Estimates
Each story is designed for **4-hour implementation windows**:
- Small stories: 1-2 hours
- Medium stories: 3-4 hours
- Large stories: 4+ hours (may need splitting)
## 🔄 Regeneration
If the source document changes:
```bash
cd docs/backlog
python3 generate_presentation.py
```
This will regenerate both `stories-presentation.html` and `STORIES_SUMMARY.md`.
## 📁 Files in This Directory
```
docs/backlog/
├── README.md # This overview
├── QUICKSTART.md # This quick start guide
├── stories-presentation.html # The presentation (118KB)
├── STORIES_SUMMARY.md # Quick reference (11KB)
└── generate_presentation.py # Regeneration script (14KB)
```
## 🎯 Next Steps
1. **Review** all stories in the presentation
2. **Prioritize** stories for Sprint 1
3. **Create branches** following BMAD workflow
4. **Implement** with QA gates
5. **Merge** to master after approval
## 💡 Pro Tips
- **Use full-screen mode** in your browser for best experience
- **Bookmark** the presentation for quick access
- **Print** STORIES_SUMMARY.md for team meetings
- **Share** the HTML file with stakeholders for review
## 🐛 Troubleshooting
**HTML won't open?**
- Ensure file extension is `.html`
- Try a different browser
- Check file permissions: `chmod 644 stories-presentation.html`
**Content looks wrong?**
- Regenerate: `python3 generate_presentation.py`
- Check source: `cat ../prd/6-epic-details.md | head -100`
**Want to see a specific story?**
- Use Ctrl+F in the summary document
- Navigate to slide number in presentation
---
**Generated:** 2026-01-15
**Source:** `docs/prd/6-epic-details.md` (832KB)
**Stories:** 42
**Total Time Estimate:** ~168 hours (42 stories × 4 hours)

@ -0,0 +1,149 @@
# Quick Start - GitHub Projects Populator
## 🚀 One-Command Setup (Recommended)
```bash
# From the project root
cd docs/backlog && ./populate_github_project.sh NeoSkosana floDoc-v3 6
```
## 📋 Prerequisites (5 minutes)
### 1. Install GitHub CLI
```bash
# macOS
brew install gh
# Ubuntu/Debian
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null
sudo apt update && sudo apt install gh
```
### 2. Authenticate
```bash
gh auth login
# Follow the browser prompts
```
### 3. Install Extension
```bash
gh extension install mislav/gh-project
```
## 🎯 Run the Script
```bash
# Make executable (first time only)
chmod +x docs/backlog/populate_github_project.sh
# Run it
./docs/backlog/populate_github_project.sh NeoSkosana floDoc-v3 6
```
**Parameters:**
- `NeoSkosana` - Your GitHub username
- `floDoc-v3` - Your repository name
- `6` - Your project number (from URL)
## 📊 What Happens
1. **Parses** all 42 stories from `docs/prd/6-epic-details.md`
2. **Creates** GitHub issues for each story
3. **Adds** labels (epic, priority, risk, portal type)
4. **Adds** issues to your project board
5. **Generates** summary file: `docs/backlog/github_project_summary.md`
## 🎨 Issue Format
Each issue contains:
```
[1.1] Database Schema Extension
## 📖 User Story
As a system architect, I want to create the database schema...
## 📋 Background
Based on the PRD analysis, we need three new tables...
## ✅ Acceptance Criteria
Functional:
1. ✅ All three tables created with correct schema
...
## 📊 Metadata
- Story Number: 1.1
- Epic: Phase 1 - Foundation
- Priority: Critical
- Estimated Effort: 2-3 days
- Risk Level: Low
- Status: Draft
```
## 🏷️ Labels Applied
- `story:1.1` - Story identifier
- `epic:phase-1-foundation` - Epic/phase
- `priority:critical` - Priority level
- `risk:low` - Risk level
- `status:draft` - Current status
- `portal:backend` - Portal type
## 🔍 Troubleshooting
### Problem: `gh: command not found`
**Solution:** Install GitHub CLI from https://cli.github.com/
### Problem: Not authenticated
**Solution:** Run `gh auth login`
### Problem: Cannot add to project
**Solution:** Add issues manually via GitHub UI (issues are still created)
### Problem: Permission denied on script
**Solution:** `chmod +x docs/backlog/populate_github_project.sh`
## 📝 Manual Alternative (Python)
If you prefer Python or don't have GitHub CLI:
```bash
# Install dependencies
pip install requests
# Run with token
python docs/backlog/populate_github_project.py \
--token YOUR_GITHUB_TOKEN \
--owner NeoSkosana \
--repo floDoc-v3 \
--project 6
```
Get token from: GitHub → Settings → Developer settings → Personal access tokens
## 📂 Files Created
| File | Description |
|------|-------------|
| `github_project_summary.md` | Complete story reference with links |
| GitHub Issues (42) | Individual story issues |
| Project Board Cards | Visual kanban cards |
## 🎯 Next Steps
1. **Review** the summary file: `cat docs/backlog/github_project_summary.md`
2. **Visit** your project: `https://github.com/users/NeoSkosana/projects/6`
3. **Organize** issues into columns (Todo, In Progress, Done)
4. **Start** with Story 1.1 (Database Schema Extension)
5. **Follow** the BMad workflow in CLAUDE.md
## 📚 More Info
- **Full Guide:** `docs/backlog/GITHUB_PROJECT_SETUP.md`
- **Story Index:** `docs/backlog/STORIES_INDEX.md`
- **Story Summary:** `docs/backlog/STORIES_SUMMARY.md`
- **Presentation:** `docs/backlog/stories-presentation.html`
---
**Need help?** Check the full guide at `docs/backlog/GITHUB_PROJECT_SETUP.md`

@ -0,0 +1,253 @@
# FloDoc User Stories - Presentation Backlog
This directory contains a presentation-style website that displays all user stories from the FloDoc enhancement project.
## Files
### 📄 `stories-kanban.html` (130KB) ⭐⭐ **NEW - BEST CHOICE**
Interactive Kanban board for story management with drag-and-drop.
**Features:**
- **5 columns**: Backlog, To Do, In Progress, Review, Done
- **Drag & drop** stories between columns
- **Real-time state persistence** (localStorage)
- **Search functionality** across all stories
- **Story details modal** with full content
- **Progress tracking** with statistics
- **Save/Reset** functionality
- **FloDoc design system** with purple theme
- **Keyboard shortcuts** (Escape to close modal)
### 📄 `stories-viewer-enhanced.html` (120KB)
Enhanced presentation with left navigation panel and main content area.
**Features:**
- **Left navigation panel** with all stories organized by phase
- **Main content area** for viewing selected story details
- **Search functionality** to find stories quickly
- **Expandable phases** for easy navigation
- **Keyboard navigation** (Arrow keys, Space, Escape)
- **Mobile responsive** with hamburger menu
- **Professional design** following FloDoc design system
### 📄 `stories-presentation.html` (117KB)
The original presentation website with 42 full-viewport slides.
**Features:**
- Full-screen slides for each story
- Navigation: Arrow keys, buttons, or swipe
- Progress bar showing completion
- Clean, professional design
### 📄 `STORIES_SUMMARY.md` (11KB)
Quick reference guide with all stories in markdown format.
### 📄 `generate_presentation.py` (14KB)
Python script that parses the epic details and generates the presentation.
### 📄 `populate_github_project.py` (8KB)
Python script to populate GitHub Projects board with user stories.
### 📄 `populate_github_project.sh` (5KB)
Shell script (recommended) to populate GitHub Projects board using GitHub CLI.
### 📄 `GITHUB_PROJECT_SETUP.md` (8KB)
Complete setup and usage guide for GitHub Projects integration.
## GitHub Projects Integration ⭐ NEW
Automatically populate your GitHub project board with all 42 user stories!
### Quick Start (Recommended)
```bash
# 1. Install GitHub CLI (if not already installed)
# https://cli.github.com/
# 2. Authenticate
gh auth login
# 3. Install gh-project extension
gh extension install mislav/gh-project
# 4. Run the populator
./populate_github_project.sh NeoSkosana floDoc-v3 6
```
**What you get:**
- ✅ 42 GitHub issues created (one per story)
- ✅ Issues added to your project board automatically
- ✅ Labels applied (epic, priority, risk, portal type)
- ✅ Summary file generated with all story details
**See `GITHUB_PROJECT_SETUP.md` for detailed instructions.**
## How to Use
### View the Presentation
**Option 1: Open in Browser**
```bash
# Navigate to the backlog directory
cd docs/backlog
# Open in your default browser
open stories-presentation.html
# or
xdg-open stories-presentation.html
# or simply double-click the file
```
**Option 2: Serve Locally**
```bash
# Python 3
python3 -m http.server 8000
# Then open: http://localhost:8000/stories-presentation.html
```
### Navigation
- **Next Slide**: `→` Arrow key, `Space`, or click "Next" button
- **Previous Slide**: `←` Arrow key or click "Previous" button
- **Progress**: Top bar shows completion percentage
- **Counter**: Shows current slide / total slides
### Story Structure
Each slide contains:
1. **User Story**: The "As a... I want... So that..." format
2. **Background**: Context and rationale for the story
3. **Acceptance Criteria**: Functional, UI/UX, Integration, Security, and Quality requirements
## Story Breakdown by Epic
### Phase 1: Foundation (3 stories)
- 1.1: Database Schema Extension
- 1.2: Core Models Implementation
- 1.3: Authorization Layer Extension
### Phase 2: Backend Logic (8 stories)
- 2.1: Cohort Creation & Management
- 2.2: TP Signing Phase Logic (High Risk - Prototype First)
- 2.3: Student Enrollment Management
- 2.4: Sponsor Review Workflow
- 2.5: TP Review & Finalization
- 2.6: Excel Export for Cohort Data
- 2.7: Audit Log & Compliance
- 2.8: Cohort State Machine & Workflow Orchestration
### Phase 3: API Layer (4 stories)
- 3.1: RESTful Cohort Management API
- 3.2: Webhook Events for Workflow State Changes
- 3.3: Student API (Ad-hoc Token-Based Access)
- 3.4: API Documentation & Versioning
### Phase 4: Admin Portal (10 stories)
- 4.1: Cohort Management Dashboard
- 4.2: Cohort Creation & Bulk Import
- 4.3: Cohort Detail Overview
- 4.4: TP Signing Interface
- 4.5: Student Management View
- 4.6: Sponsor Portal Dashboard
- 4.7: Sponsor Portal - Bulk Document Signing
- 4.8: Sponsor Portal - Progress Tracking & State Management
- 4.9: Sponsor Portal - Token Renewal & Session Management
- 4.10: TP Portal - Cohort Status Monitoring & Analytics
### Phase 5: Student Portal (5 stories)
- 5.1: Student Portal - Document Upload Interface
- 5.2: Student Portal - Form Filling & Field Completion
- 5.3: Student Portal - Progress Tracking & Save Draft
- 5.4: Student Portal - Submission Confirmation & Status
- 5.5: Student Portal - Email Notifications & Reminders
### Phase 6: Sponsor Portal (2 stories)
- 6.1: Sponsor Portal - Cohort Dashboard & Bulk Signing Interface
- 6.2: Sponsor Portal - Email Notifications & Reminders
### Phase 7: Testing & QA (5 stories)
- 7.1: End-to-End Workflow Testing
- 7.2: Mobile Responsiveness Testing
- 7.3: Performance Testing (50+ Students)
- 7.4: Security Audit & Penetration Testing
- 7.5: User Acceptance Testing
### Phase 8: Infrastructure & Documentation (4 stories)
- 8.0: Development Infrastructure Setup (Local Docker)
- 8.0.1: Management Demo Readiness & Validation
- 8.5: User Communication & Training Materials
- 8.6: In-App User Documentation & Help System
- 8.7: Knowledge Transfer & Operations Documentation
## Regenerating the Presentation
If the source document changes, regenerate the presentation:
```bash
cd docs/backlog
python3 generate_presentation.py
```
## Design Notes
- **Time Limit**: Each story is designed for 4-hour implementation windows
- **Viewport**: Each slide uses full viewport for focused reading
- **Mobile Responsive**: Works on tablets and phones
- **No External Dependencies**: Pure HTML/CSS/JS, works offline
- **Keyboard Navigation**: Accessible via keyboard only
## Next Steps
1. Review all stories in the presentation
2. Prioritize stories for implementation
3. Create individual story branches following BMAD workflow
4. Implement stories with QA gates
5. Merge to master after approval
## GitHub Projects Output
After running the populator script, you'll get:
### Generated Files
1. **`github_project_summary.md`** - Complete story reference with:
- All 42 stories organized by epic
- Metadata (priority, risk, effort, status)
- Links to GitHub issues
- Quick reference tables
2. **GitHub Issues** - 42 issues created in your repository with:
- Full story details (User Story, Background, Acceptance Criteria)
- Metadata in issue body
- Labels for filtering and organization
3. **Project Board Cards** - Issues added to your project board:
- Ready to drag between columns
- Visual progress tracking
- Team collaboration
### Example Issue Title
```
[1.1] Database Schema Extension
```
### Labels Applied
- `epic:phase-1-foundation`
- `priority:critical`
- `risk:low`
- `status:draft`
- `portal:backend`
- `story:1.1`
## Contact
For questions about specific stories, refer to the original epic details:
- Source: `docs/prd/6-epic-details.md`
- Total size: 832KB
- Total stories: 42
For GitHub Projects integration help:
- Guide: `docs/backlog/GITHUB_PROJECT_SETUP.md`
- Scripts: `populate_github_project.sh` (recommended) or `populate_github_project.py`

@ -0,0 +1,137 @@
# FloDoc Stories Index - All 42 Stories
## 📋 Complete Story List
### Phase 1: Foundation (Stories 1.1 - 1.3)
| # | Story | Focus | Time |
|---|-------|-------|------|
| 1.1 | **Database Schema Extension** | Create 3 new tables (institutions, cohorts, cohort_enrollments) | 2-3 days |
| 1.2 | **Core Models Implementation** | ActiveRecord models with associations & validations | 2 days |
| 1.3 | **Authorization Layer Extension** | Cancancan abilities for 3-portal access control | 1-2 days |
### Phase 2: Backend Logic (Stories 2.1 - 2.8)
| # | Story | Focus | Time |
|---|-------|-------|------|
| 2.1 | **Cohort Creation & Management** | TP admin creates/manages cohorts | 4 hours |
| 2.2 | **TP Signing Phase Logic** | Prototype: Sign once, replicate to all students | 4 hours |
| 2.3 | **Student Enrollment Management** | Bulk create student submissions | 4 hours |
| 2.4 | **Sponsor Review Workflow** | Sponsor receives and reviews documents | 4 hours |
| 2.5 | **TP Review & Finalization** | TP reviews all submissions, finalizes cohort | 4 hours |
| 2.6 | **Excel Export for Cohort Data** | Export cohort data to Excel (FR23) | 4 hours |
| 2.7 | **Audit Log & Compliance** | Track all actions for compliance | 4 hours |
| 2.8 | **Cohort State Machine** | Workflow orchestration & state tracking | 4 hours |
### Phase 3: API Layer (Stories 3.1 - 3.4)
| # | Story | Focus | Time |
|---|-------|-------|------|
| 3.1 | **RESTful Cohort Management API** | CRUD APIs for cohorts | 4 hours |
| 3.2 | **Webhook Events** | State change notifications | 4 hours |
| 3.3 | **Student API (Ad-hoc)** | Token-based student access | 4 hours |
| 3.4 | **API Documentation** | OpenAPI/Swagger docs | 4 hours |
### Phase 4: Admin Portal (Stories 4.1 - 4.10)
| # | Story | Focus | Time |
|---|-------|-------|------|
| 4.1 | **Cohort Management Dashboard** | Overview of all cohorts | 4 hours |
| 4.2 | **Cohort Creation & Bulk Import** | Create cohorts + import students | 4 hours |
| 4.3 | **Cohort Detail Overview** | Single cohort view with status | 4 hours |
| 4.4 | **TP Signing Interface** | TP signing workflow UI | 4 hours |
| 4.5 | **Student Management View** | Manage student enrollments | 4 hours |
| 4.6 | **Sponsor Portal Dashboard** | Sponsor's cohort overview | 4 hours |
| 4.7 | **Sponsor Portal - Bulk Signing** | Sign multiple documents at once | 4 hours |
| 4.8 | **Sponsor Portal - Progress Tracking** | View completion status | 4 hours |
| 4.9 | **Sponsor Portal - Token Renewal** | Session management for ad-hoc access | 4 hours |
| 4.10 | **TP Portal - Monitoring & Analytics** | Cohort analytics dashboard | 4 hours |
### Phase 5: Student Portal (Stories 5.1 - 5.5)
| # | Story | Focus | Time |
|---|-------|-------|------|
| 5.1 | **Student Portal - Document Upload** | Upload required documents | 4 hours |
| 5.2 | **Student Portal - Form Filling** | Complete form fields | 4 hours |
| 5.3 | **Student Portal - Progress & Draft** | Save progress, resume later | 4 hours |
| 5.4 | **Student Portal - Submission Confirmation** | Final submission UI | 4 hours |
| 5.5 | **Student Portal - Email Notifications** | Email reminders & updates | 4 hours |
### Phase 6: Sponsor Portal (Stories 6.1 - 6.2)
| # | Story | Focus | Time |
|---|-------|-------|------|
| 6.1 | **Sponsor Portal - Dashboard & Bulk Signing** | Cohort overview + bulk sign | 4 hours |
| 6.2 | **Sponsor Portal - Email Notifications** | Sponsor email workflow | 4 hours |
### Phase 7: Testing & QA (Stories 7.1 - 7.5)
| # | Story | Focus | Time |
|---|-------|-------|------|
| 7.1 | **End-to-End Workflow Testing** | Complete workflow validation | 4 hours |
| 7.2 | **Mobile Responsiveness Testing** | Mobile/tablet compatibility | 4 hours |
| 7.3 | **Performance Testing (50+ Students)** | Load testing with 50+ students | 4 hours |
| 7.4 | **Security Audit & Penetration Testing** | Security validation | 4 hours |
| 7.5 | **User Acceptance Testing** | PO/Management validation | 4 hours |
### Phase 8: Infrastructure & Documentation (Stories 8.0 - 8.7)
| # | Story | Focus | Time |
|---|-------|-------|------|
| 8.0 | **Development Infrastructure Setup** | Local Docker environment | 4 hours |
| 8.0.1 | **Management Demo Readiness** | Demo scripts & validation | 4 hours |
| 8.5 | **User Communication & Training** | Training materials | 4 hours |
| 8.6 | **In-App User Documentation** | Help system in app | 4 hours |
| 8.7 | **Knowledge Transfer & Ops Docs** | Operations documentation | 4 hours |
## 📊 Summary Statistics
- **Total Stories:** 42
- **Total Estimated Time:** ~168 hours (4 hours per story)
- **Total Phases:** 8
- **Stories per Phase:**
- Phase 1: 3 stories
- Phase 2: 8 stories
- Phase 3: 4 stories
- Phase 4: 10 stories
- Phase 5: 5 stories
- Phase 6: 2 stories
- Phase 7: 5 stories
- Phase 8: 5 stories
## 🎯 Quick Reference by Portal
### Admin Portal (TP)
- Stories: 4.1, 4.2, 4.3, 4.4, 4.5, 4.10
- Focus: Cohort management, student enrollment, signing workflow
### Student Portal
- Stories: 5.1, 5.2, 5.3, 5.4, 5.5
- Focus: Document upload, form filling, submission
### Sponsor Portal
- Stories: 4.6, 4.7, 4.8, 4.9, 6.1, 6.2
- Focus: Review, bulk signing, progress tracking
### Backend/Infrastructure
- Stories: 1.x, 2.x, 3.x, 7.x, 8.x
- Focus: Database, models, APIs, testing, deployment
## 📖 How to Use This Index
1. **Find stories by phase** - Use the phase numbers
2. **Find stories by portal** - Use the portal sections
3. **Check time estimates** - Plan sprint capacity
4. **Cross-reference** - Use story numbers with the presentation
## 🔗 Related Files
- **stories-presentation.html** - Full interactive presentation
- **STORIES_SUMMARY.md** - Quick user story reference
- **README.md** - Overview and usage guide
- **QUICKSTART.md** - Quick start instructions
---
**Generated:** 2026-01-15
**Source:** `docs/prd/6-epic-details.md`

@ -0,0 +1,384 @@
# FloDoc User Stories - Summary
**Total Stories:** 42
## Quick Reference
### 1.1: Database Schema Extension
**User Story:**
**As a** system architect,
**I want** to create the database schema for FloDoc's new models,
**So that** the application has the foundation to support cohort management.
---
### 1.2: Core Models Implementation
**User Story:**
**As a** developer,
**I want** to create ActiveRecord models for the new FloDoc tables,
**So that** the application can interact with cohorts and enrollments programmatically.
---
### 1.3: Authorization Layer Extension
**User Story:**
**As a** system administrator,
**I want** the authorization system to support FloDoc roles and permissions,
**So that** users can only access appropriate cohort management functions.
---
### 2.1: Cohort Creation & Management
**User Story:**
**As a** TP (Training Provider) administrator,
**I want** to create and manage cohorts with all their configuration details,
**So that** I can organize students into training programs and prepare them for the signature workflow.
---
### 2.2: TP Signing Phase Logic (High Risk - Prototype First)
**User Story:**
**As a** TP administrator,
**I want** to sign the first student's document and have that signing replicated to all other students in the cohort,
**So that** I don't need to sign each student's document individually, saving time and eliminating duplicate sponsor emails.
---
### 2.3: Student Enrollment Management
**User Story:**
**As a** TP administrator,
**I want** to manage student enrollment in cohorts and bulk-create student submissions,
**So that** students can access their documents to complete after TP signs.
---
### 2.4: Sponsor Review Workflow
**User Story:**
**As a** Sponsor,
**I want** to review all student documents in my cohort and sign them in bulk,
**So that** I can complete the verification workflow efficiently.
---
### 2.5: TP Review & Finalization
**User Story:**
**As a** TP administrator,
**I want** to review the sponsor-verified submissions and finalize the cohort,
**So that** the entire 3-party signature workflow is completed and documents are ready for archival.
---
### 2.6: Excel Export for Cohort Data
**User Story:**
**As a** TP administrator,
**I want** to export cohort enrollment data to Excel,
**So that** I can perform additional analysis or reporting outside the system.
---
### 2.7: Audit Log & Compliance
**User Story:**
**As a** TP administrator,
**I want** comprehensive audit logs of all cohort workflow activities,
**So that** we can demonstrate compliance and trace any issues.
---
### 2.8: Cohort State Machine & Workflow Orchestration
**User Story:**
**As a** system,
**I want** to manage cohort state transitions and workflow enforcement,
**So that** the 3-party signature workflow follows the correct sequence and prevents invalid operations.
---
### 3.1: RESTful Cohort Management API
**User Story:**
**As a** TP administrator or external system integrator,
**I want** to create, read, update, and delete cohorts via REST API,
**So that** I can automate cohort management and integrate with other systems.
---
### 3.2: Webhook Events for Workflow State Changes
**User Story:**
**As a** TP administrator,
**I want** webhook notifications for all cohort workflow events,
**So that** external systems can react to state changes in real-time.
---
### 3.3: Student API (Ad-hoc Token-Based Access)
**User Story:**
**As a** student with a cohort link,
**I want** a simple token-based API to access and complete my documents,
**So that** I can fulfill my requirements without account creation.
---
### 3.4: API Documentation & Versioning
**User Story:**
**As a** developer integrating with FloDoc,
**I want** comprehensive API documentation and stable versioning,
**So that** I can build reliable integrations without breaking changes.
---
### 4.1: Cohort Management Dashboard
**User Story:**
**As a** TP administrator,
**I want** a dashboard to view and manage all cohorts,
**So that** I can monitor the 3-party workflow at a glance.
---
### 4.2: Cohort Creation & Bulk Import
**User Story:**
**As a** TP administrator,
**I want** to create new cohorts and bulk-import students via Excel,
**So that** I can efficiently onboard large groups without manual data entry.
---
### 4.3: Cohort Detail Overview
**User Story:**
**As a** TP administrator,
**I want** to view detailed information about a specific cohort, including student list, progress status, and document workflow,
**So that** I can monitor and manage the cohort effectively.
---
### 4.4: TP Signing Interface
**User Story:**
**As a** TP administrator,
**I want** to sign the first student's document and have it automatically replicated to all other students,
**So that** I can sign once instead of signing each student's document individually.
---
### 4.5: Student Management View
**User Story:**
**As a** TP administrator,
**I want** to view and manage individual student details, including their document status and uploaded files,
**So that** I can track student progress and troubleshoot issues.
---
### 4.6: Sponsor Portal Dashboard
**User Story:**
**As a** Sponsor,
**I want** to access a dedicated portal where I can review and verify all student documents for a cohort,
**So that** I can sign once for the entire cohort instead of signing each student individually.
---
### 4.7: Sponsor Portal - Bulk Document Signing
**User Story:**
**As a** Sponsor,
**I want** to sign once and have that signature applied to all pending student documents,
**So that** I don't need to manually sign each student's documents individually.
---
### 4.8: Sponsor Portal - Progress Tracking & State Management
**User Story:**
**As a** Sponsor,
**I want** to see real-time progress tracking with clear visual indicators of which students have completed their documents and which are still pending,
**So that** I can monitor the signing workflow and know exactly when to proceed with bulk signing.
---
### 4.9: Sponsor Portal - Token Renewal & Session Management
**User Story:**
**As a** Sponsor,
**I want** to renew my access token if it expires while I'm reviewing documents,
**So that** I can complete my signing workflow without losing progress or being locked out.
---
### 4.10: TP Portal - Cohort Status Monitoring & Analytics
**User Story:**
**As a** Training Provider,
**I want** to monitor all cohorts with real-time status updates and analytics,
**So that** I can track progress, identify bottlenecks, and manage my document signing workflows efficiently.
---
### 5.1: Student Portal - Document Upload Interface
**User Story:**
**As a** Student,
**I want** to upload required documents (ID, certificates, etc.) through a simple interface,
**So that** I can provide the necessary proof documents for my cohort enrollment.
---
### 5.2: Student Portal - Form Filling & Field Completion
**User Story:**
**As a** Student,
**I want** to fill in my assigned form fields (personal info, signatures, dates, etc.),
**So that** I can complete my portion of the document before the sponsor signs.
---
### 5.3: Student Portal - Progress Tracking & Save Draft
**User Story:**
**As a** Student,
**I want** to see my overall progress and save my work as a draft at any time,
**So that** I can complete the submission at my own pace without losing work.
---
### 5.4: Student Portal - Submission Confirmation & Status
**User Story:**
**As a** Student,
**I want** to review my complete submission and receive confirmation of successful submission,
**So that** I can verify everything is correct and track when the sponsor signs.
---
### 5.5: Student Portal - Email Notifications & Reminders
**User Story:**
**As a** Student,
**I want** to receive email notifications for status updates and reminders to complete my submission,
**So that** I can stay informed and complete my work on time without constantly checking the portal.
---
### 6.1: Sponsor Portal - Cohort Dashboard & Bulk Signing Interface
**User Story:**
**As a** Sponsor,
**I want** to view all pending student documents in a cohort and sign them all at once,
**So that** I can efficiently complete my signing responsibility without reviewing each submission individually.
---
### 6.2: Sponsor Portal - Email Notifications & Reminders
**User Story:**
**As a** Sponsor,
**I want** to receive email notifications about signing requests and reminders to complete my cohort signing,
**So that** I can stay informed and fulfill my signing responsibility on time without constantly checking the portal.
---
### 7.1: End-to-End Workflow Testing
**User Story:**
**As a** QA Engineer,
**I want** to test the complete 3-portal workflow from start to finish,
**So that** I can verify all integrations work correctly and identify any breaking issues before production deployment.
---
### 7.2: Mobile Responsiveness Testing
**User Story:**
**As a** QA Engineer,
**I want** to test all three portals across different screen sizes and devices,
**So that** I can ensure the FloDoc system works perfectly on mobile, tablet, and desktop devices.
---
### 7.3: Performance Testing (50+ Students)
**User Story:**
**As a** QA Engineer,
**I want** to test system performance with large cohorts (50+ students),
**So that** I can ensure FloDoc scales efficiently and meets NFR requirements.
---
### 7.4: Security Audit & Penetration Testing
**User Story:**
**As a** Security Engineer,
**I want** to perform comprehensive security testing on all three portals,
**So that** I can identify and remediate vulnerabilities before production deployment.
---
### 7.5: User Acceptance Testing
**User Story:**
**As a** Product Owner,
**I want** to conduct comprehensive user acceptance testing with real stakeholders,
**So that** I can validate the system meets business requirements and user needs before production launch.
---
### 8.0: Development Infrastructure Setup (Local Docker)
**User Story:**
**As a** Developer,
**I want** to set up a local Docker-based development infrastructure with PostgreSQL and Redis,
**So that** I can demonstrate the complete FloDoc system to management without cloud costs or complexity.
---
### 8.0.1: Management Demo Readiness & Validation
**User Story:**
**As a** Product Manager,
**I want** to validate the complete 3-portal cohort management workflow end-to-end,
**So that** I can demonstrate FloDoc v3 to management with confidence and real data.
---
### 8.5: User Communication & Training Materials
**User Story:**
**As a** Training Provider (TP Admin),
**I want** clear guidance on using FloDoc's 3-portal system,
**So that** I can manage cohorts effectively without confusion.
---
### 8.6: In-App User Documentation & Help System
**User Story:**
**As a** User (TP Admin, Student, or Sponsor),
**I want** contextual help and documentation,
**So that** I can solve problems without contacting support.
---
### 8.7: Knowledge Transfer & Operations Documentation
**User Story:**
**As a** Support/Operations Team,
**I want** comprehensive runbooks and documentation,
**So that** I can support FloDoc without ad-hoc knowledge transfer.
---

@ -0,0 +1,259 @@
#!/usr/bin/env python3
"""
Script to parse epic details markdown and generate a presentation-style website
showing all user stories with User Story, Background, and Acceptance Criteria.
"""
import re
from pathlib import Path
def parse_epic_details(file_path):
"""Parse the epic details markdown file and extract stories."""
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
# Split by stories
story_pattern = r'### Story ([\d.]+): (.+?)\n\n(.*?)(?=\n### Story [\d.]+:|$)'
matches = re.findall(story_pattern, content, re.DOTALL)
stories = []
for story_num, title, body in matches:
# Extract User Story
user_story_match = re.search(r'#### User Story\n\n(.*?)(?=\n####|$)', body, re.DOTALL)
user_story = user_story_match.group(1).strip() if user_story_match else "Not found"
# Extract Background
background_match = re.search(r'#### Background\n\n(.*?)(?=\n####|$)', body, re.DOTALL)
background = background_match.group(1).strip() if background_match else "Not found"
# Extract Acceptance Criteria
acceptance_match = re.search(r'#### Acceptance Criteria\n\n(.*?)(?=\n####|$)', body, re.DOTALL)
acceptance = acceptance_match.group(1).strip() if acceptance_match else "Not found"
# Clean up content
user_story = clean_content(user_story)
background = clean_content(background)
acceptance = clean_content(acceptance)
stories.append({
'number': story_num,
'title': title,
'user_story': user_story,
'background': background,
'acceptance': acceptance
})
return stories
def clean_content(text):
"""Clean and escape content for HTML/JS embedding."""
if not text:
return ""
# Replace problematic characters but preserve meaningful formatting
text = text.replace('\\', '\\\\')
text = text.replace("'", "\\'")
text = text.replace('"', '\\"')
text = text.replace('\n', '\\n')
return text
def generate_html(stories):
"""Generate the HTML presentation website."""
# Build the HTML structure
html_parts = [
'<!DOCTYPE html>',
'<html lang="en">',
'<head>',
' <meta charset="UTF-8">',
' <meta name="viewport" content="width=device-width, initial-scale=1.0">',
' <title>FloDoc User Stories - Epic Details</title>',
' <style>',
' * { margin: 0; padding: 0; box-sizing: border-box; }',
' body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); height: 100vh; overflow: hidden; }',
' .slide-container { width: 100vw; height: 100vh; display: flex; justify-content: center; align-items: center; padding: 2rem; }',
' .slide { width: 90%; max-width: 1200px; height: 90%; background: white; border-radius: 20px; box-shadow: 0 20px 60px rgba(0,0,0,0.3); padding: 3rem; overflow-y: auto; display: none; animation: fadeIn 0.5s ease-in-out; }',
' .slide.active { display: block; }',
' @keyframes fadeIn { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } }',
' .slide-header { border-bottom: 3px solid #667eea; padding-bottom: 1rem; margin-bottom: 2rem; }',
' .story-number { font-size: 1.2rem; color: #667eea; font-weight: 600; margin-bottom: 0.5rem; }',
' .story-title { font-size: 2rem; font-weight: 700; color: #1a202c; line-height: 1.3; }',
' .section { margin-bottom: 2rem; }',
' .section-title { font-size: 1.3rem; font-weight: 600; color: #667eea; margin-bottom: 1rem; display: flex; align-items: center; gap: 0.5rem; }',
' .section-title::before { content: ""; width: 4px; height: 24px; background: #667eea; border-radius: 2px; }',
' .section-content { background: #f7fafc; padding: 1.5rem; border-radius: 8px; line-height: 1.8; color: #2d3748; font-size: 1rem; }',
' .section-content strong { color: #667eea; }',
' .section-content ul, .section-content ol { margin-left: 1.5rem; margin-top: 0.5rem; }',
' .section-content li { margin-bottom: 0.5rem; }',
' .section-content code { background: #edf2f7; padding: 0.2rem 0.4rem; border-radius: 4px; font-family: "Courier New", monospace; font-size: 0.9rem; }',
' .navigation { position: fixed; bottom: 2rem; left: 50%; transform: translateX(-50%); background: rgba(255,255,255,0.95); padding: 1rem 2rem; border-radius: 50px; box-shadow: 0 4px 20px rgba(0,0,0,0.2); display: flex; gap: 1rem; align-items: center; z-index: 1000; }',
' .nav-btn { background: #667eea; color: white; border: none; padding: 0.75rem 1.5rem; border-radius: 25px; cursor: pointer; font-weight: 600; transition: all 0.3s ease; font-size: 1rem; }',
' .nav-btn:hover { background: #5568d3; transform: translateY(-2px); box-shadow: 0 4px 12px rgba(102,126,234,0.4); }',
' .nav-btn:disabled { background: #cbd5e0; cursor: not-allowed; transform: none; }',
' .nav-btn.secondary { background: #718096; }',
' .nav-btn.secondary:hover { background: #4a5568; }',
' .progress-bar { position: fixed; top: 0; left: 0; height: 4px; background: #667eea; transition: width 0.3s ease; z-index: 1001; }',
' .slide-counter { font-weight: 600; color: #4a5568; min-width: 100px; text-align: center; }',
' .slide::-webkit-scrollbar { width: 8px; }',
' .slide::-webkit-scrollbar-track { background: #f1f1f1; border-radius: 10px; }',
' .slide::-webkit-scrollbar-thumb { background: #667eea; border-radius: 10px; }',
' .slide::-webkit-scrollbar-thumb:hover { background: #5568d3; }',
' @media (max-width: 768px) { .slide { padding: 1.5rem; width: 95%; } .story-title { font-size: 1.5rem; } .section-title { font-size: 1.1rem; } .section-content { font-size: 0.9rem; padding: 1rem; } .navigation { padding: 0.75rem 1rem; gap: 0.5rem; } .nav-btn { padding: 0.5rem 1rem; font-size: 0.9rem; } }',
' .loading { text-align: center; padding: 2rem; color: white; font-size: 1.5rem; }',
' </style>',
'</head>',
'<body>',
' <div class="progress-bar" id="progressBar"></div>',
' <div id="slidesContainer"><div class="loading">Loading stories...</div></div>',
' <div class="navigation" id="navigation" style="display: none;">',
' <button class="nav-btn secondary" id="prevBtn" onclick="prevSlide()">← Previous</button>',
' <span class="slide-counter" id="slideCounter">1 / 32</span>',
' <button class="nav-btn" id="nextBtn" onclick="nextSlide()">Next →</button>',
' </div>',
' <script>',
' const stories = [];',
' let currentSlide = 0;',
' function initializeSlides() {',
' const container = document.getElementById("slidesContainer");',
' container.innerHTML = "";',
' stories.forEach((story, index) => {',
' const slide = document.createElement("div");',
' slide.className = "slide";',
' slide.id = `slide-${index}`;',
' slide.innerHTML = `',
' <div class="slide-header">',
' <div class="story-number">Story ${story.number}</div>',
' <div class="story-title">${story.title}</div>',
' </div>',
' <div class="section">',
' <div class="section-title">User Story</div>',
' <div class="section-content">${formatContent(story.user_story)}</div>',
' </div>',
' <div class="section">',
' <div class="section-title">Background</div>',
' <div class="section-content">${formatContent(story.background)}</div>',
' </div>',
' <div class="section">',
' <div class="section-title">Acceptance Criteria</div>',
' <div class="section-content">${formatContent(story.acceptance)}</div>',
' </div>',
' `;',
' container.appendChild(slide);',
' });',
' showSlide(0);',
' document.getElementById("navigation").style.display = "flex";',
' }',
' function formatContent(text) {',
' if (!text) return "";',
' let html = text;',
' html = html.replace(/\\*\\*(.+?)\\*\\*/g, "<strong>$1</strong>");',
' html = html.replace(/^[\\*\\-]\\s+(.+)$/gm, "<li>$1</li>");',
' html = html.replace(/(<li>.*<\\/li>)/s, "<ul>$1</ul>");',
' html = html.replace(/^\\d+\\.\\s+(.+)$/gm, "<li>$1</li>");',
' html = html.replace(/(<li>.*<\\/li>)/s, "<ul>$1</ul>");',
' html = html.replace(/\\n\\n/g, "</p><p>");',
' html = "<p>" + html + "</p>";',
' html = html.replace(/<p><ul>/g, "<ul>");',
' html = html.replace(/<\\/ul><\\/p>/g, "</ul>");',
' html = html.replace(/<p><\\/p>/g, "");',
' return html;',
' }',
' function showSlide(index) {',
' const slides = document.querySelectorAll(".slide");',
' slides.forEach((slide, i) => { slide.classList.toggle("active", i === index); });',
' currentSlide = index;',
' updateNavigation();',
' updateProgress();',
' }',
' function updateNavigation() {',
' const prevBtn = document.getElementById("prevBtn");',
' const nextBtn = document.getElementById("nextBtn");',
' const counter = document.getElementById("slideCounter");',
' prevBtn.disabled = currentSlide === 0;',
' nextBtn.disabled = currentSlide === stories.length - 1;',
' counter.textContent = `${currentSlide + 1} / ${stories.length}`;',
' }',
' function updateProgress() {',
' const progress = ((currentSlide + 1) / stories.length) * 100;',
' document.getElementById("progressBar").style.width = progress + "%";',
' }',
' function nextSlide() { if (currentSlide < stories.length - 1) showSlide(currentSlide + 1); }',
' function prevSlide() { if (currentSlide > 0) showSlide(currentSlide - 1); }',
' document.addEventListener("keydown", (e) => {',
' if (e.key === "ArrowRight" || e.key === " ") { e.preventDefault(); nextSlide(); }',
' else if (e.key === "ArrowLeft") { e.preventDefault(); prevSlide(); }',
' });',
]
# Add stories data
html_parts.append(' const storiesData = [')
for story in stories:
html_parts.append(' {')
html_parts.append(f' number: "{story["number"]}",')
html_parts.append(f' title: "{story["title"]}",')
html_parts.append(f' user_story: "{story["user_story"]}",')
html_parts.append(f' background: "{story["background"]}",')
html_parts.append(f' acceptance: "{story["acceptance"]}",')
html_parts.append(' },')
html_parts.append(' ];')
# Add initialization
html_parts.extend([
' if (document.readyState === "loading") {',
' document.addEventListener("DOMContentLoaded", () => {',
' stories.push(...storiesData);',
' initializeSlides();',
' });',
' } else {',
' stories.push(...storiesData);',
' initializeSlides();',
' }',
' </script>',
'</body>',
'</html>'
])
return '\n'.join(html_parts)
def main():
# Paths
epic_file = Path('/home/dev-mode/dev/dyict-projects/floDoc-v3/docs/prd/6-epic-details.md')
output_dir = Path('/home/dev-mode/dev/dyict-projects/floDoc-v3/docs/backlog')
output_html = output_dir / 'stories-presentation.html'
print("Parsing epic details file...")
stories = parse_epic_details(epic_file)
print(f"Found {len(stories)} stories")
print("Generating presentation HTML...")
html = generate_html(stories)
with open(output_html, 'w') as f:
f.write(html)
print(f"✅ Presentation generated: {output_html}")
print(f"📊 Total stories: {len(stories)}")
print("\nStories included:")
for story in stories:
print(f" - {story['number']}: {story['title']}")
# Also generate a summary markdown file
summary_md = output_dir / 'STORIES_SUMMARY.md'
with open(summary_md, 'w', encoding='utf-8') as f:
f.write("# FloDoc User Stories - Summary\n\n")
f.write(f"**Total Stories:** {len(stories)}\n\n")
f.write("## Quick Reference\n\n")
for story in stories:
f.write(f"### {story['number']}: {story['title']}\n\n")
f.write("**User Story:**\n")
# Unescape for markdown
user_story = story['user_story'].replace('\\n', '\n').replace('\\t', '\t')
user_story = user_story.replace("\\'", "'").replace('\\"', '"')
f.write(f"{user_story}\n\n")
f.write("---\n\n")
print(f"\n✅ Summary generated: {summary_md}")
if __name__ == '__main__':
main()

@ -0,0 +1,599 @@
# GitHub Project - User Stories Summary
**Generated:** 2026-01-15 15:40:50
**Total Stories:** 42
**Issues Created:** 41
## Stories Created
| # | Title | Status | Priority | Epic | Effort | Risk | Issue URL |
|---|-------|--------|----------|------|--------|------|-----------|
| 1.1 | **Database Schema Extension** | Draft | Critical | Phase 1 - Foundation | 2-3 days | Low | [Link](https://github.com/NeoSkosana/floDoc-v3/issues/28) |
| 1.2 | **Core Models Implementation** | Draft | Critical | Phase 1 - Foundation | 3-4 days | Low | [Link](https://github.com/NeoSkosana/floDoc-v3/issues/29) |
| 1.3 | **Authorization Layer Extension** | Draft | Critical | Phase 1 - Foundation | 2-3 days | Medium | [Link](https://github.com/NeoSkosana/floDoc-v3/issues/30) |
| 2.1 | **Cohort Creation & Management** | Draft | High | Phase 2 - Backend Business Logic | 3-4 days | Low | [Link](https://github.com/NeoSkosana/floDoc-v3/issues/31) |
| 2.2 | **TP Signing Phase Logic (High Risk - Prototype First)** | Draft | Critical | Phase 2 - Backend Business Logic | 4-5 days | High | [Link](https://github.com/NeoSkosana/floDoc-v3/issues/32) |
| 2.3 | **Student Enrollment Management** | Draft | High | Phase 2 - Backend Business Logic | 3-4 days | Medium | [Link](https://github.com/NeoSkosana/floDoc-v3/issues/33) |
| 2.4 | **Sponsor Review Workflow** | Draft | Medium | Phase 2 - Backend Business Logic | 2-3 days | Low | [Link](https://github.com/NeoSkosana/floDoc-v3/issues/34) |
| 2.5 | **TP Review & Finalization** | Draft | Medium | Phase 2 - Backend Business Logic | 2-3 days | Low | [Link](https://github.com/NeoSkosana/floDoc-v3/issues/35) |
| 2.6 | **Excel Export for Cohort Data** | Draft | Medium | Phase 2 - Backend Business Logic | 2-3 days | Low | [Link](https://github.com/NeoSkosana/floDoc-v3/issues/36) |
| 2.7 | **Audit Log & Compliance** | Draft | High | Phase 2 - Backend Business Logic | 2-3 days | Medium | [Link](https://github.com/NeoSkosana/floDoc-v3/issues/37) |
| 2.8 | **Cohort State Machine & Workflow Orchestration** | Draft | High | Phase 2 - Backend Business Logic | 2-3 days | Medium | [Link](https://github.com/NeoSkosana/floDoc-v3/issues/38) |
| 3.1 | **RESTful Cohort Management API** | Draft | Critical | Phase 3 - API Layer | 2-3 days | Low | [Link](https://github.com/NeoSkosana/floDoc-v3/issues/39) |
| 3.2 | **Webhook Events for Workflow State Changes** | Draft | Medium | Phase 3 - API Layer | 2-3 days | Low | [Link](https://github.com/NeoSkosana/floDoc-v3/issues/40) |
| 3.3 | **Student API (Ad-hoc Token-Based Access)** | Draft | Medium | Phase 3 - API Layer | 3-4 days | Medium | [Link](https://github.com/NeoSkosana/floDoc-v3/issues/41) |
| 3.4 | **API Documentation & Versioning** | Draft | Medium | Phase 3 - API Layer | 1-2 days | Low | [Link](https://github.com/NeoSkosana/floDoc-v3/issues/42) |
| 4.1 | **Cohort Management Dashboard** | Draft | High | Phase 4 - Frontend - TP Portal | 3-4 days | Low | [Link](https://github.com/NeoSkosana/floDoc-v3/issues/43) |
| 4.2 | **Cohort Creation & Bulk Import** | Draft | High | Phase 4 - Frontend - TP Portal | 2-3 days | Medium | [Link](https://github.com/NeoSkosana/floDoc-v3/issues/44) |
| 4.3 | **Cohort Detail Overview** | Draft | High | Phase 4 - Frontend - TP Portal | 2 days | Low | [Link](https://github.com/NeoSkosana/floDoc-v3/issues/45) |
| 4.4 | **TP Signing Interface** | Draft | High | Phase 4 - Frontend - TP Portal | 3-4 days | High | [Link](https://github.com/NeoSkosana/floDoc-v3/issues/46) |
| 4.5 | **Student Management View** | Draft | Medium | Phase 4 - Frontend - TP Portal | 2 days | Low | [Link](https://github.com/NeoSkosana/floDoc-v3/issues/47) |
| 4.6 | **Sponsor Portal Dashboard** | Draft | High | Phase 4 - Frontend - TP Portal | 3 days | Medium | [Link](https://github.com/NeoSkosana/floDoc-v3/issues/48) |
| 4.7 | **Sponsor Portal - Bulk Document Signing** | Draft/Pending | High | TP Portal - Frontend Development | 3 days | Medium | [Link](https://github.com/NeoSkosana/floDoc-v3/issues/49) |
| 4.8 | **Sponsor Portal - Progress Tracking & State Management** | Draft/Pending | High | TP Portal - Frontend Development | 2 days | Low | [Link](https://github.com/NeoSkosana/floDoc-v3/issues/50) |
| 4.9 | **Sponsor Portal - Token Renewal & Session Management** | Draft/Pending | High | TP Portal - Frontend Development | 2 days | Medium | [Link](https://github.com/NeoSkosana/floDoc-v3/issues/51) |
| 4.10 | **TP Portal - Cohort Status Monitoring & Analytics** | Draft/Pending | High | TP Portal - Frontend Development | 2 days | Low | [Link](https://github.com/NeoSkosana/floDoc-v3/issues/52) |
| 5.1 | **Student Portal - Document Upload Interface** | Draft/Pending | High | Student Portal - Frontend Development | 2 days | Low | [Link](https://github.com/NeoSkosana/floDoc-v3/issues/53) |
| 5.2 | **Student Portal - Form Filling & Field Completion** | Draft/Pending | High | Student Portal - Frontend Development | 3 days | Medium | [Link](https://github.com/NeoSkosana/floDoc-v3/issues/54) |
| 5.3 | **Student Portal - Progress Tracking & Save Draft** | Draft/Pending | High | Student Portal - Frontend Development | 2 days | Low | [Link](https://github.com/NeoSkosana/floDoc-v3/issues/55) |
| 5.4 | **Student Portal - Submission Confirmation & Status** | Draft/Pending | High | Student Portal - Frontend Development | 2 days | Low | [Link](https://github.com/NeoSkosana/floDoc-v3/issues/56) |
| 5.5 | **Student Portal - Email Notifications & Reminders** | Draft/Pending | High | Student Portal - Frontend Development | 2 days | Low | [Link](https://github.com/NeoSkosana/floDoc-v3/issues/57) |
| 6.1 | **Sponsor Portal - Cohort Dashboard & Bulk Signing Interface** | Draft/Pending | High | Sponsor Portal - Frontend Development | 3 days | Medium | [Link](https://github.com/NeoSkosana/floDoc-v3/issues/58) |
| 6.2 | **Sponsor Portal - Email Notifications & Reminders** | Draft/Pending | High | Sponsor Portal - Frontend Development | 2 days | Low | [Link](https://github.com/NeoSkosana/floDoc-v3/issues/59) |
| 7.1 | **End-to-End Workflow Testing** | Draft/Pending | Critical | Integration & Testing | 3 days | High | [Link](https://github.com/NeoSkosana/floDoc-v3/issues/60) |
| 7.2 | **Mobile Responsiveness Testing** | Draft/Pending | High | Integration & Testing | 2 days | Medium | [Link](https://github.com/NeoSkosana/floDoc-v3/issues/61) |
| 7.3 | **Performance Testing (50+ Students)** | Draft/Pending | Critical | Integration & Testing | 3 days | High | [Link](https://github.com/NeoSkosana/floDoc-v3/issues/62) |
| 7.4 | **Security Audit & Penetration Testing** | Draft/Pending | Critical | Integration & Testing | 3 days | High | [Link](https://github.com/NeoSkosana/floDoc-v3/issues/63) |
| 7.5 | **User Acceptance Testing** | Draft/Pending | High | Integration & Testing | 5 days | Medium | [Link](https://github.com/NeoSkosana/floDoc-v3/issues/64) |
| 8.0 | **Development Infrastructure Setup (Local Docker)** | Draft | High | Phase 8 - Deployment & Documentation | 2 days | Low | [Link](https://github.com/NeoSkosana/floDoc-v3/issues/65) |
| 8.0.1 | **Management Demo Readiness & Validation** | Draft | High | Phase 8 - Deployment & Documentation | 3 days | Low | [Link](https://github.com/NeoSkosana/floDoc-v3/issues/66) |
| 8.5 | **User Communication & Training Materials** | Draft | High (Blocking - Required Before Development) | Phase 8 - Deployment & Documentation | 2 days | Medium | [Link](https://github.com/NeoSkosana/floDoc-v3/issues/67) |
| 8.6 | **In-App User Documentation & Help System** | Draft (Deferred - Post-MVP) | Medium | Phase 8 - Deployment & Documentation | 1.5 days | Low | [Link](https://github.com/NeoSkosana/floDoc-v3/issues/68) |
| 8.7 | **Knowledge Transfer & Operations Documentation** | Draft (Deferred - Post-MVP) | Medium | Phase 8 - Deployment & Documentation | 1 day | Medium | ❌ Failed |
## Quick Reference
### 1.1: Database Schema Extension
**Status:** Draft | **Priority:** Critical | **Epic:** Phase 1 - Foundation
**Issue:** [https://github.com/NeoSkosana/floDoc-v3/issues/28](https://github.com/NeoSkosana/floDoc-v3/issues/28)
**User Story:**
**As a** system architect,
**I want** to create the database schema for FloDoc's new models,
**So that** the application has the foundation to support cohort management.
---
### 1.2: Core Models Implementation
**Status:** Draft | **Priority:** Critical | **Epic:** Phase 1 - Foundation
**Issue:** [https://github.com/NeoSkosana/floDoc-v3/issues/29](https://github.com/NeoSkosana/floDoc-v3/issues/29)
**User Story:**
**As a** developer,
**I want** to create ActiveRecord models for the new FloDoc tables,
**So that** the application can interact with cohorts and enrollments programmatically.
---
### 1.3: Authorization Layer Extension
**Status:** Draft | **Priority:** Critical | **Epic:** Phase 1 - Foundation
**Issue:** [https://github.com/NeoSkosana/floDoc-v3/issues/30](https://github.com/NeoSkosana/floDoc-v3/issues/30)
**User Story:**
**As a** system administrator,
**I want** the authorization system to support FloDoc roles and permissions,
**So that** users can only access appropriate cohort management functions.
---
### 2.1: Cohort Creation & Management
**Status:** Draft | **Priority:** High | **Epic:** Phase 2 - Backend Business Logic
**Issue:** [https://github.com/NeoSkosana/floDoc-v3/issues/31](https://github.com/NeoSkosana/floDoc-v3/issues/31)
**User Story:**
**As a** TP (Training Provider) administrator,
**I want** to create and manage cohorts with all their configuration details,
**So that** I can organize students into training programs and prepare them for the signature workflow.
---
### 2.2: TP Signing Phase Logic (High Risk - Prototype First)
**Status:** Draft | **Priority:** Critical | **Epic:** Phase 2 - Backend Business Logic
**Issue:** [https://github.com/NeoSkosana/floDoc-v3/issues/32](https://github.com/NeoSkosana/floDoc-v3/issues/32)
**User Story:**
**As a** TP administrator,
**I want** to sign the first student's document and have that signing replicated to all other students in the cohort,
**So that** I don't need to sign each student's document individually, saving time and eliminating duplicate sponsor emails.
---
### 2.3: Student Enrollment Management
**Status:** Draft | **Priority:** High | **Epic:** Phase 2 - Backend Business Logic
**Issue:** [https://github.com/NeoSkosana/floDoc-v3/issues/33](https://github.com/NeoSkosana/floDoc-v3/issues/33)
**User Story:**
**As a** TP administrator,
**I want** to manage student enrollment in cohorts and bulk-create student submissions,
**So that** students can access their documents to complete after TP signs.
---
### 2.4: Sponsor Review Workflow
**Status:** Draft | **Priority:** Medium | **Epic:** Phase 2 - Backend Business Logic
**Issue:** [https://github.com/NeoSkosana/floDoc-v3/issues/34](https://github.com/NeoSkosana/floDoc-v3/issues/34)
**User Story:**
**As a** Sponsor,
**I want** to review all student documents in my cohort and sign them in bulk,
**So that** I can complete the verification workflow efficiently.
---
### 2.5: TP Review & Finalization
**Status:** Draft | **Priority:** Medium | **Epic:** Phase 2 - Backend Business Logic
**Issue:** [https://github.com/NeoSkosana/floDoc-v3/issues/35](https://github.com/NeoSkosana/floDoc-v3/issues/35)
**User Story:**
**As a** TP administrator,
**I want** to review the sponsor-verified submissions and finalize the cohort,
**So that** the entire 3-party signature workflow is completed and documents are ready for archival.
---
### 2.6: Excel Export for Cohort Data
**Status:** Draft | **Priority:** Medium | **Epic:** Phase 2 - Backend Business Logic
**Issue:** [https://github.com/NeoSkosana/floDoc-v3/issues/36](https://github.com/NeoSkosana/floDoc-v3/issues/36)
**User Story:**
**As a** TP administrator,
**I want** to export cohort enrollment data to Excel,
**So that** I can perform additional analysis or reporting outside the system.
---
### 2.7: Audit Log & Compliance
**Status:** Draft | **Priority:** High | **Epic:** Phase 2 - Backend Business Logic
**Issue:** [https://github.com/NeoSkosana/floDoc-v3/issues/37](https://github.com/NeoSkosana/floDoc-v3/issues/37)
**User Story:**
**As a** TP administrator,
**I want** comprehensive audit logs of all cohort workflow activities,
**So that** we can demonstrate compliance and trace any issues.
---
### 2.8: Cohort State Machine & Workflow Orchestration
**Status:** Draft | **Priority:** High | **Epic:** Phase 2 - Backend Business Logic
**Issue:** [https://github.com/NeoSkosana/floDoc-v3/issues/38](https://github.com/NeoSkosana/floDoc-v3/issues/38)
**User Story:**
**As a** system,
**I want** to manage cohort state transitions and workflow enforcement,
**So that** the 3-party signature workflow follows the correct sequence and prevents invalid operations.
---
### 3.1: RESTful Cohort Management API
**Status:** Draft | **Priority:** Critical | **Epic:** Phase 3 - API Layer
**Issue:** [https://github.com/NeoSkosana/floDoc-v3/issues/39](https://github.com/NeoSkosana/floDoc-v3/issues/39)
**User Story:**
**As a** TP administrator or external system integrator,
**I want** to create, read, update, and delete cohorts via REST API,
**So that** I can automate cohort management and integrate with other systems.
---
### 3.2: Webhook Events for Workflow State Changes
**Status:** Draft | **Priority:** Medium | **Epic:** Phase 3 - API Layer
**Issue:** [https://github.com/NeoSkosana/floDoc-v3/issues/40](https://github.com/NeoSkosana/floDoc-v3/issues/40)
**User Story:**
**As a** TP administrator,
**I want** webhook notifications for all cohort workflow events,
**So that** external systems can react to state changes in real-time.
---
### 3.3: Student API (Ad-hoc Token-Based Access)
**Status:** Draft | **Priority:** Medium | **Epic:** Phase 3 - API Layer
**Issue:** [https://github.com/NeoSkosana/floDoc-v3/issues/41](https://github.com/NeoSkosana/floDoc-v3/issues/41)
**User Story:**
**As a** student with a cohort link,
**I want** a simple token-based API to access and complete my documents,
**So that** I can fulfill my requirements without account creation.
---
### 3.4: API Documentation & Versioning
**Status:** Draft | **Priority:** Medium | **Epic:** Phase 3 - API Layer
**Issue:** [https://github.com/NeoSkosana/floDoc-v3/issues/42](https://github.com/NeoSkosana/floDoc-v3/issues/42)
**User Story:**
**As a** developer integrating with FloDoc,
**I want** comprehensive API documentation and stable versioning,
**So that** I can build reliable integrations without breaking changes.
---
### 4.1: Cohort Management Dashboard
**Status:** Draft | **Priority:** High | **Epic:** Phase 4 - Frontend - TP Portal
**Issue:** [https://github.com/NeoSkosana/floDoc-v3/issues/43](https://github.com/NeoSkosana/floDoc-v3/issues/43)
**User Story:**
**As a** TP administrator,
**I want** a dashboard to view and manage all cohorts,
**So that** I can monitor the 3-party workflow at a glance.
---
### 4.2: Cohort Creation & Bulk Import
**Status:** Draft | **Priority:** High | **Epic:** Phase 4 - Frontend - TP Portal
**Issue:** [https://github.com/NeoSkosana/floDoc-v3/issues/44](https://github.com/NeoSkosana/floDoc-v3/issues/44)
**User Story:**
**As a** TP administrator,
**I want** to create new cohorts and bulk-import students via Excel,
**So that** I can efficiently onboard large groups without manual data entry.
---
### 4.3: Cohort Detail Overview
**Status:** Draft | **Priority:** High | **Epic:** Phase 4 - Frontend - TP Portal
**Issue:** [https://github.com/NeoSkosana/floDoc-v3/issues/45](https://github.com/NeoSkosana/floDoc-v3/issues/45)
**User Story:**
**As a** TP administrator,
**I want** to view detailed information about a specific cohort, including student list, progress status, and document workflow,
**So that** I can monitor and manage the cohort effectively.
---
### 4.4: TP Signing Interface
**Status:** Draft | **Priority:** High | **Epic:** Phase 4 - Frontend - TP Portal
**Issue:** [https://github.com/NeoSkosana/floDoc-v3/issues/46](https://github.com/NeoSkosana/floDoc-v3/issues/46)
**User Story:**
**As a** TP administrator,
**I want** to sign the first student's document and have it automatically replicated to all other students,
**So that** I can sign once instead of signing each student's document individually.
---
### 4.5: Student Management View
**Status:** Draft | **Priority:** Medium | **Epic:** Phase 4 - Frontend - TP Portal
**Issue:** [https://github.com/NeoSkosana/floDoc-v3/issues/47](https://github.com/NeoSkosana/floDoc-v3/issues/47)
**User Story:**
**As a** TP administrator,
**I want** to view and manage individual student details, including their document status and uploaded files,
**So that** I can track student progress and troubleshoot issues.
---
### 4.6: Sponsor Portal Dashboard
**Status:** Draft | **Priority:** High | **Epic:** Phase 4 - Frontend - TP Portal
**Issue:** [https://github.com/NeoSkosana/floDoc-v3/issues/48](https://github.com/NeoSkosana/floDoc-v3/issues/48)
**User Story:**
**As a** Sponsor,
**I want** to access a dedicated portal where I can review and verify all student documents for a cohort,
**So that** I can sign once for the entire cohort instead of signing each student individually.
---
### 4.7: Sponsor Portal - Bulk Document Signing
**Status:** Draft/Pending | **Priority:** High | **Epic:** TP Portal - Frontend Development
**Issue:** [https://github.com/NeoSkosana/floDoc-v3/issues/49](https://github.com/NeoSkosana/floDoc-v3/issues/49)
**User Story:**
**As a** Sponsor,
**I want** to sign once and have that signature applied to all pending student documents,
**So that** I don't need to manually sign each student's documents individually.
---
### 4.8: Sponsor Portal - Progress Tracking & State Management
**Status:** Draft/Pending | **Priority:** High | **Epic:** TP Portal - Frontend Development
**Issue:** [https://github.com/NeoSkosana/floDoc-v3/issues/50](https://github.com/NeoSkosana/floDoc-v3/issues/50)
**User Story:**
**As a** Sponsor,
**I want** to see real-time progress tracking with clear visual indicators of which students have completed their documents and which are still pending,
**So that** I can monitor the signing workflow and know exactly when to proceed with bulk signing.
---
### 4.9: Sponsor Portal - Token Renewal & Session Management
**Status:** Draft/Pending | **Priority:** High | **Epic:** TP Portal - Frontend Development
**Issue:** [https://github.com/NeoSkosana/floDoc-v3/issues/51](https://github.com/NeoSkosana/floDoc-v3/issues/51)
**User Story:**
**As a** Sponsor,
**I want** to renew my access token if it expires while I'm reviewing documents,
**So that** I can complete my signing workflow without losing progress or being locked out.
---
### 4.10: TP Portal - Cohort Status Monitoring & Analytics
**Status:** Draft/Pending | **Priority:** High | **Epic:** TP Portal - Frontend Development
**Issue:** [https://github.com/NeoSkosana/floDoc-v3/issues/52](https://github.com/NeoSkosana/floDoc-v3/issues/52)
**User Story:**
**As a** Training Provider,
**I want** to monitor all cohorts with real-time status updates and analytics,
**So that** I can track progress, identify bottlenecks, and manage my document signing workflows efficiently.
---
### 5.1: Student Portal - Document Upload Interface
**Status:** Draft/Pending | **Priority:** High | **Epic:** Student Portal - Frontend Development
**Issue:** [https://github.com/NeoSkosana/floDoc-v3/issues/53](https://github.com/NeoSkosana/floDoc-v3/issues/53)
**User Story:**
**As a** Student,
**I want** to upload required documents (ID, certificates, etc.) through a simple interface,
**So that** I can provide the necessary proof documents for my cohort enrollment.
---
### 5.2: Student Portal - Form Filling & Field Completion
**Status:** Draft/Pending | **Priority:** High | **Epic:** Student Portal - Frontend Development
**Issue:** [https://github.com/NeoSkosana/floDoc-v3/issues/54](https://github.com/NeoSkosana/floDoc-v3/issues/54)
**User Story:**
**As a** Student,
**I want** to fill in my assigned form fields (personal info, signatures, dates, etc.),
**So that** I can complete my portion of the document before the sponsor signs.
---
### 5.3: Student Portal - Progress Tracking & Save Draft
**Status:** Draft/Pending | **Priority:** High | **Epic:** Student Portal - Frontend Development
**Issue:** [https://github.com/NeoSkosana/floDoc-v3/issues/55](https://github.com/NeoSkosana/floDoc-v3/issues/55)
**User Story:**
**As a** Student,
**I want** to see my overall progress and save my work as a draft at any time,
**So that** I can complete the submission at my own pace without losing work.
---
### 5.4: Student Portal - Submission Confirmation & Status
**Status:** Draft/Pending | **Priority:** High | **Epic:** Student Portal - Frontend Development
**Issue:** [https://github.com/NeoSkosana/floDoc-v3/issues/56](https://github.com/NeoSkosana/floDoc-v3/issues/56)
**User Story:**
**As a** Student,
**I want** to review my complete submission and receive confirmation of successful submission,
**So that** I can verify everything is correct and track when the sponsor signs.
---
### 5.5: Student Portal - Email Notifications & Reminders
**Status:** Draft/Pending | **Priority:** High | **Epic:** Student Portal - Frontend Development
**Issue:** [https://github.com/NeoSkosana/floDoc-v3/issues/57](https://github.com/NeoSkosana/floDoc-v3/issues/57)
**User Story:**
**As a** Student,
**I want** to receive email notifications for status updates and reminders to complete my submission,
**So that** I can stay informed and complete my work on time without constantly checking the portal.
---
### 6.1: Sponsor Portal - Cohort Dashboard & Bulk Signing Interface
**Status:** Draft/Pending | **Priority:** High | **Epic:** Sponsor Portal - Frontend Development
**Issue:** [https://github.com/NeoSkosana/floDoc-v3/issues/58](https://github.com/NeoSkosana/floDoc-v3/issues/58)
**User Story:**
**As a** Sponsor,
**I want** to view all pending student documents in a cohort and sign them all at once,
**So that** I can efficiently complete my signing responsibility without reviewing each submission individually.
---
### 6.2: Sponsor Portal - Email Notifications & Reminders
**Status:** Draft/Pending | **Priority:** High | **Epic:** Sponsor Portal - Frontend Development
**Issue:** [https://github.com/NeoSkosana/floDoc-v3/issues/59](https://github.com/NeoSkosana/floDoc-v3/issues/59)
**User Story:**
**As a** Sponsor,
**I want** to receive email notifications about signing requests and reminders to complete my cohort signing,
**So that** I can stay informed and fulfill my signing responsibility on time without constantly checking the portal.
---
### 7.1: End-to-End Workflow Testing
**Status:** Draft/Pending | **Priority:** Critical | **Epic:** Integration & Testing
**Issue:** [https://github.com/NeoSkosana/floDoc-v3/issues/60](https://github.com/NeoSkosana/floDoc-v3/issues/60)
**User Story:**
**As a** QA Engineer,
**I want** to test the complete 3-portal workflow from start to finish,
**So that** I can verify all integrations work correctly and identify any breaking issues before production deployment.
---
### 7.2: Mobile Responsiveness Testing
**Status:** Draft/Pending | **Priority:** High | **Epic:** Integration & Testing
**Issue:** [https://github.com/NeoSkosana/floDoc-v3/issues/61](https://github.com/NeoSkosana/floDoc-v3/issues/61)
**User Story:**
**As a** QA Engineer,
**I want** to test all three portals across different screen sizes and devices,
**So that** I can ensure the FloDoc system works perfectly on mobile, tablet, and desktop devices.
---
### 7.3: Performance Testing (50+ Students)
**Status:** Draft/Pending | **Priority:** Critical | **Epic:** Integration & Testing
**Issue:** [https://github.com/NeoSkosana/floDoc-v3/issues/62](https://github.com/NeoSkosana/floDoc-v3/issues/62)
**User Story:**
**As a** QA Engineer,
**I want** to test system performance with large cohorts (50+ students),
**So that** I can ensure FloDoc scales efficiently and meets NFR requirements.
---
### 7.4: Security Audit & Penetration Testing
**Status:** Draft/Pending | **Priority:** Critical | **Epic:** Integration & Testing
**Issue:** [https://github.com/NeoSkosana/floDoc-v3/issues/63](https://github.com/NeoSkosana/floDoc-v3/issues/63)
**User Story:**
**As a** Security Engineer,
**I want** to perform comprehensive security testing on all three portals,
**So that** I can identify and remediate vulnerabilities before production deployment.
---
### 7.5: User Acceptance Testing
**Status:** Draft/Pending | **Priority:** High | **Epic:** Integration & Testing
**Issue:** [https://github.com/NeoSkosana/floDoc-v3/issues/64](https://github.com/NeoSkosana/floDoc-v3/issues/64)
**User Story:**
**As a** Product Owner,
**I want** to conduct comprehensive user acceptance testing with real stakeholders,
**So that** I can validate the system meets business requirements and user needs before production launch.
---
### 8.0: Development Infrastructure Setup (Local Docker)
**Status:** Draft | **Priority:** High | **Epic:** Phase 8 - Deployment & Documentation
**Issue:** [https://github.com/NeoSkosana/floDoc-v3/issues/65](https://github.com/NeoSkosana/floDoc-v3/issues/65)
**User Story:**
**As a** Developer,
**I want** to set up a local Docker-based development infrastructure with PostgreSQL and Redis,
**So that** I can demonstrate the complete FloDoc system to management without cloud costs or complexity.
---
### 8.0.1: Management Demo Readiness & Validation
**Status:** Draft | **Priority:** High | **Epic:** Phase 8 - Deployment & Documentation
**Issue:** [https://github.com/NeoSkosana/floDoc-v3/issues/66](https://github.com/NeoSkosana/floDoc-v3/issues/66)
**User Story:**
**As a** Product Manager,
**I want** to validate the complete 3-portal cohort management workflow end-to-end,
**So that** I can demonstrate FloDoc v3 to management with confidence and real data.
---
### 8.5: User Communication & Training Materials
**Status:** Draft | **Priority:** High (Blocking - Required Before Development) | **Epic:** Phase 8 - Deployment & Documentation
**Issue:** [https://github.com/NeoSkosana/floDoc-v3/issues/67](https://github.com/NeoSkosana/floDoc-v3/issues/67)
**User Story:**
**As a** Training Provider (TP Admin),
**I want** clear guidance on using FloDoc's 3-portal system,
**So that** I can manage cohorts effectively without confusion.
---
### 8.6: In-App User Documentation & Help System
**Status:** Draft (Deferred - Post-MVP) | **Priority:** Medium | **Epic:** Phase 8 - Deployment & Documentation
**Issue:** [https://github.com/NeoSkosana/floDoc-v3/issues/68](https://github.com/NeoSkosana/floDoc-v3/issues/68)
**User Story:**
**As a** User (TP Admin, Student, or Sponsor),
**I want** contextual help and documentation,
**So that** I can solve problems without contacting support.
---
### 8.7: Knowledge Transfer & Operations Documentation
**Status:** Draft (Deferred - Post-MVP) | **Priority:** Medium | **Epic:** Phase 8 - Deployment & Documentation
**User Story:**
**As a** Support/Operations Team,
**I want** comprehensive runbooks and documentation,
**So that** I can support FloDoc without ad-hoc knowledge transfer.
---

@ -0,0 +1,473 @@
#!/usr/bin/env python3
"""
GitHub Projects Populator using GitHub API directly.
This script creates issues and adds them to a GitHub project board
using the GitHub REST API and GraphQL API.
Usage:
# Using environment variable (recommended)
export GITHUB_TOKEN="ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
python populate_github_api.py --owner NeoSkosana --repo floDoc-v3 --project 6
# Or using command-line argument
python populate_github_api.py --token "ghp_xxxxxxxxx..." --owner NeoSkosana --repo floDoc-v3 --project 6
Requirements:
- GitHub Personal Access Token with:
- repo scope (for creating issues)
- project scope (for adding to project board)
- Project number (found in GitHub project URL)
"""
import argparse
import os
import requests
import time
from pathlib import Path
from typing import List, Dict, Optional
class GitHubAPIPopulator:
"""Populates GitHub Projects board using GitHub API directly."""
def __init__(self, token: str, owner: str, repo: str, project_number: int):
self.token = token
self.owner = owner
self.repo = repo
self.project_number = project_number
self.base_url = "https://api.github.com"
self.graphql_url = "https://api.github.com/graphql"
self.headers = {
"Authorization": f"Bearer {token}",
"Accept": "application/vnd.github.v3+json",
}
self.project_node_id = None
def get_project_node_id(self) -> Optional[str]:
"""Get the project node ID using GraphQL."""
query = """
query($owner: String!, $repo: String!, $number: Int!) {
repository(owner: $owner, name: $repo) {
project(number: $number) {
id
}
}
}
"""
variables = {
"owner": self.owner,
"repo": self.repo,
"number": self.project_number,
}
response = requests.post(
self.graphql_url,
json={"query": query, "variables": variables},
headers=self.headers,
)
if response.status_code == 200:
data = response.json()
project = data.get("data", {}).get("repository", {}).get("project")
if project:
self.project_node_id = project["id"]
return project["id"]
# Try alternative: Get project from organization/user
query2 = """
query($organization: String!, $number: Int!) {
organization(login: $organization) {
project(number: $number) {
id
}
}
}
"""
variables2 = {
"organization": self.owner,
"number": self.project_number,
}
response2 = requests.post(
self.graphql_url,
json={"query": query2, "variables": variables2},
headers=self.headers,
)
if response2.status_code == 200:
data = response2.json()
org_data = data.get("data")
if org_data:
org = org_data.get("organization")
if org:
project = org.get("project")
if project:
self.project_node_id = project["id"]
return project["id"]
return None
def get_issue_node_id(self, issue_number: int) -> Optional[str]:
"""Get the issue node ID using GraphQL."""
query = """
query($owner: String!, $repo: String!, $number: Int!) {
repository(owner: $owner, name: $repo) {
issue(number: $number) {
id
}
}
}
"""
variables = {
"owner": self.owner,
"repo": self.repo,
"number": issue_number,
}
response = requests.post(
self.graphql_url,
json={"query": query, "variables": variables},
headers=self.headers,
)
if response.status_code == 200:
data = response.json()
issue = data.get("data", {}).get("repository", {}).get("issue")
if issue:
return issue["id"]
return None
def add_issue_to_project(self, issue_node_id: str) -> bool:
"""Add an issue to the project board using GraphQL."""
if not self.project_node_id:
return False
mutation = """
mutation($projectId: ID!, $contentId: ID!) {
addProjectV2ItemById(input: {projectId: $projectId, contentId: $contentId}) {
item {
id
}
}
}
"""
variables = {
"projectId": self.project_node_id,
"contentId": issue_node_id,
}
response = requests.post(
self.graphql_url,
json={"query": mutation, "variables": variables},
headers=self.headers,
)
if response.status_code == 200:
data = response.json()
if "errors" in data:
print(f" ⚠️ GraphQL error: {data['errors']}")
return False
return True
return False
def create_issue(self, story: Dict) -> Optional[Dict]:
"""Create a GitHub issue for a story."""
url = f"{self.base_url}/repos/{self.owner}/{self.repo}/issues"
# Build the issue body
body_parts = []
# User Story section
if story.get('user_story'):
body_parts.append("## 📖 User Story\n")
body_parts.append(story['user_story'])
body_parts.append("")
# Background section
if story.get('background'):
body_parts.append("## 📋 Background\n")
body_parts.append(story['background'])
body_parts.append("")
# Acceptance Criteria section
if story.get('acceptance'):
body_parts.append("## ✅ Acceptance Criteria\n")
body_parts.append(story['acceptance'])
body_parts.append("")
# Metadata section
body_parts.append("## 📊 Metadata\n")
body_parts.append(f"- **Story Number**: {story['number']}")
body_parts.append(f"- **Epic**: {story['epic']}")
body_parts.append(f"- **Priority**: {story['priority']}")
body_parts.append(f"- **Estimated Effort**: {story['effort']}")
body_parts.append(f"- **Risk Level**: {story['risk']}")
body_parts.append(f"- **Status**: {story['status']}")
issue_data = {
"title": f"[{story['number']}] {story['title']}",
"body": "\n".join(body_parts),
"labels": self._get_labels(story),
}
response = requests.post(url, headers=self.headers, json=issue_data)
if response.status_code == 201:
issue = response.json()
print(f" ✅ Created issue #{issue['number']}")
return issue
else:
print(f" ❌ Failed to create issue: {response.status_code}")
print(f" Response: {response.text}")
return None
def _get_labels(self, story: Dict) -> List[str]:
"""Generate labels based on story metadata."""
labels = []
# Story label
labels.append(f"story:{story['number']}")
# Epic label - normalize
epic = story['epic']
epic_label = epic.lower().replace(" ", "-").replace("&", "").replace("---", "-")
labels.append(f"epic:{epic_label}")
# Priority label
priority_label = story['priority'].lower()
labels.append(f"priority:{priority_label}")
# Risk label
risk_label = story['risk'].lower()
labels.append(f"risk:{risk_label}")
# Status label
status_label = story['status'].lower().replace(" ", "-")
labels.append(f"status:{status_label}")
# Portal/type labels based on title
title_lower = story['title'].lower()
if any(word in title_lower for word in ['admin', 'tp', 'training provider']):
labels.append("portal:admin")
elif any(word in title_lower for word in ['student']):
labels.append("portal:student")
elif any(word in title_lower for word in ['sponsor']):
labels.append("portal:sponsor")
elif any(word in title_lower for word in ['database', 'model', 'api', 'backend']):
labels.append("type:backend")
elif any(word in title_lower for word in ['testing', 'qa', 'audit', 'security']):
labels.append("type:qa")
elif any(word in title_lower for word in ['infrastructure', 'deployment', 'docs']):
labels.append("type:infrastructure")
return labels
def parse_stories(self, file_path: Path) -> List[Dict]:
"""Parse stories from epic details markdown file."""
import re
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
# Split by stories
story_pattern = r'### Story ([\d.]+): (.+?)\n\n(.*?)(?=\n### Story [\d.]+:|$)'
matches = re.findall(story_pattern, content, re.DOTALL)
stories = []
for story_num, title, body in matches:
# Extract metadata
status_match = re.search(r'\*\*Status\*\*: (.+)', body)
priority_match = re.search(r'\*\*Priority\*\*: (.+)', body)
epic_match = re.search(r'\*\*Epic\*\*: (.+)', body)
effort_match = re.search(r'\*\*Estimated Effort\*\*: (.+)', body)
risk_match = re.search(r'\*\*Risk Level\*\*: (.+)', body)
# Extract User Story
user_story_match = re.search(r'#### User Story\n\n(.*?)(?=\n####|$)', body, re.DOTALL)
user_story = user_story_match.group(1).strip() if user_story_match else ""
# Extract Background
background_match = re.search(r'#### Background\n\n(.*?)(?=\n####|$)', body, re.DOTALL)
background = background_match.group(1).strip() if background_match else ""
# Extract Acceptance Criteria
acceptance_match = re.search(r'#### Acceptance Criteria\n\n(.*?)(?=\n####|$)', body, re.DOTALL)
acceptance = acceptance_match.group(1).strip() if acceptance_match else ""
stories.append({
'number': story_num,
'title': title,
'status': status_match.group(1).strip() if status_match else "Draft",
'priority': priority_match.group(1).strip() if priority_match else "Medium",
'epic': epic_match.group(1).strip() if epic_match else "General",
'effort': effort_match.group(1).strip() if effort_match else "Unknown",
'risk': risk_match.group(1).strip() if risk_match else "Low",
'user_story': user_story,
'background': background,
'acceptance': acceptance,
})
return stories
def create_all_issues(self, stories: List[Dict]) -> List[Dict]:
"""Create all issues and add to project."""
created_issues = []
print(f"\n📝 Creating {len(stories)} issues...\n")
for i, story in enumerate(stories, 1):
print(f"[{i}/{len(stories)}] Processing Story {story['number']}: {story['title']}")
issue = self.create_issue(story)
if issue:
created_issues.append(issue)
# Add to project board
if self.project_node_id:
print(f" Adding to project #{self.project_number}...")
issue_node_id = self.get_issue_node_id(issue['number'])
if issue_node_id:
if self.add_issue_to_project(issue_node_id):
print(f" ✅ Added to project")
else:
print(f" ⚠️ Could not add to project")
else:
print(f" ⚠️ Could not get issue node ID")
else:
print(f" ⚠️ Project node ID not available")
# Rate limiting
time.sleep(0.5)
return created_issues
def generate_summary(self, stories: List[Dict], created_issues: List[Dict], output_path: Path):
"""Generate a summary markdown file."""
with open(output_path, 'w', encoding='utf-8') as f:
f.write("# GitHub Project - User Stories Summary\n\n")
f.write(f"**Generated:** {time.strftime('%Y-%m-%d %H:%M:%S')}\n")
f.write(f"**Total Stories:** {len(stories)}\n")
f.write(f"**Issues Created:** {len(created_issues)}\n\n")
f.write("## Stories Created\n\n")
f.write("| # | Title | Status | Priority | Epic | Effort | Risk | Issue URL |\n")
f.write("|---|-------|--------|----------|------|--------|------|-----------|\n")
for i, story in enumerate(stories):
issue = created_issues[i] if i < len(created_issues) else None
if issue:
url = issue['html_url']
f.write(f"| {story['number']} | **{story['title']}** | {story['status']} | {story['priority']} | {story['epic']} | {story['effort']} | {story['risk']} | [Link]({url}) |\n")
else:
f.write(f"| {story['number']} | **{story['title']}** | {story['status']} | {story['priority']} | {story['epic']} | {story['effort']} | {story['risk']} | ❌ Failed |\n")
f.write("\n## Quick Reference\n\n")
for i, story in enumerate(stories):
issue = created_issues[i] if i < len(created_issues) else None
f.write(f"### {story['number']}: {story['title']}\n\n")
f.write(f"**Status:** {story['status']} | **Priority:** {story['priority']} | **Epic:** {story['epic']}\n\n")
if issue:
f.write(f"**Issue:** [{issue['html_url']}]({issue['html_url']})\n\n")
f.write("**User Story:**\n")
f.write(story['user_story'])
f.write("\n\n---\n\n")
print(f"\n✅ Summary generated: {output_path}")
def main():
parser = argparse.ArgumentParser(
description="Populate GitHub Projects board with user stories using GitHub API"
)
parser.add_argument(
"--token",
help="GitHub Personal Access Token (defaults to GITHUB_TOKEN env var)"
)
parser.add_argument(
"--owner",
required=True,
help="GitHub repository owner (username or org)"
)
parser.add_argument(
"--repo",
required=True,
help="GitHub repository name"
)
parser.add_argument(
"--project",
type=int,
required=True,
help="GitHub Project number"
)
parser.add_argument(
"--input",
default="/home/dev-mode/dev/dyict-projects/floDoc-v3/docs/prd/6-epic-details.md",
help="Path to epic details markdown file"
)
parser.add_argument(
"--output",
default="/home/dev-mode/dev/dyict-projects/floDoc-v3/docs/backlog/github_project_summary.md",
help="Path to output summary markdown file"
)
args = parser.parse_args()
# Get token from args or environment variable
token = args.token or os.environ.get("GITHUB_TOKEN")
if not token:
print("❌ No token provided!")
print(" Either:")
print(" 1. Set GITHUB_TOKEN environment variable:")
print(" export GITHUB_TOKEN=\"ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\"")
print(" 2. Or use --token argument:")
print(" --token \"ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\"")
return
# Parse stories
input_file = Path(args.input)
if not input_file.exists():
print(f"❌ Input file not found: {input_file}")
return
print(f"📖 Parsing stories from: {input_file}")
populator = GitHubAPIPopulator(
token=token,
owner=args.owner,
repo=args.repo,
project_number=args.project
)
stories = populator.parse_stories(input_file)
print(f"✅ Found {len(stories)} stories\n")
# Get project node ID
print(f"🔍 Getting project node ID for project #{args.project}...")
project_id = populator.get_project_node_id()
if project_id:
print(f"✅ Project node ID: {project_id}\n")
else:
print(f"⚠️ Could not get project node ID. Issues will be created but not added to project.\n")
# Create issues
created_issues = populator.create_all_issues(stories)
# Generate summary
populator.generate_summary(stories, created_issues, Path(args.output))
print(f"\n{'='*60}")
print(f"✅ Complete!")
print(f" Created {len(created_issues)} issues")
print(f" Summary: {args.output}")
print(f"{'='*60}")
print(f"\n📋 Next Steps:")
print(f" 1. Review created issues at: https://github.com/{args.owner}/{args.repo}/issues")
print(f" 2. Add issues to project board: https://github.com/users/{args.owner}/projects/{args.project}")
print(f" 3. Review summary: {args.output}")
if __name__ == '__main__':
main()

@ -0,0 +1,346 @@
#!/usr/bin/env python3
"""
Script to populate GitHub Projects board with user stories from the backlog.
This script reads stories from the epic details markdown file and creates
GitHub issues (cards) in the specified project board.
Usage:
python populate_github_project.py --token <github_token> --project <project_id> --owner <owner> --repo <repo>
Requirements:
- GitHub Personal Access Token with:
- repo scope (for creating issues)
- project scope (for adding to project board)
- Project ID (found in GitHub project URL)
- Owner and repository name
Note: This script uses the GitHub GraphQL API for project board operations.
"""
import re
import argparse
import requests
from pathlib import Path
from typing import List, Dict, Optional
class GitHubProjectPopulator:
"""Populates GitHub Projects board with user stories."""
def __init__(self, token: str, owner: str, repo: str, project_id: str):
self.token = token
self.owner = owner
self.repo = repo
self.project_id = project_id
self.base_url = "https://api.github.com"
self.graphql_url = "https://api.github.com/graphql"
self.headers = {
"Authorization": f"Bearer {token}",
"Accept": "application/vnd.github.v3+json",
}
def parse_stories(self, file_path: Path) -> List[Dict]:
"""Parse stories from epic details markdown file."""
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
# Split by stories - looking for ### Story X.X: pattern
story_pattern = r'### Story ([\d.]+): (.+?)\n\n(.*?)(?=\n### Story [\d.]+:|$)'
matches = re.findall(story_pattern, content, re.DOTALL)
stories = []
for story_num, title, body in matches:
# Extract Status, Priority, Epic, Estimated Effort, Risk Level
status_match = re.search(r'\*\*Status\*\*: (.+)', body)
priority_match = re.search(r'\*\*Priority\*\*: (.+)', body)
epic_match = re.search(r'\*\*Epic\*\*: (.+)', body)
effort_match = re.search(r'\*\*Estimated Effort\*\*: (.+)', body)
risk_match = re.search(r'\*\*Risk Level\*\*: (.+)', body)
# Extract User Story
user_story_match = re.search(r'#### User Story\n\n(.*?)(?=\n####|$)', body, re.DOTALL)
user_story = user_story_match.group(1).strip() if user_story_match else ""
# Extract Background
background_match = re.search(r'#### Background\n\n(.*?)(?=\n####|$)', body, re.DOTALL)
background = background_match.group(1).strip() if background_match else ""
# Extract Acceptance Criteria
acceptance_match = re.search(r'#### Acceptance Criteria\n\n(.*?)(?=\n####|$)', body, re.DOTALL)
acceptance = acceptance_match.group(1).strip() if acceptance_match else ""
# Extract Tasks/Subtasks if present
tasks_match = re.search(r'#### Tasks / Subtasks\n\n(.*?)(?=\n####|$)', body, re.DOTALL)
tasks = tasks_match.group(1).strip() if tasks_match else ""
stories.append({
'number': story_num,
'title': title,
'status': status_match.group(1).strip() if status_match else "Draft",
'priority': priority_match.group(1).strip() if priority_match else "Medium",
'epic': epic_match.group(1).strip() if epic_match else "General",
'effort': effort_match.group(1).strip() if effort_match else "Unknown",
'risk': risk_match.group(1).strip() if risk_match else "Low",
'user_story': user_story,
'background': background,
'acceptance': acceptance,
'tasks': tasks,
})
return stories
def create_issue(self, story: Dict) -> Optional[Dict]:
"""Create a GitHub issue for a story."""
url = f"{self.base_url}/repos/{self.owner}/{self.repo}/issues"
# Build the issue body
body_parts = []
# User Story section
if story['user_story']:
body_parts.append("## 📖 User Story\n")
body_parts.append(story['user_story'])
body_parts.append("")
# Background section
if story['background']:
body_parts.append("## 📋 Background\n")
body_parts.append(story['background'])
body_parts.append("")
# Acceptance Criteria section
if story['acceptance']:
body_parts.append("## ✅ Acceptance Criteria\n")
body_parts.append(story['acceptance'])
body_parts.append("")
# Tasks/Subtasks section
if story['tasks']:
body_parts.append("## 📝 Tasks / Subtasks\n")
body_parts.append(story['tasks'])
body_parts.append("")
# Metadata section
body_parts.append("## 📊 Metadata\n")
body_parts.append(f"- **Story Number**: {story['number']}")
body_parts.append(f"- **Epic**: {story['epic']}")
body_parts.append(f"- **Priority**: {story['priority']}")
body_parts.append(f"- **Estimated Effort**: {story['effort']}")
body_parts.append(f"- **Risk Level**: {story['risk']}")
body_parts.append(f"- **Status**: {story['status']}")
issue_data = {
"title": f"[{story['number']}] {story['title']}",
"body": "\n".join(body_parts),
"labels": self._get_labels(story),
}
response = requests.post(url, headers=self.headers, json=issue_data)
if response.status_code == 201:
print(f"✅ Created issue: {story['number']} - {story['title']}")
return response.json()
else:
print(f"❌ Failed to create issue {story['number']}: {response.status_code}")
print(f" Response: {response.text}")
return None
def _get_labels(self, story: Dict) -> List[str]:
"""Generate labels based on story metadata."""
labels = []
# Epic-based labels
epic_label = story['epic'].replace(" ", "-").lower()
labels.append(f"epic:{epic_label}")
# Priority label
priority_label = story['priority'].lower()
labels.append(f"priority:{priority_label}")
# Risk label
risk_label = story['risk'].lower()
labels.append(f"risk:{risk_label}")
# Status label
status_label = story['status'].lower().replace(" ", "-")
labels.append(f"status:{status_label}")
# Portal-based labels (inferred from title)
title_lower = story['title'].lower()
if any(word in title_lower for word in ['admin', 'tp', 'training provider']):
labels.append("portal:admin")
elif any(word in title_lower for word in ['student']):
labels.append("portal:student")
elif any(word in title_lower for word in ['sponsor']):
labels.append("portal:sponsor")
elif any(word in title_lower for word in ['database', 'model', 'api', 'backend']):
labels.append("type:backend")
elif any(word in title_lower for word in ['testing', 'qa', 'audit', 'security']):
labels.append("type:qa")
elif any(word in title_lower for word in ['infrastructure', 'deployment', 'docs']):
labels.append("type:infrastructure")
return labels
def add_issue_to_project(self, issue: Dict, column: str = "Todo") -> bool:
"""Add an issue to the GitHub project board."""
# Note: This uses the older Projects v2 API which requires project node ID
# For simplicity, we'll use the REST API with project card endpoint
issue_id = issue['number']
# Try to add to project using GraphQL (Projects v2)
query = """
mutation($projectId: ID!, $contentId: ID!) {
addProjectV2ItemById(input: {projectId: $projectId, contentId: $contentId}) {
item {
id
}
}
}
"""
# Get the issue node ID (GraphQL ID)
# For now, we'll skip this step and just create the issue
# The user can manually add issues to the project board
print(f" Note: Issue {issue_id} created. Add to project manually via GitHub UI.")
return True
def create_issues_batch(self, stories: List[Dict]) -> List[Dict]:
"""Create all issues in batch."""
created_issues = []
print(f"\n📝 Creating {len(stories)} issues...\n")
for story in stories:
issue = self.create_issue(story)
if issue:
created_issues.append(issue)
# Small delay to avoid rate limiting
import time
time.sleep(0.5)
return created_issues
def generate_summary(self, stories: List[Dict], output_path: Path):
"""Generate a summary markdown file with all stories."""
with open(output_path, 'w', encoding='utf-8') as f:
f.write("# GitHub Project - User Stories Summary\n\n")
f.write(f"**Total Stories:** {len(stories)}\n\n")
f.write("## Stories by Phase\n\n")
# Group by epic
epics = {}
for story in stories:
epic = story['epic']
if epic not in epics:
epics[epic] = []
epics[epic].append(story)
for epic, epic_stories in sorted(epics.items()):
f.write(f"### {epic}\n\n")
f.write("| # | Title | Priority | Risk | Effort |\n")
f.write("|---|-------|----------|------|--------|\n")
for story in epic_stories:
f.write(f"| {story['number']} | **{story['title']}** | {story['priority']} | {story['risk']} | {story['effort']} |\n")
f.write("\n")
f.write("## Quick Reference\n\n")
for story in stories:
f.write(f"### {story['number']}: {story['title']}\n\n")
f.write(f"**Status:** {story['status']} | **Priority:** {story['priority']} | **Epic:** {story['epic']}\n\n")
f.write("**User Story:**\n")
f.write(story['user_story'])
f.write("\n\n---\n\n")
print(f"✅ Summary generated: {output_path}")
def main():
parser = argparse.ArgumentParser(
description="Populate GitHub Projects board with user stories"
)
parser.add_argument(
"--token",
required=True,
help="GitHub Personal Access Token"
)
parser.add_argument(
"--owner",
required=True,
help="GitHub repository owner (username or org)"
)
parser.add_argument(
"--repo",
required=True,
help="GitHub repository name"
)
parser.add_argument(
"--project",
help="GitHub Project ID (optional - for adding to project board)"
)
parser.add_argument(
"--input",
default="/home/dev-mode/dev/dyict-projects/floDoc-v3/docs/prd/6-epic-details.md",
help="Path to epic details markdown file"
)
parser.add_argument(
"--output",
default="/home/dev-mode/dev/dyict-projects/floDoc-v3/docs/backlog/github_project_summary.md",
help="Path to output summary markdown file"
)
parser.add_argument(
"--dry-run",
action="store_true",
help="Parse stories without creating GitHub issues"
)
args = parser.parse_args()
# Parse stories
input_file = Path(args.input)
if not input_file.exists():
print(f"❌ Input file not found: {input_file}")
return
print(f"📖 Parsing stories from: {input_file}")
populator = GitHubProjectPopulator(
token=args.token,
owner=args.owner,
repo=args.repo,
project_id=args.project or ""
)
stories = populator.parse_stories(input_file)
print(f"✅ Found {len(stories)} stories\n")
if args.dry_run:
print("🔍 Dry run mode - showing stories that would be created:\n")
for story in stories:
print(f" [{story['number']}] {story['title']}")
print(f" Epic: {story['epic']}, Priority: {story['priority']}, Risk: {story['risk']}")
print()
return
# Create issues
created_issues = populator.create_issues_batch(stories)
# Generate summary
populator.generate_summary(stories, Path(args.output))
print(f"\n{'='*60}")
print(f"✅ Complete!")
print(f" Created {len(created_issues)} issues")
print(f" Summary: {args.output}")
print(f"{'='*60}")
if args.project:
print(f"\n⚠️ Note: Issues created but not added to project board.")
print(f" To add issues to project, use GitHub UI or update script to use GraphQL API.")
print(f" Project ID: {args.project}")
if __name__ == '__main__':
main()

@ -0,0 +1,239 @@
#!/bin/bash
#
# GitHub Projects Populator Script (using GitHub CLI)
#
# This script creates GitHub issues from user stories and adds them to a project board.
# It uses the GitHub CLI (gh) for authentication and API access.
#
# Prerequisites:
# 1. Install GitHub CLI: https://cli.github.com/
# 2. Authenticate: gh auth login
# 3. Install 'gh-project' extension: gh extension install mislav/gh-project
#
# Usage:
# ./populate_github_project.sh <owner> <repo> <project_number>
#
# Example:
# ./populate_github_project.sh NeoSkosana floDoc-v3 6
#
set -e
# Check arguments
if [ "$#" -lt 2 ]; then
echo "Usage: $0 <owner> <repo> [project_number]"
echo ""
echo "Example:"
echo " $0 NeoSkosana floDoc-v3 6"
echo ""
echo "Prerequisites:"
echo " - GitHub CLI installed (gh)"
echo " - gh auth login completed"
echo " - gh extension install mislav/gh-project"
exit 1
fi
OWNER="$1"
REPO="$2"
PROJECT_NUMBER="${3:-6}" # Default to 6 if not provided
# File paths
EPIC_FILE="/home/dev-mode/dev/dyict-projects/floDoc-v3/docs/prd/6-epic-details.md"
SUMMARY_FILE="/home/dev-mode/dev/dyict-projects/floDoc-v3/docs/backlog/github_project_summary.md"
LOG_FILE="/home/dev-mode/dev/dyict-projects/floDoc-v3/docs/backlog/populate_log.txt"
# Check dependencies
if ! command -v gh &> /dev/null; then
echo "❌ GitHub CLI (gh) not found. Install it from https://cli.github.com/"
exit 1
fi
# Check authentication
if ! gh auth status &> /dev/null; then
echo "❌ Not authenticated with GitHub CLI. Run 'gh auth login' first."
exit 1
fi
echo "=========================================="
echo "GitHub Projects Populator"
echo "=========================================="
echo "Owner: $OWNER"
echo "Repo: $REPO"
echo "Project: #$PROJECT_NUMBER"
echo "Input: $EPIC_FILE"
echo "=========================================="
echo ""
# Check if epic file exists
if [ ! -f "$EPIC_FILE" ]; then
echo "❌ Epic file not found: $EPIC_FILE"
exit 1
fi
# Create temporary files
TEMP_STORIES="/tmp/stories_list.txt"
TEMP_ISSUES="/tmp/created_issues.txt"
# Extract stories from epic file
echo "📖 Extracting stories from epic details..."
grep -E "^### Story [0-9]" "$EPIC_FILE" > "$TEMP_STORIES"
STORY_COUNT=$(wc -l < "$TEMP_STORIES")
echo "✅ Found $STORY_COUNT stories"
echo ""
# Initialize summary
echo "# GitHub Project - User Stories Summary" > "$SUMMARY_FILE"
echo "" >> "$SUMMARY_FILE"
echo "**Generated:** $(date)" >> "$SUMMARY_FILE"
echo "**Total Stories:** $STORY_COUNT" >> "$SUMMARY_FILE"
echo "" >> "$SUMMARY_FILE"
echo "## Stories Created" >> "$SUMMARY_FILE"
echo "" >> "$SUMMARY_FILE"
echo "| # | Title | Status | Priority | Epic | Effort | Risk | Issue URL |" >> "$SUMMARY_FILE"
echo "|---|-------|--------|----------|------|--------|------|-----------|" >> "$SUMMARY_FILE"
# Counter for tracking
COUNTER=0
CREATED=0
SKIPPED=0
# Read stories and create issues
while IFS= read -r line; do
COUNTER=$((COUNTER + 1))
# Extract story number and title
STORY_NUM=$(echo "$line" | sed -E 's/### Story ([0-9.]+): .*/\1/')
STORY_TITLE=$(echo "$line" | sed -E 's/### Story [0-9.]+: //')
echo "[$COUNTER/$STORY_COUNT] Processing Story $STORY_NUM: $STORY_TITLE"
# Extract story details from epic file
# Get the section for this story
STORY_SECTION=$(awk -v num="### Story $STORY_NUM:" '
$0 ~ num {flag=1; next}
/^### Story/ && flag {flag=0}
flag {print}
' "$EPIC_FILE")
# Extract metadata
STATUS=$(echo "$STORY_SECTION" | grep -E "^\*\*Status\*\*:" | sed 's/\*\*Status\*\*: //' | head -1 || echo "Draft")
PRIORITY=$(echo "$STORY_SECTION" | grep -E "^\*\*Priority\*\*:" | sed 's/\*\*Priority\*\*: //' | head -1 || echo "Medium")
EPIC=$(echo "$STORY_SECTION" | grep -E "^\*\*Epic\*\*:" | sed 's/\*\*Epic\*\*: //' | head -1 || echo "General")
EFFORT=$(echo "$STORY_SECTION" | grep -E "^\*\*Estimated Effort\*\*:" | sed 's/\*\*Estimated Effort\*\*: //' | head -1 || echo "Unknown")
RISK=$(echo "$STORY_SECTION" | grep -E "^\*\*Risk Level\*\*:" | sed 's/\*\*Risk Level\*\*: //' | head -1 || echo "Low")
# Extract user story
USER_STORY=$(echo "$STORY_SECTION" | awk '/#### User Story/,/#### Background/' | sed '1d;$d' | sed '/^$/d' | head -20)
# Build body
BODY="## 📖 User Story
$USER_STORY
## 📊 Metadata
- **Story Number**: $STORY_NUM
- **Epic**: $EPIC
- **Priority**: $PRIORITY
- **Estimated Effort**: $EFFORT
- **Risk Level**: $RISK
- **Status**: $STATUS
---
*Generated from epic details*"
# Create labels - normalize to match created labels
EPIC_LABEL=$(echo "$EPIC" | sed 's/Phase /phase-/' | sed 's/ - /-/' | sed 's/ /-/g' | tr '[:upper:]' '[:lower:]' | sed 's/---*/-/g')
STATUS_LABEL=$(echo "$STATUS" | sed 's/ /-/g' | tr '[:upper:]' '[:lower:]')
LABELS=(
"story:$STORY_NUM"
"epic:$EPIC_LABEL"
"priority:$(echo "$PRIORITY" | tr '[:upper:]' '[:lower:]')"
"risk:$(echo "$RISK" | tr '[:upper:]' '[:lower:]')"
"status:$STATUS_LABEL"
)
# Add portal labels based on title
TITLE_LOWER=$(echo "$STORY_TITLE" | tr '[:upper:]' '[:lower:]')
if echo "$TITLE_LOWER" | grep -qE "(admin|tp|training provider)"; then
LABELS+=("portal:admin")
elif echo "$TITLE_LOWER" | grep -qE "(student)"; then
LABELS+=("portal:student")
elif echo "$TITLE_LOWER" | grep -qE "(sponsor)"; then
LABELS+=("portal:sponsor")
elif echo "$TITLE_LOWER" | grep -qE "(database|model|api|backend)"; then
LABELS+=("type:backend")
elif echo "$TITLE_LOWER" | grep -qE "(testing|qa|audit|security)"; then
LABELS+=("type:qa")
elif echo "$TITLE_LOWER" | grep -qE "(infrastructure|deployment|docs)"; then
LABELS+=("type:infrastructure")
fi
# Build label string for gh CLI
LABEL_STR=$(IFS=,; echo "${LABELS[*]}")
# Create the issue
TITLE="[$STORY_NUM] $STORY_TITLE"
echo " Creating issue..."
ISSUE_URL=$(gh issue create \
--repo "$OWNER/$REPO" \
--title "$TITLE" \
--body "$BODY" \
--label "$LABEL_STR" 2>&1 || echo "")
if [ -n "$ISSUE_URL" ]; then
echo " ✅ Created: $ISSUE_URL"
CREATED=$((CREATED + 1))
# Add to summary
echo "| $STORY_NUM | $STORY_TITLE | $STATUS | $PRIORITY | $EPIC | $EFFORT | $RISK | [Link]($ISSUE_URL) |" >> "$SUMMARY_FILE"
# Add to project if project number provided
if [ -n "$PROJECT_NUMBER" ]; then
echo " Adding to project #$PROJECT_NUMBER..."
# Extract issue number from URL
ISSUE_NUM=$(echo "$ISSUE_URL" | sed 's/.*\///')
# Try to add to project using gh project extension
if gh project item-add "$PROJECT_NUMBER" --repo "$OWNER/$REPO" --issue "$ISSUE_NUM" 2>/dev/null; then
echo " ✅ Added to project"
else
echo " ⚠️ Could not add to project (may need extension or different method)"
fi
fi
# Rate limiting
sleep 1
else
echo " ❌ Failed to create issue"
SKIPPED=$((SKIPPED + 1))
fi
echo ""
done < "$TEMP_STORIES"
# Final summary
echo "=========================================="
echo "✅ Complete!"
echo "=========================================="
echo "Created: $CREATED issues"
echo "Skipped: $SKIPPED issues"
echo "Total: $STORY_COUNT stories"
echo ""
echo "Summary file: $SUMMARY_FILE"
echo "=========================================="
# Cleanup
rm -f "$TEMP_STORIES" "$TEMP_ISSUES"
# Show next steps
echo ""
echo "📋 Next Steps:"
echo " 1. Review created issues at: https://github.com/$OWNER/$REPO/issues"
echo " 2. Add issues to project board: https://github.com/users/$OWNER/projects/$PROJECT_NUMBER"
echo " 3. Review summary: $SUMMARY_FILE"
echo ""

@ -0,0 +1,105 @@
#!/bin/bash
#
# Setup script to configure GitHub token for the populator
#
# This script saves your GitHub token to your shell profile
# so you don't need to enter it every time.
#
echo "=========================================="
echo "GitHub Token Setup"
echo "=========================================="
echo ""
# Check if token is provided
if [ -z "$1" ]; then
echo "❌ No token provided!"
echo ""
echo "Usage:"
echo " ./setup_github_token.sh ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
echo ""
echo "Get your token from:"
echo " https://github.com/settings/tokens/new"
echo ""
echo "Required scopes:"
echo " - repo (Full control of private repositories)"
echo " - project (Full control of projects)"
echo " - workflow (Update GitHub Action workflows)"
exit 1
fi
TOKEN="$1"
# Validate token format
if [[ ! "$TOKEN" =~ ^ghp_ ]]; then
echo "⚠️ Warning: Token doesn't look like a GitHub Personal Access Token"
echo " Tokens should start with 'ghp_'"
echo ""
read -p "Continue anyway? (y/N) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
exit 1
fi
fi
# Detect shell
SHELL_NAME=$(basename "$SHELL")
PROFILE_FILE=""
case "$SHELL_NAME" in
bash)
PROFILE_FILE="$HOME/.bashrc"
;;
zsh)
PROFILE_FILE="$HOME/.zshrc"
;;
fish)
PROFILE_FILE="$HOME/.config/fish/config.fish"
;;
*)
PROFILE_FILE="$HOME/.bashrc"
;;
esac
echo "Detected shell: $SHELL_NAME"
echo "Profile file: $PROFILE_FILE"
echo ""
# Check if GITHUB_TOKEN already exists
if grep -q "GITHUB_TOKEN" "$PROFILE_FILE" 2>/dev/null; then
echo "⚠️ GITHUB_TOKEN already exists in $PROFILE_FILE"
echo " Updating existing entry..."
# Remove existing GITHUB_TOKEN line
sed -i '/^export GITHUB_TOKEN=/d' "$PROFILE_FILE"
fi
# Add token to profile
echo "" >> "$PROFILE_FILE"
echo "# GitHub Token for FloDoc Populator" >> "$PROFILE_FILE"
echo "export GITHUB_TOKEN=\"$TOKEN\"" >> "$PROFILE_FILE"
echo "✅ Token saved to $PROFILE_FILE"
echo ""
# Reload profile
echo "Reloading profile..."
source "$PROFILE_FILE" 2>/dev/null || true
# Verify
if [ -n "$GITHUB_TOKEN" ] || [ -n "$(grep "GITHUB_TOKEN" "$PROFILE_FILE" 2>/dev/null)" ]; then
echo "✅ Token configured successfully!"
echo ""
echo "You can now run the populator without specifying the token:"
echo ""
echo " cd docs/backlog"
echo " python3 populate_github_api.py --owner NeoSkosana --repo floDoc-v3 --project 6"
echo ""
echo "Or in one line:"
echo ""
echo " python3 docs/backlog/populate_github_api.py --owner NeoSkosana --repo floDoc-v3 --project 6"
echo ""
else
echo "❌ Failed to save token. Please add manually to $PROFILE_FILE:"
echo ""
echo " export GITHUB_TOKEN=\"$TOKEN\""
fi

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,429 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>FloDoc User Stories - Epic Details</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); height: 100vh; overflow: hidden; }
.slide-container { width: 100vw; height: 100vh; display: flex; justify-content: center; align-items: center; padding: 2rem; }
.slide { width: 90%; max-width: 1200px; height: 90%; background: white; border-radius: 20px; box-shadow: 0 20px 60px rgba(0,0,0,0.3); padding: 3rem; overflow-y: auto; display: none; animation: fadeIn 0.5s ease-in-out; }
.slide.active { display: block; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } }
.slide-header { border-bottom: 3px solid #667eea; padding-bottom: 1rem; margin-bottom: 2rem; }
.story-number { font-size: 1.2rem; color: #667eea; font-weight: 600; margin-bottom: 0.5rem; }
.story-title { font-size: 2rem; font-weight: 700; color: #1a202c; line-height: 1.3; }
.section { margin-bottom: 2rem; }
.section-title { font-size: 1.3rem; font-weight: 600; color: #667eea; margin-bottom: 1rem; display: flex; align-items: center; gap: 0.5rem; }
.section-title::before { content: ""; width: 4px; height: 24px; background: #667eea; border-radius: 2px; }
.section-content { background: #f7fafc; padding: 1.5rem; border-radius: 8px; line-height: 1.8; color: #2d3748; font-size: 1rem; }
.section-content strong { color: #667eea; }
.section-content ul, .section-content ol { margin-left: 1.5rem; margin-top: 0.5rem; }
.section-content li { margin-bottom: 0.5rem; }
.section-content code { background: #edf2f7; padding: 0.2rem 0.4rem; border-radius: 4px; font-family: "Courier New", monospace; font-size: 0.9rem; }
.navigation { position: fixed; bottom: 2rem; left: 50%; transform: translateX(-50%); background: rgba(255,255,255,0.95); padding: 1rem 2rem; border-radius: 50px; box-shadow: 0 4px 20px rgba(0,0,0,0.2); display: flex; gap: 1rem; align-items: center; z-index: 1000; }
.nav-btn { background: #667eea; color: white; border: none; padding: 0.75rem 1.5rem; border-radius: 25px; cursor: pointer; font-weight: 600; transition: all 0.3s ease; font-size: 1rem; }
.nav-btn:hover { background: #5568d3; transform: translateY(-2px); box-shadow: 0 4px 12px rgba(102,126,234,0.4); }
.nav-btn:disabled { background: #cbd5e0; cursor: not-allowed; transform: none; }
.nav-btn.secondary { background: #718096; }
.nav-btn.secondary:hover { background: #4a5568; }
.progress-bar { position: fixed; top: 0; left: 0; height: 4px; background: #667eea; transition: width 0.3s ease; z-index: 1001; }
.slide-counter { font-weight: 600; color: #4a5568; min-width: 100px; text-align: center; }
.slide::-webkit-scrollbar { width: 8px; }
.slide::-webkit-scrollbar-track { background: #f1f1f1; border-radius: 10px; }
.slide::-webkit-scrollbar-thumb { background: #667eea; border-radius: 10px; }
.slide::-webkit-scrollbar-thumb:hover { background: #5568d3; }
@media (max-width: 768px) { .slide { padding: 1.5rem; width: 95%; } .story-title { font-size: 1.5rem; } .section-title { font-size: 1.1rem; } .section-content { font-size: 0.9rem; padding: 1rem; } .navigation { padding: 0.75rem 1rem; gap: 0.5rem; } .nav-btn { padding: 0.5rem 1rem; font-size: 0.9rem; } }
.loading { text-align: center; padding: 2rem; color: white; font-size: 1.5rem; }
</style>
</head>
<body>
<div class="progress-bar" id="progressBar"></div>
<div id="slidesContainer"><div class="loading">Loading stories...</div></div>
<div class="navigation" id="navigation" style="display: none;">
<button class="nav-btn secondary" id="prevBtn" onclick="prevSlide()">← Previous</button>
<span class="slide-counter" id="slideCounter">1 / 32</span>
<button class="nav-btn" id="nextBtn" onclick="nextSlide()">Next →</button>
</div>
<script>
const stories = [];
let currentSlide = 0;
function initializeSlides() {
const container = document.getElementById("slidesContainer");
container.innerHTML = "";
stories.forEach((story, index) => {
const slide = document.createElement("div");
slide.className = "slide";
slide.id = `slide-${index}`;
slide.innerHTML = `
<div class="slide-header">
<div class="story-number">Story ${story.number}</div>
<div class="story-title">${story.title}</div>
</div>
<div class="section">
<div class="section-title">User Story</div>
<div class="section-content">${formatContent(story.user_story)}</div>
</div>
<div class="section">
<div class="section-title">Background</div>
<div class="section-content">${formatContent(story.background)}</div>
</div>
<div class="section">
<div class="section-title">Acceptance Criteria</div>
<div class="section-content">${formatContent(story.acceptance)}</div>
</div>
`;
container.appendChild(slide);
});
showSlide(0);
document.getElementById("navigation").style.display = "flex";
}
function formatContent(text) {
if (!text) return "";
let html = text;
html = html.replace(/\*\*(.+?)\*\*/g, "<strong>$1</strong>");
html = html.replace(/^[\*\-]\s+(.+)$/gm, "<li>$1</li>");
html = html.replace(/(<li>.*<\/li>)/s, "<ul>$1</ul>");
html = html.replace(/^\d+\.\s+(.+)$/gm, "<li>$1</li>");
html = html.replace(/(<li>.*<\/li>)/s, "<ul>$1</ul>");
html = html.replace(/\n\n/g, "</p><p>");
html = "<p>" + html + "</p>";
html = html.replace(/<p><ul>/g, "<ul>");
html = html.replace(/<\/ul><\/p>/g, "</ul>");
html = html.replace(/<p><\/p>/g, "");
return html;
}
function showSlide(index) {
const slides = document.querySelectorAll(".slide");
slides.forEach((slide, i) => { slide.classList.toggle("active", i === index); });
currentSlide = index;
updateNavigation();
updateProgress();
}
function updateNavigation() {
const prevBtn = document.getElementById("prevBtn");
const nextBtn = document.getElementById("nextBtn");
const counter = document.getElementById("slideCounter");
prevBtn.disabled = currentSlide === 0;
nextBtn.disabled = currentSlide === stories.length - 1;
counter.textContent = `${currentSlide + 1} / ${stories.length}`;
}
function updateProgress() {
const progress = ((currentSlide + 1) / stories.length) * 100;
document.getElementById("progressBar").style.width = progress + "%";
}
function nextSlide() { if (currentSlide < stories.length - 1) showSlide(currentSlide + 1); }
function prevSlide() { if (currentSlide > 0) showSlide(currentSlide - 1); }
document.addEventListener("keydown", (e) => {
if (e.key === "ArrowRight" || e.key === " ") { e.preventDefault(); nextSlide(); }
else if (e.key === "ArrowLeft") { e.preventDefault(); prevSlide(); }
});
const storiesData = [
{
number: "1.1",
title: "Database Schema Extension",
user_story: "**As a** system architect,\n**I want** to create the database schema for FloDoc\'s new models,\n**So that** the application has the foundation to support cohort management.",
background: "Based on the PRD analysis, we need three new tables to support the 3-portal cohort management system:\n- `institutions` - Single training institution (not multi-tenant)\n- `cohorts` - Training program cohorts\n- `cohort_enrollments` - Student enrollments in cohorts\n\nThese tables must integrate with existing DocuSeal tables without breaking existing functionality.",
acceptance: "**Functional:**\n1. ✅ All three tables created with correct schema\n2. ✅ Foreign key relationships established\n3. ✅ All indexes created for performance\n4. ✅ Migrations are reversible\n5. ✅ No modifications to existing DocuSeal tables\n\n**Integration:**\n1. ✅ IV1: Existing DocuSeal tables remain unchanged\n2. ✅ IV2: New tables can reference existing tables (templates, submissions)\n3. ✅ IV3: Database performance not degraded (verify with EXPLAIN queries)\n\n**Security:**\n1. ✅ All tables include `deleted_at` for soft deletes\n2. ✅ Sensitive fields (emails) are encrypted at rest if required by policy\n3. ✅ Foreign keys prevent orphaned records\n\n**Quality:**\n1. ✅ Migrations follow Rails conventions\n2. ✅ Table and column names are consistent with existing codebase\n3. ✅ All migrations include `down` method for rollback\n4. ✅ Schema changes documented in migration comments",
},
{
number: "1.2",
title: "Core Models Implementation",
user_story: "**As a** developer,\n**I want** to create ActiveRecord models for the new FloDoc tables,\n**So that** the application can interact with cohorts and enrollments programmatically.",
background: "Models must follow existing DocuSeal patterns:\n- Inherit from `ApplicationRecord`\n- Use `strip_attributes` for data cleaning\n- Include soft delete functionality\n- Define proper associations and validations\n- Follow naming conventions",
acceptance: "**Functional:**\n1. ✅ All three models created with correct class structure\n2. ✅ All associations defined correctly\n3. ✅ All validations implemented\n4. ✅ All scopes defined\n5. ✅ State machine logic correct (if used)\n6. ✅ Model methods work as specified\n7. ✅ FeatureFlag model created with enabled?, enable!, disable! methods\n8. ✅ FeatureFlagCheck concern implemented\n9. ✅ Default flags seeded (flodoc_cohorts, flodoc_portals)\n10. ✅ All FloDoc routes protected by feature flags\n\n**Integration:**\n1. ✅ IV1: Models don\'t break existing DocuSeal models\n2. ✅ IV2: Associations work with existing tables (templates, submissions)\n3. ✅ IV3: Query performance acceptable with 1000+ records\n4. ✅ Feature flags integrate with existing authentication\n\n**Security:**\n1. ✅ No mass assignment vulnerabilities\n2. ✅ Proper attribute whitelisting\n3. ✅ Email validation on all email fields\n4. ✅ Feature flags can disable FloDoc instantly\n\n**Quality:**\n1. ✅ Follow existing code style (RuboCop compliant)\n2. ✅ All methods have YARD comments\n3. ✅ Test coverage > 80%\n4. ✅ No N+1 query issues\n5. ✅ Feature flag tests included",
},
{
number: "1.3",
title: "Authorization Layer Extension",
user_story: "**As a** system administrator,\n**I want** the authorization system to support FloDoc roles and permissions,\n**So that** users can only access appropriate cohort management functions.",
background: "DocuSeal uses Cancancan for authorization. We need to:\n- Extend `Ability` class to handle FloDoc models\n- Define permissions for TP, Student, and Sponsor roles\n- Support ad-hoc access patterns (students/sponsors without accounts)\n- Maintain existing DocuSeal permissions",
acceptance: "**Functional:**\n1. ✅ Ability class extended with FloDoc permissions\n2. ✅ Ad-hoc access works for students (via token)\n3. ✅ Ad-hoc access works for sponsors (via token)\n4. ✅ TP permissions work correctly\n5. ✅ Admin permissions work correctly\n6. ✅ Existing DocuSeal permissions unchanged\n\n**Integration:**\n1. ✅ IV1: Existing DocuSeal authorization still works\n2. ✅ IV2: New abilities integrate with existing Ability class\n3. ✅ IV3: Authorization checks don\'t add significant overhead\n\n**Security:**\n1. ✅ JWT tokens signed with secret key\n2. ✅ Tokens have expiration (30 days)\n3. ✅ Token verification prevents tampering\n4. ✅ Ad-hoc users can\'t access other cohorts\n5. ✅ Sponsor can\'t access before all students complete\n\n**Quality:**\n1. ✅ Follow existing authorization patterns\n2. ✅ All abilities tested\n3. ✅ Token service has comprehensive tests\n4. ✅ No security bypasses",
},
{
number: "2.1",
title: "Cohort Creation & Management",
user_story: "**As a** TP (Training Provider) administrator,\n**I want** to create and manage cohorts with all their configuration details,\n**So that** I can organize students into training programs and prepare them for the signature workflow.",
background: "Cohort creation is the entry point for the FloDoc workflow. TP administrators need to:\n- Create a cohort by selecting an existing DocuSeal template\n- Define program type (learnership/internship/candidacy)\n- Specify required student documents (ID, matric, tertiary, etc.)\n- Set sponsor email for the review phase\n- Configure cohort metadata and settings\n\nThe cohort acts as a container that orchestrates the entire 3-party signature workflow.",
acceptance: "**Functional:**\n1. ✅ TP can create cohort with template selection\n2. ✅ TP can specify program type (learnership/internship/candidacy)\n3. ✅ TP can define required student uploads (max 10 types)\n4. ✅ TP can set sponsor email\n5. ✅ TP can add cohort metadata\n6. ✅ TP can edit cohort in draft state\n7. ✅ TP can delete cohort (soft delete)\n8. ✅ All operations logged in audit trail\n\n**Integration:**\n1. ✅ IV1: Cohort creation validates template exists\n2. ✅ IV2: Cohort links correctly to existing template\n3. ✅ IV3: No performance degradation with 100+ cohorts\n\n**Security:**\n1. ✅ Only TP admins can create/manage cohorts\n2. ✅ TP can only manage their institution\'s cohorts\n3. ✅ Sponsor email validation enforced\n4. ✅ Audit logs cannot be tampered with\n\n**Quality:**\n1. ✅ Follow existing service object patterns\n2. ✅ Transactional safety for cohort creation\n3. ✅ Proper error handling and user feedback\n4. ✅ 80% test coverage for service layer",
},
{
number: "2.2",
title: "TP Signing Phase Logic (High Risk - Prototype First)",
user_story: "**As a** TP administrator,\n**I want** to sign the first student\'s document and have that signing replicated to all other students in the cohort,\n**So that** I don\'t need to sign each student\'s document individually, saving time and eliminating duplicate sponsor emails.",
background: "This is the core innovation of FloDoc. The workflow is:\n\n1. **TP Signing Phase**: TP signs ONE student\'s document (with their fields/signatures)\n2. **Duplication**: System duplicates the **completed submission** (not empty template) to remaining students\n3. **Auto-fill**: TP\'s fields and signatures are automatically populated across all student submissions\n4. **Email Management**: Sponsor receives ONE email (when all students are ready), not duplicate emails per submission\n\n**Why Prototype First**: DocuSeal\'s native multi-submission only duplicates empty templates. This story requires custom duplication of pre-filled submissions, which is a high-risk architectural change.\n\n**Prototype Approach**: Build a minimal prototype that:\n- Creates 2-3 test submissions\n- Demonstrates field/signature copying from first to remaining\n- Validates sponsor email delivery logic\n- Then expand to full implementation",
acceptance: "**Functional:**\n1. ✅ TP can initiate TP signing phase from draft state\n2. ✅ System creates \"seed\" submission for TP to sign\n3. ✅ TP\'s signatures and field values are captured\n4. ✅ System duplicates submission for all pending students\n5. ✅ TP\'s values auto-fill into all student submissions\n6. ✅ Sponsor receives only ONE email when all students ready\n7. ✅ Cohort state transitions correctly through workflow\n\n**Integration:**\n1. ✅ IV1: Doesn\'t break existing submission/submitter logic\n2. ✅ IV2: Submissions correctly linked to cohorments\n3. ✅ IV3: Performance acceptable with 100 students per cohort\n\n**Security:**\n1. ✅ Only TP can initiate TP signing phase\n2. ✅ TP can only sign their institution\'s cohorts\n3. ✅ Pre-filled submissions marked clearly\n4. ✅ Audit trail captures all duplication operations\n\n**Quality:**\n1. ✅ Transactional guarantees for multi-submission creation\n2. ✅ Proper error handling for partial failures\n3. ✅ Debug logging for debugging duplication issues\n4. ✅ 85% test coverage",
},
{
number: "2.3",
title: "Student Enrollment Management",
user_story: "**As a** TP administrator,\n**I want** to manage student enrollment in cohorts and bulk-create student submissions,\n**So that** students can access their documents to complete after TP signs.",
background: "After TP completes signing (Phase 2.2), the system needs to:\n- Create student records in the cohort\n- Set up individual submissions for each student\n- Send email invites (using existing DocuSeal email system)\n- Track student completion status\n\nThe enrollment process uses the existing DocuSeal submission invitation mechanism but adapts it to FloDoc\'s workflow needs.\n\n**Key Requirements:**\n- Bulk enrollment via CSV or manual entry\n- Each student gets their own submission (pre-filled with TP\'s data)\n- Email invites sent via DocuSeal\'s existing email system\n- Student status tracked in cohort_enrollments",
acceptance: "**Functional:**\n1. ✅ TP can bulk enroll students via CSV or manual entry\n2. ✅ System validates student emails before creating enrollments\n3. ✅ TP can send email invites to all enrolled students\n4. ✅ Students can access their pre-filled documents via link\n5. ✅ System tracks student completion (form fill + upload)\n6. ✅ System auto-moves cohort to \"ready_for_sponsor\" when all complete\n7. ✅ System triggers sponsor notification once\n\n**Integration:**\n1. ✅ IV1: Works with existing DocuSeal email system\n2. ✅ IV2: Enrollment correctly links to submissions created by TP\n3. ✅ IV3: Performance handles 500+ student cohorts\n\n**Security:**\n1. ✅ TP can only enroll students in their institution\'s cohorts\n2. ✅ Student access tokens expire after configurable duration (default 30 days)\n3. ✅ **Progress is saved independently of token expiration**\n4. ✅ **Expired tokens can be renewed via email verification**\n5. ✅ Upload tracking prevents unauthorized document completion\n6. ✅ Email validation prevents malformed addresses\n\n**Quality:**\n1. ✅ Bulk enrollment has progress feedback\n2. ✅ Duplicate email prevention\n3. ✅ Proper error messages for invalid data\n4. ✅ 85% test coverage",
},
{
number: "2.4",
title: "Sponsor Review Workflow",
user_story: "**As a** Sponsor,\n**I want** to review all student documents in my cohort and sign them in bulk,\n**So that** I can complete the verification workflow efficiently.",
background: "After all students complete their portion, the cohort enters \"ready_for_sponsor\" state. The sponsor:\n- Receives ONE email invitation (Story 2.2 ensures this)\n- Gets a portal view showing all students and their documents\n- Can review each student\'s completed document\n- Can sign/verify in bulk or individually\n- System tracks sponsor completion\n\n**No account creation needed** - sponsor uses ad-hoc token-based access.",
acceptance: "**Functional:**\n1. ✅ Sponsor receives single email invitation\n2. ✅ Sponsor can access portal via token link\n3. ✅ Sponsor sees all student submissions in list\n4. ✅ Sponsor can view each student\'s completed document\n5. ✅ Sponsor can verify/approve students individually or in bulk\n6. ✅ System tracks sponsor verification per student\n7. ✅ Cohort moves to TP review when sponsor completes\n\n**Integration:**\n1. ✅ IV1: Works with existing DocuSeal document viewing\n2. ✅ IV2: Sponsor tokens integrate with ad-hoc auth system\n3. ✅ IV3: Performance with 100+ students\n\n**Security:**\n1. ✅ Sponsor can only access their assigned cohort\n2. ✅ Sponsor access tokens expire after configurable duration (default 30 days)\n3. ✅ **Progress is saved independently of token expiration**\n4. ✅ **Expired tokens can be renewed via email verification**\n5. ✅ Cannot view other cohorts\' data\n6. ✅ Verification data is tamper-proof\n\n**Quality:**\n1. ✅ Clear UI feedback during verification\n2. ✅ Error handling for expired/invalid tokens\n3. ✅ Audit trail of sponsor actions\n4. ✅ 85% test coverage",
},
{
number: "2.5",
title: "TP Review & Finalization",
user_story: "**As a** TP administrator,\n**I want** to review the sponsor-verified submissions and finalize the cohort,\n**So that** the entire 3-party signature workflow is completed and documents are ready for archival.",
background: "Final phase of the workflow:\n1. Sponsor completes verification (Story 2.4)\n2. Cohort enters TP review state\n3. TP admin reviews sponsor\'s verification\n4. TP can approve/reject the cohort\n5. Cohort moves to completed state\n6. All documents finalized and archived\n\nThis is the final quality check in the workflow.",
acceptance: "**Functional:**\n1. ✅ TP sees sponsor verification dashboard\n2. ✅ TP can review all student verifications\n3. ✅ TP can approve/reject individual students\n4. ✅ TP can finalize entire cohort\n5. ✅ System archives all documents\n6. ✅ System generates completion report\n7. ✅ Cohort marked as completed\n8. ✅ Audit trail complete\n\n**Integration:**\n1. ✅ IV1: Uses existing DocuSeal document archiving\n2. ✅ IV2: Completes workflow state machine\n3. ✅ IV3: Handles large cohorts without performance issues\n\n**Security:**\n1. ✅ Only TP can access review dashboard\n2. ✅ All actions logged with user attribution\n3. ✅ Finalized documents cannot be modified\n4. ✅ Completion report is read-only\n\n**Quality:**\n1. ✅ Clear indication of verification status\n2. ✅ Errors for incomplete verification attempts\n3. ✅ Very fast finalization (< 3 seconds)\n4. 80% test coverage",
},
{
number: "2.6",
title: "Excel Export for Cohort Data",
user_story: "**As a** TP administrator,\n**I want** to export cohort enrollment data to Excel,\n**So that** I can perform additional analysis or reporting outside the system.",
background: "FR23 requires Excel export capability. This should include:\n- Student enrollment information\n- Document status (completed/incomplete)\n- Verification status (TP, students, sponsor)\n- Required upload status\n\nThis allows TP admins to use Excel for additional reporting.",
acceptance: "**Functional:**\n1. ✅ TP can export cohort to Excel (.xlsx format)\n2. ✅ Export includes all student enrollment data\n3. ✅ Export includes completion status\n4. ✅ Export includes sponsor verification status\n5. ✅ Export includes upload tracking\n6. ✅ Export includes summary statistics\n7. ✅ File downloads automatically\n\n**Integration:**\n1. ✅ IV1: Works with existing authorization\n2. ✅ IV2: Performance acceptable for 500 students\n3. ✅ IV3: No memory leaks with large exports\n\n**Security:**\n1. ✅ Only TP can export their institution\'s cohorts\n2. ✅ Export contains no sensitive tokens/PII\n3. ✅ File cleaned up after download\n\n**Quality:**\n1. ✅ Clean Excel formatting\n2. ✅ Handle special characters in names\n3. ✅ Nice error message for empty cohorts\n4. ✅ 80% test coverage",
},
{
number: "2.7",
title: "Audit Log & Compliance",
user_story: "**As a** TP administrator,\n**I want** comprehensive audit logs of all cohort workflow activities,\n**So that** we can demonstrate compliance and trace any issues.",
background: "FloDoc handles sensitive training documents. Compliance requires:\n- Immutable audit trail of all actions\n- Who did what and when\n- Document access tracking\n- Workflow state changes\n- Sponsor access tracking\n\nAll audit logs must be tamper-proof and easily searchable.",
acceptance: "**Functional:**\n1. ✅ Every cohort action is logged\n2. ✅ All logs are immutable (no updates/deletes)\n3. ✅ System actions logged even without user\n4. ✅ Document access tracking works\n5. ✅ Audit reports can be generated\n6. ✅ Reports show workflow timeline\n7. ✅ Reports filter by date range\n8. ✅ Reports show event counts and breakdowns\n\n**Integration:**\n1. ✅ IV1: Audit calls work without blocking main operations\n2. ✅ IV2: Logs integrate with existing models\n3. ✅ IV3: Performance impact < 5% on operations\n\n**Security:**\n1. Audit logs protected from tampering\n2. Only admins can view audit reports\n3. Logs don\'t contain sensitive data (passwords, tokens)\n4. Immutable storage is enforced\n\n**Quality:**\n1. Standardized log format\n2. Comprehensive coverage (all actions)\n3. Clear error handling if audit logging fails\n4. 90% test coverage for audit module",
},
{
number: "2.8",
title: "Cohort State Machine & Workflow Orchestration",
user_story: "**As a** system,\n**I want** to manage cohort state transitions and workflow enforcement,\n**So that** the 3-party signature workflow follows the correct sequence and prevents invalid operations.",
background: "The FloDoc workflow has strict state requirements:\n1. **Draft** → TP signs first document\n2. **TP Signing** → Student enrollment\n3. **Student Enrollment** → Student completion\n4. **Ready for Sponsor** → Sponsor review\n5. **Sponsor Review** → TP verification\n6. **TP Review** → Completed\n\nCannot skip steps. Prevents chaos.\n\nThis story ties together all Phase 2 logic with proper state enforcement.",
acceptance: "**Functional:**\n1. ✅ State transitions work via AASM events\n2. ✅ Guards prevent invalid transitions\n3. ✅ All workflow steps enforced\n4. ✅ Cohort cannot skip steps\n5. ✅ Workflow validations provide clear errors\n6. ✅ System prevents operations in wrong states\n7. ✅ Background job detects stuck cohorts\n\n**Integration:**\n1. ✅ IV1: State machine works with existing services\n2. ✅ IV2: Audit logs all state changes\n3. ✅ IV3: No impact on performance\n\n**Security:**\n1. ✅ Guards prevent unauthorized bypassing\n2. ✅ State changes logged\n3. ✅ Cannot manually set arbitrary states\n\n**Quality:**\n1. ✅ Clear error messages for failed transitions\n2. ✅ State validation in errors\n3. ✅ 85% test coverage for state machine",
},
{
number: "3.1",
title: "RESTful Cohort Management API",
user_story: "**As a** TP administrator or external system integrator,\n**I want** to create, read, update, and delete cohorts via REST API,\n**So that** I can automate cohort management and integrate with other systems.",
background: "The FloDoc system needs a complete REST API for cohort management. This API will be used by:\n\n1. **TP Portal** (Vue.js frontend) - All cohort operations\n2. **External systems** - Programmatic cohort creation and management\n3. **Automation scripts** - Bulk operations and integrations\n\nThe API should follow JSON:API standards and include proper authentication/authorization.",
acceptance: "**Functional:**\n1. ✅ GET /api/v1/cohorts - List cohorts with pagination\n2. ✅ POST /api/v1/cohorts - Create cohort\n3. ✅ GET /api/v1/cohorts/:id - Show cohort details\n4. ✅ PUT /api/v1/cohorts/:id - Update cohort\n5. ✅ DELETE /api/v1/cohorts/:id - Delete cohort (soft)\n6. ✅ POST /api/v1/cohorts/:id/start_signing - Start TP signing phase\n7. ✅ POST /api/v1/cohorts/:id/enroll_students - Bulk enroll students\n8. ✅ POST /api/v1/cohorts/:id/send_invites - Send student invitations\n9. ✅ GET /api/v1/cohorts/:id/status - Get cohort status\n10. ✅ GET /api/v1/cohorts/:id/export - Export to Excel\n11. ✅ GET /api/v1/sponsor/:token/dashboard - Sponsor dashboard\n12. ✅ POST /api/v1/sponsor/:token/verify/:student_id - Sponsor verification\n\n**Integration:**\n1. ✅ IV1: All endpoints use existing service objects\n2. ✅ IV2: Authorization works through CancanCan\n3. ✅ IV3: API response time < 500ms for standard queries\n\n**Security:**\n1. Authenticated access for TP endpoints\n2. Token validation for sponsor endpoints\n3. Authorization checks on all operations\n4. No sensitive data leaked in responses\n5. Rate limiting (if applicable)\n\n**Quality:**\n1. Consistent response format across all endpoints\n2. Proper HTTP status codes\n3. Standardized error messages\n4. API documentation in code comments\n5. 85% test coverage",
},
{
number: "3.2",
title: "Webhook Events for Workflow State Changes",
user_story: "**As a** TP administrator,\n**I want** webhook notifications for all cohort workflow events,\n**So that** external systems can react to state changes in real-time.",
background: "FloDoc should emit webhooks for:\n- Cohort created\n- TP signing completed\n- Student enrolled\n- Student completed\n- Sponsor accessed portal\n- Sponsor verified student\n- Cohort completed\n\nThis allows external integrations (e.g., CRM, LMS, reporting systems) to stay in sync.",
acceptance: "**Functional:**\n1. ✅ Webhook events created for all 7 event types\n2. ✅ Events queued for background delivery\n3. ✅ Signature generation works correctly\n4. ✅ Retry logic handles failures\n5. ✅ Multiple webhook URLs supported\n6. ✅ Event status tracking (pending/delivered/failed)\n7. ✅ Payload includes all relevant data\n\n**Integration:**\n1. ✅ IV1: Events emitted at correct workflow points\n2. ✅ IV2: Delivery job executes successfully\n3. ✅ IV3: No impact on main workflow performance\n\n**Security:**\n1. ✅ Signatures prevent tampering\n2. ✅ HTTPS URLs only (validation)\n3. ✅ Secrets can be customized per cohort\n4. ✅ Failed deliveries don\'t expose sensitive data\n\n**Quality:**\n1. ✅ Clear event naming convention\n2. ✅ Comprehensive audit logging\n3. ✅ Error messages for debugging\n4. ✅ 85% test coverage",
},
{
number: "3.3",
title: "Student API (Ad-hoc Token-Based Access)",
user_story: "**As a** student with a cohort link,\n**I want** a simple token-based API to access and complete my documents,\n**So that** I can fulfill my requirements without account creation.",
background: "Students need to:\n- Access their pre-filled document\n- Fill in their personal fields\n- Upload required documents\n- Submit the final document\n- All without creating an account\n\nThis requires a secure token-based API that:\n- Validates tokens against cohort and email\n- Exposes only student\'s own document\n- Tracks completion status",
acceptance: "**Functional:**\n1. ✅ GET /api/v1/students/:token/status - Check progress\n2. ✅ GET /api/v1/students/:token - Show document with pre-filled data\n3. ✅ PUT /api/v1/students/:token - Save student field values\n4. ✅ POST /api/v1/students/:token/upload - Upload required documents\n5. ✅ POST /api/v1/students/:token/submit - Submit final document\n6. ✅ Students cannot edit TP\'s pre-filled fields\n7. ✅ Progress tracking shows completion percentage\n\n**Integration:**\n1. ✅ IV1: Works with existing DocuSeal document rendering\n2. ✅ IV2: Student tokens integrate with ad-hoc auth system\n3. ✅ IV3: No impact on existing submission workflow\n\n**Security:**\n1. ✅ Students can only access their own enrollment\n2. ✅ Tokens have 30-day expiration\n3. ✅ Cannot access other students in cohort\n4. ✅ CSRF protection (if needed)\n\n**Quality:**\n1. ✅ Clear error messages\n2. ✅ Nice UI data structure\n3. ✅ Proper validation\n4. ✅ 85% test coverage",
},
{
number: "3.4",
title: "API Documentation & Versioning",
user_story: "**As a** developer integrating with FloDoc,\n**I want** comprehensive API documentation and stable versioning,\n**So that** I can build reliable integrations without breaking changes.",
background: "API documentation must include:\n- Endpoint reference\n- Request/response examples\n- Authentication methods\n- Error codes\n- Rate limits\n- Versioning strategy\n\nThis will be the source of truth for both internal frontend and external integrations.",
acceptance: "**Functional:**\n1. ✅ OpenAPI/Swagger spec for all endpoints\n2. ✅ Static documentation in /docs/api\n3. ✅ Versioning strategy documented\n4. ✅ Authentication methods documented (JWT + ad-hoc tokens)\n5. ✅ Error response format documented with all error codes\n6. ✅ Rate limiting implemented and documented (100 req/min)\n7. ✅ Code examples provided for all 6 core endpoints\n8. ✅ Change log maintained\n9. ✅ Complete request/response examples for POST /cohorts\n10. ✅ Complete request/response examples for GET /cohorts\n11. ✅ Complete request/response examples for POST /cohorts/{id}/start_signing\n12. ✅ Complete request/response examples for GET /sponsor/{token}/dashboard\n13. ✅ Complete request/response examples for POST /students/{token}/submit\n14. ✅ Complete request/response examples for POST /webhooks\n15. ✅ All error scenarios documented (400, 401, 403, 404, 422, 429, 500)\n\n**Quality:**\n1. ✅ Documentation is comprehensive\n2. ✅ Examples are runnable/verifiable\n3. ✅ Coverage of all 11+ endpoints\n4. ✅ Clear migration path for API versions\n5. ✅ All HTTP status codes documented\n6. ✅ All request headers documented\n7. ✅ All response fields explained\n8. ✅ Ad-hoc token flow clearly documented\n\n**Integration:**\n1. ✅ IV1: Documentation matches actual implementation\n2. ✅ IV2: Examples work without modification\n3. ✅ IV3: Static docs don\'t affect app performance\n4. ✅ IV4: All documented endpoints exist in routes",
},
{
number: "4.1",
title: "Cohort Management Dashboard",
user_story: "**As a** TP administrator,\n**I want** a dashboard to view and manage all cohorts,\n**So that** I can monitor the 3-party workflow at a glance.",
background: "TP Portal needs a comprehensive dashboard showing:\n- Cohort list with status and progress\n- Quick actions (create, open, export)\n- Filter and search capability\n- High-level metrics (total cohorts, active, completed)\n- Recent activity feed\n\nThis is the main entry point for TP administrators.",
acceptance: "**Functional:**\n1. ✅ Dashboard displays cohort list with pagination\n2. ✅ Metrics cards show accurate statistics\n3. ✅ Filters work (status, program type, search)\n4. ✅ Status badges display correctly\n5. ✅ Progress bars show student completion\n6. ✅ Actions (open/edit/export) work\n7. ✅ Empty state displays when no cohorts\n8. ✅ Pagination works\n\n**Integration:**\n1. ✅ IV1: API calls use correct endpoints\n2. ✅ IV2: Pinia store manages state properly\n3. ✅ IV3: Components follow design system\n\n**Security:**\n1. ✅ Only authenticated TP users can access\n2. ✅ Users only see their institution\'s cohorts\n3. ✅ Export button calls correct authorization\n\n**Quality:**\n1. ✅ Follows Vue 3 best practices\n2. ✅ Components are reusable\n3. ✅ TypeScript types defined\n4. ✅ Design system compliance\n5. ✅ 80% test coverage",
},
{
number: "4.2",
title: "Cohort Creation & Bulk Import",
user_story: "**As a** TP administrator,\n**I want** to create new cohorts and bulk-import students via Excel,\n**So that** I can efficiently onboard large groups without manual data entry.",
background: "The cohort creation process needs to support:\n- Basic cohort information (name, dates, description)\n- Optional bulk student import via Excel spreadsheet\n- Validation and preview before committing data\n- Seamless navigation to cohort detail after creation\n\nThis enables TP administrators to quickly set up new training cohorts with minimal effort.",
acceptance: "**Functional:**\n1. ✅ Form validation prevents submission with missing required fields\n2. ✅ Date pickers work correctly and prevent invalid date ranges\n3. ✅ Excel upload accepts only .xlsx files\n4. ✅ Validation shows preview of first 5 students\n5. ✅ Validation counts total student count\n6. ✅ Validation identifies formatting errors (missing emails, duplicates)\n7. ✅ User can re-upload file if validation fails\n8. ✅ Create button disabled until form is valid\n9. ✅ Success notification on cohort creation\n10. ✅ Auto-navigate to cohort detail after creation\n11. ✅ Bulk import creates student records with pending status\n12. ✅ Cohort name uniqueness enforced (optional, backend)\n\n**UI/UX:**\n1. ✅ Follows design system colors and spacing\n2. ✅ Upload zone has clear drag-and-drop visual feedback\n3. ✅ Loading states display during upload and creation\n4. ✅ Error messages are clear and actionable\n5. ✅ Preview table is scrollable if many rows\n6. ✅ Form is responsive on mobile devices\n7. ✅ All buttons have proper hover states\n8. ✅ File input is accessible (keyboard navigation)\n\n**Integration:**\n1. ✅ IV1: API calls use correct endpoints\n2. ✅ IV2: Pinia store updates after creation\n3. ✅ IV3: Error handling works for network failures\n4. ✅ IV4: Excel validation endpoint returns correct data structure\n\n**Security:**\n1. ✅ Only authenticated TP users can access\n2. ✅ File upload size limit enforced (10MB max)\n3. ✅ File type validation on client and server\n4. ✅ Sanitization of cohort names and descriptions\n5. ✅ Rate limiting on create endpoint\n\n**Quality:**\n1. ✅ Follows Vue 3 best practices\n2. ✅ TypeScript types defined for all data\n3. ✅ Components are reusable (form fields extracted)\n4. ✅ 80% test coverage\n5. ✅ Design system compliance verified",
},
{
number: "4.3",
title: "Cohort Detail Overview",
user_story: "**As a** TP administrator,\n**I want** to view detailed information about a specific cohort, including student list, progress status, and document workflow,\n**So that** I can monitor and manage the cohort effectively.",
background: "After creating a cohort, administrators need a comprehensive view to:\n- See all students and their current status\n- Monitor workflow progression through the 4 stages\n- View cohort metadata and settings\n- Access quick actions based on current workflow stage\n- Filter and search students\n\nThis view serves as the central hub for cohort management.",
acceptance: "**Functional:**\n1. ✅ Loads cohort details on page visit\n2. ✅ Displays all cohort information correctly\n3. ✅ Shows 5 stat cards with correct values\n4. ✅ Renders workflow steps with correct active state\n5. ✅ Lists all students in the cohort\n6. ✅ Filters students by status (all/pending/in_progress/completed)\n7. ✅ Searches students by name or email\n8. ✅ Shows status counts that update with filters\n9. ✅ Displays empty state when no students match filters\n10. ✅ Each student row has \"View\" button\n11. ✅ \"View\" button navigates to student detail\n12. ✅ \"Start Signing\" button navigates to signing interface\n13. ✅ \"Export Data\" button triggers export (links to Story 4.8)\n14. ✅ Quick action buttons are disabled when not applicable\n15. ✅ Shows \"Not found\" when cohort doesn\'t exist\n\n**UI/UX:**\n1. ✅ Follows design system colors and spacing\n2. ✅ Responsive layout on mobile devices\n3. ✅ Loading state displays during data fetch\n4. ✅ Status badges use correct colors\n5. ✅ Workflow steps are visually distinct\n6. ✅ Tables are scrollable on small screens\n7. ✅ All interactive elements have hover states\n8. ✅ Empty states are helpful and clear\n\n**Integration:**\n1. ✅ IV1: API calls use correct endpoints\n2. ✅ IV2: Pinia stores manage state correctly\n3. ✅ IV3: Router navigation works\n4. ✅ IV4: Data flows between components correctly\n\n**Security:**\n1. ✅ Only authenticated TP users can access\n2. ✅ Users only see their institution\'s cohorts\n3. ✅ Student data is not exposed to unauthorized users\n4. ✅ All API endpoints require proper authorization\n\n**Quality:**\n1. ✅ Follows Vue 3 best practices\n2. ✅ TypeScript types defined\n3. ✅ Components are maintainable\n4. ✅ 80% test coverage\n5. ✅ Design system compliance verified",
},
{
number: "4.4",
title: "TP Signing Interface",
user_story: "**As a** TP administrator,\n**I want** to sign the first student\'s document and have it automatically replicated to all other students,\n**So that** I can sign once instead of signing each student\'s document individually.",
background: "The TP Signing Phase is the critical first step in the 3-party workflow. Key requirements:\n- TP signs ONE document (the first student\'s document)\n- System duplicates the signed submission to all other students\n- TP\'s fields and signatures are pre-filled across all student submissions\n- This eliminates duplicate signing work for the TP\n- Prevents duplicate sponsor emails through workflow state management\n\nThis is the core innovation of FloDoc - bulk signing capability.",
acceptance: "**Functional:**\n1. ✅ Loads cohort and form fields on page visit\n2. ✅ Displays correct student count\n3. ✅ Shows workflow reminder with correct current step\n4. ✅ Renders all form fields based on template\n5. ✅ Accepts input for text fields\n6. ✅ Accepts input for textarea fields\n7. ✅ Accepts date selection\n8. ✅ Opens signature pad modal when clicking sign button\n9. ✅ Allows drawing signature on canvas\n10. ✅ Clears signature canvas\n11. ✅ Saves signature as image data\n12. ✅ Displays signature preview\n13. ✅ Allows removing signature\n14. ✅ Handles checkbox fields\n15. ✅ Validates all required fields before signing\n16. ✅ Shows validation errors\n17. ✅ Preview button shows field values\n18. ✅ Sign & Replicate button disabled until valid\n19. ✅ Success state shows after signing\n20. ✅ Replicates to correct number of students\n21. ✅ \"Send Invitations\" button works\n22. ✅ Navigation back to cohort works\n\n**UI/UX:**\n1. ✅ Follows design system colors and spacing\n2. ✅ Responsive layout on mobile devices\n3. ✅ Loading states during operations\n4. ✅ Modal overlays work correctly\n5. ✅ Canvas drawing is smooth\n6. ✅ Error messages are clear\n7. ✅ Success state is visually distinct\n8. ✅ Progress bar shows signing progress\n9. ✅ All buttons have proper hover states\n10. ✅ Empty states handled gracefully\n\n**Integration:**\n1. ✅ IV1: API calls use correct endpoints\n2. ✅ IV2: Pinia store manages state correctly\n3. ✅ IV3: Router navigation works\n4. ✅ IV4: Data flows between components correctly\n\n**Security:**\n1. ✅ Only authenticated TP users can access\n2. ✅ Users can only sign their institution\'s cohorts\n3. ✅ Signature data is securely stored\n4. ✅ All API endpoints require proper authorization\n5. ✅ Rate limiting on signing endpoint\n\n**Quality:**\n1. ✅ Follows Vue 3 best practices\n2. ✅ TypeScript types defined\n3. ✅ Components are maintainable\n4. ✅ Canvas drawing uses efficient rendering\n5. ✅ 80% test coverage\n6. ✅ Design system compliance verified",
},
{
number: "4.5",
title: "Student Management View",
user_story: "**As a** TP administrator,\n**I want** to view and manage individual student details, including their document status and uploaded files,\n**So that** I can track student progress and troubleshoot issues.",
background: "After TP signing and student enrollment, administrators need granular visibility into each student\'s progress:\n- View student\'s personal information\n- See document status (pending/in_progress/completed)\n- Access uploaded required documents\n- Monitor student\'s field completion\n- Send reminders or reset student progress\n\nThis provides detailed cohort management capabilities.",
acceptance: "**Functional:**\n1. ✅ Loads student details on page visit\n2. ✅ Displays student name and email\n3. ✅ Shows status banner with correct state\n4. ✅ Status banner shows correct icon\n5. ✅ Status banner shows correct title\n6. ✅ Status banner shows correct description\n7. ✅ Shows completion timestamp if completed\n8. ✅ \"Send Reminder\" button works\n9. ✅ \"Send Reminder\" disabled for completed students\n10. ✅ \"Reset Progress\" button works\n11. ✅ \"Reset Progress\" disabled for pending students\n12. ✅ \"Copy Invite Link\" button works\n13. ✅ Invite link copied to clipboard\n14. ✅ Document status shows correct progress tracker\n15. ✅ Required uploads list shows all items\n16. ✅ Upload status shows uploaded/pending correctly\n17. ✅ \"View\" button for uploaded files works\n18. ✅ \"Remind\" button for pending uploads works\n19. ✅ Field values display correctly\n20. ✅ Empty state when no fields filled\n21. ✅ Student info grid shows all data\n22. ✅ Audit log displays events chronologically\n23. ✅ Empty state when no audit events\n24. ✅ \"Not found\" state for invalid student\n25. ✅ Confirmation modal for destructive actions\n26. ✅ Modal cancels correctly\n27. ✅ Modal confirms correctly\n\n**UI/UX:**\n1. ✅ Follows design system colors and spacing\n2. ✅ Responsive layout on mobile devices\n3. ✅ Loading state displays during data fetch\n4. ✅ Status banners use correct color coding\n5. ✅ Progress tracker is visually clear\n6. ✅ Timeline is visually distinct\n7. ✅ All buttons have proper hover states\n8. ✅ Empty states are helpful and clear\n9. ✅ Modal overlays work correctly\n10. ✅ Copy confirmation feedback shown\n\n**Integration:**\n1. ✅ IV1: API calls use correct endpoints\n2. ✅ IV2: Pinia store manages state correctly\n3. ✅ IV3: Router navigation works\n4. ✅ IV4: Clipboard API works for copy\n\n**Security:**\n1. ✅ Only authenticated TP users can access\n2. ✅ Users can only view their institution\'s students\n3. ✅ Sensitive data properly protected\n4. ✅ All API endpoints require proper authorization\n5. ✅ Invite links are token-based and secure\n\n**Quality:**\n1. ✅ Follows Vue 3 best practices\n2. ✅ TypeScript types defined\n3. ✅ Components are maintainable\n4. ✅ 80% test coverage\n5. ✅ Design system compliance verified",
},
{
number: "4.6",
title: "Sponsor Portal Dashboard",
user_story: "**As a** Sponsor,\n**I want** to access a dedicated portal where I can review and verify all student documents for a cohort,\n**So that** I can sign once for the entire cohort instead of signing each student individually.",
background: "The Sponsor Portal is a critical component of the 3-party workflow. Key requirements:\n- Sponsor receives ONE email with a single access link\n- Portal shows all students in two tabs based on sponsor\'s signing status:\n - **Pending Tab**: Students awaiting sponsor signature (before sponsor completes)\n - **Completed Tab**: Students where sponsor has already applied verification\n- Sponsor fills their fields once\n- System applies sponsor\'s signature to all student documents\n- After sponsor signs once, all students move to the Completed tab\n- Progress bar shows completion status\n\nThis is the second signing phase and requires careful state management.",
acceptance: "**Functional:**\n1. ✅ Loads cohort data using token from URL\n2. ✅ Displays cohort name and institution\n3. ✅ Shows progress bar with correct percentage\n4. ✅ Displays student counts (pending/completed)\n5. ✅ Tab navigation switches between pending/completed\n6. ✅ Pending tab shows all pending students\n7. ✅ Completed tab shows all completed students\n8. ✅ Student cards display name, email, ID\n9. ✅ Empty states show when no students in tab\n10. ✅ Sponsor form has all required fields\n11. ✅ Form validation prevents submission if incomplete\n12. ✅ Signature pad opens when clicking sign button\n13. ✅ Signature can be drawn on canvas\n14. ✅ Signature can be cleared\n15. ✅ Signature can be saved\n16. ✅ Signature preview shows saved signature\n17. ✅ \"Remove & Redraw\" works\n18. ✅ Checkbox consent works\n19. ✅ Preview button shows all fields\n20. ✅ Sign & Apply button disabled until valid\n21. ✅ Success state shows after signing\n22. ✅ Refresh button updates student list\n23. ✅ Invalid token shows error state\n\n**UI/UX:**\n1. ✅ Follows design system colors and spacing\n2. ✅ Responsive layout on mobile devices\n3. ✅ Loading state displays during data fetch\n4. ✅ Progress bar is visually clear\n5. ✅ Tab navigation is intuitive\n6. ✅ Student cards are visually distinct\n7. ✅ Modal overlays work correctly\n8. ✅ Canvas drawing is smooth\n9. ✅ Error messages are clear\n10. ✅ Success state is visually distinct\n\n**Integration:**\n1. ✅ IV1: API calls use correct endpoints with token auth\n2. ✅ IV2: Pinia store manages state correctly\n3. ✅ IV3: Getters calculate counts correctly\n4. ✅ IV4: Token-based routing works\n\n**Security:**\n1. ✅ Token-based authentication required\n2. ✅ Token expires after use or time limit\n3. ✅ Sponsor can only access assigned cohort\n4. ✅ All API endpoints require valid token\n5. ✅ Signature data is securely stored\n\n**Quality:**\n1. ✅ Follows Vue 3 best practices\n2. ✅ TypeScript types defined\n3. ✅ Components are maintainable\n4. ✅ 80% test coverage\n5. ✅ Design system compliance verified",
},
{
number: "4.7",
title: "Sponsor Portal - Bulk Document Signing",
user_story: "**As a** Sponsor,\n**I want** to sign once and have that signature applied to all pending student documents,\n**So that** I don\'t need to manually sign each student\'s documents individually.",
background: "In the previous story, sponsors gain access to a dashboard that tracks student completion status (Waiting → In Progress). Once all students have completed their part (uploaded required documents + completed their fields), the sponsor receives the bulk signing prompt.\n\nThe current DocuSeal limitation is that each submission requires independent signing, which creates unnecessary friction when the same sponsor is signing the same document type for multiple students in the same cohort. The sponsor portal must enable a bulk signing workflow where:\n\n1. Sponsor reviews the general cohort document structure\n2. Sponsor provides their signature once\n3. System atomically applies this signature to ALL 20+ student submissions\n4. System transitions cohort state to \"Completed - Signed\"\n5. Single sponsor email notification (not one per student)\n\nThis aligns with FR10 (Bulk Signing) and FR13 (Single Email Rule).",
acceptance: "**Functional:**\n1. ✅ Sponsor can only access bulk signing when all students are in \"completed_student\" status\n2. ✅ Signature can be provided via canvas (draw) or text input (typed)\n3. ✅ Preview shows signature applied to sample document before final signing\n4. ✅ Bulk sign button is disabled until canvas has data + confirmation checkbox is checked\n5. ✅ Clicking \"Sign All\" atomically applies signature to all pending submissions\n6. ✅ System transitions cohort from \"ready_for_sponsor\" to \"completed_sponsor\"\n7. ✅ After signing, sponsor is redirected to sponsor dashboard with success message\n8. ✅ All signed documents show in \"completed\" tab\n\n**UI/UX:**\n1. ✅ Modal-based interface with clear progress indicators\n2. ✅ Privacy notice about bulk signing action and irreversibility\n3. ✅ Student list shows pending vs completed with counts\n4. ✅ Canvas with clear/clear & type fallback options\n5. ✅ Signature preview generation within 2 seconds\n6. ✅ Loading states during preview generation and signing\n7. ✅ Error messages displayed in red with actionable retry options\n8. ✅ Mobile-responsive design (signature canvas scales)\n\n**Integration:**\n1. ✅ API endpoints: `GET /api/sponsor/cohorts/{id}/bulk-sign` and `POST /api/sponsor/submissions/bulk-sign`\n2. ✅ Token authentication in headers for all requests\n3. ✅ Cohort state machine updates to `completed_sponsor`\n4. ✅ Single email notification to training provider on completion\n5. ✅ Final documents stored in DocuSeal with sponsor signature\n\n**Security:**\n1. ✅ Token-based authentication with expiration handling\n2. ✅ Authorization check: sponsor can only sign their assigned cohort\n3. ✅ Signature data validated (not empty) before processing\n4. ✅ Rate limiting: maximum 5 bulk signing attempts per hour per token\n5. ✅ Audit log entry created for each bulk signing action\n\n**Quality:**\n1. ✅ Atomic transaction: all documents signed or none\n2. ✅ Performance: handles 50+ students with sub-5-second response\n3. ✅ Error handling: email to TP admin if bulk signing fails\n4. ✅ Canonical signature application (same signature instance across all)",
},
{
number: "4.8",
title: "Sponsor Portal - Progress Tracking & State Management",
user_story: "**As a** Sponsor,\n**I want** to see real-time progress tracking with clear visual indicators of which students have completed their documents and which are still pending,\n**So that** I can monitor the signing workflow and know exactly when to proceed with bulk signing.",
background: "After students complete their required actions (uploading documents, filling their fields), the sponsor needs visibility into the overall cohort progress. The sponsor portal dashboard must provide:\n\n1. **Progress Overview**: Visual progress bar showing percentage of students who have completed their part\n2. **Student List with Status**: Clear indication of each student\'s current state (Waiting → In Progress → Completed)\n3. **Document Preview**: Ability to view individual student documents before signing\n4. **State-Driven UI**: Interface elements that change based on cohort state:\n - \"Waiting for students\" - Sponsor cannot sign yet\n - \"Ready for bulk signing\" - All students completed, show bulk sign button\n - \"Completed\" - All documents signed, show completion status\n\nThis story implements the dashboard UI that was outlined in Story 4.6, providing the visual layer for progress tracking that the sponsor interacts with before bulk signing (Story 4.7).\n\nThe state management ensures sponsors don\'t attempt to sign prematurely and provides confidence that all students have completed their required actions.",
acceptance: "**Functional:**\n1. ✅ Dashboard loads cohort data on mount\n2. ✅ Progress bar calculates percentage correctly (completed / total * 100)\n3. ✅ Student list separates into Pending vs Completed tabs\n4. ✅ Pending tab shows students with status: waiting, in_progress, completed_student\n5. ✅ Completed tab shows students with status: completed_all\n6. ✅ Real-time polling updates data every 30 seconds\n7. ✅ \"Sign All Documents\" button only visible when cohort status is \'ready_for_sponsor\'\n8. ✅ Clicking \"Sign All\" opens Bulk Signing Modal (Story 4.7)\n9. ✅ Clicking \"View Document\" on completed student opens preview modal\n10. ✅ After bulk signing, dashboard refreshes and switches to Completed tab\n\n**UI/UX:**\n1. ✅ Progress bar animates smoothly (0.5s transition)\n2. ✅ Status badges use color-coded styling (yellow/blue/green)\n3. ✅ Student cards show avatar initials, name, email, and status\n4. ✅ Hover states on all interactive elements\n5. ✅ Empty states for both tabs (no students message)\n6. ✅ Loading state shown during initial fetch\n7. ✅ Error messages displayed prominently with retry option\n8. ✅ Mobile-responsive layout (stacks properly on small screens)\n9. ✅ Tab switching is instant and smooth\n10. ✅ Timestamps formatted human-readable (e.g., \"Jan 15, 2025\")\n\n**Integration:**\n1. ✅ API endpoint: `GET /api/sponsor/cohorts/{id}/progress`\n2. ✅ Token authentication in headers\n3. ✅ Polling mechanism uses `setInterval` with cleanup on unmount\n4. ✅ Store getters correctly filter students by status\n5. ✅ Modal components receive correct props (cohortId, token, student data)\n6. ✅ State updates propagate to child components\n\n**Security:**\n1. ✅ Token-based authentication required for all API calls\n2. ✅ Authorization check: sponsor can only view their assigned cohort\n3. ✅ Token validation on dashboard load\n4. ✅ No sensitive data (signatures, document contents) exposed in dashboard list\n5. ✅ Rate limiting on polling endpoint (max 1 request per 30 seconds)\n\n**Quality:**\n1. ✅ Polling stops when component unmounts (no memory leaks)\n2. ✅ Error boundaries handle API failures gracefully\n3. ✅ Data refreshes automatically without user intervention\n4. ✅ State consistency: UI always reflects latest data from server\n5. ✅ Performance: renders 50+ students without lag",
},
{
number: "4.9",
title: "Sponsor Portal - Token Renewal & Session Management",
user_story: "**As a** Sponsor,\n**I want** to renew my access token if it expires while I\'m reviewing documents,\n**So that** I can complete my signing workflow without losing progress or being locked out.",
background: "Sponsors access the portal via time-limited tokens sent by email (Story 2.4). These tokens expire after a configurable period (default 30 days, but often 24-48 hours for security). \n\nThe critical problem: A sponsor might:\n1. Open the portal and review 15 out of 20 student documents\n2. Take a break or get interrupted\n3. Return after token expiration to finish the remaining 5\n4. Discover they\'re locked out and must request a new token\n5. **Lose all progress** and have to start over\n\nThis creates a poor user experience and potential data loss. The solution requires:\n\n1. **Progress Persistence**: Save signing state independently of token\n2. **Pre-Expiration Warnings**: Email notification 2 hours before expiry\n3. **Renewal Mechanism**: One-click token renewal via email\n4. **Grace Period**: 5-minute buffer after expiration for active sessions\n5. **Session Management**: Clear indication of token status\n\nThis story implements the token renewal flow referenced in Stories 2.3 and 2.4, ensuring sponsors can complete their workflow even if they exceed the token lifetime.\n\n**Architecture Note**: This is the final story in Phase 4 (TP Portal - Frontend Development), completing the sponsor portal feature set.",
acceptance: "**Functional:**\n1. ✅ Banner appears when token enters warning period (<4 hours or <25% duration)\n2. Banner shows countdown timer updating in real-time\n3. \"Renew Token\" button sends renewal request to API\n4. Success message appears after renewal email sent\n5. Error message appears if renewal fails\n6. Modal appears immediately when token expires\n7. Modal offers \"Renew\" or \"Logout\" options\n8. Renewal count tracked (max 3 per cohort)\n9. Token state saved to localStorage\n10. State restored on page reload if still valid\n\n**UI/UX:**\n1. Banner color changes based on urgency (yellow orange red)\n2. Countdown format: \"2h 15m\" for >1h, \"45m 30s\" for <1h\n3. Banner dismissible (but reappears on next visit)\n4. Modal has clear messaging about expiration\n5. Loading states on renewal button\n6. Success/error messages auto-dismiss after 5 seconds\n7. Mobile-responsive banner and modal\n8. Visual distinction between warning and expired states\n\n**Integration:**\n1. API endpoint: `POST /api/sponsor/tokens/renew`\n2. Token validation on dashboard load\n3. Renewal email contains new token link\n4. New token auto-applies and reloads page\n5. Token store integrates with dashboard store\n6. Banner appears on all sponsor portal pages\n\n**Security:**\n1. Maximum 3 renewals per cohort (prevents abuse)\n2. Rate limiting on renewal endpoint (1 per minute)\n3. Audit log of all renewal attempts\n4. Token validation before allowing renewal\n5. New tokens have full 48-hour duration (not extended)\n6. Old tokens invalidated when new one issued\n\n**Quality:**\n1. State persists across browser sessions\n2. No memory leaks (intervals cleaned up)\n3. Handles edge cases (network errors, invalid tokens)\n4. Graceful degradation if localStorage unavailable\n5. Time calculations accurate across timezones",
},
{
number: "4.10",
title: "TP Portal - Cohort Status Monitoring & Analytics",
user_story: "**As a** Training Provider,\n**I want** to monitor all cohorts with real-time status updates and analytics,\n**So that** I can track progress, identify bottlenecks, and manage my document signing workflows efficiently.",
background: "After creating cohorts and initiating workflows, training providers need visibility into the entire system. The TP Portal dashboard must provide:\n\n1. **Cohort Overview**: List of all cohorts with key metrics\n2. **Real-time Status**: Live updates of student and sponsor progress\n3. **Analytics**: Completion rates, average time to completion, bottlenecks\n4. **Actionable Insights**: Which cohorts need attention, which are completed\n5. **Bulk Operations**: Manage multiple cohorts simultaneously\n\nThis is the final story in Phase 4, completing the TP Portal frontend development. It builds upon:\n- Story 4.1: TP Portal Dashboard Layout\n- Story 4.2: TP Signing Phase Logic\n- Story 4.3: TP Review Dashboard\n- Story 4.4: TP Portal - Cohort Creation Wizard\n- Story 4.5: TP Portal - Cohort Management & Student List\n- Story 4.6: Sponsor Portal Dashboard\n- Story 4.7: Sponsor Portal - Bulk Document Signing\n- Story 4.8: Sponsor Portal - Progress Tracking\n- Story 4.9: Sponsor Portal - Token Renewal\n\nThe TP monitoring dashboard is the command center for training providers, giving them complete visibility and control over their cohort workflows.",
acceptance: "**Functional:**\n1. ✅ Dashboard loads all cohorts on mount\n2. ✅ Analytics cards show correct totals and calculations\n3. ✅ Search filters cohorts by name or ID\n4. ✅ Status filter works correctly\n5. ✅ Sort by name, status, or creation date\n6. ✅ Real-time polling updates data every 30 seconds\n7. ✅ \"Refresh All\" button manually triggers update\n8. ✅ Clicking \"View\" opens cohort detail modal\n9. ✅ \"Send Reminder\" available for in-progress cohorts\n10. ✅ \"Export\" downloads Excel file for completed cohorts\n11. ✅ New cohort button opens creation wizard\n12. ✅ Progress bars animate smoothly\n13. ✅ Last updated timestamp shows relative time\n\n**UI/UX:**\n1. ✅ Desktop: Table layout with 7 columns\n2. ✅ Mobile: Card layout with stacked information\n3. ✅ Status badges use color-coded styling\n4. ✅ Progress bars change color based on percentage\n5. ✅ Hover states on all interactive rows\n6. ✅ Loading states during data fetch\n7. ✅ Empty state when no cohorts exist\n8. ✅ Live indicator shows polling status\n9. ✅ Time since last update displays correctly\n10. ✅ Responsive design works on all screen sizes\n\n**Integration:**\n1. ✅ API endpoints: `GET /api/tp/cohorts`, `GET /api/tp/cohorts/{id}`, `POST /api/tp/cohorts/{id}/remind`, `POST /api/tp/cohorts/{id}/export`\n2. ✅ Polling mechanism with cleanup on unmount\n3. ✅ Store getters calculate analytics correctly\n4. ✅ Modal components receive correct props\n5. ✅ Export triggers file download\n6. ✅ Reminder sends email notifications\n\n**Security:**\n1. ✅ All API calls require authentication (TP session)\n2. ✅ Authorization check: TP can only view their own cohorts\n3. ✅ Export endpoint rate limited (max 5 per hour)\n4. ✅ Reminder endpoint rate limited (max 10 per hour)\n5. ✅ No sensitive data exposed in list view\n\n**Quality:**\n1. ✅ Polling stops when component unmounts\n2. ✅ Error handling for failed API calls\n3. ✅ Data consistency across refreshes\n4. ✅ Performance: renders 100+ cohorts without lag\n5. ✅ No duplicate polling intervals",
},
{
number: "5.1",
title: "Student Portal - Document Upload Interface",
user_story: "**As a** Student,\n**I want** to upload required documents (ID, certificates, etc.) through a simple interface,\n**So that** I can provide the necessary proof documents for my cohort enrollment.",
background: "Students receive email invitations to join a cohort (Story 2.2). Upon clicking the link, they access the student portal where they must complete several steps:\n\n1. **Upload Required Documents**: Government ID, certificates, photos, etc.\n2. **Fill Assigned Fields**: Personal information, signatures, dates\n3. **Review & Submit**: Final confirmation before sponsor review\n\nThis story implements the document upload interface, which is the first step in the student workflow. The interface must:\n\n- Accept multiple file types (PDF, JPG, PNG)\n- Show upload progress\n- Validate file size and type\n- Allow preview of uploaded files\n- Support drag-and-drop\n- Work on mobile devices\n\nThe uploaded documents are stored in Active Storage and linked to the student\'s submission record. After upload, students proceed to fill their assigned fields (Story 5.2).\n\n**Integration Point**: This uploads documents that will be referenced in the final signed PDF generated by DocuSeal.",
acceptance: "**Functional:**\n1. ✅ Component loads and fetches document requirements on mount\n2. ✅ Displays list of required documents with descriptions\n3. ✅ Supports drag-and-drop file upload\n4. ✅ Supports click-to-upload file selection\n5. ✅ Validates file type against accepted types\n6. ✅ Validates file size against max size\n7. ✅ Shows upload progress bar during upload\n8. ✅ Displays uploaded files with name and size\n9. ✅ Allows preview of uploaded files\n10. ✅ Allows removal of uploaded files\n11. ✅ Shows error messages for validation failures\n12. ✅ Save Draft button saves progress without validation\n13. ✅ Continue button only enabled when all required files uploaded\n14. ✅ Progress bar updates correctly based on uploaded count\n\n**UI/UX:**\n1. ✅ Drag-and-drop shows visual feedback (border color change, background)\n2. ✅ Upload progress animates smoothly\n3. ✅ Success state shows green checkmark and background\n4. ✅ Error messages appear in red below upload area\n5. ✅ File preview shows appropriate icon (image vs document)\n6. ✅ File size formatted human-readable (KB, MB)\n7. ✅ Mobile-responsive design (stacks properly on small screens)\n8. ✅ Loading state during initial requirements fetch\n9. ✅ Empty state when no requirements exist\n10. ✅ Confirmation dialog before file removal\n\n**Integration:**\n1. ✅ API endpoint: `GET /api/student/submissions/{id}/requirements`\n2. ✅ API endpoint: `POST /api/student/submissions/{id}/documents` (with progress)\n3. ✅ API endpoint: `DELETE /api/student/submissions/{id}/documents/{req_id}`\n4. ✅ API endpoint: `POST /api/student/submissions/{id}/draft`\n5. ✅ API endpoint: `POST /api/student/submissions/{id}/complete-upload`\n6. ✅ Token authentication in headers\n7. ✅ Progress tracking via XMLHttpRequest upload events\n8. ✅ State persistence in Pinia store\n\n**Security:**\n1. ✅ Token-based authentication required\n2. ✅ Authorization check: student can only upload to their submission\n3. ✅ File type validation (server-side + client-side)\n4. ✅ File size validation (server-side + client-side)\n5. ✅ No executable file types allowed\n6. ✅ Rate limiting on upload endpoint (max 10 uploads per hour)\n7. ✅ Virus scanning on server (documented requirement)\n\n**Quality:**\n1. ✅ Uploads are atomic (all or nothing)\n2. ✅ Network errors handled gracefully with retry option\n3. ✅ No memory leaks (clean up file objects)\n4. ✅ Performance: handles files up to 50MB\n5. ✅ Browser compatibility: Chrome, Firefox, Safari, Edge",
},
{
number: "5.2",
title: "Student Portal - Form Filling & Field Completion",
user_story: "**As a** Student,\n**I want** to fill in my assigned form fields (personal info, signatures, dates, etc.),\n**So that** I can complete my portion of the document before the sponsor signs.",
background: "After uploading required documents (Story 5.1), students must fill their assigned fields in the document. This is the core of the student workflow where they provide:\n\n1. **Personal Information**: Name, address, contact details\n2. **Signatures**: Digital signature capture\n3. **Dates**: Date pickers for various fields\n4. **Checkboxes**: Agreements and confirmations\n5. **Text Fields**: Additional information or comments\n\nThe form builder (created by TP in Story 4.4) defines which fields each student must fill. This story implements the rendering and completion of those fields.\n\n**Key Requirements:**\n- Fields are pre-defined by TP in the template\n- Each student sees only their assigned fields\n- Signature can be drawn or typed\n- All fields must be valid before submission\n- Progress is auto-saved\n- Mobile-friendly input methods\n\n**Integration Point**: Field data is merged with uploaded documents and TP\'s signature to generate the final PDF in DocuSeal.",
acceptance: "**Functional:**\n1. ✅ Component loads and fetches form fields on mount\n2. ✅ Renders all field types correctly (text, email, date, number, checkbox, radio, select, signature, textarea)\n3. ✅ Validates each field type appropriately\n4. ✅ Shows error messages below invalid fields\n5. ✅ Signature canvas supports drawing with mouse/touch\n6. ✅ Signature can be cleared and replaced with text\n7. ✅ Progress bar updates as fields are completed\n8. ✅ Auto-save triggers every 30 seconds if changes detected\n9. ✅ Save Draft button works immediately\n10. ✅ Continue button disabled until all required fields valid\n11. ✅ Back button returns to previous step\n12. ✅ Existing data is restored if user returns to draft\n\n**UI/UX:**\n1. ✅ All inputs show focus states with blue ring\n2. ✅ Required fields marked with red asterisk\n3. ✅ Signature canvas shows drawing feedback\n4. ✅ Text signature modal appears centered\n5. ✅ Auto-save indicator shows when saving\n6. ✅ Success indicator appears briefly after save\n7. ✅ Mobile-responsive design (inputs stack properly)\n8. ✅ Radio buttons and checkboxes are clickable and accessible\n9. ✅ Date picker uses native browser date selector\n10. ✅ Textarea auto-expands or has scroll for long text\n\n**Integration:**\n1. ✅ API endpoint: `GET /api/student/submissions/{id}/form-fields`\n2. ✅ API endpoint: `POST /api/student/submissions/{id}/form-draft`\n3. ✅ API endpoint: `POST /api/student/submissions/{id}/form-data`\n4. ✅ API endpoint: `POST /api/student/submissions/{id}/complete-form`\n5. ✅ Token authentication in headers\n6. ✅ Form data and signature data sent to server\n7. ✅ State persistence in Pinia store\n8. ✅ Data restored on page reload\n\n**Security:**\n1. ✅ Token-based authentication required\n2. ✅ Authorization check: student can only fill their submission\n3. ✅ Input validation (client-side + server-side)\n4. ✅ XSS prevention (sanitized input)\n5. ✅ Rate limiting on save endpoints\n6. ✅ Audit log of all form saves\n\n**Quality:**\n1. ✅ Auto-save doesn\'t interfere with user typing\n2. ✅ Network errors handled gracefully\n3. ✅ No memory leaks (clean up intervals)\n4. ✅ Performance: handles 50+ fields without lag\n5. ✅ Browser compatibility: Chrome, Firefox, Safari, Edge",
},
{
number: "5.3",
title: "Student Portal - Progress Tracking & Save Draft",
user_story: "**As a** Student,\n**I want** to see my overall progress and save my work as a draft at any time,\n**So that** I can complete the submission at my own pace without losing work.",
background: "Students may need multiple sessions to complete their submission:\n1. Upload documents (Story 5.1)\n2. Fill form fields (Story 5.2)\n3. Review and submit (Story 5.4)\n\nThe student portal must provide:\n- **Progress Dashboard**: Visual overview of all steps and their status\n- **Draft Management**: Save and resume capability\n- **Session Persistence**: Data survives browser refresh\n- **Multi-step Navigation**: Jump between steps\n- **Completion Indicators**: Clear visual feedback\n\nThis story implements the progress tracking UI that shows all three steps (Upload, Form, Review) with their completion status, and provides a persistent \"Save Draft\" mechanism accessible from any step.\n\n**Integration Point**: This ties together Stories 5.1 and 5.2, providing the navigation layer that orchestrates the complete student workflow.",
acceptance: "**Functional:**\n1. ✅ Dashboard loads progress data on mount\n2. ✅ Shows correct overall progress percentage\n3. ✅ Displays all 3 steps with correct status\n4. ✅ Step cards show completion indicators (checkmark, numbers)\n5. ✅ Progress bars animate smoothly\n6. ✅ Status badge shows correct text and color\n7. ✅ Last saved timestamp updates correctly\n8. ✅ \"Save Draft\" button works and shows feedback\n9. ✅ \"Submit for Review\" only enabled when all steps complete\n10. ✅ \"Resume Workflow\" directs to appropriate step\n11. ✅ Clicking step cards navigates to that step\n12. ✅ Auto-save triggers every 30 seconds if changes detected\n\n**UI/UX:**\n1. ✅ Step cards have hover effects (lift, shadow)\n2. ✅ Active step shows ring highlight\n3. ✅ Progress bars animate from 0 to current value\n4. ✅ Status badge uses color-coded styling\n5. ✅ Last saved time formats correctly (just now, Xm ago, Xh ago)\n6. ✅ Success toast appears after save\n7. ✅ Loading state during save\n8. ✅ Mobile-responsive layout\n9. ✅ Step cards are clickable and show cursor pointer\n10. ✅ Help modal provides clear instructions\n\n**Integration:**\n1. ✅ API endpoint: `GET /api/student/submissions/{id}/progress`\n2. ✅ API endpoint: `POST /api/student/submissions/{id}/save-draft`\n3. ✅ API endpoint: `POST /api/student/submissions/{id}/submit`\n4. ✅ Token authentication in headers\n5. ✅ Navigation emits events to parent\n6. ✅ Progress data reflects uploads and form completion\n\n**Security:**\n1. ✅ Token-based authentication required\n2. ✅ Authorization check: student can only view their submission\n3. ✅ Submit endpoint validates all steps complete\n4. ✅ Rate limiting on save endpoints\n5. ✅ Audit log of all saves and submissions\n\n**Quality:**\n1. ✅ Auto-save doesn\'t trigger if no changes\n2. ✅ Navigation prevents invalid transitions\n3. ✅ Error handling for failed API calls\n4. ✅ No memory leaks (clean up intervals)\n5. ✅ Performance: loads in <2 seconds",
},
{
number: "5.4",
title: "Student Portal - Submission Confirmation & Status",
user_story: "**As a** Student,\n**I want** to review my complete submission and receive confirmation of successful submission,\n**So that** I can verify everything is correct and track when the sponsor signs.",
background: "After completing all three steps (upload, form filling, review), students need to:\n1. **Final Review**: See a summary of all uploaded documents and filled fields\n2. **Confirmation**: Receive clear confirmation that submission was successful\n3. **Status Tracking**: Monitor progress through sponsor signature and TP review phases\n4. **Email Notifications**: Get updates when status changes\n\nThis is the final step in the student workflow. The student portal must provide:\n- Complete submission summary\n- Clear success confirmation\n- Real-time status updates\n- Email notification settings\n- Access to final document once complete\n\n**Status Flow:**\n- **Pending**: Student hasn\'t submitted yet\n- **In Review**: Submitted, waiting for sponsor\n- **Sponsor Signed**: Sponsor completed their part\n- **TP Reviewed**: TP completed final review\n- **Completed**: All parties finished, document finalized\n\n**Integration Point**: This story completes the student portal frontend (Phase 5). It connects to the sponsor portal (Phase 6) and TP review (Phase 4).",
acceptance: "**Functional:**\n1. ✅ Component loads status data on mount\n2. ✅ Shows success banner on fresh submission\n3. ✅ Displays timeline with all 4 stages\n4. ✅ Updates timeline icons based on status\n5. ✅ Shows uploaded documents list with sizes\n6. ✅ Shows completed fields with values\n7. ✅ Displays estimated completion time\n8. ✅ Refresh button fetches latest status\n9. ✅ Download button works when completed\n10. ✅ Notification settings can be updated\n11. ✅ Contact support opens email client\n12. ✅ Polling updates status every 60 seconds\n\n**UI/UX:**\n1. ✅ Success banner can be dismissed\n2. ✅ Timeline shows connector lines between stages\n3. ✅ Status badges use color-coded styling\n4. ✅ Current stage is highlighted\n5. ✅ Completed stages show green checkmarks\n6. ✅ Pending stages show appropriate icons\n7. ✅ Document list shows file sizes formatted\n8. ✅ Field values are displayed clearly\n9. ✅ Toast notifications show after actions\n10. ✅ Mobile-responsive design\n\n**Integration:**\n1. ✅ API endpoint: `GET /api/student/submissions/{id}/status`\n2. ✅ API endpoint: `GET /api/student/submissions/{id}/download`\n3. ✅ API endpoint: `POST /api/student/submissions/{id}/notifications`\n4. ✅ Token authentication in headers\n5. ✅ Polling mechanism with cleanup\n6. ✅ Data reflects actual submission state\n\n**Security:**\n1. ✅ Token-based authentication required\n2. ✅ Authorization check: student can only view their submission\n3. ✅ Download endpoint validates completion\n4. ✅ Rate limiting on status refresh (max 30 per hour)\n5. ✅ Audit log of all downloads\n\n**Quality:**\n1. ✅ Polling stops when component unmounts\n2. ✅ Error handling for failed API calls\n3. ✅ No duplicate polling intervals\n4. ✅ Performance: loads in <1 second\n5. Data consistency across refreshes",
},
{
number: "5.5",
title: "Student Portal - Email Notifications & Reminders",
user_story: "**As a** Student,\n**I want** to receive email notifications for status updates and reminders to complete my submission,\n**So that** I can stay informed and complete my work on time without constantly checking the portal.",
background: "Students need to stay informed about their submission progress without manually checking the portal. The system should provide:\n\n1. **Initial Invitation Email**: Sent when cohort is created, contains access link with token\n2. **Reminder Emails**: Sent if student hasn\'t started or hasn\'t completed after certain time\n3. **Status Update Emails**: Sent when key milestones are reached\n4. **Final Completion Email**: Sent when document is fully signed and ready\n\n**Email Types:**\n- **Invitation**: \"You\'ve been invited to join [Cohort Name]\"\n- **Reminder - Not Started**: \"Don\'t forget to complete your submission\"\n- **Reminder - Incomplete**: \"You\'re almost there! Finish your submission\"\n- **Status - Sponsor Signed**: \"Sponsor has signed your document\"\n- **Status - Completed**: \"Your document is ready!\"\n- **TP Reminder**: (TP sends to students who haven\'t completed)\n\n**Key Requirements:**\n- Emails contain secure, time-limited links\n- Links use JWT tokens (Story 2.2, 2.3)\n- Unsubscribe option in all emails\n- Email preferences can be managed\n- Reminder frequency is configurable\n- Email templates are customizable\n\n**Integration Point**: This story connects to the email system (Story 2.2, 2.3) and provides the student-facing notification preferences.",
acceptance: "**Functional:**\n1. ✅ Component loads existing preferences on mount\n2. ✅ All 4 notification toggles work correctly\n3. ✅ Reminder frequency radio buttons work\n4. ✅ Save button persists changes to server\n5. ✅ Reset to defaults restores original settings\n6. ✅ Unsubscribe all disables all notifications\n7. ✅ Confirmation dialog before unsubscribe\n8. ✅ Email preview updates based on settings\n9. ✅ Shows success toast after save\n10. ✅ Loading state during API calls\n\n**UI/UX:**\n1. ✅ Toggles show clear on/off states\n2. ✅ Settings organized in logical sections\n3. ✅ Warning section visually distinct (red border)\n4. ✅ Email preview shows realistic example\n5. ✅ Success toast appears for 2 seconds\n6. ✅ Loading overlay blocks interaction\n7. ✅ Mobile-responsive design\n8. ✅ Hover states on all interactive elements\n\n**Integration:**\n1. ✅ API endpoint: `GET /api/student/submissions/{id}/notification-preferences`\n2. ✅ API endpoint: `PUT /api/student/submissions/{id}/notification-preferences`\n3. ✅ API endpoint: `POST /api/student/submissions/{id}/send-invitation`\n4. ✅ API endpoint: `POST /api/student/submissions/{id}/send-reminder`\n5. ✅ Token authentication in headers\n6. ✅ Settings persist across sessions\n\n**Security:**\n1. ✅ Token-based authentication required\n2. ✅ Authorization check: student can only manage their preferences\n3. ✅ Rate limiting on update endpoint (max 10 per hour)\n4. ✅ Validation of reminder frequency values\n5. ✅ Audit log of all preference changes\n\n**Quality:**\n1. ✅ No duplicate API calls on rapid clicks\n2. ✅ Error handling for failed API calls\n3. ✅ State consistency between UI and server\n4. ✅ Performance: loads in <1 second\n5. Browser compatibility: Chrome, Firefox, Safari, Edge",
},
{
number: "6.1",
title: "Sponsor Portal - Cohort Dashboard & Bulk Signing Interface",
user_story: "**As a** Sponsor,\n**I want** to view all pending student documents in a cohort and sign them all at once,\n**So that** I can efficiently complete my signing responsibility without reviewing each submission individually.",
background: "Sponsors receive a single email per cohort (per FR12) with a secure link to the sponsor portal. Upon accessing the portal, they see:\n\n1. **Cohort Overview**: Name, total students, completion status\n2. **Student List**: All students with their completion status\n3. **Bulk Signing**: Sign once to apply to all pending submissions\n4. **Progress Tracking**: Real-time updates of signing progress\n\n**Key Requirements:**\n- Single signing action for entire cohort\n- Preview of what will be signed\n- Clear indication of which students are affected\n- Confirmation before signing\n- Immediate status update after signing\n- Email confirmation to TP after sponsor signs\n\n**Workflow:**\n1. Sponsor clicks email link with token\n2. Portal loads cohort dashboard\n3. Sponsor reviews student list\n4. Sponsor signs once (signature or typed name)\n5. System applies signature to all student submissions\n6. Status updates to \"Sponsor Signed\"\n7. TP receives notification\n8. Students receive status update email\n\n**Integration Point**: This story connects to the email system (Story 2.2, 2.3) and the backend signing workflow (Stories 2.5, 2.6).",
acceptance: "**Functional:**\n1. ✅ Component loads cohort data on mount\n2. ✅ Shows correct student counts (total, pending, completed)\n3. ✅ Displays student list with status\n4. ✅ Search filters students by name/email\n5. ✅ Status filter works correctly\n6. ✅ Signature method selection works\n7. ✅ Canvas signature drawing works\n8. ✅ Typed signature input works\n9. ✅ Clear signature button works\n10. ✅ Confirmation checkbox required\n11. ✅ Preview modal shows affected students\n12. ✅ Preview modal shows signature preview\n13. ✅ Bulk sign executes successfully\n14. ✅ Success modal appears after signing\n15. ✅ Data refreshes after signing\n\n**UI/UX:**\n1. ✅ Desktop: Table layout with 5 columns\n2. ✅ Mobile: Card layout with stacked information\n3. ✅ Status badges use color-coded styling\n4. ✅ Progress bars animate smoothly\n5. ✅ Quick stats cards show key metrics\n6. ✅ Signature canvas shows drawing feedback\n7. ✅ Modals are centered and scrollable\n8. ✅ Loading overlay blocks interaction\n9. ✅ Success modal shows confirmation\n10. ✅ Toast notifications for errors\n\n**Integration:**\n1. ✅ API endpoint: `GET /api/sponsor/cohorts/{id}`\n2. ✅ API endpoint: `POST /api/sponsor/cohorts/{id}/bulk-sign`\n3. ✅ Token authentication in headers\n4. ✅ Signature data sent correctly\n5. ✅ State updates after signing\n\n**Security:**\n1. ✅ Token-based authentication required\n2. ✅ Authorization check: sponsor can only sign their assigned cohorts\n3. ✅ Validation: all required fields before signing\n4. ✅ Rate limiting on bulk sign (max 5 per hour)\n5. ✅ Audit log of all signing actions\n\n**Quality:**\n1. ✅ No duplicate signing attempts\n2. ✅ Error handling for failed API calls\n3. ✅ Data consistency after signing\n4. ✅ Performance: handles 100+ students\n5. ✅ Browser compatibility: Chrome, Firefox, Safari, Edge",
},
{
number: "6.2",
title: "Sponsor Portal - Email Notifications & Reminders",
user_story: "**As a** Sponsor,\n**I want** to receive email notifications about signing requests and reminders to complete my cohort signing,\n**So that** I can stay informed and fulfill my signing responsibility on time without constantly checking the portal.",
background: "Sponsors need to stay informed about their signing responsibilities without manually monitoring the portal. The system should provide:\n\n1. **Initial Invitation Email**: Sent when TP creates cohort and assigns sponsor\n2. **Reminder Emails**: Sent if sponsor hasn\'t accessed the cohort after certain time\n3. **Status Update Emails**: Sent when students complete their submissions\n4. **Completion Confirmation**: Sent after sponsor completes bulk signing\n\n**Email Types:**\n- **Invitation**: \"You\'ve been assigned to sign documents for [Cohort Name]\"\n- **Reminder - Not Accessed**: \"Action required: Sign documents for [Cohort Name]\"\n- **Reminder - Partial**: \"You\'re almost done! [X] students still need your signature\"\n- **Status - Student Completed**: \"[Student Name] has submitted their documents\"\n- **Status - Signing Complete**: \"You\'ve successfully signed all documents\"\n\n**Key Requirements:**\n- Emails contain secure, time-limited links with JWT tokens\n- Unsubscribe option in all emails (per FR12)\n- Email preferences can be managed by sponsor\n- Reminder frequency is configurable\n- Single email per cohort (no duplicates per student)\n- Immediate notification when students complete submissions\n\n**Integration Point**: This story connects to the email system (Stories 2.2, 2.3) and provides sponsor-facing notification management.",
acceptance: "**Functional:**\n1. ✅ Component loads existing preferences on mount\n2. ✅ All 4 notification toggles work correctly\n3. ✅ Reminder frequency radio buttons work\n4. ✅ Save button persists changes to server\n5. ✅ Reset to defaults restores original settings\n6. ✅ Unsubscribe all disables all notifications\n7. ✅ Confirmation dialog before unsubscribe\n8. ✅ Email preview shows realistic example\n9. ✅ Shows success toast after save\n10. ✅ Loading state during API calls\n\n**UI/UX:**\n1. ✅ Toggles show clear on/off states\n2. ✅ Settings organized in logical sections\n3. ✅ Warning section visually distinct (red border)\n4. ✅ Email preview shows realistic example\n5. ✅ Success toast appears for 2 seconds\n6. ✅ Loading overlay blocks interaction\n7. ✅ Mobile-responsive design\n8. ✅ Hover states on all interactive elements\n\n**Integration:**\n1. ✅ API endpoint: `GET /api/sponsor/cohorts/{id}/notification-preferences`\n2. ✅ API endpoint: `PUT /api/sponsor/cohorts/{id}/notification-preferences`\n3. ✅ API endpoint: `POST /api/sponsor/cohorts/{id}/send-invitation`\n4. ✅ API endpoint: `POST /api/sponsor/cohorts/{id}/send-reminder`\n5. ✅ API endpoint: `POST /api/sponsor/cohorts/{id}/send-student-alert`\n6. ✅ Token authentication in headers\n7. ✅ Settings persist across sessions\n\n**Security:**\n1. ✅ Token-based authentication required\n2. ✅ Authorization check: sponsor can only manage their preferences\n3. ✅ Rate limiting on update endpoint (max 10 per hour)\n4. ✅ Validation of reminder frequency values\n5. ✅ Audit log of all preference changes\n\n**Quality:**\n1. ✅ No duplicate API calls on rapid clicks\n2. ✅ Error handling for failed API calls\n3. ✅ State consistency between UI and server\n4. ✅ Performance: loads in <1 second\n5. Browser compatibility: Chrome, Firefox, Safari, Edge",
},
{
number: "7.1",
title: "End-to-End Workflow Testing",
user_story: "**As a** QA Engineer,\n**I want** to test the complete 3-portal workflow from start to finish,\n**So that** I can verify all integrations work correctly and identify any breaking issues before production deployment.",
background: "This story validates the entire FloDoc system through complete end-to-end testing. The workflow must be tested in sequence:\n\n1. **TP Portal**: Create cohort, configure template, assign sponsor, sign first student\n2. **Student Portal**: Receive invitation, upload documents, fill forms, submit\n3. **Sponsor Portal**: Receive notification, sign all documents at once\n4. **TP Portal**: Review and finalize cohort\n\n**Key Testing Scenarios:**\n- **Happy Path**: All parties complete their steps successfully\n- **Edge Cases**: Invalid tokens, expired sessions, network failures\n- **State Transitions**: Proper status updates at each step\n- **Email Delivery**: All notifications sent and received\n- **Data Integrity**: No data loss or corruption\n- **Concurrent Access**: Multiple users accessing same cohort\n- **Error Recovery**: Graceful handling of failures\n\n**Test Data Requirements:**\n- Multiple cohorts with varying student counts (1, 5, 25, 100)\n- Different document types (PDF, images)\n- Various form field types (signature, text, date, checkbox)\n- Different signature methods (draw, type)\n\n**Integration Points to Verify:**\n- Template → Cohort mapping\n- Student → Submission mapping\n- Bulk signing → Individual student updates\n- Email triggers → Actual email delivery\n- Token generation → Token validation\n- State machine transitions\n- Excel export data accuracy",
acceptance: "**Functional:**\n1. ✅ Complete workflow tested with 5 students\n2. ✅ Complete workflow tested with 25 students\n3. ✅ Complete workflow tested with 100 students\n4. ✅ All edge cases handled (expired tokens, network failures, etc.)\n5. ✅ Concurrent access scenarios tested\n6. ✅ Data integrity verified throughout\n7. ✅ Email delivery verified in correct sequence\n8. ✅ State transitions validated\n9. ✅ Error recovery tested\n10. ✅ Performance benchmarks met\n\n**Integration:**\n1. ✅ TP Portal → Student Portal handoff verified\n2. ✅ Student Portal → Sponsor Portal handoff verified\n3. ✅ Sponsor Portal → TP Portal handoff verified\n4. ✅ Email system integration verified\n5. ✅ Token system integration verified\n6. ✅ Database state consistency verified\n7. ✅ API endpoints tested end-to-end\n\n**Security:**\n1. ✅ Token validation enforced throughout\n2. ✅ Authorization checks at each step\n3. ✅ No data leakage between users\n4. ✅ Rate limiting tested\n5. ✅ Audit trail completeness verified\n\n**Performance:**\n1. ✅ 100-student cohort completes within 5 seconds\n2. ✅ Email delivery within 10 seconds\n3. ✅ API response times < 500ms\n4. No memory leaks in long-running sessions\n\n**Quality:**\n1. 100% test coverage for critical paths\n2. All tests pass consistently\n3. No flaky tests\n4. Test data cleanup verified",
},
{
number: "7.2",
title: "Mobile Responsiveness Testing",
user_story: "**As a** QA Engineer,\n**I want** to test all three portals across different screen sizes and devices,\n**So that** I can ensure the FloDoc system works perfectly on mobile, tablet, and desktop devices.",
background: "FloDoc must work seamlessly across all device types:\n- **Mobile**: 320px - 640px (smartphones)\n- **Tablet**: 641px - 1024px (iPad, Android tablets)\n- **Desktop**: 1025px+ (laptops, monitors)\n\n**Portal-Specific Mobile Requirements:**\n\n**TP Portal**:\n- Complex admin interface must remain usable\n- Bulk operations need touch-friendly targets\n- Data tables must be responsive\n- Navigation must collapse to hamburger menu\n- Forms must stack vertically\n- Progress indicators must be visible\n\n**Student Portal**:\n- Mobile-first design (primary use case)\n- Maximum 3 clicks to complete any action\n- Touch targets minimum 44x44px\n- File upload must work with mobile camera\n- Form fields must be mobile-optimized\n- Progress tracking must be clear\n\n**Sponsor Portal**:\n- Bulk signing must work on touch devices\n- Signature canvas must support touch drawing\n- Student list must be scrollable\n- Preview modal must be mobile-friendly\n- Action buttons must be thumb-accessible\n\n**Testing Scenarios:**\n- **Viewport Sizes**: Test at 10+ breakpoints\n- **Orientation**: Portrait and landscape modes\n- **Touch Gestures**: Swipe, tap, pinch, scroll\n- **Input Methods**: Touch, keyboard, mouse\n- **Browser Compatibility**: Chrome, Safari, Firefox on mobile\n- **OS Compatibility**: iOS, Android\n\n**Critical Components to Test:**\n- Navigation menus\n- Forms and inputs\n- Tables and lists\n- Modals and dialogs\n- Buttons and links\n- File uploads\n- Signature capture\n- Progress indicators\n- Error messages\n- Loading states",
acceptance: "**Functional:**\n1. ✅ All portals render correctly on 375px (mobile)\n2. ✅ All portals render correctly on 768px (tablet)\n3. ✅ All portals render correctly on 1280px (desktop)\n4. ✅ Touch targets are minimum 44x44px everywhere\n5. ✅ Forms are mobile-optimized (proper input types)\n6. ✅ Navigation collapses to hamburger on mobile\n7. ✅ Tables scroll horizontally on small screens\n8. ✅ Modals are full-screen on mobile\n9. ✅ Signature canvas works with touch\n10. ✅ File upload works with mobile camera\n\n**UI/UX:**\n1. ✅ Portrait and landscape modes work\n2. ✅ Swipe gestures work correctly\n3. ✅ Pinch-to-zoom works on document preview\n4. ✅ Long press shows context menus\n5. ✅ Loading states are visible on all sizes\n6. ✅ Error messages are readable on mobile\n7. ✅ Buttons are thumb-accessible\n8. ✅ Text is readable without zoom\n\n**Integration:**\n1. ✅ All portals maintain consistent design\n2. ✅ Responsive breakpoints work across portals\n3. ✅ Touch events propagate correctly\n4. ✅ Keyboard navigation works on tablets\n5. ✅ Mouse events don\'t break touch\n\n**Security:**\n1. ✅ No sensitive data exposed in mobile view\n2. ✅ Touch events don\'t bypass security\n3. ✅ Mobile camera upload is secure\n4. ✅ Session management works on mobile\n\n**Quality:**\n1. ✅ Tests pass on all viewport sizes\n2. ✅ Visual regression tests pass\n3. ✅ Accessibility tests pass (WCAG 2.1 AA)\n4. ✅ No horizontal scroll on content\n5. ✅ Performance is acceptable on mobile",
},
{
number: "7.3",
title: "Performance Testing (50+ Students)",
user_story: "**As a** QA Engineer,\n**I want** to test system performance with large cohorts (50+ students),\n**So that** I can ensure FloDoc scales efficiently and meets NFR requirements.",
background: "Performance is critical for production success. This story validates:\n- **Load Time**: Pages must load within acceptable timeframes\n- **Database Queries**: No N+1 queries, optimized indexes\n- **Memory Usage**: No memory leaks, efficient garbage collection\n- **Concurrent Users**: System must handle multiple users simultaneously\n- **Large Cohorts**: 50, 100, even 500 students per cohort\n- **Bulk Operations**: Signing 100+ students at once\n- **Excel Export**: Generate large files without timeout\n- **Email Delivery**: Queue and send 100+ emails efficiently\n\n**Performance Requirements (from NFRs):**\n- Page load time: <2 seconds\n- API response time: <500ms\n- Bulk signing: <5 seconds for 100 students\n- Excel export: <10 seconds for 100 rows\n- Email queue: Process 100 emails in <30 seconds\n- Memory growth: <10% per operation\n- Database queries: <20 per page load\n\n**Test Scenarios:**\n1. **Cohort Creation**: Create cohort with 100 students\n2. **Student Upload**: 100 students uploading documents simultaneously\n3. **Bulk Signing**: Sponsor signs 100 students at once\n4. **Excel Export**: Export 100 student records\n5. **Email Blast**: Send 100 invitation emails\n6. **Concurrent Access**: 10 users accessing same cohort\n7. **Database Load**: Complex queries with large datasets\n8. **Memory Leak**: Long-running sessions over hours\n\n**Tools and Monitoring:**\n- **Rails Panel**: Query count and time\n- **Bullet**: N+1 query detection\n- **rack-mini-profiler**: Performance profiling\n- **memory_profiler**: Memory usage tracking\n- **New Relic**: Production monitoring simulation\n- **JMeter**: Load testing\n- **PgHero**: Database performance",
acceptance: "**Functional:**\n1. ✅ Cohort creation with 100 students <2 seconds\n2. Bulk signing 100 students <5 seconds\n3. Excel export 100 rows <10 seconds\n4. Email queue 100 messages <30 seconds\n5. Concurrent access (10 users) <2 seconds\n6. Student uploads (100 concurrent) <5 seconds\n7. Database queries <20 per page load\n8. API responses <500ms average\n\n**Performance:**\n1. No N+1 queries detected\n2. Proper database indexes used\n3. Memory growth <10% per operation\n4. No memory leaks over 10 iterations\n5. Object creation <1000 per operation\n6. GC overhead <5% of total time\n7. Sustained load (100 req/min) <60s total\n\n**Database:**\n1. All queries use indexes\n2. No SELECT * queries\n3. Transactions used for bulk operations\n4. Query count optimized\n5. Table sizes reasonable\n\n**Quality:**\n1. All performance tests pass consistently\n2. No flaky performance tests\n3. Performance metrics documented\n4. Bottlenecks identified and documented\n5. Recommendations provided",
},
{
number: "7.4",
title: "Security Audit & Penetration Testing",
user_story: "**As a** Security Engineer,\n**I want** to perform comprehensive security testing on all three portals,\n**So that** I can identify and remediate vulnerabilities before production deployment.",
background: "Security is paramount for a document signing platform handling sensitive student data. This story validates:\n\n**Authentication Security:**\n- JWT token generation and validation\n- Token expiration and renewal mechanisms\n- Ad-hoc access pattern security (no account creation)\n- Token leakage prevention\n- Session management\n\n**Authorization Security:**\n- Role-based access control (TP, Student, Sponsor)\n- Cross-portal access prevention\n- Data isolation between cohorts\n- Proper Cancancan ability definitions\n- API endpoint protection\n\n**Data Security:**\n- Student PII protection (names, emails, documents)\n- Document encryption at rest\n- Secure file uploads (content validation)\n- GDPR compliance (data retention, deletion)\n- Audit trail integrity\n\n**Input Validation:**\n- SQL injection prevention\n- XSS prevention (Vue templates, form inputs)\n- File upload validation (type, size, content)\n- API parameter sanitization\n- Mass assignment protection\n\n**Web Security:**\n- CSRF protection\n- CORS configuration\n- HTTPS enforcement\n- Secure headers (CSP, HSTS, X-Frame-Options)\n- Clickjacking prevention\n\n**Email Security:**\n- Email spoofing prevention\n- Link tampering protection\n- Token expiration in emails\n- Secure email templates\n\n**Third-Party Security:**\n- DocuSeal API integration security\n- Webhook signature verification\n- External service authentication\n\n**Compliance:**\n- OWASP Top 10 coverage\n- GDPR data protection requirements\n- Audit logging for all sensitive operations",
acceptance: "**Authentication Security:**\n1. ✅ JWT tokens are cryptographically signed and validated\n2. ✅ Token expiration enforced (30 days default)\n3. ✅ Token renewal mechanism works without data loss\n4. ✅ Expired tokens rejected with proper error\n5. ✅ Old tokens invalidated after renewal\n6. ✅ Ad-hoc access tokens contain no sensitive data\n7. ✅ Rate limiting prevents brute force attacks\n\n**Authorization Security:**\n1. ✅ Role-based access control enforced (TP, Student, Sponsor)\n2. ✅ Cross-portal access prevented\n3. ✅ Data isolation between cohorts enforced\n4. ✅ Cancancan abilities properly defined\n5. ✅ API endpoints protected by authorization\n6. ✅ Horizontal privilege escalation prevented\n7. ✅ Vertical privilege escalation prevented\n\n**Data Security:**\n1. ✅ Documents encrypted at rest (Active Storage)\n2. ✅ Sensitive fields encrypted in database\n3. ✅ PII properly sanitized and validated\n4. ✅ GDPR retention policies enforced\n5. ✅ Audit logs capture all sensitive operations\n6. ✅ Data export includes complete user data\n7. ✅ Data deletion properly anonymizes\n\n**Input Validation:**\n1. ✅ SQL injection prevented (parameterized queries)\n2. ✅ XSS prevented (input sanitization, CSP headers)\n3. ✅ File upload validation (type, size, content)\n4. ✅ API parameter sanitization\n5. ✅ Mass assignment protection\n6. ✅ No malicious file types accepted\n7. ✅ File size limits enforced\n\n**Web Security:**\n1. ✅ CSRF protection enabled\n2. ✅ CORS properly configured\n3. ✅ HTTPS enforced\n4. ✅ Secure headers present (CSP, HSTS, X-Frame-Options)\n5. ✅ Clickjacking prevention\n6. ✅ No open redirects\n7. ✅ Session fixation prevented\n\n**Email Security:**\n1. ✅ Email spoofing prevented (SPF, DKIM)\n2. ✅ Secure tokens in emails with expiration\n3. ✅ Token leakage prevented in logs\n4. ✅ Email templates properly sanitized\n5. ✅ Link tampering protection\n\n**Third-Party Security:**\n1. ✅ DocuSeal API responses validated\n2. ✅ Webhook signature verification\n3. ✅ Replay attack prevention\n4. ✅ External service authentication secure\n5. ✅ No sensitive data in webhook payloads\n\n**Compliance:**\n1. ✅ OWASP Top 10 coverage verified\n2. ✅ GDPR compliance validated\n3. ✅ Audit trail integrity maintained\n4. ✅ Data retention policies implemented\n5. ✅ User data export functionality works\n\n**Testing Coverage:**\n1. ✅ All security tests pass\n2. ✅ OWASP ZAP scan clean (or critical issues documented)\n3. ✅ Brakeman shows no high-severity warnings\n4. ✅ Penetration test scenarios pass\n5. ✅ Security monitoring alerts functional",
},
{
number: "7.5",
title: "User Acceptance Testing",
user_story: "**As a** Product Owner,\n**I want** to conduct comprehensive user acceptance testing with real stakeholders,\n**So that** I can validate the system meets business requirements and user needs before production launch.",
background: "User Acceptance Testing (UAT) is the final validation phase where real users test the complete system in a production-like environment. This story validates:\n\n**Stakeholder Testing:**\n- **Training Provider (TP)**: Creates cohorts, manages students, reviews submissions\n- **Students**: Upload documents, fill forms, sign documents\n- **Sponsors**: Bulk sign documents, track progress\n\n**Workflow Validation:**\n- Complete end-to-end cohort lifecycle\n- All three portals working together\n- Email notifications delivered correctly\n- Document signing workflow complete\n- Excel export functionality\n- Token renewal and session management\n\n**Real-World Scenarios:**\n- Large cohorts (50+ students)\n- Multiple concurrent users\n- Different document types\n- Various form field types\n- Edge cases and error handling\n\n**Business Process Validation:**\n- TP creates cohort with 50 students\n- TP signs first student\'s document\n- System auto-fills TP signature to all students\n- Students receive emails and upload documents\n- Students fill forms and sign\n- Sponsor receives ONE email for entire cohort\n- Sponsor bulk signs all students\n- TP reviews and finalizes cohort\n- Excel export contains all data\n\n**UX/Usability Testing:**\n- Intuitive navigation across portals\n- Clear user instructions\n- Mobile responsiveness\n- Accessibility compliance\n- Performance under real usage\n\n**Data Integrity:**\n- No data loss during workflow\n- Proper audit trail\n- Correct document generation\n- Accurate state management\n- Proper error recovery",
acceptance: "**TP Portal UAT:**\n1. ✅ Can create cohort with 50+ students in <2 seconds\n2. Can upload and configure template PDF\n3. Can sign first document and auto-fill to all students\n4. Can monitor real-time progress across all students\n5. Can export complete cohort data to Excel\n6. Can finalize cohort after sponsor approval\n7. Email notifications delivered correctly\n8. Token renewal works without data loss\n9. Mobile responsive on tablets and phones\n10. No data loss during any operation\n\n**Student Portal UAT:**\n1. Can access portal via email link\n2. Can upload required documents\n3. Can fill all 12 field types correctly\n4. Can sign documents with signature pad\n5. Can save drafts and resume later\n6. Receives timely email notifications\n7. Cannot access other students\' documents\n8. Mobile responsive and touch-friendly\n9. WCAG 2.1 AA accessibility compliant\n10. Clear error messages and guidance\n\n**Sponsor Portal UAT:**\n1. Can access portal via email link\n2. Can bulk sign all students at once\n3. Can track progress across three tabs (Waiting/In Progress/Completed)\n4. Receives exactly ONE email per cohort\n5. No duplicate email notifications\n6. Mobile responsive on all devices\n7. WCAG 2.1 AA accessibility compliant\n8. Signature appears on all student documents\n9. Cannot access other cohorts\n10. Clear progress indicators\n\n**End-to-End Workflow UAT:**\n1. Complete 3-party workflow succeeds\n2. TP signs first, auto-fills to all students\n3. All students receive emails and can complete\n4. Sponsor receives single email notification\n5. Sponsor bulk signs all students\n6. TP reviews and finalizes cohort\n7. Excel export contains complete data\n8. Audit trail captures all events\n9. No data corruption or loss\n10. All state transitions work correctly\n\n**Performance UAT:**\n1. Cohort creation with 50 students <2 seconds\n2. Bulk signing 50 students <5 seconds\n3. Excel export 50 rows <10 seconds\n4. Email delivery 50 messages <30 seconds\n5. Concurrent access (10 users) <2 seconds\n6. Student uploads (50 concurrent) <5 seconds\n7. Database queries <20 per page load\n8. API responses <500ms average\n9. No memory leaks\n10. No N+1 queries\n\n**Security UAT:**\n1. Tokens expire after 30 days\n2. Token renewal works without data loss\n3. Expired tokens rejected with clear error\n4. Cross-portal access prevented\n5. Data isolation between cohorts enforced\n6. No SQL injection vulnerabilities\n7. No XSS vulnerabilities\n8. All sensitive operations logged\n9. GDPR compliance validated\n10. No unauthorized access possible\n\n**UX/Usability UAT:**\n1. Navigation is intuitive across all portals\n2. User instructions are clear and helpful\n3. Error messages are actionable\n4. Success feedback is provided\n5. Loading states are clear\n6. Mobile experience is excellent\n7. Desktop experience is excellent\n8. Touch gestures work on mobile\n9. Keyboard navigation works\n10. Screen readers work correctly\n\n**Data Integrity UAT:**\n1. No data loss during workflow\n2. All documents generated correctly\n3. All signatures appear correctly\n4. Audit trail is complete and accurate\n5. State management is correct\n6. Email delivery is reliable\n7. Excel export is accurate\n8. Token system works correctly\n9. Error recovery works\n10. Data consistency maintained",
},
{
number: "8.0",
title: "Development Infrastructure Setup (Local Docker)",
user_story: "**As a** Developer,\n**I want** to set up a local Docker-based development infrastructure with PostgreSQL and Redis,\n**So that** I can demonstrate the complete FloDoc system to management without cloud costs or complexity.",
background: "Before investing in production AWS infrastructure, we need a working demonstration environment that:\n- Can be started with a single command\n- Requires no cloud costs or complex setup\n- Accurately represents the production architecture\n- Allows management to validate the 3-portal cohort management system\n- Can be used for UAT and stakeholder demonstrations\n\nThis story establishes the foundation using Docker Compose, which provides the same architecture as production (PostgreSQL + Redis + Rails app) but runs entirely on a local machine or demo server.",
acceptance: "**Infrastructure:**\n1. ✅ Docker Compose file created with all services\n2. ✅ PostgreSQL container running and accessible\n3. ✅ Redis container running and accessible\n4. ✅ Minio (S3-compatible) container running\n5. ✅ MailHog container running for email testing\n6. ✅ Rails app container running on port 3000\n7. ✅ Sidekiq container running for background jobs\n\n**Configuration:**\n1. ✅ Database configuration for development\n2. ✅ Redis configuration for development\n3. ✅ Storage configuration for Minio\n4. ✅ Email configuration for MailHog\n5. ✅ Environment variables properly set\n6. ✅ Secrets configured for development\n\n**Automation:**\n1. ✅ Setup script automates initialization\n2. ✅ Teardown script stops and cleans up\n3. ✅ Health check script verifies services\n4. ✅ All scripts executable and documented\n\n**Functionality:**\n1. ✅ Application starts successfully\n2. ✅ Database migrations run\n3. ✅ Seed data can be loaded\n4. ✅ File uploads work (via Minio)\n5. ✅ Emails captured by MailHog\n6. ✅ Background jobs process via Sidekiq\n7. ✅ All three portals accessible\n\n**Documentation:**\n1. ✅ README with setup instructions\n2. ✅ Quick start guide\n3. ✅ Management demo script",
},
{
number: "8.0.1",
title: "Management Demo Readiness & Validation",
user_story: "**As a** Product Manager,\n**I want** to validate the complete 3-portal cohort management workflow end-to-end,\n**So that** I can demonstrate FloDoc v3 to management with confidence and real data.",
background: "After setting up the local Docker infrastructure (Story 8.0), we need to:\n- Test the complete 3-portal workflow with real data\n- Validate all acceptance criteria from previous stories\n- Create a polished demo script for management\n- Ensure the system is production-ready for demonstration\n- Identify and fix any remaining issues before stakeholder review\n\nThis story focuses on **using** the system, not building it. We\'ll create sample cohorts, enroll students, complete signatures, and verify the entire flow works as designed.",
acceptance: "**Functional:**\n1. ✅ Complete 3-portal workflow tested end-to-end\n2. ✅ Sample cohort with 5+ students created\n3. ✅ All students complete their signing workflow\n4. ✅ Sponsor successfully signs once for entire cohort\n5. ✅ Excel export generates valid file with all data\n6. ✅ All documents signed and stored correctly\n\n**UI/UX:**\n1. ✅ All three portals render correctly\n2. ✅ Progressive disclosure works as designed\n3. ✅ Tab navigation functions properly\n4. ✅ Design system compliance verified\n5. ✅ Mobile responsiveness tested\n\n**Integration:**\n1. ✅ Sidekiq processes all background jobs\n2. ✅ Minio stores all uploaded files\n3. ✅ MailHog captures all emails\n4. ✅ PostgreSQL maintains correct data state\n5. ✅ Redis caching works properly\n\n**Quality:**\n1. ✅ No critical bugs blocking demo\n2. ✅ Performance acceptable (< 2s page loads)\n3. Error handling graceful\n4. Data integrity verified\n\n**Demo Readiness:**\n1. Demo script created and tested\n2. Management can access all portals\n3. Sample data is realistic and compelling\n4. All stakeholders can complete their tasks",
},
{
number: "8.5",
title: "User Communication & Training Materials",
user_story: "**As a** Training Provider (TP Admin),\n**I want** clear guidance on using FloDoc\'s 3-portal system,\n**So that** I can manage cohorts effectively without confusion.",
background: "Existing DocuSeal users need to understand:\n- What changed (3-portal workflow)\n- How to use new features (cohort management)\n- Where to get help (support channels)\n- What\'s different (ad-hoc student/sponsor access)\n\nWithout this communication, adoption will suffer and support will be overwhelmed. This story addresses PO Validation Issue #3 (User Communication & Training Plan Missing).\n\n**Key Deliverables:**\n1. Migration announcement for existing users\n2. TP Portal \"Getting Started\" guide\n3. Student Portal onboarding tutorial\n4. Sponsor Portal quick-start guide\n5. FAQ with 20 common questions\n6. Support contact process",
acceptance: "**Functional:**\n1. ✅ Migration announcement email sent to all existing DocuSeal users\n2. ✅ TP Portal \"Getting Started\" guide created (5 steps)\n3. ✅ Student Portal onboarding tutorial (3 steps, mobile-friendly)\n4. ✅ Sponsor Portal quick-start guide (bulk signing focus)\n5. ✅ FAQ document with 20 common questions\n6. ✅ Support contact process defined\n7. ✅ Help overlay on first login for TP Portal\n8. ✅ Help button accessible on all major screens\n9. ✅ Error messages link to contextual help\n\n**UI/UX:**\n1. ✅ Help buttons visible in all portals\n2. ✅ Tutorial tooltips on first login\n3. ✅ Mobile-responsive documentation\n4. ✅ Consistent help iconography\n\n**Integration:**\n1. ✅ Email templates integrate with existing Devise mailer\n2. ✅ Help content served via `/help` routes\n3. ✅ Error help displays in all portals\n\n**Security:**\n1. ✅ No sensitive data in documentation\n2. ✅ Token links in emails are single-use\n3. ✅ Help pages don\'t expose internal URLs\n\n**Quality:**\n1. ✅ All documentation reviewed by PO\n2. ✅ No spelling/grammar errors\n3. ✅ Consistent branding and tone\n4. ✅ Links verified and working",
},
{
number: "8.6",
title: "In-App User Documentation & Help System",
user_story: "**As a** User (TP Admin, Student, or Sponsor),\n**I want** contextual help and documentation,\n**So that** I can solve problems without contacting support.",
background: "Deferred to post-MVP per PO validation. This story adds in-app help system after core functionality is validated.\n\n**Note**: This story is deferred pending successful MVP validation.",
acceptance: "Not found",
},
{
number: "8.7",
title: "Knowledge Transfer & Operations Documentation",
user_story: "**As a** Support/Operations Team,\n**I want** comprehensive runbooks and documentation,\n**So that** I can support FloDoc without ad-hoc knowledge transfer.",
background: "Deferred to post-MVP per PO validation. This story creates operations documentation after system is proven.\n\n**Note**: This story is deferred pending successful MVP validation.",
acceptance: "Not found",
},
];
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", () => {
stories.push(...storiesData);
initializeSlides();
});
} else {
stories.push(...storiesData);
initializeSlides();
}
</script>
</body>
</html>

File diff suppressed because it is too large Load Diff

@ -0,0 +1,122 @@
#!/bin/bash
#
# Test script to verify GitHub Projects populator setup
#
set -e
echo "=========================================="
echo "GitHub Projects Populator - Setup Test"
echo "=========================================="
echo ""
# Check GitHub CLI
echo "1. Checking GitHub CLI..."
if command -v gh &> /dev/null; then
echo " ✅ GitHub CLI installed: $(gh --version | head -1)"
else
echo " ❌ GitHub CLI not found"
echo " Install from: https://cli.github.com/"
exit 1
fi
# Check authentication
echo ""
echo "2. Checking authentication..."
if gh auth status &> /dev/null; then
echo " ✅ Authenticated"
gh auth status 2>&1 | grep -E "(Logged in|Username)" | sed 's/^/ /'
else
echo " ❌ Not authenticated"
echo " Run: gh auth login"
exit 1
fi
# Check gh-project extension
echo ""
echo "3. Checking gh-project extension..."
if gh extension list | grep -q "mislav/gh-project"; then
echo " ✅ gh-project extension installed"
else
echo " ⚠️ gh-project extension not installed"
echo " Install with: gh extension install mislav/gh-project"
echo " (Optional - script will still work)"
fi
# Check script files
echo ""
echo "4. Checking script files..."
SCRIPTS=(
"populate_github_project.sh"
"populate_github_project.py"
)
for script in "${SCRIPTS[@]}"; do
if [ -f "$script" ]; then
echo "$script exists"
else
echo "$script not found"
exit 1
fi
done
# Check epic details file
echo ""
echo "5. Checking source file..."
EPIC_FILE="../prd/6-epic-details.md"
if [ -f "$EPIC_FILE" ]; then
STORY_COUNT=$(grep -c "^### Story" "$EPIC_FILE")
echo " ✅ Epic details found"
echo " 📊 Contains $STORY_COUNT stories"
else
echo " ❌ Epic details not found: $EPIC_FILE"
exit 1
fi
# Check documentation files
echo ""
echo "6. Checking documentation..."
DOCS=(
"GITHUB_PROJECT_SETUP.md"
"QUICKSTART_GITHUB_PROJECTS.md"
"GITHUB_PROJECTS_SUMMARY.md"
)
for doc in "${DOCS[@]}"; do
if [ -f "$doc" ]; then
echo "$doc exists"
else
echo "$doc not found"
exit 1
fi
done
# Test dry run (parse stories without creating)
echo ""
echo "7. Testing story parsing (dry run)..."
if python3 populate_github_project.py \
--token "fake_token_for_test" \
--owner "test" \
--repo "test" \
--dry-run 2>&1 | grep -q "Found.*stories"; then
echo " ✅ Story parsing works"
else
echo " ⚠️ Could not test parsing (may need Python dependencies)"
fi
echo ""
echo "=========================================="
echo "✅ Setup Test Complete!"
echo "=========================================="
echo ""
echo "You're ready to run the populator!"
echo ""
echo "Next steps:"
echo " 1. Run: ./populate_github_project.sh <owner> <repo> <project_number>"
echo " 2. Example: ./populate_github_project.sh NeoSkosana floDoc-v3 6"
echo ""
echo "For help:"
echo " - Quick start: cat QUICKSTART_GITHUB_PROJECTS.md"
echo " - Full guide: cat GITHUB_PROJECT_SETUP.md"
echo " - Summary: cat GITHUB_PROJECTS_SUMMARY.md"
echo ""
Loading…
Cancel
Save