03 — Someli-admin-api architecture¶
A guided tour.
Folder map¶
Someli-admin-api/
├── conf.js ← 49 lines — env-var passthrough
├── server.js ← 70 lines — Express boot, MySQL, mount routes
├── methods.js ← 16 lines — `ensureToken` Bearer-JWT middleware
├── package.json ← 78 runtime deps + 1 devDep
├── Nova-Pro_KnowledgeBased_Content.py ← batch processor for AWS Bedrock Nova (Python, separate runtime)
├── README.md ← 1 line placeholder
│
├── routes/
│ ├── routes.js ← 1400 lines — 31 endpoints; class-based pattern
│ └── auth.js ← 957 lines — 9 endpoints; Express Router, auth-gated
│
├── actions/
│ └── actions.js ← generic CRUD service layer
│
├── middlewares/
│ ├── auth.js ← token-header decryption (encrypted Bearer pattern)
│ └── validation.js ← express-validator chains
│
├── helper/ ← 10 files (see 02-stack.md for what's byte-identical vs drifted)
│ ├── aiLogics.js
│ ├── basic.js
│ ├── constants.js
│ ├── helper.js
│ ├── index.js
│ ├── ragProcess.js ← byte-identical to someli-api/
│ ├── revokeToken.js ← byte-identical
│ ├── stockImage.js
│ ├── tokenGenerator.js ← byte-identical
│ └── webScraping.js ← byte-identical
│
├── modules/
│ └── dbDriver/lib/mysql.js ← callback-style MySQL pool wrapper
│
└── conf/
└── credentials.json ← likely Google service-account JSON
Entry point — server.js¶
70 lines. Reads almost like someli-api/server.js with three differences (Passport / Paddle / dashboard absent).
const conf = require("./conf");
const express = require("express");
const bodyparser = require("body-parser");
const cors = require("cors");
const expressSession = require('express-session');
const port = process.env.port || conf.port || 5002;
const app = express();
const fileUpload = require('express-fileupload');
app.use(expressSession({
secret: "3eB(2:\srlI+qa5", // HARDCODED — known finding
resave: false,
saveUninitialized: true
}))
app.use(fileUpload());
app.use((req, res, next) => {
if (req.originalUrl === '/stripe_webhooks' || req.originalUrl === '/paddle_sandbox_webhooks' || req.originalUrl === '/paddle_production_webhooks') {
next(); // these would need raw body for signature verification — but no handlers exist
} else {
express.json({ limit: '150mb', extended: true, parameterLimit: 50000 })(req, res, next);
}
});
app.use('/favicon.ico', express.static('./favicon.ico'));
app.use('/uploads', express.static('uploads'));
var db = require('./modules/dbDriver/lib/mysql');
db.connect(conf, (res) => {
if (!res && !res.status) console.log("\n Something Went Wrong!");
});
var server = app.listen(port, ...);
const io = require('socket.io')(server);
io.on('connection', function (socket) { ... });
var App = { db, server: app, socket: socketConnection };
module.exports.appData = App; // re-exported (same as someli-api)
app.use(cors());
const authRoute = require("./routes/auth");
app.use("/auth/", authRoute); // Mount A: Express Router
var { api } = require("./routes/routes");
var Api = new api(App);
Api.init(); // Mount B: class-based, on App.server
Differences from someli-api/server.js¶
- No
routes/social.jsmount (no OAuth) - No
routes/paddle.jsmount (Paddle is hardcoded insideroutes/routes.js, not as a separate router) - No
routes/partnerAuth.jsmount - No
dashboard/routes/index.jsmount - Passport imports are commented out
- Webhook exemption paths exist but no handlers for them in
routes/routes.js
Two route surfaces¶
| File | Mount | Auth pattern | Endpoints | Notes |
|---|---|---|---|---|
routes/auth.js |
/auth/* via app.use("/auth/", authRoute) |
router.use(auth) at top — every endpoint requires a decrypted token |
9 | High-permission admin operations: user/account delete, cross-user search |
routes/routes.js |
root, via api.init() registering on App.server |
Mixed — some endpoints use methods.ensureToken per-handler, some are unauthenticated (/authenticate, /webauthenticate) |
31 | Login + most CRUD on personnel, roles, accounts, affiliate marketing |
The two-layer auth is a real source of confusion. When adding a new endpoint, decide upfront: encrypted-Bearer route (goes in
routes/auth.js) or plain JWT (goes inroutes/routes.jswithmethods.ensureToken). The two are not interchangeable.
Request lifecycle¶
For a /auth/* request:
HTTP request
│
▼
Express middleware (session → fileupload → bodyparser → cors)
│
▼
app.use("/auth/", authRoute)
│
▼
router.use(auth) ← middlewares/auth.js — token-header decryption
│
▼
handler (sets res.userId, res.accountId from decrypted token)
For a root-mounted request (routes/routes.js):
HTTP request
│
▼
Express middleware
│
▼
api.init() registers each path on App.server
│
▼
handler (with optional methods.ensureToken Bearer-JWT check inline)
Validation¶
middlewares/validation.js exposes express-validator chains. Use them on routes that accept request body:
const { check, validationResult } = require('express-validator');
const { validateRequest } = require('../middlewares/validation');
router.post('/createPersonnel',
[check('email').isEmail(), check('role').isInt()],
validateRequest,
async (req, res) => { ... }
);
This is rare in someli-api (validation is inline / absent) but present in Someli-admin-api. Use it for new endpoints.
The Python file¶
Nova-Pro_KnowledgeBased_Content.py is a one-off Python batch processor for AWS Bedrock Nova. It is not invoked from Node — runs separately. If you need to use or modify it, you need a Python environment with the Bedrock SDK.
Don't try to integrate it into the Node runtime. Either rewrite the logic in Node or invoke it as a subprocess if needed.
Code-overlap caveats (the most important section)¶
Every change to a helper/*.js file needs you to check whether the same file exists (byte-identical or drifted) in:
someli-api/helper/designer-api/helper/(helper/index.jsonly)
See the summary table in 02-stack.md and the full matrix in ../../audit/CODE-OVERLAP-MATRIX.md.
Byte-identical helpers (tokenGenerator.js, revokeToken.js, ragProcess.js, webScraping.js) must be kept in sync between someli-api and Someli-admin-api. A PR that updates one without the other will produce drift you don't want.
Where to put a new file¶
| Adding | Put it in |
|---|---|
| A new authenticated admin endpoint | routes/auth.js (Express Router; encrypted Bearer auth) |
| A new admin endpoint that should use plain JWT | routes/routes.js (class-based; add methods.ensureToken to the handler) |
| A new unauthenticated endpoint | routes/routes.js (no auth middleware in the handler) |
| A new helper function | An existing helper/*.js file if it fits topically, OR a new helper/<name>.js. Check whether the same helper exists in someli-api/helper/. |
| A new validator chain | Extend middlewares/validation.js |
| A new Paddle webhook handler | Add the handler to routes/routes.js; the server.js exemption already covers the path |