diff --git a/.github/workflows/markdown-lint.yml b/.github/workflows/markdown-lint.yml new file mode 100644 index 00000000000..1a01e977629 --- /dev/null +++ b/.github/workflows/markdown-lint.yml @@ -0,0 +1,60 @@ +name: 'Docs: Markdown Lint' + +on: + push: + branches: + - 'master' + - 'v5.*' + pull_request: + branches: + - 'master' + - 'v5.*' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: {} + +jobs: + markdown-lint: + if: github.repository == 'prowler-cloud/prowler' + runs-on: ubuntu-latest + timeout-minutes: 10 + permissions: + contents: read + + steps: + - name: Harden Runner + uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0 + with: + egress-policy: block + allowed-endpoints: > + api.github.com:443 + github.com:443 + registry.npmjs.org:443 + release-assets.githubusercontent.com:443 + + - name: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + - name: Setup Node.js + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + with: + node-version-file: ui/.nvmrc + + - name: Setup pnpm + uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0 + with: + package_json_file: ui/package.json + run_install: false + + - name: Run markdownlint + # Pin must match .pre-commit-config.yaml so prek and CI behave identically. + # pnpm dlx doesn't accept --ignore-scripts as a flag; the env var + # disables postinstall scripts on transitives the same way. + env: + pnpm_config_ignore_scripts: 'true' + run: pnpm dlx markdownlint-cli@0.45.0 '**/*.md' diff --git a/.markdownlint.json b/.markdownlint.json new file mode 100644 index 00000000000..02a11d111ba --- /dev/null +++ b/.markdownlint.json @@ -0,0 +1,10 @@ +{ + "extends": "markdownlint/style/prettier", + "first-line-h1": false, + "no-duplicate-heading": { + "siblings_only": true + }, + "no-inline-html": false, + "line-length": false, + "no-bare-urls": false +} diff --git a/.markdownlintignore b/.markdownlintignore new file mode 100644 index 00000000000..7aa58ccd1a4 --- /dev/null +++ b/.markdownlintignore @@ -0,0 +1,16 @@ +node_modules/ +ui/node_modules/ +.git/ +.venv/ +**/.venv/ +dist/ +build/ +htmlcov/ +.next/ +ui/.next/ +ui/out/ +contrib/ + +# Auto-generated content (keepachangelog format legitimately repeats section headings). +# Revisit with the team — see beads task on markdownlint rule triage. +**/CHANGELOG.md diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1d894cf531b..4e79141bb7a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -133,6 +133,13 @@ repos: pass_filenames: false priority: 50 + ## MARKDOWN + - repo: https://github.com/igorshubovych/markdownlint-cli + rev: v0.45.0 + hooks: + - id: markdownlint + priority: 30 + ## CONTAINERS - repo: https://github.com/hadolint/hadolint rev: v2.14.0 diff --git a/AGENTS.md b/AGENTS.md index d73d69f068f..1cf023889c8 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -11,6 +11,7 @@ Use these skills for detailed patterns on-demand: ### Generic Skills (Any Project) + | Skill | Description | URL | |-------|-------------|-----| | `typescript` | Const types, flat interfaces, utility types | [SKILL.md](skills/typescript/SKILL.md) | @@ -28,6 +29,7 @@ Use these skills for detailed patterns on-demand: | `tdd` | Test-Driven Development workflow | [SKILL.md](skills/tdd/SKILL.md) | ### Prowler-Specific Skills + | Skill | Description | URL | |-------|-------------|-----| | `prowler` | Project overview, component navigation | [SKILL.md](skills/prowler/SKILL.md) | diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 199d7ee13cf..90c1ed1954f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,4 +1,4 @@ -# Do you want to learn on how to... +# Do you want to learn on how to - [Contribute with your code or fixes to Prowler](https://docs.prowler.com/developer-guide/introduction) - [Create a new provider](https://docs.prowler.com/developer-guide/provider) @@ -32,5 +32,6 @@ Provider-specific developer notes: Want some swag as appreciation for your contribution? -# Prowler Developer Guide -https://goto.prowler.com/devguide +## Prowler Developer Guide + + diff --git a/README.md b/README.md index a583b102ae1..ad28c81e3d1 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@

- - + Prowler logo + Prowler logo

Prowler is the Open Cloud Security Platform trusted by thousands to automate security and compliance in any cloud environment. With hundreds of ready-to-use checks and compliance frameworks, Prowler delivers real-time, customizable monitoring and seamless integrations, making cloud security simple, scalable, and cost-effective for organizations of any size. @@ -22,8 +22,8 @@ PyPI Downloads Docker Pulls AWS ECR Gallery - - + Codecov coverage + Linux Foundation insights health score

Version @@ -36,7 +36,7 @@


- + Prowler Cloud demo

# Description @@ -146,11 +146,11 @@ Prowler App offers flexible installation methods tailored to various environment ### Docker Compose -**Requirements** +#### Requirements -* `Docker Compose` installed: https://docs.docker.com/compose/install/. +- `Docker Compose` installed: https://docs.docker.com/compose/install/. -**Commands** +#### Commands ``` console VERSION=$(curl -s https://api.github.com/repos/prowler-cloud/prowler/releases/latest | jq -r .tag_name) @@ -175,14 +175,14 @@ You can find more information in the [Troubleshooting](./docs/troubleshooting.md ### From GitHub -**Requirements** +#### Requirements -* `git` installed. -* `uv` installed: [uv installation](https://docs.astral.sh/uv/getting-started/installation/). -* `pnpm` installed: [pnpm installation](https://pnpm.io/installation). -* `Docker Compose` installed: https://docs.docker.com/compose/install/. +- `git` installed. +- `uv` installed: [uv installation](https://docs.astral.sh/uv/getting-started/installation/). +- `pnpm` installed: [pnpm installation](https://pnpm.io/installation). +- `Docker Compose` installed: https://docs.docker.com/compose/install/. -**Commands to run the API** +#### Commands to run the API ``` console git clone https://github.com/prowler-cloud/prowler @@ -199,7 +199,7 @@ gunicorn -c config/guniconf.py config.wsgi:application > After completing the setup, access the API documentation at http://localhost:8080/api/v1/docs. -**Commands to run the API Worker** +#### Commands to run the API Worker ``` console git clone https://github.com/prowler-cloud/prowler @@ -212,7 +212,7 @@ cd src/backend python -m celery -A config.celery worker -l info -E ``` -**Commands to run the API Scheduler** +#### Commands to run the API Scheduler ``` console git clone https://github.com/prowler-cloud/prowler @@ -225,7 +225,7 @@ cd src/backend python -m celery -A config.celery beat -l info --scheduler django_celery_beat.schedulers:DatabaseScheduler ``` -**Commands to run the UI** +#### Commands to run the UI ``` console git clone https://github.com/prowler-cloud/prowler @@ -237,7 +237,7 @@ pnpm start > Once configured, access the Prowler App at http://localhost:3000. Sign up using your email and password to get started. -**Pre-commit Hooks Setup** +#### Pre-commit Hooks Setup Some pre-commit hooks require tools installed on your system: @@ -257,14 +257,14 @@ prowler -v ### Containers -**Available Versions of Prowler CLI** +#### Available Versions of Prowler CLI The following versions of Prowler CLI are available, depending on your requirements: - `latest`: Synchronizes with the `master` branch. Note that this version is not stable. - `v4-latest`: Synchronizes with the `v4` branch. Note that this version is not stable. - `v3-latest`: Synchronizes with the `v3` branch. Note that this version is not stable. -- `` (release): Stable releases corresponding to specific versions. You can find the complete list of releases [here](https://github.com/prowler-cloud/prowler/releases). +- `` (release): Stable releases corresponding to specific versions. See the [complete list of Prowler releases](https://github.com/prowler-cloud/prowler/releases). - `stable`: Always points to the latest release. - `v4-stable`: Always points to the latest release for v4. - `v3-stable`: Always points to the latest release for v3. @@ -338,7 +338,7 @@ Full configuration, per-provider authentication, and SARIF examples: [Prowler Gi ## Prowler CLI -**Running Prowler** +### Running Prowler Prowler can be executed across various environments, offering flexibility to meet your needs. It can be run from: diff --git a/api/AGENTS.md b/api/AGENTS.md index b03dc5803cc..0483e55c04d 100644 --- a/api/AGENTS.md +++ b/api/AGENTS.md @@ -10,7 +10,7 @@ > - [`jsonapi`](../skills/jsonapi/SKILL.md) - Strict JSON:API v1.1 spec compliance > - [`pytest`](../skills/pytest/SKILL.md) - Generic pytest patterns -### Auto-invoke Skills +## Auto-invoke Skills When performing these actions, ALWAYS invoke the corresponding skill FIRST: @@ -81,7 +81,7 @@ When performing these actions, ALWAYS invoke the corresponding skill FIRST: ## DECISION TREES ### Serializer Selection -``` +```text Read → Serializer Create → CreateSerializer Update → UpdateSerializer @@ -89,7 +89,7 @@ Nested read → IncludeSerializer ``` ### Task vs View -``` +```text < 100ms → View > 100ms or external API → Celery task Needs retry → Celery task @@ -105,7 +105,7 @@ Django 5.1.x | DRF 3.15.x | djangorestframework-jsonapi 7.x | Celery 5.4.x | Pos ## PROJECT STRUCTURE -``` +```text api/src/backend/ ├── api/ # Main Django app │ ├── v1/ # API version 1 (views, serializers, urls) diff --git a/api/README.md b/api/README.md index 1ea27fa38f5..ea9661366fa 100644 --- a/api/README.md +++ b/api/README.md @@ -2,7 +2,7 @@ This repository contains the JSON API and Task Runner components for Prowler, which facilitate a complete backend that interacts with the Prowler SDK and is used by the Prowler UI. -# Components +## Components The Prowler API is composed of the following components: - The JSON API, which is an API built with Django Rest Framework. @@ -10,13 +10,13 @@ The Prowler API is composed of the following components: - The PostgreSQL database, which is used to store the data. - The Valkey database, which is an in-memory database which is used as a message broker for the Celery workers. -## Note about Valkey +### Note about Valkey [Valkey](https://valkey.io/) is an open source (BSD) high performance key/value datastore. Valkey exposes a Redis 7.2 compliant API. Any service that exposes the Redis API can be used with Prowler API. -# Modify environment variables +## Modify environment variables Under the root path of the project, you can find a file called `.env`. This file shows all the environment variables that the project uses. You should review it and set the values for the variables you want to change. @@ -24,7 +24,7 @@ If you don’t set `DJANGO_TOKEN_SIGNING_KEY` or `DJANGO_TOKEN_VERIFYING_KEY`, t **Important note**: Every Prowler version (or repository branches and tags) could have different variables set in its `.env` file. Please use the `.env` file that corresponds with each version. -## Local deployment +### Local deployment Keep in mind if you export the `.env` file to use it with local deployment that you will have to do it within the context of the virtual environment, not before. Otherwise, variables will not be loaded properly. To do this, you can run: @@ -34,12 +34,12 @@ set -a source .env ``` -# 🚀 Production deployment -## Docker deployment +## 🚀 Production deployment +### Docker deployment This method requires `docker` and `docker compose`. -### Clone the repository +#### Clone the repository ```console # HTTPS @@ -50,13 +50,13 @@ git clone git@github.com:prowler-cloud/api.git ``` -### Build the base image +#### Build the base image ```console docker compose --profile prod build ``` -### Run the production service +#### Run the production service This command will start the Django production server and the Celery worker and also the Valkey and PostgreSQL databases. @@ -68,7 +68,7 @@ You can access the server in `http://localhost:8080`. > **NOTE:** notice how the port is different. When developing using docker, the port will be `8080` to prevent conflicts. -### View the Production Server Logs +#### View the Production Server Logs To view the logs for any component (e.g., Django, Celery worker), you can use the following command with a wildcard. This command will follow logs for any container that matches the specified pattern: @@ -133,13 +133,13 @@ gunicorn -c config/guniconf.py config.wsgi:application > By default, the Gunicorn server will try to use as many workers as your machine can handle. You can manually change that in the `src/backend/config/guniconf.py` file. -# 🧪 Development guide +## 🧪 Development guide -## Local deployment +### Local deployment To use this method, you'll need to set up a Python virtual environment (version ">=3.11,<3.13") and keep dependencies updated. Additionally, ensure that `uv` and `docker compose` are installed. -### Clone the repository +#### Clone the repository ```console # HTTPS @@ -150,7 +150,7 @@ git clone git@github.com:prowler-cloud/api.git ``` -### Start the PostgreSQL Database and Valkey +#### Start the PostgreSQL Database and Valkey The PostgreSQL database (version 16.3) and Valkey (version 7) are required for the development environment. To make development easier, we have provided a `docker-compose` file that will start these components for you. @@ -161,7 +161,7 @@ The PostgreSQL database (version 16.3) and Valkey (version 7) are required for t docker compose up postgres valkey -d ``` -### Install the Python dependencies +#### Install the Python dependencies > You must have uv installed @@ -169,7 +169,7 @@ docker compose up postgres valkey -d uv sync ``` -### Apply migrations +#### Apply migrations For migrations, you need to force the `admin` database router. Assuming you have the correct environment variables and Python virtual environment, run: @@ -178,7 +178,7 @@ cd src/backend python manage.py migrate --database admin ``` -### Run the Django development server +#### Run the Django development server ```console cd src/backend @@ -188,7 +188,7 @@ python manage.py runserver You can access the server in `http://localhost:8000`. All changes in the code will be automatically reloaded in the server. -### Run the Celery worker +#### Run the Celery worker ```console python -m celery -A config.celery worker -l info -E @@ -196,11 +196,11 @@ python -m celery -A config.celery worker -l info -E The Celery worker does not detect and reload changes in the code, so you need to restart it manually when you make changes. -## Docker deployment +### Docker deployment This method requires `docker` and `docker compose`. -### Clone the repository +#### Clone the repository ```console # HTTPS @@ -211,13 +211,13 @@ git clone git@github.com:prowler-cloud/api.git ``` -### Build the base image +#### Build the base image ```console docker compose --profile dev build ``` -### Run the development service +#### Run the development service This command will start the Django development server and the Celery worker and also the Valkey and PostgreSQL databases. @@ -230,7 +230,7 @@ All changes in the code will be automatically reloaded in the server. > **NOTE:** notice how the port is different. When developing using docker, the port will be `8080` to prevent conflicts. -### View the development server logs +#### View the development server logs To view the logs for any component (e.g., Django, Celery worker), you can use the following command with a wildcard. This command will follow logs for any container that matches the specified pattern: @@ -238,7 +238,7 @@ To view the logs for any component (e.g., Django, Celery worker), you can use th docker logs -f $(docker ps --format "{{.Names}}" | grep 'api-') ``` -## Applying migrations +### Applying migrations For migrations, you need to force the `admin` database router. Assuming you have the correct environment variables and Python virtual environment, run: @@ -247,7 +247,7 @@ cd src/backend uv run python manage.py migrate --database admin ``` -## Apply fixtures +### Apply fixtures Fixtures are used to populate the database with initial development data. @@ -258,7 +258,7 @@ uv run python manage.py loaddata api/fixtures/0_dev_users.json --database admin > The default credentials are `dev@prowler.com:Thisisapassword123@` or `dev2@prowler.com:Thisisapassword123@` -## Run tests +### Run tests Note that the tests will fail if you use the same `.env` file as the development environment. @@ -269,7 +269,7 @@ cd src/backend uv run pytest ``` -# Custom commands +## Custom commands Django provides a way to create custom commands that can be run from the command line. @@ -281,7 +281,7 @@ To run a custom command, you need to be in the `prowler/api/src/backend` directo uv run python manage.py ``` -## Generate dummy data +### Generate dummy data ```console python manage.py findings --tenant @@ -298,7 +298,7 @@ This command creates, for a given tenant, a provider, scan and a set of findings > > The last step is required to access the findings details, since the UI needs that to print all the information. -### Example +#### Example ```console ~/backend $ uv run python manage.py findings --tenant diff --git a/docs/AGENTS.md b/docs/AGENTS.md index 826c6d63f41..8278a7f88a3 100644 --- a/docs/AGENTS.md +++ b/docs/AGENTS.md @@ -134,7 +134,7 @@ Example 1 is vague and even potentially ambiguous. Verbs state your purpose and Explicit use of second-person pronouns (you) and possessives (your) should be minimized whenever possible. Those constructions are best reserved for cases when instructions are directly given in an imperative form: -**Example of Improvement Through Avoiding Second Person Pronouns** +### Example of Improvement Through Avoiding Second Person Pronouns **Original:** Prowler App can be installed in different ways, depending on your environment: @@ -236,7 +236,7 @@ The use of bullet points is highly recommended when: * Information can be logically divided into multiple categories, each sharing characteristics, features, or other relevant classifications. * Items are significant enough as standalone concepts to deserve their own bullet point. -**Example of Improvement Through Bullet Points** +#### Example of Improvement Through Bullet Points **Original:** It contains hundreds of controls covering CIS, NIST 800, NIST CSF, CISA, RBI, FedRAMS, PCI-DSS, GDPR, HIPAA, FFIEC, SOC2, GXP, AWS Well-Architected Framework Security Pillar, AWS Foundational Technical Review (FTR), ENS (Spanish National Security Scheme), and your custom security frameworks. diff --git a/mcp_server/AGENTS.md b/mcp_server/AGENTS.md index c8f77bd4b17..a82cc42e335 100644 --- a/mcp_server/AGENTS.md +++ b/mcp_server/AGENTS.md @@ -2,7 +2,7 @@ > **Skills Reference**: See [`prowler-mcp`](../skills/prowler-mcp/SKILL.md) -### Auto-invoke Skills +## Auto-invoke Skills When performing these actions, ALWAYS invoke the corresponding skill FIRST: @@ -68,7 +68,7 @@ Python 3.12+ | FastMCP 2.13.1 | httpx (async) | Pydantic | uv ## PROJECT STRUCTURE -``` +```text mcp_server/prowler_mcp_server/ ├── server.py # Main orchestration ├── prowler_hub/server.py # Hub tools (no auth) diff --git a/mcp_server/README.md b/mcp_server/README.md index 644e4be31cb..e990f0f363d 100644 --- a/mcp_server/README.md +++ b/mcp_server/README.md @@ -83,14 +83,14 @@ npm install --save-exact mcp-remote@0.1.38 ### 2. Local STDIO Mode -**Run the server locally on your machine** +Run the server locally on your machine: - Runs as a subprocess of your MCP client - Requires Python 3.12+ or Docker ### 3. Self-Hosted HTTP Mode -**Deploy your own remote MCP server** +Deploy your own remote MCP server: - Full control over deployment - Requires Python 3.12+ or Docker @@ -132,7 +132,7 @@ All tools follow a consistent naming pattern with prefixes: ## Architecture -``` +```text prowler_mcp_server/ ├── server.py # Main orchestrator (imports sub-servers with prefixes) ├── main.py # CLI entry point @@ -154,17 +154,20 @@ prowler_mcp_server/ The Prowler MCP Server enables powerful workflows through AI assistants: -**Security Operations** +### Security Operations + - "Show me all critical findings from my AWS production accounts" - "Register my new AWS account in Prowler and run a scheduled scan every day" - "List all muted findings and detect what findgings are muted by a not enough good reason in relation to their severity" -**Security Research** +### Security Research + - "Explain what the S3 bucket public access Prowler check does" - "Find all Prowler checks related to encryption at rest" - "What is the latest version of the CIS that Prowler is covering per provider?" -**Documentation & Learning** +### Documentation & Learning + - "How do I configure Prowler to scan my GCP organization?" - "What authentication methods does Prowler support for Azure?" - "How can I contribute with a new security check to Prowler?" diff --git a/permissions/templates/terraform/README.md b/permissions/templates/terraform/README.md index ec41103e5e4..1bb037daa24 100644 --- a/permissions/templates/terraform/README.md +++ b/permissions/templates/terraform/README.md @@ -28,12 +28,12 @@ This Terraform configuration creates the necessary IAM role and policies to allo ### Usage Examples -#### Basic deployment (without S3 integration): +#### Basic deployment (without S3 integration) ```bash terraform apply -var="external_id=your-external-id-here" ``` -#### With S3 integration enabled: +#### With S3 integration enabled ```bash terraform apply \ -var="external_id=your-external-id-here" \ @@ -42,14 +42,14 @@ terraform apply \ -var="s3_integration_bucket_account_id=123456789012" ``` -#### Using terraform.tfvars file (Recommended): +#### Using terraform.tfvars file (Recommended) ```bash cp terraform.tfvars.example terraform.tfvars # Edit the file with your values terraform apply ``` -#### Command line variables (Alternative): +#### Command line variables (Alternative) ```bash terraform apply -var="external_id=your-external-id-here" ``` diff --git a/prowler/AGENTS.md b/prowler/AGENTS.md index 9c0895d3a16..ab3ba1ce677 100644 --- a/prowler/AGENTS.md +++ b/prowler/AGENTS.md @@ -7,7 +7,7 @@ > - [`prowler-compliance`](../skills/prowler-compliance/SKILL.md) - Compliance framework structure > - [`pytest`](../skills/pytest/SKILL.md) - Generic pytest patterns -### Auto-invoke Skills +## Auto-invoke Skills When performing these actions, ALWAYS invoke the corresponding skill FIRST: @@ -44,7 +44,7 @@ The Prowler SDK is the core Python engine powering cloud security assessments ac ### Provider Architecture -``` +```text prowler/providers/{provider}/ ├── {provider}_provider.py # Main provider class ├── models.py # Provider-specific models @@ -91,7 +91,7 @@ Python 3.10+ | uv | pytest | moto (AWS mocking) | Pre-commit hooks (black, flake ## PROJECT STRUCTURE -``` +```text prowler/ ├── __main__.py # CLI entry point ├── config/ # Global configuration diff --git a/skills/README.md b/skills/README.md index 999760d0796..47bf7e5562a 100644 --- a/skills/README.md +++ b/skills/README.md @@ -36,7 +36,7 @@ After running setup, restart your AI coding assistant to load the skills. Skills are automatically discovered by the AI agent. To manually load a skill during a session: -``` +```text Read skills/{skill-name}/SKILL.md ``` @@ -90,7 +90,7 @@ Patterns tailored for Prowler development: ## Directory Structure -``` +```text skills/ ├── {skill-name}/ │ ├── SKILL.md # Required - main instrunsction and metadata @@ -118,7 +118,7 @@ This reads `metadata.scope` and `metadata.auto_invoke` from each `SKILL.md` and Use the `skill-creator` skill for guidance: -``` +```text Read skills/skill-creator/SKILL.md ``` diff --git a/skills/django-drf/SKILL.md b/skills/django-drf/SKILL.md index 46c1c1bc934..7d73ed1543d 100644 --- a/skills/django-drf/SKILL.md +++ b/skills/django-drf/SKILL.md @@ -54,7 +54,7 @@ When implementing a new endpoint, review these patterns in order: ## Decision Trees ### Which Serializer? -``` +```text GET list/retrieve → Serializer POST create → CreateSerializer PATCH update → UpdateSerializer @@ -62,7 +62,7 @@ PATCH update → UpdateSerializer ``` ### Which Base Serializer? -``` +```text Read-only serializer → BaseModelSerializerV1 Create with tenant_id → RLSSerializer + BaseWriteSerializer (auto-injects tenant_id on create) Update with validation → BaseWriteSerializer (tenant_id already exists on object) @@ -70,14 +70,14 @@ Non-model data → BaseSerializerV1 ``` ### Which Filter Base? -``` +```text Direct FK to Provider → BaseProviderFilter FK via Scan → BaseScanProviderFilter No provider relation → FilterSet ``` ### Which Base ViewSet? -``` +```text RLS-protected model → BaseRLSViewSet (most common) Tenant operations → BaseTenantViewset User operations → BaseUserViewset @@ -85,7 +85,7 @@ No RLS required → BaseViewSet (rare) ``` ### Resource Name Format? -``` +```text Single word model → plural lowercase (Provider → providers) Multi-word model → plural lowercase kebab (ProviderGroup → provider-groups) Through/join model → parent-child pattern (UserRoleRelationship → user-roles) @@ -490,7 +490,7 @@ When implementing or debugging, query these libraries via `mcp_context7_query-do | **drf-spectacular** | `/tfranzel/drf-spectacular` | OpenAPI schema, `@extend_schema` | **Example queries:** -``` +```text mcp_context7_query-docs(libraryId="/websites/django-rest-framework", query="ViewSet get_queryset best practices") mcp_context7_query-docs(libraryId="/tfranzel/drf-spectacular", query="extend_schema examples for custom actions") mcp_context7_query-docs(libraryId="/websites/djangoproject_en_5_2", query="model constraints and indexes") diff --git a/skills/django-drf/references/file-locations.md b/skills/django-drf/references/file-locations.md index 30dab715502..d0f63ad042a 100644 --- a/skills/django-drf/references/file-locations.md +++ b/skills/django-drf/references/file-locations.md @@ -16,7 +16,7 @@ ## ViewSet Hierarchy -``` +```text BaseViewSet (minimal - no RLS/auth) │ ├── BaseRLSViewSet (+ tenant filtering, RLS-protected models) @@ -31,7 +31,7 @@ BaseViewSet (minimal - no RLS/auth) ## Serializer Hierarchy -``` +```text BaseModelSerializerV1 (JSON:API defaults, read_only_fields) │ ├── RLSSerializer (auto-injects tenant_id from request) @@ -47,7 +47,7 @@ BaseModelSerializerV1 (JSON:API defaults, read_only_fields) ## Filter Hierarchy -``` +```text FilterSet (django-filter) │ ├── CommonFindingFilters (mixin for date ranges, delta, status) diff --git a/skills/django-drf/references/json-api-conventions.md b/skills/django-drf/references/json-api-conventions.md index c51326b0b24..9a546671fa3 100644 --- a/skills/django-drf/references/json-api-conventions.md +++ b/skills/django-drf/references/json-api-conventions.md @@ -2,7 +2,7 @@ ## Content Type -``` +```http Content-Type: application/vnd.api+json Accept: application/vnd.api+json ``` diff --git a/skills/django-migration-psql/SKILL.md b/skills/django-migration-psql/SKILL.md index d292036dd0d..bca8949fda6 100644 --- a/skills/django-migration-psql/SKILL.md +++ b/skills/django-migration-psql/SKILL.md @@ -364,7 +364,7 @@ Batch utilities: `api/db_utils.py` (`batch_delete`, `create_objects_in_batches`, ## Decision tree -``` +```text Auto-generated migration? ├── Yes → Split it following the rules below └── No → Review it against the rules below @@ -420,7 +420,7 @@ When implementing or debugging migration patterns, query these libraries via `mc | django-postgres-extra | `/SectorLabs/django-postgres-extra` | Partitioned models, `PostgresPartitionedModel`, partition management | **Example queries:** -``` +```text mcp_context7_query-docs(libraryId="/websites/djangoproject_en_5_1", query="migration operations AddIndex RunPython atomic") mcp_context7_query-docs(libraryId="/websites/djangoproject_en_5_1", query="database indexes Meta class concurrently") mcp_context7_query-docs(libraryId="/websites/postgresql_org_docs_current", query="CREATE INDEX CONCURRENTLY partitioned table") diff --git a/skills/gh-aw/SKILL.md b/skills/gh-aw/SKILL.md index b45d4d151e8..d4c3a0c829c 100644 --- a/skills/gh-aw/SKILL.md +++ b/skills/gh-aw/SKILL.md @@ -30,7 +30,7 @@ allowed-tools: Read, Edit, Write, Glob, Grep, Bash, WebFetch ## File Layout -``` +```text .github/ ├── workflows/ │ ├── {name}.md # Frontmatter + thin context dispatcher @@ -308,7 +308,7 @@ After modifying any `.github/workflows/*.md`: Add to repo root so lock files auto-resolve on merge: -``` +```text .github/workflows/*.lock.yml linguist-generated=true merge=ours ``` diff --git a/skills/jsonapi/SKILL.md b/skills/jsonapi/SKILL.md index a8959a21995..db111469296 100644 --- a/skills/jsonapi/SKILL.md +++ b/skills/jsonapi/SKILL.md @@ -35,7 +35,7 @@ This skill focuses on **spec compliance**. For **implementation patterns** (View If Context7 MCP is available, query the JSON:API spec directly: -``` +```text mcp_context7_resolve-library-id(query="jsonapi specification") mcp_context7_query-docs(libraryId="", query="[specific topic: relationships, errors, etc.]") ``` @@ -44,7 +44,7 @@ mcp_context7_query-docs(libraryId="", query="[specific topic: relat If Context7 is not available, fetch from the official spec: -``` +```text WebFetch(url="https://jsonapi.org/format/", prompt="Extract rules for [specific topic]") ``` diff --git a/skills/nextjs-16/SKILL.md b/skills/nextjs-16/SKILL.md index 272339c2dae..cea38e255dc 100644 --- a/skills/nextjs-16/SKILL.md +++ b/skills/nextjs-16/SKILL.md @@ -14,7 +14,7 @@ allowed-tools: Read, Edit, Write, Glob, Grep, Bash, WebFetch, WebSearch, Task ## App Router File Conventions -``` +```text app/ ├── layout.tsx # Root layout (required) ├── page.tsx # Home page (/) diff --git a/skills/playwright/SKILL.md b/skills/playwright/SKILL.md index d9009d6f4a1..60c1db9fd5c 100644 --- a/skills/playwright/SKILL.md +++ b/skills/playwright/SKILL.md @@ -36,7 +36,7 @@ allowed-tools: Read, Edit, Write, Glob, Grep, Bash, WebFetch, WebSearch, Task ## File Structure -``` +```text tests/ ├── base-page.ts # Parent class for ALL pages ├── helpers.ts # Shared utilities @@ -182,14 +182,14 @@ export class SignUpPage extends BasePage { ## Refactoring Guidelines -### Move to `BasePage` when: +### Move to `BasePage` when - ✅ Navigation helpers used by multiple pages (`waitForPageLoad()`, `getCurrentUrl()`) - ✅ Common UI interactions (notifications, modals, theme toggles) - ✅ Verification patterns repeated across pages (`isVisible()`, `waitForVisible()`) - ✅ Error handling that applies to all pages - ✅ Screenshot utilities for debugging -### Move to `helpers.ts` when: +### Move to `helpers.ts` when - ✅ Test data generation (`generateUniqueEmail()`, `generateTestUser()`) - ✅ Setup/teardown utilities (`createTestUser()`, `cleanupTestData()`) - ✅ Custom assertions (`expectNotificationToContain()`) diff --git a/skills/postgresql-indexing/SKILL.md b/skills/postgresql-indexing/SKILL.md index 7fac9f4ecde..615000ad9ec 100644 --- a/skills/postgresql-indexing/SKILL.md +++ b/skills/postgresql-indexing/SKILL.md @@ -225,7 +225,7 @@ Rebuild invalid indexes without locking writes: REINDEX INDEX CONCURRENTLY index_name; ``` -### Understanding _ccnew and _ccold artifacts +### Understanding _ccnew and_ccold artifacts When `CREATE INDEX CONCURRENTLY` or `REINDEX INDEX CONCURRENTLY` is interrupted, temporary indexes may remain: @@ -377,7 +377,8 @@ VACUUM (ANALYZE) table_name; | PostgreSQL | `/websites/postgresql_org_docs_current` | Index types, EXPLAIN, partitioned table indexing, REINDEX | **Example queries:** -``` + +```text mcp_context7_query-docs(libraryId="/websites/postgresql_org_docs_current", query="CREATE INDEX CONCURRENTLY partitioned table") mcp_context7_query-docs(libraryId="/websites/postgresql_org_docs_current", query="EXPLAIN ANALYZE BUFFERS query plan") mcp_context7_query-docs(libraryId="/websites/postgresql_org_docs_current", query="partial index WHERE clause") diff --git a/skills/prowler-api/SKILL.md b/skills/prowler-api/SKILL.md index 604d7fe4d2c..0c7dc86222e 100644 --- a/skills/prowler-api/SKILL.md +++ b/skills/prowler-api/SKILL.md @@ -61,7 +61,7 @@ Provider.objects.filter(connected=True) # Requires rls_transaction context ### RLS Transaction Flow -``` +```text Request → Authentication → BaseRLSViewSet.initial() │ ├─ Extract tenant_id from JWT @@ -92,7 +92,7 @@ When implementing Prowler-specific API features: ## Decision Trees ### Which Base Model? -``` +```text Tenant-scoped data → RowLevelSecurityProtectedModel Global/shared data → models.Model + BaseSecurityConstraint (rare) Partitioned time-series → PostgresPartitionedModel + RowLevelSecurityProtectedModel @@ -100,14 +100,14 @@ Soft-deletable → Add is_deleted + ActiveProviderManager ``` ### Which Manager? -``` +```text Normal queries → Model.objects (excludes deleted) Include deleted records → Model.all_objects Celery task context → Must use rls_transaction() first ``` ### Which Database? -``` +```text Standard API queries → default (automatic via ViewSet) Read-only operations → replica (automatic for GET in BaseRLSViewSet) Auth/admin operations → MainRouter.admin_db @@ -115,7 +115,7 @@ Cross-tenant lookups → MainRouter.admin_db (use sparingly!) ``` ### Celery Task Decorator Order? -``` +```python @shared_task(base=RLSTask, name="...", queue="...") @set_tenant # First: sets tenant context @handle_provider_deletion # Second: handles deleted providers @@ -496,7 +496,7 @@ When implementing or debugging Prowler-specific patterns, query these libraries | **Django** | `/websites/djangoproject_en_5_2` | Models, ORM, constraints, indexes | **Example queries:** -``` +```text mcp_context7_query-docs(libraryId="/websites/celeryq_dev_en_stable", query="shared_task decorator retry patterns") mcp_context7_query-docs(libraryId="/celery/django-celery-beat", query="periodic task database scheduler") mcp_context7_query-docs(libraryId="/websites/djangoproject_en_5_2", query="model constraints CheckConstraint UniqueConstraint") diff --git a/skills/prowler-api/references/configuration.md b/skills/prowler-api/references/configuration.md index 677f999cc4e..0a68d589513 100644 --- a/skills/prowler-api/references/configuration.md +++ b/skills/prowler-api/references/configuration.md @@ -2,7 +2,7 @@ ## Settings File Structure -``` +```text api/src/backend/config/ ├── django/ │ ├── base.py # Base settings (all environments) diff --git a/skills/prowler-api/references/modeling-decisions.md b/skills/prowler-api/references/modeling-decisions.md index 68923c4ef48..c11ed585ec5 100644 --- a/skills/prowler-api/references/modeling-decisions.md +++ b/skills/prowler-api/references/modeling-decisions.md @@ -247,7 +247,7 @@ class JSONAPIMeta: ## Decision Tree: New Model -``` +```text Is it tenant-scoped data? ├── Yes → Inherit RowLevelSecurityProtectedModel │ Add RowLevelSecurityConstraint diff --git a/skills/prowler-attack-paths-query/SKILL.md b/skills/prowler-attack-paths-query/SKILL.md index fb25d4fa43b..6dad9769836 100644 --- a/skills/prowler-attack-paths-query/SKILL.md +++ b/skills/prowler-attack-paths-query/SKILL.md @@ -228,7 +228,7 @@ AWS_QUERIES: list[AttackPathsQueryDefinition] = [ **FIRST**, read all files in the queries module to understand the structure, type definitions, registration, and existing style: -``` +```text api/src/backend/api/attack_paths/queries/ ├── __init__.py # Module exports ├── types.py # AttackPathsQueryDefinition, AttackPathsQueryParameterDefinition @@ -250,7 +250,7 @@ grep cartography api/pyproject.toml Build the schema URL (ALWAYS use the specific tag, not master/main): -``` +```text # Git dependency (prowler-cloud/cartography@0.126.1): https://raw.githubusercontent.com/prowler-cloud/cartography/refs/tags/0.126.1/docs/root/modules/{provider}/schema.md @@ -283,7 +283,7 @@ Add the constant to the `{PROVIDER}_QUERIES` list. ### Query ID -``` +```text {provider}-{category}-{description} ``` @@ -291,7 +291,7 @@ Examples: `aws-ec2-privesc-passrole-iam`, `aws-ec2-instances-internet-exposed` ### Query constant name -``` +```text {PROVIDER}_{CATEGORY}_{DESCRIPTION} ``` diff --git a/skills/prowler-commit/SKILL.md b/skills/prowler-commit/SKILL.md index 0f67cbe882c..30dbbc49cda 100644 --- a/skills/prowler-commit/SKILL.md +++ b/skills/prowler-commit/SKILL.md @@ -28,7 +28,7 @@ metadata: ## Commit Format -``` +```text type(scope): concise description - Key change 1 @@ -68,7 +68,7 @@ type(scope): concise description ### Title Line -``` +```text # GOOD - Concise and clear feat(api): add provider connection retry logic fix(ui): resolve dashboard loading state @@ -83,7 +83,7 @@ fix(ui): fix the bug in dashboard component on line 45 ### Body (Bullet Points) -``` +```text # GOOD - High-level changes - Add retry mechanism for failed connections - Document task composition patterns @@ -132,7 +132,7 @@ fix(ui): fix the bug in dashboard component on line 45 ## Decision Tree -``` +```text Single file changed? ├─ Yes → May omit body, title only └─ No → Include body with key changes diff --git a/skills/prowler-compliance-review/SKILL.md b/skills/prowler-compliance-review/SKILL.md index 6ac720dce8f..06f371f81b9 100644 --- a/skills/prowler-compliance-review/SKILL.md +++ b/skills/prowler-compliance-review/SKILL.md @@ -53,7 +53,7 @@ diff dashboard/compliance/{new_framework}.py \ ## Decision Tree -``` +```text JSON Valid? ├── No → FAIL: Fix JSON syntax errors └── Yes ↓ diff --git a/skills/prowler-compliance/SKILL.md b/skills/prowler-compliance/SKILL.md index 51c68eb05fb..f119c7fa9bd 100644 --- a/skills/prowler-compliance/SKILL.md +++ b/skills/prowler-compliance/SKILL.md @@ -59,7 +59,7 @@ See "Compliance Framework Location" and "Framework-Specific Attribute Structures **Every framework directory follows this exact convention** — do not deviate: -``` +```text {framework}/ ├── __init__.py ├── {framework}.py # ONLY get_{framework}_table() — NO function docstring @@ -85,7 +85,7 @@ See "Compliance Framework Location" and "Framework-Specific Attribute Structures ### The CLI Pipeline (end-to-end) -``` +```text prowler aws --compliance ccc_aws ↓ Compliance.get_bulk("aws") → parses prowler/compliance/aws/*.json @@ -483,6 +483,7 @@ Prowler ThreatScore is a custom security scoring framework developed by Prowler ## Available Compliance Frameworks ### AWS (41 frameworks) + | Framework | File Name | |-----------|-----------| | CIS 1.4, 1.5, 2.0, 3.0, 4.0, 5.0 | `cis_{version}_aws.json` | @@ -508,6 +509,7 @@ Prowler ThreatScore is a custom security scoring framework developed by Prowler | NIS2 | `nis2_aws.json` | ### Azure (15+ frameworks) + | Framework | File Name | |-----------|-----------| | CIS 2.0, 2.1, 3.0, 4.0 | `cis_{version}_azure.json` | @@ -518,6 +520,7 @@ Prowler ThreatScore is a custom security scoring framework developed by Prowler | NIST CSF 2.0 | `nist_csf_2.0_azure.json` | ### GCP (15+ frameworks) + | Framework | File Name | |-----------|-----------| | CIS 2.0, 3.0, 4.0 | `cis_{version}_gcp.json` | @@ -528,6 +531,7 @@ Prowler ThreatScore is a custom security scoring framework developed by Prowler | NIST CSF 2.0 | `nist_csf_2.0_gcp.json` | ### Kubernetes (6 frameworks) + | Framework | File Name | |-----------|-----------| | CIS 1.8, 1.10, 1.11 | `cis_{version}_kubernetes.json` | @@ -561,7 +565,7 @@ done The sync tooling is split into three layers so adding a new framework only takes a YAML config (and optionally a new parser module for an unfamiliar upstream format): -``` +```text skills/prowler-compliance/assets/ ├── sync_framework.py # generic runner — works for any framework ├── configs/ @@ -902,7 +906,7 @@ Add fixtures to `tests/lib/outputs/compliance/fixtures.py`: one `Compliance` obj **The table dispatcher file (`{framework}.py`) MUST NOT import `Finding`** (directly or transitively). The cycle is: -``` +```text compliance.compliance imports get_{framework}_table → {framework}.py imports ComplianceOutput → compliance_output imports Finding diff --git a/skills/prowler-compliance/references/compliance-docs.md b/skills/prowler-compliance/references/compliance-docs.md index 62d619953fc..a8d11484a91 100644 --- a/skills/prowler-compliance/references/compliance-docs.md +++ b/skills/prowler-compliance/references/compliance-docs.md @@ -46,7 +46,7 @@ Each framework type has a specific Pydantic model in `compliance_models.py`: ## File Naming Convention -``` +```text {framework}_{version}_{provider}.json ``` diff --git a/skills/prowler-docs/SKILL.md b/skills/prowler-docs/SKILL.md index 41a97f5ff95..4c4c64967f9 100644 --- a/skills/prowler-docs/SKILL.md +++ b/skills/prowler-docs/SKILL.md @@ -104,7 +104,7 @@ Reference without articles: ## Documentation Structure -``` +```text docs/ ├── getting-started/ ├── tutorials/ diff --git a/skills/prowler-provider/SKILL.md b/skills/prowler-provider/SKILL.md index 5b93ddd479b..8042cd9f5a9 100644 --- a/skills/prowler-provider/SKILL.md +++ b/skills/prowler-provider/SKILL.md @@ -25,7 +25,7 @@ Use this skill when: Every provider MUST follow this structure: -``` +```text prowler/providers/{provider}/ ├── __init__.py ├── {provider}_provider.py # Main provider class diff --git a/skills/prowler-readme-table/SKILL.md b/skills/prowler-readme-table/SKILL.md index d6f9c6e780d..6cea125ca01 100644 --- a/skills/prowler-readme-table/SKILL.md +++ b/skills/prowler-readme-table/SKILL.md @@ -34,7 +34,7 @@ python3 prowler-cli.py --list- The CLI output ends with a summary line like: -``` +```text There are 572 available checks. There is 1 available Compliance Framework. ``` diff --git a/skills/prowler-sdk-check/SKILL.md b/skills/prowler-sdk-check/SKILL.md index 13ae895da4d..1901e996d47 100644 --- a/skills/prowler-sdk-check/SKILL.md +++ b/skills/prowler-sdk-check/SKILL.md @@ -16,7 +16,7 @@ allowed-tools: Read, Edit, Write, Glob, Grep, Bash, WebFetch, WebSearch, Task ## Check Structure -``` +```text prowler/providers/{provider}/services/{service}/{check_name}/ ├── __init__.py ├── {check_name}.py @@ -90,7 +90,7 @@ See `prowler-test-sdk` skill for test patterns (PASS, FAIL, no resources, error ## Check Naming Convention -``` +```text {service}_{resource}_{security_control} ``` diff --git a/skills/prowler-test-api/SKILL.md b/skills/prowler-test-api/SKILL.md index 6395b562dd1..5b3e2ae6a11 100644 --- a/skills/prowler-test-api/SKILL.md +++ b/skills/prowler-test-api/SKILL.md @@ -28,7 +28,7 @@ allowed-tools: Read, Edit, Write, Glob, Grep, Bash, WebFetch, WebSearch, Task ## 1. Fixture Dependency Chain -``` +```text create_test_user (session) ─► tenants_fixture (function) ─► authenticated_client │ └─► providers_fixture ─► scans_fixture ─► findings_fixture diff --git a/skills/prowler-test-api/references/test-api-docs.md b/skills/prowler-test-api/references/test-api-docs.md index 11f866bd85f..0150fbfe877 100644 --- a/skills/prowler-test-api/references/test-api-docs.md +++ b/skills/prowler-test-api/references/test-api-docs.md @@ -14,7 +14,7 @@ ## Fixture Dependency Graph -``` +```text create_test_user (session) │ └─► tenants_fixture (function) diff --git a/skills/prowler-test-sdk/SKILL.md b/skills/prowler-test-sdk/SKILL.md index a9e5b3c9feb..ccf9ecdf03a 100644 --- a/skills/prowler-test-sdk/SKILL.md +++ b/skills/prowler-test-sdk/SKILL.md @@ -265,7 +265,7 @@ from tests.providers.kubernetes.kubernetes_fixtures import set_mocked_kubernetes ## Test File Structure -``` +```text tests/providers/{provider}/services/{service}/ ├── {service}_service_test.py # Service tests └── {check_name}/ diff --git a/skills/prowler-test-ui/SKILL.md b/skills/prowler-test-ui/SKILL.md index 558525932de..2cd583eb32f 100644 --- a/skills/prowler-test-ui/SKILL.md +++ b/skills/prowler-test-ui/SKILL.md @@ -19,7 +19,7 @@ allowed-tools: Read, Edit, Write, Glob, Grep, Bash, WebFetch, WebSearch, Task ## Prowler UI Test Structure -``` +```text ui/tests/ ├── base-page.ts # Prowler-specific base page ├── helpers.ts # Prowler test utilities @@ -35,13 +35,13 @@ ui/tests/ **⚠️ ALWAYS verify BEFORE completing any E2E task:** -### When CREATING new tests: +### When CREATING new tests - [ ] `{page-name}-page.ts` - Page Object created/updated - [ ] `{page-name}.spec.ts` - Tests added with correct tags (@TEST-ID) - [ ] `{page-name}.md` - Documentation created with ALL test cases - [ ] Test IDs in `.md` match tags in `.spec.ts` -### When MODIFYING existing tests: +### When MODIFYING existing tests - [ ] `{page-name}.md` MUST be updated if: - Test cases were added/removed - Test flow changed (steps) @@ -49,7 +49,7 @@ ui/tests/ - Tags or priorities changed - [ ] Test IDs synchronized between `.md` and `.spec.ts` -### Quick validation: +### Quick validation ```bash # Verify .md exists for each test folder ls ui/tests/{feature}/{feature}.md @@ -59,7 +59,8 @@ grep -o "@[A-Z]*-E2E-[0-9]*" ui/tests/{feature}/{feature}.spec.ts | sort -u grep -o "\`[A-Z]*-E2E-[0-9]*\`" ui/tests/{feature}/{feature}.md | sort -u ``` -**❌ An E2E change is NOT considered complete without updating the corresponding .md file** +> [!IMPORTANT] +> ❌ An E2E change is NOT considered complete without updating the corresponding `.md` file. --- diff --git a/skills/prowler-ui/SKILL.md b/skills/prowler-ui/SKILL.md index bde8c966db2..f0f2bae08e6 100644 --- a/skills/prowler-ui/SKILL.md +++ b/skills/prowler-ui/SKILL.md @@ -27,7 +27,7 @@ allowed-tools: Read, Edit, Write, Glob, Grep, Bash, WebFetch, WebSearch, Task ## Tech Stack (Versions) -``` +```text Next.js 16.2.3 | React 19.2.5 | Tailwind 4.1.18 | shadcn/ui Zod 4.1.11 | React Hook Form 7.62.0 | Zustand 5.0.8 NextAuth 5.0.0-beta.30 | Recharts 2.15.4 @@ -43,7 +43,7 @@ HeroUI 2.8.4 (LEGACY - do not add new components) ### Component Placement -``` +```text New feature UI? → shadcn/ui + Tailwind Existing HeroUI feature? → Keep HeroUI (don't mix) Used 1 feature? → features/{feature}/components/ @@ -54,7 +54,7 @@ Server component? → No directive needed ### Code Location -``` +```text Server action → actions/{feature}/{feature}.ts Data transform → actions/{feature}/{feature}.adapter.ts Types (shared 2+) → types/{domain}.ts @@ -69,7 +69,7 @@ HeroUI components → components/ui/ (LEGACY) ### Styling Decision -``` +```text Tailwind class exists? → className Dynamic value? → style prop Conditional styles? → cn() @@ -85,7 +85,7 @@ Recharts/library? → CHART_COLORS constant + var() ## Project Structure -``` +```text ui/ ├── app/ │ ├── (auth)/ # Auth pages (login, signup) diff --git a/skills/skill-creator/SKILL.md b/skills/skill-creator/SKILL.md index 11787abe2b0..41b8e7e67d1 100644 --- a/skills/skill-creator/SKILL.md +++ b/skills/skill-creator/SKILL.md @@ -29,7 +29,7 @@ Create a skill when: ## Skill Structure -``` +```text skills/{skill-name}/ ├── SKILL.md # Required - main skill file ├── assets/ # Optional - templates, schemas, examples @@ -43,7 +43,7 @@ skills/{skill-name}/ ## SKILL.md Template -```markdown +````markdown --- name: {skill-name} description: > @@ -77,7 +77,7 @@ metadata: - **Templates**: See [assets/](assets/) for {description} - **Documentation**: See [references/](references/) for local docs -``` +```` --- @@ -94,7 +94,7 @@ metadata: ## Decision: assets/ vs references/ -``` +```text Need code templates? → assets/ Need JSON schemas? → assets/ Need example configs? → assets/ @@ -108,7 +108,7 @@ Link to external guides? → references/ (with local path) ## Decision: Prowler-Specific vs Generic -``` +```text Patterns apply to ANY project? → Generic skill (e.g., pytest, typescript) Patterns are Prowler-specific? → prowler-{name} skill Generic skill needs Prowler info? → Add references/ pointing to Prowler docs diff --git a/skills/skill-creator/assets/SKILL-TEMPLATE.md b/skills/skill-creator/assets/SKILL-TEMPLATE.md index 76392402454..581cafd9c44 100644 --- a/skills/skill-creator/assets/SKILL-TEMPLATE.md +++ b/skills/skill-creator/assets/SKILL-TEMPLATE.md @@ -38,7 +38,7 @@ Use this skill when: ## Decision Tree -``` +```text {Question 1}? → {Action A} {Question 2}? → {Action B} Otherwise → {Default action} diff --git a/skills/tailwind-4/SKILL.md b/skills/tailwind-4/SKILL.md index 51f57576af8..e67d2ea9445 100644 --- a/skills/tailwind-4/SKILL.md +++ b/skills/tailwind-4/SKILL.md @@ -14,7 +14,7 @@ allowed-tools: Read, Edit, Write, Glob, Grep, Bash, WebFetch, WebSearch, Task ## Styling Decision Tree -``` +```text Tailwind class exists? → className="..." Dynamic value? → style={{ width: `${x}%` }} Conditional styles? → cn("base", condition && "variant") diff --git a/skills/tdd/SKILL.md b/skills/tdd/SKILL.md index 0f84d5c5ed0..d62d3590534 100644 --- a/skills/tdd/SKILL.md +++ b/skills/tdd/SKILL.md @@ -20,7 +20,7 @@ allowed-tools: Read, Edit, Write, Glob, Grep, Bash, Task ## TDD Cycle (MANDATORY) -``` +```text +-----------------------------------------+ | RED -> GREEN -> REFACTOR | | ^ | | @@ -28,7 +28,7 @@ allowed-tools: Read, Edit, Write, Glob, Grep, Bash, Task +-----------------------------------------+ ``` -**The question is NOT "should I write tests?" but "what tests do I need?"** +The question is NOT "should I write tests?" but "what tests do I need?" --- @@ -94,7 +94,7 @@ uv run pytest api/src/backend/api/tests/test_models.py -v ### Decision Tree (All Stacks) -``` +```text +------------------------------------------+ | Does test file exist for this code? | +----------+-----------------------+-------+ @@ -122,7 +122,7 @@ uv run pytest api/src/backend/api/tests/test_models.py -v ### For NEW Functionality -**UI (Vitest)** +#### UI (Vitest) ```typescript describe("PriceCalculator", () => { @@ -139,7 +139,7 @@ describe("PriceCalculator", () => { }); ``` -**SDK (pytest)** +#### SDK (pytest) ```python class Test_ec2_ami_public: @@ -159,7 +159,7 @@ class Test_ec2_ami_public: assert len(result) == 0 ``` -**API (pytest-django)** +#### API (pytest-django) ```python @pytest.mark.django_db @@ -192,18 +192,18 @@ Write a test that **reproduces the bug** first: **API:** `assert response.status_code == 403 # Currently returns 200` -**Run -> Should FAIL (reproducing the bug)** +Run -> Should FAIL (reproducing the bug). ### For REFACTORING Capture ALL current behavior BEFORE refactoring: -``` +```text # Any stack: run ALL existing tests, they should PASS # This is your safety net - if any fail after refactoring, you broke something ``` -**Run -> All should PASS (baseline)** +Run -> All should PASS (baseline). --- @@ -288,13 +288,13 @@ Tests GREEN -> Improve code quality WITHOUT changing behavior. - Add types/validation - Reduce duplication -**Run tests after EACH change -> Must stay GREEN** +Run tests after EACH change -> Must stay GREEN. --- ## Quick Reference -``` +```text +------------------------------------------------+ | TDD WORKFLOW | +------------------------------------------------+ @@ -320,7 +320,7 @@ Tests GREEN -> Improve code quality WITHOUT changing behavior. ## Anti-Patterns (NEVER DO) -``` +```python # ANY language: # 1. Code first, tests after diff --git a/skills/vitest/SKILL.md b/skills/vitest/SKILL.md index 11190cbaef3..29ad237a3e3 100644 --- a/skills/vitest/SKILL.md +++ b/skills/vitest/SKILL.md @@ -181,7 +181,7 @@ expect(screen.getByRole("button")).toBeDisabled(); ## File Organization -``` +```text components/ ├── Button/ │ ├── Button.tsx diff --git a/ui/AGENTS.md b/ui/AGENTS.md index 43a26c74f9d..55b62045ace 100644 --- a/ui/AGENTS.md +++ b/ui/AGENTS.md @@ -15,7 +15,7 @@ > - [`vitest`](../skills/vitest/SKILL.md) - Unit testing with React Testing Library > - [`tdd`](../skills/tdd/SKILL.md) - TDD workflow (MANDATORY for UI tasks) -### Auto-invoke Skills +## Auto-invoke Skills When performing these actions, ALWAYS invoke the corresponding skill FIRST: @@ -89,7 +89,7 @@ When performing these actions, ALWAYS invoke the corresponding skill FIRST: ### Component Placement -``` +```text New/Existing UI? → shadcn/ui + Tailwind (NEVER HeroUI for new code) Used 1 feature? → features/{feature}/components | Used 2+? → components/{domain}/ Needs state/hooks? → "use client" | Server component? → No directive @@ -97,7 +97,7 @@ Needs state/hooks? → "use client" | Server component? → No directive ### Code Location -``` +```text Server action → actions/{feature}/{feature}.ts Data transform → actions/{feature}/{feature}.adapter.ts Types (shared 2+) → types/{domain}.ts | Types (local 1) → {feature}/types.ts @@ -193,7 +193,7 @@ Zod 4.1.11 | React Hook Form 7.62.0 | Zustand 5.0.8 | NextAuth 5.0.0-beta.30 | R ## PROJECT STRUCTURE -``` +```text ui/ ├── app/(auth)/ # Auth pages ├── app/(prowler)/ # Main app: compliance, findings, providers, scans diff --git a/ui/components/shadcn/README.md b/ui/components/shadcn/README.md index 06b9183408b..05f27c7d3f4 100644 --- a/ui/components/shadcn/README.md +++ b/ui/components/shadcn/README.md @@ -6,7 +6,7 @@ This directory contains all shadcn/ui based components for the Prowler applicati Example of a custom component: -``` +```text shadcn/ ├── card/ │ ├── base-card/ diff --git a/ui/tests/auth/auth.md b/ui/tests/auth/auth.md index 91b34110d5b..a388958f3ac 100644 --- a/ui/tests/auth/auth.md +++ b/ui/tests/auth/auth.md @@ -21,7 +21,7 @@ - Application is running. - No active session (cookies cleared). -### Flow Steps: +### Flow Steps 1. Clear all cookies. 2. Navigate to /sign-in. @@ -29,7 +29,7 @@ 4. Navigate to /sign-up. 5. Verify page loads. -### Expected Result: +### Expected Result - Public routes are accessible without authentication. @@ -50,7 +50,7 @@ - Application is running. -### Flow Steps: +### Flow Steps 1. Log in with valid credentials. 2. Navigate to a protected route. @@ -58,7 +58,7 @@ 4. Navigate to another protected route. 5. Verify redirect to sign-in. -### Expected Result: +### Expected Result - Invalid session results in redirect to sign-in. @@ -79,13 +79,13 @@ - Application is running. -### Flow Steps: +### Flow Steps 1. Navigate to /sign-in with error=RefreshAccessTokenError query parameter. 2. Check for toast notification. 3. Verify form elements are still visible. -### Expected Result: +### Expected Result - Toast shows "Session Expired" message with "Please sign in again". - Sign-in form is displayed and functional. @@ -107,13 +107,13 @@ - Application is running. -### Flow Steps: +### Flow Steps 1. Navigate to /sign-in with error=MissingRefreshToken query parameter. 2. Check for toast notification. 3. Verify email input is visible. -### Expected Result: +### Expected Result - Toast shows "Session Error" message. - Sign-in form is displayed. @@ -135,12 +135,12 @@ - Application is running. -### Flow Steps: +### Flow Steps 1. Navigate to /sign-in with error=UnknownError query parameter. 2. Check for toast notification. -### Expected Result: +### Expected Result - Toast shows "Authentication Error" message with "Please sign in again". @@ -162,7 +162,7 @@ - Application is running. - Valid test user credentials. -### Flow Steps: +### Flow Steps 1. Log in with valid credentials. 2. Navigate to a protected route (/scans). @@ -171,7 +171,7 @@ 5. Navigate to another protected route (/providers) using fresh navigation. 6. Verify redirect to sign-in includes callbackUrl parameter. -### Expected Result: +### Expected Result - URL contains callbackUrl=/providers parameter. - User can sign in and be redirected back to the original destination. @@ -194,7 +194,7 @@ - Application is running. - Valid test user credentials. -### Flow Steps: +### Flow Steps 1. Log in with valid credentials. 2. Verify home page is loaded. @@ -202,7 +202,7 @@ 4. Reload the page. 5. Verify session is still valid with same user data. -### Expected Result: +### Expected Result - Session persists after reload. - User email, userId, and tenantId remain the same. @@ -225,14 +225,14 @@ - Application is running. - Valid test user credentials. -### Flow Steps: +### Flow Steps 1. Log in with valid credentials. 2. Capture initial session with permissions. 3. Reload the page. 4. Verify permissions match initial session. -### Expected Result: +### Expected Result - User permissions are identical before and after refresh. - User profile data (email, name, companyName) is preserved. @@ -255,14 +255,14 @@ - Application is running. - Valid test user credentials. -### Flow Steps: +### Flow Steps 1. Log in with valid credentials. 2. Verify session is valid. 3. Clear all cookies. 4. Check session status. -### Expected Result: +### Expected Result - Session returns null after cookies are cleared. - User is effectively logged out. diff --git a/ui/tests/invitation-accept/invitation-accept.md b/ui/tests/invitation-accept/invitation-accept.md index 88f3ee76bcd..ce53d48b917 100644 --- a/ui/tests/invitation-accept/invitation-accept.md +++ b/ui/tests/invitation-accept/invitation-accept.md @@ -24,7 +24,7 @@ redirects to `/sign-in` with a `callbackUrl` that preserves the invitation token - Application is running. - No active session (cookies cleared). -### Flow Steps: +### Flow Steps 1. Clear all cookies. 2. Navigate to `/invitation/accept?invitation_token=test-token`. @@ -32,7 +32,7 @@ redirects to `/sign-in` with a `callbackUrl` that preserves the invitation token 4. Click the "I have an account — Sign in" button. 5. Verify the redirect target and `callbackUrl` query param. -### Expected Result: +### Expected Result - Heading "You've Been Invited" is visible. - Description text "invited to join a tenant" is visible. @@ -41,7 +41,7 @@ redirects to `/sign-in` with a `callbackUrl` that preserves the invitation token - Decoded `callbackUrl` equals `/invitation/accept?invitation_token=test-token`. - Decoded `callbackUrl` contains `invitation_token=test-token`. -### Key verification points: +### Key verification points - `callbackUrl` preserves the original invitation path with token. @@ -65,7 +65,7 @@ form actually renders (no redirect loop back to `/invitation/accept`). - Application is running. - No active session (cookies cleared). -### Flow Steps: +### Flow Steps 1. Clear all cookies. 2. Navigate to `/invitation/accept?invitation_token=test-token`. @@ -73,17 +73,17 @@ form actually renders (no redirect loop back to `/invitation/accept`). 4. Click the button. 5. Verify the resulting URL and that the sign-up form is rendered. -### Expected Result: +### Expected Result - URL pathname is `/sign-up`. - Query param `invitation_token` equals `test-token`. - Sign-up form is rendered (email input and submit button visible). -### Key verification points: +### Key verification points - No redirect back to `/invitation/accept` (smart router does not loop). -### Notes: +### Notes - The legacy `action=signup` param is no longer emitted: the backward-compat redirect from `/sign-up?invitation_token=...` to `/invitation/accept` was @@ -111,7 +111,7 @@ that the "Go to Sign In" link redirects to `/sign-in`. - Application is running. - No active session (cookies cleared). -### Flow Steps: +### Flow Steps 1. Clear all cookies. 2. Navigate to `/invitation/accept` (no query params). @@ -119,13 +119,13 @@ that the "Go to Sign In" link redirects to `/sign-in`. 4. Click the "Go to Sign In" link. 5. Verify redirect to `/sign-in`. -### Expected Result: +### Expected Result - Heading "Invalid Invitation Link" is visible. - Description "No invitation token was provided" is visible. - "Go to Sign In" link is visible and clickable. - After click, URL matches `/sign-in`. -### Key verification points: +### Key verification points - Client-side render only: no API calls involved. diff --git a/ui/tests/invitations/invitations.md b/ui/tests/invitations/invitations.md index 51d78356df9..1c01499ea29 100644 --- a/ui/tests/invitations/invitations.md +++ b/ui/tests/invitations/invitations.md @@ -25,7 +25,7 @@ - `E2E_ORGANIZATION_ID` (expected organization for membership verification) - Application running with accessible UI/API endpoints -### Flow Steps: +### Flow Steps 1. Navigate to invitations page 2. Click "Send Invitation" button @@ -40,7 +40,7 @@ 11. Verify successful login 12. Navigate to user profile and verify `organizationId` matches `E2E_ORGANIZATION_ID` -### Expected Result: +### Expected Result - Invitation is created and a valid share URL is provided - Invited user can sign up successfully using the invitation link @@ -48,7 +48,7 @@ - Login succeeds with the new credentials - User profile shows membership in the expected organization -### Key verification points: +### Key verification points - Invitations page loads and displays the heading - Send Invitation form is visible (email + role select) @@ -58,7 +58,7 @@ - Login with the new account succeeds - Profile page shows the expected organization id -### Notes: +### Notes - Test uses a fresh browser context for the invitee to avoid admin session leakage - Email should be unique per run (the test uses a random suffix) diff --git a/ui/tests/providers/providers.md b/ui/tests/providers/providers.md index 1e0873d5a1b..4d04adaeca9 100644 --- a/ui/tests/providers/providers.md +++ b/ui/tests/providers/providers.md @@ -24,7 +24,7 @@ - Remove any existing provider with the same Account ID before starting the test - This test must be run serially and never in parallel with other tests, as it requires the Account ID not to be already registered beforehand. -### Flow Steps: +### Flow Steps 1. Navigate to providers page 2. Click "Add Provider" button @@ -36,14 +36,14 @@ 8. Verify redirect to Scans page 9. Verify scheduled scan status in Scans table (provider exists and scan name is "scheduled scan") -### Expected Result: +### Expected Result - AWS provider successfully added with static credentials - Initial scan launched successfully - User redirected to Scans page - Scheduled scan appears in Scans table with correct provider and scan name -### Key verification points: +### Key verification points - Provider page loads correctly - Connect account page displays AWS option @@ -53,7 +53,7 @@ - Provider exists in Scans table (verified by account ID) - Scan name field contains "scheduled scan" -### Notes: +### Notes - Test uses environment variables for AWS credentials - Provider cleanup performed before each test to ensure clean state @@ -80,7 +80,7 @@ - Remove any existing provider with the same Account ID before starting the test - This test must be run serially and never in parallel with other tests, as it requires the Account ID not to be already registered beforehand. -### Flow Steps: +### Flow Steps 1. Navigate to providers page 2. Click "Add Provider" button @@ -92,14 +92,14 @@ 8. Verify redirect to Scans page 9. Verify scheduled scan status in Scans table (provider exists and scan name is "scheduled scan") -### Expected Result: +### Expected Result - AWS provider successfully added with role credentials - Initial scan launched successfully - User redirected to Scans page - Scheduled scan appears in Scans table with correct provider and scan name -### Key verification points: +### Key verification points - Provider page loads correctly - Connect account page displays AWS option @@ -109,7 +109,7 @@ - Provider exists in Scans table (verified by account ID) - Scan name field contains "scheduled scan" -### Notes: +### Notes - Test uses environment variables for AWS credentials and role ARN - Provider cleanup performed before each test to ensure clean state @@ -137,7 +137,7 @@ - Remove any existing provider with the same Subscription ID before starting the test - This test must be run serially and never in parallel with other tests, as it requires the Subscription ID not to be already registered beforehand. -### Flow Steps: +### Flow Steps 1. Navigate to providers page 2. Click "Add Provider" button @@ -148,14 +148,14 @@ 7. Verify redirect to Scans page 8. Verify scheduled scan status in Scans table (provider exists and scan name is "scheduled scan") -### Expected Result: +### Expected Result - Azure provider successfully added with static credentials - Initial scan launched successfully - User redirected to Scans page - Scheduled scan appears in Scans table with correct provider and scan name -### Key verification points: +### Key verification points - Provider page loads correctly - Connect account page displays Azure option @@ -165,7 +165,7 @@ - Provider exists in Scans table (verified by subscription ID) - Scan name field contains "scheduled scan" -### Notes: +### Notes - Test uses environment variables for Azure credentials - Provider cleanup performed before each test to ensure clean state @@ -193,7 +193,7 @@ - Remove any existing provider with the same Domain ID before starting the test - This test must be run serially and never in parallel with other tests, as it requires the Domain ID not to be already registered beforehand. -### Flow Steps: +### Flow Steps 1. Navigate to providers page 2. Click "Add Provider" button @@ -205,14 +205,14 @@ 8. Verify redirect to Scans page 9. Verify scheduled scan status in Scans table (provider exists and scan name is "scheduled scan") -### Expected Result: +### Expected Result - M365 provider successfully added with static credentials - Initial scan launched successfully - User redirected to Scans page - Scheduled scan appears in Scans table with correct provider and scan name -### Key verification points: +### Key verification points - Provider page loads correctly - Connect account page displays M365 option @@ -222,7 +222,7 @@ - Provider exists in Scans table (verified by domain ID) - Scan name field contains "scheduled scan" -### Notes: +### Notes - Test uses environment variables for M365 credentials - Provider cleanup performed before each test to ensure clean state @@ -250,7 +250,7 @@ - Remove any existing provider with the same Domain ID before starting the test - This test must be run serially and never in parallel with other tests, as it requires the Domain ID not to be already registered beforehand. -### Flow Steps: +### Flow Steps 1. Navigate to providers page 2. Click "Add Provider" button @@ -262,14 +262,14 @@ 8. Verify redirect to Scans page 9. Verify scheduled scan status in Scans table (provider exists and scan name is "scheduled scan") -### Expected Result: +### Expected Result - M365 provider successfully added with certificate credentials - Initial scan launched successfully - User redirected to Scans page - Scheduled scan appears in Scans table with correct provider and scan name -### Key verification points: +### Key verification points - Provider page loads correctly - Connect account page displays M365 option @@ -279,7 +279,7 @@ - Provider exists in Scans table (verified by domain ID) - Scan name field contains "scheduled scan" -### Notes: +### Notes - Test uses environment variables for M365 certificate credentials - Provider cleanup performed before each test to ensure clean state @@ -308,7 +308,7 @@ - Remove any existing provider with the same Context before starting the test - This test must be run serially and never in parallel with other tests, as it requires the Context not to be already registered beforehand. -### Flow Steps: +### Flow Steps 1. Navigate to providers page 2. Click "Add Provider" button @@ -320,14 +320,14 @@ 8. Verify redirect to Scans page 9. Verify scheduled scan status in Scans table (provider exists and scan name is "scheduled scan") -### Expected Result: +### Expected Result - Kubernetes provider successfully added with kubeconfig content - Initial scan launched successfully - User redirected to Scans page - Scheduled scan appears in Scans table with correct provider and scan name -### Key verification points: +### Key verification points - Provider page loads correctly - Connect account page displays Kubernetes option @@ -339,7 +339,7 @@ - Provider exists in Scans table (verified by context) - Scan name field contains "scheduled scan" -### Notes: +### Notes - Test uses environment variables for Kubernetes context and kubeconfig file path - Kubeconfig content is read from file and used for authentication @@ -369,7 +369,7 @@ - Remove any existing provider with the same Project ID before starting the test - This test must be run serially and never in parallel with other tests, as it requires the Project ID not to be already registered beforehand. -### Flow Steps: +### Flow Steps 1. Navigate to providers page 2. Click "Add Provider" button @@ -381,14 +381,14 @@ 8. Verify redirect to Scans page 9. Verify scheduled scan status in Scans table (provider exists and scan name is "scheduled scan") -### Expected Result: +### Expected Result - GCP provider successfully added with service account key - Initial scan launched successfully - User redirected to Scans page - Scheduled scan appears in Scans table with correct provider and scan name -### Key verification points: +### Key verification points - Provider page loads correctly - Connect account page displays GCP option @@ -400,7 +400,7 @@ - Provider exists in Scans table (verified by project ID) - Scan name field contains "scheduled scan" -### Notes: +### Notes - Test uses environment variables for GCP project ID and service account key - Service account key is provided as base64 encoded JSON content @@ -431,7 +431,7 @@ - Remove any existing provider with the same Username before starting the test - This test must be run serially and never in parallel with other tests, as it requires the Username not to be already registered beforehand. -### Flow Steps: +### Flow Steps 1. Navigate to providers page 2. Click "Add Provider" button @@ -443,14 +443,14 @@ 8. Verify redirect to Scans page 9. Verify scheduled scan status in Scans table (provider exists and scan name is "scheduled scan") -### Expected Result: +### Expected Result - GitHub provider successfully added with personal access token - Initial scan launched successfully - User redirected to Scans page - Scheduled scan appears in Scans table with correct provider and scan name -### Key verification points: +### Key verification points - Provider page loads correctly - Connect account page displays GitHub option @@ -462,7 +462,7 @@ - Provider exists in Scans table (verified by username) - Scan name field contains "scheduled scan" -### Notes: +### Notes - Test uses environment variables for GitHub username and personal access token - Provider cleanup performed before each test to ensure clean state @@ -491,7 +491,7 @@ - Remove any existing provider with the same Username before starting the test - This test must be run serially and never in parallel with other tests, as it requires the Username not to be already registered beforehand. -### Flow Steps: +### Flow Steps 1. Navigate to providers page 2. Click "Add Provider" button @@ -503,14 +503,14 @@ 8. Verify redirect to Scans page 9. Verify scheduled scan status in Scans table (provider exists and scan name is "scheduled scan") -### Expected Result: +### Expected Result - GitHub provider successfully added with GitHub App credentials - Initial scan launched successfully - User redirected to Scans page - Scheduled scan appears in Scans table with correct provider and scan name -### Key verification points: +### Key verification points - Provider page loads correctly - Connect account page displays GitHub option @@ -522,7 +522,7 @@ - Provider exists in Scans table (verified by username) - Scan name field contains "scheduled scan" -### Notes: +### Notes - Test uses environment variables for GitHub username, App ID, and base64 encoded private key - Private key is base64 encoded and must be decoded before use @@ -552,7 +552,7 @@ - Remove any existing provider with the same Organization name before starting the test - This test must be run serially and never in parallel with other tests, as it requires the Organization name not to be already registered beforehand. -### Flow Steps: +### Flow Steps 1. Navigate to providers page 2. Click "Add Provider" button @@ -564,14 +564,14 @@ 8. Verify redirect to Scans page 9. Verify scheduled scan status in Scans table (provider exists and scan name is "scheduled scan") -### Expected Result: +### Expected Result - GitHub provider successfully added with organization personal access token - Initial scan launched successfully - User redirected to Scans page - Scheduled scan appears in Scans table with correct provider and scan name -### Key verification points: +### Key verification points - Provider page loads correctly - Connect account page displays GitHub option @@ -583,7 +583,7 @@ - Provider exists in Scans table (verified by organization name) - Scan name field contains "scheduled scan" -### Notes: +### Notes - Test uses environment variables for GitHub organization name and organization access token - Provider cleanup performed before each test to ensure clean state @@ -612,7 +612,7 @@ - Remove any existing provider with the same Account ID before starting the test - This test must be run serially and never in parallel with other tests, as it requires the Account ID not to be already registered beforehand -### Flow Steps: +### Flow Steps 1. Navigate to providers page 2. Click "Add Provider" button @@ -625,14 +625,14 @@ 9. Verify redirect to Scans page 10. Verify scheduled scan status in Scans table (provider exists and scan name is "scheduled scan") -### Expected Result: +### Expected Result - AWS provider successfully added using AWS SDK default credentials to assume the role - Initial scan launched successfully - User redirected to Scans page - Scheduled scan appears in Scans table with correct provider and scan name -### Key verification points: +### Key verification points - Provider page loads correctly - Connect account page displays AWS option @@ -643,7 +643,7 @@ - Provider exists in Scans table (verified by account ID) - Scan name field contains "scheduled scan" -### Notes: +### Notes - Test leverages AWS SDK default credential chain (environment-configured keys) for Access Key and Secret Key - Environment variable `E2E_AWS_PROVIDER_ROLE_ARN` must reference a valid assumable role @@ -671,7 +671,7 @@ - Remove any existing provider with the same Tenancy ID before starting the test - This test must be run serially and never in parallel with other tests, as it requires the Tenancy ID not to be already registered beforehand. -### Flow Steps: +### Flow Steps 1. Navigate to providers page 2. Click "Add Provider" button @@ -683,14 +683,14 @@ 8. Verify redirect to Scans page 9. Verify scheduled scan status in Scans table (provider exists and scan name is "scheduled scan") -### Expected Result: +### Expected Result - OCI provider successfully added with API Key credentials - Initial scan launched successfully - User redirected to Scans page - Scheduled scan appears in Scans table with correct provider and scan name -### Key verification points: +### Key verification points - Provider page loads correctly - Connect account page displays OCI option @@ -702,7 +702,7 @@ - Provider exists in Scans table (verified by tenancy ID) - Scan name field contains "scheduled scan" -### Notes: +### Notes - Test uses environment variables for OCI credentials - Provider cleanup performed before each test to ensure clean state @@ -730,7 +730,7 @@ - An OCI provider with the specified Tenancy ID must already exist (run PROVIDER-E2E-012 first) - This test must be run serially and never in parallel with other tests -### Flow Steps: +### Flow Steps 1. Navigate to providers page 2. Verify OCI provider exists in the table @@ -742,7 +742,7 @@ 8. Click Next to submit 9. Verify successful navigation to test connection page -### Expected Result: +### Expected Result - Update credentials page loads successfully - OCI credentials form is displayed with all required fields @@ -750,7 +750,7 @@ - Credentials can be updated and submitted - User is redirected to test connection page after successful update -### Key verification points: +### Key verification points - Provider page loads correctly - OCI provider row is visible in providers table @@ -760,7 +760,7 @@ - Form submission succeeds (no silent failures due to missing provider UID) - Successful redirect to test connection page -### Notes: +### Notes - Test uses same environment variables as PROVIDER-E2E-012 (add OCI provider) - Requires PROVIDER-E2E-012 to be run first to create the OCI provider @@ -788,7 +788,7 @@ - Remove any existing provider with the same Account ID before starting the test - This test must be run serially and never in parallel with other tests, as it requires the Account ID not to be already registered beforehand. -### Flow Steps: +### Flow Steps 1. Navigate to providers page 2. Click "Add Provider" button @@ -802,14 +802,14 @@ 10. Verify redirect to Scans page 11. Verify scheduled scan status in Scans table (provider exists and scan name is "scheduled scan") -### Expected Result: +### Expected Result - AlibabaCloud provider successfully added with static credentials - Initial scan launched successfully - User redirected to Scans page - Scheduled scan appears in Scans table with correct provider and scan name -### Key verification points: +### Key verification points - Provider page loads correctly - Connect account page displays AlibabaCloud option @@ -822,7 +822,7 @@ - Provider exists in Scans table (verified by account ID) - Scan name field contains "scheduled scan" -### Notes: +### Notes - Test uses environment variables for AlibabaCloud credentials - Provider cleanup performed before each test to ensure clean state @@ -850,7 +850,7 @@ - Remove any existing provider with the same Account ID before starting the test - This test must be run serially and never in parallel with other tests, as it requires the Account ID not to be already registered beforehand. -### Flow Steps: +### Flow Steps 1. Navigate to providers page 2. Click "Add Provider" button @@ -864,14 +864,14 @@ 10. Verify redirect to Scans page 11. Verify scheduled scan status in Scans table (provider exists and scan name is "scheduled scan") -### Expected Result: +### Expected Result - AlibabaCloud provider successfully added with RAM Role credentials - Initial scan launched successfully - User redirected to Scans page - Scheduled scan appears in Scans table with correct provider and scan name -### Key verification points: +### Key verification points - Provider page loads correctly - Connect account page displays AlibabaCloud option @@ -884,7 +884,7 @@ - Provider exists in Scans table (verified by account ID) - Scan name field contains "scheduled scan" -### Notes: +### Notes - Test uses environment variables for AlibabaCloud RAM Role credentials - Provider cleanup performed before each test to ensure clean state @@ -914,7 +914,7 @@ - StackSet must be deployed in AWS Organizations and expose a valid IAM Role ARN for Prowler - This test must be run serially and never in parallel with other tests, as it requires the Organization ID not to be already registered beforehand. -### Flow Steps: +### Flow Steps 1. Navigate to providers page 2. Click "Add Provider" button @@ -927,14 +927,14 @@ 9. Verify organization launch step, choose single scan schedule, and launch 10. Verify redirect to Scans page -### Expected Result: +### Expected Result - AWS Organizations flow completes successfully - Accounts are connected and launch step is displayed - Scan scheduling selection is applied - User is redirected to Scans page after launch -### Key verification points: +### Key verification points - Connect account page displays AWS option - Organizations method selector is available @@ -943,7 +943,7 @@ - Accounts connected launch step appears - Successful redirect to Scans page after launching -### Notes: +### Notes - Organization ID must follow AWS format (e.g., o-abc123def4) - Role ARN must belong to the StackSet deployment for Organizations flow @@ -970,7 +970,7 @@ - Remove any existing provider with the same Customer ID before starting the test - This test must be run serially and never in parallel with other tests, as it requires the Customer ID not to be already registered beforehand. -### Flow Steps: +### Flow Steps 1. Navigate to providers page 2. Click "Add Provider" button @@ -982,14 +982,14 @@ 8. Verify redirect to Scans page 9. Verify scheduled scan status in Scans table (provider exists and scan name is "scheduled scan") -### Expected Result: +### Expected Result - Google Workspace provider successfully added with Service Account credentials - Initial scan launched successfully - User redirected to Scans page - Scheduled scan appears in Scans table with correct provider and scan name -### Key verification points: +### Key verification points - Provider page loads correctly - Connect account page displays Google Workspace option @@ -1003,7 +1003,7 @@ - Provider exists in Scans table (verified by customer ID) - Scan name field contains "scheduled scan" -### Notes: +### Notes - Test uses environment variables for Google Workspace credentials - Service Account JSON is provided as multi-line JSON string (not base64 encoded) diff --git a/ui/tests/scans/scans.md b/ui/tests/scans/scans.md index 7b8735cc1fb..4e74cbd215b 100644 --- a/ui/tests/scans/scans.md +++ b/ui/tests/scans/scans.md @@ -23,7 +23,7 @@ - Remove any existing AWS provider with the same Account ID before starting the test - This test must be run serially and never in parallel with other tests, as it requires the Account ID Provider to be already registered. -### Flow Steps: +### Flow Steps 1. Navigate to Scans page 2. Open provider selector and choose the entry whose text contains E2E_AWS_PROVIDER_ACCOUNT_ID @@ -32,13 +32,13 @@ 5. Verify the success toast appears 6. Verify a row in the Scans table contains the provided scan label (or shows the new scan entry) -### Expected Result: +### Expected Result - Scan is launched successfully - Success toast is displayed to the user - Scans table displays the new scan entry (including the alias when provided) -### Key verification points: +### Key verification points - Scans page loads correctly - Provider select is available and lists the configured provider UID @@ -46,7 +46,7 @@ - Success toast message: "The scan was launched successfully." - Table contains a row with the scan label or new scan state (queued/available/executing) -### Notes: +### Notes - The table may take a short time to reflect the new scan; assertions look for a row containing the alias. - Provider cleanup performed before each test to ensure clean state diff --git a/ui/tests/sign-in-base/sign-in-base.md b/ui/tests/sign-in-base/sign-in-base.md index 5054fc998e4..5d590a4bc24 100644 --- a/ui/tests/sign-in-base/sign-in-base.md +++ b/ui/tests/sign-in-base/sign-in-base.md @@ -20,7 +20,7 @@ - Application is running. -### Flow Steps: +### Flow Steps 1. Navigate to the Sign in page. 2. Verify page is loaded. @@ -28,7 +28,7 @@ 4. Verify social buttons (Google, GitHub). 5. Verify navigation links. -### Expected Result: +### Expected Result - All form elements are visible and properly labeled. @@ -50,14 +50,14 @@ - Application is running. - Valid test user credentials are configured via `ADMIN_USER` and `ADMIN_PASSWORD` environment variables. -### Flow Steps: +### Flow Steps 1. Navigate to the Sign in page. 2. Enter valid email and password. 3. Click the login button. 4. Verify successful redirect to home page. -### Expected Result: +### Expected Result - User is authenticated and redirected to the home page. @@ -78,14 +78,14 @@ - Application is running. -### Flow Steps: +### Flow Steps 1. Navigate to the Sign in page. 2. Enter invalid email and password. 3. Click the login button. 4. Verify error message is displayed. -### Expected Result: +### Expected Result - Error message "Invalid email or password" is displayed. - User remains on the sign-in page. @@ -107,13 +107,13 @@ - Application is running. -### Flow Steps: +### Flow Steps 1. Navigate to the Sign in page. 2. Click the login button without filling any fields. 3. Verify validation errors are displayed. -### Expected Result: +### Expected Result - Form validation errors are shown. - User remains on the sign-in page. @@ -135,14 +135,14 @@ - Application is running. -### Flow Steps: +### Flow Steps 1. Navigate to the Sign in page. 2. Enter an invalid email format. 3. Submit the form. 4. Verify validation error is displayed. -### Expected Result: +### Expected Result - Email format validation error is shown. @@ -163,14 +163,14 @@ - Application is running. -### Flow Steps: +### Flow Steps 1. Navigate to the Sign in page. 2. Fill only the email field. 3. Submit the form. 4. Verify password required error is displayed. -### Expected Result: +### Expected Result - "Password is required" error is shown. @@ -191,7 +191,7 @@ - Application is running. -### Flow Steps: +### Flow Steps 1. Navigate to the Sign in page. 2. Click "Continue with SAML SSO" button. @@ -199,7 +199,7 @@ 4. Click back button. 5. Verify normal mode is restored. -### Expected Result: +### Expected Result - SAML mode toggles correctly. - Password field visibility changes accordingly. @@ -221,14 +221,14 @@ - Application is running. -### Flow Steps: +### Flow Steps 1. Navigate to the Sign in page. 2. Fill valid credentials. 3. Submit the form. 4. Verify loading state on button. -### Expected Result: +### Expected Result - Login button shows loading state (disabled with aria-disabled). @@ -249,14 +249,14 @@ - Application is running. -### Flow Steps: +### Flow Steps 1. Navigate to the Sign in page. 2. Toggle SAML mode. 3. Enter SAML email. 4. Submit the form. -### Expected Result: +### Expected Result - SAML flow is initiated (would redirect to IdP in real scenario). @@ -278,14 +278,14 @@ - Application is running. - Valid test user credentials. -### Flow Steps: +### Flow Steps 1. Log in with valid credentials. 2. Verify successful login. 3. Refresh the page. 4. Verify user is still logged in. -### Expected Result: +### Expected Result - Session persists after refresh. - User remains on the authenticated page. @@ -308,12 +308,12 @@ - Application is running. - No active session. -### Flow Steps: +### Flow Steps 1. Navigate directly to a protected route (e.g., /providers). 2. Verify redirect to sign-in page. -### Expected Result: +### Expected Result - User is redirected to /sign-in. @@ -335,7 +335,7 @@ - Application is running. - User is logged in. -### Flow Steps: +### Flow Steps 1. Log in with valid credentials. 2. Click logout/sign out. @@ -343,7 +343,7 @@ 4. Attempt to access protected route. 5. Verify redirect to sign-in. -### Expected Result: +### Expected Result - User is logged out. - Session is invalidated. @@ -366,7 +366,7 @@ - Application is running. -### Flow Steps: +### Flow Steps 1. Create authenticated context and log in. 2. Verify session exists. @@ -374,7 +374,7 @@ 4. Verify new context has no session. 5. Verify new context is redirected to sign-in. -### Expected Result: +### Expected Result - Sessions are isolated between contexts. - Unauthenticated context cannot access protected routes. @@ -396,13 +396,13 @@ - Application is running. -### Flow Steps: +### Flow Steps 1. Navigate to the Sign in page. 2. Click the "Sign up" link. 3. Verify redirect to sign-up page. -### Expected Result: +### Expected Result - User is navigated to /sign-up. @@ -423,13 +423,13 @@ - Application is running. -### Flow Steps: +### Flow Steps 1. Navigate to the Sign up page. 2. Click the login link. 3. Verify redirect to sign-in page. -### Expected Result: +### Expected Result - User is navigated to /sign-in. @@ -450,14 +450,14 @@ - Application is running. -### Flow Steps: +### Flow Steps 1. Navigate to the Sign in page. 2. Navigate to the Sign up page. 3. Click browser back button. 4. Verify return to sign-in page. -### Expected Result: +### Expected Result - Browser history navigation works correctly. @@ -478,13 +478,13 @@ - Application is running. -### Flow Steps: +### Flow Steps 1. Navigate to the Sign in page. 2. Use Tab key to navigate through form elements. 3. Verify focus moves correctly through elements. -### Expected Result: +### Expected Result - All interactive elements are reachable via keyboard. - Focus order is logical. @@ -506,12 +506,12 @@ - Application is running. -### Flow Steps: +### Flow Steps 1. Navigate to the Sign in page. 2. Verify ARIA labels on form elements. -### Expected Result: +### Expected Result - Email input has proper label. - Password input has proper label. diff --git a/ui/tests/sign-up/sign-up.md b/ui/tests/sign-up/sign-up.md index 8344a8dd437..542d1c07782 100644 --- a/ui/tests/sign-up/sign-up.md +++ b/ui/tests/sign-up/sign-up.md @@ -22,7 +22,7 @@ - No existing data in Prowler is required; the test can run on a clean state. - `E2E_NEW_USER_PASSWORD` environment variable must be set with a valid password for the test. -### Flow Steps: +### Flow Steps 1. Navigate to the Sign up page. 2. Fill the form with valid data (unique email, valid password, terms accepted). @@ -30,18 +30,18 @@ 4. Verify redirect to the Login page. 5. Log in with the newly created credentials. -### Expected Result: +### Expected Result - Sign-up succeeds and redirects to Login. - User can log in successfully using the created credentials and reach the home page. -### Key verification points: +### Key verification points - After submitting sign-up, the URL changes to `/sign-in`. - The newly created credentials can be used to sign in successfully. - After login, the user lands on the home (`/`) and main content is visible. -### Notes: +### Notes - Test data uses a random base36 suffix to avoid collisions with email. - The test requires the `E2E_NEW_USER_PASSWORD` environment variable to be set before running. diff --git a/util/prowler-bulk-provisioning/README.md b/util/prowler-bulk-provisioning/README.md index 544862b6c1b..ff55b72aac5 100644 --- a/util/prowler-bulk-provisioning/README.md +++ b/util/prowler-bulk-provisioning/README.md @@ -429,7 +429,7 @@ This is useful for: ### Example Output -``` +```text [1] ✅ Created provider (id=db9a8985-f9ec-4dd8-b5a0-e05ab3880bed) [1] ✅ Created secret (id=466f76c6-5878-4602-a4bc-13f9522c1fd2) [1] ✅ Connection test: Connected @@ -454,25 +454,25 @@ python prowler_bulk_provisioning.py providers.yaml --dry-run ### Common Issues 1. **Invalid API Key** - ``` + ```text Error: 401 Unauthorized Solution: Check your PROWLER_API_KEY environment variable or --api-key parameter ``` 2. **Network Timeouts** - ``` + ```text Error: Request timeout Solution: Increase --timeout value or check network connectivity ``` 3. **Invalid Provider Configuration** - ``` + ```text Error: Each item must include 'provider' and 'uid' Solution: Verify all required fields are present in your config file ``` 4. **File Not Found Errors** - ``` + ```text Error: No such file or directory Solution: Check file paths for credentials files (JSON keys, kubeconfig, etc.) ```