ffdefd2c9c
Backend
- photos table + upload storage under DATA_DIR/uploads (magic-byte sniffing,
no multipart dep, SVG rejected, wx exclusive writes)
- POST/GET /api/photos, GET /api/photos/:id/file with nosniff + sandboxed CSP
- admin routes (ADMIN_EMAILS allowlist): list, delete one, clear all
- identity-keyed rate limits (login 20/15m, signup 5/h, upload 60/h)
- cookie gains Secure when the request is https (via trustProxy)
- /api/auth/me now 200 {user:null} instead of 401 when signed out
Frontend
- landing strip section: signed-in users upload straight from the reel,
guests get a /app?auth=1 link
- /admin page: grid of uploads with delete + clear all
- nginx: nosniff / X-Frame-Options / Referrer-Policy, forward
X-Forwarded-Proto so the API can mark cookies Secure behind TLS
Tests: docker/backend test/security.mjs (45 checks)
24 lines
579 B
JSON
24 lines
579 B
JSON
{
|
|
"name": "recipescam-api",
|
|
"version": "1.0.0",
|
|
"private": true,
|
|
"description": "RecipesCam web API - accounts + user recipes (server never receives photos)",
|
|
"main": "dist/server.js",
|
|
"scripts": {
|
|
"build": "tsc",
|
|
"start": "node dist/server.js",
|
|
"dev": "tsx watch src/server.ts",
|
|
"test": "node test/security.mjs"
|
|
},
|
|
"dependencies": {
|
|
"better-sqlite3": "^12.11.1",
|
|
"fastify": "^5.12.5"
|
|
},
|
|
"devDependencies": {
|
|
"@types/better-sqlite3": "^9.6.0",
|
|
"@types/node": "^22.20.3",
|
|
"tsx": "^4.23.13",
|
|
"typescript": "^5.9.3"
|
|
}
|
|
}
|