Skip to content

Session Audit Roadmap — 2026-05-10

Origin: Items surfaced during the 2026-05-09/10 working session covering prod docs 502, signup-credit fix, LAN-access setup, and full payment audit. This document is the punch list to work through; each item is applied in its own commit (or a clearly-bounded series of commits in the same area).

Repos involved: both indoxhub-backend (this repo) and indoxhub-frontend (sibling). Items note which repo to edit in.

Progress (2026-05-19)

All backend items DONE except the deployment-config check #10. Per-item commits: - #2 docs container Dockerfile — f0642f3 (shipped earlier) - #7 partial unique index on signup_credit — 13528ef - #8 payment-flow tests (23 tests, mocked Stripe) — 2d04875 - #9 CI Node 20 bump — already on v4+ (no-op) - #11 mask Stripe-secret previews in ValueError — 5dc7be1 - #12 consolidate session-breakdown shape — af173c4 - #13 lazy-init Stripe API key — c0772e0 - #17 watchdog IDLE_HOURS env-overridable (default 4h) — 1628336

Remaining: #10 (prod env check, no code), #18 (refresh 3-month plan),

19/#21 (architecture/DX, low). Frontend items #1, #3, #4, #5, #6, #14,

15, #16, #20 live in the sibling repo.


🔴 URGENT

1. Google OAuth client secret leak in frontend bundle

  • Severity: Security — credential exposed to every browser
  • Repo: indoxhub-frontend
  • Symptom: frontend/.env line 4 sets NEXT_PUBLIC_CLIENT_SECRET=GOCSPX-.... Any var with NEXT_PUBLIC_ prefix is baked into the JS bundle shipped to browsers.
  • What to do:
  • Rotate the secret in Google Cloud Console (deauth the leaked one)
  • Remove NEXT_PUBLIC_CLIENT_SECRET from frontend/.env and any .env.example / docs
  • Grep frontend src/ for NEXT_PUBLIC_CLIENT_SECRET — if any code reads it, the flow is broken-by-design (secrets must live server-side); refactor that flow to call backend instead
  • If the flow currently posts the secret to backend, that's fine — backend can hold the secret as a non-public env

🟠 High-priority

2. Production docs container is fragile — DONE f0642f3

  • Repo: indoxhub-backend
  • Symptom: docker/production/docker-compose.yml:208-214 runs apk add + pip install + mkdocs serve on every container restart. Slow recovery (~2-5 min after CI deploy) and mkdocs serve is a single-threaded dev server, not built for prod traffic.
  • What to do:
  • Create docker/docs/Dockerfile that pre-installs deps (mkdocs-material, cairosvg, pillow, mkdocs-git-revision-date-localized-plugin)
  • Run mkdocs build once at image build time
  • Final stage: nginx:alpine serving the static /site/ directory
  • Update prod compose to build from this Dockerfile, drop the inline apk add ... command
  • Verify in local first (mirror in docker/local/), then push prod compose change
  • Effort: ~30-60 min
  • Risk: Low — falls back to current behavior if rebuild fails

3. Frontend signup-credit UI incomplete (Phase 1 of 6)

  • Repo: indoxhub-frontend
  • Symptom: frontend/docs/plans/2026-05-02-signup-credit-frontend.md says Phase 1 in progress; only types + 3 React Query hooks exist (useSignupCreditStatus, useCreateSetupIntent, useGrantWithExistingCard). No UI page. Users can't actually claim the $1.
  • What to do: implement Phases 2-5 from that plan
  • Phase 2: StripeElementsProvider (client_secret + publishable_key)
  • Phase 3: /signup-credit page route + status-driven render branches
  • Phase 4: <PaymentElement> form calling confirmSetup, success state polling
  • Phase 5: i18n + a11y polish
  • Phase 6: smoke test against live Stripe test mode
  • Effort: 1-2 days per the plan's own estimate
  • Depends on: B1+B2 backend fix (already done locally, not yet pushed)

4. Crypto UI lies to users

  • Repo: indoxhub-frontend
  • Symptom: src/components/pages/landing/intro/components/CryptoLabel.tsx claims "we use crypto for payment" — zero crypto backend exists. Misleads users.
  • What to do: decide
  • (a) Remove the label — 30s edit, ship today
  • (b) Implement Stripe Crypto Onramp — 1-2 days
  • Recommendation: (a) until you have actual demand for crypto

5. Refresh token bug

  • Repo: indoxhub-frontend (probably)
  • Symptom: Tracked in 3-month plan as item 2.27. No reproduction yet this session.
  • What to do: reproduce → identify cause → fix
  • Effort: 2hr per plan estimate

🟡 Medium-priority

6. SSR fragility on home page (already planned, partially done)

  • Repo: indoxhub-frontend
  • Plan: frontend/docs/plans/2026-04-28-home-page-ssr-hardening.md
  • Status: Phase 1 audit done; Phases 2-5 fixes pending
  • 3 components with known unhardened API calls:
  • WhatsNewStrip — no fallback when API misshapes
  • Trending — partial guard, doesn't catch non-array
  • TrendingCard — numeric fields not coerced
  • Effort: half-day

7. Webhook grant idempotency hardening — DONE 13528ef

  • Repo: indoxhub-backend
  • Symptom: app/db/billing_modules/grant_signup_credit.py does 3 separate idempotency checks (email, already-granted, setup-intent) — sequential, not atomic. Webhook retries are usually serial so race risk is small, but the right fix is at the DB layer.
  • What to do:
  • Migration: add unique partial index CREATE UNIQUE INDEX ON billing_transactions (user_id) WHERE payment_method='signup_credit'
  • Remove the now-redundant Python check (just rely on the DB constraint + transaction handling)
  • Effort: ~1 hour including migration

8. No payment-flow tests — DONE 2d04875

  • Repo: indoxhub-backend
  • Symptom: tests/test_billing_fixes.py covers credit math only. No tests for Stripe checkout, SetupIntent, or grant flow.
  • What to do: integration tests with mocked Stripe API for happy paths of each flow:
  • POST /payments/create-checkout-session
  • POST /payments/signup-credit/setup-intent
  • GET /payments/signup-credit/status (with and without saved card)
  • POST /payments/signup-credit/grant-with-existing-card
  • Webhook handler for checkout.session.completed and setup_intent.succeeded
  • Effort: half-day

9. CI/CD Node 20 deprecation — DONE (no-op; all actions already at v4+)

  • Repo: indoxhub-backend (.github/workflows)
  • Symptom: docker/setup-buildx-action@v3 runs Node 20. Forced to Node 24 by 2026-06-02; removed entirely 2026-09-16.
  • What to do: bump action versions where pinned to v3 → v4 (or current latest). Test with act or a draft workflow run.
  • Effort: 30 min
  • Repo: indoxhub-backend (deployment, not code)
  • Symptom: Local has COOKIE_DOMAIN= empty; prod should have COOKIE_DOMAIN=.indoxhub.com so cookies span api/admin/main subdomains. Misconfiguration here causes silent auth failures across subdomains.
  • What to do: check prod env, set if missing.

🟢 Cleanups (low-priority)

# Issue Repo File / Detail
11 Stripe secrets logged with first-10-char "preview" — DONE 5dc7be1 backend actual leak was in app/core/config.py:172,179 not the files cited; ValueError previews dropped
12 Pricing logic duplicated — DONE af173c4 backend math wasn't duplicated; the breakdown shape was — extracted build_session_breakdown
13 Stripe API key set at module-import time — DONE c0772e0 backend new configure_stripe() in startup hook + every entry point; rotation no longer needs restart
14 Hardcoded URLs in TypeScript types frontend We fixed docs/ URL via env var. Audit other type literals like (string & {})
15 Frontend Dockerfile mismatch frontend docker/local/Dockerfile exists but docker/local/docker-compose.yml builds from docker/development/Dockerfile. Pick one and delete the other.
16 Commented-out OAuth providers in frontend .env frontend Microsoft and others commented out. Either implement or delete the cruft.
17 Watchdog auto-down at 1h is aggressive for active dev — DONE 1628336 backend env-overridable, default raised 1→4

🟣 Architecture / DX

# Suggestion
18 Refresh docs/main_plan/indoxhub_3month_plan.md — current "next task" (3.16 free signup credit) is already shipped. Mark done, pick new next.
19 Cross-compose external network is fragile if backend goes down. If team grows, consider Compose include (v2) or merging frontend service into backend's compose.
20 Split frontend .env into role-specific files (.env, .env.docker, .env.local) for cleaner role-specific overrides.
21 Add a docker compose ps --filter health overview script for the local stack — QoL.

In-flight from this session (uncommitted)

These changes are sitting in the working tree from the same session and are not yet committed:

Backend uncommitted: - app/api/routers/stripe_checkout_modules/signup_credit.py — added grant-with-existing-card endpoint, populated card fields in status (B1 + B2) - app/services/checkout_modules/setup_intent.py — added read_stripe_customer_id and get_saved_card helpers - app/services/stripe_checkout_service.py — wired the helpers - app/models/schema_modules/billing_schemas.py — added 3 fields + new response schema - app/models/schema_modules/__init__.py — re-export - docker/local/docker-compose.yml — LAN CORS additions, COOKIE_DOMAIN= empty - docker/local/nginx-local.conf/ and /api/proxy/ route to frontend container

Frontend uncommitted: - 7 files for the option-B configurable-docs-URL refactor - docker/local/Dockerfile.env.local.env - docker/local/docker-compose.yml — joins external network, drops port 3010

These are functional and tested; just need commits + push when convenient.


Order I'll work through

Priority order — finishing one before starting the next, committing after each non-trivial item. Items 1–4 are biggest impact; 11–17 are quick wins that can batch.

  1. 1 — credential leak (urgent, security)

  2. 4 — crypto label (30s, removes user-facing lie)

  3. 11 — secret logging mask (quick, security adjacent)

  4. 2 — prod docs container Dockerfile (operational stability)

  5. 7 — webhook idempotency DB constraint

  6. 9 — CI Node version bump

  7. 3 — signup-credit UI Phases 2-5 (real product work, long-running)

  8. 6 — SSR hardening Phases 2-5

  9. Remainder of cleanups (#12–#17)
  10. Refresh 3-month plan (#18)

User decides which items to push to prod after each commit.

Documentation last built on May 23, 2026