docs: update public docs post-audit for v0.7.0
- SECURITY.md: add bcrypt v6 reference and mandatory SESSION_SECRET note - CODE_OF_CONDUCT.md: add enforcement contact (GitHub Private Reporting) - BACKLOG.md: add completed features table entries for v0.5.0 through v0.7.0 - docs/SPEC.md: add supported languages table with Italian (v0.5.8) - Remove CLAUDE.md.proposed (tracked, deleted from disk)
This commit is contained in:
@@ -26,3 +26,11 @@ New suggestion? → [Open an issue](https://github.com/ulsklyc/oikos/issues/new?
|
|||||||
| BL-10 | PWA: Offline fallback for critical pages | v0.4.0 |
|
| BL-10 | PWA: Offline fallback for critical pages | v0.4.0 |
|
||||||
| - | UX Polish (animations, bottom sheet, FAB, stagger, vibration) | v0.2.0 |
|
| - | UX Polish (animations, bottom sheet, FAB, stagger, vibration) | v0.2.0 |
|
||||||
| - | Event listener leaks, CSS gaps, modal tests | v0.2.1 |
|
| - | Event listener leaks, CSS gaps, modal tests | v0.2.1 |
|
||||||
|
| - | Internationalisation system (de + en), locale picker, formatDate/Time | v0.5.0 |
|
||||||
|
| - | PWA: Correct Oikos icons (192/512/maskable/apple-touch), service worker v22 | v0.5.1 |
|
||||||
|
| - | Calendar: Fix all-day RFC 5545 DTEND, DURATION support, birthday sync | v0.5.6 |
|
||||||
|
| - | Calendar: RRULE expansion fix (strip RRULE: prefix), YEARLY support | v0.5.7 |
|
||||||
|
| - | Italian (it) localization (497 keys) | v0.5.8 |
|
||||||
|
| - | Security hardening: XSS, rate limiter bypass, OAuth CSRF, CSV injection, session invalidation | v0.5.9 |
|
||||||
|
| - | Budget: Fix update failing when category changes | v0.6.0 |
|
||||||
|
| - | Upgrade bcrypt 5 → 6, ESM migration, structured logger, remove SESSION_SECRET fallback | v0.7.0 |
|
||||||
|
|||||||
@@ -1,50 +0,0 @@
|
|||||||
# Oikos
|
|
||||||
|
|
||||||
Self-hosted family planner PWA. Node.js/Express, Vanilla JS (no build step), SQLite, Docker.
|
|
||||||
|
|
||||||
## Hard Constraints
|
|
||||||
|
|
||||||
Violations are always bugs - no exceptions.
|
|
||||||
|
|
||||||
- Never add frontend frameworks (React, Vue, Svelte), bundlers (Webpack, Vite), or CSS libraries (Tailwind, Bootstrap).
|
|
||||||
- No external frontend dependencies. Only allowed exception: Lucide Icons (`public/lucide.min.js`, self-hosted). No CDN links at runtime.
|
|
||||||
- `import`/`export` everywhere. Never `require()`.
|
|
||||||
- Never `eval()`. Never `innerHTML` with user data. Use `textContent` or DOM API.
|
|
||||||
- All UI text via `t('key')`. Never hardcode strings in components. `de` is the reference locale.
|
|
||||||
- Migrations append-only. Add entries to the `migrations` array in `server/db.js`. Never modify or reorder existing entries.
|
|
||||||
- All colors, radii, shadows, font sizes from `public/styles/tokens.css`. Never hardcode design values.
|
|
||||||
- Every route handler in `try/catch`. No unhandled promise rejections.
|
|
||||||
|
|
||||||
## Architecture
|
|
||||||
|
|
||||||
Request flow: client → Express static (`public/`) or `/api/v1/*` → session auth → route handler → better-sqlite3 (sync) → JSON.
|
|
||||||
|
|
||||||
Key locations that are non-obvious:
|
|
||||||
- `public/i18n.js` - `t()`, `formatDate()`, `formatTime()`, `SUPPORTED_LOCALES`
|
|
||||||
- `public/api.js` - fetch wrapper (handles auth, CSRF, errors)
|
|
||||||
- `public/router.js` - History API router (no library)
|
|
||||||
|
|
||||||
## Conventions
|
|
||||||
|
|
||||||
- API responses: `{ data: ... }` on success, `{ error: string, code: number }` on failure.
|
|
||||||
- Dates/times: always `formatDate()`/`formatTime()` from `i18n.js`. Never format manually.
|
|
||||||
- Pages (`public/pages/*.js`): export `render()`. No side effects on import.
|
|
||||||
- Web Components (`public/components/*.js`): `oikos-` prefix, one component per file.
|
|
||||||
- Tests: `test-[module].js` in project root, `--experimental-sqlite` flag. Add `test:[module]` script to `package.json`.
|
|
||||||
|
|
||||||
## Verification
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm run dev # Start with --watch
|
|
||||||
npm test # All test suites (requires Node ≥22)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Reference
|
|
||||||
|
|
||||||
| What | Where |
|
|
||||||
|------|-------|
|
|
||||||
| Data model, UI specs | `docs/SPEC.md` |
|
|
||||||
| Design tokens | `public/styles/tokens.css` |
|
|
||||||
| DB schema (source of truth) | `server/db.js` |
|
|
||||||
| i18n keys | `public/locales/de.json` |
|
|
||||||
| Code conventions, commit format | `CONTRIBUTING.md` |
|
|
||||||
+6
-2
@@ -45,8 +45,12 @@ an individual is officially representing the community in public spaces.
|
|||||||
## Enforcement
|
## Enforcement
|
||||||
|
|
||||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||||
reported to the community leaders responsible for enforcement. All complaints
|
reported via [GitHub Private Vulnerability Reporting](https://github.com/ulsklyc/oikos/security/advisories/new)
|
||||||
will be reviewed and investigated promptly and fairly.
|
or by opening a private issue on GitHub. All complaints will be reviewed and
|
||||||
|
investigated promptly and fairly.
|
||||||
|
|
||||||
|
All community leaders are obligated to respect the privacy and security of the
|
||||||
|
reporter of any incident.
|
||||||
|
|
||||||
## Attribution
|
## Attribution
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -29,12 +29,13 @@ Vulnerabilities that require physical access to the host or root on the server a
|
|||||||
|
|
||||||
- Session-based auth with `httpOnly`, `SameSite=Strict`, `Secure` cookies
|
- Session-based auth with `httpOnly`, `SameSite=Strict`, `Secure` cookies
|
||||||
- CSRF protection via Double Submit Cookie on all state-changing requests
|
- CSRF protection via Double Submit Cookie on all state-changing requests
|
||||||
- Passwords hashed with bcrypt (cost factor 12)
|
- Passwords hashed with bcrypt v6 (cost factor 12)
|
||||||
- Login rate limiting (5 attempts/min per IP)
|
- Login rate limiting (5 attempts/min per IP)
|
||||||
- API rate limiting (300 requests/min per IP)
|
- API rate limiting (300 requests/min per IP)
|
||||||
- Content Security Policy via Helmet (`self`-only)
|
- Content Security Policy via Helmet (`self`-only)
|
||||||
- Optional SQLCipher AES-256 database encryption
|
- Optional SQLCipher AES-256 database encryption
|
||||||
- No API endpoint accessible without session auth (except login)
|
- No API endpoint accessible without session auth (except login)
|
||||||
|
- `SESSION_SECRET` is mandatory - server refuses to start if unset
|
||||||
|
|
||||||
## Authorization Model
|
## Authorization Model
|
||||||
|
|
||||||
|
|||||||
@@ -335,6 +335,14 @@ All UI strings are managed via `public/i18n.js`. No hardcoded text in JS files o
|
|||||||
2. `navigator.languages[0]` (browser language)
|
2. `navigator.languages[0]` (browser language)
|
||||||
3. Fallback: `de`
|
3. Fallback: `de`
|
||||||
|
|
||||||
|
### Supported Languages
|
||||||
|
|
||||||
|
| Code | Language | Status |
|
||||||
|
|------|----------|--------|
|
||||||
|
| `de` | German | Reference locale (all keys defined here) |
|
||||||
|
| `en` | English | Full translation |
|
||||||
|
| `it` | Italian | Full translation (added v0.5.8) |
|
||||||
|
|
||||||
### Adding a New Language
|
### Adding a New Language
|
||||||
|
|
||||||
1. Create `public/locales/xx.json` (copy of `de.json`, translate)
|
1. Create `public/locales/xx.json` (copy of `de.json`, translate)
|
||||||
|
|||||||
Reference in New Issue
Block a user