Skip to content

Tracker Backlog

The living backlog. Field definitions, workflow, and review cadence: Tracker home. Active items first (Critical → Low); Resolved/Closed archived at the bottom. Each ID links to its detail block. When adding an item, allocate the next NFX-### and fill the detail template.

Active

IDPriorityTypeFeature · Sub-featureSummaryStatusTargetUpdated
NFX-007HighBugZoom Live Classes · embedded host-startHost-start ZAK fetch returns 400 in the embedded flowBlocked2026-07-04
NFX-005HighTechnical Debt · TestingPlatform / EF · multiple26 Edge Functions deployed without co-located testsOpenBacklog2026-07-04
NFX-004MediumBug · Technical DebtPlatform / EF · fetch-*-contributorsNseStockItem has conflicting duplicate industry/companyName declarations (9 type errors); confirmed this blocks deno test entirely (0 tests run), now a concrete backend-ci.yml Job-2 blockerOpenBacklog2026-07-09
NFX-006MediumProcess ImprovementPlatform / EF · test toolingnpm run test:ef type-checks the whole dir, so one EF's error fails the entire runOpenBacklog2026-07-04
NFX-008HighPerformanceZoom Live Classes · LiveClassRoom5.6 MB Zoom SDK bundle -- Zoom officially provides a CDN alternative, verifiedOpenBacklog2026-07-05
NFX-009HighBugMarket Mood / Index Radar / Settings · imports7 imports resolve to files that don't exist on diskOpenBacklog2026-07-05
NFX-012LowBug · TestingTrade Planner / Session Review · tests2 tests reference service exports that don't exist (deletePlan, deleteSessionReview)OpenBacklog2026-07-05
NFX-013HighTechnical DebtPlatform · repo/.gitignore.env.local + supabase/.temp/ untracked and repointed per-environment; git-history scrub deliberately deferred (no sensitive values were ever committed)Partially ResolvedDone (untrack)2026-07-08
NFX-019HighTechnical Debt · TestingPlatform · test coverageReal coverage (~17%/30%/17%/51%) is far below the documented 70/80/65/70 targetOpenBacklog2026-07-05
NFX-020LowBugPlatform · vitest/@vitest/coverage-v8 (local, Windows)Full-suite npm run test:coverage crashes entirely on this dev machine (100/100 files fail to collect)OpenBacklog2026-07-05
NFX-021MediumTechnical DebtPlatform · SonarQube code quality (whole codebase)Real baseline: 80 bugs, 0 vulnerabilities, 12792 code smells — addressed feature-by-feature going forwardOpenBacklog2026-07-05
NFX-023HighEnhancement · ArchitecturePlatform · Documentation infrastructure (3 portals)Add admin/ops + end-user help center portals alongside the dev portal, each its own deploy — not bundled into the appOpenBacklog2026-07-07
NFX-026MediumProcess ImprovementPlatform · Repo governance (GitHub Settings)Dependabot, code scanning, and branch protection are GitHub Settings toggles — not executable from the repo/CLIOpenBacklog2026-07-07
NFX-027HighEnhancement · ArchitecturePlatform · Backend CI/CD + environment isolationNefoxx-Dev provisioned + full parity achieved (schema, buckets, cron, 67 EFs, seed users, per-env frontend wiring); Phase C (backend-ci.yml PR gate) shipped 2026-07-09; Cloudflare/Zoom secrets + Phases D-F still openIn ProgressCurrent2026-07-09
NFX-028HighSecurity · Technical DebtPlatform · Dependencies (npm root + portal)Dependabot reports 59 vulnerabilities (3 critical, 18 high) across dependencies; needs triage — runtime-exposed firstOpenBacklog2026-07-07
NFX-029HighEnhancement · TestingPlatform · Playwright E2E testing layerAdd a browser-level E2E layer (journeys, a11y, visual, deploy-smoke) above Vitest; Phases 1-3 (smoke suite, e2e-smoke PR gate, deploy-smoke, verify-ci extension, rollback runbook) shipped; Phase 3 live-deploy verification pending NFX-045; Phases 4-5 remainIn ProgressCurrent2026-07-09
NFX-030HighBug · Technical DebtPlatform · Supabase migrations (version naming + prod tracking desync)149/210 migrations collided on version parsing; prod only tracked 6/212 as applied — squashed to a verified baseline, prod reconciled, db diff confirms zero driftResolvedDone2026-07-08
NFX-031MediumProcess ImprovementPlatform · Nefoxx-Dev — Google OAuth (Auth provider config)Nefoxx-Dev has no Google OAuth app of its own yet — dashboard/console-only, no code changes neededOpenBacklog2026-07-08
NFX-033MediumTechnical Debt · Process ImprovementPlatform · Supabase — cron jobs and storage buckets not version-controlled21 of production's 26 cron jobs and all 5 storage buckets exist only as live database state, never captured in any migrationOpenBacklog2026-07-09
NFX-034LowTechnical DebtPlatform · Supabase — stale Shoonya broker secretsSHOONYA_API_* + INSTRUMENT_SYMBOL confirmed unused in production (sole consumer isn't cron-scheduled); recommend removalOpenBacklog2026-07-08
NFX-035MediumTechnical DebtPlatform · Nefoxx-Dev — Cloudflare + Zoom secretsCloudflare (Images/Stream/R2) and Zoom dev-app secrets not yet set on Nefoxx-Dev; media uploads and Zoom Live Classes non-functional on devv/uatt until setOpenUser will pick up if blocked2026-07-08
NFX-036MediumProcess ImprovementPlatform · Nefoxx-Dev — Auth config paritySite URL, redirect URLs, OAuth provider config not verified in parity between Nefoxx-Prod and Nefoxx-Dev — not queryable via SQL, dashboard-only checkOpenUser will pick up if blocked2026-07-08
NFX-037LowBug · TestingPsychology Builder · psychology-builder-save-archetype (deriveArchetype)One test fixture's expected archetype doesn't match what the documented weighted formula actually produces for those inputs — implementation is internally consistent, root-causedOpenBacklog2026-07-09
NFX-038MediumBug · AccessibilityPlatform · Design system — color contrast (text-orange-500 on white)Found by the new PR-blocking a11y gate (scoped to critical-only because of this): brand orange on white measures 2.8:1 contrast, below WCAG AA's 4.5:1 minimum; a design-system-wide fix, not scoped to one pageOpenBacklog2026-07-09
NFX-039LowBugMarket Mood · vw_momentum_leaders (view)View 500s on the ephemeral stack's schema snapshot; found incidentally while verifying the new E2E market-mood smoke spec, not on the overview page's own call pathOpenBacklog2026-07-09
NFX-042MediumEnhancement · TestingPlatform · Playwright E2E — Phase 2 blocking journey coveragePhase 2's PR-blocking smoke set covers only auth + trade-planner + market-mood (deliberately narrow); Psychology Builder, Risk Radar, Session Review, Habit Tracker, Finfluencify, admin, OI Pulse/Index Radar remain uncovered until Phase 4 (nightly regression)OpenPhase 42026-07-09
NFX-044HighBug · Technical Debt · SecurityPlatform · supabase.from() used directly across ~25 filesFull-tree grep (prompted by NFX-043) found ~45 more direct .from() call sites outside FeatureGateContext.jsx — community, options-strategy index_expiry_map reads, trade journal, screeners, watchlist, sticky notes, admin ad-management, admin commission, finfluencify students; reads are get_* RPC candidates, writes each need a new Edge FunctionOpenBacklog2026-07-09
NFX-045CriticalBug · SecurityPlatform · devv.nefoxx.com / uatt.nefoxx.com — frontend Supabase client wiringMissing/incorrect dev/uat GitHub Environment variables caused both to build against Nefoxx-Prod (bundle-inspection confirmed identical baked-in URL to nefoxx.com itself); GitHub values now corrected and user-verified, but no fresh deploy has run yet to bake them inOpenAfter Phase 3 (NFX-029)2026-07-09

Resolved / Closed

IDPriorityTypeFeature · Sub-featureSummaryStatusResolvedUpdated
NFX-001CriticalBugPsychology Builder · compute-behavioral-signalsReferenceError crash for any user with ≥7 check-insResolved2026-07-042026-07-04
NFX-002MediumTechnical DebtPlatform / EF · _shared/crypto.tsBufferSource typing failed deno check on every token-encrypting EFResolved2026-07-042026-07-04
NFX-003LowTechnical Debt · TestingTrade Planner · trade-planner-share (test)Dead 'public' === 'private' comparison (TS2367 code smell)Resolved2026-07-042026-07-04
NFX-010MediumTechnical DebtSettings · pages/SettingsPage.jsxLeftover legacy component body duplicates the tiers re-export's default exportResolved2026-07-052026-07-05
NFX-011LowTechnical DebtFinfluencify · delete-bunnyService.jsTombstone file (marked for full removal) has an orphaned syntax fragment, fails to parseResolved2026-07-052026-07-05
NFX-014LowBug · TestingOnboarding · OnboardingPage.test.jsxTest asserted a hardcoded niftytoolkit.com domain the rename to nefoxx.com left staleResolved2026-07-052026-07-05
NFX-015MediumBugPlatform · eslint-plugin-sonarjs (CI/hook tooling)no-skipped-tests crashes lint on Windows when drive-letter casing differs between file path and cwdResolved2026-07-052026-07-05
NFX-016MediumTechnical DebtPlatform · eslint.config.mjs scopeRoot (React) ESLint config was linting documentations/portal (separate Vue/VitePress sub-project)Resolved2026-07-052026-07-05
NFX-017MediumBugFinfluencify · LinkInBio (editor, claim modal, hooks, payouts)10 client-side occurrences of the retired niftytoolkit.com domain — feature not yet live, no real-user impactResolved2026-07-052026-07-05
NFX-018MediumBugZoom Live Classes · LiveSessionList.jsxscrollIntoView not implemented in jsdom — missing test-env stub, not a component bug; actually failed CIResolved2026-07-052026-07-05
NFX-024MediumProcess ImprovementPlatform · .github/workflows/ci.ymlEvery fast-forward of main after a develop push doubled CI minutes for zero benefitResolved2026-07-072026-07-07
NFX-022MediumBugPlatform · dev portal (VitePress) docsLiteral GitHub Actions mustache syntax in inline code broke Vue template compile, blanking the pageResolved2026-07-072026-07-07
NFX-025HighProcess ImprovementPlatform · CI/CD (whole pipeline)No automated lint/test/build/deploy pipeline existed — GitHub Actions + Cloudflare Pages now covers dev/UAT/productionResolved2026-07-072026-07-07
NFX-032CriticalBug · Technical DebtPlatform · Nefoxx-Dev — Edge Functions / cron parityIndependent re-audit found devv/uatt were non-functional (0/67 EFs, 1/26 cron jobs deployed, cron names dropped) despite prior "data isolation live" claim; all agent-actionable scope fixed and re-verified same dayResolved2026-07-082026-07-08
NFX-040HighBugTrade Planner · public share links (/shared/plan/:token)Anonymous visitors to a public share link got an auth-modal prompt after 5s — the route was missing from ProtectedRoute.jsx's publicPaths allowlist; found writing the E2E share-journey spec (a genuinely logged-out browser context, not just a new tab), fixed same passResolved2026-07-092026-07-09
NFX-041MediumBug · AccessibilityPlatform · Global header — nav dropdown menus (NavItem.jsx)DropdownMenuTrigger asChild's cloned ARIA attributes (aria-haspopup, aria-expanded) landed on an intermediate motion.div, not the real Button — invalid ARIA on a generic div (critical, aria-allowed-attr); found by the new PR-blocking a11y gate on /trade-planner, fixed same passResolved2026-07-092026-07-09
NFX-043HighBug · SecurityPlatform · FeatureGateContext.jsx — direct supabase.from() callAbsolute hard-guardrail violation (.from('feature_flags'), client-side, on every page load) — found by the new deploy-smoke mutation guard, which flags any raw /rest/v1/<table> call; fixed via new get_feature_flags RPC, applied to both Nefoxx-Dev and Nefoxx-Prod same passResolved2026-07-092026-07-09

Details

NFX-001

  • Date Reported: 2026-07-04 · Reported By: Testing (local Deno validation)
  • Priority: Critical · Severity: Crash · Status: Resolved · Owner: — · Effort: S
  • Feature · Sub-feature: Psychology Builder · psychology-compute-behavioral-signals/helpers.ts
  • Issue Type: Bug · Domain(s): Reliability, Code quality, Testing
  • Description: generateInsights referenced sessionReviewEntries (lines 418/449) but the identifier was never added to the input destructuring, so it was an undeclared name → ReferenceError at runtime.
  • Impact: Any user with checkinCount ≥ 7 crashed insight generation; the Session Review insights (milestone/growth/warning) never fired. Live production defect from an untested deploy.
  • Proposed Solution / Action Items: ☑ Add sessionReviewEntries to the destructuring · ☑ fix two as Xas unknown as X casts (DivergenceResult, InsightRow) · ☑ add regression tests.
  • Target: Immediate · Related Links: psychology-compute-behavioral-signals; memory edge-functions-untested
  • Resolution Date: 2026-07-04 · Verification: deno test 27 passed / 0 failed, type-check clean (2 new regression tests).
  • Last Updated: 2026-07-04 · Remarks: Redeploy the EF to ship the fix (currently crashing in prod).

NFX-002

  • Date Reported: 2026-07-04 · Reported By: Testing (local Deno validation)
  • Priority: Medium · Status: Resolved · Owner: — · Effort: S
  • Feature · Sub-feature: Platform / EF · supabase/functions/_shared/crypto.ts
  • Issue Type: Technical Debt · Domain(s): Security, Developer experience, Testing
  • Description: crypto.subtle.importKey('raw', rawKey, …) tripped Deno/TS Uint8Array<ArrayBufferLike> vs BufferSource strictness (ArrayBufferLike may be SharedArrayBuffer).
  • Impact: Failed deno check transitively on every EF importing encryptToken (Zoom connect, live-session-save, …) and broke the whole-dir deno test run. Type-only; runtime unaffected.
  • Proposed Solution / Action Items: ☑ Cast rawKey as BufferSource at the call site with a comment; no runtime change.
  • Target: Immediate · Related Links: _shared/crypto.ts
  • Resolution Date: 2026-07-04 · Verification: crypto tests 8/0; deno check clean on finfluencify-live-session-save + finfluencify-zoom-connect.
  • Last Updated: 2026-07-04 · Remarks: Any redeploy of a token-encrypting EF picks up the change; no behavioural impact.

NFX-003

  • Date Reported: 2026-07-04 · Reported By: Testing (local Deno validation)
  • Priority: Low · Status: Resolved · Owner: — · Effort: S
  • Feature · Sub-feature: Trade Planner · trade-planner-share/tests/… (test-only)
  • Issue Type: Technical Debt (Testing) · Domain(s): Code quality, Testing
  • Description: Test asserted a public-share branch via a literal 'public' === 'private' comparison — always false, flagged TS2367 (unintentional comparison / dead code).
  • Impact: Broke type-check; masked the branch it meant to exercise. No production impact.
  • Proposed Solution / Action Items: ☑ Replace with a shareType: string variable so the branch is genuinely exercised.
  • Target: Immediate · Related Links: trade-planner-share
  • Resolution Date: 2026-07-04 · Verification: deno test 59 passed / 0 failed. Last Updated: 2026-07-04.

NFX-004

  • Date Reported: 2026-07-04 · Reported By: Testing (full-dir deno test)
  • Priority: Medium · Severity: Minor · Status: Open · Owner: — · Effort: S–M
  • Feature · Sub-feature: Platform / EF · fetch-*-contributors family (NseStockItem type)
  • Issue Type: Bug · Technical Debt · Domain(s): Code quality, Reliability, Testing
  • Description: NseStockItem has duplicate/conflicting industry + companyName property declarations (string | null | undefined vs string | undefined) → 9 errors: TS2300/TS2717/TS2339/TS2353.
  • Impact: Fails whole-dir deno test/deno check; indicates a merged/inconsistent interface that may hide real shape mismatches across the contributor EFs. Confirmed 2026-07-09: this isn't just "fails type-check" — deno test hard-stops at the whole-directory type-check phase when this error is present, so it runs zero tests, not "most tests, minus this one." Now a concrete blocker for promoting .github/workflows/backend-ci.yml's edge-functions job (NFX-027 Phase C) from visibility-only to a required check, alongside NFX-037.
  • Proposed Solution / Action Items: ☐ Locate the duplicate declaration(s); unify NseStockItem to a single consistent shape (likely string | null | undefined) · ☐ add/adjust tests · ☐ re-run targeted + full suite.
  • Target: Backlog · Related Links: memory edge-functions-untested; surfaced while fixing NFX-001/002/003; NFX-027 (Phase C, concrete blocker); NFX-037 (the other current Job-2 blocker).
  • Resolution Date: — · Verification: — · Last Updated: 2026-07-09
  • Remarks: Out of scope of the 2026-07-04 three-fix pass; awaiting go-ahead before touching.

NFX-005

  • Date Reported: 2026-07-04 · Reported By: Code Review (post-deploy audit)
  • Priority: High · Status: Open · Owner: — · Effort: L
  • Feature · Sub-feature: Platform / EF · multiple (26 functions)
  • Issue Type: Technical Debt · Domain(s): Testing, Reliability, Developer experience
  • Description: 26 deployed EFs have no co-located tests/ folder (full list in memory edge-functions-untested), violating the mandatory EF-testing policy.
  • Impact: Untested surface area → latent defects (see NFX-001) ship undetected; slows safe change.
  • Proposed Solution / Action Items: ☐ Backfill full co-located suites whenever an untested EF is touched (per policy) · ☐ optionally schedule a dedicated debt-burn-down for the highest-risk ones (auth/write/cron).
  • Target: Backlog (incremental) · Related Links: memory edge-functions-untested; CLAUDE.md → Edge Function Testing (Mandatory).
  • Last Updated: 2026-07-04 · Remarks: Treat "add tests" as part of any change to these EFs, not a follow-up.

NFX-006

  • Date Reported: 2026-07-04 · Reported By: Developer
  • Priority: Medium · Status: Open · Owner: — · Effort: S
  • Feature · Sub-feature: Platform / EF · test tooling (npm run test:ef)
  • Issue Type: Process Improvement · Domain(s): Developer experience, Deployment/ops, Testing
  • Description: deno test supabase/functions/ type-checks the entire directory, so a pre-existing type error in one unrelated EF fails the whole run and obscures the function under change.
  • Impact: Slows validation; encourages skipping the full run. Mitigated today by running targeted deno test … supabase/functions/{ef}/tests/.
  • Proposed Solution / Action Items: ☐ Consider per-function test scripts / a matrix runner, or splitting test:ef into test:ef:<domain> · ☐ track down and clear the remaining whole-dir errors (see NFX-004).
  • Target: Backlog · Related Links: NFX-004 · Last Updated: 2026-07-04.

NFX-007

  • Date Reported: 2026-07-04 (pre-existing) · Reported By: User + Testing
  • Priority: High · Severity: Major · Status: Blocked · Owner: — · Effort: M
  • Feature · Sub-feature: Zoom Live Classes · embedded host-start (finfluencify-live-session-join)
  • Issue Type: Bug · Domain(s): Reliability, Integrations
  • Description: Embedded host-start ZAK fetch returns 400 (zoom.zak_fetch_failed); host cannot start the embedded meeting in some cases. Needs the failing response detail to diagnose.
  • Impact: Blocks hosting a live class in the affected path — core Zoom Live Classes flow.
  • Proposed Solution / Action Items: ☐ Capture the zoom.zak_fetch_failed response body · ☐ verify the user:read:zak scope + reconnect · ☐ confirm dev-vs-prod Zoom app cutover.
  • Target: — (blocked on data) · Related Links: memory zoom-zak-blocker, zoom-integration-status.
  • Last Updated: 2026-07-04 · Remarks: Migrated from memory into the tracker so it isn't lost.

NFX-008

  • Date Reported: 2026-07-04 · Reported By: Developer · Re-verified: 2026-07-05 (Developer, per user request, using live Zoom developer docs -- not asserted from memory)
  • Priority: High · Status: Open · Owner: — · Effort: M
  • Feature · Sub-feature: Zoom Live Classes · LiveClassRoom
  • Issue Type: Performance · Domain(s): Performance, Scalability, Deployment/ops
  • Description: The Zoom Meeting SDK bundle is ~5.6 MB. It is already lazy()-loaded (off the main bundle), but could be loaded from Zoom's CDN instead of bundled from node_modules/@zoom/meetingsdk to remove it from our build/deploy artifact entirely. Verified against Zoom's official docs (2026-07-05): Zoom explicitly supports CDN import as a documented alternative to the npm package (Import the Meeting SDK for web), with a working reference implementation (meetingsdk-web-sample/CDN/meeting.html). The CDN sample pins v6.2.0 -- the exact same version already installed here ("@zoom/meetingsdk": "^6.2.0" in package.json) -- confirming this is a genuine drop-in swap, not a different SDK variant. WebAssembly assets are also CDN-hosted (https://source.zoom.us/{VERSION}/lib), so nothing would need to be self-hosted.
  • Impact: Larger build/deploy artifact; slower first entry into a live class on cold cache; every npm run build pays the cost of bundling/minifying 5.6 MB of third-party SDK code that never changes between our own releases. No impact on other pages today (already lazy-loaded).
  • Proposed Solution / Action Items: ☐ Replace the @zoom/meetingsdk npm import in LiveClassRoom.jsx with the CDN <script> tags from the official sample (SDK script + vendor/react.min.js/react-dom.min.js/redux.min.js/etc. -- Zoom's embedded UI ships its own React/Redux, loaded separately from the app's own) · ☐ verify no collision between Zoom's bundled React/Redux and the app's own React 18 instance when both are present on the same page · ☐ decide whether to pin the exact version (https://source.zoom.us/6.2.0/..., matching current npm version, safe default) or opt into patchJsMedia: true for automatic hotfixes (trades reproducibility for auto-patching -- do not enable without a deliberate reason) · ☐ weigh CSP implications (allow-listing source.zoom.us in Content-Security-Policy) and offline/reliability trade-offs (CDN adds an external runtime dependency the current bundled approach doesn't have) · ☐ remove @zoom/meetingsdk from package.json once the swap is verified working end-to-end.
  • Target: Backlog (re-prioritized High per user request, 2026-07-05) · Related Links:LiveClassRoom.jsx; Zoom Meeting SDK for Web docs; Import via CDN; official CDN sample.
  • Last Updated: 2026-07-05.

NFX-009

  • Date Reported: 2026-07-04 (pre-existing) · Reported By: Testing (ESLint import/no-unresolved, surfaced while rolling out eslint-plugin-sonarjs/eslint-plugin-security)
  • Priority: High · Severity: Major · Status: Open · Owner: — · Effort: M
  • Feature · Sub-feature: Market Mood, Index Radar, Settings, tier theming · multiple import sites
  • Issue Type: Bug · Domain(s): Reliability, Code quality
  • Description: 7 imports resolve to files that genuinely do not exist on disk (confirmed via direct filesystem check, not a resolver misconfiguration): MarketMoodLayout.jsx@/components/market-mood/MarketMoodTabs; MarketMoodNifty50Page.jsx@/components/market-mood/nifty50/Nifty50AnalyticsDashboard; IndexRadarPage.jsx@/hooks/useIndexRadarData and @/components/market-pulse/index-radar/config; IndexRadarTabs.jsx./config; src/hooks/index.js./useProfileData; src/tiers/users/theme/index.js./useUsersTierTheme.
  • Impact: These pages/modules likely already fail to build or crash at runtime on the affected paths, independent of any current work. Not yet root-caused (renamed file? never finished? dead import?) — needs investigation before fixing, not a guessed patch.
  • Proposed Solution / Action Items: ☐ For each of the 7, determine whether the target was renamed, never created, or the importing code is dead · ☐ fix the import or restore/create the missing module accordingly · ☐ confirm the affected pages actually render before closing.
  • Target: Backlog · Related Links: surfaced via eslint.config.mjs sonarjs/security rollout, 2026-07-04.
  • Resolution Date: — · Verification: — · Last Updated: 2026-07-05
  • Remarks: Pre-existing, unrelated to the SonarQube/ESLint rollout that surfaced it — do not conflate the two. 2026-07-05: each of the 7 import sites is now suppressed with a per-line eslint-disable-next-line import/no-unresolved -- NFX-009, ... comment (parse errors can't be suppressed this way, but these are rule-level violations after a successful parse) — this was needed to unblock the new Phase 2 GitHub Actions CI lint gate (.github/workflows/ci.yml), which lints the whole repo unconditionally, unlike the local hook which only lints touched files. The underlying bug is still open and still exactly as described above.

NFX-010

  • Date Reported: 2026-07-04 (pre-existing) · Reported By: Testing (ESLint parse error, same rollout as NFX-009)
  • Priority: Medium · Status: Resolved · Owner: — · Effort: S
  • Feature · Sub-feature: Settings · src/pages/SettingsPage.jsx
  • Issue Type: Technical Debt · Domain(s): Code quality, Developer experience
  • Description: The file has the modern tiers re-export (export { default } from '@/tiers/users/features/settings/pages/SettingsPage';, line 16) and a full legacy component implementation below it ending in its own export default SettingsPage; (line 368) — a duplicate-default-export parse error, leftover from the tiers migration.
  • Impact: Fails to parse under ESLint; the legacy body is dead code (superseded by the tier re-export) but currently still present and duplicating the export.
  • Proposed Solution / Action Items: ☑ Confirmed zero external consumers via the file's own documented grep (grep -r "from '@/pages/SettingsPage'" src/ → only the file itself) · ☑ deleted the legacy inline body (lines 18–368), keeping only the deprecation header + re-export (now 16 lines).
  • Target: Immediate (blocking the new Phase 2 CI lint gate) · Related Links: tiers migration pattern (src/tiers/ARCHITECTURE.md).
  • Resolution Date: 2026-07-05 · Verification: npm run lint clean; full npm run test run unaffected (99/100 files, 1351/1352 tests — the one failure is NFX-014, unrelated).
  • Last Updated: 2026-07-05 · Remarks: Same migration-cleanup pattern likely worth checking for on other pages/*.jsx re-export shims.

NFX-011

  • Date Reported: 2026-07-04 (pre-existing) · Reported By: Testing (ESLint parse error, same rollout as NFX-009)
  • Priority: Low · Status: Resolved · Owner: — · Effort: S
  • Feature · Sub-feature: Finfluencify · src/tiers/users/features/finfluencify/services/delete-bunnyService.js
  • Issue Type: Technical Debt · Domain(s): Code quality
  • Description: File's own header comment marks it TOMBSTONE — Bunny.net Video Hosting (REMOVED) and says to "Remove it entirely once all import sites are confirmed clean" — but an orphaned object-literal fragment (apiKey: …, libraryId: …, … }; with no opening declaration) remains below the stub exports, causing a parse error (Unexpected token :).
  • Impact: Fails to parse under ESLint; the file's own comment already flags it as removable.
  • Proposed Solution / Action Items: ☑ Confirmed zero import sites anywhere in src/ (grep -r "delete-bunnyService" src/ → no matches) · ☑ deleted the dead Bunny.net implementation below the stub (it was itself unparseable, and additionally redeclared the same const names as the stub above it — a duplicate-declaration error independent of the parse error) · kept the clean 4-function stub + header.
  • Target: Immediate (blocking the new Phase 2 CI lint gate) · Related Links: file's own header comment.
  • Resolution Date: 2026-07-05 · Verification: npm run lint clean; full npm run test run unaffected.
  • Last Updated: 2026-07-05 · Remarks: Someone already flagged this for removal and didn't finish — quick win once picked up.

NFX-012

  • Date Reported: 2026-07-04 (pre-existing) · Reported By: Testing (ESLint import/namespace, same rollout as NFX-009)
  • Priority: Low · Status: Open · Owner: — · Effort: S
  • Feature · Sub-feature: Trade Planner, Session Review · service tests
  • Issue Type: Bug · Testing · Domain(s): Testing, Code quality
  • Description: trade-planner/tests/services/tradePlannerService.test.js imports deletePlan and session-review/tests/services/sessionReviewService.test.js imports deleteSessionReview from their respective service modules — neither export exists. tradePlannerService.js explicitly comments "No delete export exists here, ever." — the test asserts against an intentionally-nonexistent API.
  • Impact: These specific test assertions are dead/broken; unclear if they're skipped/passing for the wrong reason or currently failing.
  • Proposed Solution / Action Items: ☐ Determine original intent of each test · ☐ remove or rewrite the assertions against the actual (append-only, no-delete) service contract.
  • Target: Backlog · Related Links: tradePlannerService.js no-delete comment.
  • Resolution Date: — · Verification: — · Last Updated: 2026-07-05
  • Remarks: Low risk (test-only), but worth cleaning up so the test suite doesn't reference a fictitious API. 2026-07-05: both assertions are now suppressed with a per-line eslint-disable-next-line import/namespace -- NFX-012, ... comment, needed to unblock the new Phase 2 CI lint gate. The underlying test design question (rewrite against the real no-delete contract) is still open.

NFX-013

  • Date Reported: 2026-07-05 (pre-existing) · Reported By: Developer (found while preparing the develop branch / CI rollout)
  • Priority: High · Status: Partially Resolved (untracked going forward; history-scrub still pending, deliberately) · Owner: — · Effort: M
  • Feature · Sub-feature: Platform · repo hygiene (.gitignore, git history)
  • Issue Type: Technical Debt · Domain(s): Security, Developer experience
  • Description: .env.local and supabase/.temp/* were both tracked in git (confirmed via git ls-files) — committed in history and pushed to origin. .gitignore never excluded either path. Values confirmed present were all VITE_-prefixed and safe-by-design (anon key, public Cloudflare delivery hashes, OAuth client id) — no service_role key or DB password was ever committed (verified during the NFX-027 backend-cicd-plan review).
  • Impact: Moderate, not catastrophic (per the exposure re-check above). More materially, it blocked per-environment configuration — every build (dev/UAT/prod) baked in the same hardcoded values from .env.local, which is what NFX-027's dev/prod isolation work needed fixed to actually take effect.
  • Done (2026-07-08, as part of NFX-027's Nefoxx-Dev rollout):git rm --cached .env.local and git rm -r --cached supabase/.temp · ☑ both added to .gitignore · ☑ .env.local repointed to Nefoxx-Dev as the new local-dev default (was hardcoded to prod) · ☑ .env.example added, documenting every required variable with no real values.
  • Still open (deliberately deferred): ☐ Git-history scrub (git filter-repo/BFG) of the historical commits containing these files — not executed, since the confirmed-safe-by-design values (no service_role/DB password) don't justify a shared-history rewrite (force-push affecting any other local clone) on their own. Revisit only if a genuinely sensitive value is ever found to have been committed.
  • Target: Done (untracking) / Backlog (history-scrub, conditional) · Related Links: NFX-027 (Nefoxx-Dev rollout that necessitated finishing this); discovered during Phase 0.2 branch-strategy setup (SonarQube/CI rollout), 2026-07-05.
  • Resolution Date: 2026-07-08 (untracking) · Verification: git status confirms both paths no longer tracked; deploy.yml now sources these values from GitHub Environment variables instead · Last Updated: 2026-07-08
  • Remarks: The history-rewrite question was explicitly deferred by user choice originally — that caution still stands; only the forward-looking untracking was done, matching the original remark's intent ("do not rush history rewriting").

NFX-014

  • Date Reported: 2026-07-05 (pre-existing) · Reported By: Testing (full npm run test run, while verifying NFX-010/NFX-011's fixes caused no regression)
  • Priority: Low · Status: Resolved · Owner: — · Effort: S
  • Feature · Sub-feature: Onboarding · src/tiers/users/features/onboarding/tests/pages/OnboardingPage.test.jsx
  • Issue Type: Bug · Testing · Domain(s): Testing, Code quality
  • Description: Line 477 asserted screen.getByText(/niftytoolkit\.com\/test-slug/i), but the component (OnboardingPage.jsx line 2401) builds the preview from window.location.host dynamically — it never hardcodes a domain. git log -S on OnboardingPage.jsx found the real history: the component used to hardcode niftytoolkit.com too, and was deliberately fixed to use window.location.host instead (so the preview is correct in every environment: localhost, devv.nefoxx.com, nefoxx.com) — the test was simply never updated to match that refactor. Empirically confirmed window.location.host in this vitest/jsdom setup is "localhost:3000", not any hardcoded domain.
  • Impact: 1 of 1352 tests failed on a clean npm run test run. Confirmed unrelated to and not caused by NFX-010/NFX-011's fixes (different feature area, no import relationship, pre-dates today's changes).
  • Proposed Solution / Action Items: ☑ Rewrote the assertion to derive its expected host from window.location.host directly (same source the component uses), instead of hardcoding any domain — future-proof against this exact class of bug recurring.
  • Target: Immediate · Related Links: af505c0 (rename commit, unrelated); the real cause was an earlier, separate, correct refactor of OnboardingPage.jsx's profileUrl.
  • Resolution Date: 2026-07-05 · Verification: npx vitest run on this file — 30/30 passed.
  • Last Updated: 2026-07-05 · Remarks: This investigation is what surfaced NFX-017 — other files never got the same window.location.host fix OnboardingPage.jsx already had.

NFX-015

  • Date Reported: 2026-07-05 · Reported By: Developer (Phase 1.2 PostToolUse hook crashing on every edit, while fixing NFX-009/012's lint suppressions)
  • Priority: Medium · Status: Resolved · Owner: — · Effort: S
  • Feature · Sub-feature: Platform · eslint-plugin-sonarjs (.claude/hooks/lint-changed-file.cjs)
  • Issue Type: Bug · Domain(s): Developer experience, Reliability
  • Description: sonarjs/no-skipped-tests's dependency-manifest lookup (assertNestedPath) does a case-sensitive check that the linted file path is nested under a computed topDir (derived from cwd). On Windows, process.cwd() returned D:\... (uppercase) while the hook passed the file path as d:\... (lowercase, matching the tool harness's convention) — an identical location on a case-insensitive filesystem, but a string-inequality crash for this rule's own check. Only reproduces when linting a single absolute file path (the hook's use case); whole-repo npm run lint (eslint .) doesn't hit this code path.
  • Impact: Crashed the PostToolUse lint hook (exit 2, no useful output) on every .js/.jsx edit under an affected directory — not a false positive, a hard crash that blocked the hook from reporting anything.
  • Proposed Solution / Action Items: ☑ Normalize the file path's drive-letter casing to match process.cwd()'s casing before invoking eslint, in the hook script itself.
  • Target: Immediate (blocking all local edits) · Related Links: .claude/hooks/lint-changed-file.cjs.
  • Resolution Date: 2026-07-05 · Verification: Re-ran the hook's exact stdin payload against a previously-crashing file — exit 0, no crash.
  • Last Updated: 2026-07-05 · Remarks: Windows-only footgun; worth remembering if any other tool in this pipeline ever compares an absolute path against process.cwd() directly.

NFX-016

  • Date Reported: 2026-07-05 · Reported By: Testing (first real GitHub Actions CI run, Phase 2)
  • Priority: Medium · Status: Resolved · Owner: — · Effort: S
  • Feature · Sub-feature: Platform · eslint.config.mjs scope
  • Issue Type: Technical Debt · Domain(s): Code quality, Developer experience, CI/CD
  • Description: The root (React-oriented) ESLint config had no exclusion for documentations/portal — a separate VitePress (Vue) sub-project with its own package.json/node_modules. Locally this never surfaced because documentations/portal/node_modules already existed from prior npm run docs:dev usage; the fresh GitHub Actions runner only ran the repo-root npm ci, so documentations/portal/docs/.vitepress/theme/index.js's import 'vitepress/theme' failed to resolve there, failing CI on its very first run.
  • Impact: First Phase 2 CI run failed at the lint step. The rules being applied (react/*, the @./src alias) were never meaningful for a Vue-based doc site regardless of the missing dependency.
  • Proposed Solution / Action Items: ☑ Excluded documentations/portal/** entirely from the root eslint.config.mjs scope (superseding the narrower pre-existing .vitepress/cache/**/dist/** entries).
  • Target: Immediate (blocking Phase 2 CI) · Related Links: .github/workflows/ci.yml first run, 2026-07-05; documentations/portal/package.json.
  • Resolution Date: 2026-07-05 · Verification: npm run lint locally, then confirmed no other documentations/portal/**/*.js files were newly exposed by the change.
  • Last Updated: 2026-07-05 · Remarks: A real local-vs-CI environment-parity gap, not a code bug — worth remembering that "works locally" can mean "this machine happens to have leftover installs."

NFX-017

  • Date Reported: 2026-07-05 · Reported By: Developer (investigating NFX-014's stale domain assertion)
  • Priority: Medium · Status: Resolved · Owner: — · Effort: S
  • Feature · Sub-feature: Finfluencify · LinkInBio (LinkInBioEditor.jsx, SlugClaimModal.jsx, useLinkInBio.js, TrainerPayoutsSettings.jsx, TrainerPublicPage.jsx, mediaUtils.js)
  • Issue Type: Bug · Domain(s): Code quality, Reliability
  • Description: 10 client-side occurrences of the retired niftytoolkit.com domain, found while investigating NFX-014. Unlike OnboardingPage.jsx (which already correctly uses window.location.host, see NFX-014), the LinkInBio feature and one Trainer settings action never got that fix: LinkInBioEditor.jsx (publicUrl + displayed URL), SlugClaimModal.jsx (BASE_URL + 2 illustrative example strings), useLinkInBio.js (2 toast messages), TrainerPayoutsSettings.jsx (support mailto: link), plus 2 stale comments (TrainerPublicPage.jsx, mediaUtils.js's CF zone note). Per the user: LinkInBio is not yet live / not serving real traffic (concept + mock-data UI), so this was not an active production incident, but needed fixing before real development continues on the feature.
  • Impact: Would have shown/generated the wrong (dead) domain in real shareable links, toasts, and the support contact link once the feature goes live, if left unfixed.
  • Proposed Solution / Action Items: ☑ Functional URL construction (publicUrl, BASE_URL, toast messages) switched to window.location.host, mirroring the already-established, already-tested pattern in SharePanel.jsx/HubSharePanel.jsx (which explicitly test "does NOT use a hardcoded niftytoolkit.com domain"). ☑ Fixed references (support email, illustrative marketing copy, comments describing the current URL pattern) updated to the literal nefoxx.com. ☑ Left IdentityRootRedirect.jsx's comment untouched — it accurately describes real old external QR codes that still need redirect support, not a bug.
  • Target: Immediate · Related Links: SharePanel.jsx/HubSharePanel.jsx (the established correct pattern this now matches); surfaced while investigating NFX-014.
  • Resolution Date: 2026-07-05 · Verification: npm run lint clean; full npm run test run — 100/100 files, 1352/1352 tests passed.
  • Last Updated: 2026-07-05 · Remarks: Deliberately left untouched: internal localStorage keys (niftytoolkit-theme-preference, niftytoolkit-sticky-notes-layout-*) — renaming would reset every existing user's saved preference, a real regression for a cosmetic fix. Also left: actual uploaded Cloudinary asset filenames, QR/CSV download filenames (cosmetic only), intentional test fixtures proving the old domain is ignored, and .md spec/README files (static docs, not runtime code).

NFX-018

  • Date Reported: 2026-07-05 · Reported By: Testing (full npm run test run, verifying NFX-017); actually diagnosed after CI (Phase 2) hit it as a real build failure
  • Priority: Medium · Status: Resolved · Owner: — · Effort: S
  • Feature · Sub-feature: Zoom Live Classes · LiveSessionList.jsx (component) / .test.jsx (test env)
  • Issue Type: Bug · Testing · Domain(s): Testing, Reliability
  • Description: Vitest reported 1 unhandled error from the test "auto-opens the detail modal and clears the param when deep-linked via ?session=": TypeError: cardRefs.current[sid]?.scrollIntoView is not a function (LiveSessionList.jsx:86, inside a requestAnimationFrame callback). Root cause: jsdom implements no layout/rendering, so Element.prototype.scrollIntoView doesn't exist there at all — the component code calling it is completely correct real-browser behavior, this was a missing test-environment stub, not a component bug.
  • Impact: Originally logged as "not blocking, exit code 0" — that was wrong. The local verification ran npm run test | tail -60; without pipefail, the reported exit code was tail's (always 0), not vitest's real one. CI (which runs the bare command, no pipe) surfaced the truth: this did fail the build the whole time. Correcting the record here rather than leaving the earlier wrong claim standing.
  • Proposed Solution / Action Items: ☑ Added a global scrollIntoView stub to src/tests/setup.js (Element.prototype.scrollIntoView = Element.prototype.scrollIntoView || function () {}) — the standard, widely-used fix for this exact jsdom gap; benefits any other component that calls it, not just this one.
  • Target: Immediate (was actively blocking CI) · Related Links: src/tests/setup.js; discovered via CI run following push 1a5dc72.
  • Resolution Date: 2026-07-05 · Verification: npm run test -- .../LiveSessionList.test.jsx — real (unpiped) exit code 0, 19/19 passed, zero unhandled errors. Full suite re-run to confirm no other fallout.
  • Last Updated: 2026-07-05 · Remarks: Process lesson: never read a piped command's exit code as the command's own — check $? immediately after the command, before any | tail/| grep, or redirect to a file and check $? right after.

NFX-019

  • Date Reported: 2026-07-05 · Reported By: Testing (first Phase 2 CI run to actually enforce npm run test:coverage's thresholds — never had teeth before today, no CI existed)
  • Priority: High · Status: Open · Owner: — · Effort: L
  • Feature · Sub-feature: Platform · test coverage (whole codebase)
  • Issue Type: Technical Debt · Testing · Domain(s): Testing, Code quality, Reliability
  • Description: vitest.config.js's coverage.thresholds (lines 70%, functions 80%, branches 65%, statements 70%) match CLAUDE.md's own documented Testing Strategy target — but real measured coverage (from CI, which ran the full suite successfully) is 17.06% lines / 30.45% functions / 17.06% statements / 51.19% branches. This was never caught before because there was no CI pipeline (the thresholds' exit code never blocked anything) and locally npm run test:coverage is rarely run day-to-day (developers use npm test/test:watch, which don't check coverage at all).
  • Impact: A large, real gap between the platform's own documented "comprehensive testing" standard and reality. Per CLAUDE.md's non-negotiable principles ("Untested code does not ship"), this is a genuine standard the codebase isn't meeting — not a false positive to suppress.
  • Proposed Solution / Action Items: ☑ (interim) Made the CI coverage step non-blocking (continue-on-error: true in .github/workflows/ci.yml) so real numbers stay visible every run without blocking merges on an unrealistic-today target · ☐ (real fix, not done here) actually write tests for the large uncovered surface area (many components/hooks/services currently at 0%) until coverage approaches the documented target · ☐ consider a patch/diff-coverage gate (Sonar-baseline-style: require coverage on new code only) as an intermediate step before re-enabling the global threshold as a hard gate.
  • Target: Backlog (large, ongoing effort) · Related Links: vitest.config.js coverage.thresholds; CLAUDE.md Testing Strategy section; .github/workflows/ci.yml.
  • Resolution Date: — · Verification: — · Last Updated: 2026-07-05
  • Remarks: User's explicit decision: make non-blocking for now rather than silently lower the documented thresholds or leave CI permanently red. This item is the real backlog entry that must not be forgotten — revisit at each release-planning pass per CLAUDE.md's tracker mandate.

NFX-020

  • Date Reported: 2026-07-05 · Reported By: Developer (diagnosing NFX-019, running npm run test:coverage locally to cross-check CI's reported numbers)
  • Priority: Low · Status: Open · Owner: — · Effort: M
  • Feature · Sub-feature: Platform · vitest / @vitest/coverage-v8 (local dev machine, Windows)
  • Issue Type: Bug · Domain(s): Developer experience, Testing
  • Description: Running the full suite with --coverage locally on this Windows dev machine fails completely — all 100 test files fail to even collect tests (Error: No test suite found in file ... for most; TypeError: Cannot read properties of undefined (reading 'on') for a couple involving HubSharePanel/MediaUploadSection), despite npm run test (no coverage) passing 100/100 files, 1352/1352 tests cleanly. A small-scope coverage run (single feature directory) works fine and reports real numbers, so the coverage instrumentation itself isn't fundamentally broken — this looks like a resource/crash issue specific to instrumenting the entire ~62k-line surface at once on this machine. CI (GitHub-hosted Linux runner) does not hit this — it ran the full suite with coverage successfully and reported real percentages (see NFX-019).
  • Impact: Nobody can currently verify real coverage numbers locally on this machine before pushing — only CI's (now non-blocking, per NFX-019) coverage step produces a trustworthy full-suite number.
  • Proposed Solution / Action Items: ☐ Investigate whether this is memory exhaustion (V8 coverage instrumentation is expensive; try --pool=forks / lower maxWorkers, or Node --max-old-space-size) · ☐ narrow down via bisection (half the suite, then half again) which file(s) actually trigger the crash rather than assuming it's purely a volume/resource issue.
  • Target: Backlog · Related Links: NFX-019 (surfaced while diagnosing it); CI run confirming the Linux runner doesn't reproduce this.
  • Resolution Date: — · Verification: — · Last Updated: 2026-07-05
  • Remarks: Not blocking — CI's coverage numbers are trustworthy even though local full-suite runs aren't right now.

NFX-021

  • Date Reported: 2026-07-05 · Reported By: Testing (first successful sonar-scan CI run, #10, push 068c7e5)
  • Priority: Medium · Status: Open · Owner: — · Effort: L (ongoing)
  • Feature · Sub-feature: Platform · SonarQube code quality (whole codebase, ~97.5k LOC)
  • Issue Type: Technical Debt · Domain(s): Code quality, Reliability, Security
  • Description: First-ever real measurement against SonarQube's own server-side rule engine (distinct from the eslint-plugin-sonarjs/eslint-plugin-security ESLint rules curated in Phase 1 — this is Sonar's full native analyzer, seeing the codebase for the first time): 80 bugs, 0 vulnerabilities, 12,792 code smells. Locked into sonar-baseline.json as the CI gate's baseline (see .github/workflows/ci.yml's sonar-scan job) — the gate now fails only if a future PR increases any of these counts; it does not require fixing existing debt to pass.
  • Impact: Real, large, pre-existing code-quality debt across the codebase — not blocking anything today, but a genuine gap worth closing over time, consistent with CLAUDE.md's "comprehensive testing"/"no known issue goes untracked" principles.
  • Proposed Solution / Action Items:Deliberate decision: no dedicated debt-burndown pass. Address feature-by-feature as normal development touches each area — whenever a feature is being worked on, review and clean up that feature's Sonar findings as part of the change (same treatment as NFX-005's untested EFs: "treat as part of any change to these files, not a follow-up") · ☐ Sonar findings become visible per-file, live, once SonarLint Connected Mode is configured (session-scoped — requires a locally running SonarQube instance to bind to, see guides/sonarqube-integration.md §6).
  • Target: Backlog (ongoing, feature-by-feature — not a scheduled burndown) · Related Links:sonar-baseline.json; .github/scripts/sonar-baseline-check.cjs; NFX-005 (same "fix as you touch it" precedent); CI run #10.
  • Resolution Date: — (ongoing, no single resolution) · Verification: Re-measured on every push to main/develop via the sonar-scan job — current counts always visible in that job's log.
  • Last Updated: 2026-07-05 · Remarks: This is the number to watch trend down over time, not a fire to put out now.

NFX-022

  • Date Reported: 2026-07-07 · Reported By: User (dev portal pages went blank after a doc push)
  • Priority: Medium · Severity: Low (docs-only, no production/app impact) · Status: Resolved · Owner: — · Effort: S
  • Feature · Sub-feature: Platform · Developer portal (VitePress, documentations/portal)
  • Issue Type: Bug · Domain(s): Documentation, Developer experience
  • Description: A doc update (guides/sonarqube-integration.md) quoted real GitHub Actions expression syntax — e.g. a dollar-brace-brace wrapper around github.ref_name — as inline single-backtick code in prose. VitePress compiles each Markdown page into a Vue component; fenced (triple-backtick) code blocks are auto-wrapped in v-pre and safe, but inline code spans are not. Vue's template compiler tried to evaluate that mustache syntax as a live interpolation referencing an undefined github object, breaking the page's render — the browser tab simply went blank with no visible error.
  • Impact: The local developer portal was unreadable until fixed. No effect on the live app or any Cloudflare deploy — this VitePress instance is local-only, not part of the CI/CD deploy pipeline.
  • Proposed Solution / Action Items: ☑ Reworded the three affected inline mentions to describe the flag/value without the literal wrapper syntax (the one legitimate use inside a fenced yaml block was already safe and left unchanged) ☑ Verified with a full local vitepress build (would have failed to render cleanly before the fix, completed clean after) · ☐ General guidance for future edits to this portal: never quote dollar-brace-brace GitHub Actions template syntax as inline code in prose — either fence it in a proper code block or describe it without the literal wrapper.
  • Target: — (resolved same session) · Related Links: commit c7d6612 (fix); guides/sonarqube-integration.md.
  • Resolution Date: 2026-07-07 · Verification: Local npx vitepress build docs completed clean (no render errors) after the fix. · Last Updated: 2026-07-07
  • Remarks: A VitePress-specific footgun worth remembering for any future doc page that quotes GitHub Actions/CI template syntax inline.

NFX-023

  • Date Reported: 2026-07-07 · Reported By: Discussion (user, forward-looking architecture question)
  • Priority: High · Status: Open · Owner: — · Effort: L
  • Feature · Sub-feature: Platform · Documentation infrastructure (developer / admin-ops / end-user portals)
  • Issue Type: Enhancement · Architecture · Domain(s): Documentation, Architecture, Security, Performance, Scalability, Developer experience
  • Description: As the platform grows, three genuinely distinct documentation audiences emerge: (1) the existing developer/engineering portal (this VitePress site), (2) an admin/internal-ops portal for operational procedures and internal reference, and (3) an end-user help center (guides, how-tos, FAQs, troubleshooting) for platform traders. All three should remain independent static site deployments — none bundled into the main React app's Vite build. Rationale: (a) anything living inside src/tiers/admin/ or src/tiers/public/ must clear this codebase's full non-negotiable engineering bar per CLAUDE.md (4-layer tests, RPC/EF boundary rules, tier import rules, dark/light theming) for content that carries none of that risk; (b) docs-only edits (an FAQ typo, a runbook update) shouldn't require a full app rebuild + sonar-scan + smoke test cycle through ci.yml; (c) the main app's build already needs a raised Node heap ceiling for its existing dependency graph — folding a docs corpus in risks further build-time/bundle-size cost for content unrelated to the trading product; (d) the end-user portal specifically wants SEO/crawlability that a dedicated docs framework does far better than routes hand-rolled inside a SPA.
  • Impact: Not urgent today (only the developer portal exists), but planning the right shape now avoids a costly retrofit later (e.g. having to un-bundle an admin-tier "Help" feature that grew inside src/tiers/admin/ after the fact).
  • Proposed Solution / Action Items: ☐ Stand up the admin/ops portal as its own static site (reuse the existing VitePress setup/pattern), own Cloudflare Pages project, gated via Cloudflare Access (Zero Trust) restricted to the admin/ops team — verify current Cloudflare Access free-tier terms at implementation time · ☐ Stand up the end-user help center as its own static site, own Cloudflare Pages project, public, own subdomain (e.g. help.nefoxx.com), linked from the app rather than embedded in it · ☐ Extend deploy.yml's existing reusable workflow_call pattern with one new calling workflow + one new Cloudflare Pages project per portal — no redesign needed, this is exactly the extensibility it was built for · ☐ Apply the Cloudflare "Production branch" rename prerequisite (see NFX-022 / guides/sonarqube-integration.md) to each new project before its first deploy · ☐ Decide whether the developer portal stays local-only long-term or moves behind Cloudflare Access if remote access is ever needed — it documents internals (EDGE_FN names, RLS internals, admin-auth mechanics) that shouldn't be public regardless · ☐ Give each new portal its own lightweight CI (markdown lint, dead-link check, build check), independent of the main app's ci.yml · ☐ Revisit the content-authoring workflow for the end-user help center if non-engineers (support/content staff) become its maintainers — a Markdown+PR workflow may become friction for a non-technical team.
  • Target: Backlog (future milestone, plan when appropriate) · Related Links:guides/sonarqube-integration.md (deploy.yml reusable workflow pattern); NFX-022 (VitePress Production-branch/compile gotchas relevant to any new VitePress-based portal); guides/git-setup.md.
  • Resolution Date: — · Verification: — · Last Updated: 2026-07-07
  • Remarks: Explicitly deferred by the user ("plan and implement when appropriate") — this is a design decision captured for later, not scheduled work.

NFX-024

  • Date Reported: 2026-07-07 · Reported By: User (spotted two workflow runs per commit in the Actions tab and questioned it directly)
  • Priority: Medium · Status: Resolved · Owner: — · Effort: S
  • Feature · Sub-feature: Platform · .github/workflows/ci.yml
  • Issue Type: Process Improvement · Domain(s): CI/CD, Cost efficiency
  • Description: Throughout the deploy-layer rollout, every fix pushed to develop was immediately fast-forwarded onto main as well (git push origin develop:main) to keep the two in sync. Since ci.yml triggers on push to either branch, pushing the identical commit SHA to both produced two full, independent workflow runs (build-and-test + sonar-scan, ~15 min combined) for one commit. The main-triggered run's deploy-dev job correctly skipped (branch guard), but the two most expensive jobs still ran twice. The habit started for a real reason early on — workflow_dispatch workflows must exist on the default branch to be dispatchable, which genuinely required fast-forwarding main once — but continuing it after every subsequent fix was unnecessary: verify-ci in deploy-prod.yml/deploy-uat.yml checks GitHub's check-runs API by commit SHA, not by branch, so the develop run alone already satisfies it.
  • Impact: Roughly 100+ minutes of GitHub Actions time burned for zero benefit across this session's fast-forwards alone (out of the 2,000 min/month private-repo allowance), and no functional risk (main pushes never auto-deploy), but it would keep compounding if left uncorrected.
  • Proposed Solution / Action Items: ☑ Stop mirroring every develop commit onto mainmain now only advances at a deliberate release/promotion point, not after every incremental fix · ☑ Add a concurrency group to ci.yml, keyed on the triggering ref with cancel-in-progress enabled, so a still-running run for the same ref is auto-canceled when a newer commit supersedes it (covers the adjacent case of rapid-fire pushes to the same branch during active debugging) · ☐ Once branch protection is configured (still pending, see guides/git-setup.md), main will only move via merged PRs from develop at actual release time, reinforcing this by construction.
  • Target: — (resolved same session) · Related Links: commit 53a183e (concurrency group); guides/sonarqube-integration.md §4c (promotion model); guides/git-setup.md (branch strategy).
  • Resolution Date: 2026-07-07 · Verification: ci.yml validated with js-yaml after the edit; behavior change (no more main-mirroring) is procedural, confirmed going forward by not fast-forwarding main for this same fix. · Last Updated: 2026-07-07
  • Remarks: A good example of a habit that was correct for the exact moment it started (bootstrapping workflow_dispatch discoverability) but wrong to keep doing afterward — worth re-checking any "just this once" workaround once its original justification no longer applies.

NFX-025

  • Date Reported: 2026-07-05 · Reported By: Discussion (SonarQube/SonarLint feasibility question that expanded into a full CI/CD assessment)
  • Priority: High · Status: Resolved · Owner: — · Effort: L
  • Feature · Sub-feature: Platform · CI/CD (whole pipeline: lint/test/build/Sonar/deploy)
  • Issue Type: Process Improvement · Domain(s): CI/CD, Security, Reliability, Developer experience
  • Description: Before this initiative, the repo had no .github/workflows/ at all — no automated gate on lint, tests, or builds on push or PR, and deployment was a fully manual npm run build + hand-upload of dist/ to whichever Cloudflare Pages destination was intended, for every environment. Full design writeup: SonarQube Integration: Feasibility Assessment.
  • Impact: Real defects reached CI-less production before (e.g. NFX-014/NFX-017/NFX-018's stale domain and jsdom gaps were only ever caught by manual review, not an automated gate); coverage/quality regressions had no mechanism to surface before a manual deploy.
  • Proposed Solution / Action Items:eslint-plugin-sonarjs + eslint-plugin-security added to eslint.config.mjs · ☑ ci.yml's build-and-test job: lint → test (hard gate) → test summary → coverage (non-blocking, NFX-019) → build · ☑ sonar-scan job: ephemeral sonarqube:community service container, fresh per-run token, baseline-gated via sonar-baseline.json (NFX-021) · ☑ deploy.yml reusable workflow (dev auto-deploy in ci.yml; UAT and production as separate workflow_dispatch workflows with independent SHA-based verify-ci checks) · ☑ Dev verified end-to-end (devv.nefoxx.com) · ☑ UAT verified end-to-end (uatt.nefoxx.com) · ☐ Production verified end-to-end — wired and ready, first manual trigger not yet run as of this entry.
  • Target: — (resolved same session) · Related Links:.github/workflows/{ci,deploy,deploy-uat,deploy-prod}.yml; sonar-baseline.json; guides/sonarqube-integration.md; guides/git-setup.md; NFX-026 (remaining governance toggles, split out separately since they're GitHub Settings actions, not pipeline code).
  • Resolution Date: 2026-07-07 · Verification: Dev and UAT deploys both confirmed working by the user against real Cloudflare Pages deployments; production deploy is gated and ready, pending a deliberate first trigger. · Last Updated: 2026-07-07
  • Remarks: Production's first real run isn't blocking this entry's resolution — the pipeline (the thing this item tracks) is complete and proven twice over (dev, UAT); running it a third time for production is a deployment event, not a remaining engineering task.

NFX-026

  • Date Reported: 2026-07-07 · Reported By: Discussion (final Phase 4 wrap-up review)
  • Priority: Medium · Status: Open · Owner: — · Effort: S
  • Feature · Sub-feature: Platform · Repo governance (GitHub Settings: Code security, Branches)
  • Issue Type: Process Improvement · Domain(s): Security, CI/CD
  • Description: Three items from the original CI/CD checklist are pure GitHub Settings toggles — not files in the repo, not gh CLI-executable in this environment (no gh installed, no admin-scoped API token available) — so they cannot be completed by an agent working from the repo; they need a human in the GitHub UI. Exact click-paths are documented in SonarQube Integration, checklist items 12–14.
  • Impact: (1) No Dependabot alerts/security updates — vulnerable dependencies wouldn't surface automatically. (2) No code scanning (CodeQL) evaluated/enabled — one fewer SAST layer than the design calls for. (3) No branch protection on main/developthe most important of the three: without "require a pull request" + "require status checks," anyone with push access can bypass CI entirely by pushing directly, which defeats the quality-gate design in NFX-025 by construction (not in practice yet, since it's a solo-developer repo, but the gate isn't structurally enforced today).
  • Proposed Solution / Action Items: ☐ Settings → Code security → enable Dependabot alerts + security updates · ☐ Settings → Code security → Code scanning → evaluate CodeQL "Default" setup availability for this private repo's current plan; enable if available, skip (don't force) if gated behind a paid entitlement · ☐ Settings → Branches → add a ruleset/rule for both main and develop requiring a pull request before merging and requiring the Lint, Test, Build and SonarQube Scan (baseline gate) status checks to pass · ☐ Once branch protection is on, update local habits per Git Setup & Workflowmain advances via merged PR, not git push origin develop:main.
  • Target: Backlog (next available session with dashboard access) · Related Links:guides/sonarqube-integration.md items 12–14; NFX-025 (the pipeline these harden).
  • Resolution Date: — · Verification: — · Last Updated: 2026-07-07
  • Remarks: Deliberately split out from NFX-025 rather than leaving it "Resolved with 3 exceptions" — a Resolved item should mean resolved; this keeps the real remaining work visible in Active.

NFX-027

  • Date Reported: 2026-07-07 · Reported By: Discussion (user, forward-looking backend-governance ask)
  • Priority: High · Status: In Progress (dev project live + full parity achieved — schema, storage, Edge Functions, cron; Phase C — PR-time validation gate — shipped 2026-07-09; Cloudflare/Zoom secrets + CI automation Phases D–F remain) · Owner: — · Effort: L (multi-phase)
  • Feature · Sub-feature: Platform · Backend CI/CD + Supabase environment isolation
  • Issue Type: Enhancement · Architecture · Domain(s): CI/CD, Security, Reliability, Scalability, Deployment/operations
  • Description: The Supabase backend is the last major area without governed CI/CD. All of dev, UAT, and production used to run on one Supabase Cloud Pro project (Nefoxx) — the shared-backend risk is now resolved (see below), and PRs touching supabase/ are now validated by backend-ci.yml (migration replay + pgTAP, EF tests/type-check). Backend deploys themselves (migrations, Edge Functions) remain manual supabase db push / functions deploy with no CI-driven promotion — that's Phases D/E. Full design of record — environment strategy, migration management, EF deploy automation, config-as-code, secrets, rollback/DR, promotion workflow, governance, monitoring, the Cloud-vs-self-host verdict, and a senior-architect gap review — is documented at Backend CI/CD (planned).
  • Impact: Data isolation for dev/UAT is now real — devv/uatt can no longer write to live prod. Remaining gap: backend deploys still have no automated CI gate, so a bad manual db push can still hit prod directly.
  • Done (2026-07-08):Nefoxx-Dev provisioned — Free tier, separate org (iepflzeiwckmdrrbehuz), ap-south-1 (matches prod), ref rchglrpywmxkcbmxcepl · ☑ Phase A "prove prod isn't drifted" — done via NFX-030: baseline migration verified byte-identical to live prod (db diff = "No schema changes found") · ☑ Baseline schema pushed to Nefoxx-Dev (db push --linked), verified clean · ☑ Storage buckets replicated (5 buckets: guide_images, finfluencify-course-thumbnails, finfluencify-course-materials, finfluencify-trainer-documents, ntk-users-profile-photo — matched public/size-limit config from prod, re-verified byte-for-byte in the NFX-032 audit) · ☑ Seeded with synthetic test users — reused the E2E seed.sql (trader/admin/target, *.local emails) instead of copying real prod user PII: no functional benefit to real data, avoids PII in a second/lower-scrutiny environment, avoids a stale snapshot · ☑ NFX-013 resolved: .env.local untracked (git rm --cached), repointed to Nefoxx-Dev as the new local-dev default, .env.example added · ☑ Per-environment frontend wiring: deploy.yml's Build step now injects VITE_SUPABASE_URL/VITE_SUPABASE_ANON_KEY/VITE_SUPABASE_URL_FALLBACK from GitHub Environment variables (dev/uat → Nefoxx-Dev, production → unchanged prod) — set by the user across all three environments and verified sequenced safely (production's vars were confirmed in place before .env.local stopped being the fallback source, avoiding an auth-breaking gap) · ☑ Logged NFX-031 — Google OAuth for Nefoxx-Dev (dashboard-only, user's action item) · ☑ NFX-032: independent re-audit + full remediation (2026-07-08, same day) — this entry's original "Cron replicated" line above was wrong: it claimed prod had only one cron job with "zero net.http_post/external-call risk found anywhere," based solely on grepping migration files. A live select * from cron.job against prod (not just its migrations) found 26 real jobs, 21 of them net.http_post calls to prod Edge Function URLs — none of that had been checked. The same live-query audit also found 0 of 67 Edge Functions and 0 of 25 secrets had ever actually been deployed/set on Nefoxx-Dev, meaning devv.nefoxx.com/uatt.nefoxx.com were non-functional for every write and enriched read from the moment the frontend was repointed at Nefoxx-Dev. All now fixed except secrets — see NFX-032 for full detail, the corrected parity table, and the promotion runbook now codified in CLAUDE.md.
  • Phase C shipped (2026-07-09): .github/workflows/backend-ci.yml (two parallel jobs — db-migrations-pgtap: migration replay via supabase start + pgTAP; edge-functions: deno test/deno check, visibility-first pending NFX-004 + NFX-037), path-filtered to supabase/**. config.toml expanded from 3 to 32 verify_jwt=false entries (the authoritative set, sourced from prod's own functions list) and one pre-existing wrong entry (trade-planner-view-shared) removed. test:ef script fixed (was missing --allow-env --allow-net --allow-read, so it had never actually completed a run as written). Full corrected design, including why the drift-check moved out of the PR gate and into post-deploy validation: see the rewritten Backend CI/CD plan.
  • Still open (Phases D–F): ☐ Cloudflare + Zoom secrets on Nefoxx-Dev (values pending from user — see NFX-035) · ☐ Auth config parity (Site URL, redirect URLs, providers) — not verifiable via CLI/SQL, needs manual Dashboard comparison (see NFX-036) · ☐ backfill NFX-005 EF tests · ☐ fix NFX-004 and NFX-037 before promoting the edge-functions job from visibility to blocking · ☐ free-tier 7-day-inactivity auto-pause keep-warm mechanism (candidate: the nightly E2E regression job from NFX-029) — not yet designed, just identified · ☐ Phase D: auto-deploy to non-prod on develop, with scoped per-environment access tokens (not the single account-wide token originally planned) · ☐ Phase E: manual prod promotion (verify-ci checking both backend-ci job names + pre-deploy snapshot) · ☐ Phase F: branch protection, DR runbook (PITR decision), monitoring — connection-pool/RPC-latency alerting named as the first priority.
  • Target: Future (Phases D–F picked up when the need arises) · Related Links:guides/backend-cicd-plan.md; guides/environment-strategy.md (full architecture + promotion runbook); NFX-030 (Phase A drift-proof, done); NFX-031 (Google OAuth follow-up); NFX-032 (parity re-audit + remediation, corrects this entry's original cron claim); NFX-033 (cron + storage-bucket IaC gap, found during NFX-032); NFX-029 (E2E, shares the ephemeral-stack pattern + could serve as the free-tier keep-warm heartbeat); NFX-005 (untested EFs, prerequisite); NFX-026 (branch protection, Phase F); NFX-004 and NFX-037 (Job-2 blockers).
  • Resolution Date: — (partial — schema/storage/EF/cron parity done, Phase C shipped; Cloudflare/Zoom secrets + Phases D–F still open) · Verification: db diff --linked on Nefoxx-Dev matches the baseline; seed users confirmed queryable; deploy.yml/backend-ci.yml YAML validated; supabase functions list/secrets list/cron.job all re-verified live against both projects on 2026-07-08 (see NFX-032); npm run test:ef re-verified locally on 2026-07-09 after the permission-flag fix (1804 passed, 1 failed — NFX-037) · Last Updated: 2026-07-09
  • Remarks: Phase A/B were explicitly deferred by the user, then revisited and re-evaluated on 2026-07-09 at the user's request ("verify that it remains valid after the recent Supabase environment changes... then we will proceed with its implementation") — that re-evaluation is NFX-032 (parity audit) plus this entry's Phase C. The free-tier + separate-org refinement (2026-07-08) reduces cost with no lock-in; the auto-pause behavior is the one operational risk still needing a deliberate design before Phase D relies on it unattended.

NFX-028

  • Date Reported: 2026-07-07 · Reported By: Monitoring (GitHub Dependabot alerts, surfaced on push to digious-platforms/nefoxx)
  • Priority: High · Severity: 3 Critical / 18 High / 33 Moderate / 5 Low (GitHub count) · Status: Open · Owner: — · Effort: M (triage) + variable (fixes)
  • Feature · Sub-feature: Platform · Dependency supply chain (npm root + docs portal)
  • Issue Type: Security · Technical Debt · Domain(s): Security, Reliability, Maintenance
  • Description: With Dependabot alerts now enabled, GitHub reports 59 vulnerabilities (3 critical, 18 high, 33 moderate, 5 low) across the repo's dependencies. Local npm audit grounds the actionable subset: root app = 21 (3 critical, 7 high, 10 moderate, 1 low); docs portal (documentations/portal) = 4 (1 high, 3 moderate — the portal's high traces to vitepress via vitepress-plugin-mermaid). GitHub's higher total reflects its broader advisory DB and full-manifest scan; the 3 criticals align exactly between GitHub and npm audit, so those are the unambiguous starting point.
  • Impact: Pre-existing supply-chain risk on a production fintech platform (payments via Razorpay, broker-credential handling). Real exposure varies sharply by whether a vulnerable package is runtime-reachable (ships in the app bundle / executes in an Edge Function) vs. build/dev-only (build tooling, test libs, docs portal) — the latter is far lower real-world risk. Triage must separate these before spending effort.
  • Proposed Solution / Action Items: ☐ Triage from the GitHub Security → Dependabot tab + npm audit --json; fix the 3 criticals first, then runtime-exposed highs · ☐ Apply non-breaking fixes via npm audit fix (root + portal) and let Dependabot's grouped PRs (now configured, NFX-026 follow-on) handle routine minor/patch bumps · ☐ For breaking (audit fix --force) or no-fix-available advisories, assess reachability and either upgrade the parent, replace the dependency, or consciously accept + note the risk · ☐ Re-baseline the count after the first pass and track the trend down (like the Sonar baseline in NFX-021) · ☐ Note: Deno/Edge-Function imports are not covered by Dependabot — review those separately.
  • Target: Backlog (dedicated triage session) · Related Links: GitHub Security → Dependabot alerts; .github/dependabot.yml (version updates now configured); NFX-026 (Dependabot enablement); NFX-021 (baseline-trend-down precedent).
  • Resolution Date: — · Verification: — · Last Updated: 2026-07-07
  • Remarks: Not fix-and-forget: the goal is the count trending down over time with criticals/highs cleared, not a one-shot audit fix. Many moderates will be build/dev-only and legitimately lower priority once reachability is confirmed.

NFX-029

  • Date Reported: 2026-07-08 · Reported By: Discussion (user, testing-strategy ask)
  • Priority: High · Status: In Progress (Phase 3 shipped, live-deploy verification pending) · Owner: — · Effort: L (multi-phase)
  • Feature · Sub-feature: Platform · Playwright E2E testing layer (above the Vitest 4-layer model)
  • Issue Type: Enhancement · Testing · Domain(s): Testing, CI/CD, Reliability, Accessibility, Quality
  • Description: The platform's Vitest suite is mature but runs entirely in JSDOM — no test executes a real browser, a real Vite bundle, or a real Supabase network call, so an entire failure class (broken imports like the RiEdit3Line incident, theme/contrast breaks, canvas/export bugs, frontend↔backend contract drift) is structurally invisible. This adds a production-grade Playwright layer — critical user journeys, @axe-core accessibility, narrow visual regression, mobile viewport, an api contract-test project, and a real functional deploy-smoke check to replace deploy.yml's bare curl. Full design of record (architecture, CI wiring across PR/dev/UAT/prod, reporting, quality gates, flaky-quarantine, a 13-point Principal-Architect review) is at E2E Testing Strategy.
  • Impact: Closes the browser-level gap that a green Vitest run cannot cover; gives real deployment confidence (the current post-deploy check would pass a blank white-screen). Respects the shared-backend constraint (NFX-027): write journeys run only against an isolated ephemeral local stack, never a real environment, structurally enforced by a mutation-guard fixture.
  • Proposed Solution / Action Items (phased, mirrors the frontend CI/CD rollout order): ☑ Phase 1 — foundation: playwright.config.js (plain JS, no TS), env-override safety contract, endpoint-allowlist mutation guard, dynamic-user isolation fixture, schema-snapshot test-DB model (supabase/schema.sql + e2e-extensions.sql + e2e-auth-hooks.sql + seed.sql, loaded via tools/e2e-db-setup.mjs), throwaway spec proving login + zero real-backend egress · ☑ Phase 2 — smoke suite + PR gate (2026-07-09): 5 real journeys against the ephemeral stack (auth sign-in/failure/modal gate, trade-planner create→save→list→close, trade-planner create→share→anonymous-public-view round trip, market-mood read-only), an api contract project (trade-planner-save auth + success-shape checks via raw @supabase/supabase-js, no browser), an a11y critical-only PR-blocking subset (2 pages), e2e-smoke added to ci.yml as a blocking job (needs: build-and-test, added to deploy-dev's needs:), .github/scripts/e2e-summary.cjs (Playwright-JSON-shaped sibling of test-summary.cjs), e2e/** added to sonar.sources. Found and fixed two structural gaps the Phase-1 proof spec's narrower scope didn't exercise (CSP connect-src silently killing the ephemeral stack's plain-HTTP calls; supabase start not serving Edge Functions — supabase functions serve is a separate process) and one real product bug (NFX-040, public share links wrongly auth-gated) plus one real a11y bug (password toggle missing aria-label, fixed) — see guides/e2e-testing-strategy.md's "What Phase 2 found" section for full detail · ☑ Phase 3 — deploy-smoke (2026-07-09): e2e/smoke/deploy/fixtures.js (mutation guard installed via a page fixture override — structurally unskippable) + public-pages.spec.js (real rendered content + zero console errors on /auth and a public content page, read-only); deploy.yml's bare curl replaced with a real Playwright smoke-deploy run (curl kept as a cheap pre-flight propagation poll); verify-ci in deploy-uat.yml/deploy-prod.yml now requires "E2E Smoke (Playwright)" alongside the existing two checks; manual CF Pages rollback runbook added (guides/deployment.md §5). Not yet verified against a real deploy — see NFX-045: dev/uat GitHub Environment variables were found missing/incorrect while building this phase (both environments were building against Production Supabase), corrected by the user, but no fresh deploy has run yet to bake the fix in and exercise this gate for real · ☐ Phase 4 — regression/visual/cross-browser/mobile (nightly, visibility→blocking after 10 green runs) · ☐ Phase 5 — remaining docs/governance (flaky-quarantine process).
  • Target: Current (Phase 4 next) · Related Links: guides/e2e-testing-strategy.md; NFX-027 (shares the ephemeral-stack pattern + shared-backend constraint); NFX-030 (why the test DB uses a schema snapshot, not migration replay); NFX-019 (coverage gate, related quality-gate discipline); NFX-038 (color-contrast debt found by the new a11y gate); NFX-039 (backend defect found incidentally); NFX-040 (public-share auth-gating bug found and fixed in Phase 2); NFX-045 (Phase 3's pending live-deploy verification, devv/uatt env-var finding).
  • Resolution Date: — · Verification: Phase 1: schema snapshot + seed load clean, real GoTrue password login works, dynamic-user fixture provisions isolated users. Phase 2: full local run of --project=smoke-ephemeral --project=api --project=a11y green after fixes (10/10 relevant specs, excluding one confirmed-transient local-machine flake in the Phase-1 proof spec unrelated to Phase 2's own changes — see guides/e2e-testing-strategy.md's local-flakiness note); npx eslint e2e/ clean; ci.yml validated with js-yaml. · Last Updated: 2026-07-09
  • Remarks: The schema-snapshot pivot (NFX-030) replaced the plan's original "replay migrations in the ephemeral stack" step — a strict improvement (faster CI, zero prod risk, no dependence on migration replayability). Phase 2 reinforced a pattern worth naming: standing up real write-journey E2E coverage finds real bugs the absence of that coverage was hiding (NFX-040, the a11y findings) — this is the point of the initiative, not a detour from it.

NFX-030

  • Date Reported: 2026-07-08 · Reported By: Testing (discovered during NFX-029 Phase 1, first from-scratch supabase db reset this repo has been put through)
  • Priority: High · Severity: Blocked any from-scratch DB rebuild + prod db push was unsafe · Status: Resolved · Owner: — · Effort: L
  • Feature · Sub-feature: Platform · Supabase migrations (version naming + prod tracking desync)
  • Issue Type: Bug · Technical Debt · Domain(s): Reliability, CI/CD, Maintainability
  • Description: The YYYYMMDD_NNN_descriptive.sql convention collided on Supabase's version parser (leading digits before the first _ → same-day migrations collapsed to one version; 149/210 files affected), so supabase db reset/supabase start aborted with duplicate key … schema_migrations_pkey. Investigating why revealed a deeper root cause: prod's own schema_migrations table recorded only 6 of 212 local files as applied (5× 2026-04-06 + 20260410) — prod's schema was built via direct SQL, not supabase db push, so the migration history was never a reliable, replayable record of prod at all. This confirms "Gap A" from the backend CI/CD plan — and meant supabase db push was already unsafe (it would see ~204 "unapplied" migrations and try to replay non-idempotent DDL against a prod DB that already has that schema).
  • Impact: Blocked the ephemeral-stack model for NFX-029 (worked around via a schema snapshot) and NFX-027's Phase C/drift-checking design. Now fully unblocked for both.
  • Resolution — baseline/squash + prod reconcile: ☑ Dumped prod's real live schema via supabase db dump (read-only) · ☑ Assembled a complete baseline (supabase/migrations/20260708000000_baseline_prod_schema.sql) = the dump + the 2 auth.users triggers + 4 storage.objects policies a schema-only dump omits (managed schemas) · ☑ Archived all 210 old migration files to supabase/migrations/_archive/ (git history preserved via git mv, not deleted) — includes the 2 genuine DDL bugs found and fixed en route (pg_policies.polnamepolicyname; a certificate-templates create/alter ordering fix) · ☑ Verified locally: supabase db reset green from an empty volume (baseline replays, seed.sql runs, real GoTrue password login works) · ☑ Reconciled prod: supabase migration repair <6 old versions> --status reverted --linked then supabase migration repair 20260708000000 --status applied --linked — metadata-only, no DDL executed against prod · ☑ Final proof: supabase migration list shows local/remote in exact agreement on 20260708000000 only; supabase db diff --linked against the live baseline returned "No schema changes found" — the archived-migration-derived baseline is byte-identical to prod's actual live schema.
  • Target: Done · Related Links: NFX-027 (Gap A — this was its concrete confirmation and fix); NFX-029 (E2E, unblocked); guides/backend-cicd-plan.md; guides/e2e-testing-strategy.md; supabase/migrations/_archive/README.md.
  • Resolution Date: 2026-07-08 · Verification: db reset green locally + db diff --linked = "No schema changes found" against live prod · Last Updated: 2026-07-08
  • Remarks: New migrations going forward use Supabase's native 14-digit YYYYMMDDHHMMSS_ timestamp format (collision-proof by construction), on top of the baseline — not the old YYYYMMDD_NNN_ convention. supabase db push is safe to use again.

NFX-031

  • Date Reported: 2026-07-08 · Reported By: User (during Nefoxx-Dev provisioning)
  • Priority: Medium · Status: Open · Owner: User · Effort: S (dashboard/console config only)
  • Feature · Sub-feature: Platform · Nefoxx-Dev — Auth (Google OAuth provider)
  • Issue Type: Process Improvement · Domain(s): Auth, Deployment/operations
  • Description: Nefoxx-Dev (the new non-prod Supabase project, NFX-027) does not yet have its own Google OAuth app. The frontend code is provider-agnostic (supabase.auth.signInWithOAuth({ provider: 'google' }) — no branching on which project/OAuth app is behind it), so no code changes are needed; this is entirely Google Cloud Console + Supabase Auth dashboard configuration.
  • Impact: Until configured, the Google sign-in button is visible on devv/uatt but errors when clicked — expected, not a bug. Email/password sign-in on dev is unaffected (seed users use email/password only).
  • Proposed Solution / Action Items: ☐ Create a Google Cloud Console OAuth 2.0 Client ID scoped to the dev domain(s) — authorized JavaScript origins https://devv.nefoxx.com (and uatt.nefoxx.com if treated separately) · ☐ Authorized redirect URI: Nefoxx-Dev's https://rchglrpywmxkcbmxcepl.supabase.co/auth/v1/callback · ☐ Paste the resulting Client ID + Secret into Nefoxx-Dev's dashboard: Authentication → Providers → Google · ☐ Set SITE_URL and the redirect allow-list in Nefoxx-Dev's Auth settings to the dev frontend domain.
  • Target: Backlog (user will pick up) · Related Links: NFX-027 (Phase B, "per-project OAuth" gap E in the backend CI/CD plan).
  • Resolution Date: — · Verification: — · Last Updated: 2026-07-08
  • Remarks: No dependency on any other tracker item — can be done independently, whenever convenient.

NFX-032

  • Date Reported: 2026-07-08 · Reported By: User (requested a principal-level architect review of the full Prod/Dev-UAT Supabase split, per NFX-027)
  • Priority: Critical · Severity: devv.nefoxx.com/uatt.nefoxx.com were non-functional for every write and enriched read (every supabase.functions.invoke() call in the codebase) from the moment the frontend was repointed at Nefoxx-Dev · Status: Resolved (all agent-actionable scope — EF deployment, cron replication + naming, CLAUDE.md/docs updates — fixed and re-verified same day; the two remaining sub-items needed real credential values or dashboard-only config, so they're spun out as their own user-owned entries, NFX-035 and NFX-036, rather than left as open checkboxes inside a "resolved" item) · Owner: — · Effort: M
  • Feature · Sub-feature: Platform · Nefoxx-Dev — Edge Functions / secrets / cron parity
  • Issue Type: Bug · Technical Debt · Domain(s): Reliability, CI/CD, Security, Deployment/operations
  • Description: A requested re-evaluation of NFX-027's completeness, using live read-only queries against both Supabase projects rather than trusting the prior session's claims. Findings, verified via supabase functions list, supabase secrets list, and select * from cron.job against both project refs:
    • Edge Functions: 0 of 67 deployed to Nefoxx-Dev. functions list --project-ref rchglrpywmxkcbmxcepl returned an empty table. Since every write and enriched read in this codebase goes through an Edge Function (supabase.from() is banned — see Database Access Strategy in CLAUDE.md), this meant devv/uatt could not save a trade plan, complete onboarding, or do anything beyond a pure RPC read.
    • Secrets: 0 of 25 configured on Nefoxx-Dev. secrets list returned an empty table — Cloudflare, Zoom, and (unused) Shoonya credentials were all missing.
    • Cron jobs: 1 of 26 replicated, and the 1 that existed (a generic VACUUM ANALYZE;) matched none of prod's actual jobs. This directly corrects NFX-027's original "cron replicated" claim, which asserted prod had only one job with "zero net.http_post/external-call risk found anywhere in the migration history." That check only grepped migration files — it never queried the live cron.job table. Production actually has 26 rows: 21 active net.http_post calls to prod Edge Function URLs (NSE market-data ingestion, refresh-materialized-views, daily-scheduled-clean-up, finfluencify-live-session-reminder-sweep), 4 per-table VACUUM jobs, and 1 inactive job (notifications-fanout) — none of it captured in any migration (see NFX-033).
    • Everything else checked out: schema objects (144 tables, 192 policies, 86 triggers, 18 views, 21 matviews, 12 sequences, 11 extensions — all identical between projects), storage buckets (5/5, identical config), and the frontend CI/CD wiring in ci.yml/deploy.yml/deploy-uat.yml/ deploy-prod.yml (structurally correct — environment: resolution confirmed to work as designed).
  • Impact: Before this fix, any manual QA or future E2E work against devv/uatt would have failed on the very first write, with no obvious cause (a 404 from a missing function looks like a config error, not a "the backend was never actually finished" error). The corrected cron claim also means a previously undetected production governance gap (NFX-033) surfaced.
  • Proposed Solution / Action Items: ☑ Deploy all 67 Edge Functions to Nefoxx-Dev, matching each function's verify_jwt setting exactly (32 Type B / --no-verify-jwt, 35 Type A — determined via functions list -o json's verify_jwt field on prod, not assumed) · ☑ Replicate all 26 cron jobs to Nefoxx-Dev with every net.http_post URL rewritten from lyaldbfgdhxpllgxbcxp.supabase.co to rchglrpywmxkcbmxcepl.supabase.co, schedules and active/inactive flags matched exactly · ☑ Follow-up fix (same day, user-caught via Dashboard screenshot comparison): the first replication pass used the unnamed 2-arg cron.schedule(schedule, command) form, so all 26 dev jobs showed "No name provided" in the Dashboard even though every prod job is named (nse-, fetch_nse_market_status, vacuum-analyze-option-chain-daily, etc.) — my own verification query never selected the jobname column, so I didn't catch this myself. Re-queried prod with jobname included, dropped all 26 unnamed dev jobs, recreated them with the named 3-arg form using prod's exact names, and fixed one incidental whitespace-only schedule difference (*/30 0-16 * * 1-5, double space, prod's own pre-existing typo) for full byte-level parity. Re-verified: 26/26 names match, 0 missing, 0 extra, all schedules and active flags identical · ☑ Confirmed SHOONYA_API_*/INSTRUMENT_SYMBOL are stale/unused even on prod (user confirmation) — deliberately not replicated (see NFX-034) · ☑ Added CLAUDE.md Architecture — Environment Strategy section codifying the non-negotiable promotion rule, plus fixed two pieces of documentation this review exposed as stale: the migration-naming convention (still described the exact YYYYMMDD_NNN_ pattern that caused NFX-030) and the Change Manifest Policy section (still asserted "a single Supabase project shared by dev and prod") · ☑ New documentations/portal/docs/guides/environment-strategy.md — full architecture, deployment-flow diagram, promotion runbook, parity verification table, honest gap disclosure, plus a bulk cron activate/deactivate runbook (SQL Editor + CLI forms) added on request · ☑ Spun out the two items needing real credentials or dashboard-only config as their own user-owned entries rather than leaving them as unresolved checkboxes here — see NFX-035 (Cloudflare + Zoom secrets) and NFX-036 (Auth config parity). Per the user: deliberately left open and non-blocking, to be picked up if/when a blocker in related feature work requires them — not tracked as part of this item's resolution.
  • Target: Done · Related Links: NFX-027 (parent item, corrected by this entry); NFX-030 (the migration-naming fix this review propagated into CLAUDE.md); NFX-033 (cron IaC gap, found here); NFX-034 (Shoonya cleanup, found here); NFX-035 (Cloudflare/Zoom secrets, spun out); NFX-036 (auth config parity, spun out); guides/environment-strategy.md (full detail); CLAUDE.md Architecture — Environment Strategy.
  • Resolution Date: 2026-07-08 · Verification:functions list --project-ref rchglrpywmxkcbmxcepl -o json → 67 functions, verify_jwt matched per-function against prod's own list; select jobid, jobname, schedule, command, active from cron.job on both projects, diffed programmatically by name → 26/26 names match, 0 missing, 0 extra, schedules and active flags identical after the whitespace fix; npm run docs:build green (new guide's mermaid diagrams render, no broken links) · Last Updated: 2026-07-08
  • Remarks: This item exists specifically because "the prior session said it was done" was not treated as sufficient evidence — every claim in NFX-027's original "Done" list was re-verified against live project state before being trusted, which is what surfaced both the EF/secrets gap and the incorrect cron claim. The cron name gap then repeated the same lesson one level deeper: my own first-pass verification query selected jobid, schedule, command, active but not jobname, so I missed that prod names every job and dev didn't — the user caught it from a Dashboard screenshot, not from anything I reported. Recommend live-query verification that selects every relevant column (not just the ones assumed relevant up front) become the standard way to check Prod/Dev parity going forward — codified in CLAUDE.md and guides/environment-strategy.md §5.

NFX-033

  • Date Reported: 2026-07-08 · Reported By: Testing (discovered during the NFX-032 live-query audit; scope broadened 2026-07-09 during the backend-CI-plan staleness audit)
  • Priority: Medium · Status: Open · Owner: — · Effort: M
  • Feature · Sub-feature: Platform · Supabase — cron jobs and storage buckets not version-controlled
  • Issue Type: Technical Debt · Process Improvement · Domain(s): Reliability, Maintainability, CI/CD
  • Description: Two independent Supabase config surfaces exist only as live database state, in neither project's migrations — same root cause, found at different times:
    • Cron jobs: production has 26 rows in cron.job (21 active net.http_post calls to Edge Functions, 4 VACUUM jobs, 1 inactive job) — none exist in any migration file. Set up directly against the live database (SQL editor or equivalent), not through supabase db push.
    • Storage buckets (found 2026-07-09, re-evaluating the backend CI/CD plan against this session's changes): all 5 buckets (guide_images, finfluencify-course-thumbnails, finfluencify-course-materials, finfluencify-trainer-documents, ntk-users-profile-photo) are correctly configured and at parity on both projects, but confirmed via direct grep of supabase/migrations/20260708000000_baseline_prod_schema.sql for storage.buckets insert statements — zero matches. Same gap, same fix mechanism. Both are pre-existing gaps on production itself, independent of the Nefoxx-Dev split — they surfaced only because live-query audits checked cron.job/storage.buckets directly instead of relying on migration history (the same category of blind spot that caused NFX-030).
  • Impact: Neither cron nor bucket configuration can be code-reviewed, diffed, or restored from version control. A cron job or bucket accidentally dropped or misconfigured via the Dashboard has no recorded "correct" state to restore from except this tracker entry and the live database itself. Also means both cron.job and storage.buckets need manual comparison (not just migration review) on any future parity check.
  • Proposed Solution / Action Items: ☐ Write a migration that captures all 26 cron jobs as named, idempotent cron.schedule(job_name, schedule, command) calls — both projects' live jobs are already correctly named (matched 26/26 as of the NFX-032 follow-up fix), so this migration only needs to express the existing state as version-controlled SQL, not restructure anything · ☐ Write a companion migration (or the same one) capturing the 5 storage bucket definitions (insert into storage.buckets (id, name, public, file_size_limit, allowed_mime_types) values (...), idempotent via on conflict (id) do nothing) · ☐ Once migration-tracked, future changes to either go through a migration like any other DDL, closing the gap for good.
  • Target: Backlog · Related Links: NFX-032 (where cron was found); NFX-030 (same root-cause pattern — live DB state undocumented in migrations); guides/backend-cicd-plan.md (Completeness model section now carries an explicit exception note for both).
  • Resolution Date: — · Verification: — · Last Updated: 2026-07-09
  • Remarks: Deliberately not fixed in the same session either half was found — restructuring production's existing cron jobs or writing a bucket-provisioning migration against a live project is a more invasive change than either discovery session was authorized for. Needs its own deliberate, reviewed change.

NFX-034

  • Date Reported: 2026-07-08 · Reported By: Testing (discovered during the NFX-032 secrets audit; confirmed stale by user)
  • Priority: Low · Status: Open · Owner: — · Effort: S
  • Feature · Sub-feature: Platform · Supabase — stale Shoonya broker secrets
  • Issue Type: Technical Debt · Domain(s): Security, Maintainability
  • Description: SHOONYA_API_KEY, SHOONYA_API_PASSWORD, SHOONYA_API_USER_ID, and INSTRUMENT_SYMBOL are configured as secrets on production. Their only consumer, shoonya-nse-indices, is not referenced anywhere in prod's cron.job table (confirmed during the NFX-032 audit) — i.e. the function that would use these live trading-broker credentials isn't actually scheduled to run. User confirmed: "this is stale and these are not being used anywhere in production."
  • Impact: Low — unused credentials sitting as secrets are a minor blast-radius-reduction opportunity (fewer live credentials = less exposure if the project were ever compromised), not an active risk. Deliberately not replicated to Nefoxx-Dev, avoiding any risk of test/QA activity authenticating against a real trading account.
  • Proposed Solution / Action Items: ☐ Confirm shoonya-nse-indices has no other invocation path (manual dashboard trigger, external webhook) before removing · ☐ supabase secrets unset SHOONYA_API_KEY SHOONYA_API_PASSWORD SHOONYA_API_USER_ID INSTRUMENT_SYMBOL --project-ref lyaldbfgdhxpllgxbcxp · ☐ Consider removing the dead shoonya-nse-indices function entirely if genuinely unused going forward.
  • Target: Backlog (low priority, prod-only cleanup) · Related Links: NFX-032 (where this was found).
  • Resolution Date: — · Verification: — · Last Updated: 2026-07-08
  • Remarks: Not actioned in this session — removing a production secret/function was outside this review's scope (parity verification + remediation of the Dev/UAT gap), and deserves its own deliberate, reviewed change rather than a drive-by deletion.

NFX-035

  • Date Reported: 2026-07-08 · Reported By: Discussion (spun out of NFX-032 at resolution — see that entry's Remarks)
  • Priority: Medium · Status: Open · Owner: User · Effort: S (credential values only, no code changes)
  • Feature · Sub-feature: Platform · Nefoxx-Dev — Cloudflare + Zoom secrets
  • Issue Type: Technical Debt · Domain(s): Deployment/operations, Media, Zoom Live Classes
  • Description: Nefoxx-Dev has no CLOUDFLARE_* or ZOOM_* Edge Function secrets set. Supabase never returns a secret's value once set (secrets list shows only a digest), so these cannot be copied programmatically from production — they need to be supplied fresh. Decisions already made (during NFX-032): Cloudflare secrets should match production (shared CF account, user's decision) — CLOUDFLARE_ACCOUNT_ID, CLOUDFLARE_IMAGES_API_TOKEN, CLOUDFLARE_R2_ACCESS_KEY_ID, CLOUDFLARE_R2_BUCKET_NAME, CLOUDFLARE_R2_SECRET_ACCESS_KEY, CLOUDFLARE_STREAM_API_TOKEN, CLOUDFLARE_STREAM_WEBHOOK_SECRET. Zoom secrets should be the dev Zoom OAuth app's own values (already referenced in .env.local as VITE_ZOOM_CLIENT_ID=PG4oXwaPSwgoIqUsTtcA) — ZOOM_CLIENT_SECRET, ZOOM_MEETING_SDK_KEY, ZOOM_MEETING_SDK_SECRET, ZOOM_OAUTH_STATE_SECRET, ZOOM_TOKEN_ENC_KEY, ZOOM_WEBHOOK_SECRET_TOKEN, ZOOM_REDIRECT_URI.
  • Impact: Media upload EFs (finfluencify-get-image-upload-url, finfluencify-get-video-upload-url, trade-planner-media-upload, etc.) and Zoom Live Classes EFs (finfluencify-zoom-connect/-disconnect/-webhook) will error on devv/uatt until set. Everything else (auth, trade planner CRUD, psychology/risk/session tools, market data reads) is unaffected.
  • Proposed Solution / Action Items: ☐ Create supabase/.dev-secrets.local (git-ignored, pattern already added to .gitignore) with KEY=value lines for the 7 Cloudflare + 7 Zoom keys above · ☐ Run supabase secrets set --env-file supabase/.dev-secrets.local --project-ref rchglrpywmxkcbmxcepl (or set individually via Dashboard → Nefoxx-Dev → Edge Functions → Secrets) · ☐ Verify via supabase secrets list --project-ref rchglrpywmxkcbmxcepl (names only) and a real upload/Zoom-connect test on devv.nefoxx.com.
  • Target: User will pick up if blocked by a related feature · Related Links: NFX-032 (source of this split); guides/environment-strategy.md §5 (promotion runbook); .env.example.
  • Resolution Date: — · Verification: — · Last Updated: 2026-07-08
  • Remarks: Deliberately left open and non-blocking per the user — not on the critical path for current work; to be resolved when/if a specific feature (media upload or Zoom Live Classes testing on dev) actually needs it.

NFX-036

  • Date Reported: 2026-07-08 · Reported By: Discussion (spun out of NFX-032 at resolution — see that entry's Remarks)
  • Priority: Medium · Status: Open · Owner: User · Effort: S (dashboard comparison, no code changes expected)
  • Feature · Sub-feature: Platform · Nefoxx-Dev — Auth config parity
  • Issue Type: Process Improvement · Domain(s): Auth, Security, Deployment/operations
  • Description: Site URL, redirect URL allow-list, OAuth provider config, JWT expiry, and email templates were not verified for parity between Nefoxx-Prod and Nefoxx-Dev during the NFX-032 audit — this config lives in Supabase's dashboard/Management-API layer, not in a queryable Postgres table, so the SQL-based audit method used for schema/EF/cron parity structurally can't reach it. Separately, an attempt to read it via the Supabase CLI's stored access token (to call the Management API directly) was blocked by the coding assistant's own sandbox as an unauthorized credential-access pattern.
  • Impact: Unknown until checked — could be full parity (most likely, since Nefoxx-Dev was provisioned as a replica) or could have gaps (e.g. redirect URLs that still point at the wrong domain, mismatched JWT expiry). NFX-031 (Google OAuth) is a known, already-tracked subset of this — Nefoxx-Dev has no Google provider configured at all yet. This item covers everything else in the same config surface.
  • Proposed Solution / Action Items: ☐ Compare Nefoxx-Prod vs Nefoxx-Dev in the Dashboard: Authentication → URL Configuration (Site URL, Redirect URLs) · ☐ Authentication → Providers (email settings, JWT expiry under Authentication → Sessions) · ☐ Authentication → Email Templates, if customized on prod · ☐ Document any intentional differences (e.g. redirect URLs necessarily differ per domain) directly in guides/environment-strategy.md §7 once checked, replacing this item's "unknown" status with a confirmed parity statement.
  • Target: User will pick up if blocked by a related feature · Related Links: NFX-032 (source of this split); NFX-031 (Google OAuth, a known subset); guides/environment-strategy.md §7 (honest gap disclosure, to be updated once resolved).
  • Resolution Date: — · Verification: — · Last Updated: 2026-07-08
  • Remarks: Deliberately left open and non-blocking per the user — not on the critical path for current work; to be resolved when/if a specific feature (e.g. auth/session testing on dev) actually surfaces a real discrepancy.

NFX-037

  • Date Reported: 2026-07-09 · Reported By: Testing (discovered while fixing test:ef's missing Deno permission flags for the backend-CI re-evaluation, NFX-027 Phase C)
  • Priority: Low · Severity: Minor · Status: Open · Owner: — · Effort: S
  • Feature · Sub-feature: Psychology Builder · psychology-builder-save-archetype (deriveArchetype)
  • Issue Type: Bug · Testing · Domain(s): Code quality, Testing
  • Description: deriveArchetype: high MA → adaptive_opportunist (psychology-save-archetype.test.ts:222) asserts { pa: 30, ro: 40, cd: 55, ma: 90, er: 50 } produces adaptive_opportunist; the function returns intuitive_pattern_trader. Traced to the documented weighted-scoring formula in helpers.ts:166-170, not a logic error in the function: with these exact inputs, adaptive_opportunist = ma×0.40 + cd×0.30 + ro×0.20 + er×0.10 = 65.5, while intuitive_pattern_trader = (100-pa)×0.35 + ma×0.35 + er×0.20 + cd×0.10 = 71.5intuitive_pattern_trader genuinely scores higher given the formula, because pa:30 isn't low enough to suppress its (100-pa) term. The sibling test two lines below (low PA + high MA → intuitive_pattern_trader, pa:15, ma:80) computes correctly (72.75 vs 57.5) under the identical formula — confirming the implementation is internally consistent; only this one fixture's expected label doesn't match what the documented weights actually produce for those specific inputs.
  • Impact: Low — an isolated test fixture, not a user-facing archetype-classification bug (nothing suggests real users are being misclassified; the formula behaves as documented). Currently causes npm run test:ef to report 1 failure (1804 passed otherwise, confirmed 2026-07-09) whenever run with --no-check, and blocks the new edge-functions CI job (NFX-027 Phase C, .github/workflows/backend-ci.yml) from being promoted from visibility-only to a required check (alongside NFX-004, the other current blocker).
  • Proposed Solution / Action Items: ☐ Decide intent: either raise the test fixture's pa value high enough that adaptive_opportunist actually wins under the current formula (since adaptive_opportunist's score doesn't depend on pa at all, any pa change only affects intuitive_pattern_trader's competing score) — e.g. pa: 80 keeps ma:90 "high MA" while no longer triggering intuitive_pattern_trader's low-PA bonus · or reconsider whether "high MA alone, regardless of PA" is actually a coherent test case for this weighting scheme, and rewrite/remove it if not.
  • Target: Backlog · Related Links: NFX-027 (Phase C, found during); NFX-004 (the other current Job-2 blocker in backend-ci.yml).
  • Resolution Date: — · Verification: — · Last Updated: 2026-07-09
  • Remarks: Not fixed in the same pass it was found — this is a test-fixture/design-intent question (which archetype should win for these inputs), not a mechanical bug fix, and deserves a deliberate decision rather than an assumption made mid-CI-plan-implementation.

NFX-038

  • Date Reported: 2026-07-09 · Reported By: Testing (found by the new PR-blocking a11y gate, NFX-029 Phase 2, first real run against /auth)
  • Priority: Medium · Severity: Serious (WCAG) · Status: Open · Owner: — · Effort: M
  • Feature · Sub-feature: Platform · Design system — color contrast
  • Issue Type: Bug · Accessibility · Domain(s): Accessibility, Design system, UI/UX
  • Description: @axe-core/playwright's color-contrast rule flags text-orange-500 (#f97316) on a white (#ffffff) background at a measured contrast ratio of 2.8:1 — WCAG 2 AA requires 4.5:1 for normal-weight text this size. On /auth this hits the Sign In/Sign Up tab triggers and the "Forgot Password?" link-button, but the same color pairing is the platform's light-theme brand-orange accent (niftytoolkit-uiux-theme-guidelines.md's "Primary brand: text-orange-600" — worth checking on the actual run/build whether orange-500 vs. the documented orange-600 is itself part of the gap, since orange-600 is measurably darker and may already close some of the distance to 4.5:1), so this is very likely reproducible across every light-theme page using it, not an /auth-specific issue.
  • Impact: Real WCAG 2 AA failure — low-vision users relying on standard contrast minimums cannot reliably read this text/these controls in light theme. Currently kept out of the new a11y PR gate's blocking scope (scoped to critical-impact only, specifically because of this finding) so standing up the gate didn't ship red on day one; the full sweep (all impact levels, once Phase 4 lands) will otherwise re-surface this on every page that uses the color.
  • Proposed Solution / Action Items: ☐ Audit every text-orange-500 (and confirm/deny orange-600) usage on a white/light background across the light theme · ☐ Either darken the token used against white backgrounds to a value that clears 4.5:1, or add a non-color affordance (underline, icon) to color-dependent controls · ☐ Re-run the a11y critical+serious sweep platform-wide once fixed and promote the PR-blocking gate's threshold back to critical+serious.
  • Target: Backlog · Related Links: NFX-029 (Phase 2, found during); guides/e2e-testing-strategy.md Governance section (documents the critical-only scoping decision this finding drove).
  • Resolution Date: — · Verification: — · Last Updated: 2026-07-09
  • Remarks: Not fixed in this pass — a design-system-wide color change is out of scope for standing up an E2E/a11y CI gate and needs its own deliberate review, not a reactive one-page patch.

NFX-039

  • Date Reported: 2026-07-09 · Reported By: Testing (incidental, verifying the new E2E market-mood smoke spec, NFX-029 Phase 2)
  • Priority: Low · Severity: Minor · Status: Open · Owner: — · Effort: S
  • Feature · Sub-feature: Market Mood · vw_momentum_leaders (database view)
  • Issue Type: Bug · Domain(s): Database, Market Mood
  • Description: A diagnostic network listener attached while building the market-mood E2E spec captured a 500 Internal Server Error on GET .../rest/v1/vw_momentum_leaders?select=* against the ephemeral stack's schema snapshot. Not part of the Market Overview page's own call graph (the smoke spec's actual assertion — "no 5xx from calls this page makes" — passed; this fired from something else active in the same browser session at the time) — root cause on the view itself not yet investigated.
  • Impact: Unknown severity until investigated — could be schema-snapshot-only (a dump/extension gap specific to supabase/schema.sql, not present against a real project) or a genuine defect reachable in Dev/Prod too. Not blocking any shipped E2E spec today.
  • Proposed Solution / Action Items: ☐ Reproduce directly (select * from vw_momentum_leaders limit 1) against both the ephemeral stack and Nefoxx-Dev to determine if this is snapshot-specific or real · ☐ If real, root-cause the view definition; if snapshot-specific, note the gap in e2e-testing-strategy.md's schema-snapshot section.
  • Target: Backlog · Related Links: NFX-029 (Phase 2, found during).
  • Resolution Date: — · Verification: — · Last Updated: 2026-07-09
  • Remarks: Logged for visibility per the tracker's "no known issue goes untracked" rule — genuinely not yet triaged past the raw 500 observation.

NFX-040

  • Date Reported: 2026-07-09 · Reported By: Testing (writing the E2E trade-planner share-journey spec, NFX-029 Phase 2)
  • Priority: High · Severity: Public share feature effectively broken for anonymous visitors · Status: Resolved (same pass) · Owner: — · Effort: S
  • Feature · Sub-feature: Trade Planner · Public share links (/shared/plan/:token)
  • Issue Type: Bug · Domain(s): Reliability, UI/UX, Accessibility (auth gating)
  • Description: src/components/routes/ProtectedRoute.jsx's publicPaths allowlist (routes that render with zero auth enforcement) listed /auth, /trading-insights, /calcify, /verify — but not /shared/plan. SharedPlanPage.jsx itself correctly handles the "must sign in" case for private shares (its own "Sign In Required" state), but ProtectedRouteWrapper's independent Tier-3 logic doesn't know this route is public: for public shares (no auth required by design), an anonymous visitor would see the real plan content render correctly, then — 5 seconds later — a non-dismissible AuthModal (onEscapeKeyDown/onInteractOutside both suppressed) would pop up over it, prompting sign in for a page that was never supposed to require it. Found because the E2E share spec deliberately opens the share link in a genuinely separate browser.newContext() (a new tab in the same context would still carry the authenticated session and never trigger this path) — a real anonymous-visitor simulation, not a UI convenience shortcut.
  • Impact: Every anonymous visitor to a public trade-plan share link (the entire point of the "Public" share type) got an unwanted, blocking-style sign-in prompt shortly after the page loaded — directly undermines the feature's stated purpose (frictionless public sharing).
  • Proposed Solution / Action Items: ☑ Add /shared/plan to ProtectedRoute.jsx's publicPaths.
  • Target: Done · Related Links: NFX-029 (Phase 2, found during); Trade Planner feature CLAUDE.md (Sharing System, Phase 5).
  • Resolution Date: 2026-07-09 · Verification: E2E share-journey spec (e2e/smoke/trade-planner/share.spec.js) opens the share URL in a fresh browser.newContext() and asserts the plan content renders with no auth-modal interference; passed after the fix (failed with a 30s timeout on the modal covering the content before the fix).
  • Remarks: A one-line fix once found, but the finding only happened because the E2E spec modeled a real anonymous visitor correctly (separate browser context) rather than a same-session new tab — worth keeping as the standard pattern for any future "what does a logged-out user see" spec.

NFX-041

  • Date Reported: 2026-07-09 · Reported By: Testing (the new PR-blocking a11y gate, NFX-029 Phase 2, first real run against /trade-planner)
  • Priority: Medium · Severity: Critical (WCAG) · Status: Resolved (same pass) · Owner: — · Effort: S
  • Feature · Sub-feature: Platform · Global header — src/components/header/NavItem.jsx
  • Issue Type: Bug · Accessibility · Domain(s): Accessibility, UI/UX
  • Description: axe-core's aria-allowed-attr rule (critical) flagged <div type="button" aria-haspopup="menu" aria-expanded="false" ...> for every dropdown-style nav item (Market Pulse, Options, Edge Builder, FinFluencify — any item with dropdownType set). Root cause: Radix's <DropdownMenuTrigger asChild> clones its ARIA/interaction props onto its immediate child. That immediate child was <motion.div variants={navItemVariants}>, with the real <Button> nested one level inside it — so Radix cloned aria-haspopup/aria-expanded/type="button" onto the motion.div (a generic, non-interactive element with no role that supports those attributes) instead of onto the actual button. aria-expanded on an element with no implicit/explicit role that supports it is exactly what aria-allowed-attr exists to catch — a screen reader has no reliable way to announce the menu's open/closed state.
  • Impact: Every dropdown nav item, on every page (this is the global header), was semantically announced incorrectly to assistive technology — the expand/collapse state lived on the wrong element.
  • Proposed Solution / Action Items: ☑ Moved the motion.div variants={navItemVariants} wrapper to sit outside <DropdownMenu> instead of inside <DropdownMenuTrigger asChild>, so asChild clones onto <Button> directly. Framer Motion variants still propagate correctly to a motion.* descendant from an ancestor animate/whileHover trigger regardless of exact nesting depth, so the hover animation is visually unchanged — confirmed via npx eslint (no new errors) and the a11y spec re-run (fix removed the aria-allowed-attr violation entirely, 0 critical remaining on /trade-planner).
  • Target: Done · Related Links: NFX-029 (Phase 2, found during).
  • Resolution Date: 2026-07-09 · Verification: e2e/a11y/trade-planner.spec.js — failed with the aria-allowed-attr violation before the fix, passed (zero critical violations) after.
  • Remarks: Same lesson as NFX-040: this bug existed on every page with the global header and would have gone unnoticed indefinitely without a real axe scan in CI — exactly the class of defect this phase of work exists to surface. A second, unrelated button-name violation (month-heatmap prev/next arrow buttons on /trade-planner, TradePlannerPage.jsx) surfaced on the very next scan once this one was fixed — also fixed same pass (aria-label="Previous month"/"Next month"), tracked under this item rather than a separate ID since it's the same rule/pattern found by the same gate in the same pass.

NFX-043

  • Date Reported: 2026-07-09 · Reported By: Testing (building the Phase 3 deploy-smoke mutation guard fixture, NFX-029)
  • Priority: High · Severity: Absolute hard-guardrail violation, platform-wide (every page load) · Status: Resolved (same pass, user confirmed "fix it now") · Owner: — · Effort: S
  • Feature · Sub-feature: Platform · src/contexts/FeatureGateContext.jsx
  • Issue Type: Bug · Security · Domain(s): Security, Architecture, Compliance
  • Description: fetchFeatureFlags() called supabase.from('feature_flags').select('feature_key, is_enabled') directly — a standalone violation of CLAUDE.md's hard guardrail #2 ("No supabase.from() anywhere in src/ — absolute prohibition, no exceptions"). FeatureGateContext/useFeatureGate() is a CLAUDE.md-documented core file that wraps the app broadly, so this fired on effectively every page load, exposing the raw table name (/rest/v1/feature_flags) in the Network tab instead of an RPC/EF name — exactly the exposure the RPC-only architecture exists to prevent. Found because the new deploy-smoke mutation guard (e2e/smoke/deploy/fixtures.js) treats any raw /rest/v1/<table> call as deny-by-default (it doesn't distinguish "accidental .from()" from "a genuine unsafe write" — both are exactly what the guard exists to catch), which would have made the very first deploy-smoke spec red for a reason unrelated to the actual deploy.
  • Impact: Low practical severity (feature_flags isn't sensitive data, and the code already degrades gracefully — catch defaults all flags to disabled on any fetch failure) but a real, unambiguous violation of an absolute architectural rule, on every single page load, for however long it had existed.
  • Proposed Solution / Action Items: ☑ New migration 20260709110955_get_feature_flags_rpc.sqlget_feature_flags(), SECURITY DEFINER, SET search_path = public, RETURNS TABLE(feature_key text, is_enabled boolean), granted to both anon and authenticated (matching feature_flags' existing "Allow public read-only access" RLS policy — the RPC preserves the exact same public-read behavior, just through the RPC-only client contract) · ☑ FeatureGateContext.jsx swapped to supabase.rpc('get_feature_flags') · ☑ Applied to both Nefoxx-Dev and Nefoxx-Prod (linked, pushed, relinked back to Dev) per the mandatory two-environment promotion rule — not just committed code.
  • Target: Done · Related Links: NFX-029 (Phase 3, found during); CLAUDE.md Database Access Strategy (the guardrail this violated).
  • Resolution Date: 2026-07-09 · Verification: SELECT * FROM public.get_feature_flags(); run directly against both projects post-migration — Dev returns 0 rows (empty table, expected), Prod returns 2 real rows (quick_access_controls, finfluencify_live_classes, both enabled); grants confirmed (anon/authenticated/service_role/postgres all have EXECUTE) on both; full Vitest suite green afterward (existing tests mock the whole useFeatureGate() hook, not the underlying .from()/.rpc() call, so none needed updating); npx eslint clean.
  • Remarks: A concrete example of what NFX-029's remark predicted: standing up real E2E/deploy-safety tooling finds real bugs the absence of that tooling was hiding, this time a genuine security-relevant compliance gap rather than a UI bug.

NFX-042

  • Date Reported: 2026-07-09 · Reported By: Discussion (user, asking why only 3 features got PR-blocking E2E coverage in Phase 2)
  • Priority: Medium · Status: Open · Owner: — · Effort: L (mirrors Phase 2's own effort, per additional feature covered)
  • Feature · Sub-feature: Platform · Playwright E2E testing layer — journey breadth
  • Issue Type: Enhancement · Testing · Domain(s): Testing, Quality, CI/CD
  • Description: Phase 2 (NFX-029) deliberately scoped its PR-blocking journey set to 5 journeys across 3 features — auth (gate), Trade Planner (write-path/EF-heavy, historical incident precedent), Market Mood (canonical RPC/read-path reference) — chosen to cover both of the platform's fundamental data-access patterns (RPC read vs. EF write) plus the auth boundary, not because other features are less important. Every other feature with real user-facing write flows or complex client logic — Psychology Builder, Risk Radar, Session Review, Habit Tracker, Trade Journal, Finfluencify (courses, live classes, Zoom), admin (users, content, app-controls, edge-functions, db-management, certificate templates, commissions), OI Pulse/Index Radar, and the calculator suite — currently has zero browser-level E2E coverage. Vitest's 4-layer model covers each of these per-feature already; what's missing is the browser/bundle/network-level class of bug Vitest structurally cannot catch (see NFX-029's "Why this exists"), for everything outside the 3 features above.
  • Impact: A regression class identical to the RiEdit3Line incident (298/298 unit tests green, production broken) remains possible, undetected until manual QA or a user report, on every feature outside the current blocking set. Not urgent today (this is the same risk profile the platform has always run under, now measurably reduced for 3 features instead of zero) but should not be left open-ended indefinitely.
  • Proposed Solution / Action Items: ☐ When Phase 4 (regression/visual/cross-browser/mobile, nightly, non-blocking → blocking after 10 green runs) is scoped, build out journeys for the features listed above, prioritized by write-path complexity and blast radius (Psychology Builder and Finfluencify Zoom Live Classes are the next-most EF/state-machine-heavy after Trade Planner) · ☐ Revisit whether any of these should be promoted into the PR-blocking set (not just nightly) if a regression in one of them reaches production before Phase 4 ships — that would be the concrete trigger to re-prioritize this item ahead of its current placement.
  • Target: Phase 4 · Related Links: NFX-029 (parent initiative, Phase 2 scope decision); guides/e2e-testing-strategy.md (Phase 4 row, full phased rollout table).
  • Resolution Date: — · Verification: — · Last Updated: 2026-07-09
  • Remarks: Logged at the user's explicit request to keep this open and revisit later rather than either expanding Phase 2's blocking scope now (a real PR-gate-speed/coverage tradeoff, not a free addition) or letting the gap go untracked.

NFX-044

  • Date Reported: 2026-07-09 · Reported By: Testing (full-tree grep prompted by fixing NFX-043, to confirm the deploy-smoke test pages wouldn't hit another undiscovered instance)
  • Priority: High · Severity: Absolute hard-guardrail violation, widespread · Status: Open · Owner: — · Effort: XL (spans many features; not a single fix)
  • Feature · Sub-feature: Platform · supabase.from() direct table access across ~25 files
  • Issue Type: Bug · Technical Debt · Security · Domain(s): Security, Architecture, Compliance, Code quality
  • Description: NFX-043 was fixed as a single, isolated instance before a full-tree check was run. grep -rn "supabase\s*\.\s*from(" src/ found ~45 more call sites across ~25 files, confirming this is a widespread, pre-existing gap, not a one-off. Rough split (exact count/line-by-line audit still needed — see Action Items):
    • Read-only (candidate get_* RPCs, lower effort per site): index_expiry_map lookups repeated across 7 option-strategy files (StraddleStrategy.jsx, useMultiStrikeDataFetching.js, useMultiStrikeStrangleDataFetching.js, useStrangleDataFetching.js, useCallVsPutData.js, useOIAnalysisData.js, useOptionChainData.js — likely collapsible into one shared RPC, not 7); useMostActiveEquitiesData.js (3 materialized views); screener view reads (Nifty500ScreenerPage.jsx, ScreenerTabContent.jsx — the latter takes a dynamic view name, supabase.from(viewName), needing more care than a 1:1 RPC swap); several admin ad-management Tab components' initial-load SELECTs.
    • Write (each needs a genuinely new Edge Function, not just a query swap): Community (CommentSection.jsx, CommunitySidebar.jsx, useCommunityData.js — post likes/follows/bookmarks/ posts, both insert and delete); Trade Journal (TradeJournal.jsx — full CRUD); Screeners (ScreenersPage.jsx — favorites CRUD); Watchlist (WatchlistSidebar.jsx — delete); Sticky Notes (StickyNotePad.jsx — full CRUD); Goal Forge (GoalForge.jsx — delete); Messages (MessagesPage.jsx — insert); admin content (useGuideEditor.js — update/insert); admin ad-management (8 components: AdFormModal, AdsTab, PlacementFormModal, PlacementsTab, RuleFormModal, RulesTab, UserRoleFormModal, UserRolesTab — the single largest concentration, all CRUD); admin commission (AdminCommissionPage.jsx — bracket CRUD); Finfluencify Students (AddStudentModal.jsx, Students.jsx — insert/update).
  • Impact: Same class of exposure as NFX-043 (raw table names in the Network tab instead of RPC/EF names) but at a scale that represents a real, long-standing architectural drift from the documented RPC/EF-only contract — not a one-off oversight. Admin ad-management in particular is the densest cluster and touches revenue-adjacent data (ads, placements, special-user overrides).
  • Proposed Solution / Action Items: ☐ Produce a complete, line-by-line audit (this entry's file list is from one grep pass, not a verified exhaustive count) · ☐ Triage each site read vs. write, and within reads, look for consolidation opportunities before writing 1:1 RPCs (the 7-file index_expiry_map duplication is the clearest example — one shared RPC likely replaces all 7) · ☐ For writes, design + build + test (full EF test suite per CLAUDE.md's mandatory gate) one Edge Function per logical write operation, prioritizing by blast radius — admin ad-management and commission first (most concentrated, most business-sensitive), community/screeners/watchlist/sticky-notes next · ☐ Sequence as its own planned initiative (not a side-fix), likely feature-by-feature, each landing with its own PR, tests, and both-environment migration promotion.
  • Target: Backlog · Related Links: NFX-043 (the single-instance fix that prompted this discovery); CLAUDE.md Database Access Strategy (the guardrail this violates, and the RPC-vs-EF decision rule to apply during triage).
  • Resolution Date: — · Verification: — · Last Updated: 2026-07-09
  • Remarks: Logged at the user's explicit direction — catalogue now, scope and fix later as a deliberate initiative, not folded into Phase 3's deploy-smoke work. The file list above is a first pass, not a final audit; treat it as a starting point for the line-by-line pass in the action items, not as authoritative.

Detail template

Copy this block when adding a new item (allocate the next NFX-###, add a matching row to the table above):

md
### NFX-XXX
- **Date Reported:** YYYY-MM-DD · **Reported By:** User | Developer | Code Review | Testing | Monitoring | Discussion
- **Priority:** Critical|High|Medium|Low · **Severity:** (bugs) · **Status:** Open · **Owner:** — · **Effort:** S|M|L
- **Feature · Sub-feature:** … · …
- **Issue Type:** … · **Domain(s):**
- **Description:**
- **Impact:**
- **Proposed Solution / Action Items:** ☐ … ☐ …
- **Target:** Backlog · **Related Links:**
- **Resolution Date:** — · **Verification:** — · **Last Updated:** YYYY-MM-DD
- **Remarks:**