diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..6ce7004a --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,444 @@ +# Contributing to Respondent-Driven Sampling (RDS) App + +Thank you for your interest in contributing to the RDS App. This project is a secure, accessible, and open-source web application that streamlines data collection for homelessness research using Respondent-Driven Sampling (RDS). Developed in collaboration with the University of Washington iSchool and the King County Regional Homelessness Authority (KCRHA), this application enables volunteers and administrators to collect accurate survey data, track referrals, and generate population estimates more effectively than traditional Point-In-Time (PIT) counts. + +Your contributions directly support research-driven methodologies and help build a secure, HIPAA and HUD compliant platform for homelessness research. + +## Table of Contents + +- [Code of Conduct](#code-of-conduct) +- [Getting Started](#getting-started) +- [Development Workflow](#development-workflow) +- [Code Standards](#code-standards) +- [Testing](#testing) +- [Submitting Changes](#submitting-changes) +- [Project Architecture](#project-architecture) +- [Getting Help](#getting-help) + +## Code of Conduct + +This project adheres to the [Contributor Covenant Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code and contribute to an open, welcoming, diverse, inclusive, and healthy community. Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the maintainers responsible for enforcement anonymously through our [reporting form](https://form.jotform.us/70666109215151). + +## Getting Started + +### Prerequisites + +Before you begin, ensure you have the following installed: + +- **Node.js** (v22 or higher) +- **npm** (comes with Node.js) +- **Git** +- **MongoDB** (or access to MongoDB Atlas) +- **Twilio Account** (for SMS verification features) + +### Fork and Clone + +1. **Fork the repository** on GitHub by clicking the "Fork" button +2. **Clone your fork** locally: + +```bash +git clone https://github.com/YOUR_USERNAME/respondent-driven-sampling.git +cd respondent-driven-sampling +``` + +3. **Add the upstream remote** to stay in sync: + +```bash +git remote add upstream https://github.com/uw-ssec/respondent-driven-sampling.git +``` + +### Environment Setup + +1. **Set Environment Variables** + +Copy the `.env.example` file as `.env` in the `server` directory: + +```bash +cp server/.env.example server/.env +``` + +2. **Configure your `.env` file** with the following required values: + - `NODE_ENV`: Set to `development` for local development + - `MONGO_URI`: Your MongoDB connection string (MongoDB Atlas or local instance) + - `TWILIO_ACCOUNT_SID`: Your Twilio Account SID from the Twilio Console + - `TWILIO_AUTH_TOKEN`: Your Twilio Auth Token from the Twilio Console + - `TWILIO_VERIFY_SID`: Your Twilio Verify service ID (starts with "VA", found in Twilio Console under Verify services) + - `AUTH_SECRET`: A secure random string for JWT token signing + +3. **Install Packages** + +From the root directory: + +```bash +npm install +``` + +This will install dependencies for both the client and server. + +### Running Locally + +You will need two separate terminal windows: + +**Terminal 1 - Start Backend Server**: + +```bash +npm start +``` + +The backend server will run on port 1234. + +**Terminal 2 - Start Frontend Dev Server**: + +```bash +cd client +npm run dev +``` + +The frontend development server will run on port 3000. + +Visit the application at `http://localhost:3000`. + +## Development Workflow + +### Creating a Branch + +Always create a new branch for your work: + +```bash +git checkout -b feature/your-feature-name +# or +git checkout -b fix/bug-description +``` + +**Branch naming conventions**: +- `feature/` - New features +- `fix/` - Bug fixes +- `docs/` - Documentation changes +- `refactor/` - Code refactoring +- `test/` - Adding or updating tests + +### Making Changes + +1. **Make your changes** in the appropriate directory: + - `client/` - Frontend React code + - `server/` - Backend Express API + - `docs/` - Documentation + +2. **Test your changes** locally (see [Testing](#testing)) + +3. **Commit your changes** with clear, descriptive messages: + +```bash +git add . +git commit -m "feat: add survey export functionality" +``` + +### Commit Message Format + +We follow [Conventional Commits](https://www.conventionalcommits.org/): + +``` +: + +[optional body] + +[optional footer] +``` + +**Types**: +- `feat:` - New feature +- `fix:` - Bug fix +- `docs:` - Documentation changes +- `style:` - Code style changes (formatting, no logic change) +- `refactor:` - Code refactoring +- `test:` - Adding or updating tests +- `chore:` - Maintenance tasks + +**Examples**: +``` +feat: add CSV export for survey data +fix: resolve referral code generation collision +docs: update deployment instructions +test: add unit tests for survey controller +``` + +### Keeping Your Fork Updated + +Regularly sync with the upstream repository: + +```bash +git fetch upstream +git checkout main +git merge upstream/main +git push origin main +``` + +## Code Standards + +### TypeScript + +- Use TypeScript for all new code +- Avoid `any` types - use proper typing +- Export types from appropriate files in `types/` directories + +### Code Style + +We use ESLint and Prettier for code formatting: + +```bash +# Lint your code +npm run lint + +# Auto-fix linting issues +npm run lint:fix +``` + +### Pre-commit Hooks + +Pre-commit hooks will automatically run when you commit: +- Code formatting (Prettier) +- Linting (ESLint) +- TypeScript type checking +- JSON validation + +If pre-commit fails, fix the issues and commit again. + +### Path Aliases + +Use path aliases for cleaner imports: + +```typescript +// ✅ Good +import { authenticate } from '@/middleware/auth'; + +// ❌ Avoid +import { authenticate } from '../../../middleware/auth'; +``` + +### File Structure + +Follow the domain-driven structure for backend code: + +``` +server/src/database/{domain}/ + ├── mongoose/ # Mongoose models + hooks + ├── zod/ # Zod validation schemas + ├── {domain}.controller.ts # Business logic + └── {domain}.utils.ts # Domain utilities +``` + +## Testing + +### Running Tests + +```bash +# Server tests +cd server +npm test # Run all tests +npm run test:watch # Watch mode +npm run test:coverage # Generate coverage report +``` + +### Writing Tests + +- Place tests in `__tests__/` directories alongside source files +- Use descriptive test names +- Test both success and error cases +- Mock external dependencies (database, Twilio, etc.) + +**Example test structure**: + +```typescript +import { describe, expect, test } from '@jest/globals'; + +describe('Survey Controller', () => { + test('should generate unique child survey codes', async () => { + // Test implementation + }); + + test('should throw error when survey not found', async () => { + // Test implementation + }); +}); +``` + +### Test Requirements + +Contributions should include appropriate test coverage: + +- **Bug fixes**: Must include a test that reproduces the bug and verifies the fix +- **New features**: Should include tests covering the main functionality and edge cases +- **Refactoring**: All existing tests must continue to pass without modification +- **API changes**: Must include integration tests for new or modified endpoints + +## Submitting Changes + +### Before Submitting a Pull Request + +Ensure your contribution meets the following requirements: + +- [ ] Code follows the project's style guidelines and conventions +- [ ] All tests pass locally (`npm test` in server directory) +- [ ] Pre-commit hooks pass without errors +- [ ] Documentation is updated if applicable +- [ ] Commit messages follow the conventional commits format +- [ ] Changes do not introduce security vulnerabilities +- [ ] Sensitive data is not logged or exposed + +### Creating a Pull Request + +1. **Push your branch** to your fork: + +```bash +git push origin feature/your-feature-name +``` + +2. **Open a Pull Request** on GitHub from your fork to the `main` branch of `uw-ssec/respondent-driven-sampling` + +3. **Complete the PR template** with the following information: + - **Description**: Provide a clear, concise description of what changed and why it is needed + - **Related Issues**: Link any related issues using "Resolves #" + - **Type of change**: Check the appropriate box (bug fix, feature, documentation, refactor, build/CI, or other) + - **Testing instructions**: Provide steps reviewers can follow to verify functionality + - **Checklist**: Confirm tests are added/updated and documentation is current + - **Notes to reviewers**: Include any specific information reviewers should know + +4. **Respond to review feedback** promptly and professionally + +### Pull Request Review Process + +- Project maintainers will review your pull request +- Reviewers may request changes or ask clarifying questions +- Address all feedback and update your PR as needed +- Once approved by maintainers, your PR will be merged +- Your contribution will be recognized in the project README + +## Project Architecture + +### Repository Structure + +This is a monolithic React + Node.js application with the following structure: + +- **`client/`**: React frontend application (Vite + TypeScript + Material-UI) +- **`server/`**: Express backend API (TypeScript + MongoDB + Mongoose) +- **`docs/`**: Project documentation (deployment, database migration) +- **`terraform/`**: Infrastructure as code for Azure deployment +- **`.github/`**: GitHub workflows, issue templates, and PR templates + +### Key Concepts + +#### Domain-Driven Controllers + +The backend uses a layered domain structure where controllers contain business logic and are invoked from routes: + +```typescript +// ✅ Controller (business logic) +// server/src/database/survey/survey.controller.ts +export async function createSurvey(data: SurveyData) { + // Business logic here +} + +// ✅ Route (HTTP handling) +// server/src/routes/v2/surveys.ts +router.post('/', validate(createSurveySchema), async (req, res) => { + const survey = await createSurvey(req.body); + res.status(201).json(survey); +}); +``` + +#### Authentication & Authorization + +- JWT tokens are stored in localStorage on the client side +- Authentication middleware verifies JWT tokens and checks user approval status +- CASL (Capability-based Access Control Library) provides role-based and attribute-based permissions +- Users must have `APPROVED` status to access protected routes +- Volunteers can only access surveys they created at their assigned location + +#### Survey Referral Chain System + +The application implements Respondent-Driven Sampling through a referral chain mechanism: + +- Each survey has a unique `surveyCode` identifier +- Surveys may have a `parentSurveyCode` linking to the referring survey +- Upon completion, each survey generates 3 unique `childSurveyCodes` for participant referrals +- This creates a social network sampling structure for population estimation + +#### API Versioning + +- **v1 routes** (`/api/auth`, `/api/surveys`): Legacy routes, currently being deprecated +- **v2 routes** (`/api/v2/*`): Current API version, use these for all new features +- All v2 routes implement Zod validation middleware for request validation + +### Security Considerations + +This application handles sensitive homelessness research data and is built with HIPAA and HUD compliance in mind: + +- Never log personally identifiable information (PII) or sensitive survey data +- Follow HIPAA and HUD compliance guidelines in all contributions +- Do not modify security headers without maintainer review and approval +- Validate and sanitize all user inputs +- Use parameterized queries (Mongoose provides this by default) +- Report security vulnerabilities responsibly through private channels + +## Getting Help + +### Resources + +- **README**: [README.md](README.md) - Project overview, tech stack, and setup instructions +- **Documentation**: [docs/](docs/) - Deployment guides and database migration instructions +- **Issues**: [GitHub Issues](https://github.com/uw-ssec/respondent-driven-sampling/issues) - Bug reports, feature requests, and discussions + +### Asking Questions + +Before opening a new issue: + +1. Search existing issues to avoid duplicates +2. Review the README and documentation +3. Use the appropriate issue template for your question +4. Provide sufficient context, examples, and environment details +5. Be respectful and patient while awaiting responses + +### Issue Templates + +The project provides the following issue templates: + +- **Bug Report** (`🐞`): For reporting reproducible problems with the software +- **Feature Request** (`✨`): For suggesting new ideas or enhancements +- **Documentation Gap** (`📚`): For reporting missing or unclear documentation +- **Performance Issue**: For reporting performance-related concerns + +Select the template that best matches your needs when creating an issue. + +## Future Directions + +The project maintainers have identified several high-priority features and improvements that are currently out of scope but recommended for future development: + +**App Features**: +- Auto-populate location using GPS location coordinates +- Widget for staff to comment on survey responses +- Integration with Homeless Management Information System (HMIS) database system +- Volunteer scheduling dashboard for administrators +- Automated SMS gift card distribution +- Resume unfinished survey feature +- Admin ability to edit survey questions +- Volunteer ability to edit survey responses +- Survey analytics dashboard + +**Testing**: +- Dynamic Application Security Testing (DAST) + +**User Experience**: +- Step-by-step user training guide +- Setup wizard + +These items represent excellent opportunities for meaningful contributions to the project. + +## Recognition + +Contributors are recognized in the project README. Your contributions help advance homelessness research and support vulnerable populations. + +--- + +**Questions?** Open an issue using the appropriate template or reach out to the maintainers. + +**Ready to contribute?** Review open issues and look for those labeled `good first issue` to get started. diff --git a/docs/user-permissions.md b/docs/user-permissions.md new file mode 100644 index 00000000..8355215e --- /dev/null +++ b/docs/user-permissions.md @@ -0,0 +1,327 @@ +# User Permissions Documentation + +## Overview + +The RDS App implements a role-based access control (RBAC) system with attribute-based conditions using [CASL (Capability-based Access Control Library)](https://casl.js.org/). This document describes the user roles, their permissions, and the conditions that govern access to resources. + +## User Roles + +The application defines four hierarchical user roles: + +1. **Volunteer** - Field workers who conduct surveys +2. **Manager** - Supervisors who oversee volunteers at specific locations +3. **Admin** - Administrators with broad system access +4. **Super Admin** - System administrators with unrestricted access + +## User Lifecycle + +### Approval Status + +All users (except Super Admins) go through an approval process: + +- **PENDING** - Initial status when a user account is created +- **APPROVED** - User has been approved and can access the system +- **REJECTED** - User account has been rejected + +Only users with `APPROVED` status can authenticate and access protected routes. + +### User Creation and Approval + +- **Volunteers**: Can be created and approved by Managers (at the same location), Admins, or Super Admins +- **Managers**: Can be created and approved by Admins or Super Admins +- **Admins**: Can be created and approved by Admins or Super Admins +- **Super Admins**: Can only be created by other Super Admins + +## Resources (Subjects) + +The system currently implements access control for the following resources: + +- **User** - User accounts and profiles +- **Survey** - Survey data collected in the field + +### Future Resources + +The following resources are defined in the system but do not yet have role-based permissions implemented: + +- **Seed** - Initial survey seeds for starting referral chains (permissions planned but not yet implemented) +- **Location** - Geographic locations where surveys are conducted (permissions planned but not yet implemented) + +These resources are managed by Super Admins until specific role-based permissions are implemented. + +## Actions + +### Standard CRUD Actions + +- **create** - Create new resources +- **read** - View existing resources +- **update** - Modify existing resources +- **delete** - Remove resources (generally restricted) +- **manage** - Special action that includes all other actions + +### Custom Actions + +- **createWithoutReferral** - Create a survey without a parent referral code (seed surveys) + +## Permission Conditions + +Permissions can be restricted by the following conditions: + +- **IS_SELF** - User is accessing their own account +- **IS_CREATED_BY_SELF** - Resource was created by the current user +- **HAS_SAME_LOCATION** - Resource belongs to the user's assigned location +- **WAS_CREATED_TODAY** - Resource was created today (UTC timezone) +- **HAS_VOLUNTEER_ROLE** - Target user has the Volunteer role +- **HAS_MANAGER_ROLE** - Target user has the Manager role +- **HAS_ADMIN_ROLE** - Target user has the Admin role + +## Detailed Role Permissions + +### Volunteer + +Volunteers have the most restricted access, limited to their own data and surveys they create. + +#### User Permissions + +| Action | Subject | Conditions | Description | +|--------|---------|------------|-------------| +| read | User | IS_SELF | Can view their own profile only | +| update | User (profile fields only) | IS_SELF | Can update their own profile information (firstName, lastName, email, phone) | + +#### Survey Permissions + +| Action | Subject | Conditions | Description | +|--------|---------|------------|-------------| +| create | Survey | None | Can create new surveys | +| createWithoutReferral | Survey | None | Can create seed surveys without a referral code | +| read | Survey | IS_CREATED_BY_SELF, HAS_SAME_LOCATION, WAS_CREATED_TODAY | Can only view surveys they created today at their assigned location | +| update | Survey | IS_CREATED_BY_SELF, HAS_SAME_LOCATION, WAS_CREATED_TODAY | Can only edit surveys they created today at their assigned location | + +**Restrictions:** +- Cannot delete any surveys +- Cannot view or modify other users' data +- Cannot approve users +- Cannot change their own role or location + +### Manager + +Managers supervise volunteers at a specific location and have additional permissions for user management within their location. + +#### User Permissions + +| Action | Subject | Conditions | Description | +|--------|---------|------------|-------------| +| read | User | None | Can view all user profiles | +| create | User | HAS_VOLUNTEER_ROLE, HAS_SAME_LOCATION | Can create volunteer accounts at their assigned location (no time restriction) | +| update | User (approval fields) | HAS_VOLUNTEER_ROLE, HAS_SAME_LOCATION, WAS_CREATED_TODAY | Can approve volunteers at their location who were created today | +| update | User (profile fields only) | IS_SELF | Can update their own profile information | + +#### Survey Permissions + +| Action | Subject | Conditions | Description | +|--------|---------|------------|-------------| +| create | Survey | None | Can create new surveys | +| createWithoutReferral | Survey | None | Can create seed surveys without a referral code | +| read | Survey | IS_CREATED_BY_SELF, HAS_SAME_LOCATION, WAS_CREATED_TODAY | Can view surveys they created today at their assigned location | +| update | Survey | IS_CREATED_BY_SELF, HAS_SAME_LOCATION, WAS_CREATED_TODAY | Can edit surveys they created today at their assigned location | + +**Restrictions:** +- Cannot delete any surveys or users +- Cannot approve Managers or Admins +- Cannot change user roles or locations +- Cannot access surveys from other locations or previous days + +### Admin + +Admins have broad system access and can manage users and surveys across all locations. + +#### User Permissions + +| Action | Subject | Conditions | Description | +|--------|---------|------------|-------------| +| read | User | None | Can view all user profiles | +| create | User | HAS_VOLUNTEER_ROLE, HAS_MANAGER_ROLE, or HAS_ADMIN_ROLE | Can create Volunteer, Manager, and Admin accounts | +| update | User (approval fields) | HAS_VOLUNTEER_ROLE, HAS_MANAGER_ROLE, or HAS_ADMIN_ROLE | Can approve Volunteers, Managers, and Admins | +| update | User (role and location fields) | HAS_VOLUNTEER_ROLE or HAS_MANAGER_ROLE | Can change roles and locations for Volunteers and Managers | +| update | User (profile and location fields) | IS_SELF | Can update their own profile and location | + +#### Survey Permissions + +| Action | Subject | Conditions | Description | +|--------|---------|------------|-------------| +| create | Survey | None | Can create new surveys | +| createWithoutReferral | Survey | None | Can create seed surveys without a referral code | +| read | Survey | None | Can view all surveys | +| update | Survey | WAS_CREATED_TODAY | Can edit any survey created today | + +**Restrictions:** +- Cannot delete any surveys or users +- Cannot create or approve Super Admin accounts +- Cannot modify Super Admin accounts + +### Super Admin + +Super Admins have unrestricted access to all system resources and actions. + +#### Permissions + +| Action | Subject | Conditions | Description | +|--------|---------|------------|-------------| +| manage | all | None | Full access to all resources and actions | + +**Capabilities:** +- Create, read, update, and delete any resource +- Manage all user roles including other Super Admins +- No restrictions on surveys, locations, or any other resources +- Full system administration capabilities + +## Field-Level Permissions + +Certain actions are restricted to specific fields within resources: + +### User Fields + +- **Profile fields**: `firstName`, `lastName`, `email`, `phone` +- **Role field**: `role` +- **Approval fields**: `approvalStatus`, `approvedByUserObjectId` +- **Location field**: `locationObjectId` + +Different roles have different permissions on these field groups as described in the role-specific sections above. + +## Custom Permissions + +In addition to role-based permissions, individual users can be assigned custom permissions that override or supplement their default role permissions. Custom permissions are stored in the user's `permissions` array and consist of: + +- **action** - The action being granted (e.g., `read`, `update`) +- **subject** - The resource type (e.g., `Survey`, `User`) +- **conditions** - Array of conditions that must be met (e.g., `IS_SELF`, `HAS_SAME_LOCATION`) + +Custom permissions are evaluated after role-based permissions and can be used to grant additional access on a case-by-case basis. + +## Location-Based Access Control + +Many permissions are scoped to a user's assigned location (`locationObjectId`). This ensures: + +- Managers only supervise volunteers at their location +- Volunteers only access surveys from their location +- Data is compartmentalized by geographic area + +The user's location is determined by their most recent survey's location, not their profile location field. + +## Time-Based Access Control + +Survey access is often restricted to the current day (UTC timezone). This means: + +- Users can only view and edit surveys created today +- Historical surveys become read-only after the day they were created +- This prevents accidental modification of completed survey data + +## Security Considerations + +### Authentication Requirements + +- All users must have `APPROVED` status to access protected routes +- JWT tokens are used for authentication +- Tokens are verified on every request + +### Data Protection + +- Users cannot delete surveys to maintain data integrity +- Survey modifications are time-limited to prevent tampering +- Location-based restrictions prevent unauthorized cross-location access +- Field-level permissions prevent unauthorized role or approval changes + +### Audit Trail + +- All resources include `createdAt` and `updatedAt` timestamps +- Survey records include `createdByUserObjectId` for accountability +- User approvals track `approvedByUserObjectId` + +## Permission Evaluation Flow + +1. **Authentication**: Verify JWT token and check approval status +2. **Role-Based Permissions**: Apply default permissions based on user role +3. **Custom Permissions**: Apply any user-specific permission overrides +4. **Condition Evaluation**: Check if all required conditions are met +5. **Action Authorization**: Allow or deny the requested action + +## Examples + +### Example 1: Volunteer Creating a Survey + +A volunteer wants to create a new survey: +- **Action**: `create` +- **Subject**: `Survey` +- **Conditions**: None +- **Result**: ✅ Allowed - Volunteers can create surveys + +### Example 2: Volunteer Viewing Another User's Survey + +A volunteer wants to view a survey created by another volunteer: +- **Action**: `read` +- **Subject**: `Survey` +- **Conditions Required**: `IS_CREATED_BY_SELF`, `HAS_SAME_LOCATION`, `WAS_CREATED_TODAY` +- **Condition Check**: `IS_CREATED_BY_SELF` fails +- **Result**: ❌ Denied - Survey was not created by this volunteer + +### Example 3: Manager Approving a Volunteer + +A manager wants to approve a volunteer at their location who registered today: +- **Action**: `update` (approval fields) +- **Subject**: `User` +- **Conditions Required**: `HAS_VOLUNTEER_ROLE`, `HAS_SAME_LOCATION`, `WAS_CREATED_TODAY` +- **Condition Check**: All conditions pass +- **Result**: ✅ Allowed - Manager can approve this volunteer + +### Example 4: Admin Changing a Manager's Location + +An admin wants to change a manager's assigned location: +- **Action**: `update` (location field) +- **Subject**: `User` +- **Conditions Required**: `HAS_VOLUNTEER_ROLE` or `HAS_MANAGER_ROLE` +- **Condition Check**: `HAS_MANAGER_ROLE` passes +- **Result**: ✅ Allowed - Admins can change manager locations + +## Technical Implementation + +The permission system is implemented using: + +- **CASL Library**: Provides the core authorization framework +- **MongoDB Query Conditions**: Permissions are translated to MongoDB queries for efficient filtering +- **Middleware**: Authentication middleware injects user abilities into requests +- **Ability Builder**: Constructs permission sets based on roles and custom permissions + +For implementation details, see: +- `server/src/permissions/constants.ts` - Permission definitions +- `server/src/permissions/abilityBuilder.ts` - Permission assignment logic +- `server/src/middleware/auth.ts` - Authentication and authorization middleware + +## Future Development + +### Planned Permission Enhancements + +The following permission features are planned for future implementation: + +#### Seed Permissions + +Seed resources will have role-specific CRUD permissions to manage initial survey seeds for referral chains. Planned permissions include: + +- **Super Admin & Admin**: Full CRUD access to seeds +- **Manager**: Create, read, update, and delete seeds at their assigned location +- **Volunteer**: Read-only access to seeds at their location + +#### Location Permissions + +Location resources will have permissions to manage geographic locations where surveys are conducted: + +- **Super Admin & Admin**: Full CRUD access to all locations +- **Manager**: Read access to all locations, update access to their assigned location +- **Volunteer**: Read-only access to their assigned location + +These permissions are documented in the project's [permissions planning spreadsheet](https://docs.google.com/spreadsheets/d/134uRSlIAUwz1lsuSYB7IsAdIvexrOUfc5pgB6303GVY/edit) and will be implemented in future releases. + +## Related Documentation + +- [CASL Documentation](https://casl.js.org/v6/en/guide/intro) +- [CONTRIBUTING.md](../CONTRIBUTING.md) - Development guidelines +- [README.md](../README.md) - Project overview +- [Permissions Planning Spreadsheet](https://docs.google.com/spreadsheets/d/134uRSlIAUwz1lsuSYB7IsAdIvexrOUfc5pgB6303GVY/edit) - Detailed permission specifications