Skip to content

Conversation

@nahimterrazas
Copy link
Collaborator

@nahimterrazas nahimterrazas commented Jan 26, 2026

Summary by CodeRabbit

  • New Features

    • Wallet-based Admin API: nonce/types endpoints and signed admin actions (add token, update fees) with live-config reload.
    • Health endpoint and tokens endpoints that read live configuration.
  • Chores

    • Operator-centric, storage-backed runtime config with hot-reloadable shared config, storage readiness checks, atomic storage primitives, and a nonce store.
  • Tests

    • Expanded tests for signing/verification, nonce lifecycle, readiness, config merge, and serialization.
  • Bug Fixes

    • Hardened admin auth error responses to avoid leaking internal details.
  • Documentation

    • README updated with Admin API and Health usage.

@coderabbitai
Copy link

coderabbitai bot commented Jan 26, 2026

📝 Walkthrough

Walkthrough

Adds a wallet‑based Admin API with EIP‑712/personal_sign verification, nonce management, storage-backed OperatorConfig with optimistic locking, hot‑reloadable runtime Config (Arc<RwLock>), atomic storage primitives across backends, a /health readiness endpoint, and widespread call‑site/test updates.

Changes

Cohort / File(s) Summary
Admin API & DTOs
crates/solver-service/src/apis/admin.rs
New AdminApiState, endpoints (GET /nonce, GET /types, POST /tokens, PUT /fees), NonceResponse/AdminActionResponse/Eip712 DTOs, verifier rebuild/hot-reload logic, config_store persistence calls, serialization and tests.
Auth — admin subsystem
crates/solver-service/src/auth/admin/*, crates/solver-service/src/auth/mod.rs, crates/solver-service/src/auth/admin/error.rs
New admin auth module: signature recovery (personal_sign & hash), EIP‑712 types and SignedAdminRequest, AdminAction trait, AdminActionVerifier with nonce verification/atomic consume, AdminAuthError mapping and tests.
Nonce storage & exports
crates/solver-storage/src/nonce_store.rs, crates/solver-storage/src/lib.rs, crates/solver-storage/Cargo.toml
NonceStore abstraction (Memory/Redis), errors, creation helpers; crate root exports updated; chrono/uuid deps added.
OperatorConfig & config-store
crates/solver-types/src/operator_config.rs, crates/solver-storage/src/config_store.rs, crates/solver-types/src/lib.rs
Introduce OperatorConfig family and StorageConfigStore (StorageInterface‑backed ConfigStore), create_config_store(StoreConfig) factory, CONFIG_KEY_PREFIX, versioned JSON + optimistic compare‑and‑swap.
StorageInterface & backends
crates/solver-storage/src/lib.rs, crates/solver-storage/src/implementations/{redis,file,memory}.rs
Extend StorageInterface with atomic ops (set_nx, compare_and_swap, delete_if_exists, cleanup_expired); File/Memory/Redis implementations updated to support TTL‑aware entries and atomic semantics.
Removed legacy Redis config impl
crates/solver-storage/src/implementations/config/redis.rs, crates/solver-storage/src/implementations/config/mod.rs
Deleted previous RedisConfigStore implementation and re-export; migrated config‑store functionality to StorageConfigStore + StoreConfig.
Server bootstrap & hot‑reload wiring
crates/solver-service/src/main.rs, crates/solver-service/src/server.rs, crates/solver-service/src/config_merge.rs, crates/solver-service/src/factory_registry.rs
Startup seeds/loads OperatorConfig via storage, creates config_store and nonce_store, builds runtime Config, exposes shared Arc<RwLock> (dynamic_config), mounts admin routes and /health conditionally, passes dynamic_config into solver construction.
Solver core / engine snapshotting
crates/solver-core/src/builder/mod.rs, crates/solver-core/src/engine/mod.rs, crates/solver-core/src/engine/cost_profit.rs
Introduce dynamic_config (Arc<RwLock>) and static snapshot; builders/engine accept both and use static snapshot for wiring; cost logic reads solver.gas_buffer_bps from runtime config.
Tokens & API exposure
crates/solver-service/src/apis/tokens.rs, crates/solver-service/src/apis/mod.rs
Tokens endpoints read from shared Arc<RwLock>; exported new apis::admin and apis::health modules.
Seed/override types & config
crates/solver-types/src/auth.rs, crates/solver-types/src/seed_overrides.rs, config/seed-overrides-testnet.json
Add AdminConfig/AdminOverride and admin field on AuthConfig/SeedOverrides; testnet seed updated to include admin block and adjust solver_id.
Health & readiness
crates/solver-service/src/apis/health.rs, crates/solver-storage/src/redis_health.rs, crates/solver-storage/src/readiness/*
New /health endpoint and types (HealthResponse, RedisHealth), Redis persistence checks, readiness abstraction and RedisReadiness implementation, and supporting utilities/tests.
Call-sites & tests updates
multiple files (auth, order, quote, validators, intent, etc.)
Numerous call sites and tests updated to accept/pass shared_config (Arc<RwLock>); test fixtures adjusted.
Config builder / defaults
crates/solver-config/src/*, crates/solver-pricing/src/lib.rs
Added solver.gas_buffer_bps default into config builder and solver‑config; removed PricingConfig.gas_buffer_bps from pricing crate.
Docs & README
README.md
Documentation additions for Admin API and Health endpoints, examples and curl usage.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    actor Client
    participant API as rgba(63,81,181,0.5)
    participant Verifier as rgba(3,169,244,0.5)
    participant Nonce as rgba(76,175,80,0.5)
    participant Store as rgba(255,153,51,0.5)
    participant Crypto as rgba(233,30,99,0.5)

    Client->>API: GET /api/v1/admin/nonce
    API->>Verifier: generate_nonce()
    Verifier->>Nonce: generate()
    Nonce-->>Verifier: nonce + ttl
    Verifier-->>API: NonceResponse
    API-->>Client: NonceResponse

    Client->>Client: Sign action (EIP‑712 / personal_sign)
    Client->>API: POST /api/v1/admin/tokens (SignedAdminRequest)
    API->>Verifier: verify(action, signature)
    Verifier->>Nonce: exists(action.nonce)
    alt nonce valid
        Verifier->>Crypto: recover_from_hash(action_hash, signature)
        Crypto-->>Verifier: signer address
        Verifier->>Verifier: is_admin(address)
        Verifier->>Nonce: consume(nonce)
        alt admin authorized
            Verifier-->>API: verified signer
            API->>Store: load -> compare_and_swap update (operator config)
            Store-->>API: updated
            API-->>Client: AdminActionResponse(success)
        else not admin
            Verifier-->>API: AdminAuthError(NotAuthorized)
            API-->>Client: error
        end
    else invalid/used/expired nonce
        Verifier-->>API: AdminAuthError(nonce issue)
        API-->>Client: error
    end
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

Suggested reviewers

  • pepebndc
  • shahnami
  • NicoMolinaOZ

Poem

I nibble bytes beneath the moon,
nonces hop and signatures croon,
Redis burrows guard each key,
configs swap while hot‑reloads flee,
admins sign — the rabbit cheers with glee! 🐇✨

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Description check ⚠️ Warning The pull request description is entirely empty; no summary, testing information, or checklist items were provided by the author. Add a comprehensive description following the template: include a summary of changes, testing process, related issue reference (e.g., #268), and completed checklist items.
Title check ❓ Inconclusive The title '268 siwe admin auth module' is vague and uses a jargon-like reference ('268 SIWE') without clearly explaining what the PR does; it doesn't convey the main change (implementing admin authentication with EIP-712 and related infrastructure). Use a more descriptive title like 'Add SIWE-based admin authentication module with EIP-712 verification' or 'Implement wallet-based admin API with signature verification and nonce management'.
✅ Passed checks (1 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 268-siwe-admin-auth-module

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@nahimterrazas
Copy link
Collaborator Author

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Jan 26, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🤖 Fix all issues with AI agents
In `@crates/solver-service/src/apis/admin.rs`:
- Around line 85-94: The nonce handling is inconsistent: handle_get_nonce
returns a String but AddTokenContents expects a u64 (request.contents.nonce), so
change the API to use a consistent nonce type; choose one of the suggested fixes
and implement it across the codebase—either (A) change AddTokenContents.nonce
and all uses (including verifier.verify and nonce_string construction) to String
so the server and client pass the original nonce string unchanged, or (B) add a
separate field (e.g., original_nonce: String) to the request payload to carry
the exact string while keeping a numeric nonce for internal use, or (C) switch
generate_nonce to emit numeric-only nonces that safely convert to/from u64 and
update tests to use the returned nonce instead of hardcoding 1; update
handle_get_nonce, AddTokenContents, any tests that construct AddTokenContents,
and the call site building nonce_string before calling verifier.verify to match
the chosen approach.

In `@crates/solver-service/src/auth/admin/error.rs`:
- Around line 57-76: The IntoResponse implementation for AdminAuthError leaks
internal details by using self.to_string() for all variants; modify
into_response so that for AdminAuthError::Internal the
AdminAuthErrorResponse.error_description is a generic message like "internal
server error" (or similar) instead of the internal error string, and separately
log the detailed error server-side (e.g., using tracing::error! or the existing
logger) when matching AdminAuthError::Internal; keep all other variants'
error_description as self.to_string(); update the match arm or response
construction in the into_response method (referencing AdminAuthError::Internal,
into_response, and AdminAuthErrorResponse).

In `@crates/solver-service/src/auth/admin/types.rs`:
- Around line 219-250: The struct_hash implementation on WithdrawContents
silently maps invalid amount strings to zero via
U256::from_str_radix(...).unwrap_or(U256::ZERO); change
WithdrawContents::struct_hash to return Result<FixedBytes<32>, Error> (or a
crate error type) and propagate any parsing error from U256::from_str_radix
instead of defaulting to zero, updating the AdminAction trait signature for
struct_hash() to Result<FixedBytes<32>, Error> and adjust all callers to handle
the error; ensure you reference WithdrawContents::struct_hash, the
U256::from_str_radix call, and the AdminAction trait when making these changes.

In `@crates/solver-storage/src/nonce_store.rs`:
- Around line 110-115: The debug log currently prints self.redis_url which may
contain credentials; change the logging to redact or omit credentials before
logging (e.g., implement a small helper redact_redis_url(self.redis_url) or
parse with url::Url and replace the password with "<redacted>" or log only
host:port), then pass the redacted string to the debug! call that currently
includes redis_url and solver_id (the block that logs "Nonce store Redis
connection established" and returns Ok(Arc::new(manager))). Also apply the same
redaction to the other debug call mentioned (the similar debug! around the
second occurrence) so no raw redis URI is ever emitted.
- Around line 77-88: In NonceStore::new (pub fn new(redis_url: &str, solver_id:
&str, ttl_seconds: u64)), add a validation that rejects ttl_seconds == 0 and
return an appropriate NonceError::Configuration with a clear message (e.g., "TTL
seconds must be > 0") to prevent immediate nonce expiry; update the constructor
to check ttl_seconds before completing initialization and ensure any tests or
callers handle the new error case.
- Around line 21-27: The OnceCell currently stores Arc<ConnectionManager> which
causes Arc::make_mut to clone the inner ConnectionManager (bypassing caching);
change the OnceCell type to store ConnectionManager directly
(OnceCell<ConnectionManager>), initialize it with the ConnectionManager (no
Arc), remove all Arc::make_mut calls in get_connection and other helpers (e.g.,
places around lines referenced in the review) and instead return a cloned
ConnectionManager from the OnceCell when a caller needs a manager; update
callers of get_connection (and code paths at the noted locations) to
accept/handle a cloned ConnectionManager rather than an Arc-wrapped one so the
ConnectionManager reuse and cheap cloning semantics are preserved.

In `@crates/solver-types/src/auth.rs`:
- Around line 145-152: The is_admin method on AdminConfig currently ignores the
enabled flag and only checks admin_addresses, enabling auth bypass; update
AdminConfig::is_admin(&self, address: &Address) to first return false if
self.enabled is false, otherwise perform the existing
admin_addresses.iter().any(|a| a == address) check so callers of is_admin (e.g.,
signature/verify flows) respect the enabled toggle.
🧹 Nitpick comments (4)
crates/solver-storage/Cargo.toml (1)

27-27: Redundant uuid in dev-dependencies.

Since uuid is now listed under [dependencies] (line 27), it's automatically available for tests. The entry in [dev-dependencies] (line 35) is redundant and can be removed.

🧹 Suggested cleanup
 [dev-dependencies]
 tempfile = { workspace = true }
 futures = { workspace = true }
-uuid = { workspace = true }
 rust_decimal = { workspace = true }

Also applies to: 35-35

crates/solver-service/src/auth/admin/types.rs (1)

324-344: Prefer &[u8] over &Vec<u8> for function parameters.

Using &[u8] is more idiomatic and flexible as it accepts any slice-like type.

Proposed fix
-    pub fn serialize<S>(bytes: &Vec<u8>, serializer: S) -> Result<S::Ok, S::Error>
+    pub fn serialize<S>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error>
     where
         S: Serializer,
     {
crates/solver-service/src/apis/admin.rs (2)

96-104: Reminder: Address the TODO comment for token persistence.

The endpoint currently only logs the action without persisting the token configuration. This should be tracked as a follow-up task.

Do you want me to open an issue to track implementing the actual token persistence to the config store?


106-114: Use Display instead of Debug for the admin address.

alloy_primitives::Address implements Display to produce EIP-55 checksummed hex format (e.g., 0xd8dA6bf...), whereas format!("{:?}", admin) uses Debug which produces a different representation. Use format!("{}", admin) or admin.to_string() for consistency with line 99's tracing macro and to produce the expected checksummed hex output.

Proposed fix
     Ok(Json(AdminActionResponse {
         success: true,
         message: format!(
             "Token {} added to chain {}",
             request.contents.symbol, request.contents.chain_id
         ),
-        admin: format!("{:?}", admin),
+        admin: format!("{}", admin),
     }))

Base automatically changed from 267-config-store-with-seeding-fixed to main January 26, 2026 21:50
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@crates/solver-storage/src/nonce_store.rs`:
- Around line 8-18: The doc example currently passes &nonce to exists/consume
but the NonceStore API uses u64 nonces; update the example so the value returned
by NonceStore::generate (referenced as generate) is treated as a u64 and call
exists and consume with that u64 (e.g., exists(nonce) and consume(nonce)) rather
than &nonce, keeping NonceStore::new and the async flow unchanged.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@crates/solver-service/src/server.rs`:
- Around line 118-122: The chain_id selection is non-deterministic due to
HashMap iteration; change the assignment of chain_id (currently using
config.networks.keys().next().copied().unwrap_or(1)) to a deterministic choice
such as config.networks.keys().copied().min().unwrap_or(1) (or read an explicit
chain_id from config) so AdminActionVerifier receives a stable chain_id when
computing the EIP-712 domain separator and signature verification succeeds.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@crates/solver-core/src/builder/mod.rs`:
- Around line 60-64: The builder doc comment incorrectly suggests TokenManager
reads dynamic config; update the comment to clarify that the builder takes a
static snapshot of config and services created from it (including TokenManager,
which is constructed from static_config.networks) will NOT see hot-reload
changes, and only services explicitly implemented to read dynamic config at
runtime will observe hot-reloads; reference TokenManager and
static_config.networks in the reworded note so it’s clear TokenManager uses the
static snapshot rather than dynamic config.

In `@crates/solver-service/src/server.rs`:
- Around line 195-226: The code currently swallows create_nonce_store errors and
returns None, silently disabling admin routes; change the control flow so admin
initialization fails fast by returning an error when create_nonce_store returns
Err instead of logging and returning None. Update the caller/signature that
produces AdminApiState (currently returning Option<AdminApiState>) to return
Result<AdminApiState, E> (or propagate the error with ?), and in the Err(e)
branch of create_nonce_store return Err(e). Ensure the AdminApiState
construction (verifier, nonce_store, config_store, dynamic_config) remains
unchanged and include contextual error text when converting/propagating the
error.
🧹 Nitpick comments (1)
crates/solver-config/src/builders/config.rs (1)

41-47: Centralize the gas buffer default to avoid magic numbers.

💡 Suggested refactor
 use std::collections::HashMap;
 
+const DEFAULT_GAS_BUFFER_BPS: u32 = 1_000;
+
@@
 	pub fn new() -> Self {
 		Self {
 			solver_id: "test-solver".to_string(),
 			monitoring_timeout_seconds: 60,
 			min_profitability_pct: Decimal::ZERO,
-			gas_buffer_bps: 1000, // 10% default
+			gas_buffer_bps: DEFAULT_GAS_BUFFER_BPS, // 10% default
 			storage_primary: "memory".to_string(),

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@crates/solver-service/src/main.rs`:
- Around line 9-12: Remove the duplicated sentence in the crate-level
documentation comment at the top of main.rs (the module-level doc comment
starting with "The solver uses a storage backend..."); delete the extra repeated
line ("on subsequent startups.") so the documentation only contains the sentence
once and keep the surrounding paragraphs intact.
🧹 Nitpick comments (3)
crates/solver-storage/src/readiness/mod.rs (1)

233-247: Consider removing empty log statement.

Line 237 logs an empty string which adds visual noise without value. This is a minor cosmetic issue.

♻️ Suggested fix
 			tracing::error!("  STARTUP BLOCKED: Storage not ready");
 			tracing::error!("════════════════════════════════════════════════════════════");
-			tracing::error!("");
 			tracing::error!("  To fix:");
 			tracing::error!("  1. Address the failed checks above OR");
 			tracing::error!("  2. Set REQUIRE_PERSISTENCE=false (not recommended)");
-			tracing::error!("");
 			tracing::error!("  See docs/redis-persistence.md for instructions.");
crates/solver-service/src/apis/health.rs (2)

88-107: Consider caching StoreConfig in AppState instead of reading environment on each request.

StoreConfig::from_env() is called on every health check invocation, reading environment variables repeatedly. While environment variables are typically stable, this adds unnecessary overhead and could cause inconsistency if env vars change during runtime.

Consider storing StoreConfig in AppState during server initialization:

// In AppState (hypothetical):
pub struct AppState {
    pub config: Arc<RwLock<Config>>,
    pub store_config: StoreConfig,  // Add this
    // ...
}

// In handle_health:
let store_config = state.store_config.clone();

119-126: Consider using constants for check names to prevent silent failures from typos.

The string matching against "connectivity", "rdb_persistence", and "aof_persistence" is fragile. If the readiness checker changes these names, the health endpoint would silently report false values.

♻️ Extract constants (or import from readiness module)
// In readiness module or shared constants:
pub const CHECK_CONNECTIVITY: &str = "connectivity";
pub const CHECK_RDB_PERSISTENCE: &str = "rdb_persistence";
pub const CHECK_AOF_PERSISTENCE: &str = "aof_persistence";

// In health.rs:
match check.name.as_str() {
    CHECK_CONNECTIVITY => connected = check.passed,
    CHECK_RDB_PERSISTENCE => rdb_enabled = check.passed,
    CHECK_AOF_PERSISTENCE => aof_enabled = check.passed,
    _ => {},
}

@shahnami
Copy link
Collaborator

shahnami commented Feb 2, 2026

Changes look good! Just a few more questions

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Fix all issues with AI agents
In `@crates/solver-service/src/apis/admin.rs`:
- Around line 112-129: The JSON examples in the doc comments that show the
request body with "nonce" as a number must be changed to a string because the
API now returns/uses nonce as a string to preserve precision; update the "nonce"
field in the illustrated request body (the doc comment describing the
signature/contents block) and the other occurrence later in the same file so
they show e.g. "nonce": "12345678901234" (retain quotes) everywhere the request
example appears.

In `@crates/solver-service/src/apis/health.rs`:
- Around line 88-106: The health endpoint is returning raw error strings (e.g.,
the Err from StoreConfig::from_env serialized into HealthResponse.storage.error
and similarly in the Redis/other health branches), which can leak sensitive
internals; replace those direct e.to_string() usages with a sanitized public
message like "internal error" or "unavailable", move the full e (or context)
into a server-side log (use your existing logger or tracing::error) and
optionally add a helper sanitize_error_for_public(err: &anyhow::Error) -> String
used by HealthResponse; update the places that populate
HealthResponse.storage.error and the Redis-related health error to use the
sanitized message while logging the original error.
- Around line 69-87: The API docs above the handle_health function are out of
sync: update the example JSON in the doc comment to include the required
"storage" field (e.g., "storage":
{"backend":"Redis","ready":true,"checks":[],"details":{}}) and change the
status-code descriptions to reflect storage readiness (replace "Healthy (Redis
connected)" / "Unhealthy (Redis disconnected)" with "Healthy (storage ready)" /
"Unhealthy (storage not ready)"). Make these edits in the comment block
immediately preceding pub async fn handle_health(State(state): State<AppState>)
-> impl IntoResponse so the docs match the current response schema.

In `@crates/solver-storage/src/lib.rs`:
- Around line 395-424: redact_url_credentials currently only redacts when a
scheme ("scheme://") exists; update it to also redact schemeless userinfo by
detecting userinfo anywhere in the input. Specifically, in
redact_url_credentials: if the string contains an '@' and that '@' occurs before
the first '/' (or if no '/' exists), treat the substring before the '@' as
userinfo and replace it with "[REDACTED]" (preserving any scheme if present);
otherwise keep the existing logic (scheme-based redaction). This ensures inputs
like "user:pass@host:port" are redacted even without "scheme://".
- Around line 607-692: Tests that call StoreConfig::from_env mutate global
environment variables (STORAGE_BACKEND, REDIS_URL, STORAGE_PATH) without
restoring prior values, causing flakiness when run in parallel; wrap each
env-mutating test (e.g., test_store_config_from_env_redis_default,
test_store_config_from_env_redis_custom_url,
test_store_config_from_env_file_default_path,
test_store_config_from_env_file_custom_path, test_store_config_from_env_memory,
test_store_config_from_env_unsupported) with an env-guard that saves previous
values and restores them on drop or serialize the tests; implement a small test
helper (EnvGuard) used at the start of each test to snapshot and restore
STORAGE_BACKEND, REDIS_URL, STORAGE_PATH (or use an existing crate like temp_env
or add #[serial] via serial_test) and ensure every test that mutates env calls
the guard so StoreConfig::from_env reads deterministic values and no global
state leaks between tests.

Copy link
Collaborator

@shahnami shahnami left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still think the whole "storage readiness" is a bit strange (I can't pinpoint it), but fine for now. LGTM, thanks for your hard work!

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@crates/solver-demo/.env.example`:
- Line 19: The file ends without a trailing newline which fails dotenv-linter;
update the .env example by adding a single newline at end of file so the
JWT_SECRET=MySuperDuperSecureSecret123! line is terminated with a trailing
newline character (ensure the file ends with that newline).
🧹 Nitpick comments (1)
crates/solver-demo/.env.example (1)

19-19: Use a placeholder JWT secret to avoid accidental reuse in real deployments.

Keeping a real-looking secret in .env.example can lead to copy‑paste into production. Consider a clear placeholder and note that it must be replaced.

📝 Proposed change
-JWT_SECRET=MySuperDuperSecureSecret123!
+JWT_SECRET=change-me-in-prod

@nahimterrazas nahimterrazas merged commit 3d14302 into main Feb 3, 2026
17 of 20 checks passed
@nahimterrazas nahimterrazas deleted the 268-siwe-admin-auth-module branch February 3, 2026 12:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants