From 27c69d201fca2d1af4887f832647094f10663266 Mon Sep 17 00:00:00 2001 From: Evercatch Date: Fri, 13 Feb 2026 15:15:20 +0000 Subject: [PATCH] Initial commit --- .env.example | 39 ++++++++++ .gitea/pull_request_template.md | 68 +++++++++++++++++ .gitea/workflows/pr-management.yml | 76 +++++++++++++++++++ .gitea/workflows/pr-title-checker.yml | 105 ++++++++++++++++++++++++++ .gitignore | 47 ++++++++++++ CODEOWNERS | 5 ++ CONTRIBUTING.md | 63 ++++++++++++++++ LICENSE | 8 ++ README.md | 72 ++++++++++++++++++ SECURITY.md | 24 ++++++ 10 files changed, 507 insertions(+) create mode 100644 .env.example create mode 100644 .gitea/pull_request_template.md create mode 100644 .gitea/workflows/pr-management.yml create mode 100644 .gitea/workflows/pr-title-checker.yml create mode 100644 .gitignore create mode 100644 CODEOWNERS create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE create mode 100644 README.md create mode 100644 SECURITY.md diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..bb0023b --- /dev/null +++ b/.env.example @@ -0,0 +1,39 @@ +# ───────────────────────────────────────────── +# Evercatch — Environment Variables +# Copy this file to .env and fill in values. +# NEVER commit .env to version control. +# ───────────────────────────────────────────── + +# App +APP_ENV=development +APP_PORT=8000 +APP_SECRET_KEY=change-me + +# Database — PostgreSQL +POSTGRES_HOST=localhost +POSTGRES_PORT=5432 +POSTGRES_DB=evercatch +POSTGRES_USER=evercatch +POSTGRES_PASSWORD=change-me + +# Database — MongoDB +MONGO_URI=mongodb://localhost:27017 +MONGO_DB=evercatch_events + +# Redis +REDIS_URL=redis://localhost:6379 + +# Stripe +STRIPE_SECRET_KEY=sk_test_... +STRIPE_WEBHOOK_SECRET=whsec_... +STRIPE_PRICE_ID_INDIE=price_... +STRIPE_PRICE_ID_PRO=price_... +STRIPE_PRICE_ID_BUSINESS=price_... + +# Providers +SENDGRID_WEBHOOK_KEY= +SHOPIFY_WEBHOOK_SECRET= +GITHUB_WEBHOOK_SECRET= + +# Internal +BOT_ACCESS_TOKEN= diff --git a/.gitea/pull_request_template.md b/.gitea/pull_request_template.md new file mode 100644 index 0000000..f826965 --- /dev/null +++ b/.gitea/pull_request_template.md @@ -0,0 +1,68 @@ +### 🎟️ Evercatch Ticket + + + +Resolves: [EC-XXX]() + +### 🎯 Purpose & Impact + +> Please provide a clear, high-level summary of the change and its intended impact. Why is this change valuable to the Evercatch platform? + +### 🛠️ Key Changes + + + +- +- +- + +### 📸 Screenshots or Videos + + + +--- + +### ✅ Author's Definition of Done + + + +- [ ] I have performed a self-review of my own code. +- [ ] My code follows the style guidelines and architectural patterns of this project. +- [ ] I have added or updated tests that prove my feature works or my fix is effective. +- [ ] All new and existing tests pass locally with my changes. +- [ ] I have made corresponding changes to the documentation (if applicable). + +
+ +
+🔬 Reviewer's Guide & Additional Info (Click to Expand) + +--- + +#### Where should the reviewer start? + + + +#### 🏷️ Type of Change + + + +- [ ] **FEAT**: A new feature +- [ ] **FIX**: A bug fix +- [ ] **DOCS**: Documentation only changes +- [ ] **STYLE**: Code style changes (formatting, etc.) +- [ ] **REFACTOR**: A code change that neither fixes a bug nor adds a feature +- [ ] **PERF**: A code change that improves performance +- [ ] **TEST**: Adding missing tests or correcting existing tests +- [ ] **CHORE**: Changes to the build process or auxiliary tools + +--- + +
+ +--- + +![Evercatch Banner](https://placehold.co/1200x300/080c12/00e5ff?text=Evercatch&font=montserrat) diff --git a/.gitea/workflows/pr-management.yml b/.gitea/workflows/pr-management.yml new file mode 100644 index 0000000..f8a5cda --- /dev/null +++ b/.gitea/workflows/pr-management.yml @@ -0,0 +1,76 @@ +name: PR Management Bot + +on: + pull_request: + types: [opened, edited, synchronize, reopened] + branches: [main] + +jobs: + pr-bot: + runs-on: ubuntu-latest + env: + API_TOKEN: ${{ secrets.BOT_ACCESS_TOKEN }} + API_BASE_URL: https://git.psmattas.com/api/v1 + REPO: ${{ gitea.repository }} + PR_NUMBER: ${{ gitea.event.pull_request.number }} + PR_AUTHOR: ${{ gitea.actor }} + + steps: + - name: Check out repository + uses: https://gitea.com/actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Auto-label from commit messages + run: | + API_URL="$API_BASE_URL/repos/$REPO/pulls/$PR_NUMBER/commits" + MESSAGES=$(curl -s -H "Authorization: token $API_TOKEN" "$API_URL" | jq -r '.[].commit.message') + UNIQUE_TYPES=$(echo "$MESSAGES" | grep -oP '^EC-\d+: \K(FEAT|FIX|DOCS|STYLE|REFACTOR|PERF|TEST|CHORE)' | sort -u) + if [[ -z "$UNIQUE_TYPES" ]]; then exit 0; fi + LABELS_JSON=$(echo "$UNIQUE_TYPES" | jq -R '("type: " + (. | ascii_downcase))' | jq -s '{"labels": .}') + ISSUES_API_URL="$API_BASE_URL/repos/$REPO/issues/$PR_NUMBER/labels" + curl -s -f -X POST -H "Authorization: token $API_TOKEN" -H "Content-Type: application/json" -d "$LABELS_JSON" "$ISSUES_API_URL" + + - name: Auto-assign author + if: gitea.event.pull_request.assignees_count == 0 && gitea.actor != 'gitea-actions' && gitea.actor != 'EC-bot' + run: | + ISSUES_EDIT_API_URL="$API_BASE_URL/repos/$REPO/issues/$PR_NUMBER" + JSON_PAYLOAD=$(echo "$PR_AUTHOR" | jq -R '{"assignees": [.]}') + curl -s -f -X PATCH -H "Authorization: token $API_TOKEN" -H "Content-Type: application/json" -d "$JSON_PAYLOAD" "$ISSUES_EDIT_API_URL" + + - name: Add conflict label and comment + if: gitea.event.pull_request.merge_status == 'CONFLICT' + run: | + COMMENT_BODY="🚨 **Merge Conflict Detected** 🚨\n\nHi @$PR_AUTHOR, this pull request has merge conflicts with the \`main\` branch. Please resolve them by rebasing or merging \`main\` into your branch so the PR can be reviewed." + COMMENT_JSON=$(jq -n --arg body "$COMMENT_BODY" '{"body": $body}') + ISSUES_API_URL="$API_BASE_URL/repos/$REPO/issues/$PR_NUMBER/comments" + curl -s -f -X POST -H "Authorization: token $API_TOKEN" -H "Content-Type: application/json" -d "$COMMENT_JSON" "$ISSUES_API_URL" + + LABEL_JSON='{ "labels": ["status: needs-rebase"] }' + LABELS_API_URL="$API_BASE_URL/repos/$REPO/issues/$PR_NUMBER/labels" + curl -s -f -X POST -H "Authorization: token $API_TOKEN" -H "Content-Type: application/json" -d "$LABEL_JSON" "$LABELS_API_URL" + + - name: Remove 'needs-rebase' label if clean + if: gitea.event.pull_request.merge_status != 'CONFLICT' + run: | + LABEL_TO_REMOVE="status: needs-rebase" + ISSUES_API_URL="$API_BASE_URL/repos/$REPO/issues/$PR_NUMBER" + + CURRENT_LABELS_JSON=$(curl -s -H "Authorization: token $API_TOKEN" "$ISSUES_API_URL/labels") + LABEL_ID=$(echo "$CURRENT_LABELS_JSON" | jq --arg name "$LABEL_TO_REMOVE" '.[] | select(.name == $name) | .id') + + # Only try to delete the label if we found its ID + if [ -n "$LABEL_ID" ]; then + echo "Found and removing '$LABEL_TO_REMOVE' (ID: $LABEL_ID)..." + curl -s -f -X DELETE -H "Authorization: token $API_TOKEN" "$ISSUES_API_URL/labels/$LABEL_ID" + fi + + - name: Auto-assign reviewers + run: | + REVIEWERS_JSON='{ "reviewers": ["psmattas"] }' + + if [[ -n "$REVIEWERS_JSON" ]]; then + echo "Requesting review from: $REVIEWERS_JSON" + API_URL="$API_BASE_URL/repos/$REPO/pulls/$PR_NUMBER/requested_reviewers" + curl -s -f -X POST -H "Authorization: token $API_TOKEN" -H "Content-Type: application/json" -d "$REVIEWERS_JSON" "$API_URL" + fi \ No newline at end of file diff --git a/.gitea/workflows/pr-title-checker.yml b/.gitea/workflows/pr-title-checker.yml new file mode 100644 index 0000000..03bd706 --- /dev/null +++ b/.gitea/workflows/pr-title-checker.yml @@ -0,0 +1,105 @@ +name: PR Title Checker + +on: + pull_request: + types: [opened, edited, synchronize] + +jobs: + enforce-pr-title: + name: Validate PR Title Format + runs-on: ubuntu-latest + steps: + - name: Check PR Title and Manage Labels/Comments + env: + API_TOKEN: ${{ secrets.BOT_ACCESS_TOKEN }} + API_BASE_URL: https://git.psmattas.com/api/v1 + REPO: ${{ gitea.repository }} + PR_NUMBER: ${{ gitea.event.pull_request.number }} + PR_TITLE: ${{ gitea.event.pull_request.title }} + COMMENT_BODY_INVALID: | + Hi @${{ gitea.actor }}, thanks for the contribution! + + The title of this pull request does not follow the required format. This PR is currently **blocked from merging**. + + To fix this, please update the title to match the following structure: + **`EC-[JIRA_NUMBER]: [TYPE]: [Your Description]`** + + - **Valid [TYPE] values are:** `FEAT`, `FIX`, `DOCS`, `REFACTOR`, `STYLE`, `PERF`, `TEST`, `CHORE` + - **Example:** `EC-42: FEAT: Add new user login endpoint` + + Once you have updated the title, this check will re-run automatically and remove the blocking label. + + + COMMENT_BODY_WIP: | + Hi @${{ gitea.actor }}, this pull request has been marked as a **Work in Progress**. + + While in this state, it is **blocked from merging**. + + When the PR is ready for review, please remove the `WIP:` prefix from the title. This check will re-run automatically and remove the blocking label. + + + run: | + WIP_LABEL="status: work-in-progress" + INVALID_LABEL="INVALID-TITLE-DO-NOT-MERGE" + WIP_REGEX="^WIP:" + FORMAT_REGEX="^EC-[0-9]+: (FEAT|FIX|DOCS|REFACTOR|STYLE|PERF|TEST|CHORE): .+$" + ISSUES_API_URL="$API_BASE_URL/repos/$REPO/issues/$PR_NUMBER" + + if [ -z "$PR_NUMBER" ]; then + echo "::error::Could not determine PR Number. Aborting." + exit 1 + fi + + if [[ "$PR_TITLE" =~ $WIP_REGEX ]]; then + echo "ℹ️ PR is marked as a Work in Progress." + LABEL_JSON=$(echo "$WIP_LABEL" | jq -R '{"labels": [.]}') + curl -s -f -X POST -H "Authorization: token $API_TOKEN" -H "Content-Type: application/json" -d "$LABEL_JSON" "$ISSUES_API_URL/labels" + + WIP_COMMENT_IDENTIFIER="" + EXISTING_COMMENTS=$(curl -s -H "Authorization: token $API_TOKEN" "$ISSUES_API_URL/comments") + if ! echo "$EXISTING_COMMENTS" | grep -q "$WIP_COMMENT_IDENTIFIER"; then + echo "Posting WIP comment." + COMMENT_JSON=$(jq -n --arg body "$COMMENT_BODY_WIP" '{"body": $body}') + curl -s -f -X POST -H "Authorization: token $API_TOKEN" -H "Content-Type: application/json" -d "$COMMENT_JSON" "$ISSUES_API_URL/comments" + fi + exit 1 + + elif [[ "$PR_TITLE" =~ $FORMAT_REGEX ]]; then + echo "✅ PR title format is correct and not a WIP." + echo "Checking for labels to remove..." + + CURRENT_LABELS_JSON=$(curl -s -H "Authorization: token $API_TOKEN" "$ISSUES_API_URL/labels") + + INVALID_LABEL_ID=$(echo "$CURRENT_LABELS_JSON" | jq --arg name "$INVALID_LABEL" '.[] | select(.name == $name) | .id') + if [ -n "$INVALID_LABEL_ID" ]; then + echo "Found and removing '$INVALID_LABEL' (ID: $INVALID_LABEL_ID)..." + curl -s -f -X DELETE -H "Authorization: token $API_TOKEN" "$ISSUES_API_URL/labels/$INVALID_LABEL_ID" + fi + + WIP_LABEL_ID=$(echo "$CURRENT_LABELS_JSON" | jq --arg name "$WIP_LABEL" '.[] | select(.name == $name) | .id') + if [ -n "$WIP_LABEL_ID" ]; then + echo "Found and removing '$WIP_LABEL' (ID: $WIP_LABEL_ID)..." + curl -s -f -X DELETE -H "Authorization: token $API_TOKEN" "$ISSUES_API_URL/labels/$WIP_LABEL_ID" + fi + + exit 0 + + else + echo "❌ ERROR: PR title does not match the required format." + echo "Adding '$INVALID_LABEL' label..." + LABEL_JSON=$(echo "$INVALID_LABEL" | jq -R '{"labels": [.]}') + curl -s -f -X POST -H "Authorization: token $API_TOKEN" -H "Content-Type: application/json" -d "$LABEL_JSON" "$ISSUES_API_URL/labels" + + # Remove WIP label just in case + ENCODED_WIP_LABEL=$(python3 -c "import urllib.parse; print(urllib.parse.quote('$WIP_LABEL'))") + curl -s -X DELETE -H "Authorization: token $API_TOKEN" "$ISSUES_API_URL/labels/$ENCODED_WIP_LABEL" || true + + INVALID_COMMENT_IDENTIFIER="" + EXISTING_COMMENTS=$(curl -s -H "Authorization: token $API_TOKEN" "$ISSUES_API_URL/comments") + if ! echo "$EXISTING_COMMENTS" | grep -q "$INVALID_COMMENT_IDENTIFIER"; then + echo "Posting invalid title comment." + COMMENT_JSON=$(jq -n --arg body "$COMMENT_BODY_INVALID" '{"body": $body}') + curl -s -f -X POST -H "Authorization: token $API_TOKEN" -H "Content-Type: application/json" -d "$COMMENT_JSON" "$ISSUES_API_URL/comments" + fi + exit 1 + fi \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0be5d15 --- /dev/null +++ b/.gitignore @@ -0,0 +1,47 @@ +# Environment +.env +.env.* +!.env.example + +# Python +__pycache__/ +*.py[cod] +*.pyo +*.pyd +.Python +*.egg-info/ +dist/ +build/ +.venv/ +venv/ +*.log + +# Node / Angular +node_modules/ +dist/ +.angular/ +*.tsbuildinfo + +# Docker +.docker/ + +# IDE +.vscode/ +.idea/ +*.swp +*.swo +.DS_Store +Thumbs.db + +# Coverage +.coverage +htmlcov/ +coverage/ +*.lcov + +# Secrets +*.pem +*.key +*.p12 +*.pfx +secrets/ diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 0000000..225c647 --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1,5 @@ +# Evercatch Code Owners +# These users are automatically requested for review on PRs. +# Format: path @username + +* @psmattas diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..475de33 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,63 @@ +# Contributing to Evercatch + +Thank you for contributing. Please read this guide before opening issues or PRs. + +--- + +## 🌿 Branching + +Branch from `main` using the format `EC-ID-short-description`. + +```bash +git checkout -b EC-12-implement-stripe-inbound +``` + +--- + +## ✨ Commit Messages + +Follow the Conventional Commits standard prefixed with the issue ID. + +**Format:** `EC-00: (scope): message` + +| Type | Description | +| :--- | :--- | +| `feat` | New feature | +| `fix` | Bug fix | +| `docs` | Documentation | +| `style` | Formatting | +| `refactor` | Refactor | +| `perf` | Performance | +| `test` | Tests | +| `build` | Build system | +| `ci` | CI/CD config | +| `chore` | Maintenance | + +**Examples:** +- `EC-12: feat(webhooks): implement stripe inbound endpoint` +- `EC-18: fix(relay): resolve double-delivery on retry` + +--- + +## 🔍 Pull Requests + +- Link the issue in your PR description +- All CI checks must pass before requesting review +- Minimum one approval required to merge +- Keep PRs focused — one feature or fix per PR + +--- + +## 🏷️ Labels + +Apply the appropriate labels to your issue or PR: + +- `type:` — what kind of change is this +- `priority:` — how urgent is it +- `status:` — current state of the issue or PR + +--- + +## ❓ Questions + +Open an issue with the `type: chore` label or reach out via the org README. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..689c1be --- /dev/null +++ b/LICENSE @@ -0,0 +1,8 @@ +Copyright (c) 2026 Evercatch. All rights reserved. + +This software and its source code are proprietary and confidential. +Unauthorised copying, distribution, modification, or use of this software, +in whole or in part, via any medium, is strictly prohibited without the +prior written permission of Evercatch. + +For licensing enquiries, contact: legal@evercatch.io diff --git a/README.md b/README.md new file mode 100644 index 0000000..788863e --- /dev/null +++ b/README.md @@ -0,0 +1,72 @@ +# 📦 Repository Name + +> Short one-line description of what this repository does. + +--- + +## 🧭 Overview + +Describe what this service/module is responsible for within the Evercatch platform. + +--- + +## 🛠️ Tech Stack + +| Layer | Technology | +| :--- | :--- | +| Language | — | +| Framework | — | +| Key Dependencies | — | + +--- + +## 🚀 Getting Started + +### Prerequisites + +- Docker & Docker Compose +- Node.js / Python (specify version) + +### Local Development + +```bash +# Clone the repo +git clone https://git.psmattas.com/Evercatch/REPO_NAME.git +cd REPO_NAME + +# Copy environment variables +cp .env.example .env + +# Start services +docker compose up -d +``` + +--- + +## 🌿 Branching & Commits + +All work follows the Evercatch contribution guide defined in the org README. + +**Branch format:** `EC-ID-short-description` +**Commit format:** `EC-00: type(scope): message` + +See [Evercatch Org README](https://git.psmattas.com/Evercatch) for full conventions. + +--- + +## ⚙️ CI/CD + +Automated via Jenkins. Merges to `main` trigger staging deployments. + +| Pipeline | Status | +| :--- | :---: | +| Build | ![Build Status](https://img.shields.io/badge/build-pending-lightgrey) | +| Lint | ![Lint Status](https://img.shields.io/badge/lint-pending-lightgrey) | +| Test | ![Test Status](https://img.shields.io/badge/tests-pending-lightgrey) | + +--- + +## 📄 License + +**Copyright © 2026 Evercatch.** +Proprietary and confidential. Unauthorised distribution is strictly prohibited. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..088a2c2 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,24 @@ +# Security Policy + +## Reporting a Vulnerability + +If you discover a security vulnerability in any Evercatch repository, +please do **not** open a public issue. + +Report it privately to: **security@evercatch.io** + +Include: +- A description of the vulnerability +- Steps to reproduce +- Potential impact +- Any suggested fixes if available + +We will acknowledge receipt within 48 hours and aim to release a fix +within 14 days depending on severity. + +## Supported Versions + +| Version | Supported | +| :--- | :---: | +| Latest `main` | ✅ | +| Older releases | ❌ |