Skip to content

Enterprise Readiness Assessment

1. Executive summary

Verdict: A small, narrowly-scoped admin API forked from someli-api's skeleton. The codebase is manageable (~2400 LoC of routes vs someli-api's 22 000+), but suffers from the same patterns: no tests, weak observability, mixed auth schemes, and shared-helper drift. It has the least deploy infrastructure of the four backends — no Dockerfile, no CI workflow committed in the repo. There are two high-severity security findings (hardcoded session secret, hardcoded Slack token) that should be addressed this week.

Top 3 strengths: 1. Small surface — only 40 endpoints; easy to read; easy to refactor. 2. Sensible structure inherited from someli-api — server / routes / actions / helpers / middlewares is a known shape. 3. Modern admin FEadmin_console_R is on Vite + React + TS + shadcn/ui, a forward-looking stack that pairs well with a cleanup of this backend.

Top 5 risks: 1. Hardcoded credentials in source (Slack bot token; express-session secret) 2. No CI / no Dockerfile — deploys are ad-hoc 3. In-memory token revocation + no token expiry = effectively long-lived tokens, no real logout 4. Helper-code drift from someli-api (some helpers byte-identical, some heavily diverged) — bug fixes need coordination 5. Auth-by-SQL-filter — no requireRole middleware; new endpoints can accidentally expose admin data

Top 5 recommendations: 1. This week (Phase 0a): rotate Slack token; move session secret to env; move conf/credentials.json out of the repo (if committed) 2. Phase 0: add Dockerfile, CI workflow, /health endpoint, structured logging, request id middleware 3. Phase 0: introduce requireRole(...) middleware and apply per-router 4. Phase 1: extract the 4 byte-identical helpers (tokenGenerator, revokeToken, ragProcess, webScraping) into a shared npm package 5. Phase 1: prune ~20 unused dependencies (Passport, Twitter, Expo, path/fs/http/stream/url squatters)

2. Methodology & scope

Audited via find, cat, diff, grep, wc against the cloned someli-gh/Someli-admin-api/ directory. Compared against someli-api/ for shared lineage. No tests run (none exist).

3. Maturity assessment (CMMI 1–5)

Pillar Current 12-mo target Why
Architecture & Modularity 2 3 Small, comprehensible; needs requireRole middleware and route splitting (one 1400-line file is enough)
API Contract & Versioning 1 2 No OpenAPI; inconsistent path naming (/word:param vs /word/:param); typos in path names
Data Architecture 2 2 Same MySQL schema as platform; queries mostly parameterised; some dynamic-filter risk (F-8)
Background Processing n/a n/a No jobs in this repo
Security & Compliance 1 3 Two hardcoded credentials; CORS wildcard; in-memory revocation; auth-by-SQL-filter
Observability 1 3 console.log only; no health, no metrics, no error tracking
Reliability & Resilience 1 2 sync-mysql blocks the event loop; no graceful shutdown
Scalability 2 3 Admin tool — low traffic by nature, so this is less acute
Testing & Quality Gates 1 2 Zero tests; no CI gate
CI/CD & Deployment 1 3 No Dockerfile, no Jenkins, no GHA in this repo
Infrastructure as Code 1 2 nothing
Cost Visibility & FinOps 2 2 Small footprint; not a top concern
Documentation & Knowledge Management 2 3 This audit covers the gap; needs OpenAPI
Team Practices & Governance 2 3 Branch model exists; no PR template, no code-owners file

4. Findings (security-leading)

See security.md. Summary:

ID Severity Description Phase
F-1 HIGH Hardcoded express-session secret in server.js 0a
F-2 HIGH Hardcoded Slack bot token in routes/auth.js 0a
F-3 MEDIUM In-memory token revocation (cleared on restart) 0
F-4 MEDIUM Encrypted tokens have no expiry 0
F-5 MEDIUM CORS wildcard 0
F-6 LOW Webhook body-parser exemption with no handlers 1
F-7 MEDIUM Role gating via SQL only, no requireRole middleware 0
F-8 MEDIUM Possible SQL injection via dynamic filter interpolation (spot-check needed) 0
F-9 LOW 150 MB JSON body limit on unauthenticated endpoints 0
F-10 HIGH (if true) conf/credentials.json may be committed (Google service account) 0a verify; then immediate rotation

Non-security findings:

ID Severity Description Phase
N-1 n/a No tests, no CI 0
N-2 n/a No Dockerfile / no nginx config 0
N-3 n/a ~20 unused npm dependencies 0a
N-4 n/a Two coexisting auth schemes (Bearer JWT + encrypted-token); pick one 1
N-5 n/a aws-sdk v2 in addition to v3; align 2
N-6 n/a Helper drift with someli-api: 4 files identical, 6 forked 1 (extract identicals)

5. Strategic decisions

  1. Where does admin logic live going forward? Two options:
  2. Keep it here: continue to evolve Someli-admin-api as the admin scope grows. Pro: clean separation; small surface. Con: helper-drift compounds.
  3. Fold it back into someli-api: undo the fork; mount admin routes inside the main app, protected by a role check. Pro: zero drift; one runtime. Con: bigger someli-api; admin work blocks on the main app's release cadence.

Audit recommendation: keep it here. The trend across the platform is more service separation, not less. But invest in the helper-extraction (Phase 1) so the drift becomes a fixed cost rather than growing.

  1. Auth scheme consolidation. Bearer JWT vs encrypted-token. The admin FE uses encrypted-token; keep that, deprecate the JWT path. Remove methods.js's ensureToken once nothing uses it.

  2. Observability investment. The admin tool is the smallest, lowest-traffic backend — the ideal pilot for adding Sentry + pino + request ids + Prometheus metrics. Patterns proven here can roll out to someli-api later.

6. Roadmap

Phase 0a — This week

  • Rotate Slack token; move to process.env.SLACK_BOT_TOKEN (F-2)
  • Move session secret to process.env.SESSION_SECRET; throw if unset (F-1)
  • Verify whether conf/credentials.json is committed; if so, rotate and gitignore (F-10)
  • Prune unused npm deps (path, http, fs, stream, url, crypto, fetch, possibly request, passport-*, twitter*, expo-server-sdk) (N-3)

Phase 0 — Stabilise (months 0–3)

  • Add Dockerfile (copy/adapt from someli-api) (N-2)
  • Add CI workflow (GitHub Actions; copy/adapt from someli-api/.github/workflows/dev-api-deploy.yml) (N-2)
  • Add /health endpoint
  • Add morgan access logs
  • Add request-id middleware
  • Move token revocation to DB-backed store (F-3)
  • Add requireRole(...) middleware; apply per-router (F-7)
  • Audit dynamic-SQL filters; replace string interpolation with ? placeholders (F-8)
  • Tighten CORS to known FE origins (F-5)
  • Tighten body-size limits on unauthenticated endpoints (F-9)
  • Encode an exp claim in the encrypted-token (F-4)

Phase 1 — Foundation (months 3–9)

  • Extract tokenGenerator.js, revokeToken.js, ragProcess.js, webScraping.js to a shared internal npm package (N-6)
  • Sentry integration (or equivalent)
  • Smoke tests + auth tests (N-1)
  • OpenAPI spec generation
  • Deprecate methods.ensureToken path (Decision 2)

Phase 2 — Modular refactor (months 9–18)

  • Split routes/routes.js and routes/auth.js by domain (personnel, accounts, marketing) (Pillar 1)
  • Migrate aws-sdk v2 calls to v3 (Pillar 5)
  • Move from mysql/sync-mysql to mysql2/promise consistently (Pillar 5)

Phase 3 — Selective extraction (months 18+)

  • Only if needed: split into multiple admin services by domain (accounts, marketing, support tooling)

7. Risk register

ID Risk Likelihood Impact Mitigation phase
R-1 Leaked Slack bot token used by attacker for phishing in customer Slack Medium Medium 0a
R-2 Stale encrypted token replayed after intended logout (in-memory revocation) Medium Medium 0
R-3 New endpoint shipped without role gating exposes admin data Medium High 0
R-4 Helper drift causes a bug fix in someli-api not to apply here High Medium 1
R-5 sync-mysql blocks event loop during a heavy admin operation (e.g., getAllOwnerList with no filters) Medium Medium 2
R-6 No CI → manual deploy errors (wrong env, wrong branch) Medium Medium 0
R-7 Production runs nodemon instead of node (because that's what start does) Low Medium 0

8. Standards compliance

  • OWASP A02 Cryptographic Failures: encrypted-token format with no expiry; AES key handling not audited
  • OWASP A04 Insecure Design: in-memory revocation; auth-by-SQL-filter; CORS wildcard
  • OWASP A05 Security Misconfiguration: hardcoded credentials; default config
  • OWASP A07 Identification & Authentication Failures: long-lived tokens; weak logout

9. Open questions

See verify-markers.md.