Skip to content

Conversation

@kkartunov
Copy link
Contributor

kkartunov and others added 25 commits November 4, 2025 10:04
…ing or encoding

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Potential fix for code scanning alert no. 72: Incomplete string escaping or encoding
PS-441 Fix for processing phases in challenge update
@kkartunov kkartunov requested review from jmgasper and vas3a November 11, 2025 08:28
if (suspiciousReason) {
if (invalidDateBehavior.warn) {
console.warn(`${fileName}: record ${recordIdentifier} has ${suspiciousReason.replace('|', ' & ')} (${parsedDate.toISOString()}); strategy=${invalidDateBehavior.strategy}`);
console.warn(`${fileName}: record ${recordIdentifier} has ${suspiciousReason.replace(/\|/g, ' & ')} (${parsedDate.toISOString()}); strategy=${invalidDateBehavior.strategy}`);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ correctness]
The change from suspiciousReason.replace('|', ' & ') to suspiciousReason.replace(/\|/g, ' & ') is correct as it ensures all occurrences of the pipe character are replaced. However, consider verifying that suspiciousReason is always a string to avoid potential runtime errors if it is unexpectedly not a string.


CMD ["node","/challenge-api/app.js"]
# Copy entrypoint script and make it executable
COPY docker/entrypoint.sh /entrypoint.sh

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ security]
Consider verifying the integrity of entrypoint.sh after copying it into the image. This can help ensure that the script has not been tampered with and is safe to execute.


# Use entrypoint to run migrations at startup (not build time)
# Prisma uses PostgreSQL advisory locks to prevent concurrent migrations
ENTRYPOINT ["/entrypoint.sh"]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ correctness]
Using an entrypoint script to run migrations at startup can be risky if the script fails or if the database is not ready. Consider adding error handling or retry logic within entrypoint.sh to handle such cases gracefully.

awsMock.mock('S3', 'getObject', (params, callback) => {
callback(null, { Body: Buffer.from(attachmentContent) });
// mock S3 GetObject command
s3Mock.on(GetObjectCommand).resolves({

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ correctness]
Using Readable.from([attachmentContent]) to create a stream from a buffer is technically correct, but ensure that attachmentContent is always a buffer and not accidentally a string or other type. Consider adding validation for attachmentContent to prevent runtime errors.

LIMIT 1;

IF idx_schema IS NOT NULL THEN
EXECUTE format('DROP INDEX %I.%I', idx_schema, 'challenge_phase_order_idx');

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ maintainability]
Consider adding a check to ensure that the index exists before attempting to drop it. Although the current logic handles the case where idx_schema is NULL, explicitly checking for the existence of the index might prevent unexpected errors if the index is dropped or renamed outside of this script.

RETURN;
END IF;

EXECUTE format(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ correctness]
The ALTER TABLE operation assumes that the column isAIReviewer exists. Consider adding a check to ensure the column exists before attempting to alter it. This will prevent runtime errors if the column is missing or renamed.

generator client {
provider = "prisma-client-js"
previewFeatures = ["fullTextSearchPostgres", "postgresqlExtensions"]
previewFeatures = ["fullTextSearchPostgres", "postgresqlExtensions", "views"]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ maintainability]
Adding views to previewFeatures may introduce instability as preview features are not fully stable. Ensure that this feature is necessary and tested thoroughly in your environment.

@@index([trackId, typeId, status])
@@index([status, typeId, trackId, createdAt(sort: Desc)], map: "challenge_status_type_track_created_at_idx")
@@index([name(ops: raw("pg_catalog.gin_trgm_ops"))], type: Gin, map: "challenge_name_trgm_idx")
@@index([legacyId])

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[❗❗ performance]
The removal of the @@index([name(ops: raw("pg_catalog.gin_trgm_ops"))], type: Gin, map: "challenge_name_trgm_idx") index could impact performance if text search on the name field was previously optimized by this index. Verify that this change does not degrade query performance.

//////////////////////////////////////////

model MemberChallengeAccess {
view MemberChallengeAccess {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[❗❗ correctness]
Changing MemberChallengeAccess from a model to a view alters its behavior significantly. Ensure that all dependencies on this model are updated to handle it as a view, and verify that the view definition aligns with the expected data structure.

incrementalCoefficient Float?
opportunityType ReviewOpportunityTypeEnum?
isAIReviewer Boolean
isAIReviewer Boolean?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[❗❗ correctness]
Changing isAIReviewer from Boolean to Boolean? introduces a potential for null values. Ensure that the application logic correctly handles null values for this field.

paths:
- node_modules

finger_print_add: &finger_print_add

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ performance]
The removal of the restore_cache_settings_for_build and save_cache_settings anchors, along with their usage in the builddeploy_steps, could lead to increased build times if the node_modules directory is not cached elsewhere. Consider verifying if caching is handled in another part of the pipeline or if this removal is intentional and acceptable.

Allow for Topgear Submission type phase when calculating start / end …
const { ensureAcessibilityToModifiedGroups } = require("./group-helper");
const { ChallengeStatusEnum } = require("@prisma/client");

const SUBMISSION_PHASE_PRIORITY = ["Topcoder Submission", "Submission"];

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[💡 performance]
Consider using a Set for SUBMISSION_PHASE_PRIORITY if the list of phase names is expected to grow or if you need to perform frequent lookups. This could improve performance slightly by reducing the time complexity of lookups from O(n) to O(1).


const registrationPhase = _.find(phases, (p) => p.name === "Registration");
const submissionPhase =
_.find(phases, (p) => p.name === SUBMISSION_PHASE_PRIORITY[0]) ||

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ correctness]
The logic for finding the submissionPhase uses a priority list but does not handle the case where neither 'Topcoder Submission' nor 'Submission' phases are found. Consider adding a fallback or handling this case explicitly to avoid potential issues if both phases are missing.

Allow for registration phase reopening if submission or TG submission phases are open
});

if (dependentOpenPhases.length === 0) {
const normalizedPhaseName = normalizePhaseName(phaseName);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ performance]
The normalizePhaseName function is called twice for each phase in openPhases within the some method. Consider normalizing the phase name once before the some method to improve performance.

const hasSubmissionVariantOpen = openPhases.some((phase) =>
SUBMISSION_PHASE_NAME_SET.has(normalizePhaseName(phase?.name))
);
const allowRegistrationReopenWithoutExplicitDependency =

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ maintainability]
The logic to allow reopening the registration phase without explicit dependency when a submission variant is open is embedded within the condition. Consider extracting this logic into a well-named function to improve readability and maintainability.

}
})

try {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ correctness]
The try block is used to execute partiallyUpdateChallengePhase, but the finally block contains database updates that should be in a catch block to handle potential errors from the try block. Consider adding a catch block to handle errors explicitly.


})

it('partially update challenge phase - cannot reopen when open phase is not a successor or submission variant', async () => {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ correctness]
The test case description mentions 'cannot reopen when open phase is not a successor or submission variant', but the logic in the test does not verify the 'submission variant' condition explicitly. Ensure the test case covers all conditions mentioned in the description.

Allow reopening of registration phase and submission start / end date fix
-- Improve search responsiveness for group-constrained queries
CREATE INDEX IF NOT EXISTS "challenge_groups_gin_idx"
ON "challenges"."Challenge"
USING GIN ("groups");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[❗❗ correctness]
Ensure that the groups column is of a suitable data type for a GIN index, such as jsonb or array. Using GIN on unsupported types may lead to unexpected behavior or performance issues.

@@index([updatedAt])
@@index([typeId])
@@index([trackId])
@@index([groups], type: Gin, map: "challenge_groups_gin_idx")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ performance]
The use of a GIN index on the groups array field is appropriate for efficient querying of array data types in PostgreSQL. Ensure that the queries taking advantage of this index are optimized to benefit from the GIN index, as not all operations on array fields will automatically leverage it.

/*
Warnings:
- You are about to drop the column `isAIReviewer` on the `DefaultChallengeReviewer` table. All the data in the column will be lost.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[❗❗ correctness]
Dropping the isAIReviewer column will result in data loss. Ensure that this data is either backed up or is no longer needed.

*/
-- AlterTable
ALTER TABLE "DefaultChallengeReviewer" DROP COLUMN "isAIReviewer",
ADD COLUMN "aiWorkflowId" VARCHAR(14),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ maintainability]
Consider specifying a default value for the new aiWorkflowId column to avoid potential issues with null values.

-- AlterTable
ALTER TABLE "DefaultChallengeReviewer" DROP COLUMN "isAIReviewer",
ADD COLUMN "aiWorkflowId" VARCHAR(14),
ALTER COLUMN "scorecardId" DROP NOT NULL;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[❗❗ correctness]
Dropping the NOT NULL constraint on scorecardId may lead to null values being inserted, which could affect application logic. Verify that the application can handle null scorecardId values.

timelineTemplateId String?
// Reviewer configuration (mirrors ChallengeReviewer)
scorecardId String
scorecardId String?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[❗❗ correctness]
Changing scorecardId from String to String? (nullable) could impact logic that assumes this field is always present. Ensure that any code relying on scorecardId being non-null is updated to handle null values appropriately.

incrementalCoefficient Float?
opportunityType ReviewOpportunityTypeEnum?
isAIReviewer Boolean
aiWorkflowId String? @db.VarChar(14)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[❗❗ correctness]
The change from isAIReviewer to aiWorkflowId introduces a new field with a specific length constraint (@db.VarChar(14)). Ensure that any existing data migration scripts or database constraints are updated to accommodate this change, and verify that the application logic correctly handles the new field.

@@index([timelineTemplateId])
@@index([timelineTemplateId, phaseId])
}
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[💡 style]
The absence of a newline at the end of the file may cause issues with some tools that expect a newline. Consider adding a newline to maintain consistency and avoid potential issues.

trackId: Joi.id().required(),
timelineTemplateId: Joi.optionalId().allow(null),
scorecardId: Joi.string().required(),
scorecardId: Joi.string().optional(),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[❗❗ correctness]
Changing scorecardId from required to optional could lead to potential issues if the system relies on this field being present. Ensure that the rest of the codebase can handle scorecardId being undefined or null.

trackId: Joi.id().required(),
timelineTemplateId: Joi.optionalId().allow(null),
scorecardId: Joi.string().required(),
scorecardId: Joi.string().optional(),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[❗❗ correctness]
Changing scorecardId from required to optional could lead to potential issues if the system relies on this field being present. Ensure that the rest of the codebase can handle scorecardId being undefined or null.

.insensitive()
.allow(null),
isAIReviewer: Joi.boolean(),
aiWorkflowId: Joi.string(),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ maintainability]
The aiWorkflowId is now a simple string without any conditional requirements. Consider whether this field should have validation similar to the other schemas to ensure consistency and prevent potential errors.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants