Skip to content

Improve security and usability of the Registration Key API.#32

Merged
yulmwu merged 5 commits intomainfrom
improve/registration-key
Feb 15, 2026
Merged

Improve security and usability of the Registration Key API.#32
yulmwu merged 5 commits intomainfrom
improve/registration-key

Conversation

@yulmwu
Copy link
Member

@yulmwu yulmwu commented Feb 15, 2026

Previously, registration keys consisted of random 6-digit numbers. However, this approach was considered vulnerable to guessing and brute force attacks.

To address this, registration keys have been updated to use stronger 16-character alphanumeric strings such as 4TKBS7ZPZFJ4PNRZ. To prevent user confusion, visually ambiguous characters such as I, 1, O, and 0 are excluded.

In addition, registration keys are no longer limited to single use. A maximum usage count can now be specified, allowing multi-use keys. As a result, the following API endpoints have been updated:

  • GET /api/admin/registration-keys
  • POST /api/admin/registration-keys

Please refer to the API documentation for more details. Accordingly, the database tables have been separated into registration_keys and registration_key_uses to reflect their distinct responsibilities.

type RegistrationKey struct {
	bun.BaseModel `bun:"table:registration_keys"`
	ID            int64     `bun:"id,pk,autoincrement"`
	Code          string    `bun:"code,unique,notnull"`
	CreatedBy     int64     `bun:"created_by,notnull"`
	TeamID        int64     `bun:"team_id,notnull"`
	MaxUses       int       `bun:"max_uses,notnull,default:1"`
	UsedCount     int       `bun:"used_count,notnull,default:0"`
	CreatedAt     time.Time `bun:"created_at,nullzero,notnull,default:current_timestamp"`
}

type RegistrationKeyUse struct {
	bun.BaseModel     `bun:"table:registration_key_uses"`
	ID                int64     `bun:"id,pk,autoincrement"`
	RegistrationKeyID int64     `bun:"registration_key_id,notnull"`
	UsedBy            int64     `bun:"used_by,notnull"`
	UsedByIP          string    `bun:"used_by_ip,notnull"`
	UsedAt            time.Time `bun:"used_at,nullzero,notnull,default:current_timestamp"`
}

@yulmwu yulmwu self-assigned this Feb 15, 2026
@yulmwu yulmwu added the enhancement New feature or request label Feb 15, 2026
@codecov
Copy link

codecov bot commented Feb 15, 2026

Codecov Report

❌ Patch coverage is 91.78082% with 6 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
internal/service/auth_service.go 82.35% 2 Missing and 1 partial ⚠️
internal/repo/registration_key_repo.go 92.85% 1 Missing and 1 partial ⚠️
internal/service/helpers.go 94.44% 0 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

@yulmwu
Copy link
Member Author

yulmwu commented Feb 15, 2026

Codecov Report

❌ Patch coverage is 87.67123% with 9 lines in your changes missing coverage. Please review.
...

Understood. The sections mentioned in auth_service.go at lines 92 and 142 are considered areas that require testing.

However, the other logic that returns errors is primarily related to database errors, and we have decided not to cover those in unit tests.

Copy link
Contributor

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 upgrades the Registration Key system from guessable single-use 6-digit codes to stronger multi-use alphanumeric keys, and refactors persistence to track individual key usages in a separate table (registration_key_uses) while adding max_uses/used_count to registration_keys.

Changes:

  • Generate and validate stronger registration key codes and normalize input (uppercasing), plus introduce max_uses and usage counting.
  • Add registration_key_uses tracking (model/repo/service/tests) and update admin/auth endpoints and related test helpers.
  • Update docs, dummy SQL generator, and README/assets to reflect the new API and project documentation direction.

Reviewed changes

Copilot reviewed 33 out of 73 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
scripts/generate_dummy_sql/sql_writer.py Writes SQL for separated registration_keys and registration_key_uses tables.
scripts/generate_dummy_sql/main.py Wires generation output into the updated SQL writer.
scripts/generate_dummy_sql/generator.py Generates 16-char codes and multi-use key usage rows for dummy data.
internal/stack/mock_test.go Renames tests (style cleanup).
internal/service/testenv_test.go Updates truncation and registration key fixtures for new schema.
internal/service/helpers_test.go Updates helper tests to new registration-code validation function.
internal/service/helpers.go Implements new registration-code validation and 16-char code generation.
internal/service/auth_service_test.go Updates auth service tests for multi-use keys and usage tracking.
internal/service/auth_service.go Implements multi-use registration keys and inserts key-usage records.
internal/repo/testenv_test.go Updates truncation to include registration_key_uses.
internal/repo/registration_key_repo_test.go Updates repo tests for max_uses/used_count and uses list.
internal/repo/registration_key_repo.go Updates listing query to include usage summary + loads uses list.
internal/models/user.go Makes bun column tags explicit (schema clarity).
internal/models/team.go Makes bun column tags explicit (schema clarity).
internal/models/submission.go Makes bun column tags explicit (schema clarity).
internal/models/stack.go Makes bun column tags explicit (schema clarity).
internal/models/registration_key.go Adds max_uses/used_count and new RegistrationKeyUse model + summaries.
internal/models/challenge.go Makes bun column tags explicit (schema clarity).
internal/models/app_config.go Makes bun column tags explicit (schema clarity).
internal/http/integration/testenv_test.go Updates integration fixtures and expected JSON fields for key usage tracking.
internal/http/integration/auth_test.go Updates integration auth test to use new-style keys.
internal/http/integration/admin_test.go Updates admin integration tests for 16-char codes and uses list.
internal/http/handlers/types.go Extends request type to accept optional max_uses.
internal/http/handlers/testenv_test.go Updates handler test env truncation and key fixtures for new schema.
internal/http/handlers/handler_test.go Updates handler tests to submit max_uses and new key format.
internal/http/handlers/handler.go Passes max_uses through admin create-keys handler and returns new fields.
internal/db/db.go Auto-migrates new registration_key_uses model and adds an index for it.
internal/config/config_test.go Renames tests (style cleanup).
internal/cache/redis_test.go Renames tests (style cleanup).
docs/docs/auth.md Updates registration docs for alphanumeric/multi-use keys.
docs/docs/admin.md Updates admin docs for max_uses, used_count, last_used_at, and uses list.
assets/README.md Removes assets naming README (cleanup).
assets/9_users_light.jpeg Adds UI screenshot asset.
assets/9_users_dark.jpeg Adds UI screenshot asset.
assets/8_groups_detail_light.jpeg Adds UI screenshot asset.
assets/8_groups_detail_dark.jpeg Adds UI screenshot asset.
assets/7_groups_light.jpeg Adds UI screenshot asset.
assets/7_groups_dark.jpeg Adds UI screenshot asset.
assets/6_scoreboard_group_leaderboard_light.jpeg Adds UI screenshot asset.
assets/6_scoreboard_group_leaderboard_dark.jpeg Adds UI screenshot asset.
assets/5_scoreboard_group_timeline_light.jpeg Adds UI screenshot asset.
assets/5_scoreboard_group_timeline_dark.jpeg Adds UI screenshot asset.
assets/4_scoreboard_leaderboard_light.jpeg Adds UI screenshot asset.
assets/4_scoreboard_leaderboard_dark.jpeg Adds UI screenshot asset.
assets/3_scoreboard_timeline_light.jpeg Adds UI screenshot asset.
assets/3_scoreboard_timeline_detail_light.jpeg Adds UI screenshot asset.
assets/3_scoreboard_timeline_detail_dark.jpeg Adds UI screenshot asset.
assets/3_scoreboard_timeline_dark.jpeg Adds UI screenshot asset.
assets/2_challenges_detail_light.jpeg Adds UI screenshot asset.
assets/2_challenges_detail_dark.jpeg Adds UI screenshot asset.
assets/1_challenges_light.jpeg Adds UI screenshot asset.
assets/1_challenges_dark.jpeg Adds UI screenshot asset.
assets/18_mobile_sidebar_light.jpeg Adds UI screenshot asset.
assets/18_mobile_sidebar_dark.jpeg Adds UI screenshot asset.
assets/17_admin_groups_light.jpeg Adds UI screenshot asset.
assets/17_admin_groups_dark.jpeg Adds UI screenshot asset.
assets/16_admin_registration_keys_ip_light.jpeg Adds UI screenshot asset.
assets/16_admin_registration_keys_ip_dark.jpeg Adds UI screenshot asset.
assets/15_admin_registration_keys_light.jpeg Adds UI screenshot asset.
assets/15_admin_registration_keys_dark.jpeg Adds UI screenshot asset.
assets/14_admin_challenge_management_edit_light.jpeg Adds UI screenshot asset.
assets/14_admin_challenge_management_edit_dark.jpeg Adds UI screenshot asset.
assets/13_admin_challenge_management_light.jpeg Adds UI screenshot asset.
assets/13_admin_challenge_management_dark.jpeg Adds UI screenshot asset.
assets/12_admin_create_challenge_light.jpeg Adds UI screenshot asset.
assets/12_admin_create_challenge_dark.jpeg Adds UI screenshot asset.
assets/11_profile_light.jpeg Adds UI screenshot asset.
assets/11_profile_dark.jpeg Adds UI screenshot asset.
assets/10_users_detail_light.jpeg Adds UI screenshot asset.
assets/10_users_detail_dark.jpeg Adds UI screenshot asset.
assets/0_main_light.jpeg Adds UI screenshot asset.
assets/0_main_dark.jpeg Adds UI screenshot asset.
README.md Updates README to link docs, note frontend repo split, and removes preview section.
Comments suppressed due to low confidence (1)

internal/db/db.go:52

  • AutoMigrate only runs CREATE TABLE ... IF NOT EXISTS for models. With this PR changing the registration_keys schema (new max_uses / used_count columns) and adding registration_key_uses, enabling AutoMigrate on an existing database won’t add/alter columns, which can lead to runtime SQL errors after deployment. Consider adding an explicit migration/ALTER step for existing tables (or switching to a real migration system) rather than relying on IfNotExists for evolving schemas.

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

@yulmwu
Copy link
Member Author

yulmwu commented Feb 15, 2026

@yulmwu yulmwu merged commit 3e1ad7c into main Feb 15, 2026
2 checks passed
@yulmwu yulmwu deleted the improve/registration-key branch February 15, 2026 11:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants