# Contributing to TMI Thank you for your interest in contributing to TMI (Threat Modeling Improved)! This guide will help you understand the contribution process, code standards, and best practices. ## Table of Contents - [Getting Started](#getting-started) - [Development Workflow](#development-workflow) - [Code Standards](#code-standards) - [Testing Requirements](#testing-requirements) - [Pull Request Process](#pull-request-process) - [Code Review Guidelines](#code-review-guidelines) - [Community Guidelines](#community-guidelines) - [AI-Assisted Development](#ai-assisted-development) ## Getting Started ### Before You Begin 1. **Read the documentation** - [[Getting-Started-with-Development]] - [[Architecture-and-Design]] - [[Testing]] 2. **Set up your development environment** ```bash # Fork and clone repository git clone https://github.com/YOUR_USERNAME/tmi.git cd tmi # Add upstream remote git remote add upstream https://github.com/ericfitz/tmi.git # Start development environment make start-dev ``` For the web app: ```bash git clone https://github.com/YOUR_USERNAME/tmi-ux.git cd tmi-ux git remote add upstream https://github.com/ericfitz/tmi-ux.git pnpm install pnpm run dev ``` 3. **Find something to work on** - Check [Issues](https://github.com/ericfitz/tmi/issues) - Look for `good-first-issue` or `help-wanted` labels - Review the [Roadmap](https://github.com/ericfitz/tmi/projects) ### Types of Contributions We welcome various types of contributions: - **Bug Fixes** - Fix reported bugs or issues you find - **New Features** - Add new functionality - **Documentation** - Improve or add documentation - **Tests** - Add or improve test coverage - **Performance** - Optimize existing code - **Refactoring** - Improve code quality - **Examples** - Add usage examples or tutorials ## Development Workflow ### 1. Create a Feature Branch ```bash # Update your fork git fetch upstream git checkout main git merge upstream/main # Create feature branch git checkout -b feature/your-feature-name # Or for bug fixes git checkout -b fix/bug-description ``` ### 2. Make Your Changes Follow these guidelines: #### For Server Changes (Go) ```bash # Make your changes vim api/your_file.go # Run linter make lint # Run unit tests make test-unit # Run integration tests make test-integration # Build server make build-server ``` #### For Web App Changes (Angular 21 / Vitest / Playwright) ```bash cd tmi-ux # Make your changes vim src/app/your-component.ts # Run linter (ESLint with auto-fix) pnpm run lint # Run all linters (ESLint + Stylelint for SCSS) pnpm run lint:all # Run unit tests (Vitest) pnpm run test # Run unit tests in watch mode pnpm run test:watch # Run E2E tests (Playwright) pnpm run test:e2e ``` ### 3. Commit Your Changes Follow conventional commit format: ```bash git add . git commit -m "type(scope): description" ``` **Commit Types**: - `feat`: New feature - `fix`: Bug fix - `docs`: Documentation only - `style`: Code style changes (formatting, etc.) - `refactor`: Code refactoring - `test`: Adding or updating tests - `chore`: Build process or auxiliary tool changes **Examples**: ```bash git commit -m "feat(api): add bulk threat creation endpoint" git commit -m "fix(auth): correct OAuth callback URL handling" git commit -m "docs(readme): update installation instructions" git commit -m "test(integration): add authorization tests" ``` ### Automatic Semantic Versioning TMI uses automatic semantic versioning based on conventional commit types. Commits to the `main` branch trigger a post-commit hook that updates the version automatically. **Version Format**: `MAJOR.MINOR.PATCH` (optionally with a prerelease suffix, e.g. `1.4.0-rc.0`) - **MAJOR**: Incremented for breaking changes - **MINOR**: Incremented on `feat:` commits (server only; in tmi-ux, minor bumps occur only when a release branch merges into `main`) - **PATCH**: Incremented on all other commits (`fix:`, `refactor:`, `docs:`, etc.) **How It Works**: The post-commit hook runs only on the `main` branch. When you commit to `main`, it automatically: 1. Checks whether production-relevant files were modified (Go source in `api/`, `auth/`, `cmd/server/`, `internal/`, or files in `static/`) 2. Reads the commit message and parses the conventional commit type 3. Updates version: `feat:` increments MINOR (resets PATCH), others increment PATCH 4. Updates `.version` file and `api/version.go` 5. Amends the commit with version changes On feature branches (e.g. `dev/*`, `feature/*`, `fix/*`), the hook is a no-op. **Example Progression** (server, on `main` branch): ```bash # Starting at 1.4.0 git commit -m "fix(api): correct JWT validation" # → 1.4.1 (patch++) git commit -m "refactor(auth): simplify login flow" # → 1.4.2 (patch++) git commit -m "feat(api): add user deletion endpoint" # → 1.5.0 (minor++, patch=0) git commit -m "docs: update API documentation" # → 1.5.1 (patch++) git commit -m "feat(websocket): add heartbeat" # → 1.6.0 (minor++, patch=0) ``` **Version Storage**: - `.version` - JSON file tracking current version state including major, minor, patch, and optional prerelease fields (tracked in git) - `api/version.go` - Go variables set at build time via `-ldflags` - `package.json` (tmi-ux) - The `version` field is updated by the tmi-ux post-commit hook **Checking Version**: ```bash # View version file cat .version # Query running server curl http://localhost:8080/ | jq '.service.build' # Output: "1.4.0-abc1234" ``` **Troubleshooting**: - Hook not running? Ensure executable: `chmod +x .git/hooks/post-commit` - Version not updating? Verify `jq` is installed: `which jq` - Files out of sync? Make any commit to trigger sync: `git commit --allow-empty -m "chore: sync version files"` ### 4. Push Changes ```bash # Push to your fork git push origin feature/your-feature-name ``` ### 5. Create Pull Request 1. Go to https://github.com/ericfitz/tmi 2. Click "New Pull Request" 3. Select your fork and branch 4. Fill out the PR template ## Code Standards ### Go Code Standards #### Formatting ```bash # Format code gofmt -w . # Run linter golangci-lint run ./... ``` #### Style Guidelines **Naming Conventions**: ```go // Good type ThreatModel struct { } func GetThreatModel(id string) (*ThreatModel, error) { } var threatModelStore = NewStore[ThreatModel]() // Bad type threat_model struct { } func get_threat_model(ID string) (*ThreatModel, error) { } var ThreatModelStore = NewStore[ThreatModel]() // unexported globals ``` **Error Handling**: ```go // Good - comprehensive error handling func CreateThreatModel(data ThreatModel) error { if err := validate(data); err != nil { return fmt.Errorf("validation failed: %w", err) } if err := db.Save(&data); err != nil { return fmt.Errorf("failed to save threat model: %w", err) } return nil } // Bad - swallowing errors func CreateThreatModel(data ThreatModel) error { validate(data) db.Save(&data) return nil } ``` **Logging**: ```go // Use structured logging via slogging logger := slogging.Get() logger.Info("Created threat model", slog.String("threat_model_id", tmID), slog.String("user_id", userID), ) // Not this logger.Info("Created threat model " + tmID + " for user " + userID) ``` ### TypeScript/Angular Standards #### Formatting ```bash # Format code pnpm run format # Check formatting pnpm run format:check # Lint pnpm run lint:all ``` #### Style Guidelines **Naming Conventions**: ```typescript // Classes - PascalCase export class ThreatModelService { } // Interfaces - PascalCase with 'I' prefix (optional) export interface ThreatModel { } export interface IThreatModel { } // also acceptable // Functions/Methods - camelCase getThreatModels(): Observable { } // Constants - UPPER_SNAKE_CASE const MAX_THREAT_COUNT = 100; // Properties - camelCase private threatModels: ThreatModel[]; ``` **RxJS Best Practices**: ```typescript // Good - proper subscription handling export class ThreatModelComponent implements OnInit, OnDestroy { private destroy$ = new Subject(); ngOnInit() { this.apiService.getThreatModels() .pipe(takeUntil(this.destroy$)) .subscribe(tms => this.threatModels = tms); } ngOnDestroy() { this.destroy$.next(); this.destroy$.complete(); } } // Bad - memory leaks export class ThreatModelComponent implements OnInit { ngOnInit() { this.apiService.getThreatModels() .subscribe(tms => this.threatModels = tms); // Never unsubscribed! } } ``` **Component Structure** (Angular 21 standalone components): ```typescript @Component({ selector: 'app-threat-model', templateUrl: './threat-model.component.html', styleUrl: './threat-model.component.scss', standalone: true, imports: [CommonModule, TranslocoModule] }) export class ThreatModelComponent implements OnInit { // 1. Public properties threatModels: ThreatModel[]; // 2. Private properties private destroy$ = new Subject(); // 3. Constructor (or use inject() for signal-based DI) constructor( private apiService: ApiService, private logger: LoggerService ) { } // 4. Lifecycle hooks ngOnInit(): void { this.loadThreatModels(); } ngOnDestroy(): void { this.destroy$.next(); this.destroy$.complete(); } // 5. Public methods loadThreatModels(): void { // Implementation } // 6. Private methods private handleError(error: Error): void { // Implementation } } ``` ### Documentation Standards #### Code Comments **Go**: ```go // ThreatModel represents a threat modeling project // containing diagrams, threats, and security analysis. type ThreatModel struct { ID string `json:"id"` Name string `json:"name"` Description *string `json:"description,omitempty"` } // CreateThreatModel creates a new threat model with the given data. // It validates the input, assigns ownership to the authenticated user, // and persists to the database. // // Returns the created threat model or an error. func CreateThreatModel(c *gin.Context) { // Implementation } ``` **TypeScript**: ```typescript /** * Service for managing threat model operations. * * Provides methods for CRUD operations on threat models * and handles communication with the TMI API. */ @Injectable({providedIn: 'root'}) export class ThreatModelService { /** * Retrieves all threat models accessible to the current user. * * @returns Observable of threat model array * @throws Error if API call fails */ getThreatModels(): Observable { // Implementation } } ``` #### README and Documentation - Keep documentation up to date with code changes - Add code examples for new features - Update API documentation when endpoints change - Include migration guides for breaking changes ### Documentation Structure The TMI documentation is organized by audience and purpose across multiple repositories: #### TMI-UX Local Documentation (`tmi-ux/docs/`) **Reference Documentation** (`reference/`): | Directory | Contents | |-----------|----------| | `reference/architecture/` | `overview.md`, `validation.md`, `violations.md` (all resolved), `service-provisioning.md`, `naming-conventions.md`, `session-management.md`, `autosave-data-modeling.md`, `dfd-change-propagation/` | | `reference/libraries/` | `x6-complete-guide.md` - Comprehensive X6 graph library documentation | | `reference/features/` | `collaborative-editing.md`, `dfd-user-interaction-guide.md` | | `reference/security/` | `headers.md` - HTTP security header implementation | **Developer Documentation** (`developer/`): | Directory | Contents | |-----------|----------| | `developer/setup/` | `environment-configuration.md`, `core-services.md`, `import-constants.md` | | `developer/testing/` | `testing-utilities.md` - Testing utilities and patterns | | `developer/features/` | `validation-framework.md` | **AI Agent Documentation** (`agent/`): - `collaboration-participant-list-ux-design.md` - Collaboration UX design - `dfd-integration-testing-approach.md` - DFD integration testing strategy - `dfd-integration-test-plan.md` - DFD integration test plan - `developers-guide-antvx6-graphing-library.md` - X6 developer guide - `interesting-x6-events.txt` - X6 event samples - `pdf-report-diagram-rendering-design.md` - PDF diagram rendering design **Supporting Files** (in `docs/reference/`): - `authentication-component-architecture.png` - Authentication component architecture diagram - `authentication-flow.png` - OAuth authentication flow diagram #### TMI Server Local Documentation (`tmi/docs/`) - `docs/developer/` - Development documentation (setup, testing, integration) - `docs/operator/` - Operations documentation (deployment, database, monitoring) - `docs/reference/` - Reference materials (API specs, schemas, architecture) #### Wiki Documentation (GitHub wiki) - **Getting Started** - End-user guides for threat modeling - **Deployment** - Operator deployment guides - **Operation** - SRE/DevOps running TMI - **Development** - Contributor documentation - **API Reference** - Technical API documentation #### Documentation Conventions - **File Naming**: Use `kebab-case.md` naming convention (lowercase with hyphens, except README.md) - **Cross-References**: Maintain links between related documents - **Audience-Focused**: Each section serves a specific audience (developers, operators, end-users, AI agents) - **Verification**: All file references should be verified to exist before committing #### Quick Navigation for New Developers 1. Start with `CLAUDE.md` in the repository root for AI assistant guidance and project overview 2. Read the [[Architecture-and-Design]] guide 3. Review Service Provisioning Standards (`docs/reference/architecture/service-provisioning.md`) 4. Check Environment Configuration (`docs/developer/setup/environment-configuration.md`) #### When Adding New Documentation 1. Choose the appropriate location based on primary audience 2. Use descriptive, hyphenated filenames 3. Update README files in parent directories 4. Add cross-references to related documents 5. Verify all internal links before committing ## Testing Requirements ### Required Tests All contributions must include appropriate tests: #### 1. Unit Tests **Server (Go)**: ```go func TestCreateThreatModel(t *testing.T) { // Test your function } ``` **Web App (TypeScript)**: ```typescript describe('ThreatModelService', () => { it('should create threat model', () => { // Test your service }); }); ``` #### 2. Integration Tests For server changes that affect database or API: ```go func TestDatabaseThreatModelIntegration(t *testing.T) { suite := SetupIntegrationTest(t) defer suite.TeardownIntegrationTest(t) // Test with real database } ``` #### 3. API Tests For new endpoints, add Postman tests: ```javascript pm.test("Status code is 201", function () { pm.response.to.have.status(201); }); ``` #### 4. E2E Tests (if applicable) For UI changes (using Playwright): ```typescript import { test, expect } from '@playwright/test'; test('should create new threat model', async ({ page }) => { await page.goto('/threat-models'); await page.getByTestId('create-button').click(); // Test the flow }); ``` ### Test Coverage - Aim for **80%+ code coverage** on new code - All bug fixes must include a regression test - Test both happy path and error cases ### Running Tests ```bash # Server (Go) make test-unit # Go unit tests make test-integration # Integration tests with PostgreSQL make test-api # Postman/Newman API tests # Web App (Angular / Vitest / Playwright) cd tmi-ux pnpm run test # Unit tests (Vitest) pnpm run test:coverage # Unit tests with coverage report pnpm run test:e2e # E2E tests (Playwright) pnpm run test:e2e:ui # E2E tests with Playwright UI ``` ## Pull Request Process ### 1. PR Template Fill out all sections of the PR template: ```markdown ## Description Brief description of changes ## Type of Change - [ ] Bug fix - [ ] New feature - [ ] Breaking change - [ ] Documentation update ## Testing - [ ] Unit tests pass - [ ] Integration tests pass - [ ] API tests pass (if applicable) - [ ] E2E tests pass (if applicable) ## Checklist - [ ] Code follows style guidelines - [ ] Self-review completed - [ ] Code is commented where needed - [ ] Documentation updated - [ ] Tests added/updated - [ ] All tests pass locally ``` ### 2. Before Submitting Ensure your PR: - ✅ **Passes all checks** ```bash # Server make lint make test-unit make test-integration make build-server # Web App cd tmi-ux pnpm run lint:all pnpm run test pnpm run build ``` - Has no merge conflicts ```bash git fetch upstream git merge upstream/main # Resolve any conflicts ``` - ✅ **Has clear commit messages** - ✅ **Includes tests** - ✅ **Updates documentation** ### 3. PR Size Keep PRs focused and manageable: - **Ideal**: < 400 lines changed - **Maximum**: < 1000 lines changed - Large changes should be split into multiple PRs ### 4. Draft PRs Use draft PRs for: - Work in progress - Getting early feedback - Discussing approach ``` Mark PR as "Draft" when creating it Convert to "Ready for review" when complete ``` ## Code Review Guidelines ### For Contributors **Responding to Feedback**: - Be open to suggestions - Ask questions if unclear - Make requested changes promptly - Explain your reasoning when disagreeing **Handling Requests**: ```bash # Make requested changes git add . git commit -m "refactor: address review comments" git push origin feature/your-feature-name # Force push if rebasing/squashing git push --force-with-lease origin feature/your-feature-name ``` ### For Reviewers **Review Focus Areas**: 1. **Correctness** - Does it work as intended? 2. **Tests** - Adequate test coverage? 3. **Design** - Fits architecture? 4. **Performance** - Any bottlenecks? 5. **Security** - Any vulnerabilities? 6. **Documentation** - Clear and complete? **Giving Feedback**: ```markdown # Good feedback "Consider using a map here for O(1) lookup instead of iterating the array" "This could cause a race condition if two users update simultaneously. Consider using a transaction or optimistic locking." # Less helpful "This is wrong" "Do it differently" ``` ## Community Guidelines ### Code of Conduct We follow the [Contributor Covenant](https://www.contributor-covenant.org/): - **Be respectful** - Treat everyone with respect - **Be inclusive** - Welcome all contributors - **Be constructive** - Provide helpful feedback - **Be professional** - Keep discussions on-topic ### Communication Channels - **GitHub Issues** - Bug reports and feature requests - **GitHub Discussions** - Questions and general discussion - **Pull Requests** - Code review and technical discussions ### Asking Questions Before asking: 1. Check existing documentation 2. Search closed issues 3. Review pull requests When asking: - Provide context - Include error messages - Share relevant code snippets - Describe what you've tried ### Reporting Bugs Use this template: ```markdown ## Bug Description Clear description of the bug ## Steps to Reproduce 1. Go to '...' 2. Click on '...' 3. See error ## Expected Behavior What should happen ## Actual Behavior What actually happens ## Environment - OS: [e.g. macOS 13.0] - Browser: [e.g. Chrome 120] - TMI Version: [e.g. 0.9.0] ## Additional Context Screenshots, logs, etc. ``` ### Suggesting Features Use this template: ```markdown ## Feature Description Clear description of the feature ## Use Case Why is this needed? Who will use it? ## Proposed Solution How should it work? ## Alternatives Considered What other approaches did you consider? ## Additional Context Mockups, examples, etc. ``` ## Recognition Contributors are recognized in: - Release notes - Contributors list - Project README Significant contributions may lead to: - Maintainer status - Core team membership - Speaking opportunities ## AI-Assisted Development TMI supports AI-assisted development through detailed context documentation. The `docs/agent/` directory contains context and implementation guidance for AI coding agents working on this project, including architecture proposals, implementation plans, design documents, and technical context. ### Agent Documentation Contents The agent documentation directory includes: **Design and Planning Documents:** - **collaboration-participant-list-ux-design.md** - UX design for collaboration participant list feature - **pdf-report-diagram-rendering-design.md** - Design document for pre-rendered diagram storage to enable full diagram inclusion in PDF reports **Testing Documentation:** - **dfd-integration-testing-approach.md** - Integration testing approach for DFD services - **dfd-integration-test-plan.md** - Comprehensive integration test plan for DFD graph component **Implementation Guides:** - **developers-guide-antvx6-graphing-library.md** - Developer guide for working with the AntV X6 graphing library **Reference Information:** - **interesting-x6-events.txt** - Log samples of X6 graph events showing actual event data ### Related Documentation When working with AI tools on TMI, also reference: - **Architecture**: `docs/reference/architecture/` - Architecture overview, service provisioning standards, naming conventions, session management - **Developer Docs**: `docs/developer/` - Environment configuration, testing utilities, core services setup - **Technical References**: `docs/reference/` - X6 complete guide, collaborative editing implementation, security headers ### Authentication Context When working with TMI authentication: 1. **Primary Flow**: TMI uses OAuth 2.0 Authorization Code flow with PKCE (RFC 7636) 2. **TMI Provider**: Built-in development OAuth provider (`idp=tmi`) for testing 3. **JWT Tokens**: Authentication uses JWT tokens with specific claim structure 4. **Multi-Provider**: Supports Google, GitHub, and Microsoft OAuth providers ### Project Context Files - **CLAUDE.md**: Project-specific instructions in the repository root - **OpenAPI Spec**: `docs/reference/apis/tmi-openapi.json` for API structure - **Architecture Docs**: [[Architecture-and-Design]] for system understanding ### AI Development Best Practices - Reference the OpenAPI specification for endpoint behavior - Use structured logging with `github.com/ericfitz/tmi/internal/slogging` - Follow the testing patterns in existing test files - Always use Make targets (never run `go test` or `go run` directly) ### Usage Guidelines for AI Agents 1. **Implementation Plans**: Use `docs/agent/` for storing implementation plans, progress tracking, and design documents 2. **Context Documents**: Store technical context and background information there 3. **Testing Strategies**: Document testing approaches and plans 4. **Research Notes**: Keep research findings and technical analysis there 5. **Update Directory Contents**: AI assistants should update the directory README when adding or removing files ## Getting Help Need help contributing? - Read [[Getting-Started-with-Development]] - Check [[FAQ]] - Ask in GitHub Discussions - Review existing PRs for examples ## Quick Reference ### Common Commands ```bash # Server Development (Go 1.26.x) make start-dev # Start dev environment (DB + Redis + server) make test-unit # Run unit tests make test-integration # Run integration tests (PostgreSQL) make test-api # Run Postman/Newman API tests make lint # Run golangci-lint make build-server # Build binary make status # Check status of all services # Web App Development (Angular 21.x / Vitest 4.x / Playwright) cd tmi-ux pnpm run dev # Start dev server (ng serve --open) pnpm run test # Run unit tests (Vitest) pnpm run test:coverage # Run unit tests with coverage pnpm run test:e2e # Run E2E tests (Playwright) pnpm run lint:all # Run all linters (ESLint + Stylelint) pnpm run format # Format code (Prettier) pnpm run build # Build for production # Git Workflow (default branch is 'main') git checkout -b feature/name # Create branch from main git add . # Stage changes git commit -m "msg" # Commit git push origin feature/name # Push ``` ### Style Checklist - ✅ Go code formatted with `gofmt` - ✅ TypeScript/HTML formatted with Prettier - ✅ Linters pass - ✅ Tests pass - ✅ Documentation updated - ✅ Commit messages follow convention - ✅ No merge conflicts ## Next Steps Ready to contribute? 1. Set up your development environment: [[Getting-Started-with-Development]] 2. Understand the architecture: [[Architecture-and-Design]] 3. Review the testing guide: [[Testing]] 4. [Find an issue to work on](https://github.com/ericfitz/tmi/issues) 5. Create your first PR! Thank you for contributing to TMI!