Ctrl K
ComunidadGuías…

CONTRIBUTING.md

Rama develop · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# Contributing to Taskist

We welcome and appreciate all contributions to **Taskist** — bug fixes, features, documentation, translations, and help for other users in the community.

## 💡 Before You Start

**For anything beyond a small fix, please discuss the change first** in an [issue](https://github.com/Taskist/taskist/issues), in [GitHub Discussions](https://github.com/Taskist/taskist/discussions/categories/ideas), or by [email](mailto:taskist@outlook.in). It saves your time if the idea doesn't fit the project's direction.

Other ways to help:

- Answer questions in [GitHub Discussions](https://github.com/Taskist/taskist/discussions/categories/q-a)
- Improve the [documentation](https://docs.taskist.org)
- Spread the word — write about Taskist or link to it

Found a vulnerability? Please **do not** open a public issue or pull request. Follow [SECURITY.md](SECURITY.md) to report it privately.

## 🛠 Setting Up Your Development Environment

### Prerequisites

- [.NET 10 SDK](https://dotnet.microsoft.com/download/dotnet/10.0)
- SQL Server (Express, LocalDB or the Docker image)
- EF Core tools: `dotnet tool install --global dotnet-ef`
- Optional: [Docker Desktop](https://www.docker.com/products/docker-desktop/) for the full stack

### Getting started

```bash
git clone https://github.com/Taskist/taskist.git
cd taskist
dotnet restore src/Taskist.sln
```

Create `src/Presentation/Taskist.Web/appsettings.Development.json` (git-ignored):

```json
{
  "ConnectionStrings": {
    "AppContext": "Server=.\\SQLEXPRESS;Database=Taskist;Integrated Security=True;TrustServerCertificate=True;"
  }
}
```

Create the schema, then run `sql-scripts/02_defaults.sql` and `03_locale.sql` (`04_demo.sql` adds optional sample data):

```bash
dotnet ef database update --project src/Libraries/Taskist.Data --startup-project src/Libraries/Taskist.Data
```

Run the app and sign in with `admin@taskist.org` / `Admin@123`:

```bash
dotnet run --project src/Presentation/Taskist.Web
```

### Solution layout

| Project | Contents |
| ------- | -------- |
| `src/Libraries/Taskist.Core` | Entities, enums, DTOs, settings, shared helpers |
| `src/Libraries/Taskist.Data` | EF Core context, configurations, migrations, repositories |
| `src/Libraries/Taskist.Service` | Business services (registered automatically by assembly scan) |
| `src/Presentation/Taskist.Web` | MVC controllers, views, view models, validators, `wwwroot` |
| `src/Tests/Taskist.Tests` | xUnit tests (no database needed) |
| `sql-scripts/` | Idempotent seed scripts, run in numeric order |
| `tools/theme/` | Dark-theme generator (`generate-dark-css.py`) |

## ✅ Before Opening a Pull Request

CI runs these on every pull request, so please run them locally first:

```bash
dotnet build src/Taskist.sln
dotnet test src/Taskist.sln

# fails if the model changed without a migration
dotnet ef migrations has-pending-model-changes --project src/Libraries/Taskist.Data --startup-project src/Libraries/Taskist.Data
```

If you changed an entity, add a migration:

```bash
dotnet ef migrations add YourMigrationName --project src/Libraries/Taskist.Data --startup-project src/Libraries/Taskist.Data
```

Rebuild first; a stale build can produce an empty migration.

## 📐 Code Guidelines

Please match the style of the file you are editing. In particular:

**C#**

- **No comments in `.cs` files.** Group members with `#region` blocks instead (`Fields`, `Ctor`, `Methods`, `Utilities`, …).
- **One top-level type per file**, named after the type. Nested types stay with their parent.
- Inject dependencies through the constructor into `private readonly` fields.

**Views and front end**

- **No inline `<script>` or `<style>` blocks.** Put JavaScript in `wwwroot/js` and CSS in `wwwroot/css`.
- **No CDNs.** Vendor libraries locally under `wwwroot/lib`.
- **No `ViewBag` / `ViewData`** for passing data (the layout title is the only exception). Every view has a typed `@model`; put UI-only flags on a view model in `Taskist.Web/Models`.
- Empty, setup and error states use the `<wp-empty-state>` tag helper.
- After changing a colour in `wwwroot/css`, regenerate the dark theme with `python tools/theme/generate-dark-css.py` (Python 3.8+, no packages) and commit the result; CI fails if it is stale. Never edit `theme-dark.generated.css` by hand; dark fixes the generator can't infer go in `theme-dark.css`.

**Text and translations**

- UI text comes from the database. Add new keys to `sql-scripts/03_locale.sql`; labels don't render until the script runs.
- Seed scripts containing non-ASCII characters must stay **UTF-8 with BOM**.

**Database**

- Schema changes go in an EF Core migration only; never hand-written DDL.
- Migrations must be **additive and non-destructive**: add nullable columns or relax constraints. Don't drop columns holding data or rewrite existing values. Installs run in production with live data.
- Seed data follows the existing `INSERT … SELECT … WHERE NOT EXISTS` pattern, matched on business keys. Never use `SET IDENTITY_INSERT`.
- Edit forms must always include the record's current value in drop-downs, so saving can't silently clear a foreign key.

**Dependencies**

- Only permissively licensed (MIT, Apache 2.0, BSD) packages. No commercial, dual-licensed or "non-commercial" packages — for example FluentAssertions 8+ or EPPlus 5+.

**Tests**

- New pure logic (parsers, rules, calculations) should come with tests in `src/Tests/Taskist.Tests`. Use plain xUnit `Assert`.

### Adding a master (CRUD screen)

Entity (`BaseEntity` + `ISoftDeletedEntity` + `IAuditableEntity`) → EF configuration → service interface and implementation → model (`[LocalizedDisplayName]`) → controller (`[CheckPermission]`) → views (index DataTable, `_Form` create/edit) → FluentValidation validator → Mapperly mapping → permission in `PermissionProvider` and `02_defaults.sql` → menu entry in `02_defaults.sql` → labels in `03_locale.sql`.

## 🔐 Security-Sensitive Changes

Take extra care with code that touches authentication, authorization, file uploads, outbound HTTP or query building, and call it out in your pull request description.

- **Never interpolate user input into a query expression.** Grid sorting goes through `ApplySafeSort`, which only accepts real property names. Don't bypass it.
- **Always scope data access to the caller.** Loading a record by ID is not enough; check that the signed-in user may reach it (project membership, `CanEditTaskAsync`, …).
- **Outbound requests** to user-configured URLs must use the hardened named `HttpClient`s, which block loopback, link-local and metadata addresses.
- **Secrets** are stored through `[Encrypted]` properties or `ISecretProtector`, never in plain text, and never logged.

By participating, you agree to uphold our [Code of Conduct](CODE_OF_CONDUCT.md).