Skip to content

About

No description, website, or topics provided.

Resources

Stars

3 stars

Watchers

2 watching

Forks

Latest commit

 

History

1,396 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Topcoder Review API

Opportunities experience additions

Review API built on modern frameworks for managing all review-related Topcoder needs.

Use Node.js 26.5.1 (see .nvmrc) and pnpm 11.15.1 for local development and builds.

The Docker build and runtime stages use the same Alpine release. The runtime installs Alpine's available Node.js package within the build's Node.js major version, allowing minor, patch, and package revision updates without depending on older packages remaining available. This preserves dynamic linkage to patched system OpenSSL. The final image runs as the app user and excludes npm and pnpm.

Project setup

$ pnpm install

Compile and run the project

# development
$ pnpm run start

# watch mode
$ pnpm run start:dev

# production mode
$ pnpm run start:prod

Database

# run postgres in docker, or other approach
docker run -p 5432:5432  -e POSTGRES_PASSWORD=mysecretpassword postgres:14

# Configure the database connection URL (without schema parameter)
export DATABASE_URL="postgresql://postgres:mysecretpassword@localhost:5432/postgres"

# Configure the PostgreSQL schema (defaults to 'public' if not specified)
export POSTGRES_SCHEMA="public"

# run migration
npx prisma migrate dev

# seed data
npx prisma db seed
or
npx prisma migrate reset

# if you modify prisma schema, run migration again
# and it'll ask
# Enter a name for the new migration:
# just provide a good migration name, such as
#- `add_user_table`
#- `update_user_fields`
#- `create_posts_table`
#- `add_email_to_users`
#- `update_foreign_keys`

Schema Configuration

The application supports configurable PostgreSQL schemas through the POSTGRES_SCHEMA environment variable:

# Set the schema for development
export POSTGRES_SCHEMA="dev_schema"

# Set the schema for production
export POSTGRES_SCHEMA="prod_schema"

# If not specified, the application defaults to the 'public' schema

This allows you to:

  • Use different schemas for different environments (development, testing, production)
  • Isolate data for different instances of the application
  • Improve security by separating schemas based on environment

Data import

  • create a .env file mv .env.sample .env
  • update the postgres database url in .env file — DATABASE_URL="postgresql://postgres:mysecretpassword@localhost:5432/postgres"
  • set the PostgreSQL schema in .env file — POSTGRES_SCHEMA="public" (or your preferred schema name)
  • place all the legacy json files in the prisma/Scorecards directory or specify it in .env file — DATA_DIR=/path/to/Scorecards/folder/
  • install dependencies pnpm install
  • run the prisma migration npx prisma migrate dev
  • run the prisma seed npx prisma db seed
  • run the project pnpm run start

Design submission visibility

GET /v6/submissions?challengeId=... returns the configured review window to assigned Design screeners, checkpoint screeners, reviewers, and other review resources. A finite submissionLimit.count retains that many non-deleted submissions per member and exact submission type; checkpoint and final submissions are ranked independently. Missing or explicitly unlimited Design metadata keeps all non-deleted contest and checkpoint submissions visible. Malformed limits fall back to one per type. Selection happens before pagination and row-specific filters, and isLatest query flags cannot expand access beyond this window. Other types, including Final Fix, retain only the latest non-deleted row per member/type.

For visible Marathon Matches, all viewers, including anonymous and unregistered visitors, can request complete submission history by omitting isLatest. Challenge whitelist and group checks still run first, and private submission fields and artifact downloads retain their existing authorization. Explicit isLatest=true requests still return only the newest attempt per member/type, with full submission counts for the Opportunities History action.

Ordinary viewers of other challenge types retain latest-only access, and Development review resources keep the existing latest-only behavior. Owners requesting their own submissions, challenge copilots/managers, admins, project managers, and authorized machine clients retain their existing history access. Unavailable challenge or resource metadata does not grant broader access.

Three rules keep "latest-only" from hiding a member's own work:

  • Latest is per submission type. The canonical ranking partitions by challengeId, memberId, and type, so a Checkpoint Submission is never treated as an older attempt at a Contest Submission. Without this, a member who submitted in the final round of a two-round Design challenge lost their entire checkpoint round from every listing.
  • Privacy hides other people's history, never the caller's own. When latest-only is imposed on a challenge-scoped list rather than requested with isLatest, the caller still receives every submission they made themselves alongside everybody else's latest attempt. isLatest is then resolved per row instead of being assumed for the whole page. An explicit isLatest=true request (including the accepted TRUE and 1 aliases) returns only the latest attempt per member and type, including the caller's own submissions. This filter applies before pagination and counting, keeping Marathon Match Submissions rows and totals consistent before and after system testing. My Submissions and history requests without the flag retain the owner's full history, and a list already scoped to another memberId cannot be widened.
  • Reviewers keep what they reviewed. On the same imposed latest-only lists, a non-Design review resource (for example a First2Finish iterative reviewer) also receives every older attempt that already has a review by one of their resources. Without this, a submitter who failed an iterative review and resubmitted hid the first iterative review from the reviewer who scored it. The original score, review comments, and phase remain available on active and completed challenges, while the older attempt is marked isLatest=false. This also applies when the caller requests isLatest=false; explicit isLatest=true requests are not widened.

Run tests

# unit tests
$ pnpm run test

# e2e tests
$ pnpm run test:e2e

# test coverage
$ pnpm run test:cov

Review summation metadata

GET /v6/reviewSummations?metadata=true returns full metadata for admins, copilots, and machine clients. Member/submitter requests are limited to their own Marathon Match submissions and receive only progress metadata: testProcess, testProgress, testStatus, and safe count/timestamp fields in testProgressDetails. Per-seed scores and runner messages are not returned to competitors.

Submission responses include that same safe progress subset in nested review summations. The allowlisted process values are example, provisional, and system; raw test scores, seeds, and runner messages remain excluded.

Duplicate submission detection

GET /v6/submissions/{challengeId}/duplicates?submissionId=s1&submissionId=s2&crossChallenge=false returns submissions that share the exact sha256Hash of each requested submission.

  • submissionId is required and repeatable (a comma-separated list also works). Up to 100 ids per request, and every id must belong to {challengeId}.
  • crossChallenge defaults to false, which limits matches to {challengeId}. Set it to true to match across every challenge.
  • Access is limited to admins, machine clients with read:submission/all:submission, users holding the Project Manager role, and challenge Reviewer/Screener/Copilot/Manager resources.
  • The response is keyed by the requested submission id: { "s1": { "duplicates": [{ "submissionId", "challenge", "challengeTitle", "user", "submittedAt" }] } }, newest first. Submissions without a stored digest and DELETED submissions never match, so their lists come back empty.

Shared authentication and bus client (v6 refresh)

This branch uses tc-core-library-js 4.0.0-rc.1. Use its named createJwtVerifier / createJwtAuthenticator, createM2MClient, and createBusApiClient exports for shared authentication and bus API publishing. Service-specific roles, scopes, sessions and ownership checks remain in this service. The former bus wrapper dependency and local JWT cryptography must not be reintroduced.

RSA verification requires an exact configured issuer and audience (JWT_AUDIENCE for client tokens, AUTH0_AUDIENCE for machine/API tokens, or this service's explicit issuer-policy settings). HMAC secrets must be at least 32 bytes; no default secret is supplied. Expiry is enforced. Machine identity comes from the shared verifier, not the presence of scopes. Supply real development credentials through the service's existing environment configuration before deployment.

Bus publishers use createBusApiClient(config).postEvent(event) with the existing event envelope and optional key. Configure BUSAPI_URL for v6 and the existing OAuth credentials/token provider. The client uses bounded HTTPS requests and does not retry POSTs automatically. Application retry/outbox behavior remains local.

See the core migration guide for the API mapping, compatibility requirements, and rollout scope.

Alpine Node runtime packages

Container stages that install Node through APK constrain nodejs-current to the major version in NODE_VERSION, rather than an exact Alpine package revision. Alpine replaces older patch packages in its repositories; the compatible pin allows current security patches while a build-time check rejects a different Node major. The runtime keeps Alpine's dynamically linked Node and system libraries. Existing non-root users and application entrypoints are preserved. Build stages using a versioned official Node image retain their configured version, and pnpm build arguments are explicitly declared in the consuming stage.

Shared JWT deployment configuration

Development deployments load /config/common/global-appvar alongside the service's application parameters. JWT verification uses the same four settings as the other v6 services: VALID_ISSUERS (JSON array or comma-separated exact issuers), AUTH_SECRET (the existing shared HS256 signing key, at least 32 UTF-8 bytes), JWT_AUDIENCE (the browser application's audience), and AUTH0_AUDIENCE (the machine/API audience). RSA keys are fetched over HTTPS from the trusted issuer's /.well-known/jwks.json. Audience settings must reach the shared verifier; OAuth client IDs/secrets used for outbound requests are independent of JWT audiences.

The development browser audience is BXWXUWnilVUPdN01t2Se29Tw2ZYNGZvH, and the machine audience is https://m2m.topcoder-dev.com/. Use the existing Parameter Store secret rather than creating a per-service key. Reconcile any service-specific overrides of these four keys with the global values before deployment. Parameters are consumed on deployment/task startup; changing Parameter Store alone does not replace running tasks. Existing role, scope, ownership and active-session checks continue after JWT verification.

About

No description, website, or topics provided.

Resources

Stars

3 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages