Dialog/button titles said "colour" instead of "Color", and the
hidden native color input had no positioned ancestor so the browser
picker opened at the top-left of the viewport instead of near the
dialog.
Guard against missing tags array in FeaturesView so a malformed row
doesn't blow up the whole table render. Replace the separate
create-tag-then-click-to-assign flow in TagsChipInput with a single
type-and-add input: typing >=2 chars suggests existing unassigned
tags, picking one assigns it instead of creating a duplicate, and the
color picker is now a dialog of 15 preset swatches plus a custom
picker trigger.
- Replace sidebar org dropdown with a header link/menu (left of theme toggle) that
includes a "New Organization" entry opening the create dialog
- Self-host Inter via @fontsource-variable/inter instead of relying on system fonts
- Wire up real feature<->tag assignment (was UI-only before): expose Tags on
FeatureResponse, add assign/remove endpoints, make tag chips in the feature
detail dialog toggle assignment, and show up to 5 tags (+ellipsis) in the
features table next to the segment-override icon
- Normalize all API routes to singular/plural REST convention: singular resource
name when addressing one item by id/key (e.g. /feature/{id}), plural for
list/create endpoints (e.g. /features). Updated every controller, the admin
frontend API clients, and affected tests to match
Instruments FeatureEvaluationService with System.Diagnostics.Metrics (Counter + IMeterFactory). Accumulates per-feature/day evaluation counts in-process, flushed every 30s to a new FeatureUsageDaily Postgres table via PostgreSQL ON CONFLICT upsert. Caches dashboard query results for 180s in IMemoryCache. New GET /api/v1/environments/{id}/usage endpoint returns top-10 features last day and 14-day per-day breakdown. Admin dashboard shows two ApexCharts bar charts: top features and evaluations by day with per-flag hover tooltip.
Remove Key from UpsertTraitRequest body (comes from URL route). Emit 'updated' event from IdentityDetail on trait mutations and sync parent. Reload segment data on tab activation and dialog open.
Replace v-btn-toggle with manual button pairs in RuleGroupEditor and
FeatureValueEditor — VSlideGroup (used internally) measures zero width
inside teleported dialogs, causing buttons to overlap and show scroll arrows.
Add donut chart icon next to feature names in the features grid when segment
overrides exist; clicking opens FeatureDetail directly on the Segments tab.
- Add refreshOrganization/refreshProject/refreshEnvironment to context store — update value and localStorage without clearing child selections
- OrgSelector: use refreshOrganization when same org is already stored, preventing the chain that was clearing project and environment
- ProjectSelector: watch org ID (not object ref) so refresh doesn't retrigger; add autoSelectProject to restore stored project or auto-select single project
- EnvironmentTabBar: watch project ID; skip env-clear on initial mount; add autoSelectEnvironment to restore stored env or fall back to first
- Fix test fixtures missing isPrimary field; update EnvironmentTabBar tests to match v-select implementation; add tests for restore behavior
Adds IsPrimary to OrganizationUser (per-user flag, one primary per user).
First org created is automatically set as primary. Selecting a different
org via the UI calls PUT /organisations/{id}/primary to persist the choice
server-side. Dashboard auto-selects: localStorage org (refreshed) →
primary org → single org when no explicit selection exists.
Fix first/last name field overlap by using no-gutters row with
responsive padding. Override global hideDetails:'auto' Vuetify default
with :hide-details="false" so the details area is always rendered,
preventing 22px layout shift when validation messages appear.
Registers the Vue admin as an Aspire resource via AddViteApp, wired to
the API so Aspire injects service discovery env vars that the existing
Vite proxy config already reads.
Remove duplicate source files from old ApiKeys/, Authentication/, and
Authorization/ folders that were already migrated to Common/Security/.
Update test namespace usings to match. Pin EFC Relational 10.0.5 to
resolve MSB3277 version conflict with Npgsql's transitive dependency.
Add LangVersion and TreatWarningsAsErrors to AppHost and ServiceDefaults.
NUnit integration tests that target a running API by URL and seed/clean
data directly in Postgres. Settings (BaseUrl, DbConnectionString) come
from .runsettings or environment variables so tests can be pointed at
any environment. HTTP requests live in HttpFiles/*.http; assertion
failures include a fresh DB snapshot of the relevant rows. First test
covers the flag-enabled path.