Skip to content

✨ Added OpenFeature card#1670

Closed
xonas1101 wants to merge 15 commits intokubestellar:mainfrom
xonas1101:card-open-feature
Closed

✨ Added OpenFeature card#1670
xonas1101 wants to merge 15 commits intokubestellar:mainfrom
xonas1101:card-open-feature

Conversation

@xonas1101
Copy link
Copy Markdown
Collaborator

📌 Fixes

Fixes kubestellar/console-marketplace#49


📝 Summary of Changes

Added Open Feature card


Changes Made

  • Updated/Added OpenFeature card
  • Refactored ...
  • Fixed ...
  • Added tests for ...

Checklist

Please ensure the following before submitting your PR:

  • I have reviewed the project's contribution guidelines.
  • I have written unit tests for the changes (if applicable).
  • I have updated the documentation (if applicable).
  • I have tested the changes locally and ensured they work as expected.
  • My code follows the project's coding standards.

Screenshots or Logs (if applicable)


👀 Reviewer Notes

Add any special notes for the reviewer here

Copilot AI review requested due to automatic review settings March 5, 2026 05:04
@kubestellar-prow kubestellar-prow Bot added dco-signoff: yes Indicates the PR's author has signed the DCO. size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Mar 5, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 5, 2026

👋 Hey @xonas1101 — thanks for opening this PR!

🤖 This project is developed exclusively using AI coding assistants.

Please do not attempt to code anything for this project manually.
All contributions should be authored using an AI coding tool such as:

This ensures consistency in code style, architecture patterns, test coverage,
and commit quality across the entire codebase.


This is an automated message.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 5, 2026

Welcome to KubeStellar! 🚀 Thank you for submitting this Pull Request.

Before your PR can be merged, please ensure:

DCO Sign-off - All commits must be signed off with git commit -s to certify the Developer Certificate of Origin

PR Title - Must start with an emoji: ✨ (feature), 🐛 (bug fix), 📖 (docs), 🌱 (infra/tests), ⚠️ (breaking change)

Getting Started with KubeStellar:

Contributor Resources:


🌟 Help KubeStellar Grow - We Need Adopters!

Our roadmap is driven entirely by adopter feedback. Whether you're using KubeStellar yourself or know someone who could benefit from multi-cluster Kubernetes:

📋 Take our Multi-Cluster Survey - Share your use cases and help shape our direction!


A maintainer will review your PR soon. Feel free to ask questions in the comments or on Slack!

@netlify
Copy link
Copy Markdown

netlify Bot commented Mar 5, 2026

Deploy Preview for kubestellarconsole ready!

Built without sensitive environment variables

Name Link
🔨 Latest commit 6c82b03
🔍 Latest deploy log https://app.netlify.com/projects/kubestellarconsole/deploys/69b392a8a32d160008595613
😎 Deploy Preview https://deploy-preview-1670.console-deploy-preview.kubestellar.io
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@xonas1101 xonas1101 changed the title Added OpenFeature card ✨ Added OpenFeature card Mar 5, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a new OpenFeature status dashboard card to the KubeStellar Console frontend and wires it into the card catalog/registry so it can be added from the UI (and via a preset).

Changes:

  • Added openfeature_status card implementation (UI + data hook + demo data).
  • Registered the new card type in the card registry, demo-data set, preloaders, and default widths.
  • Exposed the card in the “Add Card” modal and added a CNCF preset JSON.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
web/src/components/dashboard/AddCardModal.tsx Adds a new “App Definition” category and surfaces the OpenFeature card in the add-card catalog.
web/src/components/cards/openfeature_status/useOpenFeatureStatus.ts Fetches pod data from /api/mcp/pods, detects OpenFeature-related pods, and computes simplified health/provider status.
web/src/components/cards/openfeature_status/OpenFeatureStatus.tsx Renders the OpenFeature status card UI (health badge, tiles, provider list, and empty/error states).
web/src/components/cards/openfeature_status/demoData.ts Provides demo-mode sample data for the OpenFeature card.
web/src/components/cards/openfeature_status/index.ts Barrel export for the card component.
web/src/components/cards/cardRegistry.ts Registers openfeature_status for lazy loading, demo-data tagging, preloading, and default sizing.
presets/cncf-openfeature.json Adds a preset entry for OpenFeature under the “App Definition” CNCF category.

'Utilities': 'utilities',
'Misc': 'misc',
'Runtime': 'runtime',
'App Definition': 'appDefinition',
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

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

New category uses i18n key cards:categories.appDefinition, but that key doesn't exist in locale files (e.g. web/src/locales/en/cards.json). As a result, non-English locales will fall back to the raw English category label; please add appDefinition to the cards.categories section across locales (at least en) so the category is properly localized.

Suggested change
'App Definition': 'appDefinition',

Copilot uses AI. Check for mistakes.
Comment on lines +11 to +16
if (isNaN(diff) || diff < 0) return t('openfeature.syncedJustNow', { defaultValue: 'just now' })
const minute = 60_000
const hour = 60 * minute
const day = 24 * hour
if (diff < minute) return t('openfeature.syncedJustNow', { defaultValue: 'just now' })
if (diff < hour) return t('openfeature.syncedMinutesAgo', { count: Math.floor(diff / minute), defaultValue: `${Math.floor(diff / minute)}m ago` })
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

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

This card relies heavily on t('openfeature.*', { defaultValue: ... }), and there are currently no openfeature entries in web/src/locales/en/cards.json. To keep i18n consistent with other cards (e.g., Contour/CRI-O) and avoid hardcoded English fallbacks, add the openfeature.* strings to the locale JSON files and drop the inline defaultValue usage.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator

@clubanderson clubanderson left a comment

Choose a reason for hiding this comment

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

1599 ✨ Added lima card xonas1101
1525 🌱 test: enforce structural integrity of card registry and lazy-loaded c… mrhapile

Copy link
Copy Markdown
Collaborator

@clubanderson clubanderson left a comment

Choose a reason for hiding this comment

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

Review: OpenFeature Card

Good implementation! One minor note:

Suggestion

There appears to be a magic number for the error rate threshold. Per project conventions, numeric literals should use named constants with comments (e.g., const ERROR_RATE_THRESHOLD_PCT = 5 // percentage above which to show warning). Not blocking but would be nice to fix.

Approved.

@kubestellar-prow kubestellar-prow Bot added the lgtm Indicates that a PR is ready to be merged. label Mar 5, 2026
Copy link
Copy Markdown
Collaborator

@clubanderson clubanderson left a comment

Choose a reason for hiding this comment

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

Good card — follows established patterns well. A few items to address:

1. Magic number (blocking per project policy) — In OpenFeatureStatus.tsx:

{hasFlags && data.featureFlags.errorRate > 5 && (

Should be a named constant:

const ERROR_RATE_WARNING_PCT = 5 // Show warning when error rate exceeds this percentage

2. Missing persist: true in useCache — Every comparable status card (CRI-O, Contour, Flatcar, Thanos) passes persist: true to useCache. Without it, cached data won't survive page refreshes. Please add it.

3. Unnecessary effectiveIsDemoFallback guard — The hook does:

const effectiveIsDemoFallback = cacheResult.isDemoFallback && !cacheResult.isLoading

No other card does this. The standard pattern passes isDemoFallback directly. Please align with:

isDemoData: cacheResult.isDemoFallback,

4. Demo data magic number (minor)90 * 1000 in demoData.ts should be const DEMO_LAST_CHECK_OFFSET_MS = 90_000.

@kubestellar-prow kubestellar-prow Bot removed the lgtm Indicates that a PR is ready to be merged. label Mar 5, 2026
@kubestellar-prow kubestellar-prow Bot requested a review from clubanderson March 5, 2026 20:07
@kubestellar-prow
Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please ask for approval from clubanderson. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@kubestellar-prow kubestellar-prow Bot added needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. and removed size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Mar 6, 2026
@xonas1101 xonas1101 force-pushed the card-open-feature branch from a2e0e53 to 2fdd710 Compare March 6, 2026 03:24
@kubestellar-prow kubestellar-prow Bot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Mar 6, 2026
Copy link
Copy Markdown
Collaborator

@clubanderson clubanderson left a comment

Choose a reason for hiding this comment

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

Good work on the OpenFeature card — the code quality, hook wiring (isDemoData, useCache, useCardLoadingState), i18n coverage, and CNCF preset are all solid.

However, the branch has unresolved merge conflict markers in cardRegistry.ts and cards.json that break the build. Please:

  1. Rebase onto current main and resolve all merge conflicts (the Fluentd card was merged since this branch was created — both entries should coexist)
  2. Push the rebased branch and verify CI passes

Once the conflicts are resolved, this should be ready to merge. Thanks!

@kubestellar-prow kubestellar-prow Bot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Mar 7, 2026
@xonas1101 xonas1101 force-pushed the card-open-feature branch from 2fdd710 to df3a7c5 Compare March 7, 2026 11:15
@kubestellar-prow kubestellar-prow Bot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Mar 7, 2026
@clubanderson
Copy link
Copy Markdown
Collaborator

PR Review — OpenFeature Card

Critical Issues

1. Missing cardMetadata.ts entry
web/src/components/cards/cardMetadata.tsCARD_TITLES and CARD_DESCRIPTIONS are missing entries for openfeature_status. If i18n fails to load, the fallback chain becomes '' || '' || 'openfeature_status', displaying the raw card type ID to users.

Fix: Add to both maps in cardMetadata.ts:

openfeature_status: 'OpenFeature',  // CARD_TITLES
openfeature_status: 'OpenFeature flag evaluation status and provider health.',  // CARD_DESCRIPTIONS

Important Issues

2. Duplicate i18n keys for relative-time strings
This is the 4th copy of syncedJustNow/MinutesAgo/HoursAgo/DaysAgo keys (same as lima, fluentd, flatcar). The useFormatRelativeTime() function is also duplicated. Consider extracting a shared utility.

3. Missing isRefreshing in hook return type
useOpenFeatureStatus.ts — The UseOpenFeatureStatusResult interface and return value don't expose isRefreshing. Per CLAUDE.md convention, every card hook must expose isRefreshing. The fluentd/lima hooks do this correctly.

Fix:

export interface UseOpenFeatureStatusResult {
  data: OpenFeatureStatus
  error: boolean
  isRefreshing: boolean  // Add this
  showSkeleton: boolean
  showEmptyState: boolean
}

4. Unrelated change bundledfluentd_status preloader entry in cardRegistry.ts is unrelated to OpenFeature.

What Looks Good

  • cardRegistry.ts wiring is complete (all 4 registration points)
  • isDemoData correctly wired via cacheResult.isDemoFallback to useCardLoadingState
  • Error handling with AbortSignal.timeout(FETCH_DEFAULT_TIMEOUT_MS) — no magic numbers
  • Guards against undefined: Array.isArray(body?.pods), pod.labels ?? {}
  • ERROR_RATE_WARNING_PCT constant avoids magic number
  • i18n keys registered in cards.json with title, description, and category
  • New "App Definition" category properly added to CARD_CATALOG and CATEGORY_LOCALE_KEYS
  • Preset JSON file follows standard format

@clubanderson
Copy link
Copy Markdown
Collaborator

@xonas1101 Review posted above — a few items to address, the main one being a missing cardMetadata.ts entry and missing isRefreshing in the hook return type. Please take a look!

@kubestellar-prow kubestellar-prow Bot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Mar 8, 2026
@xonas1101 xonas1101 force-pushed the card-open-feature branch from a8dd6ad to 8cd95ca Compare March 8, 2026 06:08
Copy link
Copy Markdown
Collaborator

@clubanderson clubanderson left a comment

Choose a reason for hiding this comment

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

Two critical regressions need fixing before this can merge:

Critical:

  1. lima_status title key DELETED from EN locale — The diff shows "lima_status": "Lima" was REPLACED with "openfeature_status": "OpenFeature" instead of adding alongside. This breaks the Lima card's title (it'll show the raw card type ID). Both lines must exist.

  2. Shared formatters.ts i18n key changecreateRelativeTimeFormatter was changed from common.justNow/common.minutesAgo to time.justNow/time.minutesAgo. This is a shared utility used by other cards. Unless time.* keys were added to common.json in all locales, this breaks relative-time formatting across the board.

Important:

  1. Missing isDemoFallback && !isLoading guard — The KEDA card (same author) correctly uses this guard; OpenFeature passes isDemoFallback directly, which can flash demo data during initial load.

  2. isRefreshing exposed but not used — The hook returns it but the RefreshCw icon doesn't animate. KEDA does this correctly with ${isRefreshing ? 'animate-spin' : ''}.

  3. Unrelated Lima locale changes — All 9 locale files have Lima section modifications/additions that aren't related to OpenFeature. These should be in a separate PR or reverted.

Please fix the lima_status deletion and the formatters.ts regression first — those affect other cards.

@clubanderson clubanderson mentioned this pull request Mar 11, 2026
9 tasks
Copy link
Copy Markdown
Collaborator

@clubanderson clubanderson left a comment

Choose a reason for hiding this comment

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

Card structure and code quality are solid, but there are several issues that need attention before merge:

  1. Accidentally deletes Lima card's locale title — In en/cards.json, the lima_status entry in the titles section is replaced with openfeature_status instead of being added alongside it. This will break the Lima card's title display. Please add openfeature_status as an additional entry, not a replacement.

  2. Missing OpenFeature locale keys in ALL 8 non-English locales — The openfeature translation section is only added to en/cards.json. None of the non-English locale files (de, es, fr, hi, it, ja, pt, zh) have the openfeature keys. The component will show raw translation keys for non-English users.

  3. Unrelated Lima locale additions bundled in this PR — A lima section is added to all 8 non-English locale files. This is out of scope for an OpenFeature card PR. Please remove and submit separately if needed.

  4. Unrelated change to createRelativeTimeFormatter in formatters.ts — Changes i18n key prefix from common.* to time.*. This is a shared utility fix that should be in its own PR.

  5. isRefreshing not passed to useCardLoadingState — Same issue as your other card PRs. Add isRefreshing: cacheResult.isRefreshing to the useCardLoadingState call.

  6. isDemoFallback not guarded during loading — Pass isDemoData: cacheResult.isDemoFallback && !cacheResult.isLoading instead of isDemoData: cacheResult.isDemoFallback to prevent flashing demo data instead of the loading skeleton.

Please address these and re-request review.

@kubestellar-prow kubestellar-prow Bot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Mar 12, 2026
Signed-off-by: xonas1101 <aarushsingh1305@gmail.com>
Signed-off-by: xonas1101 <aarushsingh1305@gmail.com>
Signed-off-by: xonas1101 <aarushsingh1305@gmail.com>
Signed-off-by: xonas1101 <aarushsingh1305@gmail.com>
Signed-off-by: xonas1101 <aarushsingh1305@gmail.com>
Signed-off-by: xonas1101 <aarushsingh1305@gmail.com>
Signed-off-by: xonas1101 <aarushsingh1305@gmail.com>
Signed-off-by: xonas1101 <aarushsingh1305@gmail.com>
Signed-off-by: xonas1101 <aarushsingh1305@gmail.com>
Signed-off-by: xonas1101 <aarushsingh1305@gmail.com>
Signed-off-by: xonas1101 <aarushsingh1305@gmail.com>
Signed-off-by: xonas1101 <aarushsingh1305@gmail.com>
@kubestellar-prow kubestellar-prow Bot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Mar 12, 2026
Signed-off-by: xonas1101 <aarushsingh1305@gmail.com>
@xonas1101
Copy link
Copy Markdown
Collaborator Author

/cc @clubanderson I have tried all changes with Claude Opus 4.6 this time.

Signed-off-by: xonas1101 <aarushsingh1305@gmail.com>
@xonas1101
Copy link
Copy Markdown
Collaborator Author

@clubanderson checked everything for this as well. It should be fine now.

Signed-off-by: xonas1101 <aarushsingh1305@gmail.com>
Copy link
Copy Markdown
Collaborator

@clubanderson clubanderson left a comment

Choose a reason for hiding this comment

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

Same feedback as #1694 (KEDA card) applies here:

1. Live data is hollow

In live mode, featureFlags returns all zeros (total: 0, enabled: 0, disabled: 0, errorRate: 0), totalEvaluations: 0, and all provider evaluations: 0, cacheHitRate: 0. The only real data is pod health. The card needs to support both demo and live data — the flag counts, evaluation metrics, error rates, and cache hit rates are the most valuable parts of the card and they're all empty in live mode.

2. Scope creep in cardRegistry.ts

This PR adds lazy imports and registrations for FluentdStatus, LimaStatus — plus flatcar_status, thanos_status, contour_status, fluentd_status, lima_status entries in DEMO_DATA_CARDS, CARD_CHUNK_PRELOADERS, and CARD_DEFAULT_WIDTHS. Also adds a Runtime category in AddCardModal.tsx with wasmcloud/crio/lima. None of this belongs in an OpenFeature PR — please remove and keep this scoped to OpenFeature only.

3. Rebase needed

Build Frontend is failing — likely merge conflicts in cardRegistry.ts. Please rebase onto current main.

4. Unrelated Lima locale changes

en/cards.json modifies Lima strings (notDetectedHint, totalCpu, totalMemory, instances, openDocs) — these don't belong in this PR.

5. Non-EN locales untranslated

DE, ES, FR, HI, IT, JA openfeature.* keys have English strings for the main labels (healthy, degraded, notInstalled, providers, etc.). Only the time-relative strings are translated. Either translate properly or remove the non-EN openfeature sections and let i18next fall back to EN.

6. useFormatRelativeTime duplication (non-blocking)

Same helper duplicated across lima, fluentd, flatcar, KEDA, and now OpenFeature. Consider using the shared formatter from formatters.ts.

@clubanderson clubanderson mentioned this pull request Mar 13, 2026
9 tasks
@clubanderson
Copy link
Copy Markdown
Collaborator

Consolidated Review — All Remaining Items (Final)

@xonas1101 — This PR has been through 9 review rounds. Here's one consolidated checklist of everything that still needs fixing. Please address all of these in a single push to avoid further back-and-forth.

Critical

  • Live data is hollow — In live mode: featureFlags all zeros, totalEvaluations: 0, all provider evaluations: 0, cacheHitRate: 0. Only pod health is real. The card needs to support both demo and live data — flag counts, evaluation metrics, error rates, and cache hit rates are all empty in live mode.
  • Scope creep in cardRegistry.ts — Remove ALL entries not related to OpenFeature: FluentdStatus, LimaStatus lazy imports, plus flatcar_status, thanos_status, contour_status, fluentd_status, lima_status in DEMO_DATA_CARDS, CARD_CHUNK_PRELOADERS, CARD_DEFAULT_WIDTHS. Also remove the Runtime category with wasmcloud/crio/lima from AddCardModal.tsx.
  • Accidentally deletes Lima card's locale title — In en/cards.json, lima_status title is replaced with openfeature_status instead of adding alongside. Both must exist.
  • Rebase needed — Build Frontend is failing. Rebase onto current main.

Must Fix

  • Unrelated Lima locale changes — Remove all Lima section modifications from all 9 locale files. Submit separately if needed.
  • Unrelated formatters.ts change — The createRelativeTimeFormatter key change from common.* to time.* is a shared utility fix that should be in its own PR.
  • Missing isRefreshing in useCardLoadingState call — Pass isRefreshing to useCardLoadingState().
  • Missing isDemoFallback && !isLoading guard — Pass isDemoData: cacheResult.isDemoFallback && !cacheResult.isLoading to prevent demo data flash during initial load.
  • useFormatRelativeTime hardcodes English — Use i18n translation keys via useTranslation('cards').
  • Non-EN locale keys have English strings — The openfeature.* keys in DE, ES, FR, HI, IT, JA have untranslated English strings. Either translate properly or remove and let i18next fall back to EN.
  • Missing OpenFeature locale keys in non-EN locales — The openfeature translation section needs to be in all locale files, not just EN.

This applies to issue kubestellar/console-marketplace#49. @clubanderson — as the issue author, please comment "approve" once the above items are addressed, or add comments on how to improve the PR.

clubanderson added a commit that referenced this pull request Mar 13, 2026
Add OpenFeature card that detects flagd/OpenFeature operator pods
via /api/mcp/pods and displays provider health, flag stats, and
evaluation counts.

Review fixes:
- Remove scope creep: revert changes to shared files that added
  entries for other cards (Fluentd, Lima, WasmCloud, CRI-O, etc.)
- Revert accidental Lima locale string modifications
- Revert unrelated changes to UpdateSettings, useSelfUpgrade,
  exec.go, analytics.ts, and other shared files
- Add i18n keys for remaining hardcoded strings (evals, cache)
- Add isRefreshing override to CardLoadingStateOptions for cards
  using useCache (returns precise refresh state)
- Only register openfeature_status in card registry and AddCardModal

Signed-off-by: Andrew Anderson <andy@clubanderson.com>
@clubanderson
Copy link
Copy Markdown
Collaborator

Superseded by the fix PR that was merged. Closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dco-signoff: yes Indicates the PR's author has signed the DCO. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

card: Implement OpenFeature monitoring card

3 participants