Skip to content

feat(flag): Flag Description and Tags — Phase 2 - #64

Merged
amodelandme merged 5 commits into
devfrom
feat/flag-description-and-tags
May 12, 2026
Merged

amodelandme merged 5 commits into
devfrom
feat/flag-description-and-tags

Conversation

@amodelandme

Copy link
Copy Markdown
Owner

Summary

Operators can attach a human-readable description and a set of lowercase
organizational tags to any feature flag. Both fields ride on the existing
per-environment Flag row (a deliberate pre-aggregate-split landing), are
normalized at the service boundary (trim + lowercase + dedupe for tags;
empty/whitespace description → null), and flow through IPromptSanitizer
into the AI flag-health analyzer payload. The change is purely additive on the
wire and in the database — existing clients and rows are unaffected.

Changes in this PR

  • feat(domain) — Flag.Description, Flag.Tags, Flag.UpdateMetadata
    (archived guard + UpdatedAt bump)
  • feat(app) — DTOs, validators (≤500 char description; ≤20 tags × ≤50 chars,
    char-class ^[a-z0-9\-_]+$ on cleaned + lowercased), service-layer
    normalization, single SaveChangesAsync across Reconfigure + UpdateMetadata
  • feat(infra) — TagListConverter, FlagConfiguration mapping with
    HasDefaultValueSql("'[]'"), zero-downtime additive migration, AI prompt
    enrichment with Description + Tags declared inert in the system prompt,
    seed data on all six manifest entries, smoke-test.http demonstrating rich +
    minimal create shapes and PUT clear/no-change semantics
  • test — 50 new unit/integration tests; 153 → 203 unit, 54 → 70 integration
  • docs — spec + implementation notes; foundation docs refreshed; DDD backlog
    items checked off

Spec

Docs/Decisions/flag-description-and-tags/spec.md

Implementation Notes

Docs/Decisions/flag-description-and-tags/implementation-notes.md

Definition of Done

Domain

  • Flag.Description (string?) + Flag.Tags (IReadOnlyList<string>)
  • Public ctor accepts optional description + tags; tags default to []
  • Flag.UpdateMetadata with archived guard + UpdatedAt bump
  • No public setters introduced

Application

  • CreateFlagRequest, UpdateFlagRequest, FlagResponse carry the new fields
  • FlagMappings.ToResponse propagates description + tags
  • CreateFlagRequestValidator enforces description/tag rules
  • UpdateFlagRequestValidator enforces the same rules with null-tolerant guards
  • BanderasService.CreateFlagAsync sanitizes description and normalizes tags
  • BanderasService.UpdateFlagAsync calls Reconfigure then conditionally
    UpdateMetadata within a single SaveChangesAsync
  • BanderasService.AnalyzeFlagsAsync projection sanitizes description and tags

Infrastructure

  • TagListConverter at Banderas.Infrastructure/Persistence/
  • FlagConfiguration maps both columns with the documented constraints
  • EF Core migration AddFlagDescriptionAndTags
  • BanderasDbContextModelSnapshot regenerated
  • AiFlagAnalyzer.BuildPrompt + SystemPrompt updated
  • DatabaseSeeder.SeedManifest carries realistic description + tags

Tests

  • Unit tests cover domain mutation, validators, service normalization,
    converter round-trip, AI prompt-projection sanitization
  • Integration tests cover POST/PUT/GET semantics and AI sanitization wiring
  • No existing test broken by the schema change (audit pass complete)
  • 153 → 203 unit, 54 → 70 integration (exceeds spec targets of ≥165 / ≥60)

Build & CI

  • dotnet build -p:TreatWarningsAsErrors=true succeeds
  • dotnet csharpier check . passes
  • dotnet test (unit + integration) all green locally
  • Requests/smoke-test.http updated for the new shapes

Testing

Locally on a fresh devcontainer:

dotnet build -p:TreatWarningsAsErrors=true
dotnet csharpier check .
dotnet test Banderas.Tests/Banderas.Tests.csproj
dotnet test Banderas.Tests.Integration/Banderas.Tests.Integration.csproj

Then docker compose up, point a .http runner at Requests/smoke-test.http,
and run the file top to bottom. Expected:

  • First create returns 201 with description + tags echoed back.
  • Second create returns 201 with description: null and tags: [].
  • PUT variants demonstrate no-change vs. clear semantics.
  • POST /api/flags/health returns 200 with assessments for every seed flag,
    and the analyzer payload contains sanitized description + tags.

@amodelandme
amodelandme merged commit c084a34 into dev May 12, 2026
5 checks passed
@amodelandme
amodelandme deleted the feat/flag-description-and-tags branch May 12, 2026 20:06
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.

1 participant