Skip to content

feat(cntr): resolve BE-36, BE-37, BE-38, BE-39 — rating, webhook logger, token blacklist, opening hours#1068

Merged
yusuftomilola merged 1 commit into
DistinctCodes:mainfrom
Tyler7x:feat/be-36-37-38-39-cntr-utilities
Jun 2, 2026
Merged

feat(cntr): resolve BE-36, BE-37, BE-38, BE-39 — rating, webhook logger, token blacklist, opening hours#1068
yusuftomilola merged 1 commit into
DistinctCodes:mainfrom
Tyler7x:feat/be-36-37-38-39-cntr-utilities

Conversation

@Tyler7x
Copy link
Copy Markdown
Contributor

@Tyler7x Tyler7x commented Jun 1, 2026

Summary

Implements four self-contained utility/service files in backend/cntr/, each with a paired unit test spec. All logic is pure TypeScript with no framework dependencies or external I/O.


BE-38 — In-Memory JWT Token Blacklist (#977)

File: backend/cntr/token-blacklist.util.ts

  • TokenBlacklist class backed by Map<string, Date>
  • blacklist(jti, expiresAt) — stores the token
  • isBlacklisted(jti) — returns false for unknown or expired JTIs
  • purgeExpired(now?) — removes all entries whose expiresAt < now; accepts optional now param for deterministic tests

BE-39 — Workspace Opening Hours Validator (#978)

File: backend/cntr/opening-hours.validator.ts

  • Exports OpeningHoursEntry, ValidationResult interfaces and validateOpeningHours(hours)
  • Validates HH:MM format with /^([01]\d|2[0-3]):[0-5]\d$/
  • Rejects closeTime <= openTime when isClosed = false
  • Rejects duplicate dayOfWeek entries
  • Accumulates all errors before returning — no fail-fast

BE-37 — Webhook Event Logger with Payload Sanitization (#976)

File: backend/cntr/webhook-event-logger.ts

  • Exports WebhookEventLog interface and createWebhookEventLog(event, payload, status, error?)
  • id generated via crypto.randomUUID()
  • receivedAt is ISO 8601 string
  • Sanitizes payload by removing keys matching /(card|cvv|pan|account_number)/i (case-insensitive)
  • Original payload object is not mutated — operates on a shallow copy

BE-36 — Workspace Rating Service (#975)

File: backend/cntr/workspace-rating.service.ts

  • Exports WorkspaceRating interface, validateRating, and computeAverageRating
  • validateRating throws RangeError for score outside 1–5 and Error for comment > 500 chars
  • computeAverageRating([]) returns 0
  • Average rounded to 1 decimal place via Math.round(avg * 10) / 10

Test plan

  • backend/cntr/token-blacklist.util.spec.ts — 6 tests covering unknown JTIs, valid tokens, expired tokens, purgeExpired with and without now
  • backend/cntr/opening-hours.validator.spec.ts — 9 tests covering format errors, close≤open, duplicate days, multi-error accumulation, isClosed bypass, full week
  • backend/cntr/webhook-event-logger.spec.ts — 7 tests covering UUID format, ISO date, sensitive key removal (all variants), no mutation, empty payload
  • backend/cntr/workspace-rating.service.spec.ts — 13 tests covering all invalid scores, comment length boundary, all valid scores 1–5, average edge cases

Closes #975
Closes #976
Closes #977
Closes #978

@vercel
Copy link
Copy Markdown

vercel Bot commented Jun 1, 2026

@Tyler7x is attempting to deploy a commit to the naijabuz's projects Team on Vercel.

A member of the Team first needs to authorize it.

@drips-wave
Copy link
Copy Markdown

drips-wave Bot commented Jun 1, 2026

@Tyler7x Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

- BE-38 (DistinctCodes#977): Add TokenBlacklist class with Map-based in-memory store;
  blacklist/isBlacklisted/purgeExpired with optional now param for testability;
  isBlacklisted returns false for expired or unknown JTIs

- BE-39 (DistinctCodes#978): Add validateOpeningHours with HH:MM regex validation, close>open
  enforcement when isClosed=false, duplicate dayOfWeek detection, and full
  multi-error accumulation (no fail-fast)

- BE-37 (DistinctCodes#976): Add createWebhookEventLog with randomUUID id, ISO 8601 receivedAt,
  and payload sanitization that strips keys matching /(card|cvv|pan|account_number)/i
  without mutating the original object

- BE-36 (DistinctCodes#975): Add WorkspaceRating service with validateRating (throws RangeError
  for score outside 1-5, Error for comment >500 chars) and computeAverageRating
  (1 decimal precision, returns 0 for empty array)

Closes #975Closes #976Closes #977Closes DistinctCodes#978

Co-Authored-By: Demilade18-git <Demilade18-
@Tyler7x Tyler7x force-pushed the feat/be-36-37-38-39-cntr-utilities branch from 9b6fc3d to 4190e47 Compare June 2, 2026 00:34
Copy link
Copy Markdown
Collaborator

@yusuftomilola yusuftomilola left a comment

Choose a reason for hiding this comment

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

Perfect implementation

@yusuftomilola yusuftomilola merged commit d65b40f into DistinctCodes:main Jun 2, 2026
1 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants