NestJS drop-in replacement for tc-project-service, serving the Topcoder platform at /v6/projects.
- Overview
- Architecture
- API Reference
- Platform Consumers
- Authorization Model
- Event Publishing
- Environment Variables
- Setup and Development
- Testing
- Deployment
- Security Notes
- Dependency Status
- Code Quality Notes
- Migration from v5
- Related Documentation
Projects API v6 manages the full project lifecycle: project CRUD, member management, invites, phases, phase products, attachments, workstreams, copilot request/opportunity/application workflows, and metadata.
It is the platform replacement for tc-project-service (/v5) and is consumed by multiple frontend apps and backend services.
Key design decisions:
- Elasticsearch removed; Prisma + PostgreSQL handle all reads and writes.
- NestJS modular architecture with focused feature modules.
- Layered JWT + M2M authorization.
- Kafka event publishing for mutation flows.
sequenceDiagram
participant Client
participant TokenRolesGuard
participant ProjectContextInterceptor
participant PermissionGuard
participant Controller
participant Service
participant Prisma
participant EventBus
Client->>TokenRolesGuard: HTTP request + Bearer JWT / M2M token
TokenRolesGuard->>TokenRolesGuard: Validate JWT, set request.user
TokenRolesGuard->>ProjectContextInterceptor: pass
ProjectContextInterceptor->>Prisma: Load project members (if :projectId route)
ProjectContextInterceptor->>Controller: request.projectContext populated
Controller->>PermissionGuard: @RequirePermission check
PermissionGuard->>Controller: authorized
Controller->>Service: business logic
Service->>Prisma: DB query
Service->>EventBus: publish Kafka event (on mutations)
Service-->>Controller: result
Controller-->>Client: HTTP response
| NestJS Module | Responsibility |
|---|---|
GlobalProvidersModule |
Prisma, JWT, M2M, Logger, EventBus, shared services |
ApiModule |
Aggregates all feature modules |
ProjectModule |
Project CRUD, listing, billing account lookup |
ProjectMemberModule |
Member add/update/remove |
ProjectInviteModule |
Invite create/update/delete, email notifications |
ProjectPhaseModule |
Phase CRUD |
PhaseProductModule |
Phase product CRUD |
ProjectAttachmentModule |
File/link attachment CRUD, S3 presigned URLs |
ProjectSettingModule |
Project settings |
WorkstreamModule |
Workstream + work + workitem CRUD |
CopilotModule |
Copilot request/opportunity/application workflows |
MetadataModule |
Project types, templates, forms, plan configs, org configs, milestone templates, work-management permissions |
HealthCheckModule |
GET /v6/projects/health |
For the full v5 -> v6 mapping table, see docs/api-usage-analysis.md.
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/v6/projects |
JWT / M2M | List projects with filters (keyword, status, memberOnly, billingAccountId, sort, page, perPage) |
POST |
/v6/projects |
JWT / M2M | Create project |
GET |
/v6/projects/:projectId |
JWT / M2M | Get project by ID (includes members, invites) |
PATCH |
/v6/projects/:projectId |
JWT / M2M | Update project |
DELETE |
/v6/projects/:projectId |
Admin only | Soft-delete project |
GET |
/v6/projects/:projectId/billingAccount |
JWT / M2M | Default billing account (Billing Accounts API with Salesforce fallback) |
GET |
/v6/projects/:projectId/billingAccounts |
JWT / M2M | All billing accounts for project |
GET |
/v6/projects/:projectId/permissions |
JWT / M2M | Regular human JWT: caller work-management policy map. M2M, admins, project managers, talent managers, and project copilots on the project: per-member permission matrix with project permissions and template policies |
Talent Manager note:
Talent ManagerandTopcoder Talent Managercallers create projects as primarymanagermembers.Talent ManagerandTopcoder Talent Managerusers can also be assigned themanager(Full Access) project role through member add/update/invite flows.Talent ManagerandTopcoder Talent Managercallers also receive the elevated per-member response fromGET /v6/projects/:projectId/permissions, which is used to provision challenge-related actions in Work Manager.- Updating
billingAccountIdis restricted to human administrators and project members whose role on that project ismanager(Full Access).
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/v6/projects/:projectId/members |
JWT / M2M | List members |
GET |
/v6/projects/:projectId/members/:id |
JWT / M2M | Get member |
POST |
/v6/projects/:projectId/members |
JWT / M2M | Add member |
PATCH |
/v6/projects/:projectId/members/:id |
JWT / M2M | Update member role |
DELETE |
/v6/projects/:projectId/members/:id |
JWT / M2M | Remove member |
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/v6/projects/:projectId/invites |
JWT / M2M | List invites |
GET |
/v6/projects/:projectId/invites/:inviteId |
JWT / M2M | Get invite |
POST |
/v6/projects/:projectId/invites |
JWT / M2M | Create invite(s) - returns 201 when any invite is created and includes { success[], failed[] } for rejected targets |
PATCH |
/v6/projects/:projectId/invites/:inviteId |
JWT / M2M | Accept / decline invite |
DELETE |
/v6/projects/:projectId/invites/:inviteId |
JWT / M2M | Delete invite |
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/v6/projects/:projectId/phases |
JWT / M2M | List phases |
GET |
/v6/projects/:projectId/phases/:phaseId |
JWT / M2M | Get phase |
POST |
/v6/projects/:projectId/phases |
JWT / M2M | Create phase |
PATCH |
/v6/projects/:projectId/phases/:phaseId |
JWT / M2M | Update phase |
DELETE |
/v6/projects/:projectId/phases/:phaseId |
JWT / M2M | Soft-delete phase |
GET |
/v6/projects/:projectId/phases/:phaseId/products |
JWT / M2M | List phase products |
GET |
/v6/projects/:projectId/phases/:phaseId/products/:productId |
JWT / M2M | Get phase product |
POST |
/v6/projects/:projectId/phases/:phaseId/products |
JWT / M2M | Create phase product (challenge linkage via details.challengeGuid) |
PATCH |
/v6/projects/:projectId/phases/:phaseId/products/:productId |
JWT / M2M | Update phase product |
DELETE |
/v6/projects/:projectId/phases/:phaseId/products/:productId |
JWT / M2M | Soft-delete phase product |
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/v6/projects/:projectId/attachments |
JWT / M2M | List attachments |
GET |
/v6/projects/:projectId/attachments/:id |
JWT / M2M | Get attachment (file -> presigned S3 URL) |
POST |
/v6/projects/:projectId/attachments |
JWT / M2M | Upload file or add link attachment |
PATCH |
/v6/projects/:projectId/attachments/:id |
JWT / M2M | Update attachment metadata |
DELETE |
/v6/projects/:projectId/attachments/:id |
JWT / M2M | Soft-delete + async S3 removal |
| Method | Path | Auth | Description |
|---|---|---|---|
GET/POST |
/v6/projects/:projectId/workstreams |
JWT / M2M | List / create workstreams |
GET/PATCH/DELETE |
/v6/projects/:projectId/workstreams/:id |
JWT / M2M | Get / update / delete workstream |
GET/POST |
/v6/projects/:projectId/workstreams/:workStreamId/works |
JWT / M2M | List / create works (maps to ProjectPhase) |
GET/PATCH/DELETE |
/v6/projects/:projectId/workstreams/:workStreamId/works/:id |
JWT / M2M | Get / update / delete work |
GET/POST |
/v6/projects/:projectId/workstreams/:workStreamId/works/:workId/workitems |
JWT / M2M | List / create work items (maps to PhaseProduct) |
GET/PATCH/DELETE |
/v6/projects/:projectId/workstreams/:workStreamId/works/:workId/workitems/:id |
JWT / M2M | Get / update / delete work item |
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/v6/projects/copilots/requests |
JWT / M2M | List all copilot requests (admin/PM sees all; others see own) |
GET |
/v6/projects/:projectId/copilots/requests |
JWT / M2M | Project-scoped copilot requests |
GET |
/v6/projects/copilots/requests/:copilotRequestId |
JWT / M2M | Get single copilot request |
POST |
/v6/projects/:projectId/copilots/requests |
JWT / M2M | Create copilot request |
PATCH |
/v6/projects/copilots/requests/:copilotRequestId |
JWT / M2M | Update copilot request |
POST |
/v6/projects/:projectId/copilots/requests/:copilotRequestId/approve |
JWT / M2M | Approve request -> creates opportunity |
GET |
/v6/projects/copilots/opportunities |
Public | Dynamically filter and page copilot opportunities |
GET |
/v6/projects/copilot/opportunity/:id (alias: /copilots/opportunity/:id) |
Public | Get opportunity details and current-user application state |
POST |
/v6/projects/copilots/opportunity/:id/apply |
JWT | Apply as copilot |
GET |
/v6/projects/copilots/opportunity/:id/applications |
JWT | List applications |
POST |
/v6/projects/copilots/opportunity/:id/assign |
JWT | Assign copilot (triggers member/state transitions) |
DELETE |
/v6/projects/copilots/opportunity/:id/cancel |
JWT | Cancel opportunity (cascade) |
Copilot request management routes accept M2M tokens with project-write authorization such as write:projects, all:projects, or all:connect_project.
The opportunity list supports database-level search, status, projectId,
projectName, type, skills, requested-start/created date ranges, sorting,
and current-user applied / applicationStatus filters. The existing response
array and pagination headers remain compatible. See
docs/copilot-opportunities.md for the exact
contract, aliases, current-user fields, and examples.
Cross-service consumers can install the checked-in
packages/projects-prisma-client subdirectory as
@topcoder/projects-api-v6. It exports all generated Projects Prisma models,
enums, and PrismaClient, plus
createProjectsPrismaClient(connectionString, options?), which configures the
required Prisma 7 PostgreSQL adapter. See the package
README for installation and
lifecycle usage.
See docs/api-usage-analysis.md (P2 section) for the complete metadata list.
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/v6/projects/metadata |
JWT / M2M | Aggregate metadata object |
GET/POST/PATCH/DELETE |
/v6/projects/metadata/projectTypes |
JWT / M2M | Project type CRUD |
GET/POST/PATCH/DELETE |
/v6/projects/metadata/projectTemplates |
JWT / M2M | Project template CRUD |
GET |
/v6/projects/metadata/productTemplates |
JWT / M2M | Product templates |
GET/POST/PATCH/DELETE |
/v6/projects/metadata/workManagementPermission |
JWT / M2M | Work-management permission rows |
GET/POST/PATCH/DELETE |
/v6/projects/metadata/orgConfig |
JWT / M2M | Org config |
GET/POST/PATCH/DELETE |
/v6/projects/metadata/milestoneTemplates |
JWT / M2M | Milestone template CRUD |
GET/POST/PATCH/DELETE |
/v6/projects/metadata/forms |
JWT / M2M | Form CRUD |
GET/POST/PATCH/DELETE |
/v6/projects/metadata/planConfigs |
JWT / M2M | Plan config CRUD |
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/v6/projects/health |
Public | Liveness check |
Swagger UI: http://localhost:3000/v6/projects/api-docs
PROJECTS_API_URLresolves to${EnvironmentConfig.API.V6}/projects.- Calls
GET /v6/projects(paginated listing withsort,status,memberOnly,billingAccountId,keyword),GET /v6/projects/:id,POST /v6/projects,PATCH /v6/projects/:id. - Member operations:
POST /members,PATCH /members/:id,DELETE /members/:id. - Invite operations via
platform-ui/src/apps/work/src/lib/services/project-member-invites.service.ts:POST /invites?fields=...,PATCH /invites/:id,DELETE /invites/:id. - Phase/product linkage:
GET /phases?fields=id,name,products,status,POST /phases/:phaseId/products(challenge linkage withdetails.challengeGuid),DELETE /phases/:phaseId/products/:productId. - Attachment operations:
GET /attachments/:id,POST /attachments,PATCH /attachments/:id,DELETE /attachments/:id. - Billing:
GET /billingAccount. - Metadata:
GET /metadata/projectTypeswith fallback toGET /metadata.
baseUrlresolves to${EnvironmentConfig.API.V6}/projects.- Uses SWR hook
useProjectsfor reactive project listing with chunked ID filtering (20 IDs per request, 200 ms rate-limit delay between chunks). - Calls
GET /v6/projects(withnamesearch and arbitrary filter params),GET /v6/projects/:id.
- Heaviest consumer of the P0 surface: project CRUD/listing, billing lookups, member/invite write flows, attachment file/link flows, phase-product linkage.
- Uses
action: "complete-copilot-requests"onPATCH /members/:idto trigger copilot workflow side effects. - Reads pagination headers:
X-Page,X-Per-Page,X-Total,X-Total-Pages.
- Calls
GET /v6/projects/:projectIdto validate project existence and extractmembers[]+invites[]for engagement creation.
- Calls
GET /v6/projects/:projectIdandGET /v6/projects/:projectId/billingAccount(readsmarkupfield for M2M payment flows). - Calls
POST /v6/projectsandPATCH /v6/projects/:projectIdfor self-service challenge project lifecycle.
- Calls
GET /v6/projects/copilots/opportunities?noGrouping=true(public endpoint) for the copilot marketplace listing.
Layered auth details and guard usage are documented in docs/PERMISSIONS.md.
JWT Bearer token -> TokenRolesGuard -> request.user
↓
ProjectContextInterceptor (loads project members for :projectId routes)
↓
PermissionGuard / AdminOnlyGuard / ProjectMemberGuard / CopilotAndAboveGuard
↓
Controller (@CurrentUser, @ProjectMembers decorators)
TokenRolesGuardvalidates JWT or M2M token; routes decorated with@Public()bypass it.PermissionGuardevaluates@RequirePermission(PERMISSION.X)using allow + deny rule semantics.AdminOnlyGuardrestricts to Topcoder admin roles.ProjectMemberGuardrequires caller to be a project member; optionally filtered by@RequireProjectMemberRoles(...).CopilotAndAboveGuardrequires copilot, manager, or admin role.
| Scope | Implies |
|---|---|
all:connect_project / all:project |
All project read/write scopes |
all:projects |
read:projects + write:projects |
all:project-members |
read:project-members + write:project-members |
all:project-invites |
read:project-invites + write:project-invites |
all:* |
All scopes |
For full event envelope and payload schemas, see docs/event-schemas.md.
| Kafka Topic | Trigger |
|---|---|
project.created |
POST /v6/projects |
project.updated |
PATCH /v6/projects/:projectId (status change or field update) |
project.action.billingAccount.update |
PATCH /v6/projects/:projectId (only when billingAccountId changes) |
project.deleted |
DELETE /v6/projects/:projectId |
project.member.added |
POST /v6/projects/:projectId/members |
project.member.removed |
DELETE /v6/projects/:projectId/members/:id |
- Originator:
project-service-v6. - Status-change events are emitted only when status actually changes.
- Billing-account update event payload matches legacy
tc-project-servicecontract and is sent as raw payload (noresource/datawrapper). - Metadata event publishing is currently disabled.
Reference source: .env.example.
| Variable | Required | Default | Description |
|---|---|---|---|
DATABASE_URL |
✅ | - | PostgreSQL connection string for Prisma |
AUTH_SECRET |
✅ | - | JWT signing secret (from tc-core-library-js) |
VALID_ISSUERS |
✅ | - | JSON array of accepted JWT issuers |
AUTH0_URL |
✅ | - | Auth0 token endpoint for M2M |
AUTH0_AUDIENCE |
✅ | - | M2M audience |
AUTH0_PROXY_SERVER_URL |
- | - | Auth0 proxy (optional) |
AUTH0_CLIENT_ID |
✅ | - | M2M client ID |
AUTH0_CLIENT_SECRET |
✅ | - | M2M client secret |
KAFKA_URL |
- | - | Legacy/compatibility setting; not used by current tc-bus-api-wrapper client init |
KAFKA_ERROR_TOPIC |
✅ | - | Kafka topic used by tc-bus-api-wrapper for postError routing (required by wrapper init) |
KAFKA_CLIENT_CERT |
- | - | Legacy/compatibility setting; not used by current tc-bus-api-wrapper client init |
KAFKA_CLIENT_CERT_KEY |
- | - | Legacy/compatibility setting; not used by current tc-bus-api-wrapper client init |
BUSAPI_URL |
✅ | - | Topcoder Bus API base URL |
KAFKA_PROJECT_CREATED_TOPIC |
✅ | project.created |
Kafka topic |
KAFKA_PROJECT_UPDATED_TOPIC |
✅ | project.updated |
Kafka topic |
KAFKA_PROJECT_BILLING_ACCOUNT_UPDATED_TOPIC |
✅ | project.action.billingAccount.update |
Kafka topic |
KAFKA_PROJECT_DELETED_TOPIC |
✅ | project.deleted |
Kafka topic |
KAFKA_PROJECT_MEMBER_ADDED_TOPIC |
✅ | project.member.added |
Kafka topic |
KAFKA_PROJECT_MEMBER_REMOVED_TOPIC |
✅ | project.member.removed |
Kafka topic |
ATTACHMENTS_S3_BUCKET |
✅ | - | S3 bucket for file attachments |
PROJECT_ATTACHMENT_PATH_PREFIX |
- | projects |
S3 key prefix |
PRESIGNED_URL_EXPIRATION |
- | 3600 |
Presigned URL TTL (seconds) |
MAX_PHASE_PRODUCT_COUNT |
- | 20 |
Max phase products per phase |
ENABLE_FILE_UPLOAD |
- | true |
Toggle S3 file upload |
MEMBER_API_URL |
✅ | - | Member API base URL |
IDENTITY_API_URL |
✅ | - | Identity API base URL |
BILLING_ACCOUNTS_API_URL |
- | - | Billing Accounts API base URL used for default billing-account lookup before Salesforce fallback |
SALESFORCE_CLIENT_ID |
✅ | - | Salesforce JWT client ID |
SALESFORCE_CLIENT_AUDIENCE |
✅ | https://login.salesforce.com |
Salesforce audience |
SALESFORCE_SUBJECT |
✅ | - | Salesforce JWT subject |
SALESFORCE_CLIENT_KEY |
✅ | - | Salesforce private key |
SALESFORCE_LOGIN_BASE_URL |
- | https://login.salesforce.com |
Salesforce login URL |
SALESFORCE_API_VERSION |
- | v37.0 |
Salesforce API version |
SFDC_BILLING_ACCOUNT_NAME_FIELD |
- | Billing_Account_name__c |
SOQL field name |
SFDC_BILLING_ACCOUNT_MARKUP_FIELD |
- | Mark_Up__c |
SOQL field name |
SFDC_BILLING_ACCOUNT_ACTIVE_FIELD |
- | Active__c |
SOQL field name |
INVITE_EMAIL_SUBJECT |
- | - | Email subject for invites |
SENDGRID_PROJECT_INVITATION_KNOWN_USER_TEMPLATE_ID |
- | - | SendGrid template ID for registered users (Join/Decline invite email) |
SENDGRID_PROJECT_INVITATION_UNKNOWN_USER_TEMPLATE_ID |
- | - | SendGrid template ID for unregistered emails (Register invite email) |
SENDGRID_TEMPLATE_PROJECT_MEMBER_INVITED |
- | - | Legacy fallback SendGrid template ID when dedicated invite template vars are unset |
SENDGRID_TEMPLATE_COPILOT_ALREADY_PART_OF_PROJECT |
- | - | SendGrid template ID |
SENDGRID_TEMPLATE_INFORM_PM_COPILOT_APPLICATION_ACCEPTED |
- | - | SendGrid template ID |
COPILOT_PORTAL_URL |
- | - | Copilot portal URL (used in invite emails) |
WORK_MANAGER_URL |
✅ | - | Work Manager base URL used to build invite action links in emails. Format: https://work.topcoder.com. Must not have a trailing slash. |
ACCOUNTS_APP_URL |
- | - | Accounts app URL (used in invite emails) |
UNIQUE_GMAIL_VALIDATION |
- | false |
Treat Gmail + aliases as same address |
PORT |
- | 3000 |
HTTP listen port |
API_PREFIX |
- | v6 |
Global route prefix |
HEALTH_CHECK_TIMEOUT |
- | 60000 |
Health check timeout (ms) |
PROJECT_SERVICE_PRISMA_TIMEOUT |
- | 10000 |
Prisma query timeout (ms) |
CORS_ALLOWED_ORIGIN |
- | - | Additional CORS origin (regex string) |
NODE_ENV |
- | development |
Node environment |
- Node.js
v26.5.1(nvm usein this project folder) - pnpm
10.28.2 - PostgreSQL
pnpm installpostinstall runs prisma generate.
Configure DATABASE_URL, then run:
pnpm exec prisma migrate dev
pnpm prisma db seedCopy .env.example to .env and fill in all required variables.
pnpm run start:devpnpm run build
pnpm run start:prodpnpm lintMust pass before every commit per AGENTS.md.
pnpm buildMust pass before every commit per AGENTS.md.
| Command | Purpose |
|---|---|
pnpm test |
Unit tests (Jest) |
pnpm test:cov |
Unit tests with coverage |
pnpm test:e2e |
Full e2e suite |
pnpm test:load |
Load / performance tests (autocannon) |
pnpm test:deployment |
Deployment smoke validation |
- CI/CD: CircleCI -> AWS ECS Fargate.
- The multi-stage Docker image builds with Node 26.5.1 and copies only compiled output, production dependencies, and Prisma migration assets into its Alpine 3.24 runtime. The runtime installs the dynamically linked Alpine Node package and does not contain npm or other package tooling.
- Container startup invokes the local Prisma CLI to deploy migrations before
replacing the shell process with
node dist/src/main. - Blue-green rollout strategy is documented in
docs/MIGRATION_RUNBOOK.md. - Recommended alerts:
- 5xx rate > 2% for 5 minutes
- p95 latency > 2.5s for 10 minutes
- event publish failures > 0.5% for 5 minutes
- DB pool saturation > 85%
Open findings are tracked inline with TODO (security) comments in source.
| Location | Finding | Severity | Status |
|---|---|---|---|
src/main.ts |
CORS_ALLOWED_ORIGIN env var compiled directly into RegExp - ReDoS risk |
Medium | Open - validate/escape before use |
src/main.ts |
CORS returns '*' for requests with no Origin header |
Low | Open - consider returning false for server-to-server calls |
src/main.ts |
Swagger UI publicly accessible with no auth in production | Medium | Open - restrict by IP or add HTTP Basic auth, or gate behind env flag |
src/main.ts |
Duplicate Swagger mount at /v6/projects-api-docs |
Low (quality) | Open - consolidate to single path |
| Event publication logging | Environment-derived Kafka topics and raw client errors could reach clear-text logs | High | Resolved - log fixed operation markers and allowlisted error categories only |
docs/DEPENDENCIES.md |
GitHub-sourced Topcoder packages do not have a registry release stream | Low | Mitigated with immutable commit pins; external API dependencies install only their generated Prisma-client subdirectories |
Summary from docs/DEPENDENCIES.md:
- Production audit: no known vulnerabilities.
- Node 26.5.1, NestJS 11.1.28, Prisma 7.9.0, Axios 1.18.1, Lodash 4.18.1, qs 6.15.3, and UUID 14.0.1 are locked in the security candidate.
- Security overrides for affected transitives are maintained in
pnpm-workspace.yamland captured inpnpm-lock.yaml. - Topcoder Git dependencies use immutable commits. Cross-service database dependencies install only committed generated Prisma clients rather than the full API applications and their unrelated dependency graphs.
Full details: docs/DEPENDENCIES.md.
Open TODO (quality) findings from prior phases:
| Location | Finding |
|---|---|
src/main.ts |
serializeBigInt should move to src/shared/utils/serialization.utils.ts |
src/main.ts |
LoggerService instantiated per HTTP request - hoist to module scope |
src/main.ts |
Duplicate Swagger mount - consolidate to one path |
src/main.ts |
WorkStreamModule included in Swagger but not in ApiModule imports - causes documentation drift |
src/shared/services/permission.service.ts |
Large switch/case permission map - refactor to a data-driven lookup table |
src/api/copilot/copilot.utils.ts |
Sort utility functions duplicated across copilot sub-services - centralize |
- API prefix changed from
/v5to/v6. - Elasticsearch removed; all reads use PostgreSQL via Prisma.
- Timeline/milestone CRUD intentionally not migrated (see
docs/timeline-milestone-migration.md). - Deprecated endpoints not ported (scope change requests, reports, customer payments, phase members/approvals, estimation items).
- Invite creation returns
201when any invite is created and still uses{ success: Invite[], failed: ErrorInfo[] }for rejected targets. - Event originator changed from
tc-project-servicetoproject-service-v6.
Full details: docs/DIFFERENCES_FROM_V5.md and docs/MIGRATION_FROM_TC_PROJECT_SERVICE.md.
Migration runbook (phased rollout, rollback, monitoring): docs/MIGRATION_RUNBOOK.md.
| Document | Purpose |
|---|---|
docs/PERMISSIONS.md |
Full permission system reference, guard usage, M2M scope hierarchy |
docs/api-usage-analysis.md |
v5 -> v6 endpoint mapping, P0/P1/P2 classification, consumer call patterns |
docs/event-schemas.md |
Kafka event envelope and payload schemas |
docs/DIFFERENCES_FROM_V5.md |
Intentional differences and improvements vs tc-project-service |
docs/MIGRATION_FROM_TC_PROJECT_SERVICE.md |
Auth migration guide, permission mapping, consumer notes |
docs/MIGRATION_RUNBOOK.md |
Phased rollout, rollback procedures, monitoring alerts |
docs/DEPENDENCIES.md |
Dependency security audit, outdated packages, overrides |
docs/timeline-milestone-migration.md |
Guidance for future timeline/milestone migration |