Skip to content

Conversation

@gugu
Copy link
Contributor

@gugu gugu commented Nov 21, 2025

No description provided.

@gugu gugu requested a review from Artuomka November 23, 2025 10:34
@gugu gugu marked this pull request as ready for review November 23, 2025 10:34
Copilot AI review requested due to automatic review settings November 23, 2025 10:34
@gugu
Copy link
Contributor Author

gugu commented Nov 23, 2025

@codex review

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR implements a secret storage feature that allows users to securely store, manage, and audit sensitive company information like API keys, tokens, and passwords. The feature includes encrypted storage with optional master password protection, comprehensive audit logging, and company-based access control.

  • Adds complete secret storage backend with entities, service, controller, and DTOs
  • Implements two-layer encryption (application-level + optional master password)
  • Adds database migrations for user secrets and audit logs
  • Includes comprehensive unit and E2E test coverage
  • Updates Docker configuration for test environment

Reviewed changes

Copilot reviewed 21 out of 21 changed files in this pull request and generated 26 comments.

Show a summary per file
File Description
backend/test/ava-tests/non-saas-tests/non-saas-secrets-e2e.test.ts Comprehensive E2E tests covering all secret operations including CRUD, authentication, authorization, and master password protection
backend/src/migrations/1763724062000-CreateSecretAccessLogEntity.ts Database migration for audit log table with proper indexes and foreign keys
backend/src/migrations/1763724061000-CreateUserSecretEntity.ts Database migration for user secrets table with encryption support and company-level scoping
backend/src/entities/user-secret/user-secrets.service.ts Core service implementing secret management with encryption, access control, and audit logging
backend/src/entities/user-secret/user-secrets.service.spec.ts Unit tests for the secrets service covering all major operations and error cases
backend/src/entities/user-secret/user-secret.module.ts NestJS module definition registering the secret storage components
backend/src/entities/user-secret/user-secret.entity.ts TypeORM entity for user secrets with relationships and indexes
backend/src/entities/user-secret/user-secret.controller.ts REST API controller exposing secret management endpoints
backend/src/entities/user-secret/application/dto/update-secret.dto.ts DTO for updating secret values with validation
backend/src/entities/user-secret/application/dto/secret-list.dto.ts DTOs for paginated secret list responses
backend/src/entities/user-secret/application/dto/found-secret.dto.ts DTO for returning secret details with optional value
backend/src/entities/user-secret/application/dto/create-secret.dto.ts DTO for creating secrets with validation and master password support
backend/src/entities/user-secret/application/dto/audit-log.dto.ts DTOs for audit log entries and paginated responses
backend/src/entities/secret-access-log/secret-access-log.entity.ts TypeORM entity for tracking all secret access events
backend/src/decorators/company-id.decorator.ts Custom decorator for extracting company ID from authenticated requests
backend/src/app.module.ts Registers the UserSecretModule in the main application module
justfile Adds --attach flag to focus test output on backend_test container
docker-compose.tst.yml Updates test environment with explicit DATABASE_URL and simplified volume mounts
Dockerfile Modifies file ownership configuration for the application directory
SECRET_STORAGE_SPECIFICATION.md Comprehensive specification document detailing the secret storage feature design
Comments suppressed due to low confidence (1)

backend/test/ava-tests/non-saas-tests/non-saas-secrets-e2e.test.ts:71

  • Unused variable connectionId.
  const connectionId = JSON.parse(createdConnection.text).id;

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

.set('Content-Type', 'application/json')
.set('Accept', 'application/json');

const connectionId = JSON.parse(createdConnection.text).id;
Copy link

Copilot AI Nov 23, 2025

Choose a reason for hiding this comment

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

The variable connectionId is created but never used in this test or any other tests in the file. Each test creates a connection but doesn't use the connectionId for any assertions or operations. Consider removing these unused variable declarations throughout the test file (lines 71, 107, 138, 170, 202, 228, 254, 277, 312, 334, 361, 392, 426, 455, 490, 516, 550, 573, 600, 623) to improve code maintainability.

Suggested change
const connectionId = JSON.parse(createdConnection.text).id;
// Removed unused connectionId variable

Copilot uses AI. Check for mistakes.
Post,
Put,
Query,
UseGuards,
Copy link

Copilot AI Nov 23, 2025

Choose a reason for hiding this comment

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

Unused import UseGuards.

Suggested change
UseGuards,

Copilot uses AI. Check for mistakes.
jest.spyOn(auditLogRepository, 'save').mockResolvedValue({} as SecretAccessLogEntity);

const result = await service.updateSecret('user-uuid-1', 'test-secret', updateDto);

Copy link

Copilot AI Nov 23, 2025

Choose a reason for hiding this comment

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

Unused variable result.

Suggested change
expect(result.slug).toBe('test-secret');
expect(result.encryptedValue).toBe('new-value');

Copilot uses AI. Check for mistakes.
.set('Content-Type', 'application/json')
.set('Accept', 'application/json');

const connectionId = JSON.parse(createdConnection.text).id;
Copy link

Copilot AI Nov 23, 2025

Choose a reason for hiding this comment

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

Unused variable connectionId.

Suggested change
const connectionId = JSON.parse(createdConnection.text).id;

Copilot uses AI. Check for mistakes.
.set('Content-Type', 'application/json')
.set('Accept', 'application/json');

const connectionId = JSON.parse(createdConnection.text).id;
Copy link

Copilot AI Nov 23, 2025

Choose a reason for hiding this comment

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

Unused variable connectionId.

Copilot uses AI. Check for mistakes.
.set('Content-Type', 'application/json')
.set('Accept', 'application/json');

const connectionId = JSON.parse(createdConnection.text).id;
Copy link

Copilot AI Nov 23, 2025

Choose a reason for hiding this comment

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

Unused variable connectionId.

Copilot uses AI. Check for mistakes.
.set('Content-Type', 'application/json')
.set('Accept', 'application/json');

const connectionId = JSON.parse(createdConnection.text).id;
Copy link

Copilot AI Nov 23, 2025

Choose a reason for hiding this comment

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

Unused variable connectionId.

Copilot uses AI. Check for mistakes.
.set('Content-Type', 'application/json')
.set('Accept', 'application/json');

const connectionId = JSON.parse(createdConnection.text).id;
Copy link

Copilot AI Nov 23, 2025

Choose a reason for hiding this comment

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

Unused variable connectionId.

Suggested change
const connectionId = JSON.parse(createdConnection.text).id;

Copilot uses AI. Check for mistakes.
@gugu gugu marked this pull request as draft November 23, 2025 10:53
Copy link
Collaborator

@Artuomka Artuomka left a comment

Choose a reason for hiding this comment

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

The implementation does not align with the overall project architecture.
New entities have been added that are related to existing ones, but the corresponding changes were not made to the existing entities.


export class AuditLogResponseDto {
@ApiProperty({ type: [AuditLogEntryDto] })
data: AuditLogEntryDto[];
Copy link
Collaborator

Choose a reason for hiding this comment

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

({ type: AuditLogEntryDto, isArray: true })

@gugu gugu marked this pull request as ready for review November 28, 2025 13:23
@Artuomka Artuomka self-requested a review December 2, 2025 10:37
@Column({ type: 'varchar', length: 4096, nullable: true })
masterHash: string;

@OneToMany(() => SecretAccessLogEntity, (log) => log.secret)
Copy link
Collaborator

Choose a reason for hiding this comment

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

need to add description of the inverse relation

@PrimaryGeneratedColumn('uuid')
id: string;

@ManyToOne(() => CompanyInfoEntity, { onDelete: 'CASCADE' })
Copy link
Collaborator

Choose a reason for hiding this comment

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

need to add description of the inverse relation

Copy link
Collaborator

@Artuomka Artuomka left a comment

Choose a reason for hiding this comment

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

need to improve swagger DTOs, need to add inverse relations in TypeORM entities (secret.accessLogs ↔ accessLog.secret), change ForbiddenException to NotFoundException when user is not found, and add guard to endpoints, if its needed

@gugu gugu enabled auto-merge (squash) December 4, 2025 15:08
@gugu gugu merged commit 292da6c into main Dec 4, 2025
18 checks passed
@gugu gugu deleted the secrets branch December 4, 2025 15:49
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.

3 participants