Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
46d8918
feat: enhance error handling and eligibility checks in task assignment
Keyrxng Nov 6, 2025
0c9d6b1
fix: improve error handling for task assignment and enhance test cove…
Keyrxng Nov 6, 2025
06bb5a7
refactor: reorganize task handling and introduce new command structure
Keyrxng Nov 6, 2025
188a428
chore: run format
Keyrxng Nov 6, 2025
c36eda1
chore: rename command-handler
Keyrxng Nov 6, 2025
823f03e
feat: implement public API for task management and recommendations
Keyrxng Nov 7, 2025
4bd4028
Merge remote-tracking branch 'upstream/development' into feat/public-api
Keyrxng Nov 7, 2025
3ace75d
test: fix account age and experience checks in user start/stop tests
Keyrxng Nov 7, 2025
0ab733d
refactor: extract account age and experience validation helpers
Keyrxng Nov 7, 2025
49f5b19
feat: add account age and experience checks to eligibility evaluation
Keyrxng Nov 7, 2025
ba2f991
test: mock date for account age validation in user start/stop tests
Keyrxng Nov 7, 2025
4f7efbb
feat: enhance context handling by supporting ShallowContext in adapte…
Keyrxng Nov 7, 2025
1c6248f
refactor: simplify startTask and evaluateStartEligibility by removing…
Keyrxng Nov 7, 2025
cb63eaa
feat: implement recommendation handling and validation execution for …
Keyrxng Nov 7, 2025
6c67e58
refactor: update getRecommendations to use ShallowContext and improve…
Keyrxng Nov 7, 2025
2b290cd
feat: add CORS support for public API and enhance environment variabl…
Keyrxng Nov 7, 2025
59e450a
test: enhance collaborator tests to validate pull request user assign…
Keyrxng Nov 7, 2025
3b46303
feat: enhance JWT verification and authentication flow for Supabase a…
Keyrxng Nov 7, 2025
9da5559
refactor: improve JWT verification and error handling in authenticati…
Keyrxng Nov 8, 2025
619b2fb
feat: add mock handlers for Supabase authentication and public API tests
Keyrxng Nov 8, 2025
2dd5c2e
refactor: remove API task recommendation handling related code and tests
Keyrxng Nov 8, 2025
ca05dc8
feat: enhance context building and organization handling in public AP…
Keyrxng Nov 8, 2025
fdca05d
feat: ESLint import plugin, deno scripts, kv namespace
Keyrxng Nov 16, 2025
0060d28
chore: reorganize imports across multiple files for improved clarity …
Keyrxng Nov 16, 2025
68c8cdf
feat: enhance CORS handling and environment validation in public API
Keyrxng Nov 16, 2025
faab88e
feat: enhance public API with environment validation and request body…
Keyrxng Nov 16, 2025
8c8a8c4
feat: refactor authentication flow in public API to improve error han…
Keyrxng Nov 16, 2025
667a34f
feat: implement rate limiting with Deno and Cloudflare KV support; re…
Keyrxng Nov 16, 2025
19249d3
feat: add configuration fetching, parsing, and validation for plugin …
Keyrxng Nov 16, 2025
f5c8f6e
chore: update public API tests to enhance request handling and valida…
Keyrxng Nov 16, 2025
3287827
refactor: update Jest configuration and dependencies
Keyrxng Nov 17, 2025
05ffa34
feat: integrate Octokit for repository interactions and enhance conte…
Keyrxng Nov 17, 2025
162d7d1
feat: update public API to use query parameters instead of request bo…
Keyrxng Nov 17, 2025
a6c2d7a
feat: enhance fetchRawConfigWithOctokit and extractAndValidatePluginS…
Keyrxng Nov 17, 2025
f40a4b6
feat: enhance mock handlers and tests for public API; update context …
Keyrxng Nov 17, 2025
fe44fc0
feat: update assignment period reasoning to include user-initiated un…
Keyrxng Nov 17, 2025
31f2e1d
chore: remove unused cross-env dependency from bun.lock
Keyrxng Nov 17, 2025
d694a13
chore: add mock handler for GitHub GraphQL API response in tests
Keyrxng Nov 17, 2025
1348a17
chore: integrate Supabase client and enhance test setup for improved …
Keyrxng Nov 17, 2025
78d2f72
chore: update http-trigger typecast, remove transformIgnorePatterns f…
Keyrxng Nov 17, 2025
45fe458
chore: [skip ci] updated manifest.json and dist build
ubq-testing[bot] Nov 17, 2025
876775c
chore: update API to support POST method and remove mode parameter fr…
Keyrxng Nov 17, 2025
ecb7ab3
chore: [skip ci] updated manifest.json and dist build
ubq-testing[bot] Nov 17, 2025
a6e7396
chore: remove typebox-validators dependency and improve error logging…
Keyrxng Nov 20, 2025
1a61487
chore: refactor error handling and improve assignment logic in task p…
Keyrxng Nov 20, 2025
8d1e469
chore: refactor start eligibility error handling and improve response…
Keyrxng Nov 20, 2025
1e819ca
chore: enhance task limit checks and improve error handling in experi…
Keyrxng Nov 20, 2025
928dc68
chore: update user XP values and adjust user login in pull request tests
Keyrxng Nov 20, 2025
63f86c2
chore: [skip ci] updated manifest.json and dist build
ubq-testing[bot] Nov 20, 2025
d732a5a
chore: enhance public API request handling by adding JSON body suppor…
Keyrxng Nov 20, 2025
f859fa5
chore: [skip ci] updated manifest.json and dist build
ubq-testing[bot] Nov 20, 2025
a4ac9a6
chore: enhance README with detailed public API documentation, includi…
Keyrxng Nov 20, 2025
4b5c44b
chore: refactor error handling in validate-or-execute to use try-catc…
Keyrxng Nov 20, 2025
54c0abd
chore: [skip ci] updated manifest.json and dist build
ubq-testing[bot] Nov 20, 2025
3db2db7
chore: implement CORS middleware using hono/cors for improved API req…
Keyrxng Nov 21, 2025
112f6b3
chore: update ESLint configuration to enforce no newlines between imp…
Keyrxng Nov 21, 2025
71397a0
Merge branch 'feat/public-api' of https://github.com/ubq-testing/comm…
Keyrxng Nov 21, 2025
9f42cfb
chore: [skip ci] updated manifest.json and dist build
ubq-testing[bot] Nov 21, 2025
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
1 change: 1 addition & 0 deletions .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"useGitignore": true,
"language": "en",
"words": [
"workerd",
"dataurl",
"devpool",
"knip",
Expand Down
2 changes: 1 addition & 1 deletion .github/knip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const config: KnipConfig = {
ignore: ["src/types/config.ts", "**/__mocks__/**", "**/__fixtures__/**", "src/worker.ts", "dist/**"],
ignoreExportsUsedInFile: true,
// eslint can also be safely ignored as per the docs: https://knip.dev/guides/handling-issues#eslint--jest
ignoreDependencies: ["eslint-config-prettier", "eslint-plugin-prettier", "ts-node", "@octokit/rest"],
ignoreDependencies: ["eslint-config-prettier", "eslint-plugin-prettier", "ts-node"],
eslint: true,
};

Expand Down
165 changes: 160 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ This plugin allows a hunter to begin a task as well as gracefully stop a task wi
- Built as a UbiquityOS plugin using TypeScript
- Reads wallet addresses for users
- Implements a webhook-based event system for GitHub interactions
- Provides a REST API for programmatic access to task operations
- Runs as a Cloudflare Worker using Hono for HTTP handling
- Supports JWT authentication and rate limiting for API access

### Core Components

Expand Down Expand Up @@ -59,6 +61,16 @@ Two main commands with complex validation:
- Wallet verification when required
- Review authority validation

#### 6. Public API

The plugin exposes a REST API for external integrations:

- **Authentication**: JWT-based authentication using Supabase tokens
- **Rate Limiting**: Per-user limits using Cloudflare KV or Deno KV storage
- **CORS Support**: Configurable cross-origin resource sharing
- **Dual Modes**: Validate-only (GET) and execute (POST) operations
- **Error Handling**: Structured JSON responses with detailed error messages

## Usage

### Start a task
Expand All @@ -69,7 +81,9 @@ To start a task, a hunter should use the `/start` command. This will assign them
- The issue is not already assigned
- The hunter has not reached the maximum number of concurrent tasks
- The command is not disabled at the repository or organization level
- The contributor meets any configured account age and XP requirements
- The contributor's GitHub account meets the minimum age requirement (default: 365.25 days)
- The contributor has sufficient XP for the task's priority level (if configured)
- The contributor has set their wallet address (if required)

### Stop a task

Expand All @@ -79,6 +93,120 @@ To stop a task, a hunter should use the `/stop` command. This will unassign them
- The command is not disabled at the repository or organization level
- The command is called on the issue, not the associated pull request

## Public API

The plugin provides a REST API endpoint for programmatic access to task eligibility checking and assignment functionality. This allows external applications to integrate with the start/stop workflow.

### Endpoint

**Base URL**: `/start`

### Authentication

All API requests require JWT authentication via the `Authorization` header:

```
Authorization: Bearer <jwt_token>
```

The JWT token should be obtained from Supabase authentication.

### Response

**Example Response:**

```json
{
ok: boolean;
errors: LogReturn[] | null;
warnings: LogReturn[] | null;
computed: {
deadline: string | null;
isTaskStale: boolean | null;
wallet: string | null;
toAssign: string[];
assignedIssues: AssignedIssue[];
consideredCount: number;
senderRole: ReturnType<typeof getTransformedRole>;
};
};
```

### Methods

#### GET `/start` (Validate Mode)

Validates task eligibility without performing assignment.

**Query Parameters:**

- `userId` (required): GitHub user ID (numeric)
- `issueUrl` (required): Full GitHub issue URL

**Example Request:**

```bash
GET /start?userId=123456&issueUrl=https://github.com/owner/repo/issues/1
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6Ikp...
```

#### POST `/start` (Execute Mode)

Validates eligibility and performs task assignment.

**Request Body:**

```json
{
"userId": 123456,
"issueUrl": "https://github.com/owner/repo/issues/1"
}
```

**Example Request:**

```bash
POST /start
Content-Type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6Ikp...

{
"userId": 123456,
"issueUrl": "https://github.com/owner/repo/issues/1"
}
```

### Rate Limiting

- **Validate mode (GET)**: 10 requests per minute per user
- **Execute mode (POST)**: 3 requests per minute per user

Rate limited responses include:

```json
{
"ok": false,
"reasons": ["RateLimit: exceeded"],
"resetAt": 1703123456789
}
```

### CORS Support

The API supports CORS for cross-origin requests. Configure allowed origins via the `PUBLIC_API_ALLOWED_ORIGINS` environment variable.

### Development and Testing Notes

Contributors working on this API are likely to also be working on `work.ubq.fi`. If so, they should set up their own `devpool-directory` and integrate it properly. Otherwise, the system will attempt to create an Octokit instance through their GitHub app (kernel app) using ubiquity/partner issues, which will fail since the app is not installed on those repositories.

To successfully QA this API as a contributor:

- Only use `issueUrl` parameters that belong to repositories where your GitHub app is installed
- This can be achieved by hardcoding URLs on the client side or when creating request payloads
- Use repositories within your own organizations or test repositories where the app has been properly installed

Failure to use properly accessible repositories will result in `repoOctokit` instantiation failures. While this doesn't block functionality in development environments (as long as appropriate workarounds are implemented), it prevents proper testing of the full integration workflow.

### [Configuration](./src/types/plugin-input.ts)

#### Note: The command name is `"start"` when configuring your `.ubiquity-os.config.yml` file.
Expand All @@ -104,15 +232,23 @@ To configure your Ubiquity Kernel to run this plugin, add the following to the `
taskAccessControl:
usdPriceMax:
collaborator: 5000
contributor: 1000 # Set to -1 to disable collaborator tasks (only allow core operations)
contributor: 1000 # Set to -1 to disable contributor tasks (only allow core operations)
accountRequiredAge:
minimumDays: 30
minimumDays: 365.25 # Default: 365.25 days (1 year)
experience:
priorityThresholds:
- label: "Priority: 0 (Regression)"
minimumXp: -2000
- label: "Priority: 1 (Normal)"
minimumXp: -1000
- label: "Priority: 2 (Medium)"
minimumXp: 0
- label: "Priority: 3 (High)"
minimumXp: 500
- label: "Priority: 4 (Urgent)"
minimumXp: 1000
- label: "Priority: 4 (Urgent)"
minimumXp: 2000
- label: "Priority: 5 (Emergency)"
minimumXp: 3000
```

## Development
Expand Down Expand Up @@ -157,6 +293,25 @@ Run all formatting:
bun run format
```

## Environment Variables

### Required

- `APP_ID`: GitHub App ID
- `APP_PRIVATE_KEY`: GitHub App private key
- `SUPABASE_URL`: Supabase project URL
- `SUPABASE_KEY`: Supabase service role key
- `BOT_USER_ID`: Bot's GitHub user ID
- `KERNEL_PUBLIC_KEY`: Public key for webhook signature verification

### Optional

- `LOG_LEVEL`: Logging level (default: INFO)
- `XP_SERVICE_BASE_URL`: XP service URL (default: https://os-daemon-xp.ubq.fi)
- `PUBLIC_API_ALLOWED_ORIGINS`: Comma-separated list of allowed origins for CORS (default: localhost in dev)
- `RATE_LIMIT_KV`: Cloudflare KV namespace binding for rate limiting (optional, falls back to in-memory)
- `NODE_ENV`: Environment mode (development, production, test)

## Technical Dependencies

### Core
Expand Down
Loading