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
36 changes: 19 additions & 17 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# syntax=docker/dockerfile:1.7

ARG NODE_VERSION=26.5.0
ARG NODE_VERSION=26.5.1
ARG PNPM_VERSION=11.15.1

FROM node:${NODE_VERSION}-alpine AS external-clients
Expand Down Expand Up @@ -38,32 +38,34 @@ RUN DATABASE_URL="postgresql://user:password@localhost:5432/forums" pnpm prisma:
&& pnpm install --prod --frozen-lockfile --ignore-scripts \
&& pnpm rebuild @prisma/engines

FROM node:${NODE_VERSION}-alpine AS production
FROM alpine:3.24 AS production

ARG NODE_VERSION
RUN apk upgrade --no-cache \
&& rm -rf /usr/local/lib/node_modules/npm \
&& rm -f /usr/local/bin/npm /usr/local/bin/npx
&& apk add --no-cache nodejs-current=${NODE_VERSION}-r0 \
&& addgroup -S app \
&& adduser -S -D -H -u 10001 -G app app

# External Prisma clients are copied beside the application under /usr/src.
# Expose the application's production dependencies to their CommonJS imports.
ENV NODE_ENV=production \
NODE_PATH=/usr/src/app/node_modules
WORKDIR /usr/src/app

COPY --from=build --chown=node:node /usr/src/app/dist ./dist
COPY --from=build --chown=node:node /usr/src/app/node_modules ./node_modules
COPY --from=build --chown=node:node /usr/src/app/prisma/generated ./prisma/generated
COPY --from=build --chown=node:node /usr/src/app/prisma/migrations ./prisma/migrations
COPY --from=build --chown=node:node /usr/src/app/prisma/schema.prisma ./prisma/schema.prisma
COPY --from=build --chown=node:node /usr/src/app/prisma.config.ts ./prisma.config.ts
COPY --from=build --chown=node:node /usr/src/app/package.json ./package.json
COPY --from=build --chown=node:node --chmod=0555 /usr/src/app/appStartUp.sh ./appStartUp.sh
COPY --from=external-clients --chown=node:node /clients/challenge-api-v6/packages/challenge-prisma-client /usr/src/challenge-api-v6/packages/challenge-prisma-client
COPY --from=external-clients --chown=node:node /clients/identity-api-v6/packages/identity-prisma-client /usr/src/identity-api-v6/packages/identity-prisma-client
COPY --from=external-clients --chown=node:node /clients/member-api-v6/packages/member-prisma-client /usr/src/member-api-v6/packages/member-prisma-client
COPY --from=external-clients --chown=node:node /clients/resource-api-v6/packages/resources-prisma-client /usr/src/resource-api-v6/packages/resources-prisma-client
COPY --from=build --chown=app:app /usr/src/app/dist ./dist
COPY --from=build --chown=app:app /usr/src/app/node_modules ./node_modules
COPY --from=build --chown=app:app /usr/src/app/prisma/generated ./prisma/generated
COPY --from=build --chown=app:app /usr/src/app/prisma/migrations ./prisma/migrations
COPY --from=build --chown=app:app /usr/src/app/prisma/schema.prisma ./prisma/schema.prisma
COPY --from=build --chown=app:app /usr/src/app/prisma.config.ts ./prisma.config.ts
COPY --from=build --chown=app:app /usr/src/app/package.json ./package.json
COPY --from=build --chown=app:app --chmod=0555 /usr/src/app/appStartUp.sh ./appStartUp.sh
COPY --from=external-clients --chown=app:app /clients/challenge-api-v6/packages/challenge-prisma-client /usr/src/challenge-api-v6/packages/challenge-prisma-client
COPY --from=external-clients --chown=app:app /clients/identity-api-v6/packages/identity-prisma-client /usr/src/identity-api-v6/packages/identity-prisma-client
COPY --from=external-clients --chown=app:app /clients/member-api-v6/packages/member-prisma-client /usr/src/member-api-v6/packages/member-prisma-client
COPY --from=external-clients --chown=app:app /clients/resource-api-v6/packages/resources-prisma-client /usr/src/resource-api-v6/packages/resources-prisma-client

USER node
USER app
EXPOSE 3000

CMD ["./appStartUp.sh"]
15 changes: 14 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ and post-commit watch notifications.
- `GET /v6/forums/health`
- `GET /v6/forums/readiness`
- `GET /v6/forums/api-docs`
- `GET /v6/forums/public/categories`
- `GET /v6/forums/public/topics`
- `GET /v6/forums/topics`
- `GET /v6/forums/topics/challenges/:challengeId`
- `GET /v6/forums/topics/:topicId/children`
Expand Down Expand Up @@ -141,6 +143,14 @@ PORT=3000
Health and readiness checks intentionally remain DB-only; they do not validate
event-bus, SendGrid template, producer, or outbound Auth0 readiness.

## Public forums

See [Public forums and migration](docs/public-forums.md) for guest reads, category
ACLs, target-member mapping, insert-only Vanilla import and cutover checks.
Public and general read routes accept anonymous callers, while mutations and
challenge lists still require authentication. Restricted category content is
filtered before statistics, search, pagination, watches and notifications.

## Authentication

Bearer tokens are validated with `tc-core-library-js` and normalized before guards
Expand Down Expand Up @@ -214,8 +224,11 @@ but the `/moderation` endpoints require administrator role access for humans or

## Development

The supported local and container runtime is Node.js 26.5.0 with pnpm 11.15.1.
The supported local and container runtime is Node.js 26.5.1 with pnpm 11.15.1.
The checked-in `.nvmrc` selects the required Node.js release.
The production image installs Alpine's dynamically linked Node.js package and
runs as an unprivileged application user so patched system libraries are used at
runtime without shipping package-manager tooling.

```bash
nvm use
Expand Down
87 changes: 87 additions & 0 deletions docs/public-forums-dev-migration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Dev public-forums migration verification

Executed on 7 October 2026 (Australia/Hobart), using production Vanilla as a
read-only source and the AWS dev forums/Member databases as the target.
Production databases were not written to.

The API was deployed before importing restricted categories. The dev service
`forums-api-v6` is on task revision 18, using code commit `90f244a` and image tag
`public-forums-90f244a`. ECS reached a stable deployment and live public reads
return `Cache-Control: private, no-store`.

## Imported data

| Data | Rows |
| --- | ---: |
| Categories | 57 |
| Discussion threads | 1,355 |
| Starter posts and comments | 3,756 |
| Closure relationships | 4,295 |
| Mapped forum-only role memberships | 139 |
| Watches | 619 |
| Read states | 11,162 |
| Total imported data rows | 21,440 |

The immediate second apply found all 21,440 rows and inserted **zero** rows.
The dry-run, apply and rerun plan digest was:

`aeccd893e9d6486b0750dea69d9e00a51374772c309d3c9da08f342155dcab5b`

There were 1,079 source author IDs without a matching dev member. Their original
handles and content were preserved using non-login legacy IDs. 16,013 source
state records belonged to members absent from dev and were omitted. Production
mapping must be rerun against production Members; dev IDs must not be reused.
No native Vanilla media or reactions required copying. All 99 Filestack links
in the source post bodies were preserved unchanged.

## Existing challenge data

These counts and SHA-256 fingerprints were identical in dry-run, before and
after apply, and after the no-op rerun:

| Table | Rows | SHA-256 |
| --- | ---: | --- |
| Topic | 6,437 | `3dae055b315e049750e2aff4fbbed47cdfcd24f009792235709d950a3a012f83` |
| Post | 6,484 | `c0967e56431ddddbcdd832ad7e6f2cfa70274c9557781dcffdfd9dd4b394a5d3` |
| TopicWatch | 69 | `1e9c7c8269d3c4e6f6ecfefe7617e845f0f7b93f41f7c89e0e4d90ef90e84134` |
| TopicReadState | 6,522 | `ac0b498e58c2a643303783e8ba12d65a028487b474062a9c55bffcdf164ce21b` |
| TopicClosure | 6,437 | `2d1c882cb7691562120e1222254ecbf66500eb7f0924a216d951d7abc4079a9c` |

## Live dev verification

Read-only probes used short-lived dev tokens for a synthetic QA principal; no
member roles, posts, watches or read states were created by the probes. Category
IDs and topic totals matched an independently computed source ACL projection:

| Reader | Visible categories | Visible threads |
| --- | ---: | ---: |
| Guest | 30 | 1,111 |
| Member | 48 | 1,286 |
| Copilot | 52 | 1,323 |
| Reviewer | 49 | 1,288 |

Copilot and Reviewer Discussions returned 403 to guests, ordinary members and
the other role, and 200 to the required role. Invalid tokens returned 401.
Anonymous Watching returned zero results. Measured catalog requests completed
in approximately 1.4–3.5 seconds including network latency from the test host.

The API lint/build, production Docker build and 167 tests passed. Local real
PostgreSQL/HTTP tests cover posting, replies, reactions, watches, nested private
membership, migration conflicts and reruns without sending notifications.

## Remaining production gates

The [UI PR](https://github.com/topcoder-platform/platform-ui/pull/2444) contains
the new app and passed lint, dev/prod builds and 58 focused regression tests.
Connected Chrome verification covered desktop/mobile Figma layouts, category
navigation, search/pagination, guest login return URLs, signed-in composers,
live member suggestions and Markdown preview. The approved generated text
attachment uploaded to Filestack, inserted an HTTPS Markdown link, and rendered
in preview. No test posts were submitted to migrated discussions. Accept the dev
data/role mappings before production cutover. Follow
[the migration runbook](public-forums.md); production has not been migrated.

Full owner-readable reports were retained outside the repository at
`/tmp/public-forums-dev-{dry-run,applied,rerun}.json` and
`/tmp/public-forums-live-access.json`. No credentials, post contents or member
lists are included in this document.
Loading
Loading