| type | Feature |
|---|---|
| title | Implement a real email transport in the email queue processor |
| labels | type:feature, area:queue, stack:nodejs, stack:typescript, priority:high, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN |
| assignees |
processEmailNotification in src/queue/processors/email-processor.ts does not send email β it validates subject/body, then calls simulateEmailSend, which only console.logs the payload and resolves after a 100ms setTimeout. The function returns { success: true } regardless, so every queued email job "succeeds" while nothing is delivered. The inline comments explicitly say "replace with actual email service integration" (SendGrid, AWS SES, etc.). This issue wires a real, injectable email transport so queued notifications are actually delivered.
- Repository scope: Talenttrust/Talenttrust-Backend only.
- Introduce an
EmailTransportinterface so a real provider (SMTP/SendGrid/SES) can be configured and a mock injected in tests; select the transport from validated config insrc/config/env.schema.ts. - Replace
simulateEmailSendwith a real dispatch that surfaces provider failures so the job fails (and is retried) instead of silently succeeding. - Validate the recipient
towith a strict email check and guard against header injection before dispatch. - Keep the existing return shape
{ success, message, data: { emailId } }and the job-failure semantics expected by the queue manager insrc/queue/queue-manager.ts. - Do not log full recipient addresses or bodies at info level; route through the structured logger in
src/logger.ts.
- Fork the repo and create a branch
git checkout -b feature/queue-31-email-transport- Implement changes
- Write code in:
src/queue/processors/email-processor.tsand createsrc/queue/processors/email.transport.ts. - Write comprehensive tests in:
src/queue/processors/email-processor.test.tsβ mock the transport and assert delivery, provider-failure propagation, and recipient validation. - Add documentation: create
docs/email-notifications.mddescribing transport selection and config. - Add TSDoc to the new interface and dispatch method.
- Validate security: header-injection guard, no PII in logs.
- Write code in:
- Test and commit
- Run
npm run lintandnpm test. - Cover edge cases: missing subject/body, invalid recipient, transport throws, transport timeout.
- Include the full
npm testoutput and notes in the PR.
feat(queue): implement real email transport in the email processor
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the TalentTrust community on Discord for questions, reviews, and faster merges: https://discord.gg/WqnGpcPx
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Wire the blockchain sync queue processor to real RPC block ingestion" labels: type:feature, area:queue, stack:nodejs, stack:typescript, priority:high, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
processBlockchainSync in src/queue/processors/blockchain-processor.ts iterates a block range and calls a processBatch helper that does nothing but console.log(\Processed ${network} blocks ...`) after an artificial delay β no RPC calls and no events are ingested. The job reports success while no blockchain data is synced. This issue connects the processor to the real Stellar/Soroban RPC layer already present in [src/services/soroban/SorobanRpcService.ts`](src/services/soroban/SorobanRpcService.ts) and persists ingested events through the existing indexer.
- Repository scope: Talenttrust/Talenttrust-Backend only.
- Replace
processBatchwith real ledger/event fetches viasrc/services/soroban/SorobanRpcService.ts, usingSOROBAN_RPC_URL/SOROBAN_CONTRACT_IDfromsrc/config/env.schema.ts. - Persist ingested events idempotently through
src/services/indexer.ts, reusing dedupe insrc/contracts/dedupe.tsso replayed batches do not double-write. - Wrap RPC calls in the existing breaker from
src/circuit-breaker/CircuitBreaker.ts; fail the job (so it retries) on RPC error instead of resolving silently. - Track the last-synced block so a restarted job resumes rather than re-scanning from zero.
- Apply SSRF guards via
src/utils/ssrf.tson the configured RPC URL.
- Fork the repo and create a branch
git checkout -b feature/queue-32-blockchain-sync-rpc- Implement changes
- Write code in:
src/queue/processors/blockchain-processor.ts. - Write comprehensive tests in:
src/queue/processors/blockchain-processor.test.tsβ mock the RPC client and indexer; assert ingestion, idempotency, breaker-open, and resume. - Add documentation: update the Soroban/sync section of
README.md. - Add TSDoc to the ingestion helper.
- Validate security: SSRF guard on RPC URL; no secrets in logs.
- Write code in:
- Test and commit
- Run
npm run lintandnpm test. - Cover edge cases: empty range, RPC timeout, breaker open, duplicate batch replay.
- Include the full
npm testoutput and notes in the PR.
feat(queue): wire blockchain sync processor to real RPC block ingestion
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the TalentTrust community on Discord for questions, reviews, and faster merges: https://discord.gg/WqnGpcPx
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Replace mock freelancer enumeration in the reputation recompute processor" labels: type:feature, area:queue, stack:nodejs, stack:typescript, priority:high, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
getAllFreelancerIds in src/queue/processors/reputation-recompute-processor.ts is a hardcoded stub that returns synthetic ids freelancer-1 β¦ freelancer-1000 in a loop, with a comment stating "this is a mock implementation - in production, this would query the database." As a result, the bulk recompute job operates on fake ids and never recomputes a single real freelancer's score. This issue replaces the stub with a real, paginated query against the reputation store so the job recomputes actual subjects.
- Repository scope: Talenttrust/Talenttrust-Backend only.
- Replace
getAllFreelancerIdswith a query againstsrc/repositories/reputationRepository.ts/src/models/reputation.store.tsthat returns the distinct subject ids that actually have ratings. - Stream/paginate the id list so recompute does not load the entire table into memory at once.
- Reuse the aggregation in
src/services/reputation.service.tsand persist a checkpoint viasrc/models/reputation-checkpoint.store.tsso on-demand and scheduled recompute stay consistent. - Preserve the per-subject error isolation already in the processor (one failure must not abort the batch).
- Fork the repo and create a branch
git checkout -b feature/queue-33-real-freelancer-recompute- Implement changes
- Write code in:
src/queue/processors/reputation-recompute-processor.ts. - Write comprehensive tests in:
src/queue/processors/reputation-recompute-processor.test.tsβ mock the repository; assert pagination, per-subject isolation, and checkpoint writes. - Add documentation: note the recompute flow in
docs/reputation-scoring.md(or create it if absent). - Add TSDoc to the new query method.
- Validate: empty store yields zero work without error.
- Write code in:
- Test and commit
- Run
npm run lintandnpm test. - Cover edge cases: no freelancers, single page, multi-page, one subject throwing.
- Include the full
npm testoutput and notes in the PR.
feat(queue): query real freelancer ids in reputation recompute processor
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the TalentTrust community on Discord for questions, reviews, and faster merges: https://discord.gg/WqnGpcPx
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Implement real deployment promotion, rollback, and promotion history" labels: type:feature, area:deployment, stack:nodejs, stack:typescript, priority:medium, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
promoteDeployment and rollbackDeployment in src/deployment/promoter.ts return a success object without doing anything β the inline comments list the intended steps ("tag the version, trigger pipeline, run smoke tests, update registry") and then immediately return a mock. getPromotionHistory likewise returns an empty array ("for now, return empty array"). Operators see "promoted" responses with no real effect and no audit trail. This issue implements real promotion/rollback orchestration with persisted history.
- Repository scope: Talenttrust/Talenttrust-Backend only.
- Implement
promoteDeploymentto run the deployment validator insrc/deployment/validator.ts, execute a health/smoke check against the target, and only then record the promotion. - Persist promotion/rollback records (timestamp, fromβto, actor, outcome) so
getPromotionHistoryreturns real data; emit an audit entry viasrc/audit/service.ts. - Implement
rollbackDeploymentto restore the previous recorded version and write a corresponding history/audit entry. - Keep the existing function signatures and the success/error shape consumed by
src/routes/deploy.routes.ts. - Reuse the blue-green color/port logic in
src/deploy.tsrather than duplicating it.
- Fork the repo and create a branch
git checkout -b feature/deployment-34-real-promotion- Implement changes
- Write code in:
src/deployment/promoter.ts. - Write comprehensive tests in:
src/deployment/promoter.test.tsβ assert validation gate, history persistence, rollback restores prior version, and audit emission. - Add documentation: update
docs/deploy.mdwith the promotion/rollback lifecycle. - Add TSDoc to the three functions.
- Validate: failed validation blocks promotion; rollback is recorded.
- Write code in:
- Test and commit
- Run
npm run lintandnpm test. - Cover edge cases: validation failure, rollback with no prior version, repeated promotion, history ordering.
- Include the full
npm testoutput and notes in the PR.
feat(deployment): implement real promotion, rollback, and persisted history
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the TalentTrust community on Discord for questions, reviews, and faster merges: https://discord.gg/WqnGpcPx
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Implement archived-data listing and statistics in the retention archival service" labels: type:feature, area:retention, stack:nodejs, stack:typescript, priority:medium, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
listArchivedData and getArchiveStats in src/retention/archival.ts are stubs: listArchivedData always returns [] (with a "placeholder for more comprehensive listing" comment) and getArchiveStats returns { totalArchived: 0, byStorageType: {} }. This makes the archived-data inventory invisible β a problem for compliance reporting (GDPR/retention audits) and for the purge flow in src/retention/purge.ts, which has no accurate view of what has been archived. This issue implements real enumeration and statistics over the configured storage backends.
- Repository scope: Talenttrust/Talenttrust-Backend only.
- Implement
listArchivedData(storageType?)to enumerate archived records from the storage layer insrc/retention/storage.ts, filtering byArchivalStorageTypewhen provided. - Implement
getArchiveStats()to return a realtotalArchivedcount and abyStorageTypebreakdown derived from the storage layer. - Support pagination/bounded reads so large archives do not load fully into memory.
- Preserve the existing
RetainedDatashape fromsrc/retention/types.tsand the policies insrc/retention/policies.ts.
- Fork the repo and create a branch
git checkout -b feature/retention-35-archive-inventory- Implement changes
- Write code in:
src/retention/archival.ts. - Write comprehensive tests in:
src/retention/retention.test.tsβ seed mock archives across storage types and assert listing/filtering and stat counts. - Add documentation: update
docs/DATA_RETENTION.mdwith the inventory/stats API. - Add TSDoc to both methods.
- Validate: counts match listed records across storage types.
- Write code in:
- Test and commit
- Run
npm run lintandnpm test. - Cover edge cases: empty archive, single storage type, mixed storage types, pagination boundary.
- Include the full
npm testoutput and notes in the PR.
feat(retention): implement archived-data listing and statistics
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the TalentTrust community on Discord for questions, reviews, and faster merges: https://discord.gg/WqnGpcPx
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Add queue and circuit-breaker health probes to the readiness endpoint" labels: type:enhancement, area:health, stack:nodejs, stack:typescript, priority:medium, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
The probes in src/health/probes.ts cover environment, database, Redis, and Stellar RPC, but they do not surface the health of background job processing. QueueManager.getHealth() already exists in src/queue/queue-manager.ts and the breaker registry in src/circuit-breaker/registry.ts tracks open breakers β yet neither is wired into the health check. A node can report "ready" while its queues are backed up or breakers are tripped, so load balancers keep routing traffic to a broken instance. This issue adds probes for queue and breaker health.
- Repository scope: Talenttrust/Talenttrust-Backend only.
- Add a
queueProbethat callsQueueManager.getHealth()and reports degraded/failed when failed-job counts or backlog exceed configurable thresholds. - Add a
circuitBreakerProbethat reports the number of open breakers fromsrc/circuit-breaker/registry.ts. - Register both in the probe runner so they appear in
/health/readyviasrc/health/router.ts; keep probe timeouts bounded so health never blocks. - Make probe thresholds configurable through the validated config and do not leak internal error detail in the response body.
- Fork the repo and create a branch
git checkout -b enhancement/health-36-queue-breaker-probes- Implement changes
- Write code in:
src/health/probes.ts. - Write comprehensive tests in:
src/health/probes.test.tsβ mock queue/breaker state and assert ok/degraded/failed mapping and timeout safety. - Add documentation: update the health section of
README.mdand any health docs. - Add TSDoc to the new probes.
- Validate: probes are bounded and never throw out of the runner.
- Write code in:
- Test and commit
- Run
npm run lintandnpm test. - Cover edge cases: healthy queue, backed-up queue, one breaker open, probe timeout.
- Include the full
npm testoutput and notes in the PR.
feat(health): add queue and circuit-breaker readiness probes
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the TalentTrust community on Discord for questions, reviews, and faster merges: https://discord.gg/WqnGpcPx
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Replace O(n) API key validation with an indexed hashed-key lookup" labels: type:enhancement, area:api-keys, stack:nodejs, stack:typescript, priority:medium, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
validateApiKey in src/auth/apiKeys.ts loads every active key and loops over them, calling verifyApiKey (PBKDF2) once per stored key until a match is found β the code's own comment admits "in a real implementation, you'd need to iterate through keys or use an index." With N active keys this runs up to N expensive PBKDF2 hashes on every authenticated request, a clear scaling and DoS-amplification risk. This issue introduces an indexed lookup so validation is O(1) in the number of stored keys.
- Repository scope: Talenttrust/Talenttrust-Backend only.
- Add a deterministic lookup index: store a separate fast key-id/selector (e.g. HMAC or SHA-256 of the presented key, distinct from the slow per-key salted hash) so a candidate row can be found without scanning all keys.
- After the indexed lookup, still verify with the existing salted
verifyApiKeyto keep the strong per-key hash as the source of truth. - Preserve expiry deactivation,
last_used_atupdate, and the returnedApiKeyInfoshape. - Provide a migration so existing keys gain the new selector without invalidating them.
- Fork the repo and create a branch
git checkout -b enhancement/api-keys-37-indexed-lookup- Implement changes
- Write code in:
src/auth/apiKeys.tsand a migration insrc/db/migrations.ts. - Write comprehensive tests in:
src/auth/__tests__/apiKeys.test.tsβ assert single-hash lookup, expired-key deactivation, and unknown-key rejection. - Add documentation: update
docs/api-keys.mdwith the lookup model. - Add TSDoc to the new lookup helper.
- Validate security: selector is non-reversible; verification still uses the salted hash; constant-time compare on the selector.
- Write code in:
- Test and commit
- Run
npm run lintandnpm test. - Cover edge cases: no keys, expired key, revoked key, valid key among many.
- Include the full
npm testoutput and a security notes section in the PR.
feat(api-keys): add indexed lookup to remove O(n) key validation scan
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the TalentTrust community on Discord for questions, reviews, and faster merges: https://discord.gg/WqnGpcPx
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Add unit tests for the stale-while-revalidate cache utility" labels: type:test, area:utils, stack:nodejs, stack:typescript, priority:medium, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
SWRCache in src/utils/swrCache.ts serves cached values, triggers background revalidation, coalesces in-flight fetches, and swallows revalidation errors with a single console.error β but it has no test file. Its concurrency and staleness behavior gate any consumer that relies on it, and untested cache stampede / error handling is a latent reliability risk. This issue adds a deterministic unit suite.
- Repository scope: Talenttrust/Talenttrust-Backend only.
- Assert a fresh hit returns the cached value without calling the fetcher.
- Assert a stale hit returns the stale value immediately and revalidates in the background exactly once (coalescing concurrent callers).
- Assert a cache miss awaits the fetcher and populates the entry.
- Assert a failed background revalidation does not throw to callers and the stale value is retained.
- Use fake timers to control TTL/staleness deterministically; no real delays.
- Fork the repo and create a branch
git checkout -b test/utils-38-swr-cache- Implement changes
- Write comprehensive tests in: create
src/utils/swrCache.test.ts. - Write code in: none expected beyond a minimal test seam if required.
- Add documentation: add usage notes in TSDoc on
SWRCache. - Add TSDoc to shared test helpers.
- Validate: tests are deterministic and leave no open timers.
- Write comprehensive tests in: create
- Test and commit
- Run
npm run lintandnpm run test:ci. - Cover edge cases: fresh, stale-with-revalidate, miss, revalidation error, concurrent miss coalescing.
- Include the full
npm testoutput and notes in the PR.
test(utils): add deterministic coverage for SWR cache
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the TalentTrust community on Discord for questions, reviews, and faster merges: https://discord.gg/WqnGpcPx
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Add tests for the timing-safe deduplication manager" labels: type:test, area:utils, stack:nodejs, stack:typescript, priority:medium, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
DeduplicationManager in src/utils/deduplication.ts hashes payloads and compares them with crypto.timingSafeEqual, including an explicit equal-length guard before the constant-time compare. This is security-sensitive (timing-attack resistance) and gates dedupe correctness, yet there is no test file. This issue adds focused coverage for hashing, equal/unequal comparison, and the length-guard branch.
- Repository scope: Talenttrust/Talenttrust-Backend only.
- Assert identical payloads are detected as duplicates and distinct payloads are not.
- Assert the equal-length guard is exercised so
timingSafeEqualis never called with mismatched buffer lengths. - Assert the hash is stable for identical input and changes for different input.
- Cover any TTL/eviction behavior the manager exposes deterministically (fake timers if time-based).
- Fork the repo and create a branch
git checkout -b test/utils-39-deduplication- Implement changes
- Write comprehensive tests in: create
src/utils/deduplication.test.ts. - Write code in: none expected.
- Add documentation: add TSDoc clarifying the timing-safe rationale.
- Add TSDoc to shared test helpers.
- Validate security: no comparison path bypasses the length guard.
- Write comprehensive tests in: create
- Test and commit
- Run
npm run lintandnpm run test:ci. - Cover edge cases: identical payload, different payload, different-length payloads, empty payload.
- Include the full
npm testoutput and a short security notes section in the PR.
test(utils): cover timing-safe deduplication manager
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the TalentTrust community on Discord for questions, reviews, and faster merges: https://discord.gg/WqnGpcPx
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Add unit tests for the API key and audit middleware" labels: type:test, area:audit, stack:nodejs, stack:typescript, stack:express, priority:medium, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
Three request-path middleware modules have no dedicated unit tests: src/auth/apiKeyMiddleware.ts (authenticateApiKey, requireApiKeyScope, authenticateEither), src/audit/middleware.ts (the auditMiddleware request wrapper), and src/audit/protectedEndpointMiddleware.ts (the res.on('finish') audit hook). These guard authentication fallbacks, scope checks, and audit-trail emission, so their error and edge paths are security-critical and currently unverified. This issue adds isolated coverage.
- Repository scope: Talenttrust/Talenttrust-Backend only.
- For
authenticateApiKey: assert missing/invalidX-API-Keyis rejected and a valid key populates the request principal. - For
requireApiKeyScope: assert scope match, scope mismatch (403), and missing-scope handling. - For
authenticateEither: assert the JWT path and the API-key fallback path, plus the both-missing rejection. - For the audit middleware: assert an audit entry is emitted on response finish with correlation id and that handler errors still produce an audit record.
- Fork the repo and create a branch
git checkout -b test/audit-40-middleware-coverage- Implement changes
- Write comprehensive tests in: create
src/auth/apiKeyMiddleware.test.ts,src/audit/middleware.test.ts, andsrc/audit/protectedEndpointMiddleware.test.ts. - Write code in: none expected beyond minimal test seams.
- Add documentation: note the covered scenarios in the relevant module TSDoc.
- Add TSDoc to shared mocks/helpers.
- Validate security: 401/403 paths do not leak internal detail.
- Write comprehensive tests in: create
- Test and commit
- Run
npm run lintandnpm run test:ci. - Cover edge cases: missing header, wrong scope, JWT+API-key fallback, audit on error.
- Include the full
npm testoutput and a security notes section in the PR.
test(audit): add unit coverage for API key and audit middleware
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the TalentTrust community on Discord for questions, reviews, and faster merges: https://discord.gg/WqnGpcPx
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Add tests for the utils redaction helper and webhook metrics counters" labels: type:test, area:observability, stack:nodejs, stack:typescript, priority:low, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
Two observability/security utilities ship without test files: src/utils/redact.ts (sensitive-field redaction used before logging) and src/utils/webhookMetrics.ts (the counters/gauges for webhook delivery). Untested redaction risks leaking secrets into logs, and untested metric accumulation risks silently wrong dashboards. This issue adds focused coverage for both.
- Repository scope: Talenttrust/Talenttrust-Backend only.
- For redaction: assert known sensitive keys (tokens, auth headers, secrets) are masked, nested objects are handled, and non-sensitive fields pass through unchanged.
- For webhook metrics: assert outcome counters increment for success/retry/dlq and that label cardinality stays bounded (host/status only, never raw URLs).
- Keep tests independent of any live Prometheus registry by resetting metrics between cases.
- Do not assert on real secret values in test output.
- Fork the repo and create a branch
git checkout -b test/observability-41-redact-webhook-metrics- Implement changes
- Write comprehensive tests in: create
src/utils/redact.test.tsandsrc/utils/webhookMetrics.test.ts. - Write code in: none expected.
- Add documentation: note redaction keys and metric names in TSDoc.
- Add TSDoc to shared fixtures.
- Validate security: no secret value appears in assertions or snapshots.
- Write comprehensive tests in: create
- Test and commit
- Run
npm run lintandnpm run test:ci. - Cover edge cases: nested sensitive object, unknown key, success/retry/dlq increments, label bounds.
- Include the full
npm testoutput and notes in the PR.
test(observability): cover redaction helper and webhook metrics counters
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the TalentTrust community on Discord for questions, reviews, and faster merges: https://discord.gg/WqnGpcPx
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Remove the hardcoded fallback HMAC secret in compliance audit proof generation" labels: type:security, area:retention, stack:nodejs, stack:typescript, priority:high, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
generateProof in src/retention/audit.ts builds an HMAC over compliance audit records using process.env.COMPLIANCE_AUDIT_SECRET || 'talenttrust-compliance-secret-key-2024'. When the env var is unset, the proof is signed with a secret that is committed to source control β anyone can forge or validate proofs, which defeats the tamper-evidence the audit trail is supposed to provide for DELETE/ARCHIVE operations. This issue removes the fallback and fails fast when the secret is absent.
- Repository scope: Talenttrust/Talenttrust-Backend only.
- Delete the literal fallback; require
COMPLIANCE_AUDIT_SECRETand read it from the validated config insrc/config/env.schema.tswith a minimum length. - Fail fast at startup (consistent with the existing
validateEnvbehavior) when the secret is missing outside tests, rather than silently signing with a weak key. - Never log the secret value; preserve any existing security notes in the file.
- Update
.env.examplewith guidance on generating a strong secret.
- Fork the repo and create a branch
git checkout -b security/retention-42-audit-proof-secret- Implement changes
- Write code in:
src/retention/audit.tsandsrc/config/env.schema.ts. - Write comprehensive tests in:
src/retention/retention.test.tsβ assert proof verification with a configured secret and that boot fails without one. - Add documentation: update
docs/DATA_RETENTION.mdand.env.example. - Add TSDoc explaining the security rationale.
- Validate security: no fallback secret remains; secret never appears in logs or errors.
- Write code in:
- Test and commit
- Run
npm run lintandnpm test. - Cover edge cases: missing secret, short secret, valid secret, tampered record fails verification.
- Include the full
npm testoutput and a security notes section in the PR.
fix(security): require COMPLIANCE_AUDIT_SECRET and drop hardcoded fallback
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the TalentTrust community on Discord for questions, reviews, and faster merges: https://discord.gg/WqnGpcPx
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Make contract-metadata sensitive masking fail-closed when the caller is unknown" labels: type:security, area:contract-metadata, stack:nodejs, stack:typescript, priority:high, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
formatResponse in src/modules/contractMetadata/contractMetadata.service.ts masks sensitive values only when metadata.is_sensitive && user && metadata.created_by !== user.id && user.role !== 'admin'. Because the condition requires user to be truthy to mask, a request where user is undefined (the controller passes an optional req.user) skips masking entirely and returns the raw sensitive value. This is fail-open: an unauthenticated/unknown caller sees more than an authenticated non-owner. This issue inverts the logic so masking is the default and only the owner/admin sees the clear value.
- Repository scope: Talenttrust/Talenttrust-Backend only.
- Recompute
shouldMaskValueso that for anis_sensitiverecord the value is masked unless the caller is the owner (metadata.created_by === user.id) or anadmin; an absent/undefinedusermust always be masked. - Keep the
***REDACTED***placeholder and the rest of the response shape unchanged. - Ensure the controller in
src/modules/contractMetadata/contractMetadata.controller.tspasses the authenticated user consistently. - This is a fail-closed security fix; do not broaden who can see clear values.
- Fork the repo and create a branch
git checkout -b security/contract-metadata-43-mask-fail-closed- Implement changes
- Write code in:
src/modules/contractMetadata/contractMetadata.service.ts. - Write comprehensive tests in:
src/modules/contractMetadata/contractMetadata.test.tsβ assert masking for undefined user, non-owner, and clear value only for owner/admin. - Add documentation: note the masking rule in the module TSDoc and
docs/API.md. - Add TSDoc to
formatResponse. - Validate security: no path returns a sensitive clear value to an unknown caller.
- Write code in:
- Test and commit
- Run
npm run lintandnpm test. - Cover edge cases: undefined user, non-owner user, owner, admin, non-sensitive record.
- Include the full
npm testoutput and a security notes section in the PR.
fix(security): fail closed on contract-metadata sensitive masking
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the TalentTrust community on Discord for questions, reviews, and faster merges: https://discord.gg/WqnGpcPx
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Replace the always-true blue-green health checker with a real readiness probe" labels: type:security, area:deployment, stack:nodejs, stack:typescript, priority:high, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
The default _healthChecker in src/deploy.ts is a stub that always returns true (its comment shows the intended GET /health/ready check that was never implemented). switchToGreen relies on this checker before cutting traffic over, so a blue-green deployment will promote an instance that is actually unhealthy β defeating the entire safety gate. This issue replaces the mock with a real, timeout-bounded HTTP readiness probe.
- Repository scope: Talenttrust/Talenttrust-Backend only.
- Implement the default checker to call the target's
/health/readyendpoint (served bysrc/health/router.ts) and treat only a200/ready response as healthy. - Apply a bounded timeout and a small retry/poll window before declaring failure; keep the existing injectable seam (
setHealthChecker) for tests. - Validate the target URL/port with the SSRF guard in
src/utils/ssrf.tsso the probe cannot be pointed at arbitrary internal hosts. - Ensure
switchToGreenaborts the cutover (no traffic switch) when the probe fails.
- Fork the repo and create a branch
git checkout -b security/deployment-44-real-health-checker- Implement changes
- Write code in:
src/deploy.ts. - Write comprehensive tests in:
src/deploy.test.tsβ mock the HTTP probe and assert healthyβswitch, unhealthyβabort, and timeout handling. - Add documentation: update
docs/deploy.mdwith the readiness-gate behavior. - Add TSDoc to the checker.
- Validate security: SSRF guard on the probe target; bounded timeout.
- Write code in:
- Test and commit
- Run
npm run lintandnpm test. - Cover edge cases: ready 200, not-ready 503, connection refused, probe timeout.
- Include the full
npm testoutput and a security notes section in the PR.
fix(deployment): use a real readiness probe in the blue-green health checker
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the TalentTrust community on Discord for questions, reviews, and faster merges: https://discord.gg/WqnGpcPx
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Document the API key lifecycle, scopes, and rotation" labels: type:docs, area:api-keys, stack:nodejs, stack:typescript, priority:low, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
API keys are created, validated, scoped, and revoked across src/auth/apiKeys.ts, src/auth/apiKeyMiddleware.ts, src/controllers/apiKeyController.ts, and src/routes/apiKeys.routes.ts, with hashing via salted PBKDF2 and per-key scopes. The existing docs/api-keys.md does not fully explain the lifecycle (issue β use β expire β revoke), the scope vocabulary, or rotation guidance. This issue completes the integrator-facing documentation.
- Repository scope: Talenttrust/Talenttrust-Backend only.
- Document key creation, the returned plaintext-once secret, hashing/storage (salt:hash), and how
X-API-Keyis presented on requests. - Enumerate the available scopes and how
requireApiKeyScopeenforces them, plus the JWT-or-key fallback viaauthenticateEither. - Describe expiry/
expires_atdeactivation, revocation, and a recommended rotation procedure. - Cross-link the auth section of
README.md.
- Fork the repo and create a branch
git checkout -b docs/api-keys-45-lifecycle- Implement changes
- Write code in: none beyond doc-only clarifying TSDoc.
- Write comprehensive tests in: rely on existing API key tests to confirm documented behavior.
- Add documentation: expand
docs/api-keys.md. - Ensure documented scopes match the code.
- Validate: examples reflect real request/response shapes.
- Test and commit
- Run
npm run lintto ensure no drift. - Cross-check documented scopes and headers against the implementation.
- Include notes in the PR confirming accuracy.
docs(api-keys): document key lifecycle, scopes, and rotation
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the TalentTrust community on Discord for questions, reviews, and faster merges: https://discord.gg/WqnGpcPx
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Document the data retention, archival, and purge lifecycle" labels: type:docs, area:retention, stack:nodejs, stack:typescript, priority:low, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
The retention subsystem spans policies in src/retention/policies.ts, archival in src/retention/archival.ts, purge in src/retention/purge.ts, storage in src/retention/storage.ts, and compliance audit proofs in src/retention/audit.ts, with a partial docs/DATA_RETENTION.md. Operators lack a single guide describing how data flows from active β archived β purged and how compliance proofs are generated. This issue completes that documentation.
- Repository scope: Talenttrust/Talenttrust-Backend only.
- Describe the retention policy model, how archival selects records, and how purge enforces deletion windows.
- Document the storage backends/types and how compliance proofs (HMAC) make DELETE/ARCHIVE actions tamper-evident.
- Explain configuration (retention periods, the audit secret) and the safety guarantees (idempotent re-runs).
- Include a sequence diagram of active β archive β purge with a proof checkpoint.
- Fork the repo and create a branch
git checkout -b docs/retention-46-lifecycle- Implement changes
- Write code in: none beyond doc-only clarifying comments.
- Write comprehensive tests in: rely on
src/retention/retention.test.tsandsrc/retention/purge.test.tsto confirm behavior matches docs. - Add documentation: expand
docs/DATA_RETENTION.mdand link it fromREADME.md. - Ensure documented policies match the constants in code.
- Validate: diagram and steps match the implementation.
- Test and commit
- Run
npm run lintto ensure no drift. - Cross-check documented retention windows against
src/retention/policies.ts. - Include notes in the PR confirming accuracy.
docs(retention): document retention, archival, and purge lifecycle
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the TalentTrust community on Discord for questions, reviews, and faster merges: https://discord.gg/WqnGpcPx
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Route queue processor logging through Pino and use crypto-strong job ids" labels: type:refactor, area:queue, stack:nodejs, stack:typescript, priority:medium, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
The queue processors log with raw console.log instead of the structured Pino logger used elsewhere β src/queue/processors/email-processor.ts, src/queue/processors/blockchain-processor.ts, src/queue/processors/reputation-processor.ts, and src/queue/processors/contract-processor.ts all bypass src/logger.ts, breaking log aggregation and correlation, and the contract processor logs ids straight to stdout. Separately, generateEmailId uses Date.now() + Math.random().toString(36), which is collision-prone and not suitable for ids. This behavior-preserving refactor moves all processor logging onto Pino and switches id generation to a crypto-strong source.
- Repository scope: Talenttrust/Talenttrust-Backend only.
- Replace
console.*in all four processors with the structured logger fromsrc/logger.ts, attaching correlation/job context and applying redaction fromsrc/utils/redact.tswhere payloads are logged. - Replace
generateEmailId(and any similarDate.now()+Math.random()id) withcrypto.randomUUID()(orrandomBytes). - Do not change job outcomes, return shapes, or retry behavior; this is purely logging + id generation.
- Avoid logging recipient PII or contract ids at info level in plaintext.
- Fork the repo and create a branch
git checkout -b refactor/queue-47-structured-logging-ids- Implement changes
- Write code in: the four processor files listed above.
- Write comprehensive tests in: the existing processor test files (e.g.
src/queue/processors/email-processor.test.ts) β assert structured log shape, redaction, and unique id generation. - Add documentation: note the logging convention in the queue section of
README.md. - Add TSDoc to the id helper.
- Validate: no secrets/PII in logs; ids are unique across rapid calls.
- Test and commit
- Run
npm run lintandnpm test. - Cover edge cases: rapid successive id generation, payload with sensitive fields, processor error path logging.
- Include the full
npm testoutput and notes in the PR.
refactor(queue): use Pino logging and crypto-strong ids in processors
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the TalentTrust community on Discord for questions, reviews, and faster merges: https://discord.gg/WqnGpcPx
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Add per-request timeout and retry to the default Stellar RPC transport" labels: type:enhancement, area:stellar, stack:nodejs, stack:typescript, priority:high, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
defaultTransport in src/rpc/stellarClient.ts calls fetch with no timeout, no abort, and no HTTP-level retry. Its own doc comment admits this is "intentionally simple: real production code would also set a request timeout, add auth headers, and handle HTTP-level retries before the circuit breaker," and the file header references a STELLAR_RPC_TIMEOUT_MS env var that is never read. A hung Soroban RPC therefore stalls the calling request indefinitely and the circuit breaker (5-failure threshold) never trips because the call neither succeeds nor fails. This issue gives the transport a bounded, abortable request lifecycle.
- Repository scope: Talenttrust/Talenttrust-Backend only.
- Wrap the
fetchindefaultTransportwith anAbortControllerdriven by aSTELLAR_RPC_TIMEOUT_MSenv var (sane default), aborting and throwing a typed timeout error so the breaker counts it as a failure. - Add a small bounded HTTP-level retry (idempotent reads only) with jitter, layered below the
CircuitBreakerinsrc/circuit-breaker/CircuitBreaker.tsso retries and breaker accounting do not double-count. - Keep the injectable
Transportseam intact so tests pass a mock; do not hard-code the production URL. - Surface the timeout value through validated config rather than reading
process.envinline twice.
- Fork the repo and create a branch
git checkout -b enhancement/stellar-rpc-transport-timeout- Implement changes
- Write code in:
src/rpc/stellarClient.ts. - Write comprehensive tests in: create
src/rpc/stellarClient.test.tsβ fake timers/abort; assert timeout aborts the fetch, retries are bounded, and the breaker records failures. - Add documentation: update
docs/backend/SOROBAN_RPC.mdwith the timeout/retry env vars. - Add TSDoc to the timeout wrapper.
- Validate security: no secrets in logs; timeout cannot be disabled to 0.
- Write code in:
- Test and commit
- Run
npm run lintandnpm test. - Cover edge cases: fast success, slow-then-timeout, transient 5xx retry, breaker-open short-circuit.
- Include the full
npm testoutput and notes in the PR.
feat(stellar): add per-request timeout and bounded retry to RPC transport
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the TalentTrust community on Discord for questions, reviews, and faster merges: https://discord.gg/WqnGpcPx
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Remove hardcoded default JWT_SECRET and DATABASE_URL from the secrets initializer" labels: type:security, area:config, stack:nodejs, stack:typescript, priority:high, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
initializeSecrets in src/config/secrets.ts registers JWT_SECRET with a literal fallback 'dev-secret-keep-it-safe' and DATABASE_URL with 'postgresql://localhost:5432/talenttrust'. Because EnvSecret only throws when no default is supplied, a production deploy that forgets to set JWT_SECRET will silently sign and verify tokens with a publicly-known secret committed to source β anyone can mint valid JWTs. This issue makes these secrets required outside development.
- Repository scope: Talenttrust/Talenttrust-Backend only.
- Register
JWT_SECRETandDATABASE_URLwithout a literal fallback whenNODE_ENVis notdevelopment/test, soEnvSecret.load()throws the existing "Missing required secret" error at boot. - Enforce a minimum
JWT_SECRETlength and reject the known weak literal even if explicitly set. - Keep developer ergonomics: a clearly-labelled dev-only default is acceptable only under
development. - Never log the secret value; route any diagnostics through
src/logger.ts.
- Fork the repo and create a branch
git checkout -b security/secrets-no-hardcoded-jwt-default- Implement changes
- Write code in:
src/config/secrets.ts. - Write comprehensive tests in: create
src/config/secrets.test.tsβ assert boot fails in production without the secret, dev default still works, and the weak literal is rejected. - Add documentation: update
docs/backend/secrets-handling.mdand.env.example. - Add TSDoc explaining the fail-fast rationale.
- Validate security: no weak fallback reachable in production.
- Write code in:
- Test and commit
- Run
npm run lintandnpm test. - Cover edge cases: missing in prod, present, weak literal, short secret, dev mode.
- Include the full
npm testoutput and a security notes section in the PR.
fix(security): require JWT_SECRET and DATABASE_URL in production
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the TalentTrust community on Discord for questions, reviews, and faster merges: https://discord.gg/WqnGpcPx
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Implement a real HTTP probe in the deployment validator's performHealthCheck" labels: type:feature, area:deployment, stack:nodejs, stack:typescript, priority:high, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
performHealthCheck(baseUrl) in src/deployment/validator.ts never contacts the service: its comment says "In a real implementation, this would make an HTTP request / For now, we'll simulate a successful health check," and it returns { status: 'healthy' } with a meaningless responseTime (start/end measured around zero work). Any caller validating deployment readiness through this function gets a green light regardless of the target's true state. This issue makes the probe actually call the target's readiness endpoint.
- Repository scope: Talenttrust/Talenttrust-Backend only.
- Implement
performHealthCheckto GET the target's/health/readyendpoint (served bysrc/health/router.ts) with a bounded timeout and reportunhealthyon non-200, network error, or timeout. - Validate
baseUrlwith the SSRF guard insrc/utils/ssrf.tsso the probe cannot be aimed at arbitrary internal hosts. - Record an accurate
responseTimemeasured around the real request and keep the existingHealthCheckResultshape consumed byvalidateDeploymentReadiness. - Make the HTTP call injectable so tests avoid real network access.
- Fork the repo and create a branch
git checkout -b feature/deployment-validator-real-probe- Implement changes
- Write code in:
src/deployment/validator.ts. - Write comprehensive tests in: create
src/deployment/validator.test.tsβ mock the HTTP client; assert healthy 200, 503 unhealthy, connection refused, timeout, and SSRF rejection. - Add documentation: update
docs/backend/deployment-guide.md. - Add TSDoc to the probe.
- Validate security: SSRF guard applied; no internal detail leaked.
- Write code in:
- Test and commit
- Run
npm run lintandnpm test. - Cover edge cases: 200, 503, refused, timeout, invalid/internal URL.
- Include the full
npm testoutput and a security notes section in the PR.
feat(deployment): make performHealthCheck probe the target readiness endpoint
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the TalentTrust community on Discord for questions, reviews, and faster merges: https://discord.gg/WqnGpcPx
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Add a real notification email transport to replace the console-only fallback" labels: type:feature, area:notifications, stack:nodejs, stack:typescript, priority:high, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
ConsoleTransport in src/services/notification.transport.ts is the default NotificationTransport: its sendEmail only console.logs the recipient and returns { success: true }, and sendWebNotification does the same. Only WebhookTransport is a real implementation β there is no concrete email provider, so any notification flow that resolves to the default transport silently drops mail while reporting success. This issue adds a real, injectable SMTP/provider email transport implementing the existing NotificationTransport interface.
- Repository scope: Talenttrust/Talenttrust-Backend only.
- Add a concrete email transport (SMTP/SES/SendGrid) implementing
NotificationTransport.sendEmail, selected from validated config insrc/config/env.schema.ts. - Surface provider failures so
NotificationResult.successisfalse(and callers can retry) rather than always-true. - Validate
EmailPayload.toand guard against header injection before dispatch; keepConsoleTransportas the explicit dev/test default. - Do not log full recipient addresses at info level; route through
src/logger.tsand reuse redaction fromsrc/utils/redact.ts.
- Fork the repo and create a branch
git checkout -b feature/notification-email-transport- Implement changes
- Write code in:
src/services/notification.transport.tsand wiring insrc/services/notification.service.ts. - Write comprehensive tests in: create
src/services/notification.transport.test.tsβ mock the provider; assert delivery, failure propagation, recipient validation, and header-injection rejection. - Add documentation: update
docs/notifications.md. - Add TSDoc to the new transport.
- Validate security: header-injection guard; no PII in logs.
- Write code in:
- Test and commit
- Run
npm run lintandnpm test. - Cover edge cases: valid send, provider throws, invalid recipient, injected header, missing config.
- Include the full
npm testoutput and notes in the PR.
feat(notifications): add a real email transport behind the transport interface
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the TalentTrust community on Discord for questions, reviews, and faster merges: https://discord.gg/WqnGpcPx
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Generate collision-resistant notification ids in the webhook transport" labels: type:enhancement, area:notifications, stack:nodejs, stack:typescript, priority:medium, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
WebhookTransport.sendWebNotification in src/services/notification.transport.ts builds the delivery id as `${payload.userId}:${Date.now()}`. Two notifications for the same user within the same millisecond produce an identical id, which collides with the idempotency/dedupe keys downstream in webhook delivery and can suppress a legitimate second notification. This issue switches id generation to a crypto-strong unique source.
- Repository scope: Talenttrust/Talenttrust-Backend only.
- Replace the
userId:Date.now()id withcrypto.randomUUID()(optionally prefixed withuserIdfor readability) so ids are unique under rapid succession. - Preserve the
NotificationResultshape and thewebhookService.sendcall contract. - Ensure the id remains stable for a single logical send (do not regenerate on retry within the same
send). - Add a focused regression assertion that rapid successive sends for one user produce distinct ids.
- Fork the repo and create a branch
git checkout -b enhancement/notification-strong-ids- Implement changes
- Write code in:
src/services/notification.transport.ts. - Write comprehensive tests in: create
src/services/notification.transport.test.ts(or extend the suite added for the email transport) β assert uniqueness across rapid calls and stable id on retry. - Add documentation: note the id scheme in the module TSDoc and
docs/notifications.md. - Add TSDoc to the id helper.
- Validate: no id reuse within the same millisecond.
- Write code in:
- Test and commit
- Run
npm run lintandnpm test. - Cover edge cases: 1000 rapid sends for one user, retry path, distinct users.
- Include the full
npm testoutput and notes in the PR.
feat(notifications): use crypto-strong unique ids in webhook transport
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the TalentTrust community on Discord for questions, reviews, and faster merges: https://discord.gg/WqnGpcPx
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Guard the SSRF allowlist bypass so dev/test never leaks into production" labels: type:security, area:security, stack:nodejs, stack:typescript, priority:high, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
isSafeUrl in src/utils/ssrf.ts short-circuits to return true whenever NODE_ENV is development or test, disabling all private-IP and metadata-endpoint checks. If NODE_ENV is ever unset, misspelled, or left as a non-production value in a deployed environment, the bypass does not trigger but neither does any positive assertion that protection is on β there is no fail-closed default and no explicit, auditable opt-in. This issue tightens the bypass to a deliberate, narrowly-scoped flag and adds IPv6/embedded-IPv4 coverage to the blocklist.
- Repository scope: Talenttrust/Talenttrust-Backend only.
- Replace the implicit
NODE_ENVbypass with an explicit, default-off allow flag (e.g.SSRF_ALLOW_PRIVATE_HOSTS) that is rejected outright whenNODE_ENV==='production'. - Extend
isPrivateHostto cover IPv6 loopback/ULA (::1,fc00::/7), IPv4-mapped IPv6, and decimal/octal-encoded IPv4 that currently bypass the string-prefix check. - Fail closed: any unparseable host or unknown environment must be treated as unsafe.
- Keep the existing function signatures so current callers (
src/deploy.ts, RPC, webhook) need no changes.
- Fork the repo and create a branch
git checkout -b security/ssrf-bypass-hardening- Implement changes
- Write code in:
src/utils/ssrf.ts. - Write comprehensive tests in: create
src/utils/ssrf.test.tsβ assert private IPv4/IPv6, encoded-IP bypass attempts, metadata endpoint, and that production ignores the allow flag. - Add documentation: update
docs/backend/security.mdwith the flag semantics. - Add TSDoc to the new flag handling.
- Validate security: no path returns true for a private host in production.
- Write code in:
- Test and commit
- Run
npm run lintandnpm test. - Cover edge cases:
::1,0177.0.0.1,2130706433,[::ffff:127.0.0.1], unset NODE_ENV. - Include the full
npm testoutput and a security notes section in the PR.
fix(security): harden SSRF bypass and add IPv6/encoded-IP coverage
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the TalentTrust community on Discord for questions, reviews, and faster merges: https://discord.gg/WqnGpcPx
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Persist the retention manager's in-memory storage provider to SQLite" labels: type:feature, area:retention, stack:nodejs, stack:typescript, priority:high, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
The DataRetentionManager in src/retention/index.ts defaults to an InMemoryStorageProvider from src/retention/storage.ts, so archived records, retention state, and the data backing listArchivedData/getArchiveStats live only in a process-local Map. A restart or blue-green switch wipes the entire archival inventory, which breaks compliance reporting and any purge decision that depends on knowing what was archived. This issue adds a durable SQLite-backed storage provider.
- Repository scope: Talenttrust/Talenttrust-Backend only.
- Implement a
SqliteStorageProvidersatisfying the storage interface insrc/retention/storage.ts, using the existing connection fromsrc/db/database.tsand a migration insrc/db/migrations.ts. - Default
DataRetentionManagerto the persistent provider outside tests; keepInMemoryStorageProviderinjectable for unit tests. - Preserve the
RetainedDatashape fromsrc/retention/types.tsand the policies insrc/retention/policies.ts; support bounded/paginated reads. - Ensure writes are transactional and survive restart.
- Fork the repo and create a branch
git checkout -b feature/retention-sqlite-storage-provider- Implement changes
- Write code in:
src/retention/storage.tsandsrc/retention/index.ts. - Write comprehensive tests in:
src/retention/retention.test.tsβ assert records survive a simulated restart and stats match persisted rows. - Add documentation: update
docs/DATA_RETENTION.mdwith the storage backend. - Add TSDoc to the provider.
- Validate: no data loss across reopen; pagination bounds enforced.
- Write code in:
- Test and commit
- Run
npm run lintandnpm test. - Cover edge cases: empty store, large archive pagination, reopen persistence, mixed storage types.
- Include the full
npm testoutput and notes in the PR.
feat(retention): add SQLite-backed storage provider
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the TalentTrust community on Discord for questions, reviews, and faster merges: https://discord.gg/WqnGpcPx
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Persist the in-memory DLQ store so failed webhooks survive restarts" labels: type:feature, area:dlq, stack:nodejs, stack:typescript, priority:high, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
src/dlqStore.ts backs the dead-letter queue with an in-process array, so every failed webhook delivery captured for later replay is lost on process exit or a blue-green switch. Operators replaying via the DLQ endpoints in src/api/jobs.ts silently lose entries that were enqueued by the previous process. This issue moves the DLQ to durable SQLite storage.
- Repository scope: Talenttrust/Talenttrust-Backend only.
- Back the DLQ with SQLite via
src/db/database.tsand a migration insrc/db/migrations.ts, preserving the currentdlqStorepublic API so callers insrc/api/jobs.tsandsrc/queue/webhook-dlq.tsare unchanged. - Store enqueue timestamp, provider, attempt count, and redacted payload (reuse
src/utils/redact.ts); never store raw signing secrets. - Keep an optional bounded capacity with a documented eviction policy.
- Support reads after restart so replay sees previously-enqueued entries.
- Fork the repo and create a branch
git checkout -b feature/dlq-sqlite-persistence- Implement changes
- Write code in:
src/dlqStore.ts. - Write comprehensive tests in: create
src/dlqStore.test.tsβ assert enqueue/list survive a simulated reopen and payloads are redacted at rest. - Add documentation: update
docs/WEBHOOK-DLQ.md. - Add TSDoc to the persistence layer.
- Validate security: no secrets persisted in cleartext.
- Write code in:
- Test and commit
- Run
npm run lintandnpm test. - Cover edge cases: empty DLQ, capacity eviction, reopen persistence, concurrent enqueue.
- Include the full
npm testoutput and a security notes section in the PR.
feat(dlq): persist dead-letter entries in SQLite
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the TalentTrust community on Discord for questions, reviews, and faster merges: https://discord.gg/WqnGpcPx
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Add a Redis-backed shared store option to the token-bucket rate limiter" labels: type:feature, area:rate-limit, stack:nodejs, stack:typescript, priority:medium, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
TokenBucketLimiter in src/rateLimit.ts holds bucket state in a per-process Map; its own docs note that "in a blue/green or multi-replica deployment each process maintains its own independent bucket state." With N replicas a provider can effectively send NΓ its intended rate, undermining the pacing guarantee for slow partners. This issue adds an optional shared backing store so the limit is enforced cluster-wide.
- Repository scope: Talenttrust/Talenttrust-Backend only.
- Introduce a
BucketStoreabstraction with the existing in-processMapas the default and a Redis-backed implementation selected via validated config insrc/config/env.schema.ts. - Implement token refill/consume atomically in Redis (e.g. Lua/
MULTI) so concurrent replicas cannot over-issue tokens. - Keep
acquireToken/getTokenCount/getQueueDepthsemantics and theredactIdlog redaction unchanged; never store provider secrets. - Fall back cleanly to in-process mode when Redis is unconfigured, documenting the trade-off.
- Fork the repo and create a branch
git checkout -b feature/rate-limit-redis-store- Implement changes
- Write code in:
src/rateLimit.ts. - Write comprehensive tests in: create
src/rateLimit.test.tsβ fake timers + mock Redis; assert atomic consume, cross-instance enforcement, and in-process fallback. - Add documentation: update
docs/request-limits-implementation.mdwith the upgrade path. - Add TSDoc to the
BucketStoreinterface. - Validate security: only opaque provider IDs in store keys/logs.
- Write code in:
- Test and commit
- Run
npm run lintandnpm test. - Cover edge cases: burst over capacity, two instances sharing a bucket, Redis down fallback.
- Include the full
npm testoutput and notes in the PR.
feat(rate-limit): add optional Redis-backed bucket store
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the TalentTrust community on Discord for questions, reviews, and faster merges: https://discord.gg/WqnGpcPx
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Bound the token-bucket queue depth to prevent unbounded waiter accumulation" labels: type:enhancement, area:rate-limit, stack:nodejs, stack:typescript, priority:medium, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
In src/rateLimit.ts, acquireToken pushes every throttled caller onto bucket.queue with no upper bound. A provider that is persistently slower than its refill rate accumulates waiters indefinitely β each holding an unresolved promise and its captured closure β which is an unbounded-memory / backpressure failure mode. This issue caps queue depth and applies a defined policy when the cap is hit.
- Repository scope: Talenttrust/Talenttrust-Backend only.
- Add a configurable max queue depth per provider (validated alongside
WEBHOOK_BUCKET_CAPACITY/WEBHOOK_REFILL_RATE_PER_SECinloadRateLimiterConfig). - When the cap is exceeded, reject with a typed error (so the caller can route the delivery to the DLQ) rather than queueing forever.
- Record the rejection via the metrics module (
src/webhookMetrics.ts/src/utils/webhookMetrics.ts) without raising label cardinality. - Preserve FIFO ordering and existing pacing for queues below the cap.
- Fork the repo and create a branch
git checkout -b enhancement/rate-limit-queue-cap- Implement changes
- Write code in:
src/rateLimit.ts. - Write comprehensive tests in: create
src/rateLimit.test.tsβ fake timers; assert below-cap queues drain FIFO and over-cap acquisitions reject with the typed error. - Add documentation: update
docs/request-limits-implementation.md. - Add TSDoc to the cap config.
- Validate: no unbounded growth; rejection is deterministic.
- Write code in:
- Test and commit
- Run
npm run lintandnpm test. - Cover edge cases: exactly-at-cap, one-over-cap, drain-then-refill, single fast provider.
- Include the full
npm testoutput and notes in the PR.
feat(rate-limit): cap per-provider queue depth with reject-on-overflow
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the TalentTrust community on Discord for questions, reviews, and faster merges: https://discord.gg/WqnGpcPx
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Protect the circuit breaker reset() method behind an authenticated admin route" labels: type:security, area:circuit-breaker, stack:nodejs, stack:typescript, stack:express, priority:high, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
src/circuit-breaker/CircuitBreaker.ts documents that "the reset() method is intended for admin/test use only; in production it should be protected behind an authenticated admin route." Today nothing enforces that β any route or module with a breaker reference can force a tripped breaker back to CLOSED, defeating the protection that was tripping for a reason. This issue exposes reset only through an authenticated admin endpoint with an audit trail.
- Repository scope: Talenttrust/Talenttrust-Backend only.
- Add an admin-guarded endpoint that resets a named breaker via the registry in
src/circuit-breaker/registry.ts, protected by the admin guard insrc/middleware/adminAuthGuard.ts. - Emit an audit entry (who reset which breaker, when) via
src/audit/service.ts. - Reject unauthenticated/unauthorized callers with a safe error from
src/errors/safeErrors.ts; never expose internal breaker internals in the body. - Keep
reset()callable directly in tests without the HTTP layer.
- Fork the repo and create a branch
git checkout -b security/circuit-breaker-admin-reset- Implement changes
- Write code in: a route under
src/routes/admin.routes.tsand the registry insrc/circuit-breaker/registry.ts. - Write comprehensive tests in: create
src/circuit-breaker/registry.test.tsand a route integration test β assert reset requires admin auth and writes an audit record. - Add documentation: update
docs/backend/circuit-breaker.md. - Add TSDoc to the reset endpoint.
- Validate security: 401/403 leak nothing; audit emitted on success.
- Write code in: a route under
- Test and commit
- Run
npm run lintandnpm test. - Cover edge cases: missing auth, wrong role, valid admin, unknown breaker name.
- Include the full
npm testoutput and a security notes section in the PR.
feat(circuit-breaker): gate reset behind authenticated admin route with audit
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the TalentTrust community on Discord for questions, reviews, and faster merges: https://discord.gg/WqnGpcPx
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Add a length guard before timingSafeEqual in contract metadata hash verification" labels: type:security, area:contract-metadata, stack:nodejs, stack:typescript, priority:high, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
The metadata hash verification in src/contractMetadata.ts lowercases the expected and fetched contract hashes and compares them, but crypto.timingSafeEqual throws a RangeError when the two buffers differ in length. A swapped contract whose hash differs in length therefore triggers an unhandled exception instead of a clean fail-closed rejection, and the throw path may surface internal detail. This issue adds an explicit equal-length guard so a mismatch is always a controlled rejection.
- Repository scope: Talenttrust/Talenttrust-Backend only.
- Add an explicit length check before the constant-time compare; unequal lengths must short-circuit to a "not verified" result, never throw out of the verifier.
- Keep the comparison constant-time for equal-length inputs and preserve the existing fail-closed behaviour (reject on mismatch before any settlement/processing).
- Route any diagnostics through
src/logger.tswithout logging the raw hashes; emit a safe error viasrc/errors/safeErrors.ts. - Do not broaden what counts as a verified contract.
- Fork the repo and create a branch
git checkout -b security/contract-metadata-hash-length-guard- Implement changes
- Write code in:
src/contractMetadata.ts. - Write comprehensive tests in: create
src/contractMetadata.test.tsβ assert equal-hash verify, mismatched-length reject (no throw), and mismatched-equal-length reject. - Add documentation: note the verification rule in
docs/backend/contract-metadata-api.md. - Add TSDoc to the verifier.
- Validate security: no RangeError escapes; no raw hash logged.
- Write code in:
- Test and commit
- Run
npm run lintandnpm test. - Cover edge cases: identical, different-length, same-length-different, empty hash.
- Include the full
npm testoutput and a security notes section in the PR.
fix(security): guard hash length before timingSafeEqual in metadata verify
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the TalentTrust community on Discord for questions, reviews, and faster merges: https://discord.gg/WqnGpcPx
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Validate the salt:hash format before splitting in API key verification" labels: type:security, area:api-keys, stack:nodejs, stack:typescript, priority:medium, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
verifyApiKey in src/auth/apiKeys.ts splits the stored credential on : to recover the salt and hash before running PBKDF2. A stored value that is empty, missing the separator, or otherwise malformed (e.g. from a botched migration) yields undefined halves that flow into the crypto call, risking a thrown exception on the authentication hot path rather than a clean rejection. This issue validates the stored format up front and fails closed.
- Repository scope: Talenttrust/Talenttrust-Backend only.
- Validate that the stored credential is a well-formed
salt:hash(both parts present, correct hex length) before calling PBKDF2; on malformed input, reject as an invalid key without throwing. - Keep the existing salted PBKDF2 verification and timing-safe comparison as the source of truth for well-formed records.
- Do not log the stored hash or salt; surface a generic invalid-key result.
- Preserve the
ApiKeyInfo/return shape and existing expiry/last_used_atbehaviour.
- Fork the repo and create a branch
git checkout -b security/api-key-stored-format-validation- Implement changes
- Write code in:
src/auth/apiKeys.ts. - Write comprehensive tests in:
src/auth/__tests__/apiKeys.test.tsβ assert malformed stored values reject cleanly and valid keys still verify. - Add documentation: note the storage format in
docs/api-keys.md. - Add TSDoc to the validation helper.
- Validate security: no throw on malformed input; constant-time compare preserved.
- Write code in:
- Test and commit
- Run
npm run lintandnpm test. - Cover edge cases: empty string, no colon, extra colons, wrong-length hex, valid key.
- Include the full
npm testoutput and a security notes section in the PR.
fix(api-keys): validate stored salt:hash format before verification
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the TalentTrust community on Discord for questions, reviews, and faster merges: https://discord.gg/WqnGpcPx
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Avoid leaking the raw secret value in EnvSecret transform error messages" labels: type:security, area:config, stack:nodejs, stack:typescript, priority:medium, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
EnvSecret.load() in src/config/secrets.ts wraps a failed transform() in Configuration Error: Failed to transform secret "${key}": ${error.message}. Because the transform callback receives the raw secret string, a thrown error inside it (e.g. a parser that echoes its input) can carry the secret value into the error message, which then propagates to startup logs/stack traces. This issue ensures transform failures never embed the secret value.
- Repository scope: Talenttrust/Talenttrust-Backend only.
- Catch transform failures and emit an error that names only the
key, never the raw value or any substring of it; redact viasrc/utils/redact.tswhere helpful. - Preserve the fail-fast contract (still throws) and the existing
Secret/EnvSecret/SecretsManagerAPI. - Ensure the message is safe to log through
src/logger.ts. - Cover both string and non-Error throws from
transform.
- Fork the repo and create a branch
git checkout -b security/envsecret-transform-error-redaction- Implement changes
- Write code in:
src/config/secrets.ts. - Write comprehensive tests in: create
src/config/secrets.test.ts(or extend it) β assert a transform that includes the raw value never leaks it into the thrown message. - Add documentation: note the guarantee in
docs/backend/secrets-handling.md. - Add TSDoc to the error path.
- Validate security: no secret substring in any thrown/logged message.
- Write code in:
- Test and commit
- Run
npm run lintandnpm test. - Cover edge cases: transform throws Error with value, throws string, throws non-Error, succeeds.
- Include the full
npm testoutput and a security notes section in the PR.
fix(security): never embed raw secret values in EnvSecret errors
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the TalentTrust community on Discord for questions, reviews, and faster merges: https://discord.gg/WqnGpcPx
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Support asynchronous secret rotation backends in the SecretsManager" labels: type:feature, area:config, stack:nodejs, stack:typescript, priority:medium, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
EnvSecret.refresh() in src/config/secrets.ts only re-reads process.env, and its TSDoc notes that "in a production environment with rotation (like AWS Secrets Manager), this would involve an asynchronous API call to fetch the latest version." There is no concrete rotating Secret implementation, so SecretsManager.refreshAll() is effectively a no-op for real rotation. This issue adds a pluggable async secret source so secrets can rotate without a restart.
- Repository scope: Talenttrust/Talenttrust-Backend only.
- Add a
RotatingSecretimplementation of the existingSecret<T>interface that fetches from an injectable async provider with a cached value and a configurable refresh interval. - Keep the synchronous
get()contract (serve the last fetched value) and makerefresh()perform the real async fetch; integrate cleanly withSecretsManager.refreshAll(). - Never log fetched secret values; reuse redaction and fail safe (retain the prior value) on a refresh error.
- Document how to register a rotating secret alongside
EnvSecret.
- Fork the repo and create a branch
git checkout -b feature/secrets-rotating-source- Implement changes
- Write code in:
src/config/secrets.ts. - Write comprehensive tests in: create
src/config/secrets.test.tsβ mock the async provider; assert initial fetch, refresh updates value, and refresh failure retains the prior value. - Add documentation: update
docs/backend/secrets-handling.md. - Add TSDoc to
RotatingSecret. - Validate security: no secret value in logs; old value retained on error.
- Write code in:
- Test and commit
- Run
npm run lintandnpm test. - Cover edge cases: initial load, successful rotation, provider error, refreshAll across mixed sources.
- Include the full
npm testoutput and a security notes section in the PR.
feat(config): add async rotating secret source to SecretsManager
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the TalentTrust community on Discord for questions, reviews, and faster merges: https://discord.gg/WqnGpcPx
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Route swrCache background revalidation errors through the structured logger" labels: type:enhancement, area:utils, stack:nodejs, stack:typescript, priority:low, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
SWRCache in src/utils/swrCache.ts swallows background revalidation failures with a single console.error, and a comment notes "depending on error handling policy, we could log this explicitly." Silent console.error means a key that fails to revalidate keeps serving stale data with no aggregatable signal β operators cannot alert on a wedged cache. This issue routes the failure through structured logging and an optional callback.
- Repository scope: Talenttrust/Talenttrust-Backend only.
- Replace the
console.errorwith a structured log viasrc/logger.tsincluding the cache key and error, redacted viasrc/utils/redact.ts. - Add an optional
onRevalidationErrorcallback hook so consumers can increment a metric; keep the swallow-and-serve-stale behaviour (callers must never see the background error). - Do not change fresh/stale/miss/coalescing semantics; behaviour-preserving except logging.
- Keep timers clean (no leaked handles) so tests remain deterministic.
- Fork the repo and create a branch
git checkout -b enhancement/swrcache-structured-error-logging- Implement changes
- Write code in:
src/utils/swrCache.ts. - Write comprehensive tests in: create
src/utils/swrCache.test.tsβ fake timers; assert revalidation error logs structured, fires the callback, and callers still get stale value. - Add documentation: add usage notes in the
SWRCacheTSDoc. - Add TSDoc to the callback hook.
- Validate: no error propagates to callers; no leaked timers.
- Write code in:
- Test and commit
- Run
npm run lintandnpm test. - Cover edge cases: revalidation throws, succeeds, concurrent miss coalescing, callback omitted.
- Include the full
npm testoutput and notes in the PR.
feat(utils): log SWR revalidation errors via structured logger and callback
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the TalentTrust community on Discord for questions, reviews, and faster merges: https://discord.gg/WqnGpcPx
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Add max-entry eviction to the in-memory SWR cache to bound memory" labels: type:enhancement, area:utils, stack:nodejs, stack:typescript, priority:medium, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
SWRCache in src/utils/swrCache.ts stores entries in an unbounded Map; keys are only ever added, never evicted beyond their TTL/staleness role. A high-cardinality key space (e.g. per-user or per-contract cache keys) grows the map without limit, leaking memory over the life of the process. This issue adds a bounded-capacity eviction policy.
- Repository scope: Talenttrust/Talenttrust-Backend only.
- Add a configurable
maxEntrieswith an LRU (or insertion-order) eviction so the map never exceeds the cap. - Eviction must not break in-flight coalesced revalidation for a still-referenced key.
- Preserve the fresh/stale/miss semantics and the existing constructor options; default to a sane cap.
- Expose the current size for observability/testing.
- Fork the repo and create a branch
git checkout -b enhancement/swrcache-bounded-eviction- Implement changes
- Write code in:
src/utils/swrCache.ts. - Write comprehensive tests in: create
src/utils/swrCache.test.ts(or extend it) β assert eviction at cap, LRU ordering, and that an in-flight revalidation is not corrupted by eviction. - Add documentation: document
maxEntriesin theSWRCacheTSDoc anddocs/backend/caching.md. - Add TSDoc to the eviction logic.
- Validate: size never exceeds cap; no stale-pointer bug.
- Write code in:
- Test and commit
- Run
npm run lintandnpm test. - Cover edge cases: cap of 1, eviction during revalidation, repeated access reorders LRU.
- Include the full
npm testoutput and notes in the PR.
feat(utils): add bounded LRU eviction to SWR cache
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the TalentTrust community on Discord for questions, reviews, and faster merges: https://discord.gg/WqnGpcPx
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward.