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
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
26.5.0
26.5.1
26 changes: 25 additions & 1 deletion ReadMe.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Technology Stack

- Node.js 26.5.0 (use the version pinned in `.nvmrc`)
- Node.js 26.5.1 (use the version pinned in `.nvmrc`)
- TypeScript and NestJS 11, with the established Express routes mounted through Nest
- Prisma ORM 7 with the PostgreSQL driver adapter
- pnpm 11.15.1
Expand All @@ -26,6 +26,30 @@ pnpm start
For development with TypeScript watch mode, use `pnpm start:dev`. Production runs the
compiled NestJS entrypoint at `dist/main.js`.

## Copilot History Regression Tests

Copilot profile summaries, challenge history, and track totals include only
completed or cancelled challenges. Fulfillment is completed challenges divided
by completed plus cancelled challenges, excluding client-request cancellations
from the denominator. Client-request cancellations remain visible in history.
Drafts and other non-terminal challenges, including active challenges in post
mortem, are excluded from all Copilot counts. Reviewer status handling is unchanged.

The PostgreSQL regression suite executes the service's real SQL against minimal
fixtures in an empty test database. It verifies the PM-5966 clarification example,
all cancellation types, empty fulfillment denominators, visibility, and Reviewer
behavior. Both schemas and all fixtures are created in a transaction and rolled
back afterward; setup fails if either schema already exists.

```bash
nvm use
SPECIAL_ROLE_TEST_DB_URL=postgresql://user:password@localhost:5432/member_test \
pnpm exec mocha --require ts-node/register/transpile-only test/integration/SpecialRoleService.test.js
```

The suite is skipped when `SPECIAL_ROLE_TEST_DB_URL` is unset. The existing
isolated service tests remain available through `pnpm test`.

## Database Setup

Please setup PostgreSQL first. If you are using docker, you can run:
Expand Down
11 changes: 6 additions & 5 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# syntax=docker/dockerfile:1.7

# Keep a Debian/glibc build because upstream generated Prisma clients ship Debian engines.
FROM node:26.5.0-bookworm-slim AS build-base
FROM node:26.5.1-bookworm-slim AS build-base

WORKDIR /member-api-v6
RUN apt-get update \
Expand Down Expand Up @@ -34,12 +34,13 @@ RUN sh docker/prune-internal-api-packages.sh \

# The pinned Wolfi/glibc runtime supports the checked-in Debian/OpenSSL 3 Prisma
# engines without shipping a shell, package manager, or build toolchain.
FROM cgr.dev/chainguard/node:latest@sha256:c002402b355201714dfbeb3b1a7ca99152cccced4b334496db2442a3a9bf4883 AS runtime
FROM cgr.dev/chainguard/node:latest@sha256:f819ce9bc54ff2a771a6849ec8453aaab9bb697873f3f6b91039ed07a3626748 AS runtime

# The upstream minimal Node image currently includes npm launchers. Remove them
# and their package payload with Node itself; this image intentionally has no shell.
# The pinned runtime includes maintenance utilities that the service does not use.
# Remove every executable except Node, plus the global npm/node-gyp payload, so
# the final image has no shell, package manager, or build toolchain.
USER 0
RUN ["/usr/bin/node", "-e", "const fs=require('node:fs'); for (const target of ['/usr/bin/npm','/usr/bin/npx','/usr/bin/corepack','/usr/lib/node_modules/npm','/usr/lib/node_modules/corepack']) fs.rmSync(target,{force:true,recursive:true})"]
RUN ["/usr/bin/node", "-e", "const fs=require('node:fs'); for (const entry of fs.readdirSync('/usr/bin')) if (entry !== 'node') fs.rmSync('/usr/bin/'+entry,{force:true,recursive:true}); fs.rmSync('/usr/lib/node_modules',{force:true,recursive:true})"]

WORKDIR /member-api-v6

Expand Down
44 changes: 30 additions & 14 deletions docs/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1656,8 +1656,11 @@ paths:
Reviewer, Primary Reviewer, Reviewer, Failure Reviewer, Final Reviewer,
Aggregator, Stress Reviewer, Accuracy Reviewer, Primary Screener,
Checkpoint Screener, and Checkpoint Reviewer. Copilot assignments use
the Copilot resource role. The summary does not load challenge names or
Copilot track/fulfillment details.
the Copilot resource role and count only COMPLETED, CANCELLED, or
CANCELLED_* challenges, including client-request cancellations. Drafts
and other non-terminal challenges are excluded from Copilot counts;
Reviewer counts have no status restriction. The summary does not load
challenge names or Copilot track/fulfillment details.

Authorization:
- Public: Anonymous callers may retrieve the count-only summary.
Expand Down Expand Up @@ -1707,12 +1710,19 @@ paths:
no groups, no user-whitelist rows, and are not tasks. Restricted
challenge IDs and names are never returned.

Copilot history, detail totals, and track counts include only COMPLETED,
CANCELLED, or CANCELLED_* challenges. Drafts and other non-terminal
challenges, including active challenges in post mortem, are excluded.
Reviewer history and totals have no status restriction.

Copilot `trackCounts` includes only non-zero Development, Design,
Quality Assurance, and Data Science keys. Fulfillment is
`COMPLETED / (COMPLETED + CANCELLED*) * 100`; `CANCELLED` and every
`CANCELLED_*` status count as cancelled, non-terminal statuses are
excluded, a zero denominator returns 0, and the percentage is rounded
to two decimal places on a 0-100 scale.
`COMPLETED / (COMPLETED + qualifying CANCELLED*) * 100`.
`CANCELLED_CLIENT_REQUEST` remains in challenge history and track counts
but is excluded from fulfillment because it is not a Copilot failure.
Other `CANCELLED` and `CANCELLED_*` statuses count as cancelled,
non-terminal statuses are excluded, a zero denominator returns 0, and
the percentage is rounded to two decimal places on a 0-100 scale.

Cross-schema special-role queries require the `challenges` and `resources`
schemas to be co-located in the challenge database, as in the supported
Expand Down Expand Up @@ -2801,12 +2811,15 @@ definitions:
type: integer
format: int32
minimum: 1
description: Anonymous-visible distinct challenge count for this role family.
description: >
Anonymous-visible distinct challenge count for this role family.
Copilot counts include only completed or cancelled challenges.
SpecialRoleTrackCounts:
type: object
description: >
Non-zero Copilot challenge counts by challenge track. A zero-count track
is omitted.
Non-zero Copilot challenge counts by challenge track, including only
completed or cancelled challenges. Client-request cancellations are
included. A zero-count track is omitted.
properties:
DEVELOPMENT:
type: integer
Expand Down Expand Up @@ -2842,21 +2855,22 @@ definitions:
format: int32
minimum: 0
description: >
Anonymous-visible Copilot challenges in CANCELLED or any CANCELLED_*
status.
Anonymous-visible Copilot challenges in CANCELLED or CANCELLED_*
statuses included as Copilot failures. CANCELLED_CLIENT_REQUEST is
excluded.
total:
type: integer
format: int32
minimum: 0
description: Completed plus cancelled terminal challenges.
description: Completed plus included cancelled terminal challenges.
rate:
type: number
format: double
minimum: 0
maximum: 100
description: >
Completed percentage on a 0-100 scale, rounded to two decimals; zero
when there are no terminal outcomes.
when there are no included terminal outcomes.
SpecialRoleChallengeDimension:
type: object
required:
Expand Down Expand Up @@ -2916,7 +2930,9 @@ definitions:
type: integer
format: int32
minimum: 0
description: Total anonymous-visible distinct challenges for this role.
description: >
Total anonymous-visible distinct challenges for this role. Copilot
totals include only completed or cancelled challenges.
trackCounts:
description: Present only for Copilot details.
$ref: '#/definitions/SpecialRoleTrackCounts'
Expand Down
Loading
Loading