Fix/dashboard auth clear stale cookies#5
Merged
Conversation
When /_api/auth/me returns non-200, dashboard_auth/dashboard_admin_auth redirected to login but left the dead sdb_token/sdb_server cookies in place, so an expired/stale token could trap the user in a redirect loop. Expire the cookies on validation failure so the next login isn't shadowed by the dead one. Defensive hardening; the primary cause of the recent login loop was a proxy cookie-coalescing bug fixed separately in soli-proxy. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Production requests intermittently stalled (~5s, sometimes indefinitely) with the system idle, surfacing only under DB use. Root cause: hops in the request path waited for a reply with no bounded timeout, so a stale/half-open connection or a stalled shard op parked a thread forever. - main.rs: bound the per-connection protocol-sniff read (10s); drive HTTP via hyper_util's auto Builder with an HTTP/1 header_read_timeout (30s) instead of axum::serve, preserving graceful shutdown (adds hyper-util dependency). - sdbql/executor/execution/clauses.rs: sharded INSERT/UPDATE/DELETE use recv_sharded with a 10s recv_timeout instead of an unbounded blocking recv(); adds unit tests. - error.rs: new DbError::Timeout mapped to HTTP 504. Also folds in in-progress dashboard/docs view edits already present in the tree. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Performance: - Prepared-statement and query caches: sync parking_lot RwLock (no .await on hot paths) with a per-collection invalidation index under the same lock — invalidation is O(matches), eviction prunes only its own index sets, and emptied sets are dropped (no leak) - New in-memory ApiKeyCache (Arc<ApiKey>): validate_api_key is O(1) instead of scanning _api_keys per request; pre-warmed at startup, kept in sync by handlers AND replication apply paths - Accept loop: try_send dispatch (8192-deep channels) so a saturated protocol worker drops new connections instead of blocking accepts - SyncLog::append: entry + sequence in one WriteBatch (one fsync) - Scans: scan_values() skips the intermediate Document allocation - storage/collection: std RwLock -> parking_lot (no poisoning) - Compression: skip 4xx/5xx and video/audio, composed with tower-http's DefaultPredicate (size/SSE/gRPC exemptions preserved) Security/correctness: - Login rate limiter keys on the real socket IP via ConnectInfo; X-Forwarded-For/X-Real-IP only trusted with SOLIDB_TRUST_PROXY_HEADERS=1 (headers are client-spoofable); limiter and Basic-auth caches are bounded LRUs (50K/10K) - Replicated _api_keys deletes evict the auth cache so revoked keys stop authenticating on peer nodes immediately - Schema validator cache sets hash+validator under both write guards (no mismatched pair under concurrent schema updates) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
New /database/:db/relationships page rendering an ER-style graph of all collections: FK relations inferred from index fields (snake_case and camelCase naming heuristics) and graph relations sampled from edge collection _from/_to references. Data endpoint sends Cache-Control: private, max-age=30 so quick navigations don't redo the per-collection index walk. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ions - Use DBWithThreadMode<MultiThreaded> (storage::RocksDb): create_cf/drop_cf take &self with internal synchronization, removing the unsafe Arc::as_ptr-as-*mut-DB casts that raced lock-free cf_handle() reads (and each other across StorageEngine's and Database's separate cf_locks) - Apply shared tuned CF options everywhere: Database::create_collection used bare Options::default(), so most collections got no LZ4 compression or tuning - Attach an explicit block-based table factory with a process-wide shared 512MB block cache and bloom filters to every CF; previously the configured cache applied only to the default CF while each of the other CFs lazily grew its own private 32MB default cache with no bloom filter - list_collections: use the live in-memory cf_names() instead of DB::list_cf(), which re-read the MANIFEST from disk on every call (~20x faster at 1000 CFs: 678us -> 34us per call) - Add examples/cf_perf_probe.rs to track CF-scaling costs (the per-create OPTIONS rewrite remains O(total CF count), tracked in tasks/todo/slow-database-drop-per-cf-options-rewrite.md) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…y drops
Every drop_cf rewrites + fsyncs the entire OPTIONS file (one section per
CF) under the DB mutex, so delete_database blocked for collections x
~400ms on instances with many CFs (measured: 18s for a 25-collection
database at ~1800 CFs).
delete_database now atomically deletes the db:{name} meta key and
persists a pending_drop:{cf} marker per collection in one WriteBatch,
then returns (~1ms); a background thread performs the expensive drops,
paced 25ms apart so foreground CF ops don't starve behind the queue.
Markers are resumed by initialize() so drops interrupted by a crash or
restart complete eventually.
Recreating the same database/collection while its old CF is still doomed
is handled by claiming: create_collection atomically takes ownership of
a Pending CF and drops + recreates it fresh, or waits if the dropper is
mid-drop on that exact CF. Doomed CFs are filtered from list_collections,
get_collection, delete_collection, and is_columnar_collection.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The test cast Database::db_arc()'s Arc pointer to the single-threaded rust_rocksdb::DB type and called create_cf through it. Since the switch to DBWithThreadMode<MultiThreaded> (7aa803c) the layouts differ, so the unsafe mutation was type confusion and segfaulted in CI (SIGSEGV). MultiThreaded create_cf takes &self, so the unsafe block is unnecessary: call it directly on the Arc. Also drop the stale single-threaded create_test_db helper. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Embed the admin/ Soli application (controllers, views, specs) into the main repository, add the tasks/ ticket workflow directory, and include a TailwindCSS rebuild of www/public/layouts.css. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
node_modules is gitignored, but these 541 files were committed accidentally in da1ffa8 before the rule applied. Remove them from tracking; the directory stays on disk. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.