Appearance
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
| ID | Priority | Type | Feature · Sub-feature | Summary | Status | Target | Updated |
|---|---|---|---|---|---|---|---|
| NFX-007 | High | Bug | Zoom Live Classes · embedded host-start | Host-start ZAK fetch returns 400 in the embedded flow | Blocked | — | 2026-07-04 |
| NFX-005 | High | Technical Debt · Testing | Platform / EF · multiple | 26 Edge Functions deployed without co-located tests | Open | Backlog | 2026-07-04 |
| NFX-004 | Medium | Bug · Technical Debt | Platform / EF · fetch-*-contributors | NseStockItem 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 blocker | Open | Backlog | 2026-07-09 |
| NFX-006 | Medium | Process Improvement | Platform / EF · test tooling | npm run test:ef type-checks the whole dir, so one EF's error fails the entire run | Open | Backlog | 2026-07-04 |
| NFX-008 | High | Performance | Zoom Live Classes · LiveClassRoom | 5.6 MB Zoom SDK bundle -- Zoom officially provides a CDN alternative, verified | Open | Backlog | 2026-07-05 |
| NFX-009 | High | Bug | Market Mood / Index Radar / Settings · imports | 7 imports resolve to files that don't exist on disk | Open | Backlog | 2026-07-05 |
| NFX-012 | Low | Bug · Testing | Trade Planner / Session Review · tests | 2 tests reference service exports that don't exist (deletePlan, deleteSessionReview) | Open | Backlog | 2026-07-05 |
| NFX-013 | High | Technical Debt | Platform · repo/.gitignore | .env.local + supabase/.temp/ untracked and repointed per-environment; git-history scrub deliberately deferred (no sensitive values were ever committed) | Partially Resolved | Done (untrack) | 2026-07-08 |
| NFX-019 | High | Technical Debt · Testing | Platform · test coverage | Real coverage (~17%/30%/17%/51%) is far below the documented 70/80/65/70 target | Open | Backlog | 2026-07-05 |
| NFX-020 | Low | Bug | Platform · vitest/@vitest/coverage-v8 (local, Windows) | Full-suite npm run test:coverage crashes entirely on this dev machine (100/100 files fail to collect) | Open | Backlog | 2026-07-05 |
| NFX-021 | Medium | Technical Debt | Platform · SonarQube code quality (whole codebase) | Real baseline: 80 bugs, 0 vulnerabilities, 12792 code smells — addressed feature-by-feature going forward | Open | Backlog | 2026-07-05 |
| NFX-023 | High | Enhancement · Architecture | Platform · Documentation infrastructure (3 portals) | Add admin/ops + end-user help center portals alongside the dev portal, each its own deploy — not bundled into the app | Open | Backlog | 2026-07-07 |
| NFX-026 | Medium | Process Improvement | Platform · Repo governance (GitHub Settings) | Dependabot, code scanning, and branch protection are GitHub Settings toggles — not executable from the repo/CLI | Open | Backlog | 2026-07-07 |
| NFX-027 | High | Enhancement · Architecture | Platform · Backend CI/CD + environment isolation | Nefoxx-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 open | In Progress | Current | 2026-07-09 |
| NFX-028 | High | Security · Technical Debt | Platform · Dependencies (npm root + portal) | Dependabot reports 59 vulnerabilities (3 critical, 18 high) across dependencies; needs triage — runtime-exposed first | Open | Backlog | 2026-07-07 |
| NFX-029 | High | Enhancement · Testing | Platform · Playwright E2E testing layer | Add 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 remain | In Progress | Current | 2026-07-09 |
| NFX-030 | High | Bug · Technical Debt | Platform · 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 drift | Resolved | Done | 2026-07-08 |
| NFX-031 | Medium | Process Improvement | Platform · Nefoxx-Dev — Google OAuth (Auth provider config) | Nefoxx-Dev has no Google OAuth app of its own yet — dashboard/console-only, no code changes needed | Open | Backlog | 2026-07-08 |
| NFX-033 | Medium | Technical Debt · Process Improvement | Platform · Supabase — cron jobs and storage buckets not version-controlled | 21 of production's 26 cron jobs and all 5 storage buckets exist only as live database state, never captured in any migration | Open | Backlog | 2026-07-09 |
| NFX-034 | Low | Technical Debt | Platform · Supabase — stale Shoonya broker secrets | SHOONYA_API_* + INSTRUMENT_SYMBOL confirmed unused in production (sole consumer isn't cron-scheduled); recommend removal | Open | Backlog | 2026-07-08 |
| NFX-035 | Medium | Technical Debt | Platform · Nefoxx-Dev — Cloudflare + Zoom secrets | Cloudflare (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 set | Open | User will pick up if blocked | 2026-07-08 |
| NFX-036 | Medium | Process Improvement | Platform · Nefoxx-Dev — Auth config parity | Site URL, redirect URLs, OAuth provider config not verified in parity between Nefoxx-Prod and Nefoxx-Dev — not queryable via SQL, dashboard-only check | Open | User will pick up if blocked | 2026-07-08 |
| NFX-037 | Low | Bug · Testing | Psychology 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-caused | Open | Backlog | 2026-07-09 |
| NFX-038 | Medium | Bug · Accessibility | Platform · 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 page | Open | Backlog | 2026-07-09 |
| NFX-039 | Low | Bug | Market 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 path | Open | Backlog | 2026-07-09 |
| NFX-042 | Medium | Enhancement · Testing | Platform · Playwright E2E — Phase 2 blocking journey coverage | Phase 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) | Open | Phase 4 | 2026-07-09 |
| NFX-044 | High | Bug · Technical Debt · Security | Platform · supabase.from() used directly across ~25 files | Full-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 Function | Open | Backlog | 2026-07-09 |
| NFX-045 | Critical | Bug · Security | Platform · devv.nefoxx.com / uatt.nefoxx.com — frontend Supabase client wiring | Missing/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 in | Open | After Phase 3 (NFX-029) | 2026-07-09 |
Resolved / Closed
| ID | Priority | Type | Feature · Sub-feature | Summary | Status | Resolved | Updated |
|---|---|---|---|---|---|---|---|
| NFX-001 | Critical | Bug | Psychology Builder · compute-behavioral-signals | ReferenceError crash for any user with ≥7 check-ins | Resolved | 2026-07-04 | 2026-07-04 |
| NFX-002 | Medium | Technical Debt | Platform / EF · _shared/crypto.ts | BufferSource typing failed deno check on every token-encrypting EF | Resolved | 2026-07-04 | 2026-07-04 |
| NFX-003 | Low | Technical Debt · Testing | Trade Planner · trade-planner-share (test) | Dead 'public' === 'private' comparison (TS2367 code smell) | Resolved | 2026-07-04 | 2026-07-04 |
| NFX-010 | Medium | Technical Debt | Settings · pages/SettingsPage.jsx | Leftover legacy component body duplicates the tiers re-export's default export | Resolved | 2026-07-05 | 2026-07-05 |
| NFX-011 | Low | Technical Debt | Finfluencify · delete-bunnyService.js | Tombstone file (marked for full removal) has an orphaned syntax fragment, fails to parse | Resolved | 2026-07-05 | 2026-07-05 |
| NFX-014 | Low | Bug · Testing | Onboarding · OnboardingPage.test.jsx | Test asserted a hardcoded niftytoolkit.com domain the rename to nefoxx.com left stale | Resolved | 2026-07-05 | 2026-07-05 |
| NFX-015 | Medium | Bug | Platform · eslint-plugin-sonarjs (CI/hook tooling) | no-skipped-tests crashes lint on Windows when drive-letter casing differs between file path and cwd | Resolved | 2026-07-05 | 2026-07-05 |
| NFX-016 | Medium | Technical Debt | Platform · eslint.config.mjs scope | Root (React) ESLint config was linting documentations/portal (separate Vue/VitePress sub-project) | Resolved | 2026-07-05 | 2026-07-05 |
| NFX-017 | Medium | Bug | Finfluencify · LinkInBio (editor, claim modal, hooks, payouts) | 10 client-side occurrences of the retired niftytoolkit.com domain — feature not yet live, no real-user impact | Resolved | 2026-07-05 | 2026-07-05 |
| NFX-018 | Medium | Bug | Zoom Live Classes · LiveSessionList.jsx | scrollIntoView not implemented in jsdom — missing test-env stub, not a component bug; actually failed CI | Resolved | 2026-07-05 | 2026-07-05 |
| NFX-024 | Medium | Process Improvement | Platform · .github/workflows/ci.yml | Every fast-forward of main after a develop push doubled CI minutes for zero benefit | Resolved | 2026-07-07 | 2026-07-07 |
| NFX-022 | Medium | Bug | Platform · dev portal (VitePress) docs | Literal GitHub Actions mustache syntax in inline code broke Vue template compile, blanking the page | Resolved | 2026-07-07 | 2026-07-07 |
| NFX-025 | High | Process Improvement | Platform · CI/CD (whole pipeline) | No automated lint/test/build/deploy pipeline existed — GitHub Actions + Cloudflare Pages now covers dev/UAT/production | Resolved | 2026-07-07 | 2026-07-07 |
| NFX-032 | Critical | Bug · Technical Debt | Platform · Nefoxx-Dev — Edge Functions / cron parity | Independent 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 day | Resolved | 2026-07-08 | 2026-07-08 |
| NFX-040 | High | Bug | Trade 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 pass | Resolved | 2026-07-09 | 2026-07-09 |
| NFX-041 | Medium | Bug · Accessibility | Platform · 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 pass | Resolved | 2026-07-09 | 2026-07-09 |
| NFX-043 | High | Bug · Security | Platform · FeatureGateContext.jsx — direct supabase.from() call | Absolute 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 pass | Resolved | 2026-07-09 | 2026-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:
generateInsightsreferencedsessionReviewEntries(lines 418/449) but the identifier was never added to the input destructuring, so it was an undeclared name →ReferenceErrorat runtime. - Impact: Any user with
checkinCount ≥ 7crashed insight generation; the Session Review insights (milestone/growth/warning) never fired. Live production defect from an untested deploy. - Proposed Solution / Action Items: ☑ Add
sessionReviewEntriesto the destructuring · ☑ fix twoas X→as unknown as Xcasts (DivergenceResult,InsightRow) · ☑ add regression tests. - Target: Immediate · Related Links:
psychology-compute-behavioral-signals; memoryedge-functions-untested - Resolution Date: 2026-07-04 · Verification:
deno test27 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/TSUint8Array<ArrayBufferLike>vsBufferSourcestrictness (ArrayBufferLikemay beSharedArrayBuffer). - Impact: Failed
deno checktransitively on every EF importingencryptToken(Zoom connect, live-session-save, …) and broke the whole-dirdeno testrun. Type-only; runtime unaffected. - Proposed Solution / Action Items: ☑ Cast
rawKey as BufferSourceat 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 checkclean onfinfluencify-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: stringvariable so the branch is genuinely exercised. - Target: Immediate · Related Links:
trade-planner-share - Resolution Date: 2026-07-04 · Verification:
deno test59 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-*-contributorsfamily (NseStockItemtype) - Issue Type: Bug · Technical Debt · Domain(s): Code quality, Reliability, Testing
- Description:
NseStockItemhas duplicate/conflictingindustry+companyNameproperty declarations (string | null | undefinedvsstring | 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 testhard-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'sedge-functionsjob (NFX-027 Phase C) from visibility-only to a required check, alongside NFX-037. - Proposed Solution / Action Items: ☐ Locate the duplicate declaration(s); unify
NseStockItemto a single consistent shape (likelystring | 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 memoryedge-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:efintotest: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_failedresponse body · ☐ verify theuser:read:zakscope + 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 fromnode_modules/@zoom/meetingsdkto 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"inpackage.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 buildpays 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/meetingsdknpm import inLiveClassRoom.jsxwith 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 intopatchJsMedia: truefor automatic hotfixes (trades reproducibility for auto-patching -- do not enable without a deliberate reason) · ☐ weigh CSP implications (allow-listingsource.zoom.usinContent-Security-Policy) and offline/reliability trade-offs (CDN adds an external runtime dependency the current bundled approach doesn't have) · ☐ remove@zoom/meetingsdkfrompackage.jsononce 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 outeslint-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/useIndexRadarDataand@/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.mjssonarjs/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 ownexport 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 lintclean; fullnpm run testrun 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/*.jsxre-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 sameconstnames 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 lintclean; fullnpm run testrun 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.jsimportsdeletePlanandsession-review/tests/services/sessionReviewService.test.jsimportsdeleteSessionReviewfrom their respective service modules — neither export exists.tradePlannerService.jsexplicitly 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.jsno-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
developbranch / 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.localandsupabase/.temp/*were both tracked in git (confirmed viagit ls-files) — committed in history and pushed toorigin..gitignorenever excluded either path. Values confirmed present were allVITE_-prefixed and safe-by-design (anon key, public Cloudflare delivery hashes, OAuth client id) — noservice_rolekey 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.localandgit rm -r --cached supabase/.temp· ☑ both added to.gitignore· ☑.env.localrepointed to Nefoxx-Dev as the new local-dev default (was hardcoded to prod) · ☑.env.exampleadded, 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 statusconfirms both paths no longer tracked;deploy.ymlnow 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 testrun, 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.jsxline 2401) builds the preview fromwindow.location.hostdynamically — it never hardcodes a domain.git log -SonOnboardingPage.jsxfound the real history: the component used to hardcodeniftytoolkit.comtoo, and was deliberately fixed to usewindow.location.hostinstead (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 confirmedwindow.location.hostin this vitest/jsdom setup is"localhost:3000", not any hardcoded domain. - Impact: 1 of 1352 tests failed on a clean
npm run testrun. 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.hostdirectly (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 ofOnboardingPage.jsx'sprofileUrl. - Resolution Date: 2026-07-05 · Verification:
npx vitest runon 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.hostfixOnboardingPage.jsxalready 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 computedtopDir(derived from cwd). On Windows,process.cwd()returnedD:\...(uppercase) while the hook passed the file path asd:\...(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-reponpm run lint(eslint .) doesn't hit this code path. - Impact: Crashed the PostToolUse lint hook (exit 2, no useful output) on every
.js/.jsxedit 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 invokingeslint, 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.mjsscope - 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 ownpackage.json/node_modules. Locally this never surfaced becausedocumentations/portal/node_modulesalready existed from priornpm run docs:devusage; the fresh GitHub Actions runner only ran the repo-rootnpm ci, sodocumentations/portal/docs/.vitepress/theme/index.js'simport '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
@→./srcalias) were never meaningful for a Vue-based doc site regardless of the missing dependency. - Proposed Solution / Action Items: ☑ Excluded
documentations/portal/**entirely from the rooteslint.config.mjsscope (superseding the narrower pre-existing.vitepress/cache/**/dist/**entries). - Target: Immediate (blocking Phase 2 CI) · Related Links:
.github/workflows/ci.ymlfirst run, 2026-07-05;documentations/portal/package.json. - Resolution Date: 2026-07-05 · Verification:
npm run lintlocally, then confirmed no otherdocumentations/portal/**/*.jsfiles 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.comdomain, found while investigating NFX-014. UnlikeOnboardingPage.jsx(which already correctly useswindow.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(supportmailto: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 towindow.location.host, mirroring the already-established, already-tested pattern inSharePanel.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 literalnefoxx.com. ☑ LeftIdentityRootRedirect.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 lintclean; fullnpm run testrun — 100/100 files, 1352/1352 tests passed. - Last Updated: 2026-07-05 · Remarks: Deliberately left untouched: internal
localStoragekeys (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.mdspec/README files (static docs, not runtime code).
NFX-018
- Date Reported: 2026-07-05 · Reported By: Testing (full
npm run testrun, 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 arequestAnimationFramecallback). Root cause: jsdom implements no layout/rendering, soElement.prototype.scrollIntoViewdoesn'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; withoutpipefail, the reported exit code wastail'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
scrollIntoViewstub tosrc/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 push1a5dc72. - 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'scoverage.thresholds(lines 70%, functions 80%, branches 65%, statements 70%) matchCLAUDE.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 locallynpm run test:coverageis rarely run day-to-day (developers usenpm 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: truein.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.jscoverage.thresholds;CLAUDE.mdTesting 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:coveragelocally 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
--coveragelocally 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 involvingHubSharePanel/MediaUploadSection), despitenpm 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/ lowermaxWorkers, 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-scanCI run, #10, push068c7e5) - 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-securityESLint 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 intosonar-baseline.jsonas the CI gate's baseline (see.github/workflows/ci.yml'ssonar-scanjob) — 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/developvia thesonar-scanjob — 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 aroundgithub.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 inv-preand safe, but inline code spans are not. Vue's template compiler tried to evaluate that mustache syntax as a live interpolation referencing an undefinedgithubobject, 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
yamlblock was already safe and left unchanged) ☑ Verified with a full localvitepress 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 docscompleted 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/orsrc/tiers/public/must clear this codebase's full non-negotiable engineering bar perCLAUDE.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 throughci.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 · ☐ Extenddeploy.yml's existing reusableworkflow_callpattern 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'sci.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.ymlreusable 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
developwas immediately fast-forwarded ontomainas well (git push origin develop:main) to keep the two in sync. Sinceci.ymltriggers onpushto 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. Themain-triggered run'sdeploy-devjob correctly skipped (branch guard), but the two most expensive jobs still ran twice. The habit started for a real reason early on —workflow_dispatchworkflows must exist on the default branch to be dispatchable, which genuinely required fast-forwardingmainonce — but continuing it after every subsequent fix was unnecessary:verify-ciindeploy-prod.yml/deploy-uat.ymlchecks GitHub's check-runs API by commit SHA, not by branch, so thedeveloprun 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
developcommit ontomain—mainnow only advances at a deliberate release/promotion point, not after every incremental fix · ☑ Add aconcurrencygroup toci.yml, keyed on the triggering ref withcancel-in-progressenabled, 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, seeguides/git-setup.md),mainwill only move via merged PRs fromdevelopat 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.ymlvalidated withjs-yamlafter the edit; behavior change (no more main-mirroring) is procedural, confirmed going forward by not fast-forwardingmainfor 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_dispatchdiscoverability) 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 manualnpm run build+ hand-upload ofdist/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-securityadded toeslint.config.mjs· ☑ci.yml'sbuild-and-testjob: lint → test (hard gate) → test summary → coverage (non-blocking, NFX-019) → build · ☑sonar-scanjob: ephemeralsonarqube:communityservice container, fresh per-run token, baseline-gated viasonar-baseline.json(NFX-021) · ☑deploy.ymlreusable workflow (dev auto-deploy inci.yml; UAT and production as separateworkflow_dispatchworkflows with independent SHA-basedverify-cichecks) · ☑ 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
ghCLI-executable in this environment (noghinstalled, 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/develop— the 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
mainanddeveloprequiring a pull request before merging and requiring theLint, Test, BuildandSonarQube Scan (baseline gate)status checks to pass · ☐ Once branch protection is on, update local habits per Git Setup & Workflow —mainadvances via merged PR, notgit push origin develop:main. - Target: Backlog (next available session with dashboard access) · Related Links:
guides/sonarqube-integration.mditems 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 touchingsupabase/are now validated bybackend-ci.yml(migration replay + pgTAP, EF tests/type-check). Backend deploys themselves (migrations, Edge Functions) remain manualsupabase db push/functions deploywith 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/uattcan no longer write to live prod. Remaining gap: backend deploys still have no automated CI gate, so a bad manualdb pushcan still hit prod directly. - Done (2026-07-08): ☑ Nefoxx-Dev provisioned — Free tier, separate org (
iepflzeiwckmdrrbehuz),ap-south-1(matches prod), refrchglrpywmxkcbmxcepl· ☑ 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 E2Eseed.sql(trader/admin/target,*.localemails) 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.localuntracked (git rm --cached), repointed to Nefoxx-Dev as the new local-dev default,.env.exampleadded · ☑ Per-environment frontend wiring:deploy.yml's Build step now injectsVITE_SUPABASE_URL/VITE_SUPABASE_ANON_KEY/VITE_SUPABASE_URL_FALLBACKfrom 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.localstopped 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 "zeronet.http_post/external-call risk found anywhere," based solely on grepping migration files. A liveselect * from cron.jobagainst prod (not just its migrations) found 26 real jobs, 21 of themnet.http_postcalls 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, meaningdevv.nefoxx.com/uatt.nefoxx.comwere 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 inCLAUDE.md. - ☑ Phase C shipped (2026-07-09):
.github/workflows/backend-ci.yml(two parallel jobs —db-migrations-pgtap: migration replay viasupabase start+ pgTAP;edge-functions:deno test/deno check, visibility-first pending NFX-004 + NFX-037), path-filtered tosupabase/**.config.tomlexpanded from 3 to 32verify_jwt=falseentries (the authoritative set, sourced from prod's ownfunctions list) and one pre-existing wrong entry (trade-planner-view-shared) removed.test:efscript 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-functionsjob 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 ondevelop, with scoped per-environment access tokens (not the single account-wide token originally planned) · ☐ Phase E: manual prod promotion (verify-cichecking 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 --linkedon Nefoxx-Dev matches the baseline; seed users confirmed queryable;deploy.yml/backend-ci.ymlYAML validated;supabase functions list/secrets list/cron.joball re-verified live against both projects on 2026-07-08 (see NFX-032);npm run test:efre-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 auditgrounds 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 tovitepressviavitepress-plugin-mermaid). GitHub's higher total reflects its broader advisory DB and full-manifest scan; the 3 criticals align exactly between GitHub andnpm 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 vianpm 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
RiEdit3Lineincident, theme/contrast breaks, canvas/export bugs, frontend↔backend contract drift) is structurally invisible. This adds a production-grade Playwright layer — critical user journeys,@axe-coreaccessibility, narrow visual regression, mobile viewport, anapicontract-test project, and a real functional deploy-smoke check to replacedeploy.yml's barecurl. 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 viatools/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), anapicontract project (trade-planner-saveauth + success-shape checks via raw@supabase/supabase-js, no browser), ana11ycritical-only PR-blocking subset (2 pages),e2e-smokeadded toci.ymlas a blocking job (needs: build-and-test, added todeploy-dev'sneeds:),.github/scripts/e2e-summary.cjs(Playwright-JSON-shaped sibling oftest-summary.cjs),e2e/**added tosonar.sources. Found and fixed two structural gaps the Phase-1 proof spec's narrower scope didn't exercise (CSPconnect-srcsilently killing the ephemeral stack's plain-HTTP calls;supabase startnot serving Edge Functions —supabase functions serveis a separate process) and one real product bug (NFX-040, public share links wrongly auth-gated) plus one real a11y bug (password toggle missingaria-label, fixed) — seeguides/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 apagefixture override — structurally unskippable) +public-pages.spec.js(real rendered content + zero console errors on/authand a public content page, read-only);deploy.yml's bare curl replaced with a real Playwrightsmoke-deployrun (curl kept as a cheap pre-flight propagation poll);verify-ciindeploy-uat.yml/deploy-prod.ymlnow 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/uatGitHub 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=a11ygreen 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 — seeguides/e2e-testing-strategy.md's local-flakiness note);npx eslint e2e/clean;ci.ymlvalidated withjs-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 resetthis repo has been put through) - Priority: High · Severity: Blocked any from-scratch DB rebuild + prod
db pushwas 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.sqlconvention collided on Supabase's version parser (leading digits before the first_→ same-day migrations collapsed to one version; 149/210 files affected), sosupabase db reset/supabase startaborted withduplicate key … schema_migrations_pkey. Investigating why revealed a deeper root cause: prod's ownschema_migrationstable recorded only 6 of 212 local files as applied (5×2026-04-06+20260410) — prod's schema was built via direct SQL, notsupabase 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 meantsupabase db pushwas 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 2auth.userstriggers + 4storage.objectspolicies a schema-only dump omits (managed schemas) · ☑ Archived all 210 old migration files tosupabase/migrations/_archive/(git history preserved viagit mv, not deleted) — includes the 2 genuine DDL bugs found and fixed en route (pg_policies.polname→policyname; a certificate-templates create/alter ordering fix) · ☑ Verified locally:supabase db resetgreen from an empty volume (baseline replays,seed.sqlruns, real GoTrue password login works) · ☑ Reconciled prod:supabase migration repair <6 old versions> --status reverted --linkedthensupabase migration repair 20260708000000 --status applied --linked— metadata-only, no DDL executed against prod · ☑ Final proof:supabase migration listshows local/remote in exact agreement on20260708000000only;supabase db diff --linkedagainst 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 resetgreen 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 oldYYYYMMDD_NNN_convention.supabase db pushis 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/uattbut 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(anduatt.nefoxx.comif treated separately) · ☐ Authorized redirect URI: Nefoxx-Dev'shttps://rchglrpywmxkcbmxcepl.supabase.co/auth/v1/callback· ☐ Paste the resulting Client ID + Secret into Nefoxx-Dev's dashboard: Authentication → Providers → Google · ☐ SetSITE_URLand 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.comwere non-functional for every write and enriched read (everysupabase.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, andselect * from cron.jobagainst both project refs:- Edge Functions: 0 of 67 deployed to Nefoxx-Dev.
functions list --project-ref rchglrpywmxkcbmxceplreturned 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 inCLAUDE.md), this meantdevv/uattcould not save a trade plan, complete onboarding, or do anything beyond a pure RPC read. - Secrets: 0 of 25 configured on Nefoxx-Dev.
secrets listreturned 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 "zeronet.http_post/external-call risk found anywhere in the migration history." That check only grepped migration files — it never queried the livecron.jobtable. Production actually has 26 rows: 21 activenet.http_postcalls to prod Edge Function URLs (NSE market-data ingestion,refresh-materialized-views,daily-scheduled-clean-up,finfluencify-live-session-reminder-sweep), 4 per-tableVACUUMjobs, 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).
- Edge Functions: 0 of 67 deployed to Nefoxx-Dev.
- Impact: Before this fix, any manual QA or future E2E work against
devv/uattwould 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_jwtsetting exactly (32 Type B /--no-verify-jwt, 35 Type A — determined viafunctions list -o json'sverify_jwtfield on prod, not assumed) · ☑ Replicate all 26 cron jobs to Nefoxx-Dev with everynet.http_postURL rewritten fromlyaldbfgdhxpllgxbcxp.supabase.cotorchglrpywmxkcbmxcepl.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-argcron.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 thejobnamecolumn, so I didn't catch this myself. Re-queried prod withjobnameincluded, 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 · ☑ ConfirmedSHOONYA_API_*/INSTRUMENT_SYMBOLare stale/unused even on prod (user confirmation) — deliberately not replicated (see NFX-034) · ☑ AddedCLAUDE.mdArchitecture — 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 exactYYYYMMDD_NNN_pattern that caused NFX-030) and the Change Manifest Policy section (still asserted "a single Supabase project shared by dev and prod") · ☑ Newdocumentations/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.mdArchitecture — Environment Strategy. - Resolution Date: 2026-07-08 · Verification:
functions list --project-ref rchglrpywmxkcbmxcepl -o json→ 67 functions,verify_jwtmatched per-function against prod's own list;select jobid, jobname, schedule, command, active from cron.jobon 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:buildgreen (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, activebut notjobname, 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 inCLAUDE.mdandguides/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 activenet.http_postcalls to Edge Functions, 4VACUUMjobs, 1 inactive job) — none exist in any migration file. Set up directly against the live database (SQL editor or equivalent), not throughsupabase 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 directgrepofsupabase/migrations/20260708000000_baseline_prod_schema.sqlforstorage.bucketsinsert 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 checkedcron.job/storage.bucketsdirectly instead of relying on migration history (the same category of blind spot that caused NFX-030).
- Cron jobs: production has 26 rows in
- 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.jobandstorage.bucketsneed 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 viaon 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, andINSTRUMENT_SYMBOLare configured as secrets on production. Their only consumer,shoonya-nse-indices, is not referenced anywhere in prod'scron.jobtable (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-indiceshas 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 deadshoonya-nse-indicesfunction 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_*orZOOM_*Edge Function secrets set. Supabase never returns a secret's value once set (secrets listshows 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.localasVITE_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 ondevv/uattuntil 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) withKEY=valuelines for the 7 Cloudflare + 7 Zoom keys above · ☐ Runsupabase secrets set --env-file supabase/.dev-secrets.local --project-ref rchglrpywmxkcbmxcepl(or set individually via Dashboard → Nefoxx-Dev → Edge Functions → Secrets) · ☐ Verify viasupabase secrets list --project-ref rchglrpywmxkcbmxcepl(names only) and a real upload/Zoom-connect test ondevv.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 }producesadaptive_opportunist; the function returnsintuitive_pattern_trader. Traced to the documented weighted-scoring formula inhelpers.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, whileintuitive_pattern_trader = (100-pa)×0.35 + ma×0.35 + er×0.20 + cd×0.10 = 71.5—intuitive_pattern_tradergenuinely scores higher given the formula, becausepa:30isn'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:efto report 1 failure (1804 passed otherwise, confirmed 2026-07-09) whenever run with--no-check, and blocks the newedge-functionsCI 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
pavalue high enough thatadaptive_opportunistactually wins under the current formula (sinceadaptive_opportunist's score doesn't depend onpaat all, anypachange only affectsintuitive_pattern_trader's competing score) — e.g.pa: 80keepsma:90"high MA" while no longer triggeringintuitive_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'scolor-contrastrule flagstext-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/auththis 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 whetherorange-500vs. the documentedorange-600is itself part of the gap, sinceorange-600is 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/denyorange-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 a11ycritical+serioussweep platform-wide once fixed and promote the PR-blocking gate's threshold back tocritical+serious. - Target: Backlog · Related Links: NFX-029 (Phase 2, found during);
guides/e2e-testing-strategy.mdGovernance 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 ErroronGET .../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 ine2e-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'spublicPathsallowlist (routes that render with zero auth enforcement) listed/auth,/trading-insights,/calcify,/verify— but not/shared/plan.SharedPlanPage.jsxitself correctly handles the "must sign in" case for private shares (its own"Sign In Required"state), butProtectedRouteWrapper'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-dismissibleAuthModal(onEscapeKeyDown/onInteractOutsideboth 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 separatebrowser.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/plantoProtectedRoute.jsx'spublicPaths. - 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 freshbrowser.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'saria-allowed-attrrule (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 withdropdownTypeset). 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 clonedaria-haspopup/aria-expanded/type="button"onto themotion.div(a generic, non-interactive element with no role that supports those attributes) instead of onto the actual button.aria-expandedon an element with no implicit/explicit role that supports it is exactly whataria-allowed-attrexists 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>, soasChildclones onto<Button>directly. Framer Motion variants still propagate correctly to amotion.*descendant from an ancestoranimate/whileHovertrigger regardless of exact nesting depth, so the hover animation is visually unchanged — confirmed vianpx eslint(no new errors) and the a11y spec re-run (fix removed thearia-allowed-attrviolation 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 thearia-allowed-attrviolation 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-nameviolation (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()calledsupabase.from('feature_flags').select('feature_key, is_enabled')directly — a standalone violation of CLAUDE.md's hard guardrail #2 ("Nosupabase.from()anywhere insrc/— 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_flagsisn't sensitive data, and the code already degrades gracefully —catchdefaults 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.sql—get_feature_flags(),SECURITY DEFINER,SET search_path = public,RETURNS TABLE(feature_key text, is_enabled boolean), granted to bothanonandauthenticated(matchingfeature_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.jsxswapped tosupabase.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/postgresall haveEXECUTE) on both; full Vitest suite green afterward (existing tests mock the wholeuseFeatureGate()hook, not the underlying.from()/.rpc()call, so none needed updating);npx eslintclean. - 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
RiEdit3Lineincident (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
grepprompted 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_maplookups 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-managementTabcomponents' initial-loadSELECTs. - 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).
- Read-only (candidate
- 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
greppass, 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-fileindex_expiry_mapduplication 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:** …