Skip to content

Move feature flags and faucet config into /api/config#52

Merged
tac0turtle merged 3 commits intomainfrom
pthmas/faucet-info-404
Apr 9, 2026
Merged

Move feature flags and faucet config into /api/config#52
tac0turtle merged 3 commits intomainfrom
pthmas/faucet-info-404

Conversation

@pthmas
Copy link
Copy Markdown
Collaborator

@pthmas pthmas commented Apr 8, 2026

Summary

  • move DA and faucet capability metadata into /api/config, and keep /api/height limited to height data
  • reuse the shared frontend config state for feature gating so page reloads stop probing /api/faucet/info from the global layout
  • keep the faucet page fetching live faucet info only when the faucet is enabled

Validation

  • cargo test -p atlas-server
  • bunx tsc --noEmit

Summary by CodeRabbit

  • New Features

    • Faucet configuration (enabled, optional amount, optional cooldown) and chain features (DA tracking) now come from the central config API and are exposed to the UI; branding normalization fills safe defaults.
  • Refactor

    • Faucet info flow simplified: removed legacy context plumbing, now reads branding + guarded faucet hook; faucet nav and page rendering respect the centralized faucet state and loading.
  • Style

    • Consistent string quoting and minor formatting cleanup.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 8, 2026

📝 Walkthrough

Walkthrough

This PR adds chain feature flags and faucet configuration to the /api/config payload, moves DA-tracking out of /status, wires new faucet fields through server AppState and runtime, and updates frontend types, normalization, context, hooks, and pages to consume the new features and faucet properties.

Changes

Cohort / File(s) Summary
Backend Config & AppState
backend/crates/atlas-server/src/api/handlers/config.rs, backend/crates/atlas-server/src/api/mod.rs
Add ChainFeatures and FaucetConfig response structs; extend BrandingConfig with features and faucet; add faucet_amount_wei and faucet_cooldown_minutes to AppState.
Backend Runtime & Tests
backend/crates/atlas-server/src/main.rs, backend/crates/atlas-server/tests/integration/common.rs
Derive faucet_amount_wei/faucet_cooldown_minutes from runtime config and populate AppState; test router helpers initialize new fields to None.
Backend Handler Tests / Status
backend/crates/atlas-server/src/api/handlers/{faucet.rs,health.rs,metrics.rs,status.rs}
Update test AppState constructors for new faucet fields; remove ChainFeatures export and features from status/height response and associated assertions.
Frontend Config API
frontend/src/api/config.ts
Add FaucetConfig type and require features/faucet on BrandingConfig; add normalizeBrandingConfig and helpers; update getConfig() to fetch partial payload and return normalized config.
Frontend Branding Context & Provider
frontend/src/context/branding-context.ts, frontend/src/context/branding.ts, frontend/src/context/BrandingContext.tsx
Add features and faucet to BrandingContextValue and defaults; include features/faucet when resolving branding; cache reads use normalizeBrandingConfig.
Frontend Faucet & Features Hooks
frontend/src/hooks/useFaucetInfo.ts, frontend/src/hooks/useFeatures.ts
useFaucetInfo(enabled = true) adds enablement guard, request-versioning, stale-result protection; useFeatures simplified to return useBranding().features.
Frontend Pages / Components
frontend/src/pages/FaucetPage.tsx, frontend/src/components/Layout.tsx, frontend/src/context/FaucetInfoContext.tsx
Remove FaucetInfoContext; FaucetPage and Layout now read faucet config from branding and use useFaucetInfo(faucet.enabled) / conditional rendering; deleted context module.
Frontend API Types & Misc
frontend/src/api/status.ts, frontend/src/types/index.ts, various small files
Remove features from HeightResponse; normalize/standardize string-quote styles; minor formatting and type refinements across files.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant Frontend
  participant Server
  participant AppState

  Client->>Frontend: open app / Faucet page
  Frontend->>Server: GET /api/config
  Server->>AppState: read branding + features + faucet fields
  AppState-->>Server: return config state
  Server-->>Frontend: 200 JSON (branding + features + faucet)
  Frontend->>Frontend: normalizeBrandingConfig(...)
  Frontend->>BrandingContext: set branding (features, faucet, loaded)
  Frontend->>FaucetHook: useFaucetInfo(faucet.enabled)
  Note right of Frontend: Components render based on faucet.enabled and fetched info
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • tac0turtle

Poem

🐇 I nibble code and hop with glee,
Features, faucet, tucked in tree;
Server whispers config true,
Frontend fluffs the branding through,
Hop — the app is snug and free!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 36.36% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the main change: moving feature flags and faucet configuration from separate endpoints into the /api/config endpoint.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch pthmas/faucet-info-404

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.

Copy link
Copy Markdown

@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: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@frontend/src/api/config.ts`:
- Around line 20-25: getConfig() currently returns the raw /config response
typed as BrandingConfig but does no runtime validation; update getConfig to
normalize and validate the returned object so required fields are always
present: call client.get("/config"), verify that features exists and is an
object (fallback to a default ChainFeatures object) and that faucet exists and
matches FaucetConfig shape (fallback to { enabled: false, ...defaultProps }),
then return a fully populated BrandingConfig; reference the getConfig function
and the BrandingConfig/ChainFeatures/FaucetConfig types and ensure consumers
like Layout.tsx and FaucetPage.tsx can safely access faucet.enabled without
runtime errors.

In `@frontend/src/hooks/useFaucetInfo.ts`:
- Around line 37-53: The async handler in useFaucetInfo can let a response from
an earlier request overwrite state after enabled flips false; add a
request-version guard: create a mutable request counter/ref (e.g., requestIdRef)
that you increment when a new fetch starts in the function that calls
getFaucetInfo and capture the current id in the try block, then before calling
setFaucetInfo, setNotFound, setError, or setLoading check that the captured id
=== requestIdRef.current and skip state updates if it differs (also ensure the
guard handles the background flag similarly). Update functions referenced in the
diff (getFaucetInfo call and the setFaucetInfo / setNotFound / setError /
setLoading calls) to respect this request-id check so late in-flight responses
are ignored.

In `@frontend/src/pages/FaucetPage.tsx`:
- Around line 33-36: The NotFoundPage is rendering prematurely because
brandingDefaults initializes faucet.enabled=false; update the render logic to
wait for branding to finish loading from useBranding before treating notFound as
a 404: use the branding "loaded" (or similarly named) flag returned by
useBranding and gate the notFound/404 branch with it (i.e. only show
NotFoundPage when loaded && notFound). Apply the same change to the other
NotFound branch referenced (the block around the later faucet rendering at lines
~98-104) so both places check the branding loaded flag in addition to notFound.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6ad890fa-6085-4d8d-b6b8-7dcb0637aa82

📥 Commits

Reviewing files that changed from the base of the PR and between 54cc935 and f6ad69d.

📒 Files selected for processing (18)
  • backend/crates/atlas-server/src/api/handlers/config.rs
  • backend/crates/atlas-server/src/api/handlers/faucet.rs
  • backend/crates/atlas-server/src/api/handlers/health.rs
  • backend/crates/atlas-server/src/api/handlers/metrics.rs
  • backend/crates/atlas-server/src/api/handlers/status.rs
  • backend/crates/atlas-server/src/api/mod.rs
  • backend/crates/atlas-server/src/main.rs
  • backend/crates/atlas-server/tests/integration/common.rs
  • frontend/src/api/config.ts
  • frontend/src/api/status.ts
  • frontend/src/components/Layout.tsx
  • frontend/src/context/FaucetInfoContext.tsx
  • frontend/src/context/branding-context.ts
  • frontend/src/context/branding.ts
  • frontend/src/hooks/useFaucetInfo.ts
  • frontend/src/hooks/useFeatures.ts
  • frontend/src/pages/FaucetPage.tsx
  • frontend/src/types/index.ts
💤 Files with no reviewable changes (1)
  • frontend/src/context/FaucetInfoContext.tsx

Copy link
Copy Markdown

@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

🧹 Nitpick comments (1)
frontend/src/api/config.ts (1)

58-61: Normalize the optional branding strings too.

This function now hardens features and faucet, but ...config still passes logo_url* and color fields through unchanged. Since this normalizer now sits on both the /config and cached-config path, it would be safer to whitelist the existing optional string fields here as well.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/api/config.ts` around lines 58 - 61, The returned config still
spreads unvalidated branding fields; extend the normalizer to whitelist and
sanitize optional branding strings (e.g. logo_url, logo_url_dark, favicon_url,
and any theme/accent color fields) instead of passing them via ...config. Add a
small helper (or reuse existing normalizers) and invoke it alongside
normalizeFeatures and normalizeFaucet (e.g. normalizeBranding(config)) to coerce
non-string values to null/empty-string and strip unexpected keys so only the
allowed branding string/color fields are returned.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@frontend/src/api/config.ts`:
- Around line 49-50: The current check uses typeof faucet.cooldown_minutes ===
"number" which allows NaN, Infinity, negatives and fractions; change the
validation for cooldown_minutes in frontend/src/api/config.ts to only accept
finite, non-negative integers by replacing that predicate with a stricter one
such as Number.isFinite(faucet.cooldown_minutes) && faucet.cooldown_minutes >= 0
&& Number.isInteger(faucet.cooldown_minutes), and ensure the normalized object
includes cooldown_minutes only when that condition passes (refer to the existing
faucet.cooldown_minutes usage in the normalizer).

In `@frontend/src/hooks/useFaucetInfo.ts`:
- Around line 41-45: The background refresh success path in useFaucetInfo
(inside the try where getFaucetInfo() returns and you call setFaucetInfo(info))
must also clear any previously latched failure flags so the UI unblocks; after
verifying requestVersion === requestVersionRef.current and calling
setFaucetInfo(info), reset the error and notFound flags (e.g. call the relevant
setters such as setError(null/undefined) and setNotFound(false) or whatever
state setters you have for those flags) so a successful background refetch
clears earlier failures.

---

Nitpick comments:
In `@frontend/src/api/config.ts`:
- Around line 58-61: The returned config still spreads unvalidated branding
fields; extend the normalizer to whitelist and sanitize optional branding
strings (e.g. logo_url, logo_url_dark, favicon_url, and any theme/accent color
fields) instead of passing them via ...config. Add a small helper (or reuse
existing normalizers) and invoke it alongside normalizeFeatures and
normalizeFaucet (e.g. normalizeBranding(config)) to coerce non-string values to
null/empty-string and strip unexpected keys so only the allowed branding
string/color fields are returned.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 89c93471-201b-4c39-8bd8-e50562c376b7

📥 Commits

Reviewing files that changed from the base of the PR and between f6ad69d and d4bd791.

📒 Files selected for processing (4)
  • frontend/src/api/config.ts
  • frontend/src/context/BrandingContext.tsx
  • frontend/src/hooks/useFaucetInfo.ts
  • frontend/src/pages/FaucetPage.tsx
✅ Files skipped from review due to trivial changes (1)
  • frontend/src/context/BrandingContext.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/src/pages/FaucetPage.tsx

Copy link
Copy Markdown

@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.

🧹 Nitpick comments (1)
frontend/src/api/config.ts (1)

24-25: Avoid returning shared default object instances.

Line 29 and Line 40 return module-level default objects by reference. Returning fresh objects avoids accidental cross-call mutation if any consumer mutates the normalized result.

♻️ Suggested hardening
-const defaultFeatures: ChainFeatures = { da_tracking: false };
-const defaultFaucet: FaucetConfig = { enabled: false };
+const makeDefaultFeatures = (): ChainFeatures => ({ da_tracking: false });
+const makeDefaultFaucet = (): FaucetConfig => ({ enabled: false });

 function normalizeFeatures(value: unknown): ChainFeatures {
   if (!value || typeof value !== "object") {
-    return defaultFeatures;
+    return makeDefaultFeatures();
   }
@@
 function normalizeFaucet(value: unknown): FaucetConfig {
   if (!value || typeof value !== "object") {
-    return defaultFaucet;
+    return makeDefaultFaucet();
   }

Also applies to: 29-30, 39-41

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/api/config.ts` around lines 24 - 25, defaultFeatures and
defaultFaucet are module-level objects returned by reference; change the code to
return fresh objects instead of the shared instances to prevent accidental
cross-call mutation—either replace the constants with factory functions (e.g.,
getDefaultFeatures(), getDefaultFaucet()) that create and return new objects, or
always return shallow copies (e.g., {...defaultFeatures}, {...defaultFaucet})
where the normalized result is produced (refer to the constants defaultFeatures
and defaultFaucet to locate the code paths that currently return them).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@frontend/src/api/config.ts`:
- Around line 24-25: defaultFeatures and defaultFaucet are module-level objects
returned by reference; change the code to return fresh objects instead of the
shared instances to prevent accidental cross-call mutation—either replace the
constants with factory functions (e.g., getDefaultFeatures(),
getDefaultFaucet()) that create and return new objects, or always return shallow
copies (e.g., {...defaultFeatures}, {...defaultFaucet}) where the normalized
result is produced (refer to the constants defaultFeatures and defaultFaucet to
locate the code paths that currently return them).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 06d85049-39f2-45ed-aa33-9f03d790813f

📥 Commits

Reviewing files that changed from the base of the PR and between d4bd791 and 134609b.

📒 Files selected for processing (2)
  • frontend/src/api/config.ts
  • frontend/src/hooks/useFaucetInfo.ts
✅ Files skipped from review due to trivial changes (1)
  • frontend/src/hooks/useFaucetInfo.ts

@pthmas pthmas self-assigned this Apr 8, 2026
@pthmas pthmas requested a review from tac0turtle April 8, 2026 19:38
@tac0turtle tac0turtle merged commit e1b3e31 into main Apr 9, 2026
10 checks passed
@tac0turtle tac0turtle deleted the pthmas/faucet-info-404 branch April 9, 2026 06:20
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.

2 participants