Skip to content
Open
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
7 changes: 3 additions & 4 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@ jobs:
targets: wasm32-unknown-unknown

- name: Install stellar-cli
uses: stellar/setup-stellar-cli@v1
with:
version: 21.6.0
run: cargo install --locked stellar-cli --version 21.6.0

- name: Setup Node.js
uses: actions/setup-node@v6
Expand Down Expand Up @@ -55,4 +53,5 @@ jobs:
- name: Export Logs on Failure
if: failure()
run: |
docker logs soroban-local
docker logs soroban-local || echo "Container soroban-local not found"
docker ps -a
2 changes: 1 addition & 1 deletion .github/workflows/node.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:

- name: Install packages
working-directory: ./${{ matrix.project }}
run: npm install
run: npm install --legacy-peer-deps

- name: Lint
working-directory: ./${{ matrix.project }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pr-size.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: PR Size Enforcement

on:
pull_request:
pull_request_target:
types: [opened, synchronize, reopened]

jobs:
Expand Down
4 changes: 1 addition & 3 deletions .github/workflows/secret-scan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,4 @@ jobs:
fetch-depth: 0

- name: Run Gitleaks
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: docker run -v ${{ github.workspace }}:/path zricethezav/gitleaks:latest detect --source="/path" -v
4 changes: 2 additions & 2 deletions .gitleaks.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ useDefault = true
[[rules]]
id = "sorolab-api-key"
description = "SoroLabs API Key pattern"
regex = '''(?i)(sorolab[_-]?api[_-]?key|sorolab[_-]?secret)\s*=\s*['\"]?[a-z0-9]{32,}['\"]?'''
secretGroup = 3
regex = '''(?i)(sorolab[_-]?api[_-]?key|sorolab[_-]?secret)\s*=\s*['\"]?([a-z0-9]{32,})['\"]?'''
secretGroup = 2
entropy = 5.0

# Allowlist patterns - files or paths to exclude
Expand Down
79 changes: 79 additions & 0 deletions indexer/GRAPHQL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# SoroTask GraphQL API

This document describes the GraphQL API built into the `indexer` service. It provides deep, field-level role-based access control, allowing consumers to securely query indexed contract events, tasks, and reconciliation logs.

## Overview

The API is powered by **Apollo Server** and **Express**, sitting directly on top of the `indexer`'s SQLite database to serve high-performance reads for the SoroTask platform.

### Roles and Authorization

The API supports complex authorization scenarios using JWT-based Context verification.

| Role | Access Level | Description |
| ---- | ------------ | ----------- |
| `ADMIN` | **3** | Full access to all resources. Can pause any task, view whitelists, and access all fields. |
| `OPERATOR` | **2** | Operational access. Can view reconciliation logs, but cannot pause arbitrary tasks. |
| `USER` | **1** | Standard access. Can view public tasks and events. Can pause their *own* tasks and view their *own* whitelists/block reasons. |
| `ANONYMOUS` | **0** | Unauthenticated. Can only view public information (Tasks, Events). |

### Endpoints
- **URL**: `http://localhost:4000/graphql`
- **Method**: `POST`
- **Headers**:
- `Authorization: Bearer <JWT_TOKEN>`
- `Content-Type: application/json`

---

## Schema Explorer

### Queries

#### `me: User`
Returns the currently authenticated user's details.

#### `tasks(limit: Int, offset: Int): [Task!]!`
Returns a paginated list of all registered tasks.

#### `task(id: ID!): Task`
Fetches a single task by ID. Note: Fields like `whitelist_json` and `blocked_by_json` are restricted to `ADMIN` or the task's Creator.

#### `events(task_id: Int, limit: Int, offset: Int): [Event!]!`
Fetches blockchain events. Optionally filter by a specific `task_id`.

#### `reconciliationLogs(task_id: Int, limit: Int, offset: Int): [ReconciliationLog!]!`
**(Requires OPERATOR or ADMIN role)**
Fetches background reconciliation logs.

---

### Mutations

#### `loginDemo(address: String!, role: String): AuthPayload!`
*Development/Testing only.* Generates a signed JWT for testing different roles.

#### `pauseTask(id: ID!): Task`
Sets a task to inactive (`is_active = 0`).
- **Authorization**: The caller must either be an `ADMIN` or the `Creator` of the task.

---

## Development and Testing

The GraphQL API is tightly integrated with the existing `indexer.db`. To run tests:
\`\`\`bash
cd indexer
npm test
\`\`\`

The test suite validates:
1. Role Hierarchy Enforcement
2. JWT Verification
3. Ownership Detection
4. Field-level isolation

---

## Integration with Infrastructure
The API server is initialized automatically alongside the indexer event loop inside `indexer/src/index.js` and defaults to port `4000`. You can change this via the `PORT` environment variable.
Loading
Loading