- Replace unsafe base64-only decode_token() with HTTP POST to gateway /whoami,
which performs RSA signature verification and expiry checks internally
- Fail-closed on gateway unreachable: return 503 instead of allowing access
- Add [gateway] config section (url/timeout) with GATEWAY_URL env override
- Add missing @_handle_exp decorator to delete_note and update_note views
- Fix Flask endpoint name collision using @functools.wraps on _handle_exp
- Remove unused base64 import
- Update dnfs.ini with gateway config (http://127.0.0.1:8443/whoami, timeout=5)
- Update docker-compose.yml with GATEWAY_URL and host.docker.internal for containers
Replace the insecure local base64 decode (with FIXME comment about
missing signature verification) with proper remote RSA signature
verification through gateway's /whoami endpoint:
- Add [gateway] config section (url, timeout) to dnfs.ini with defaults.
- Support GATEWAY_URL environment variable override for Docker.
- decode_token() now POSTs to gateway /whoami with Authorization: Bearer
<token>; gateway verifies RSA signature and expiry, returns login/user/
is_admin. Network/gateway errors fail-closed with 503.
- Add @_handle_exp decorators to delete_note() and update_note() which
were missing exception handling wrappers (consistent with other routes).
- docker-compose.yml: add GATEWAY_URL, CONFS_HOST, CONFS_PORT env vars
plus host.docker.internal extra_hosts so dnfs container can reach
host-side gateway and confs services.
- Add dnfs.ini to confs/configs/ with server, database, ai_review, confs sections
- Refactor dnfs.py to use three-layer fail-safe config loading (defaults → confs → env vars)
- Unify timeouts for DB RPC and AI review calls via configuration
- Add _merge_ini() whitelist merging to prevent unexpected config injection
- Environment variables have highest priority for Docker networking (db/ai_review hostnames)
- Document config loading mechanism in both confs/README.md and dnfs/README.md
Follows the same pattern as static service integration; confs failure falls back
gracefully to built-in defaults + environment variables.
- Wrap _flush_loop main body in outer try/except to prevent any
unexpected exception (network errors, serialization errors, etc.)
from killing the background thread (which would cause unbounded
queue growth and eventual OOM)
- Wrap _send() call in inner try/except as final safety net
- Wrap RpcClient() construction in try/except (connection failures
during client creation were previously unhandled)
- Add _safe_json() helper: unserializable extra fields fall back to
repr()/str() instead of raising TypeError that could kill thread
- Generate timestamp at push() (enqueue time) instead of _send() time,
so timestamps reflect actual event time even when queue is backed up
- Replace unreliable time.sleep(0.6) in flush() with _flush_done Event
for proper synchronization between caller and background thread
- Add _QUEUE_MAXSIZE=10000 with drop-oldest policy to prevent unbounded
memory growth even in pathological cases
- Use put_nowait with Full handling to ensure push() never blocks
business threads
- Sync fix to all 4 copies: confs/static/smtp/dnfs
- New token_manager.js: silent refresh timer (80% lifetime) + global
fetch 401 interceptor with one-shot retry.
- dnfs.py /whoami now returns iat, created_at, keep_time for expiry
estimation.
- Dnfs.html loads token_manager.js before dnfs.js (zero change to dnfs.js).
- Graceful fallback: stale tokens without new fields, refresh failures,
and /refresh_token 401 itself all degrade to the existing 401→login flow.