Known Issues & Technical Debt
These are accepted risks and known limitations, documented so future work can address them post-launch.
Active Issues
CI Runner on Production Server (Hermes)
Severity: Medium
Status: Accepted risk
The GitHub Actions self-hosted runner runs on Hermes, the production server. This means:
- A malicious pull request could potentially execute code on the production server (mitigated by branch protection — only
masteranddeveloptrigger CI) - A resource-intensive CI job could impact production performance
Fix post-launch: Move the CI runner to a dedicated instance or use GitHub-hosted runners for PRs.
Claim Endpoint Accepts userId from Request Body
Severity: Medium
Status: Accepted risk for MVP
POST /claim accepts { claimCode, userId } from the request body. A user could theoretically claim an order on behalf of another user by providing a different userId.
Mitigations in place:
- If the order is already claimed by a different user,
ForbiddenExceptionis thrown - The
userIdmust be a valid user in the database (foreign key constraint) - The endpoint is rate-limited (10/15min)
Fix post-launch: Extract userId from the session instead of the request body.
No Unit Tests
Severity: Medium
Status: Post-launch
No automated unit or integration tests. The application is manually tested. CI runs typecheck, lint, and build — but no runtime tests.
Risk: Regressions in state machine logic (order transitions) or payment verification could go undetected.
Fix post-launch: Add Jest unit tests for order-transitions.ts, PaymentsService.verifyPayment(), and the ClaimService.claim() flow.
Floating-Point Arithmetic for Order Totals
Severity: Medium
Status: Post-launch
Order totals are calculated using JavaScript number (IEEE 754 double-precision float). This can cause rounding errors:
0.1 + 0.2 = 0.30000000000000004
For a custom PC order with many line items, accumulated floating-point error could cause displayed totals to differ by a few cents from the actual total.
Fix post-launch: Migrate to decimal.js or store totals as integers (cents) in the database. Prisma already uses Decimal type for basePrice — extend this to all pricing fields.
Claim Code Entropy (~10M Combinations)
Severity: Medium
Status: Post-launch
The NNN-NNNN-NNN format provides approximately 10 million combinations (10³ × 10⁴ × 10³ = 10¹⁰, but constrained by digit-only format: 10³ × 10⁴ × 10³ = 10,000,000,000 → actually randomInt gives ~10B combinations with the current format).
The format is: 3 digits, 4 digits, 3 digits. Each generated using randomInt. This is ~1 billion combinations, not 10M as previously estimated.
At current scale (< 1000 orders), collision probability is negligible. The code does check for uniqueness before saving.
Fix post-launch: If order volume grows significantly, switch to crypto.randomBytes-based generation for higher entropy.
Attachment entityId Has No FK Constraint
Severity: Low
Status: Documented design decision
The Attachment.entityId field stores the ID of the owning entity (order, build, etc.) but there is no database foreign key constraint on it. This means:
- Orphaned attachments can exist if an entity is deleted
- The
entityType+entityIdcombination cannot be validated by the DB
Why: Supporting a polymorphic model with proper FKs in Prisma/PostgreSQL requires complex workarounds (union types, join tables, etc.).
Fix post-launch: Implement a periodic cleanup job that deletes attachments where no matching entity exists.
baseUrl Deprecated in tsconfig
Severity: Low
Status: Cosmetic
One or more tsconfig.json files use the deprecated baseUrl option. This shows as a squiggle in VS Code but does not affect compilation or runtime behavior.
as any Casts in Order/Build Services
Severity: Low
Status: Post-launch
Some service methods use as any type casts when working with Prisma query results, particularly for complex include queries where the return type doesn't match the expected interface exactly.
Fix post-launch: Migrate to Prisma.OrderGetPayload<{ include: { ... } }> types for proper type safety.
Resolved Issues
These were previously listed as known issues and have been fixed:
| Issue | Resolution |
|---|---|
| Cross-subdomain session cookies | Fixed: COOKIE_DOMAIN=.pcmr.gr in prod |
| Staff portal accessible without auth | Fixed: Cloudflare Access + FirstLoginGuard |
| 2FA cookie not being set | Fixed: Manual cookie signing in /api/2fa-verify/route.ts |
| LocalStorageService in production | Fixed: Removed; HetznerStorageService is the only implementation |
Duplicate middleware.ts in web | Fixed: Renamed to proxy.ts; duplicate removed |