Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .github/workflows/protect-changelog.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: Protect CHANGELOG

on:
pull_request:
paths:
- "CHANGELOG.md"

jobs:
block-manual-changelog:
name: Block manual CHANGELOG edits
runs-on: ubuntu-latest
steps:
- name: Fail if CHANGELOG.md was manually edited
run: |
echo "❌ CHANGELOG.md must not be edited manually."
echo "It is auto-generated by git-cliff on release."
echo "Remove the CHANGELOG.md change from this PR."
exit 1
77 changes: 22 additions & 55 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,77 +1,44 @@
name: Semantic Release
name: Release

on:
push:
branches: [main]
tags:
- "v[0-9]+.[0-9]+.[0-9]*"

permissions:
contents: write
pull-requests: write

jobs:
release:
name: Semantic Release
changelog:
name: Generate Changelog & Release
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}

- name: Setup Node.js
uses: actions/setup-node@v4
- name: Generate changelog with git-cliff
uses: orhun/git-cliff-action@v3
id: cliff
with:
node-version: '18'

- name: Install semantic-release
run: npm install -g semantic-release @semantic-release/changelog @semantic-release/git @semantic-release/github
config: cliff.toml
args: --verbose --tag ${{ github.ref_name }}
env:
OUTPUT: CHANGELOG.md
GITHUB_REPO: ${{ github.repository }}

- name: Configure git
- name: Commit updated CHANGELOG.md
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add CHANGELOG.md
git diff --cached --quiet || git commit -m "chore(changelog): update for ${{ github.ref_name }} [skip ci]"
git push origin HEAD:main

- name: Create .releaserc.json
run: |
cat > .releaserc.json << 'EOF'
{
"branches": ["main"],
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
[
"@semantic-release/changelog",
{
"changelogFile": "CHANGELOG.md"
}
],
[
"@semantic-release/git",
{
"assets": ["CHANGELOG.md", "package.json", "package-lock.json"],
"message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
}
],
[
"@semantic-release/github",
{
"successComment": "🎉 This issue has been resolved in version ${nextRelease.version}",
"failTitle": "The automated release failed"
}
]
]
}
EOF

- name: Run semantic-release
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
body: ${{ steps.cliff.outputs.content }}
tag_name: ${{ github.ref_name }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: semantic-release

- name: Upload release artifacts
if: success()
uses: actions/upload-artifact@v4
with:
name: release-notes
path: CHANGELOG.md
if-no-files-found: ignore
196 changes: 196 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
# Contributing to PredictIQ

Thank you for your interest in contributing! This guide covers everything you need to get started.

## Table of Contents

- [Development Setup](#development-setup)
- [Branch Naming](#branch-naming)
- [Commit Conventions](#commit-conventions)
- [Pull Request Process](#pull-request-process)
- [Running Tests](#running-tests)
- [Code Style](#code-style)

---

## Development Setup

### Prerequisites

- [Rust](https://rustup.rs/) (stable toolchain)
- [Node.js](https://nodejs.org/) 18+
- [Docker](https://docs.docker.com/get-docker/) and Docker Compose
- [PostgreSQL](https://www.postgresql.org/) 15+ (or use the provided Docker Compose stack)

### Getting Started

```bash
# Clone the repository
git clone https://github.com/solutions-plug/predictIQ.git
cd predictIQ

# Start backing services (Postgres, Redis, etc.)
docker compose up -d

# API service
cd services/api
cp .env.example .env # fill in required values
cargo build

# Frontend
cd frontend
cp .env.example .env.local # fill in required values
npm install
npm run dev

# TTS service
cd services/tts
npm install
npm run dev
```

---

## Branch Naming

Use the following prefixes:

| Prefix | Purpose |
|--------|---------|
| `feat/` | New feature |
| `fix/` | Bug fix |
| `chore/` | Maintenance, dependency updates |
| `docs/` | Documentation only |
| `refactor/` | Code refactoring without behaviour change |
| `perf/` | Performance improvement |
| `ci/` | CI/CD changes |

Examples: `feat/market-resolution`, `fix/rate-limit-header`, `docs/contributing`

---

## Commit Conventions

This project uses **[Conventional Commits](https://www.conventionalcommits.org/)**.
The CHANGELOG is **auto-generated** from commit messages via [git-cliff](https://git-cliff.org/) — do not edit `CHANGELOG.md` manually.

### Format

```
<type>(<scope>): <short description>

[optional body]

[optional footer(s)]
```

### Types

| Type | When to use |
|------|-------------|
| `feat` | A new feature (triggers a minor version bump) |
| `fix` | A bug fix (triggers a patch version bump) |
| `docs` | Documentation changes only |
| `chore` | Build process, dependency updates, tooling |
| `refactor` | Code change that neither fixes a bug nor adds a feature |
| `perf` | Performance improvement |
| `test` | Adding or updating tests |
| `ci` | CI/CD configuration changes |

Append `!` after the type/scope for **breaking changes** (triggers a major version bump):

```
feat(api)!: remove deprecated /v0 endpoints
```

### Examples

```
feat(markets): add oracle result caching
fix(newsletter): handle duplicate subscription gracefully
docs(api): document rate-limit response headers
chore(deps): bump axum to 0.7.5
```

---

## Pull Request Process

1. Fork the repository and create your branch from `main`.
2. Ensure all tests pass locally (see [Running Tests](#running-tests)).
3. Keep commits focused — one logical change per commit.
4. Open a PR against `main` with a clear title following the commit convention.
5. Fill in the PR description:
- **What** changed and **why**
- How to test the change
- Any breaking changes or migration steps
6. Link related issues using `Closes #<issue>` in the PR description.
7. At least one approval is required before merging.
8. Squash-merge is preferred to keep the history clean.

### PR Checklist

- [ ] Branch is up to date with `main`
- [ ] Commit messages follow Conventional Commits
- [ ] Tests added or updated for the change
- [ ] Documentation updated if behaviour changed
- [ ] No secrets or credentials committed
- [ ] `CHANGELOG.md` **not** manually edited

---

## Running Tests

### API (Rust)

```bash
cd services/api
cargo test
```

### Frontend (Next.js)

```bash
cd frontend
npm test # unit tests (Jest)
npm run test:e2e # end-to-end tests (Playwright)
```

### TTS Service

```bash
cd services/tts
npm test
```

### Smart Contracts

```bash
cd contracts/predict-iq
make test
```

---

## Code Style

### Rust

- Follow `rustfmt` defaults — run `cargo fmt` before committing.
- Lint with `cargo clippy -- -D warnings`.

### TypeScript / JavaScript

- ESLint and Prettier are configured in the `frontend/` directory.
- Run `npm run lint` and `npm run format` before committing.

### YAML / Markdown

- Keep line length reasonable (80–100 characters).
- Use 2-space indentation for YAML.

---

## Questions?

Open an issue or start a discussion on [GitHub](https://github.com/solutions-plug/predictIQ/issues).
69 changes: 69 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Security Policy

## Supported Versions

Only the latest release of PredictIQ receives security fixes.

| Version | Supported |
|---------|-----------|
| Latest | ✅ Yes |
| Older | ❌ No |

## Reporting a Vulnerability

**Please do not open a public GitHub issue for security vulnerabilities.**

Use one of the following channels:

1. **GitHub Private Vulnerability Reporting** (preferred) — click the
[Report a vulnerability](../../security/advisories/new) button on the
Security tab of this repository.
2. **Email** — send details to `security@predictiq.io` with the subject line
`[SECURITY] <brief description>`.

### What to include

- A clear description of the vulnerability and its potential impact
- Steps to reproduce or a proof-of-concept (if available)
- Affected component(s) and version(s)
- Any suggested mitigations

## Response Timeline

| Milestone | Target |
|-----------|--------|
| Acknowledgement | Within **2 business days** |
| Initial assessment | Within **5 business days** |
| Fix or mitigation | Within **30 days** for critical/high; **90 days** for medium/low |
| Public disclosure | After a fix is available and affected users have had time to update |

We follow [coordinated disclosure](https://en.wikipedia.org/wiki/Coordinated_vulnerability_disclosure). We will notify you before any public disclosure and credit you in the release notes unless you prefer to remain anonymous.

## Disclosure Policy

- Vulnerabilities are kept confidential until a fix is released.
- We will publish a security advisory on GitHub after the fix is deployed.
- We ask reporters to refrain from public disclosure until we have released a fix or the agreed embargo period has passed.

## Scope

The following are **in scope**:

- `services/api` — Rust API backend
- `services/tts` — TTS microservice
- `frontend` — Next.js frontend
- `contracts/predict-iq` — Soroban smart contracts
- CI/CD pipelines and infrastructure-as-code in this repository

The following are **out of scope**:

- Third-party services (SendGrid, Stellar network, Pyth Network)
- Denial-of-service attacks without a demonstrated security impact
- Issues already reported or known

## Security Best Practices for Contributors

- Never commit secrets, API keys, or credentials — use environment variables.
- Follow the principle of least privilege when adding new permissions.
- Validate and sanitise all external input.
- Keep dependencies up to date; dependency-scan CI runs on every PR.
Loading