Security & hardening pass: scrypt password hashing, persisted admin sessions, upvote/analytics rate limits, dependency fixes, healthcheck, lint cleanup; v2.10.0
Publish Container / build (push) Successful in 17m3s
Publish Container / build (push) Successful in 17m3s
- Study passwords: salted scrypt; legacy SHA-256 hashes verified and upgraded on login - Admin sessions persisted (hashed tokens) so deploys no longer log the admin out - Upvotes: rate limit + one per client per question, approved questions only; rate limit on analytics play/event - npm audit: 46 -> 4 vulnerabilities (tiptap bumped to 3.31.4) - Untrack per-user data (study users/notes/progress/etc.) from git - Dockerfile HEALTHCHECK; node --test suite for password hashing - Fix email template cards remounting (lost input focus) on each keystroke - Lint: 34 errors -> 0 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
e2150e1cd7
commit
8a796964b9
27 files changed
+880
-1034
No files matched your search
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"id": "da3f5f52-f0a3-4a36-9f52-7938b82e899a",
|
||||
"submissionId": "0c2e3dc4-5ee3-42e9-a81b-172bedc16713",
|
||||
"toEmail": "hello@versebyversewithnate.us",
|
||||
"toName": "NoAdmin Signup",
|
||||
"fromEmail": "hello@versebyversewithnate.us",
|
||||
"subject": "Thanks for reaching out to Verse by Verse with Nate",
|
||||
"preview": "Thank you for reaching out.\n\nI appreciate your message and wanted to follow up personally. I just wanted to say thank you for your email.\n\n~Nate",
|
||||
"sentAt": "2026-05-07T12:54:06.683Z"
|
||||
}
|
||||
],
|
||||
"updatedAt": "2026-05-07T12:54:06.685Z"
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
{
|
||||
"scrollDepth": {
|
||||
"/episodes": {
|
||||
"25": 4,
|
||||
"50": 4,
|
||||
"75": 2,
|
||||
"90": 0
|
||||
},
|
||||
"/": {
|
||||
"25": 2,
|
||||
"50": 2,
|
||||
"75": 2,
|
||||
"90": 2
|
||||
},
|
||||
"/about": {
|
||||
"25": 6,
|
||||
"50": 6,
|
||||
"75": 6,
|
||||
"90": 6
|
||||
}
|
||||
},
|
||||
"timeOnPage": {
|
||||
"/": {
|
||||
"totalSeconds": 64,
|
||||
"count": 5
|
||||
},
|
||||
"/episodes": {
|
||||
"totalSeconds": 318967,
|
||||
"count": 305
|
||||
},
|
||||
"/episodes/movn6tk3": {
|
||||
"totalSeconds": 445,
|
||||
"count": 3
|
||||
},
|
||||
"/about": {
|
||||
"totalSeconds": 63497,
|
||||
"count": 128
|
||||
}
|
||||
},
|
||||
"outboundClicks": {},
|
||||
"linkClicks": {
|
||||
"https://ko-fi.com/versebyversewithnate": {
|
||||
"count": 1,
|
||||
"internal": false
|
||||
},
|
||||
"/": {
|
||||
"count": 1,
|
||||
"internal": true
|
||||
},
|
||||
"/about": {
|
||||
"count": 1,
|
||||
"internal": true
|
||||
}
|
||||
},
|
||||
"utmSources": {},
|
||||
"searchQueries": {},
|
||||
"notFound": {},
|
||||
"audioEvents": {
|
||||
"Living Between Two Appearings": {
|
||||
"pauses": 0,
|
||||
"completions": 0,
|
||||
"totalListenSeconds": 43
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"Living Between Two Appearings": {
|
||||
"total": 1,
|
||||
"byDay": {
|
||||
"2026-07-22": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
{
|
||||
"posts": [
|
||||
{
|
||||
"id": "fd6f2d9c-8abc-43b2-8e93-c58c0cb1ff7b",
|
||||
"studySlug": "colossians",
|
||||
"sectionId": "",
|
||||
"authorUserId": "3307bdd7-a770-4fad-a28e-cf2d0c2a6e34",
|
||||
"authorName": "Test Student",
|
||||
"message": "reading",
|
||||
"createdAt": "2026-06-02T17:41:48.684Z",
|
||||
"replies": []
|
||||
},
|
||||
{
|
||||
"id": "001f2545-e1ee-4748-902b-5da5c47554bb",
|
||||
"studySlug": "colossians",
|
||||
"sectionId": "",
|
||||
"authorUserId": "3307bdd7-a770-4fad-a28e-cf2d0c2a6e34",
|
||||
"authorName": "Test Student",
|
||||
"message": "sool",
|
||||
"createdAt": "2026-06-02T17:41:41.608Z",
|
||||
"replies": []
|
||||
},
|
||||
{
|
||||
"id": "c40e4c10-47a3-42e8-88bd-78116af5babe",
|
||||
"studySlug": "colossians",
|
||||
"sectionId": "",
|
||||
"authorUserId": "3307bdd7-a770-4fad-a28e-cf2d0c2a6e34",
|
||||
"authorName": "Test Student",
|
||||
"message": "test",
|
||||
"createdAt": "2026-06-02T17:41:16.795Z",
|
||||
"replies": [
|
||||
{
|
||||
"id": "efe0bf3d-66e8-4dad-98c1-2e8c742e3120",
|
||||
"authorUserId": "3307bdd7-a770-4fad-a28e-cf2d0c2a6e34",
|
||||
"authorName": "Test Student",
|
||||
"message": "test",
|
||||
"createdAt": "2026-06-02T17:41:25.003Z"
|
||||
},
|
||||
{
|
||||
"id": "1d6c3bd1-5ada-4f98-8ca3-5ed15bd00a68",
|
||||
"authorUserId": "3307bdd7-a770-4fad-a28e-cf2d0c2a6e34",
|
||||
"authorName": "Test Student",
|
||||
"message": "test",
|
||||
"createdAt": "2026-06-02T17:41:34.406Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"updatedAt": "2026-06-02T17:41:48.685Z"
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"colossians--1-1-2": "test....teset"
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"1-1-2": "Test"
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
{
|
||||
"byStudy": {
|
||||
"colossians": {
|
||||
"completedSectionIds": [
|
||||
"1-1-2",
|
||||
"1-3-8"
|
||||
],
|
||||
"quizAnswers": {
|
||||
"1-1-2": [
|
||||
"test",
|
||||
"test"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"updatedAt": "2026-06-08T20:30:19.689Z"
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"users": {},
|
||||
"updatedAt": "2026-09-03T21:13:33.725Z"
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
{
|
||||
"users": [
|
||||
{
|
||||
"id": "9b74971e-bfdc-4e64-a8d7-87cd8f2bb5c4",
|
||||
"username": "student.test@versebyverse.local",
|
||||
"passwordHash": "6500cc2e717d1d646f371dba1ec918d2f2f9fddbb8576c792df69a1f2340dcd9",
|
||||
"displayName": "Student Test",
|
||||
"subscribeNewsletter": false,
|
||||
"studyRemindersEnabled": false,
|
||||
"enrolledStudySlugs": [],
|
||||
"avatarUrl": "",
|
||||
"createdAt": null,
|
||||
"updatedAt": "2026-08-10T12:39:25.413Z",
|
||||
"lastLoginAt": "2026-05-21T15:41:16.259Z",
|
||||
"reengagementSentAt": {},
|
||||
"pendingEmailChange": null,
|
||||
"twoFaMethod": null,
|
||||
"totpSecret": null,
|
||||
"totpVerified": false,
|
||||
"totpEnabledAt": null,
|
||||
"totpRecoveryCodes": [],
|
||||
"remindersPausedUntil": null,
|
||||
"reminderFrequency": "immediate",
|
||||
"weeklyDigestSentAt": null
|
||||
},
|
||||
{
|
||||
"id": "3307bdd7-a770-4fad-a28e-cf2d0c2a6e34",
|
||||
"username": "test.user@versebyverse.local",
|
||||
"passwordHash": "fc89481d72dbea9af1d4f054faad48813227fa018da39259272dd27b5e493bb5",
|
||||
"displayName": "Test Student",
|
||||
"subscribeNewsletter": false,
|
||||
"studyRemindersEnabled": false,
|
||||
"enrolledStudySlugs": [
|
||||
"colossians"
|
||||
],
|
||||
"avatarUrl": "data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2288%22%20height%3D%2288%22%3E%3Crect%20width%3D%22100%25%22%20height%3D%22100%25%22%20rx%3D%2218%22%20ry%3D%2218%22%20fill%3D%22%2311100d%22%2F%3E%3Ctext%20x%3D%2250%25%22%20y%3D%2250%25%22%20dominant-baseline%3D%22middle%22%20text-anchor%3D%22middle%22%20font-size%3D%2256%22%3E%F0%9F%A6%81%3C%2Ftext%3E%3C%2Fsvg%3E",
|
||||
"createdAt": null,
|
||||
"updatedAt": "2026-06-08T20:46:30.804Z",
|
||||
"lastLoginAt": "2026-06-08T20:46:30.804Z",
|
||||
"reengagementSentAt": {},
|
||||
"pendingEmailChange": null,
|
||||
"twoFaMethod": null,
|
||||
"totpSecret": null,
|
||||
"totpVerified": false,
|
||||
"totpEnabledAt": null,
|
||||
"totpRecoveryCodes": [],
|
||||
"totpSecretPending": "FGR7UI5TWA4HB4DURCXEUXATTVVVJDJ5",
|
||||
"remindersPausedUntil": null,
|
||||
"reminderFrequency": "immediate",
|
||||
"weeklyDigestSentAt": null
|
||||
},
|
||||
{
|
||||
"id": "81c01e32-d94e-4e19-93ea-e5cd7644ea6a",
|
||||
"username": "test.avatar@versebyverse.local",
|
||||
"passwordHash": "fc89481d72dbea9af1d4f054faad48813227fa018da39259272dd27b5e493bb5",
|
||||
"displayName": "Avatar Test",
|
||||
"subscribeNewsletter": false,
|
||||
"studyRemindersEnabled": false,
|
||||
"enrolledStudySlugs": [],
|
||||
"avatarUrl": "data:image/svg+xml;utf8,%3Csvg xmlns=\"http://www.w3.org/2000/svg\" width=\"88\" height=\"88\"%3E%3Crect width=\"100%\" height=\"100%\" rx=\"18\" ry=\"18\" fill=\"%2311100d\"/%3E%3Ctext x=\"50%\" y=\"50%\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-size=\"56\"%3E🐱%3C/text%3E%3C/svg%3E",
|
||||
"createdAt": null,
|
||||
"updatedAt": null,
|
||||
"lastLoginAt": "2026-06-02T17:33:13.669Z",
|
||||
"reengagementSentAt": {},
|
||||
"pendingEmailChange": null,
|
||||
"twoFaMethod": null,
|
||||
"totpSecret": null,
|
||||
"totpVerified": false,
|
||||
"totpEnabledAt": null,
|
||||
"totpRecoveryCodes": [],
|
||||
"remindersPausedUntil": null,
|
||||
"reminderFrequency": "immediate",
|
||||
"weeklyDigestSentAt": null
|
||||
},
|
||||
{
|
||||
"id": "6cd08599-b8a8-4aa9-809d-dd606cf21635",
|
||||
"username": "nmemmert@outlook.com",
|
||||
"passwordHash": "534c7ff8f203149c82881728eada86729bc69ef069db2f4b8f7202d7cf8b11f9",
|
||||
"displayName": "",
|
||||
"subscribeNewsletter": true,
|
||||
"studyRemindersEnabled": false,
|
||||
"pendingEmailChange": null,
|
||||
"enrolledStudySlugs": [
|
||||
"colossians",
|
||||
"titus"
|
||||
],
|
||||
"createdAt": "2026-09-03T20:14:39.297Z",
|
||||
"updatedAt": "2026-09-03T20:14:49.258Z",
|
||||
"lastLoginAt": "2026-09-03T20:14:39.297Z",
|
||||
"firstVisitAt": "2026-09-03T20:14:51.933Z"
|
||||
}
|
||||
],
|
||||
"updatedAt": "2026-09-03T20:14:51.933Z"
|
||||
}
|
||||
Reference in new issue
Block a user