Files
StarPunk/docs/projectplan/v1/implementation-plan.md
2025-11-18 19:21:31 -07:00

1253 lines
40 KiB
Markdown

# StarPunk V1 Implementation Plan
## Overview
This document provides a comprehensive, dependency-ordered implementation plan for StarPunk V1, taking the project from its current state (basic infrastructure complete) to a fully functional IndieWeb CMS.
**Current State**: Core infrastructure complete (database schema, config, basic Flask app)
**Target State**: Working V1 with all features implemented, tested, and documented
**Estimated Total Effort**: ~40-60 hours of focused development
## Implementation Strategy
1. **Bottom-up approach**: Build foundation modules before features that depend on them
2. **Feature completeness**: Implement each feature fully (code + tests + docs) before moving to the next
3. **Continuous validation**: Test integration points as we build
4. **Documentation alongside code**: Update docs as implementation progresses
---
## Phase 1: Core Utilities and Models (Foundation)
These utilities are used by all other features. Must be implemented first.
### 1.1 Utility Functions (`starpunk/utils.py`)
**Priority**: CRITICAL - Required by all other features
**Estimated Effort**: 2-3 hours
**Dependencies**: None
- [ ] Implement slug generation function
- Extract first 5 words from content
- Normalize to lowercase with hyphens
- Remove special characters, preserve alphanumeric + hyphens
- Fallback to timestamp-based slug if content too short
- Check uniqueness against database
- Add random suffix if slug exists
- **References**: ADR-004 (File-Based Storage), project-structure.md
- **Acceptance Criteria**: Generates valid, unique, URL-safe slugs
- [ ] Implement content hash calculation
- Use SHA-256 algorithm
- Return hex digest string
- Handle UTF-8 encoding properly
- **Acceptance Criteria**: Consistent hashes for same content
- [ ] Implement file path helpers
- Generate year/month directory structure from timestamp
- Build file paths: `data/notes/YYYY/MM/slug.md`
- Validate paths (prevent directory traversal)
- Ensure paths stay within DATA_PATH
- **References**: ADR-004, architecture/security.md
- **Acceptance Criteria**: Safe path generation and validation
- [ ] Implement atomic file operations
- Write to temp file first (`.tmp` suffix)
- Atomic rename to final destination
- Handle errors with rollback
- Create parent directories if needed
- **References**: ADR-004
- **Acceptance Criteria**: Files written safely without corruption risk
- [ ] Implement date/time utilities
- RFC-822 date formatting (for RSS)
- ISO 8601 formatting (for timestamps)
- Timezone handling (UTC)
- **Acceptance Criteria**: Correct date formatting for all use cases
- [ ] Write comprehensive tests (`tests/test_utils.py`)
- Test slug generation with various inputs
- Test uniqueness enforcement
- Test content hash consistency
- Test path validation (including security tests)
- Test atomic file operations
- Test date formatting
**Completion Criteria**: All utility functions implemented and tested with >90% coverage
---
### 1.2 Data Models (`starpunk/models.py`)
**Priority**: CRITICAL - Used by all feature modules
**Estimated Effort**: 3-4 hours
**Dependencies**: `utils.py`
- [ ] Implement `Note` model class
- Properties: id, slug, file_path, published, created_at, updated_at, content_hash
- Method: `from_row()` - Create Note from database row
- Method: `to_dict()` - Serialize to dictionary
- Property: `content` - Lazy load from file
- Property: `html` - Render markdown to HTML (cached)
- Method: `permalink()` - Generate public URL
- **References**: ADR-004, architecture/overview.md
- **Acceptance Criteria**: Clean interface for note data access
- [ ] Implement `Session` model class
- Properties: id, session_token, me, created_at, expires_at, last_used_at
- Method: `from_row()` - Create Session from database row
- Property: `is_expired` - Check if session expired
- Method: `is_valid()` - Comprehensive validation
- **References**: ADR-005
- **Acceptance Criteria**: Session validation works correctly
- [ ] Implement `Token` model class (Micropub)
- Properties: token, me, client_id, scope, created_at, expires_at
- Method: `from_row()` - Create Token from database row
- Property: `is_expired` - Check if token expired
- Method: `has_scope()` - Check if token has required scope
- **References**: Micropub spec
- **Acceptance Criteria**: Token scope checking works
- [ ] Implement `AuthState` model class
- Properties: state, created_at, expires_at
- Method: `from_row()` - Create AuthState from database row
- Property: `is_expired` - Check if state expired
- **References**: ADR-005
- **Acceptance Criteria**: State token validation works
- [ ] Write model tests (`tests/test_models.py`)
- Test all model creation methods
- Test property access
- Test expiration logic
- Test serialization/deserialization
- Test edge cases (None values, invalid data)
**Completion Criteria**: All models implemented with clean interfaces and full test coverage
---
## Phase 2: Notes Management (Core Feature)
This is the heart of the application. File operations + database sync.
### 2.1 Notes Module (`starpunk/notes.py`)
**Priority**: CRITICAL - Core functionality
**Estimated Effort**: 6-8 hours
**Dependencies**: `utils.py`, `models.py`, `database.py`
- [ ] Implement `create_note()` function
- Accept: content (markdown), published (boolean), created_at (optional)
- Generate unique slug using utils
- Determine file path (year/month from timestamp)
- Create directory structure if needed
- Write markdown file atomically
- Calculate content hash
- Begin database transaction
- Insert note record with metadata
- If DB insert fails: delete file, raise error
- If successful: commit transaction, return Note object
- **References**: ADR-004, architecture/data-flow.md
- **Acceptance Criteria**: Note created with file + database entry in sync
- [ ] Implement `get_note()` function
- Accept: slug (string) or id (int)
- Query database for note metadata
- If not found: return None
- Read file content from disk
- Verify content hash (optional, log if mismatch)
- Return Note object with content loaded
- **References**: ADR-004
- **Acceptance Criteria**: Note retrieved with content from file
- [ ] Implement `list_notes()` function
- Accept: published_only (boolean), limit (int), offset (int)
- Query database with filters and sorting (created_at DESC)
- Return list of Note objects (metadata only, no content)
- Support pagination
- **References**: ADR-004
- **Acceptance Criteria**: Efficient listing with proper filtering
- [ ] Implement `update_note()` function
- Accept: slug or id, new content, published status
- Query database for existing note
- Create backup of original file (optional)
- Write new content to file atomically
- Calculate new content hash
- Update database record (updated_at, content_hash, published)
- If DB update fails: restore backup, raise error
- Return updated Note object
- **References**: ADR-004
- **Acceptance Criteria**: Note updated safely with sync maintained
- [ ] Implement `delete_note()` function
- Accept: slug or id, hard_delete (boolean, default False)
- Query database for note
- If soft delete: update deleted_at timestamp, optionally move file to .trash/
- If hard delete: delete database record, delete file
- **References**: ADR-004
- **Acceptance Criteria**: Note deleted (soft or hard) correctly
- [ ] Implement `search_notes()` function (optional for V1)
- Accept: query string
- Search file content using grep or Python search
- Return matching Note objects
- **Priority**: LOW - Can defer to V2
- **Acceptance Criteria**: Basic text search works
- [ ] Handle edge cases
- Orphaned files (file exists, no DB record)
- Orphaned records (DB record exists, no file)
- File read/write errors
- Permission errors
- Disk full errors
- **References**: architecture/security.md
- [ ] Write comprehensive tests (`tests/test_notes.py`)
- Test create with various content
- Test slug uniqueness enforcement
- Test file/database sync
- Test get by slug and id
- Test list with filters and pagination
- Test update operations
- Test delete (soft and hard)
- Test error handling (DB failure, file failure)
- Test edge cases (empty content, very long content, special characters)
- Integration test: create → read → update → delete cycle
**Completion Criteria**: Full CRUD operations working with file+database sync, comprehensive tests passing
---
## Phase 3: Authentication (IndieLogin)
Implements the IndieLogin OAuth flow for admin access.
### 3.1 Authentication Module (`starpunk/auth.py`)
**Priority**: HIGH - Required for admin interface
**Estimated Effort**: 5-6 hours
**Dependencies**: `models.py`, `database.py`, `httpx` library
- [ ] Implement state token management
- `generate_state()` - Create random CSRF token (32 bytes)
- `store_state()` - Save to database with 5-minute expiry
- `verify_state()` - Check validity and delete (single-use)
- `cleanup_expired_states()` - Remove old tokens
- **References**: ADR-005
- **Acceptance Criteria**: State tokens prevent CSRF attacks
- [ ] Implement session token management
- `generate_session_token()` - Create random token (32 bytes)
- `create_session()` - Store session with user 'me' URL
- `get_session()` - Retrieve session by token
- `validate_session()` - Check if valid and not expired
- `update_session_activity()` - Update last_used_at
- `delete_session()` - Logout
- `cleanup_expired_sessions()` - Remove old sessions
- **References**: ADR-005, architecture/security.md
- **Acceptance Criteria**: Sessions work for 30 days, extend on use
- [ ] Implement IndieLogin OAuth flow
- `initiate_login()` - Build authorization URL, store state, redirect
- Validate 'me' URL format
- Generate state token
- Build indielogin.com authorization URL with params
- Return redirect response
- `handle_callback()` - Exchange code for identity
- Verify state token (CSRF check)
- POST to indielogin.com/auth with code
- Verify HTTP response (200 OK)
- Extract 'me' from JSON response
- Verify 'me' matches ADMIN_ME config
- Create session if authorized
- Set secure HttpOnly cookie
- Redirect to admin dashboard
- **References**: ADR-005, IndieLogin API docs
- **Acceptance Criteria**: Full OAuth flow works with indielogin.com
- [ ] Implement authentication decorator
- `require_auth()` - Decorator for protected routes
- Check session cookie
- Validate session
- Store user info in Flask `g` context
- Redirect to login if not authenticated
- **Acceptance Criteria**: Protects admin routes correctly
- [ ] Implement logout
- `logout()` - Delete session from database
- Clear session cookie
- Redirect to homepage
- **Acceptance Criteria**: Logout works completely
- [ ] Error handling
- Invalid state token
- IndieLogin API errors
- Network timeouts
- Unauthorized users (wrong 'me' URL)
- Expired sessions
- **References**: architecture/security.md
- [ ] Write comprehensive tests (`tests/test_auth.py`)
- Test state token generation and validation
- Test session creation and validation
- Test session expiry
- Mock IndieLogin API responses
- Test full OAuth flow (integration test with mocked API)
- Test CSRF protection (invalid state)
- Test unauthorized user rejection (wrong 'me')
- Test session cookie security (HttpOnly, Secure flags)
- Test logout functionality
- Test decorator on protected routes
**Completion Criteria**: Authentication works end-to-end, all security measures tested
---
## Phase 4: Web Routes and Templates
User-facing interface (public site + admin interface).
### 4.1 Public Routes Blueprint (`starpunk/routes/public.py`)
**Priority**: HIGH - Public interface
**Estimated Effort**: 3-4 hours
**Dependencies**: `notes.py`, `models.py`
Note: Create `starpunk/routes/` directory first
- [ ] Create routes module structure
- Create `starpunk/routes/__init__.py`
- Create `starpunk/routes/public.py`
- Create `starpunk/routes/admin.py`
- Create `starpunk/routes/api.py`
- [ ] Implement homepage route (`/`)
- GET handler
- List published notes (limit 20, newest first)
- Render `templates/index.html`
- Pass notes to template
- **Acceptance Criteria**: Homepage displays recent published notes
- [ ] Implement note permalink route (`/note/<slug>`)
- GET handler
- Retrieve note by slug
- Check if published (404 if not published)
- Render `templates/note.html`
- Pass note with rendered HTML content
- **Acceptance Criteria**: Individual notes display correctly
- [ ] Register blueprint in `starpunk/__init__.py`
- Import public blueprint
- Register with app
- **Acceptance Criteria**: Routes are accessible
- [ ] Write route tests
- Test homepage returns 200
- Test homepage lists published notes only
- Test note permalink returns 200 for published note
- Test note permalink returns 404 for unpublished note
- Test note permalink returns 404 for non-existent note
**Completion Criteria**: Public routes work, return correct content
---
### 4.2 Admin Routes Blueprint (`starpunk/routes/admin.py`)
**Priority**: HIGH - Admin interface
**Estimated Effort**: 4-5 hours
**Dependencies**: `auth.py`, `notes.py`
- [ ] Implement login routes
- GET `/admin/login` - Display login form
- POST `/admin/login` - Initiate IndieLogin flow
- GET `/auth/callback` - Handle IndieLogin callback
- POST `/admin/logout` - Logout and clear session
- **References**: ADR-005
- **Acceptance Criteria**: Authentication flow works
- [ ] Implement admin dashboard (`/admin`)
- GET handler (protected with `@require_auth`)
- List all notes (published and drafts)
- Show note count, recent activity
- Render `templates/admin/dashboard.html`
- **Acceptance Criteria**: Dashboard shows all notes
- [ ] Implement create note routes (`/admin/new`)
- GET handler - Display note creation form
- POST handler - Create note from form data
- Extract content and published status
- Call `create_note()`
- Redirect to dashboard on success
- Show errors on failure
- **Acceptance Criteria**: Can create notes via web form
- [ ] Implement edit note routes (`/admin/edit/<slug>`)
- GET handler - Display edit form with existing content
- POST handler - Update note
- Call `update_note()`
- Redirect to dashboard on success
- Show errors on failure
- **Acceptance Criteria**: Can edit notes via web form
- [ ] Implement delete note route (`/admin/delete/<slug>`)
- POST handler - Delete note
- Confirm deletion (soft delete by default)
- Call `delete_note()`
- Redirect to dashboard
- **Acceptance Criteria**: Can delete notes
- [ ] Register blueprint in `starpunk/__init__.py`
- Import admin blueprint
- Register with app
- **Acceptance Criteria**: Admin routes accessible
- [ ] Write route tests
- Test login flow (with mocked IndieLogin)
- Test authentication required for admin routes
- Test dashboard displays notes
- Test create note form submission
- Test edit note form submission
- Test delete note
- Test logout
**Completion Criteria**: Admin interface fully functional, authentication working
---
### 4.3 HTML Templates
**Priority**: HIGH - Required for web interface
**Estimated Effort**: 6-8 hours
**Dependencies**: None (can be done in parallel with routes)
#### Base Templates
- [ ] Implement `templates/base.html`
- HTML5 semantic structure
- Meta tags (charset, viewport)
- Link to stylesheet (`/static/css/style.css`)
- Navigation (home, admin)
- Content block (`{% block content %}`)
- Footer with attribution
- **Microformats**: h-card for site author
- **References**: ADR-003, architecture/overview.md
- **Acceptance Criteria**: Clean, semantic HTML base template
- [ ] Implement `templates/admin/base.html`
- Extends base or separate admin layout
- Admin navigation (dashboard, new note, logout)
- Admin-specific styling
- Flash message display
- **Acceptance Criteria**: Consistent admin layout
#### Public Templates
- [ ] Implement `templates/index.html`
- Extends `base.html`
- Display list of notes
- Each note: title (first line), excerpt, timestamp, permalink
- Pagination controls (if >20 notes)
- **Microformats**: h-feed with h-entry for each note
- **References**: Microformats2 spec
- **Acceptance Criteria**: Homepage displays notes with proper markup
- [ ] Implement `templates/note.html`
- Extends `base.html`
- Display full note content (rendered HTML)
- Timestamp, permalink
- **Microformats**: h-entry with e-content, dt-published
- **References**: Microformats2 h-entry spec
- **Acceptance Criteria**: Note displays with proper semantic markup
#### Admin Templates
- [ ] Implement `templates/admin/login.html`
- Simple form asking for website URL
- Input for 'me' URL
- Submit button
- Explanation of IndieLogin
- **Acceptance Criteria**: Clean login form
- [ ] Implement `templates/admin/dashboard.html`
- Extends `admin/base.html`
- Table of all notes (published + drafts)
- Columns: title, status, created, updated, actions (edit, delete)
- "New Note" button
- Summary stats (total notes, published count)
- **Acceptance Criteria**: Dashboard shows all notes with actions
- [ ] Implement `templates/admin/new.html`
- Extends `admin/base.html`
- Form with markdown textarea
- Published checkbox
- Submit button
- Optional: markdown preview (if JS enabled)
- **Acceptance Criteria**: Form for creating notes
- [ ] Implement `templates/admin/edit.html`
- Extends `admin/base.html`
- Form pre-filled with existing content
- Markdown textarea
- Published checkbox
- Save and Cancel buttons
- Optional: markdown preview
- **Acceptance Criteria**: Form for editing notes
**Completion Criteria**: All templates implemented with proper HTML5 and Microformats2 markup
---
### 4.4 CSS Styling (`static/css/style.css`)
**Priority**: MEDIUM - Functional without, better with
**Estimated Effort**: 4-5 hours
**Dependencies**: None
- [ ] Implement CSS custom properties (variables)
- Colors (background, text, accent, borders)
- Typography (font families, sizes, line heights)
- Spacing scale
- **References**: ADR-003
- **Acceptance Criteria**: Consistent design tokens
- [ ] Implement base styles
- CSS reset/normalize
- Typography (readable font sizes, line heights)
- Links and buttons
- Forms and inputs
- **Acceptance Criteria**: Clean, readable defaults
- [ ] Implement layout
- Centered content container (max-width: 800px)
- Header and footer
- Navigation
- Grid for note lists
- **Acceptance Criteria**: Responsive layout works
- [ ] Implement component styles
- Note cards
- Note content (markdown rendering)
- Forms (admin interface)
- Tables (dashboard)
- Buttons and inputs
- **Acceptance Criteria**: Components look consistent
- [ ] Implement responsive design
- Mobile-first approach
- Breakpoints for tablet and desktop
- Touch-friendly targets
- Readable on all screen sizes
- **References**: ADR-003 (Progressive Enhancement)
- **Acceptance Criteria**: Works on mobile, tablet, desktop
- [ ] Keep total CSS under 300 lines
- Minimal styling philosophy
- No fancy animations or effects
- Focus on readability and usability
- **References**: ADR-003
- **Acceptance Criteria**: CSS is simple and maintainable
**Completion Criteria**: Site is usable and looks clean on all devices
---
### 4.5 Optional JavaScript Enhancement (`static/js/preview.js`)
**Priority**: LOW - Optional enhancement only
**Estimated Effort**: 2-3 hours
**Dependencies**: None
This is OPTIONAL for V1. Can be deferred.
- [ ] Implement markdown preview (optional)
- Load marked.js from CDN
- Listen to textarea input
- Render markdown in real-time
- Display preview beside textarea
- Degrades gracefully if JS disabled
- **References**: ADR-003 (Progressive Enhancement)
- **Acceptance Criteria**: Preview works, form works without it
**Completion Criteria**: Preview enhances editing experience but isn't required
---
## Phase 5: RSS Feed Generation
Syndication for published notes.
### 5.1 Feed Module (`starpunk/feed.py`)
**Priority**: HIGH - Core feature
**Estimated Effort**: 3-4 hours
**Dependencies**: `notes.py`, `feedgen` library
- [ ] Implement `generate_rss_feed()` function
- Create FeedGenerator instance
- Set feed metadata (title, link, description, language)
- Set feed author from config
- Query published notes (limit 50, newest first)
- For each note:
- Add feed entry
- Set entry title (first line or slug)
- Set entry link (permalink)
- Set entry description/content (rendered HTML, CDATA-wrapped)
- Set entry published date (RFC-822 format)
- Set entry GUID (permalink)
- Generate RSS 2.0 XML string
- Return XML
- **References**: ADR-002 (feedgen), RSS 2.0 spec, architecture/overview.md
- **Acceptance Criteria**: Valid RSS 2.0 feed generated
- [ ] Implement feed caching (optional)
- Cache generated feed for 5 minutes
- Invalidate on note create/update/delete
- **Priority**: MEDIUM - Can defer to V2
- **Acceptance Criteria**: Feed generation is performant
- [ ] Write tests (`tests/test_feed.py`)
- Test feed generation with notes
- Test feed metadata is correct
- Test entry format
- Test date formatting (RFC-822)
- Test HTML content in CDATA
- Validate XML structure
- Test empty feed (no published notes)
- Test W3C Feed Validator compliance (manual test)
**Completion Criteria**: RSS feed generates valid XML, passes W3C validator
---
### 5.2 Feed Route (`/feed.xml`)
**Priority**: HIGH - Part of RSS feature
**Estimated Effort**: 1 hour
**Dependencies**: `feed.py`
- [ ] Add feed route to public blueprint
- GET `/feed.xml`
- Call `generate_rss_feed()`
- Return XML with correct Content-Type (`application/rss+xml`)
- Set Cache-Control header (5 minutes)
- **Acceptance Criteria**: Feed accessible at /feed.xml
- [ ] Add feed auto-discovery to templates
- Add `<link rel="alternate" type="application/rss+xml">` to base.html
- **Acceptance Criteria**: RSS readers auto-discover feed
- [ ] Write route tests
- Test feed returns 200
- Test Content-Type is correct
- Test feed contains published notes
- Test feed is valid XML
**Completion Criteria**: Feed is accessible and discoverable
---
## Phase 6: Micropub API
Micropub endpoint for publishing from external clients.
### 6.1 Token Management (for Micropub)
**Priority**: HIGH - Required for Micropub
**Estimated Effort**: 2-3 hours
**Dependencies**: `models.py`, `database.py`
Note: Micropub clients will obtain tokens via external IndieAuth flow. StarPunk just validates tokens.
- [ ] Implement token validation in `starpunk/auth.py`
- `validate_micropub_token()` - Check if token exists and valid
- Query tokens table
- Check expiration
- Return Token object with 'me' and scope
- **References**: IndieAuth spec, Micropub spec
- **Acceptance Criteria**: Token validation works
- [ ] Implement token creation (for testing)
- `create_token()` - Manually create token (for development/testing)
- Store token with 'me', client_id, scope
- **Priority**: For testing only, real tokens come from IndieAuth server
- **Acceptance Criteria**: Can create test tokens
- [ ] Implement Micropub authentication decorator
- `require_micropub_auth()` - Decorator for Micropub endpoint
- Extract Bearer token from Authorization header
- Validate token
- Check scope (must have 'create' or 'post')
- Store token info in Flask `g`
- Return 401 if invalid
- **Acceptance Criteria**: Protects Micropub endpoint
**Completion Criteria**: Token validation works for Micropub
---
### 6.2 Micropub Endpoint (`starpunk/micropub.py`)
**Priority**: HIGH - Core IndieWeb feature
**Estimated Effort**: 6-8 hours
**Dependencies**: `auth.py`, `notes.py`, Micropub spec knowledge
- [ ] Implement Micropub POST handler (create)
- Handle `application/json` content type
- Handle `application/x-www-form-urlencoded` content type
- Parse Micropub payload
- Validate h-entry structure
- Extract content from properties.content[0]
- Extract name from properties.name[0] (if present)
- Call `create_note()` with content
- Return 201 Created with Location header (note URL)
- Handle errors (400, 500)
- **References**: Micropub spec, ADR-005
- **Acceptance Criteria**: Can create notes via Micropub
- [ ] Implement Micropub GET handler (query)
- Handle `q=config` query - Return supported config
- Handle `q=source` query - Return note source by URL
- Handle `q=syndicate-to` query - Return empty (no syndication targets in V1)
- Return JSON responses
- **References**: Micropub spec
- **Acceptance Criteria**: Query endpoints return correct data
- [ ] Implement Micropub media endpoint (optional for V1)
- Handle file uploads
- Store in `data/media/`
- Return media URL
- **Priority**: LOW - Defer to V2
- **Acceptance Criteria**: Media uploads work (if implemented)
- [ ] Implement error responses
- 400 Bad Request - Invalid payload
- 401 Unauthorized - Missing/invalid token
- 403 Forbidden - Insufficient scope
- 500 Server Error - Internal errors
- Return JSON error responses with Micropub error codes
- **References**: Micropub spec error handling
- **Acceptance Criteria**: Errors return proper Micropub responses
- [ ] Write comprehensive tests (`tests/test_micropub.py`)
- Test POST with JSON payload
- Test POST with form-encoded payload
- Test authentication (valid token, invalid token, missing token)
- Test scope checking
- Test content extraction from h-entry
- Test error responses
- Test query endpoints (config, source)
- Integration test: Full Micropub create flow
**Completion Criteria**: Micropub endpoint fully implements spec, passes micropub.rocks tests
---
### 6.3 Micropub Route
**Priority**: HIGH - Part of Micropub feature
**Estimated Effort**: 1 hour
**Dependencies**: `micropub.py`
- [ ] Add Micropub route to API blueprint
- POST `/api/micropub` - Create entry
- GET `/api/micropub` - Query endpoint
- Apply `@require_micropub_auth` decorator
- **Acceptance Criteria**: Micropub endpoint accessible
- [ ] Add Micropub endpoint discovery
- Add `<link rel="micropub">` to base template
- Point to `/api/micropub`
- **References**: Micropub spec
- **Acceptance Criteria**: Clients can discover endpoint
- [ ] Write route tests
- Test endpoint returns 401 without auth
- Test endpoint accepts authenticated requests
- Test both POST and GET methods
**Completion Criteria**: Micropub endpoint discoverable and functional
---
## Phase 7: API Routes (CRUD API)
Optional REST API for notes (in addition to Micropub).
### 7.1 Notes API Blueprint (`starpunk/routes/api.py`)
**Priority**: MEDIUM - Nice to have, not critical
**Estimated Effort**: 3-4 hours
**Dependencies**: `auth.py`, `notes.py`
This is OPTIONAL for V1. The admin interface uses forms, Micropub handles external publishing. This JSON API is a bonus.
- [ ] Implement notes CRUD API
- GET `/api/notes` - List published notes (JSON)
- POST `/api/notes` - Create note (requires auth)
- GET `/api/notes/<slug>` - Get single note (JSON)
- PUT `/api/notes/<slug>` - Update note (requires auth)
- DELETE `/api/notes/<slug>` - Delete note (requires auth)
- Use session auth for write operations
- Return JSON responses
- **Acceptance Criteria**: JSON API works for notes
- [ ] Register API blueprint
- Import in `starpunk/__init__.py`
- Register with app
- **Acceptance Criteria**: API routes accessible
- [ ] Write API tests
- Test list notes
- Test get single note
- Test create requires auth
- Test update requires auth
- Test delete requires auth
- Test JSON serialization
**Completion Criteria**: REST API provides JSON access to notes (if implemented)
---
## Phase 8: Testing and Quality Assurance
Comprehensive testing to ensure reliability.
### 8.1 Integration Tests
**Priority**: HIGH - Ensure components work together
**Estimated Effort**: 4-5 hours
**Dependencies**: All features implemented
- [ ] Write end-to-end tests (`tests/test_integration.py`)
- Test complete user journey: login → create note → view note → edit → delete
- Test complete Micropub flow: authenticate → publish → view on site
- Test RSS feed updates when notes created
- Test file/database sync integrity
- Test error recovery (DB failure, file failure)
- **Acceptance Criteria**: All major user flows tested
- [ ] Test data consistency
- Create note, verify file exists
- Create note, verify DB record exists
- Update note, verify file content changes
- Update note, verify DB timestamp changes
- Delete note, verify file and DB record handled correctly
- **Acceptance Criteria**: File and database stay in sync
- [ ] Test edge cases
- Very long content (>10k characters)
- Special characters in content (unicode, emoji)
- Concurrent requests (if applicable)
- Low disk space scenarios
- **Acceptance Criteria**: Edge cases handled gracefully
**Completion Criteria**: Integration tests pass, coverage >80%
---
### 8.2 Standards Validation
**Priority**: HIGH - Ensure compliance
**Estimated Effort**: 2-3 hours
**Dependencies**: All features implemented
- [ ] Validate HTML output
- Run W3C HTML Validator on templates
- Fix any validation errors
- **Tool**: https://validator.w3.org/
- **Acceptance Criteria**: Valid HTML5
- [ ] Validate RSS feed
- Run W3C Feed Validator on /feed.xml
- Fix any validation errors
- **Tool**: https://validator.w3.org/feed/
- **Acceptance Criteria**: Valid RSS 2.0
- [ ] Validate Microformats
- Use IndieWebify.me to check h-entry markup
- Verify h-card, h-feed, h-entry parsing
- **Tool**: https://indiewebify.me/
- **Acceptance Criteria**: Microformats2 properly parsed
- [ ] Validate Micropub
- Use micropub.rocks to test endpoint
- Pass all required tests
- **Tool**: https://micropub.rocks/
- **Acceptance Criteria**: Micropub spec compliant
**Completion Criteria**: All standards validators pass
---
### 8.3 Security Testing
**Priority**: HIGH - Critical for production
**Estimated Effort**: 3-4 hours
**Dependencies**: All features implemented
- [ ] Test authentication security
- CSRF protection (state tokens)
- Session hijacking prevention
- Cookie security (HttpOnly, Secure, SameSite)
- Session expiry
- **References**: architecture/security.md
- **Acceptance Criteria**: Authentication is secure
- [ ] Test input validation
- SQL injection prevention (parameterized queries)
- XSS prevention (markdown sanitization)
- Path traversal prevention
- File upload security (if media implemented)
- **References**: architecture/security.md
- **Acceptance Criteria**: All inputs validated
- [ ] Test authorization
- Only ADMIN_ME can login
- Unauthorized users rejected
- Protected routes require auth
- Token scope enforcement
- **Acceptance Criteria**: Authorization works correctly
- [ ] Security headers
- Content-Security-Policy
- X-Frame-Options
- X-Content-Type-Options
- Referrer-Policy
- **References**: architecture/security.md
- **Acceptance Criteria**: Security headers set
**Completion Criteria**: No security vulnerabilities found
---
### 8.4 Manual Testing
**Priority**: HIGH - Real-world validation
**Estimated Effort**: 3-4 hours
**Dependencies**: All features implemented
- [ ] Test with real IndieLogin
- Authenticate with actual indielogin.com
- Verify session persistence
- Test logout
- **Acceptance Criteria**: Real IndieLogin works
- [ ] Test with real Micropub client
- Use Quill or Indigenous app
- Publish a note
- Verify it appears on site
- **Tools**: Quill (https://quill.p3k.io/)
- **Acceptance Criteria**: Real clients work
- [ ] Test in multiple browsers
- Chrome/Chromium
- Firefox
- Safari (if available)
- Mobile browsers
- **Acceptance Criteria**: Works in all major browsers
- [ ] Test responsive design
- Mobile phone (320px width)
- Tablet (768px width)
- Desktop (1200px width)
- **Acceptance Criteria**: Responsive on all sizes
- [ ] Test accessibility
- Keyboard navigation
- Screen reader (if available)
- Color contrast
- **Acceptance Criteria**: Basic accessibility works
**Completion Criteria**: Manual testing reveals no critical issues
---
## Phase 9: Documentation and Deployment
Final documentation and deployment preparation.
### 9.1 User Documentation
**Priority**: HIGH - Required for V1 release
**Estimated Effort**: 3-4 hours
**Dependencies**: All features complete
- [ ] Update README.md
- Verify all sections accurate
- Update installation instructions
- Add screenshots (optional)
- Update configuration examples
- **Acceptance Criteria**: README is complete and accurate
- [ ] Create deployment guide (`docs/architecture/deployment.md`)
- Production setup instructions
- Systemd service configuration
- Nginx/Caddy reverse proxy setup
- SSL/TLS configuration
- Backup procedures
- **References**: architecture/overview.md
- **Acceptance Criteria**: Deployment guide is comprehensive
- [ ] Create user guide (`docs/user-guide.md`)
- How to login
- How to create notes
- How to use Micropub clients
- How to backup data
- Troubleshooting common issues
- **Acceptance Criteria**: Users can self-serve
- [ ] Create API documentation (`docs/api.md`)
- REST API endpoints
- Micropub endpoint
- Authentication methods
- Example requests/responses
- **Acceptance Criteria**: API is documented
**Completion Criteria**: Documentation is complete and helpful
---
### 9.2 Developer Documentation
**Priority**: MEDIUM - Helpful for maintenance
**Estimated Effort**: 2-3 hours
**Dependencies**: All features complete
- [ ] Create contributing guide (`CONTRIBUTING.md`)
- Development setup
- Running tests
- Code style
- Pull request process
- **Acceptance Criteria**: Contributors can get started
- [ ] Create architecture diagram
- Visual representation of system
- Component interactions
- Data flow
- Save to `docs/architecture/diagrams/`
- **Acceptance Criteria**: Architecture is visualized
- [ ] Update ADRs if needed
- Document any architectural changes made during implementation
- Add new ADRs for new decisions
- **Acceptance Criteria**: All decisions documented
**Completion Criteria**: Developer documentation is complete
---
### 9.3 Deployment Testing
**Priority**: HIGH - Verify production readiness
**Estimated Effort**: 2-3 hours
**Dependencies**: Deployment guide complete
- [ ] Test production deployment
- Deploy to test server
- Use gunicorn (not Flask dev server)
- Configure reverse proxy
- Enable HTTPS
- Test performance under load
- **Acceptance Criteria**: Runs in production environment
- [ ] Test backup and restore
- Create backup of data/
- Restore to new instance
- Verify all notes accessible
- **Acceptance Criteria**: Backup/restore works
- [ ] Performance testing
- Test response times (< 300ms target)
- Test with 100+ notes
- Test RSS generation time
- Check memory usage
- **References**: architecture/overview.md (performance targets)
- **Acceptance Criteria**: Meets performance targets
**Completion Criteria**: Production deployment verified
---
## Phase 10: Release Preparation
Final steps before V1 release.
### 10.1 Final Quality Checks
**Priority**: CRITICAL - No release without this
**Estimated Effort**: 2-3 hours
**Dependencies**: Everything complete
- [ ] Run full test suite
- All unit tests pass
- All integration tests pass
- Test coverage >80%
- **Acceptance Criteria**: All tests green
- [ ] Code quality checks
- Run black (code formatting)
- Run flake8 (linting)
- Run mypy (type checking)
- Fix any issues
- **Acceptance Criteria**: Code passes all quality checks
- [ ] Final security review
- Review security checklist
- Verify all secrets in .env (not code)
- Verify data/ is gitignored
- Check for any hardcoded credentials
- **Acceptance Criteria**: No security issues
- [ ] Final documentation review
- All docs accurate
- All links working
- All code examples correct
- **Acceptance Criteria**: Documentation complete
**Completion Criteria**: Ready for release
---
### 10.2 Release
**Priority**: CRITICAL - V1 milestone
**Estimated Effort**: 1-2 hours
**Dependencies**: All quality checks pass
- [ ] Version tagging
- Update version in `starpunk/__init__.py` to `1.0.0`
- Create git tag `v1.0.0`
- Write release notes
- **Acceptance Criteria**: Version tagged
- [ ] Release announcement
- Post to IndieWeb wiki
- Share on personal site
- Optional: Announce on social media
- **Acceptance Criteria**: V1 announced
- [ ] Archive project state
- Create release branch `release/v1.0.0`
- Tag in git
- **Acceptance Criteria**: Release archived
**Completion Criteria**: StarPunk V1 released!
---
## Summary Checklist
### Core Features (Must Have)
- [ ] Notes CRUD operations (file + database sync)
- [ ] IndieLogin authentication
- [ ] Admin web interface
- [ ] Public web interface
- [ ] RSS feed generation
- [ ] Micropub endpoint
- [ ] All tests passing
- [ ] Standards compliance (HTML, RSS, Microformats, Micropub)
- [ ] Documentation complete
### Optional Features (Nice to Have)
- [ ] Markdown preview (JavaScript)
- [ ] Notes search
- [ ] Media uploads (Micropub)
- [ ] JSON REST API
- [ ] Feed caching
### Quality Gates
- [ ] Test coverage >80%
- [ ] All validators pass (HTML, RSS, Microformats, Micropub)
- [ ] Security tests pass
- [ ] Manual testing complete
- [ ] Performance targets met (<300ms responses)
- [ ] Production deployment tested
---
## Estimated Timeline
**Total Effort**: 40-60 hours of focused development work
**Breakdown by Phase**:
- Phase 1 (Utilities & Models): 5-7 hours
- Phase 2 (Notes Management): 6-8 hours
- Phase 3 (Authentication): 5-6 hours
- Phase 4 (Web Interface): 13-17 hours
- Phase 5 (RSS Feed): 4-5 hours
- Phase 6 (Micropub): 9-12 hours
- Phase 7 (REST API): 3-4 hours (optional)
- Phase 8 (Testing): 9-12 hours
- Phase 9 (Documentation): 5-7 hours
- Phase 10 (Release): 3-5 hours
**Recommended Schedule**:
- Week 1: Phases 1-3 (foundation and auth)
- Week 2: Phase 4 (web interface)
- Week 3: Phases 5-6 (RSS and Micropub)
- Week 4: Phases 8-10 (testing, docs, release)
---
## Development Notes
### Working Incrementally
1. Complete each phase before moving to next
2. Run tests after each feature
3. Keep commits small and focused
4. Document as you go (don't defer to end)
### When Stuck
1. Review relevant ADRs and architecture docs
2. Check IndieWeb specs (Micropub, Microformats)
3. Look at reference implementations
4. Ask for architectural guidance
### Testing Strategy
1. Write tests alongside features (not after)
2. Test happy path AND error cases
3. Integration tests for cross-component features
4. Manual testing for user experience
### Quality Over Speed
- Don't skip tests
- Don't skip documentation
- Don't compromise security
- Simple implementations are better than clever ones
---
## References
### Project Documentation
- [Architecture Overview](/home/phil/Projects/starpunk/docs/architecture/overview.md)
- [Technology Stack](/home/phil/Projects/starpunk/docs/architecture/technology-stack.md)
- [ADR-001: Python Web Framework](/home/phil/Projects/starpunk/docs/decisions/ADR-001-python-web-framework.md)
- [ADR-002: Flask Extensions](/home/phil/Projects/starpunk/docs/decisions/ADR-002-flask-extensions.md)
- [ADR-003: Frontend Technology](/home/phil/Projects/starpunk/docs/decisions/ADR-003-frontend-technology.md)
- [ADR-004: File-Based Storage](/home/phil/Projects/starpunk/docs/decisions/ADR-004-file-based-note-storage.md)
- [ADR-005: IndieLogin Authentication](/home/phil/Projects/starpunk/docs/decisions/ADR-005-indielogin-authentication.md)
- [ADR-006: Python Virtual Environment](/home/phil/Projects/starpunk/docs/decisions/ADR-006-python-virtual-environment-uv.md)
- [Project Structure](/home/phil/Projects/starpunk/docs/design/project-structure.md)
- [Python Coding Standards](/home/phil/Projects/starpunk/docs/standards/python-coding-standards.md)
### External Standards
- [Micropub Specification](https://micropub.spec.indieweb.org/)
- [IndieAuth Specification](https://indieauth.spec.indieweb.org/)
- [Microformats2](http://microformats.org/wiki/microformats2)
- [RSS 2.0 Specification](https://www.rssboard.org/rss-specification)
- [IndieLogin API](https://indielogin.com/api)
### Testing Tools
- [W3C HTML Validator](https://validator.w3.org/)
- [W3C Feed Validator](https://validator.w3.org/feed/)
- [IndieWebify.me](https://indiewebify.me/)
- [Micropub.rocks](https://micropub.rocks/)
---
**This implementation plan is a living document. Update as implementation progresses and new insights emerge.**