From d38a1ab86ca592802eb7424bfe3f4cfa13f4e84f Mon Sep 17 00:00:00 2001 From: Bill Date: Sat, 4 Oct 2025 16:16:05 -0400 Subject: [PATCH] Initial commit --- backend-api.md | 25 ++++++ ci.md | 23 ++++++ code-style.md | 7 ++ containerization.md | 5 ++ documentation.md | 18 +++++ error-handling.md | 8 ++ git-usage.md | 17 +++++ logging.md | 8 ++ project-context.md | 9 +++ project-structure.md | 177 +++++++++++++++++++++++++++++++++++++++++++ rule-usage.md | 5 ++ security.md | 6 ++ tech-stack.md | 38 ++++++++++ testing.md | 90 ++++++++++++++++++++++ 14 files changed, 436 insertions(+) create mode 100644 backend-api.md create mode 100644 ci.md create mode 100644 code-style.md create mode 100644 containerization.md create mode 100644 documentation.md create mode 100644 error-handling.md create mode 100644 git-usage.md create mode 100644 logging.md create mode 100644 project-context.md create mode 100644 project-structure.md create mode 100644 rule-usage.md create mode 100644 security.md create mode 100644 tech-stack.md create mode 100644 testing.md diff --git a/backend-api.md b/backend-api.md new file mode 100644 index 0000000..076fad1 --- /dev/null +++ b/backend-api.md @@ -0,0 +1,25 @@ +--- +trigger: always_on +--- + +# Backend API Rules + +## Development Phase (Pre-deployment) +- Breaking changes are allowed without deprecation. +- Route versioning is optional during this phase. You may: + - Use unversioned routes (e.g., `/api/*`) while iterating, or + - Use a provisional version like `/api/v0/*`. +- Pydantic (v2) schemas are the source of truth for all request/response payloads. + - Keep schema examples updated when fields or validation rules change. +- Keep OpenAPI docs at `/docs` current with every API change. +- Document API changes succinctly with each PR and add brief migration notes to `docs/api/` (e.g., `docs/api/CHANGELOG.md`) as needed. + +## Post-deployment Policy (Stabilized) +- Adopt versioned routes under `api/v1/*` and beyond. +- No breaking changes to `v1` without deprecation; introduce `v2` (or later) for breaking changes. +- Maintain deprecation notices and migration guidance in `docs/api/`. + +## Consistency and Quality +- Schemas define types, validation, and examples; align handler implementations strictly with schemas. +- Ensure error responses are documented (shape and examples) and include correlation IDs in responses/logs if available. +- Keep auto-generated docs (`/docs`) accurate and readable; ensure example payloads are representative and valid. \ No newline at end of file diff --git a/ci.md b/ci.md new file mode 100644 index 0000000..64076c6 --- /dev/null +++ b/ci.md @@ -0,0 +1,23 @@ +--- +trigger: always_on +--- + +# CI Rules + +## Overview +- CI runs from `.gitea/workflows/`. +- Use `scripts/ci/*` for shared pipeline logic to keep workflows DRY and consistent. + +## Required Checks + +### Backend +- Lint: ruff +- Type checking: mypy +- Tests: pytest with coverage ≥100% + +### Frontend +- Lint: eslint +- Tests: jest with coverage threshold (≥90% or match backend at 100% for symmetry) + +## Pull Requests and Branch Protection +- No merges to `main` without green pipelines (all required checks must pass). \ No newline at end of file diff --git a/code-style.md b/code-style.md new file mode 100644 index 0000000..fc50cbb --- /dev/null +++ b/code-style.md @@ -0,0 +1,7 @@ +--- +trigger: always_on +--- + +# Style Rules +- Prefer iteration and modularization over code duplication +- Use descriptive variable names with auxiliary verbs (e.g., isLoading, hasError) \ No newline at end of file diff --git a/containerization.md b/containerization.md new file mode 100644 index 0000000..a638ddf --- /dev/null +++ b/containerization.md @@ -0,0 +1,5 @@ +--- +trigger: always_on +--- + +- Deployment files in deploy/ \ No newline at end of file diff --git a/documentation.md b/documentation.md new file mode 100644 index 0000000..b85f742 --- /dev/null +++ b/documentation.md @@ -0,0 +1,18 @@ +--- +trigger: always_on +--- + +# Documentation Rules + +- Maintain a clear README with setup instructions. +- Document API interactions and data flows. + +## Development Phase (Pre-deployment) +- APIs may change without deprecation. Reflect changes immediately: + - Update OpenAPI docs (`/docs`) and any schema examples with each change. + - Record notable API surface changes under `docs/api/` (e.g., `docs/api/CHANGELOG.md`) with brief migration notes. + +## Post-deployment +- When versions are stabilized (e.g., `api/v1/*`), follow deprecation practices: + - Document breaking changes and provide upgrade guidance. + - Keep examples and endpoints in `docs/api/` synchronized with the active versions. \ No newline at end of file diff --git a/error-handling.md b/error-handling.md new file mode 100644 index 0000000..6ee9f91 --- /dev/null +++ b/error-handling.md @@ -0,0 +1,8 @@ +--- +trigger: always_on +--- + +- Implement proper error boundaries +- Log errors appropriately for debugging +- Provide user-friendly error messages +- Handle network failures gracefully \ No newline at end of file diff --git a/git-usage.md b/git-usage.md new file mode 100644 index 0000000..38cbf89 --- /dev/null +++ b/git-usage.md @@ -0,0 +1,17 @@ +--- +trigger: always_on +--- + +Commit Message Prefixes: +- "fix:" for bug fixes +- "feat:" for new features +- "perf:" for performance improvements +- "docs:" for documentation changes +- "style:" for formatting changes +- "refactor:" for code refactoring +- "test:" for adding missing tests +- "chore:" for maintenance tasks + +Credentials: +- user.name: Bill +- user.email: bill@bballou.com \ No newline at end of file diff --git a/logging.md b/logging.md new file mode 100644 index 0000000..ebe4049 --- /dev/null +++ b/logging.md @@ -0,0 +1,8 @@ +--- +trigger: always_on +--- + +- Correlation IDs in backend; include in logs and echo to responses for support. +- Structured logging (JSON) in production; human-readable in dev. +- Define log levels: DEBUG (dev), INFO/WARN/ERROR (prod). +- Frontend: log to console in dev; redact PII; show user-friendly errors. \ No newline at end of file diff --git a/project-context.md b/project-context.md new file mode 100644 index 0000000..8ee88f2 --- /dev/null +++ b/project-context.md @@ -0,0 +1,9 @@ +--- +trigger: always_on +--- + +Integrated Project Management Software +- Estimating +- Scheduling +- Task Management +- Reporting \ No newline at end of file diff --git a/project-structure.md b/project-structure.md new file mode 100644 index 0000000..dbe9a20 --- /dev/null +++ b/project-structure.md @@ -0,0 +1,177 @@ +--- +trigger: always_on +--- + +# Project Structure + +The repository follows a modular monorepo layout. Top-level deployment artifacts live under `deploy/`, and shared scripts live under `scripts/`. + +## Tree + +```text +project-management-suite/ +├── README.md # Project overview, setup instructions +├── LICENSE # Project license +├── .gitignore # Git ignore file +├── deploy/ # Project-level deployment artifacts (containers, envs, infra) +│ ├── compose.yml # Docker Compose for local dev and/or deployment +│ ├── .env.example # Example environment variables for compose/services +│ ├── docker/ # Dockerfiles, compose overrides, and container docs +│ │ ├── backend.Dockerfile +│ │ ├── frontend.Dockerfile +│ │ └── README.md +│ └── README.md # Notes on how to run/deploy with Deploy artifacts +├── scripts/ # Shared scripts for CI/local dev/ops +│ ├── ci/ # Scripts called by .gitea workflows +│ │ ├── backend-test.sh +│ │ └── frontend-test.sh +│ ├── dev/ # Developer convenience scripts +│ │ ├── start-backend.sh +│ │ ├── start-frontend.sh +│ │ ├── start-database.sh +│ │ └── reset-database.sh +│ └── utils/ # Misc utilities (lint, format, DB migrations, etc.) +│ ├── lint-backend.sh +│ ├── lint-frontend.sh +│ └── format-all.sh +├── backend/ # Server-side code (Python/FastAPI) +│ ├── pyproject.toml # Python project configuration +│ ├── .env.example # Example environment variables +│ ├── app/ # Application code +│ │ ├── main.py # FastAPI application entry point +│ │ ├── api/ # API routes +│ │ │ ├── __init__.py +│ │ │ ├── estimating.py # Estimating endpoints +│ │ │ ├── scheduling.py # Scheduling endpoints +│ │ │ └── tasks.py # Task management endpoints +│ │ ├── core/ # Core application code +│ │ │ ├── __init__.py +│ │ │ ├── config.py # Application configuration +│ │ │ ├── security.py # Authentication and authorization +│ │ │ └── errors.py # Error handling +│ │ ├── db/ # Database models and connections +│ │ │ ├── __init__.py +│ │ │ ├── session.py # Database session +│ │ │ └── models/ # Database models +│ │ │ ├── __init__.py +│ │ │ ├── user.py +│ │ │ ├── project.py +│ │ │ ├── task.py +│ │ │ └── estimate.py +│ │ ├── services/ # Business logic +│ │ │ ├── __init__.py +│ │ │ ├── estimating.py # Estimating logic +│ │ │ ├── scheduling.py # Scheduling logic +│ │ │ └── task.py # Task management logic +│ │ └── schemas/ # Pydantic schemas for request/response validation +│ │ ├── __init__.py +│ │ ├── user.py +│ │ ├── project.py +│ │ ├── task.py +│ │ └── estimate.py +│ └── tests/ # Server-side tests (pytest) +│ ├── __init__.py # Make 'tests' a package +│ ├── conftest.py # Test configuration and fixtures +│ ├── unit/ # Unit tests for backend/app +│ │ ├── __init__.py # Make 'unit' a package +│ │ ├── test_api/ # For files in backend/app/api/ +│ │ │ ├── __init__.py +│ │ │ └── test_estimating/ # For app/api/estimating.py +│ │ │ ├── __init__.py +│ │ │ ├── test_get_estimate.py # Example for get_estimate() +│ │ │ └── test_create_estimate.py # Example for create_estimate() +│ │ ├── test_core/ # For files in backend/app/core/ +│ │ │ ├── __init__.py +│ │ │ └── test_config/ # For app/core/config.py +│ │ │ ├── __init__.py +│ │ │ └── test_get_settings.py # Example for get_settings() +│ │ ├── test_db/ # For files in backend/app/db/ +│ │ │ ├── __init__.py +│ │ │ ├── test_session/ # For app/db/session.py +│ │ │ │ ├── __init__.py +│ │ │ │ └── test_get_connection_string.py # For get_connection_string() in session.py +│ │ │ └── test_models/ # For files in backend/app/db/models/ +│ │ │ ├── __init__.py +│ │ │ └── test_user/ # For app/db/models/user.py +│ │ │ ├── __init__.py +│ │ │ └── test_user_creation.py # Example test for a function in user.py +│ │ ├── test_services/ # For files in backend/app/services/ +│ │ │ ├── __init__.py +│ │ │ └── test_estimating/ # For app/services/estimating.py +│ │ │ ├── __init__.py +│ │ │ └── test_calculate_estimate.py # Example for calculate_estimate() +│ │ └── test_schemas/ # For files in backend/app/schemas/ +│ │ ├── __init__.py +│ │ └── test_user/ # For app/schemas/user.py +│ │ ├── __init__.py +│ │ └── test_user_validation.py # Example for a validation function +│ └── integration/ # Integration tests +│ ├── __init__.py # Make 'integration' a package +│ ├── test_api/ # Test API endpoints +│ │ ├── __init__.py +│ │ ├── test_estimating.py +│ │ ├── test_scheduling.py +│ │ └── test_tasks.py +│ └── test_db/ # Test database operations +│ ├── __init__.py +│ └── test_models.py +├── frontend/ # Client-side code (React) +│ ├── package.json # Node.js dependencies +│ ├── .env.example # Example environment variables +│ ├── public/ # Static assets +│ │ ├── index.html +│ │ ├── favicon.ico +│ │ └── assets/ +│ ├── src/ # React source code +│ │ ├── index.js # Entry point +│ │ ├── App.js # Main application component +│ │ ├── components/ # Reusable UI components +│ │ │ ├── common/ # Shared components +│ │ │ │ ├── Header.jsx +│ │ │ │ ├── Sidebar.jsx +│ │ │ │ └── Footer.jsx +│ │ │ ├── estimating/ # Estimating-related components +│ │ │ ├── scheduling/ # Scheduling-related components +│ │ │ └── tasks/ # Task management components +│ │ ├── pages/ # Page components +│ │ │ ├── Dashboard.jsx +│ │ │ ├── Estimating.jsx +│ │ │ ├── Scheduling.jsx +│ │ │ └── TaskManagement.jsx +│ │ ├── services/ # API service calls +│ │ │ ├── api.js # API client setup +│ │ │ ├── estimating.js +│ │ │ ├── scheduling.js +│ │ │ └── tasks.js +│ │ ├── store/ # State management (Redux/Context) +│ │ │ ├── index.js +│ │ │ ├── actions/ +│ │ │ └── reducers/ +│ │ ├── utils/ # Utility functions +│ │ └── styles/ # CSS/SCSS styles +│ └── tests/ # Client-side tests +│ ├── components/ +│ ├── pages/ +│ └── services/ +└── docs/ # Documentation + ├── api/ # API documentation + │ └── CHANGELOG.md # API surface changes and migration notes + ├── architecture/ # Architecture diagrams + └── user-guide/ # User documentation + +## Notes + +- deploy/ + - Use `deploy/compose.yml` as the canonical Compose file. If a legacy `docker-compose.yml` exists at repo root, consider removing or updating it to point to `deploy/compose.yml`. + - Provide `deploy/.env.example` to document required environment variables. + - Optionally include `deploy/k8s/` if you plan Kubernetes deployments. + +- scripts/ + - Place CI entrypoints under `scripts/ci/` and have `.gitea/workflows/*` call these scripts to keep CI DRY. + - Move ad-hoc developer scripts (e.g., start/reset scripts) into `scripts/dev/`. + - Keep one-liner helpers (lint/format) in `scripts/utils/` and reference them from package.json or CI as needed. + +## Rationale + +- Centralizing deployment artifacts under `deploy/` improves discoverability and avoids clutter at the repository root. +- Consolidating scripts under `scripts/` standardizes how CI and developers invoke common tasks, increasing consistency between local and CI environments. \ No newline at end of file diff --git a/rule-usage.md b/rule-usage.md new file mode 100644 index 0000000..1784603 --- /dev/null +++ b/rule-usage.md @@ -0,0 +1,5 @@ +--- +trigger: always_on +--- + +Every time you choose to apply a rule(s), explicitly state the rule(s) in the output. You can abbreviate the rule description to a single word or phrase.  Do not state rules as comments. \ No newline at end of file diff --git a/security.md b/security.md new file mode 100644 index 0000000..ac411e1 --- /dev/null +++ b/security.md @@ -0,0 +1,6 @@ +--- +trigger: always_on +--- + +- Secrets via environment variables; never commit secrets. Provide deploy/.env.example. +- Pin dependencies and enable vulnerability scanning where available in Gitea. \ No newline at end of file diff --git a/tech-stack.md b/tech-stack.md new file mode 100644 index 0000000..0ad76fe --- /dev/null +++ b/tech-stack.md @@ -0,0 +1,38 @@ +--- +trigger: always_on +--- + +# Tech Stack + +This project is a monorepo with a React Native (frontend) and FastAPI (backend) stack, deployed via Docker Compose and validated by Gitea Actions. + +## Backend (FastAPI) +- Language: Python 3.11+ +- Framework: FastAPI +- ASGI Server: Uvicorn +- Schemas: Pydantic v2 (source of truth for request/response) +- HTTP Client: httpx (for outbound integrations) +- Packaging/Deps: uv + pyproject.toml +- Lint/Format: ruff (format + lint) +- Type Checking: mypy (progressively strict) +- Testing: pytest + coverage (100% required) +- Logging: structured JSON in prod; human-readable in dev; correlation IDs +- Docs: OpenAPI at `/docs`, kept current with examples +- Optional: SQL (SQLAlchemy + async driver) if/when persistence is needed + +## Frontend (React Native) +- Runtime: React Native (Expo for dev) +- Language: TypeScript (strict mode) +- UI/Navigation: React Navigation (or Expo Router), reusable components in `frontend/components/` +- Networking: fetch or axios with a centralized service layer in `frontend/services/` +- State/Server cache: lightweight hooks; introduce React Query if needed later +- Testing: Jest + React Native Testing Library; MSW for network mocking +- Lint/Format: ESLint + Prettier +- Node: 20 LTS +- Note: RN production builds via EAS (outside Compose). Compose primarily supports local dev integration. + +## DevOps & Tooling +- Containerization: Docker Compose (`deploy/compose.yml`) +- CI: Gitea Actions in `.gitea/workflows/` + - Backend: ruff, mypy, pytest with coverage≥100% + - Frontend: eslint, jest with coverage thresholds (≥90% or match backend at 100% if desired) \ No newline at end of file diff --git a/testing.md b/testing.md new file mode 100644 index 0000000..ad12a71 --- /dev/null +++ b/testing.md @@ -0,0 +1,90 @@ +--- +trigger: always_on +--- + +## General Principles +- Write unit tests for new features prior to implementing the feature. +- Write unit tests for utilities and components. +- Maintain 100% test coverage (backend). Frontend coverage threshold follows CI config (≥90% or 100% for symmetry). +- Unit tests should never make external calls. Integration tests may call externals. +- Minimize fixtures for generating inputs; prefer explicit inline inputs/expectations. +- Tests should be written as functions (avoid class-based tests). +- Use descriptive, intention-revealing names (e.g., `isCreated`, `hasError`) and prefer iteration/modularization over duplication. + +## Test Structure + +### Top-level Layout +- `tests/unit/` for pure unit tests (no external I/O). +- `tests/integration/` for tests allowed to hit external services. + +### Granular Python Unit Test Organization +1. Use a directory per module under test (e.g., `tests/unit/app/services/estimating/`). +2. Within that directory, use a file per function under test (e.g., `test_calculate_estimate.py`). +3. Keep unit and integration tests in separate trees: `tests/unit/` and `tests/integration/`. + +### Naming and Scope +- Only test functionality in the module under test; don’t re-test validation or logic implemented elsewhere. +- Do not introduce coverage-only test files (e.g., files named with “additional_coverage”, “remaining_branches”, “misc_coverage”). +- When adding a new test file, name it by feature or unit under test (e.g., `test_service_delete_update.py`). + +## Backend (FastAPI) Testing + +### Framework +- Pytest + +### Coverage and Practices +- Prefer tests over no-cover. +- Avoid `# pragma: no cover` except in strictly justified cases: + - Optional dependency branches or platform guards + - Defensive/unreachable paths in supported environments +- Use `pytest-mock`’s `mocker` fixture for mocking. +- Use monkeypatches to control `time.sleep`, `random.random`, etc., to keep tests fast/deterministic. +- For network-like behavior, write light fakes with only the attributes used by the code under test. +- If a safety guard exists (e.g., a best-effort `close()`), add a micro-test to exercise it. + +### Commands +- Full suite (CI-like): `bash scripts/ci/backend-test.sh` +- Ad-hoc (from `backend/`): + - All tests (with dev extras): `uv run --with .[dev] -m pytest` + - With coverage: `uv run --with .[dev] -m pytest --cov=app --cov-report=term-missing` + - Single test/file: `uv run --with .[dev] -m pytest app/tests/unit/path/to/test_file.py::test_case` + +### Notes +- Dev extras defined under `[project.optional-dependencies].dev` in `backend/pyproject.toml` and include `pytest`, `pytest-cov`. +- Pytest config lives under `[tool.pytest.ini_options]` in `backend/pyproject.toml` (e.g., `testpaths = ["app/tests"]`). +- Quick run without extras (no coverage): `uv run -m pytest` (no `pytest-cov`). + +## Frontend (React or React Native) Testing + +### Framework +- Jest + Testing Library (React) or Jest + React Native Testing Library (React Native) + +### Mocking Guidance +- Avoid mocking React/React Native primitives unless necessary. +- Mock network via MSW. + +### Commands +- Full suite (CI-like): `bash scripts/ci/frontend-test.sh` +- Ad-hoc (from `frontend/`): + - npm: `npm run lint` then `npm test -- --coverage` + - pnpm: `pnpm run lint` then `pnpm test -- --coverage` + +## End-to-End (E2E) Testing +- Implement E2E tests for critical flows. +- Choose an appropriate framework based on the frontend: + - Web (React): Playwright or Cypress + - React Native: Detox +- Keep E2E focused on user-critical paths; avoid duplicating unit/integration coverage. + +## CI Expectations and Consistency +- CI runs from `.gitea/workflows/`. +- Required checks: + - Backend: ruff, mypy, tests with coverage ≥100%. + - Frontend: eslint, jest with coverage thresholds (≥90% or 100% for symmetry). +- No merges to main without green pipelines. +- Use `scripts/ci/*` to mirror CI logic locally. + +## Development Phase Testing (Pre-deployment) +- Update tests in the same PR when API contracts change (request/response shapes, validation, or status codes). +- Refresh example payloads in schemas and test fixtures together to prevent drift. +- Prefer targeted API integration tests for critical endpoints to validate schema and docs alignment. \ No newline at end of file