Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
4225c6a
Configuration cleanup
jmgasper Jan 11, 2026
770b541
Build fix
jmgasper Jan 11, 2026
e821ce3
Runtime fixes
jmgasper Jan 11, 2026
c4b906c
Fix auth for anonymous access to get engagements list, fix Dockerfile
jmgasper Jan 12, 2026
0aea525
Docker issue
jmgasper Jan 12, 2026
1c5f516
Docker fix
jmgasper Jan 12, 2026
7a2145a
Tweaks to M2M auth setup for global vars
jmgasper Jan 12, 2026
13062ee
Fix prisma errors
jmgasper Jan 12, 2026
4ac8dce
Updates to more align with gigs
jmgasper Jan 12, 2026
fb095b7
Fix parameter sent to member-api-v6 when creating an application
jmgasper Jan 13, 2026
a969bf3
Tweak request format to allow multiple statuses
jmgasper Jan 13, 2026
93f8f5d
Updates for changes to work manager
jmgasper Jan 14, 2026
661510d
Tweaks to data model and services for new statuses, member assigments…
jmgasper Jan 15, 2026
2e628fc
Build fix
jmgasper Jan 15, 2026
dac9eb1
Build issueh
jmgasper Jan 15, 2026
da9124f
Assignment handling
jmgasper Jan 15, 2026
296a1da
Assignment updates for multi-member engagements
jmgasper Jan 15, 2026
f614418
PM-3420 PM-3422 PM-3423 PM-3427 PM-3428 PM-3430 PM-3431 PM-3432 PM-34…
jmgasper Jan 15, 2026
ea38f2c
Further bug fixes and handling of multi-member engagements
jmgasper Jan 16, 2026
3111d40
PM-3420 PM-3423, PM-3428, PM-3431, PM-3432, PM-3449
jmgasper Jan 19, 2026
2e25622
Allow numeric member IDs
jmgasper Jan 19, 2026
aa96c81
Fix up roles for access
jmgasper Jan 19, 2026
4d6935b
Update swaggerg
jmgasper Jan 19, 2026
ef00834
Raise Kafka message for skills assignment processing
jmgasper Jan 19, 2026
5eac44e
QA fixes and phone number to applications
jmgasper Jan 20, 2026
127986c
Clean up permissions for task manager role
jmgasper Jan 20, 2026
154f5a1
Member experience model and APIs
jmgasper Jan 20, 2026
467785a
Updates to swagger to require a duration field
jmgasper Jan 20, 2026
8b12cce
Fix up Task vs. Talent manager, and QA issues
jmgasper Jan 20, 2026
ef19df0
Allow for better feedback link functionality.
jmgasper Jan 21, 2026
7b6adbf
Use the correct env variables when creating the bus client
jmgasper Jan 21, 2026
450100b
Sorting to support community app engagements UI
jmgasper Jan 21, 2026
e142496
Better access checks and also support for searching by "Any" country …
jmgasper Jan 22, 2026
340fe3c
Generate external prisma client
vas3a Jan 28, 2026
152ec24
regenerate prisma-client
vas3a Jan 28, 2026
eddab32
regenerate prisma-client
vas3a Jan 28, 2026
eab8aae
Merge pull request #1 from topcoder-platform/prisma-client
kkartunov Jan 29, 2026
94c7b02
Engagements feedback and tweaks
jmgasper Jan 30, 2026
2463775
Merge branch 'develop' of github.com:topcoder-platform/engagements-ap…
jmgasper Jan 30, 2026
9cffa5d
Add mermaid diagram for flow
jmgasper Jan 30, 2026
e346719
Remove pending assignment status
jmgasper Jan 30, 2026
88782e7
review actions
kkartunov Jan 30, 2026
9550438
Swap application deadline with anticipated start date
jmgasper Feb 2, 2026
1a97171
Merge branch 'develop' of github.com:topcoder-platform/engagements-ap…
jmgasper Feb 2, 2026
38d139e
Engagements feedback updates
jmgasper Feb 2, 2026
aba4175
Additional fields for the assignment email.
jmgasper Feb 3, 2026
464dc69
Tweak to how we send the dates for the engagement selection email to …
jmgasper Feb 3, 2026
53aa2bf
Add some basic notifications for project admins when a user accepts /…
jmgasper Feb 3, 2026
27f78a8
Tweak for this to fix error in dev.
jmgasper Feb 3, 2026
43dea3f
Don't count completed, terminated, or offer rejected assignments when…
jmgasper Feb 3, 2026
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
25 changes: 20 additions & 5 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,32 @@ VALID_ISSUERS='["https://api.topcoder-dev.com"]'
# ========================================
# EXTERNAL SERVICES
# ========================================
TC_PROJECT_SERVICE_URL=http://localhost:8001/v5
STANDARDIZED_SKILLS_API_URL=http://localhost:3000
MEMBER_API_V6_URL=http://localhost:3001/v6
TOPCODER_API_URL_BASE=https://api.topcoder-dev.com
# Derived endpoints:
# - TC_PROJECT_SERVICE_URL: ${TOPCODER_API_URL_BASE}/v5/projects
# - STANDARDIZED_SKILLS_API_URL: ${TOPCODER_API_URL_BASE}/v5/standardized-skills
# - MEMBER_API_V6_URL: ${TOPCODER_API_URL_BASE}/v6/members
# PLATFORM UI BASE URL (used to generate anonymous feedback links)
PLATFORM_UI_BASE_URL=http://localhost:3001
# In production use https://platform.topcoder.com or https://platform.topcoder-dev.com

# ========================================
# EVENT BUS
# ========================================
BUS_API_URL=https://api.topcoder-dev.com/eventBus
KAFKA_ERROR_TOPIC=common.error.reporting

# ========================================
# EMAIL
# ========================================
SENDGRID_ASSIGNMENT_OFFER_TEMPLATE_ID=
SENDGRID_ASSIGNMENT_OFFER_ACCEPTED_TEMPLATE_ID=
SENDGRID_ASSIGNMENT_OFFER_REJECTED_TEMPLATE_ID=

# ========================================
# M2M AUTHENTICATION
# ========================================
M2M_AUTH_URL=https://topcoder-dev.auth0.com/oauth/token
AUTH0_URL=https://topcoder-dev.auth0.com/oauth/token
M2M_CLIENT_ID=your_client_id
M2M_CLIENT_SECRET=your_client_secret
M2M_AUDIENCE=https://api.topcoder-dev.com
AUTH0_AUDIENCE=https://api.topcoder-dev.com
21 changes: 21 additions & 0 deletions .github/workflows/code_reviewer.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: AI PR Reviewer

on:
pull_request:
types:
- opened
- synchronize
permissions:
pull-requests: write
jobs:
tc-ai-pr-review:
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v3

- name: TC AI PR Reviewer
uses: topcoder-platform/tc-ai-pr-reviewer@master
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # The GITHUB_TOKEN is there by default so you just need to keep it like it is and not necessarily need to add it as secret as it will throw an error. [More Details](https://docs.github.com/en/actions/security-guides/automatic-token-authentication#about-the-github_token-secret)
LAB45_API_KEY: ${{ secrets.LAB45_API_KEY }}
34 changes: 34 additions & 0 deletions .github/workflows/trivy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Trivy Scanner

permissions:
contents: read
security-events: write
on:
push:
branches:
- main
- dev
pull_request:
jobs:
trivy-scan:
name: Use Trivy
runs-on: ubuntu-24.04
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Run Trivy scanner in repo mode
uses: aquasecurity/trivy-action@0.33.1
with:
scan-type: "fs"
ignore-unfixed: true
format: "sarif"
output: "trivy-results.sarif"
severity: "CRITICAL,HIGH,UNKNOWN"
scanners: vuln,secret,misconfig,license
github-pat: ${{ secrets.GITHUB_TOKEN }}

- name: Upload Trivy scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: "trivy-results.sarif"
15 changes: 7 additions & 8 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ RUN npm install -g pnpm
COPY package.json pnpm-lock.yaml ./
# Install dependencies
RUN pnpm install --frozen-lockfile
COPY prisma ./prisma
COPY prisma.config.ts ./
RUN DATABASE_URL="postgresql://user:pass@localhost:5432/db?schema=public" pnpm prisma:generate

# ---- Build Stage ----
FROM base AS build
Expand All @@ -20,23 +23,19 @@ COPY . .
RUN pnpm build

# ---- Production Dependencies Stage ----
FROM base AS prod-deps
RUN npm install -g pnpm
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile --prod
FROM deps AS prod-deps
RUN pnpm prune --prod

# ---- Production Stage ----
FROM base AS production
ENV NODE_ENV production
ENV NODE_ENV=production
# Copy built application from the build stage
COPY --from=build /usr/src/app/dist ./dist
COPY --from=build /usr/src/app/sql ./sql
COPY --from=build /usr/src/app/data ./data
# Copy production dependencies from the deps stage
COPY --from=prod-deps /usr/src/app/node_modules ./node_modules

# Expose the application port
EXPOSE 3000

# The command to run the application
CMD ["node", "dist/main.js"]
CMD ["node", "dist/src/main.js"]
28 changes: 24 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,28 +37,48 @@ pnpm prisma:migrate
pnpm start:dev
```

## Configuration

Set the following environment variables (see `.env.example` for defaults):

| Variable | Description |
| --- | --- |
| `PORT` | Port the API listens on. |
| `DATABASE_URL` | PostgreSQL connection string used by Prisma. |
| `AUTH_SECRET` | Shared secret for JWT verification in local/dev scenarios. |
| `VALID_ISSUERS` | JSON array of allowed JWT issuers. |
| `TOPCODER_API_URL_BASE` | Base URL for Topcoder API services. |
| `PLATFORM_UI_BASE_URL` | Platform UI base URL used to generate anonymous feedback links. |
| `AUTH0_URL` | Auth0 token endpoint for M2M client credentials. |
| `M2M_CLIENT_ID` | Auth0 M2M client ID. |
| `M2M_CLIENT_SECRET` | Auth0 M2M client secret. |
| `AUTH0_AUDIENCE` | Auth0 audience for M2M tokens. |
| `SENDGRID_ASSIGNMENT_OFFER_TEMPLATE_ID` | SendGrid template ID for assignment offer emails. |
| `SENDGRID_ASSIGNMENT_OFFER_ACCEPTED_TEMPLATE_ID` | SendGrid template ID for assignment offer accepted emails. |
| `SENDGRID_ASSIGNMENT_OFFER_REJECTED_TEMPLATE_ID` | SendGrid template ID for assignment offer rejected emails. |

## Authentication

This API uses JWT authentication for user requests and supports M2M tokens for service-to-service access. Provide a Bearer token with the required scopes for protected endpoints.

## Security & Authorization

The API supports both user JWTs and machine-to-machine (M2M) tokens. User tokens are evaluated for roles and scopes, while M2M tokens rely on scopes. Administrators and Topcoder Project Managers have elevated privileges for management operations.
The API supports both user JWTs and machine-to-machine (M2M) tokens. User tokens are evaluated for roles and scopes, while M2M tokens rely on scopes. Administrators, Topcoder Project Managers, Topcoder Task Managers, and Topcoder Talent Managers have elevated privileges for management operations.

| Scope | Description | Endpoints |
| --- | --- | --- |
| `read:engagements` | View engagement listings and details | `GET /engagements`, `GET /engagements/:id`, `GET /engagements/active` |
| `write:engagements` | Create and update engagements | `POST /engagements`, `PUT /engagements/:id` |
| `manage:engagements` | Full engagement management including deletion | `DELETE /engagements/:id` |
| `read:applications` | View applications | `GET /applications`, `GET /applications/:id`, `GET /engagements/:id/applications` |
| `write:applications` | Submit and update applications | `POST /engagements/:id/applications`, `PATCH /applications/:id/status` |
| `write:applications` | Submit and update applications | `POST /engagements/:id/applications`, `PATCH /applications/:id/status`, `PATCH /applications/:id/approve` |

## M2M Token Configuration

M2M access uses Auth0 client credentials. Ensure the client is configured with the required scopes for the endpoints it calls. Tokens are validated by `tc-core-library-js` before being processed by the service.

## Role-Based Access

- Administrators and Topcoder Project Managers can bypass scope checks for most management operations.
- Administrators, Topcoder Project Managers, Topcoder Task Managers, and Topcoder Talent Managers can bypass scope checks for most management operations.
- Regular members can view engagements and manage their own applications.
- Project Managers can view and update application statuses for engagements they own.
- Project Managers can view and update application statuses for engagements they created, while Task Managers and Talent Managers can do so across engagements.
28 changes: 28 additions & 0 deletions docs/ASSIGNMENT_STATUS_FLOW.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Assignment Status Flow

This diagram describes how an engagement assignment moves between statuses and the conditions for each transition.

```mermaid
stateDiagram-v2
direction LR

[*] --> SELECTED
SELECTED : Initial state

SELECTED --> OFFER_REJECTED : Candidate rejects offer or rate
SELECTED --> ASSIGNED : Offer accepted\nagreementRate agreed\nTalent Manager activates

ASSIGNED : Engagement active
ASSIGNED : Payments allowed

ASSIGNED --> COMPLETED : Work finished and duration ends
ASSIGNED --> TERMINATED : Ended early by member or manager

OFFER_REJECTED : Terminal (negative)
COMPLETED : Terminal (positive)
TERMINATED : Early termination

OFFER_REJECTED --> [*]
COMPLETED --> [*]
TERMINATED --> [*]
```
2 changes: 1 addition & 1 deletion docs/AUTHENTICATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ M2M tokens are issued via the Auth0 client credentials flow. These tokens do not
| `write:engagements` | Create and update engagements | `POST /engagements`, `PUT /engagements/:id` |
| `manage:engagements` | Full engagement management including deletion | `DELETE /engagements/:id` |
| `read:applications` | View applications | `GET /applications`, `GET /applications/:id`, `GET /engagements/:id/applications` |
| `write:applications` | Submit and update applications | `POST /engagements/:id/applications`, `PATCH /applications/:id/status` |
| `write:applications` | Submit and update applications | `POST /engagements/:id/applications`, `PATCH /applications/:id/status`, `PATCH /applications/:id/approve` |

## Role-Based Access

Expand Down
13 changes: 8 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,20 @@
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand"
},
"dependencies": {
"@nestjs/cli": "^11.0.12",
"@nestjs/axios": "^3.0.0",
"@nestjs/cli": "^11.0.12",
"@nestjs/common": "^11.1.9",
"@nestjs/config": "^4.0.2",
"@nestjs/core": "^11.1.9",
"@nestjs/platform-express": "^11.1.9",
"@nestjs/schematics": "^11.0.9",
"@nestjs/swagger": "^11.2.3",
"@nestjs/testing": "^11.1.9",
"@prisma/adapter-pg": "^7.0.1",
"@prisma/client": "^7.0.1",
"@types/express": "^5.0.5",
"@types/jest": "^29.5.8",
"axios": "^1.13.2",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.3",
"date-fns": "^4.1.0",
Expand All @@ -34,10 +39,8 @@
"pg": "^8.16.3",
"reflect-metadata": "^0.1.13",
"rxjs": "^7.8.2",
"tc-core-library-js": "github:topcoder-platform/tc-core-library-js#master",
"@nestjs/schematics": "^11.0.9",
"@types/jest": "^29.5.8",
"@nestjs/testing": "^11.1.9"
"tc-bus-api-wrapper": "github:topcoder-platform/tc-bus-api-wrapper",
"tc-core-library-js": "github:topcoder-platform/tc-core-library-js#master"
},
"devDependencies": {
"@eslint/eslintrc": "^3.2.0",
Expand Down
1 change: 1 addition & 0 deletions packages/engagements-prisma-client/client.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./index"
5 changes: 5 additions & 0 deletions packages/engagements-prisma-client/client.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@

/* !!! This is code generated by Prisma. Do not edit directly. !!!
/* eslint-disable */
// biome-ignore-all lint: generated file
module.exports = { ...require('.') }
1 change: 1 addition & 0 deletions packages/engagements-prisma-client/default.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./index"
5 changes: 5 additions & 0 deletions packages/engagements-prisma-client/default.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@

/* !!! This is code generated by Prisma. Do not edit directly. !!!
/* eslint-disable */
// biome-ignore-all lint: generated file
module.exports = { ...require('#main-entry-point') }
1 change: 1 addition & 0 deletions packages/engagements-prisma-client/edge.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./default"
Loading