Harden sync and security; add IQ Bible, templates, password reset, backups
Build and Push Docker Image / build-and-push (push) Successful in 7m14s
Build and Push Docker Image / build-and-push (push) Successful in 7m14s
Sync and data safety - Autosave flushes on leaving a study or the tab; storage-full errors are reported - Unsynced studies, deletes and ink are queued and retried when back online - Deletes propagate across devices (with a "Keep it" undo) and no longer resurrect - Server assigns study versions (no client-clock conflicts); "Combine both" merges a conflicted study chunk by chunk - Reading-plan progress made offline is merged, not overwritten; plans, ink and marks are cleared from the device on sign-out Security - Block SSRF through the ntfy reminder URL; failure-only rate limiting per IP and account; constant-time login; TOTP replay protection; input validation; SESSION_SECRET required in production; admin user delete fixed - Forgot password: one-time code sent to the account's ntfy topic Features - IQ Bible proxy (route allow-list, text-only caching per its terms): more commentaries, lexicons, study aids, daily verse and devotional, plan calendar export, narrations, podcast background - Study templates, reading-plan catch-up, account export, daily database snapshots Tests and tooling - ESLint config; App tests split into src/test; tests for sync queues, library hook, merge, templates, IQ Bible UI and reset form Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
6bb392933a
commit
f274bc9c8a
67 files changed
+4734
-1569
No files matched your search
@@ -0,0 +1,33 @@
|
||||
import js from '@eslint/js';
|
||||
import globals from 'globals';
|
||||
import reactHooks from 'eslint-plugin-react-hooks';
|
||||
|
||||
export default [
|
||||
{ ignores: ['dist/**', 'coverage/**', 'node_modules/**', 'server/data/**', 'public/**'] },
|
||||
js.configs.recommended,
|
||||
{
|
||||
files: ['src/**/*.{js,jsx}'],
|
||||
languageOptions: {
|
||||
ecmaVersion: 'latest',
|
||||
sourceType: 'module',
|
||||
globals: { ...globals.browser },
|
||||
parserOptions: { ecmaFeatures: { jsx: true } },
|
||||
},
|
||||
plugins: { 'react-hooks': reactHooks },
|
||||
rules: {
|
||||
'react-hooks/rules-of-hooks': 'error',
|
||||
'react-hooks/exhaustive-deps': 'warn',
|
||||
'no-unused-vars': ['warn', { varsIgnorePattern: '^_|^[A-Z]', argsIgnorePattern: '^_', caughtErrors: 'none' }],
|
||||
'no-empty': ['error', { allowEmptyCatch: true }],
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['server/**/*.js', 'scripts/**/*.mjs', 'vite.config.js', 'eslint.config.js', 'postcss.config.js', 'tailwind.config.js'],
|
||||
languageOptions: { ecmaVersion: 'latest', sourceType: 'module', globals: { ...globals.node } },
|
||||
rules: { 'no-unused-vars': ['warn', { argsIgnorePattern: '^_', caughtErrors: 'none' }], 'no-empty': ['error', { allowEmptyCatch: true }] },
|
||||
},
|
||||
{
|
||||
files: ['**/*.test.{js,jsx}', 'src/setupTests.js', 'src/test/**'],
|
||||
languageOptions: { globals: { ...globals.browser, ...globals.node, vi: 'readonly' } },
|
||||
},
|
||||
];
|
||||
Reference in new issue
Block a user