Skip to content

Result-based error handling for Catalog/Auth; remove Tags from frontend - #69

Closed
evertonschuster wants to merge 9 commits into
mainfrom
feat/reorganize-components
Closed

Result-based error handling for Catalog/Auth; remove Tags from frontend#69
evertonschuster wants to merge 9 commits into
mainfrom
feat/reorganize-components

Conversation

@evertonschuster

Copy link
Copy Markdown
Owner

Summary

  • Migrated features/catalog/ (Categories/Tags) and features/auth/ to a
    throw-free, Result<T, E>-based error-handling convention end to end
    (domain entities, mappers, repositories, hooks, use cases), plus a
    global error-capture net (onCaughtError/onUncaughtError,
    unhandledrejection/error listeners) wired through a pluggable
    ErrorReporter port — see docs/adr/014 and docs/adr/015.
  • Added GET /api/v1/categories/{id} and switched useCategoryEditor to
    fetch its own category directly instead of sharing state through
    useOutletContext — see docs/adr/013.
  • Removed the entire Tags vertical from the frontend (domain, application,
    infrastructure, presentation, MSW handlers, E2E specs, nav entry, route)
    while intentionally keeping the backend Tag domain entity and
    /api/v1/tags endpoints untouched, including Service's many-to-many
    relationship to Tag — a project-owner decision, see
    docs/adr/016-remove-tags-frontend.md. Categories replaces Tags as the
    reference CRUD implementation throughout the docs and the
    agenza-frontend-feature skill.

Test plan

  • dotnet build backend/AdminBackend.slnx / dotnet test backend/AdminBackend.slnx — green
  • npm run format:check / lint / build / test:coverage (apps/admin-frontend) — green, 305/305 tests, coverage above the 85/85/80/80 gate
  • scripts/sync_agent_skills.py --check, scripts/check_agent_governance.py, scripts/architecture_guard.py — all pass
  • Manual browser verification against the real Aspire-orchestrated stack: OIDC login/logout, Categories CRUD (edit/update/duplicate-name conflict/delete), Tags CRUD (pre-removal) — zero console errors

🤖 Generated with Claude Code

evertonschuster and others added 9 commits July 29, 2026 18:28
Remove the standalone useCategories hook and inline its logic into useCategoriesListPage. Add create/update/delete handlers and list state (useAsync, mutate, captureGeneration) directly in the page hook. Introduce CategoriesEditorContext in the types file and update CategoryEditorDialog to consume the new context type. Also adjust onRetry to call execute(). This refactor removes indirection, consolidates list + editor mutations, and preserves existing behavior.
docs/adr/ (31 backend ADRs) was removed without updating any of the
100+ references to it across AGENTS.md, skills, and docs, which broke
the governance check that verifies every docs/adr/NNNN reference
resolves. Restoring the files keeps the documented rationale behind
existing backend rules intact.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Business/presentation code no longer throws for expected outcomes or
relies on try/catch as its primary error-handling mechanism (ADR 014,
ADR 015): domain entities (Category, Tag, Session, User, Tenant),
infrastructure mappers, useAsync, and every Catalog/Auth hook branch on
Result directly instead. Converting mapOidcUserToSession/mapCategoryDtoToDomain
surfaced a real gap along the way - a malformed cached session could
throw uncaught and get silently misread as "not logged in" - now closed.

Adds a global error-capture net (ErrorReporter port + React 19's
onCaughtError/onUncaughtError + window unhandledrejection/error
listeners) for whatever still throws unexpectedly, ready to wire to a
real observability backend later.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Removes the entire Tags vertical from apps/admin-frontend (domain,
application, infrastructure, presentation, MSW handlers, E2E specs, nav
entry, route, and catalog facade wiring) while intentionally retaining
the backend Tag domain entity and /api/v1/tags endpoints, including
Service's many-to-many relationship to Tag - a project-owner decision
documented in docs/adr/016-remove-tags-frontend.md.

Updates STATUS.md, DOMAIN.md, API.md, apps/admin-frontend/AGENTS.md,
.agent.md, and the canonical agenza-frontend-feature skill (synced to
.claude/skills/ and .agents/skills/) so Categories replaces Tags as the
reference CRUD implementation throughout, and so the docs are explicit
that the backend still returns tags/tagIds on ServiceDto even though the
frontend has no Tag type to represent it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 244 files, which is 144 over the limit of 100.

To get a review, narrow the scope:
• coderabbit review --committed # exclude uncommitted changes
• coderabbit review --dir # limit to a subdirectory
• coderabbit review --base # compare against a closer base

Upgrade to a paid plan to raise the limit.

This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: cb1be1fc-0c52-4932-a277-7bbc55d0c878

📥 Commits

Reviewing files that changed from the base of the PR and between 033baf9 and 4911abb.

⛔ Files ignored due to path filters (2)
  • apps/admin-frontend/src/features/catalog/infrastructure/generated/services-api.d.ts is excluded by !**/generated/**
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (244)
  • .agents/skills/agenza-frontend-feature/SKILL.md
  • .claude/skills/agenza-frontend-feature/SKILL.md
  • .gitignore
  • .husky/pre-commit
  • AGENTS.md
  • README.md
  • agent-skills/agenza-frontend-feature/SKILL.md
  • apps/admin-frontend/.agent.md
  • apps/admin-frontend/.env.example
  • apps/admin-frontend/.lintstagedrc.json
  • apps/admin-frontend/AGENTS.md
  • apps/admin-frontend/docs/API.md
  • apps/admin-frontend/docs/DECISIONS.md
  • apps/admin-frontend/docs/DOMAIN.md
  • apps/admin-frontend/docs/STATUS.md
  • apps/admin-frontend/docs/adr/001-clean-architecture-layers.md
  • apps/admin-frontend/docs/adr/012-routed-category-editor.md
  • apps/admin-frontend/docs/adr/013-category-editor-fetches-by-id.md
  • apps/admin-frontend/docs/adr/014-catalog-result-errors-and-global-net.md
  • apps/admin-frontend/docs/adr/015-auth-result-errors.md
  • apps/admin-frontend/docs/adr/016-remove-tags-frontend.md
  • apps/admin-frontend/e2e/authenticated-shell.spec.ts
  • apps/admin-frontend/e2e/categories-mobile.spec.ts
  • apps/admin-frontend/e2e/tags-crud.spec.ts
  • apps/admin-frontend/e2e/tags-list-retry.spec.ts
  • apps/admin-frontend/eslint.config.js
  • apps/admin-frontend/src/app/composition/container.test.ts
  • apps/admin-frontend/src/app/composition/container.ts
  • apps/admin-frontend/src/app/layouts/AdminLayout.test.tsx
  • apps/admin-frontend/src/app/layouts/AdminLayout.tsx
  • apps/admin-frontend/src/app/main.tsx
  • apps/admin-frontend/src/app/pages/ServicesPage/ServicesPage.tsx
  • apps/admin-frontend/src/app/routes/router.tsx
  • apps/admin-frontend/src/features/auth/application/errors/AuthFlowError.ts
  • apps/admin-frontend/src/features/auth/application/repositories/AuthRepository.ts
  • apps/admin-frontend/src/features/auth/application/test-helpers/createFakeAuthRepository.ts
  • apps/admin-frontend/src/features/auth/application/use-cases/GetCurrentSession.test.ts
  • apps/admin-frontend/src/features/auth/application/use-cases/HandleAuthCallback.test.ts
  • apps/admin-frontend/src/features/auth/application/use-cases/HandleAuthCallback.ts
  • apps/admin-frontend/src/features/auth/application/use-cases/InitiateLogin.test.ts
  • apps/admin-frontend/src/features/auth/application/use-cases/InitiateLogin.ts
  • apps/admin-frontend/src/features/auth/application/use-cases/Logout.test.ts
  • apps/admin-frontend/src/features/auth/application/use-cases/Logout.ts
  • apps/admin-frontend/src/features/auth/domain/entities/Session.test.ts
  • apps/admin-frontend/src/features/auth/domain/entities/Session.ts
  • apps/admin-frontend/src/features/auth/domain/entities/User.test.ts
  • apps/admin-frontend/src/features/auth/domain/entities/User.ts
  • apps/admin-frontend/src/features/auth/domain/value-objects/Tenant.test.ts
  • apps/admin-frontend/src/features/auth/domain/value-objects/Tenant.ts
  • apps/admin-frontend/src/features/auth/infrastructure/MissingExpiryClaimError.ts
  • apps/admin-frontend/src/features/auth/infrastructure/OidcAuthRepository.test.ts
  • apps/admin-frontend/src/features/auth/infrastructure/OidcAuthRepository.ts
  • apps/admin-frontend/src/features/auth/infrastructure/mapOidcErrorToAuthFlowError.ts
  • apps/admin-frontend/src/features/auth/infrastructure/oidcUserToSessionMapper.test.ts
  • apps/admin-frontend/src/features/auth/infrastructure/oidcUserToSessionMapper.ts
  • apps/admin-frontend/src/features/auth/presentation/AuthContext.test.ts
  • apps/admin-frontend/src/features/auth/presentation/AuthContext.ts
  • apps/admin-frontend/src/features/auth/presentation/AuthProvider.test.tsx
  • apps/admin-frontend/src/features/auth/presentation/AuthProvider.tsx
  • apps/admin-frontend/src/features/auth/presentation/CallbackPage/CallbackPage.test.tsx
  • apps/admin-frontend/src/features/auth/presentation/CallbackPage/CallbackPage.tsx
  • apps/admin-frontend/src/features/auth/presentation/LoginPage/LoginPage.test.tsx
  • apps/admin-frontend/src/features/auth/presentation/LoginPage/LoginPage.tsx
  • apps/admin-frontend/src/features/auth/presentation/ProtectedRoute.test.tsx
  • apps/admin-frontend/src/features/auth/presentation/TenantBoundary.test.tsx
  • apps/admin-frontend/src/features/auth/presentation/authFlowFeedback.ts
  • apps/admin-frontend/src/features/auth/presentation/useAuthenticatedTenant.test.tsx
  • apps/admin-frontend/src/features/catalog/application/repositories/CategoryRepository.ts
  • apps/admin-frontend/src/features/catalog/application/repositories/ServiceRepository.ts
  • apps/admin-frontend/src/features/catalog/application/repositories/TagRepository.ts
  • apps/admin-frontend/src/features/catalog/application/test-helpers/createFakeCategoryRepository.ts
  • apps/admin-frontend/src/features/catalog/application/test-helpers/createFakeServiceRepository.ts
  • apps/admin-frontend/src/features/catalog/application/test-helpers/createFakeTagRepository.ts
  • apps/admin-frontend/src/features/catalog/application/use-cases/categories/CreateCategory.test.ts
  • apps/admin-frontend/src/features/catalog/application/use-cases/categories/CreateCategory.ts
  • apps/admin-frontend/src/features/catalog/application/use-cases/categories/DeleteCategory.test.ts
  • apps/admin-frontend/src/features/catalog/application/use-cases/categories/DeleteCategory.ts
  • apps/admin-frontend/src/features/catalog/application/use-cases/categories/ListCategories.test.ts
  • apps/admin-frontend/src/features/catalog/application/use-cases/categories/ListCategories.ts
  • apps/admin-frontend/src/features/catalog/application/use-cases/categories/UpdateCategory.test.ts
  • apps/admin-frontend/src/features/catalog/application/use-cases/categories/UpdateCategory.ts
  • apps/admin-frontend/src/features/catalog/application/use-cases/services/CreateService.test.ts
  • apps/admin-frontend/src/features/catalog/application/use-cases/services/CreateService.ts
  • apps/admin-frontend/src/features/catalog/application/use-cases/services/DeleteService.test.ts
  • apps/admin-frontend/src/features/catalog/application/use-cases/services/DeleteService.ts
  • apps/admin-frontend/src/features/catalog/application/use-cases/services/ListServices.test.ts
  • apps/admin-frontend/src/features/catalog/application/use-cases/services/ListServices.ts
  • apps/admin-frontend/src/features/catalog/application/use-cases/services/UpdateService.test.ts
  • apps/admin-frontend/src/features/catalog/application/use-cases/services/UpdateService.ts
  • apps/admin-frontend/src/features/catalog/application/use-cases/tags/CreateTag.test.ts
  • apps/admin-frontend/src/features/catalog/application/use-cases/tags/CreateTag.ts
  • apps/admin-frontend/src/features/catalog/application/use-cases/tags/DeleteTag.test.ts
  • apps/admin-frontend/src/features/catalog/application/use-cases/tags/DeleteTag.ts
  • apps/admin-frontend/src/features/catalog/application/use-cases/tags/ListTags.test.ts
  • apps/admin-frontend/src/features/catalog/application/use-cases/tags/ListTags.ts
  • apps/admin-frontend/src/features/catalog/application/use-cases/tags/UpdateTag.test.ts
  • apps/admin-frontend/src/features/catalog/application/use-cases/tags/UpdateTag.ts
  • apps/admin-frontend/src/features/catalog/domain/entities/Category.test.ts
  • apps/admin-frontend/src/features/catalog/domain/entities/Category.ts
  • apps/admin-frontend/src/features/catalog/domain/entities/Service.test.ts
  • apps/admin-frontend/src/features/catalog/domain/entities/Service.ts
  • apps/admin-frontend/src/features/catalog/domain/entities/Tag.test.ts
  • apps/admin-frontend/src/features/catalog/domain/entities/Tag.ts
  • apps/admin-frontend/src/features/catalog/domain/errors/InvalidServiceError.ts
  • apps/admin-frontend/src/features/catalog/domain/errors/InvalidTagError.ts
  • apps/admin-frontend/src/features/catalog/index.ts
  • apps/admin-frontend/src/features/catalog/infrastructure/mappers/categoryMapper.test.ts
  • apps/admin-frontend/src/features/catalog/infrastructure/mappers/categoryMapper.ts
  • apps/admin-frontend/src/features/catalog/infrastructure/mappers/serviceMapper.test.ts
  • apps/admin-frontend/src/features/catalog/infrastructure/mappers/serviceMapper.ts
  • apps/admin-frontend/src/features/catalog/infrastructure/mappers/tagMapper.test.ts
  • apps/admin-frontend/src/features/catalog/infrastructure/mappers/tagMapper.ts
  • apps/admin-frontend/src/features/catalog/infrastructure/repositories/ApiCategoryRepository.test.ts
  • apps/admin-frontend/src/features/catalog/infrastructure/repositories/ApiCategoryRepository.ts
  • apps/admin-frontend/src/features/catalog/infrastructure/repositories/ApiServiceRepository.test.ts
  • apps/admin-frontend/src/features/catalog/infrastructure/repositories/ApiServiceRepository.ts
  • apps/admin-frontend/src/features/catalog/infrastructure/repositories/ApiTagRepository.test.ts
  • apps/admin-frontend/src/features/catalog/infrastructure/repositories/ApiTagRepository.ts
  • apps/admin-frontend/src/features/catalog/presentation/categories/CategoriesPage.test.tsx
  • apps/admin-frontend/src/features/catalog/presentation/categories/CategoriesPage.tsx
  • apps/admin-frontend/src/features/catalog/presentation/categories/components/CategoryDeleteDialog.tsx
  • apps/admin-frontend/src/features/catalog/presentation/categories/components/CategoryEditorDialog.tsx
  • apps/admin-frontend/src/features/catalog/presentation/categories/hooks/useCategories.test.tsx
  • apps/admin-frontend/src/features/catalog/presentation/categories/hooks/useCategories.ts
  • apps/admin-frontend/src/features/catalog/presentation/categories/hooks/useCategoriesPage.ts
  • apps/admin-frontend/src/features/catalog/presentation/categories/pages/CategoriesListPage/CategoriesListPage.tsx
  • apps/admin-frontend/src/features/catalog/presentation/categories/pages/CategoriesListPage/components/CategoriesTable.tsx
  • apps/admin-frontend/src/features/catalog/presentation/categories/pages/CategoriesListPage/components/CategoriesTable.types.ts
  • apps/admin-frontend/src/features/catalog/presentation/categories/pages/CategoriesListPage/hooks/useCategoriesListPage.ts
  • apps/admin-frontend/src/features/catalog/presentation/categories/pages/CategoriesListPage/hooks/useCategoriesListPage.types.ts
  • apps/admin-frontend/src/features/catalog/presentation/categories/pages/CategoriesListPage/hooks/useCategoryDeletion.ts
  • apps/admin-frontend/src/features/catalog/presentation/categories/pages/CategoriesListPage/hooks/useCategoryDeletion.types.ts
  • apps/admin-frontend/src/features/catalog/presentation/categories/pages/CategoriesRoutes.test.tsx
  • apps/admin-frontend/src/features/catalog/presentation/categories/pages/CategoryEditorDialog/CategoryEditorDialog.tsx
  • apps/admin-frontend/src/features/catalog/presentation/categories/pages/CategoryEditorDialog/forms/CategoryForm.tsx
  • apps/admin-frontend/src/features/catalog/presentation/categories/pages/CategoryEditorDialog/forms/CategoryForm.types.ts
  • apps/admin-frontend/src/features/catalog/presentation/categories/pages/CategoryEditorDialog/forms/categoryFieldMaps.ts
  • apps/admin-frontend/src/features/catalog/presentation/categories/pages/CategoryEditorDialog/hooks/useCategoryEditor.ts
  • apps/admin-frontend/src/features/catalog/presentation/categories/pages/CategoryEditorDialog/hooks/useCategoryEditor.types.ts
  • apps/admin-frontend/src/features/catalog/presentation/services/ServicesPage.accessibilityAndSecurity.test.tsx
  • apps/admin-frontend/src/features/catalog/presentation/services/ServicesPage.crud.test.tsx
  • apps/admin-frontend/src/features/catalog/presentation/services/ServicesPage.dialogLifecycle.test.tsx
  • apps/admin-frontend/src/features/catalog/presentation/services/ServicesPage.formValidation.test.tsx
  • apps/admin-frontend/src/features/catalog/presentation/services/ServicesPage.listBehavior.test.tsx
  • apps/admin-frontend/src/features/catalog/presentation/services/ServicesPage.testSupport.tsx
  • apps/admin-frontend/src/features/catalog/presentation/services/ServicesPage.tsx
  • apps/admin-frontend/src/features/catalog/presentation/services/components/ServiceBasicFields.tsx
  • apps/admin-frontend/src/features/catalog/presentation/services/components/ServiceCategoryField.tsx
  • apps/admin-frontend/src/features/catalog/presentation/services/components/ServiceCommercialFields.tsx
  • apps/admin-frontend/src/features/catalog/presentation/services/components/ServiceDeleteDialog.tsx
  • apps/admin-frontend/src/features/catalog/presentation/services/components/ServiceDialog.tsx
  • apps/admin-frontend/src/features/catalog/presentation/services/components/ServiceDurationFields.tsx
  • apps/admin-frontend/src/features/catalog/presentation/services/components/ServiceTableRow.tsx
  • apps/admin-frontend/src/features/catalog/presentation/services/components/ServiceTagsField.tsx
  • apps/admin-frontend/src/features/catalog/presentation/services/components/ServicesFilters.tsx
  • apps/admin-frontend/src/features/catalog/presentation/services/components/ServicesList.tsx
  • apps/admin-frontend/src/features/catalog/presentation/services/components/ServicesPagination.tsx
  • apps/admin-frontend/src/features/catalog/presentation/services/components/ServicesTable.tsx
  • apps/admin-frontend/src/features/catalog/presentation/services/forms/ServiceForm.schema.test.ts
  • apps/admin-frontend/src/features/catalog/presentation/services/forms/ServiceForm.schema.ts
  • apps/admin-frontend/src/features/catalog/presentation/services/forms/ServiceForm.tsx
  • apps/admin-frontend/src/features/catalog/presentation/services/forms/serviceFieldMaps.ts
  • apps/admin-frontend/src/features/catalog/presentation/services/hooks/useServiceDeletion.test.tsx
  • apps/admin-frontend/src/features/catalog/presentation/services/hooks/useServiceDeletion.ts
  • apps/admin-frontend/src/features/catalog/presentation/services/hooks/useServiceEditor.test.tsx
  • apps/admin-frontend/src/features/catalog/presentation/services/hooks/useServiceEditor.ts
  • apps/admin-frontend/src/features/catalog/presentation/services/hooks/useServiceFilters.test.tsx
  • apps/admin-frontend/src/features/catalog/presentation/services/hooks/useServiceFilters.ts
  • apps/admin-frontend/src/features/catalog/presentation/services/hooks/useServices.test.tsx
  • apps/admin-frontend/src/features/catalog/presentation/services/hooks/useServices.ts
  • apps/admin-frontend/src/features/catalog/presentation/services/hooks/useServicesPage.ts
  • apps/admin-frontend/src/features/catalog/presentation/services/models/serviceFormatters.ts
  • apps/admin-frontend/src/features/catalog/presentation/services/models/servicePresentationModels.ts
  • apps/admin-frontend/src/features/catalog/presentation/tags/TagsPage.test.tsx
  • apps/admin-frontend/src/features/catalog/presentation/tags/TagsPage.tsx
  • apps/admin-frontend/src/features/catalog/presentation/tags/components/TagDeleteDialog.tsx
  • apps/admin-frontend/src/features/catalog/presentation/tags/components/TagEditorDialog.tsx
  • apps/admin-frontend/src/features/catalog/presentation/tags/components/TagsTable.tsx
  • apps/admin-frontend/src/features/catalog/presentation/tags/forms/TagForm.test.tsx
  • apps/admin-frontend/src/features/catalog/presentation/tags/forms/TagForm.tsx
  • apps/admin-frontend/src/features/catalog/presentation/tags/forms/tagFieldMaps.ts
  • apps/admin-frontend/src/features/catalog/presentation/tags/hooks/useTags.test.tsx
  • apps/admin-frontend/src/features/catalog/presentation/tags/hooks/useTags.ts
  • apps/admin-frontend/src/features/catalog/presentation/tags/hooks/useTagsPage.ts
  • apps/admin-frontend/src/shared/application/ErrorReporter.ts
  • apps/admin-frontend/src/shared/application/HttpClient.ts
  • apps/admin-frontend/src/shared/application/Result.test.ts
  • apps/admin-frontend/src/shared/application/Result.ts
  • apps/admin-frontend/src/shared/infrastructure/http/AuthenticatedHttpClient.test.ts
  • apps/admin-frontend/src/shared/infrastructure/http/AuthenticatedHttpClient.ts
  • apps/admin-frontend/src/shared/infrastructure/http/malformedResponseError.ts
  • apps/admin-frontend/src/shared/infrastructure/http/mapErrorToAppError.ts
  • apps/admin-frontend/src/shared/infrastructure/http/parseApiResponse.ts
  • apps/admin-frontend/src/shared/infrastructure/observability/ConsoleErrorReporter.ts
  • apps/admin-frontend/src/shared/presentation/components/CollectionFeedback.tsx
  • apps/admin-frontend/src/shared/presentation/components/DeleteConfirmationDialog.tsx
  • apps/admin-frontend/src/shared/presentation/components/ErrorBoundary.tsx
  • apps/admin-frontend/src/shared/presentation/hooks/useAsync.test.tsx
  • apps/admin-frontend/src/shared/presentation/hooks/useAsync.ts
  • apps/admin-frontend/src/shared/presentation/hooks/useCreateInline.test.ts
  • apps/admin-frontend/src/shared/presentation/hooks/useCreateInline.ts
  • apps/admin-frontend/src/shared/presentation/hooks/useDeleteConfirmation.ts
  • apps/admin-frontend/src/shared/presentation/hooks/useDialogTarget.ts
  • apps/admin-frontend/src/test/fixtures/authEntityFixtures.ts
  • apps/admin-frontend/src/test/fixtures/createFakeAppContainer.ts
  • apps/admin-frontend/src/test/fixtures/unwrapResult.ts
  • apps/admin-frontend/src/test/mocks/handlers/categoryHandlers.ts
  • apps/admin-frontend/src/test/mocks/handlers/index.ts
  • apps/admin-frontend/src/test/mocks/handlers/serviceHandlers.ts
  • apps/admin-frontend/src/test/mocks/handlers/tagHandlers.ts
  • backend/AppHost/AppHost.cs
  • backend/Directory.Packages.props
  • backend/services/identity-service/IdentityService.Api/IdentityService.Api.csproj
  • backend/services/identity-service/IdentityService.Api/Program.cs
  • backend/services/identity-service/IdentityService.Api/Properties/launchSettings.json
  • backend/services/identity-service/IdentityService.Api/Seed/DatabaseSeeder.cs
  • backend/services/identity-service/IdentityService.Api/Setup/CorsExtensions.cs
  • backend/services/identity-service/IdentityService.Api/Setup/DocumentationExtensions.cs
  • backend/services/identity-service/IdentityService.Api/appsettings.Development.json
  • backend/services/services-service/ServicesService.Api/Controllers/CategoriesController.cs
  • backend/services/services-service/ServicesService.Api/Controllers/ServicesController.cs
  • backend/services/services-service/ServicesService.Api/Controllers/TagsController.cs
  • backend/services/services-service/ServicesService.Api/Program.cs
  • backend/services/services-service/ServicesService.Api/Properties/launchSettings.json
  • backend/services/services-service/ServicesService.Api/ServicesService.Api.csproj
  • backend/services/services-service/ServicesService.Api/Setup/DocumentationExtensions.cs
  • backend/services/services-service/ServicesService.Api/appsettings.Development.json
  • backend/services/services-service/ServicesService.Application/Categories/GetCategoryById/GetCategoryByIdQuery.cs
  • backend/services/services-service/ServicesService.Application/Categories/GetCategoryById/GetCategoryByIdQueryHandler.cs
  • backend/services/services-service/ServicesService.Tests/Categories/GetCategoryById/GetCategoryByIdQueryHandlerTests.cs
  • backend/shared/Admin.SharedKernel.AspNetCore/ApiProblemDetails.cs
  • backend/shared/Admin.SharedKernel.AspNetCore/ApiProblemDetailsFactory.cs
  • backend/shared/Admin.SharedKernel.AspNetCore/ApiResponse.cs
  • backend/shared/Admin.SharedKernel.AspNetCore/GenericExceptionHandler.cs
  • backend/shared/Admin.SharedKernel.AspNetCore/ProblemDetailsAuthorizationMiddlewareResultHandler.cs
  • backend/shared/Admin.SharedKernel.AspNetCore/ResultExtensions.cs
  • backend/shared/Admin.SharedKernel.Tests/ResultExtensionsTests.cs
  • docs/MONOREPO.md
  • docs/adr/0021-trunk-based-git-workflow.md
  • docs/adr/0030-branch-agnostic-precommit.md
  • docs/adr/0031-remove-local-git-hooks.md
  • package.json
  • scripts/architecture_guard.py
  • scripts/tests/test_architecture_guard.py

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


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.

@evertonschuster

Copy link
Copy Markdown
Owner Author

Fechando em favor da divisão em PRs menores para revisão com CodeRabbit:

  1. Remove local git hooks; add GetCategoryById endpoint; backend API response/CORS infra #70 — Backend + infra do repositório (40 arquivos, independente)
  2. Migrate Auth to Result-based error handling; add shared Result/error infra #71 — Auth: migração para Result + infra compartilhada de erro (69 arquivos, independente)
  3. Migrate Catalog (Categories/Services/Tags) to Result errors; remove Services; physical reorg #72 — Catalog: Categories/Services/Tags migrados para Result + reorganização física + remoção de Services (150 arquivos — ver a PR para explicação de por que não deu pra dividir mais)
  4. Remove Tags feature from frontend, keep backend Tag API intact #73 — Remoção do Tags do frontend, mantendo a API de Tag no backend (42 arquivos)

Todas as 4 verificadas com build/lint/format/test reais antes do push. #71 empilhada sobre #70... na verdade #71 é independente (base main); #72 empilhada sobre #71; #73 empilhada sobre #72.

@evertonschuster

Copy link
Copy Markdown
Owner Author

Correção rápida na ordem de empilhamento acima: #70 (backend) e #71 (Auth) são ambas independentes, baseadas direto em main. #72 (Catalog) está empilhada sobre #71. #73 (remoção de Tags) está empilhada sobre #72.

evertonschuster added a commit that referenced this pull request Aug 2, 2026
Admin.SharedKernel.AspNetCore's ResultExtensions.ToActionResult now wraps
every successful Result<TValue> response in an ApiResponse<T> envelope
(data/success/timestamp/traceId/correlationId) - this PR's own change.
scripts/smoke_oidc_contract.py wasn't updated to match, so its tenant-
provisioning assertion read the old flat shape and failed even though
the endpoint worked correctly (201, real tenantId, just nested under
"data" now). The three assertions checking failure responses (401/403
"code" field) are unaffected - those go through ToProblemResult, which
was not wrapped and never changed shape.

This bug predates this PR split - it already failed identically on the
original, unsplit PR (#69) before any of this work was divided up.

Verified against a real locally-running Aspire stack: both
`npm run generate:api-types:check` and
`python scripts/smoke_oidc_contract.py` pass.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
evertonschuster added a commit that referenced this pull request Aug 2, 2026
…ponse/CORS infra (#70)

* Remove local git hooks, add GetCategoryById endpoint, backend API response/CORS infra

Repo tooling: removes .husky/pre-commit and apps/admin-frontend/.lintstagedrc.json
in favor of explicit quality-gate commands (docs/adr/0031); updates the
trunk-based-workflow and branch-agnostic-precommit ADRs accordingly.

Backend: adds GetCategoryById query/handler/endpoint for Categories;
introduces ApiResponse/ApiProblemDetailsFactory and CORS/OpenAPI
documentation setup extensions shared across identity-service and
services-service; updates architecture_guard.py's database-boundary
check to match.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* Regenerate services-api.d.ts to match the GetCategoryById endpoint

This PR added GET /api/v1/categories/{id} to the backend but didn't
update the frontend's generated OpenAPI types, so CI's api-contract-check
correctly failed - it regenerates services-api.d.ts from the live
backend and diffs against the checked-in version. Regenerated against
this PR's own backend (npm run generate:api-types), verified clean with
npm run generate:api-types:check, and re-ran build/lint/format to
confirm nothing downstream broke.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* Fix smoke_oidc_contract.py for the new ApiResponse<T> success envelope

Admin.SharedKernel.AspNetCore's ResultExtensions.ToActionResult now wraps
every successful Result<TValue> response in an ApiResponse<T> envelope
(data/success/timestamp/traceId/correlationId) - this PR's own change.
scripts/smoke_oidc_contract.py wasn't updated to match, so its tenant-
provisioning assertion read the old flat shape and failed even though
the endpoint worked correctly (201, real tenantId, just nested under
"data" now). The three assertions checking failure responses (401/403
"code" field) are unaffected - those go through ToProblemResult, which
was not wrapped and never changed shape.

This bug predates this PR split - it already failed identically on the
original, unsplit PR (#69) before any of this work was divided up.

Verified against a real locally-running Aspire stack: both
`npm run generate:api-types:check` and
`python scripts/smoke_oidc_contract.py` pass.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
evertonschuster added a commit that referenced this pull request Aug 2, 2026
…infra (#71)

Split out of #69 (part 2 of N — see that PR for the full picture).

- features/auth/: Session/User/Tenant.create() and every AuthRepository
  method (initiateLogin/handleCallback/logout) return Result<T, E>
  instead of throwing; OidcAuthRepository's own try/catch around
  oidc-client-ts stays as a contained infrastructure-adapter boundary.
  See docs/adr/015-auth-result-errors.md (landing in a later PR in this
  stack, since it documents Catalog too).
- shared/: adds Result.ts (Result/success/failure/flatMapResult/
  combineResults), ErrorReporter port + ConsoleErrorReporter adapter,
  and rewrites useAsync.ts to take () => Promise<Result<T, E>> instead
  of a throwing () => Promise<T>.
- test/fixtures/: adds authEntityFixtures.ts (shadow Tenant/User/Session
  fixtures that unwrap the Result so call sites read like before) and
  unwrapResult.ts.

Temporary compatibility shims (flagged for removal in the next PR in
this stack, which migrates Catalog to Result end-to-end and removes
Tags): useCategories.ts/useServices.ts/useTags.ts wrap their existing
list-fetch call in success()/failure() instead of letting it reject, and
~20 old Categories/Services/Tags test files that constructed Tenant/User
directly now import the shadow fixtures instead — neither changes any
other behavior, they only satisfy useAsync's new contract so this PR
builds and tests green on its own without pulling in the unrelated
Catalog reorg.

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
evertonschuster added a commit that referenced this pull request Aug 2, 2026
…ervices; physical reorg (#75)

* Migrate Catalog (Categories/Services/Tags) to Result errors; remove Services vertical; physical reorg

Split out of #69 (part 3 of 4 — see that PR for the full picture).
Recreated from origin/main after #70 and #71 merged, since this repo's
convention (and the split-large-coderabbit-pr skill) is a sequential
series, not stacking on an unmerged branch — CodeRabbit also doesn't
review PRs whose base isn't the default branch, so stacking silently
skipped review for this and the next PR in the series. Same content as
the original #72, just re-based; no functional change.

This PR is larger than the <100-file target used for the other PRs in
this series, deliberately — see "Why this couldn't be split further"
below.

- Categories, Services, and Tags all move to the Result-based error
  convention docs/adr/014 establishes: domain entities' create() methods,
  mappers, and API repositories return Result<T, AppError> instead of
  throwing; useAsync.ts (already Result-based, landed in #71) is the one
  hook every feature's data layer builds on now.
- app/composition/container.ts's CatalogFacade drops the use-case-class
  indirection (ListCategories/CreateTag/etc. as separate classes) for
  direct repository delegation (`{ execute: repo.method }`) - there's no
  orchestration between the facade and the repository, so the extra
  class per operation wasn't earning its keep. The 24 now-orphaned
  use-case-class files (application/use-cases/{categories,services,tags}/)
  are deleted.
- Services' frontend implementation (ServicesPage, ServiceForm, six
  ServicesPage.*.test.tsx files, all its components/hooks/models) is
  fully removed, reverting `/services` to a placeholder page
  (app/pages/ServicesPage/ServicesPage.tsx) - this vertical is going
  back to `stub` status, see docs/STATUS.md.
- Categories moves to a routed create/edit dialog
  (features/catalog/presentation/categories/pages/CategoriesListPage/,
  .../CategoryEditorDialog/) per docs/adr/012, replacing the old flat
  CategoriesPage.tsx/useCategories.ts/CategoryEditorDialog.tsx shape.
- Tags gets the equivalent internal move (hooks/useTagEditor.ts,
  pages/TagEditorDialog.tsx) and its own Result migration
  (Tag.ts/tagMapper.ts/ApiTagRepository.ts) - Tags itself is not
  being removed here, just migrated; its removal is a later PR in
  this stack (docs/adr/016).
- shared/: AuthenticatedHttpClient's get/post/put/delete now return
  Result<T, AppError> instead of throwing; DeleteConfirmationDialog
  takes entityName/entityType instead of a raw title/description pair;
  useCreateInline is removed (no longer used once Services - its only
  consumer - is gone).
- Also removes .husky/pre-commit and fixes architecture_guard.py's
  precommit check accordingly (already merged independently via #70;
  included here too since this branch's own ancestry needed it before
  #70 existed).

## Why this couldn't be split further

I initially tried a narrower "Category-only foundation" PR (~99 files)
deferring Services/Tags. That failed a real build: app/composition/
container.ts wires TagRepository with its *new* method signature
directly (tagRepository.listAll(options) instead of the old
(tenantContext, options) two-arg form) - not just a return-type
change useAsync-style, but the interface itself. Making that build
without also migrating TagRepository/ApiTagRepository/tagMapper/Tag.ts
for real isn't a smaller wrapper shim - it's the same size of work as
just finishing the migration, since there's no reduced version of an
interface signature. Categories, Services, and Tags share
container.ts's catalog wiring, router.tsx, and AuthenticatedHttpClient
tightly enough that they're one atomic, verified-buildable unit at this
layer - mirroring why Auth couldn't be split from Catalog either,
just one layer down.

## Test plan

- [x] `npm install` + `npm run build --workspace=apps/admin-frontend` — green
- [x] `npm run lint --workspace=apps/admin-frontend` — clean, 0 warnings
- [x] `npm run format:check --workspace=apps/admin-frontend` — clean
- [x] `npm run test --workspace=apps/admin-frontend` — 368/368 passing
- [x] `scripts/sync_agent_skills.py --check`, `scripts/check_agent_governance.py`, `scripts/architecture_guard.py` — all pass

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* Fix categories-mobile.spec.ts's mock for the GET-by-id endpoint

useCategoryEditor fetches its own category via GET /api/v1/categories/{id}
(docs/adr/013), but this spec's route mock matched any /api/v1/categories*
path and always returned the full list array regardless of whether the
request was for the collection or a single id - so the by-id fetch
received an array instead of a CategoryDto, and the edit dialog's Nome
field never populated. Mock now inspects the last path segment and
returns the matching single category (404 if not found) for a by-id GET,
the full list otherwise.

Verified against the real Playwright suite (production build + preview,
matching CI): all 10 e2e specs pass, including this one.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
evertonschuster added a commit that referenced this pull request Aug 2, 2026
Split out of #69 (final part of this series — see that PR for the full
picture). Recreated from origin/main after #70/#71/#75 merged, since
this repo's convention (and the split-large-coderabbit-pr skill) is a
sequential series, not stacking on an unmerged branch. Same content as
the original #73, just re-based; no functional change.

Removes the entire Tags vertical from apps/admin-frontend (domain,
application, infrastructure, presentation, MSW handlers, E2E specs, nav
entry, route, and catalog facade wiring) while intentionally retaining
the backend Tag domain entity and /api/v1/tags endpoints, including
Service's many-to-many relationship to Tag - a project-owner decision,
see docs/adr/016-remove-tags-frontend.md. Categories replaces Tags as
the reference CRUD implementation throughout the docs and the
agenza-frontend-feature skill.

## Test plan

- [x] `npm install` + `npm run build --workspace=apps/admin-frontend` — green
- [x] `npm run lint --workspace=apps/admin-frontend` — clean, 0 warnings
- [x] `npm run format:check --workspace=apps/admin-frontend` — clean
- [x] `npm run test --workspace=apps/admin-frontend` — 305/305 passing
- [x] `npx playwright test` (full e2e suite, production build + preview) — 8/8 passing
- [x] `scripts/sync_agent_skills.py --check`, `scripts/check_agent_governance.py`, `scripts/architecture_guard.py` — all pass

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
evertonschuster added a commit that referenced this pull request Aug 2, 2026
…#77)

These 3 files (agent-skills/agenza-frontend-feature/SKILL.md and its two
synced copies under .claude/skills/ and .agents/skills/) live at the repo
root, outside apps/admin-frontend/ — every diff I computed while splitting
#69 into #70/#71/#75/#76 was scoped to apps/admin-frontend (and backend/
for #70), so these files' accumulated updates from this session (Catalog
Result migration, Auth Result migration, and finally the Tags-removal
doc pass replacing TagsPage/TagForm with Categories as the reference
implementation) never made it into any of the split PRs, even though the
actual code changes they describe are all correctly merged.

Content taken directly from the original branch's final commit
(4911abb), already reviewed and governance-checked at the time. Verified
again here against the current merged main: sync_agent_skills.py --check,
check_agent_governance.py, and architecture_guard.py all pass, and the
file paths the skill references (CategoriesListPage.tsx, CategoryForm.tsx,
categoryMapper.ts, AdminLayout.tsx) all exist in the current tree.

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
@evertonschuster
evertonschuster deleted the feat/reorganize-components branch August 2, 2026 23:09
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