Skip to content
CAI
Software that uses CAICheck a score

bravodev-hub/appointme

55.9

Adequate · 21 September 2026

19.7k

lines of production code

TypeScript

with C#

1

measurement over time

CAI band scale
CAI lens gauges

What this system is

AppointMe is a multi-tenant appointment and business management platform that provides a React-based frontend and a .NET backend for scheduling, customer management, and staff administration. It features a business analytics dashboard that visualizes key performance indicators, revenue trends, and staff utilization, supported by optimistic concurrency controls to prevent data conflicts. The system enforces strict security and multi-tenancy through role-based access control, CSRF protection, and tenant-scoped messaging, while utilizing a broker-less, SQL-durable transport for reliable background job processing.

Features

AppointMe v1.1.0: Business Dashboard, GitHub-only CI, and npm migration

This release introduces a new business analytics dashboard at /dashboard, featuring KPI cards, trend charts, staff utilization views, and a peak-hours heatmap, all secured by new statistics permissions and backed by Dapper reads with a covering index. The CI/CD pipeline has been migrated from GitLab to GitHub Actions, dropping the GitLab runner and Azure Service Bus in favor of Wolverine's SQL-durable transport for cheaper, broker-less local and devtest infrastructure. The frontend build system has switched from Yarn to npm, and the tech stack has been updated to include React 19, TypeScript 6, Vite 8, and Wolverine 6.24.

(repo-wide) · high confidence

Cloudflare Worker proxy enables custom domain on Free tier

A new Cloudflare Worker has been added to route traffic from app.appointme.dev to the Azure App Service origin. This proxy allows the application to use a custom hostname despite the Azure Free (F1) tier restriction on custom bindings, by terminating TLS at Cloudflare and forwarding requests with the original host header.

infra/cloudflare-worker · high confidence

Dashboard statistics and peak hours endpoints with demo data seeding

This change introduces the backend components for the Booking dashboard, including endpoints to retrieve aggregated appointment statistics (total appointments, utilization, returning client rate, staff load, and trend buckets) and peak-hour analysis, along with the underlying calculators and database queries that filter for active providers and respect company time zones. It also adds a recurring job that seeds demo appointments daily to support dashboard visualization in demo environments, and introduces rowversion concurrency tokens on the Appointment, Attendee, BookingCompany, and ServiceProvider entities to prevent lost updates during concurrent modifications.

src/Booking · high confidence

New dashboard with business statistics and customer management actions

Users can now access a new Dashboard page that displays key performance indicators (appointments, revenue, chair utilization, returning clients) with period-over-period comparisons, alongside trend charts, peak-hour heatmaps, and staff load views. Revenue figures are currently derived from deterministic fake data based on appointment counts. Additionally, customer and team management actions (edit, delete, manage roles, resend/cancel invitations) are now available via dropdown menus in their respective lists, gated by specific permissions like customers:update, customers:delete, and employees:update\_roles.

src/AppointMe.Frontend/src/app · high confidence

Security

CSRF protection for logout and API requests

The application now includes CSRF protection for the logout flow and general API interactions. The logout function has been updated to submit a POST request via a dynamically created form instead of a simple GET, mitigating logout CSRF attacks. Additionally, the Axios HTTP client instance is configured to automatically handle XSRF tokens using the 'XSRF-TOKEN' cookie and 'X-XSRF-TOKEN' header, ensuring subsequent API requests are protected against cross-site request forgery.

src/AppointMe.Frontend/src/lib · high confidence

Behavioural changes

Constrain system role assignments and add row version concurrency

Assigning or removing system roles (such as Owner or Manager) now requires the managing user to hold the new 'manage\_owners' permission; attempts without this permission will fail with a validation error. Additionally, row version concurrency tokens have been added to the Company, Employee, EmployeeInvitation, and RolePermissionOverride database tables to prevent data conflicts during concurrent updates.

src/Organizations · high confidence

Demo login support and session security hardening

The API now includes a /login/demo endpoint that allows pre-provisioned users to sign in directly via the backend, supporting both Keycloak (ROPC) and Microsoft Entra External ID (native auth) identity providers for quick local or demo access. Session management has been hardened by explicitly setting a 7-day expiration with sliding expiration, and the authentication cookie now stores only the ID token (removing access/refresh tokens) to prevent header size limits and improve security. Additionally, the default for RequireHttpsMetadata has been changed to true to enforce HTTPS for identity provider metadata fetching in production environments.

src/AppointMe.Api/Authentication · high confidence

Demo seeding saga updated with higher customer count and simplified tenant binding

The demo seeding process now generates 400 customers instead of 100, providing a more populated environment for testing. Additionally, the saga's command construction has been simplified by replacing the string-based tenant ID assignment with a direct company ID binding, streamlining how the demo data is associated with the company context.

src/AppointMe.Api/Demo · high confidence

Demo user seeding and frontend build tooling update

The local development environment now includes a pre-seeded demo user ([e-mail redacted]) in the Keycloak realm configuration, allowing immediate access to the application without manual registration. Additionally, the frontend build process has switched from Yarn to npm, requiring npm for local development, and the Keycloak client configuration now enables direct access grants to support this demo flow.

src/AppointMe.Aspire · high confidence

Devtest infrastructure cost controls and Service Bus removal

The devtest environment now removes the Azure Service Bus module entirely, with the App Service module no longer accepting or injecting a Service Bus connection string. The App Service Plan default SKU has been changed from Basic (B1) to Free (F1), which disables Always On and requires a Cloudflare Worker for custom domain binding. SQL Database defaults to the Basic tier (5 DTU, 2 GB cap) instead of Standard (S0), and Log Analytics now enforces a 0.5 GB/day ingestion cap to prevent runaway costs.

infra/modules · high confidence

Enable OpenTelemetry tracing and metrics for Wolverine

The API's OpenTelemetry configuration now explicitly includes instrumentation sources and meters for Wolverine. This ensures that distributed traces and metrics generated by Wolverine are captured and exported via OTLP, providing visibility into Wolverine-related operations alongside existing ASP.NET Core, HTTP client, and SQL client telemetry.

src/AppointMe.Api/OpenTelemetry · high confidence

Enhanced security posture with CSRF protection, security headers, and HSTS

The API now enforces stricter security standards by introducing custom Antiforgery middleware that validates state-changing requests on the /api prefix while issuing tokens for authenticated sessions, and by adding a Security Headers middleware that sets X-Content-Type-Options, X-Frame-Options, Referrer-Policy, and a Content-Security-Policy-Report-Only header. Additionally, HTTP Strict Transport Security (HSTS) is enabled for non-development environments, and data protection keys are now configurable to persist to Azure Blob Storage via a dedicated connection string. The frontend build process has also switched from Yarn to npm, and the application now honors the X-Original-Host header to correctly identify the public hostname when behind proxies like Cloudflare.

src/AppointMe.Api · high confidence

Frontend build tooling and configuration updates

The frontend build system has switched from Yarn to npm, requiring users to use npm commands for development and building. The Vite configuration now uses import.meta.dirname for path resolution, and the ESLint rules have been updated to exempt vendored shadcn/ui components from the single-export rule to support cleaner updates. Additionally, the orval code generator no longer applies prettier formatting during API client generation, relying instead on post-generation hooks, and documentation has been updated to reflect these changes along with specific instructions for managing npm lockfile compatibility.

src/AppointMe.Frontend · high confidence

Hangfire dashboard access restricted to super-admins

Access to the Hangfire job dashboard at /admin/jobs is now gated behind a new authorization policy that requires both an authenticated user and the super-admin role. This is enforced by introducing a SuperAdminRequirement and handler, registering the policy in the authorization service collection, and applying the policy to the Hangfire dashboard endpoint mapping.

src/AppointMe.Api/Authorization · high confidence

Optimistic concurrency conflict handling for appointments

The API now detects and handles optimistic concurrency conflicts when updating appointments. If a record is modified by another operation while being edited, the system returns a 409 Conflict response with a clear message instructing the user to reload and try again, preventing silent data overwrites.

src/AppointMe.Api/ErrorHandling · high confidence

Platform super-admin role, tenant-scoped messaging, and pagination limits

This update introduces a platform-level 'super admin' role (configured via email list) that operates independently of company boundaries, alongside new extension methods to seamlessly attach company context to Wolverine messages and invoke commands scoped to a specific tenant. It also adds configuration options for a demo mode with seeded user credentials, domain logic for aggregating statistics into day/week/month buckets, and a fix to prevent SQL connection leaks during open failures. Additionally, the maximum pagination limit per request is lowered from 1000 to 100 rows to reduce resource consumption.

src/AppointMe.Shared · high confidence

Refactored context hooks and improved error handling in frontend components

The auth and theme context hooks (useCurrentUser, useCurrentCompany, useUserAccess, useTheme) have been split into separate .ts files to follow fast-refresh conventions, with the context providers now importing from these new hook files. The permission system now supports checking multiple permissions at once, allowing the Can component to accept an array of permissions. Error handling in the signup and onboarding forms has been improved to properly catch and display specific error messages from the API, including better handling of Axios errors. Additionally, the modal dialog provider now uses unknown type instead of any for better type safety, and the onboarding form now includes a name attribute on the timezone select field.

src/AppointMe.Frontend/src/components · high confidence

Simplifies devtest infrastructure and updates deployment documentation

The devtest environment now uses a free App Service plan (F1) instead of B1, a Basic SQL tier instead of Standard (S0), and a 0.5 GB/day ingestion cap for Log Analytics. Azure Service Bus has been removed from the provisioned resources. The deployment guide has been reworked to focus on GitHub Actions with OIDC authentication, removing GitLab CI support, and adding instructions for optional custom domain binding via Cloudflare Workers.

infra · high confidence

Upgrade to React Router v8

The application has upgraded its routing library to React Router v8. This change updates the import paths for core routing components, such as moving \RouterProvider\ to \react-router/dom\ and \useBlocker\ to \react-router\, ensuring compatibility with the new major version's module structure.

src/AppointMe.Frontend/src, src/AppointMe.Frontend/src/hooks · high confidence

User logout now requires authentication and POST requests

The logout endpoint has been changed from an anonymous GET request to a POST request that requires authorization. This prevents unauthorized users from triggering logout actions and mitigates potential CSRF vulnerabilities associated with GET-based state changes. Additionally, a rowversion concurrency token has been added to the User entity to handle optimistic concurrency control in the database.

src/Identity · high confidence

Validation exceptions are routed to the error queue

The application now automatically catches ValidationException instances during message processing and moves them to the error queue instead of failing the operation. This ensures that invalid data does not crash the processing pipeline, allowing for better observability and retry handling of validation failures.

src/AppointMe.Api/Wolverine · high confidence

Test coverage

Added unit tests for API security middleware and authorization; Added unit tests for shared domain and infrastructure components.

Dependencies

Major dependency upgrades and security hardening across frontend and backend

This update upgrades the frontend to React 19 and React Router v8, replacing the legacy react-router-dom package, and enforces Node.js 22 as the minimum runtime. The backend upgrades .NET 10 packages (including EF Core, Aspire, and Wolverine) to their latest minor versions and introduces a transitive pin for Microsoft.OpenApi to version 2.11.0 to address the [GHSA redacted] vulnerability. Additionally, the frontend has switched from Yarn to npm, removing yarn.lock in favor of a complete package-lock.json, and adds overrides for undici and minimatch to further secure the dependency tree.

(dependencies) · high confidence

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

How this codebase got here

This is the PUBLIC form of this artifact. Findings are listed in full, but the details of SECURITY findings — which rule fired, in which file, on which line, and how to fix it — are deliberately withheld, and any secret-scanner results are excluded entirely. Where detail is absent here it was REMOVED FOR PUBLICATION; it is not missing from the analysis. The complete artifact is available from the repository owner.

Score

  • CAI 54 → 56 (+2.0)
  • Rubric changed (rubric-2026.08.18 → rubric-2026.09.15) — scores are not directly comparable.

Lenses

  • Code Health 87 → 89 (+2.1)
  • Architecture 73 → 73 (-0.8)
  • Maturity 69 → 69 (-0.0)
  • Readiness 32 → 40 (+8.0)
  • Security 77 → 78 (+1.0)
  • Domain Modelling 100 → 65 (-34.5)
  • Event-Driven 100 → 100 (+0.0)
  • Accessibility 71 → 71 (-0.6)
  • Performance 72 → 72 (-0.3)

Resolved (34)

  • Bounded contexts not declared
  • Dependency hygiene not measured — this repository's dependencies are not NuGet
  • Duplicated block (13 lines × 2) (src/AppointMe.Api/Authentication/EntraExternalId/EntraExternalIdClaimsTransformer.cs)
  • High CVE: [GHSA redacted] (src/AppointMe.Frontend/package-lock.json)
  • High CVE: [GHSA redacted] (src/AppointMe.Frontend/package-lock.json)
  • High CVE: [GHSA redacted] (src/AppointMe.Frontend/package-lock.json)
  • High CVE: [GHSA redacted] (src/AppointMe.Frontend/package-lock.json)
  • High CVE: System.Security.Cryptography.Xml 10.0.7
  • High CVE: System.Security.Cryptography.Xml 10.0.7
  • High CVE: System.Security.Cryptography.Xml 10.0.7
  • High CVE: System.Security.Cryptography.Xml 10.0.7
  • High CVE: System.Security.Cryptography.Xml 10.0.7
  • High vulnerability: [GHSA redacted] (src/AppointMe.Frontend/package-lock.json)
  • High vulnerability: [GHSA redacted] (src/AppointMe.Frontend/package-lock.json)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • …and 14 more

New (153)

  • Cross-context type AttendeeProjected (Booking → AppointMe.Api)
  • Cross-context type CompanyRegistered (Organizations → AppointMe.Api)
  • Cross-context type CompanyRegistered (Organizations → Booking)
  • Cross-context type CompanySnapshot (Organizations → Booking)
  • Cross-context type CustomerDeletedEvent (CRM → Booking)
  • Cross-context type CustomerRegisteredEvent (CRM → Booking)
  • Cross-context type CustomerSnapshot (CRM → Booking)
  • Cross-context type CustomerUpdatedEvent (CRM → Booking)
  • Cross-context type EmployeeDeleted (Organizations → Booking)
  • Cross-context type EmployeeInvitationResent (Organizations → Identity)
  • Cross-context type EmployeeInvited (Organizations → Identity)
  • Cross-context type EmployeeRegistered (Organizations → Booking)
  • Cross-context type EmployeeRolesUpdated (Organizations → Booking)
  • Cross-context type EmployeeSnapshot (Organizations → Booking)
  • Cross-context type ServiceProviderProjected (Booking → AppointMe.Api)
  • Dead code: GetDashboardStatsEndpoint (src/Booking/AppointMe.Booking/Dashboard/GetDashboardStats/GetDashboardStatsEndpoint.cs)
  • Dead code: GetNewCustomerStatsEndpoint (src/CRM/AppointMe.Crm/Customers/GetNewCustomerStats/GetNewCustomerStatsEndpoint.cs)
  • Dead code: GetPeakHoursEndpoint (src/Booking/AppointMe.Booking/Dashboard/GetPeakHours/GetPeakHoursEndpoint.cs)
  • Documentation: no installation or build instructions (README.md)
  • Documentation: no usage examples (README.md)
  • …and 133 more

Changes since last survey

  • 56 commits — 51 feature/other, 5 fixes

By area

  • src/AppointMe.Frontend — 20 commits
  • docs/superpowers — 11 commits
  • .github/workflows — 8 commits
  • (root) — 6 commits
  • src/AppointMe.Api — 3 commits
  • infra/README.md — 2 commits
  • infra/modules — 2 commits
  • docs/images — 1 commit
  • infra/cloudflare-worker — 1 commit
  • src/Booking — 1 commit
  • src/CRM — 1 commit

Notable commits

  • fix: - fix versions in CLAUDE.md - add Wolverine OTel
  • fix: Fix input field names
  • fix: Fix login effect deps; suppress compiler notice at useReactTable sites
  • fix: Fix pre-existing eslint errors now that CI runs frontend lint
  • fix: Fix volnurable dependencies
  • change: - Add missing DialogDescription to the schedule-appointment dialog. The only DialogContent without a description — source of Radix's aria-describedby console warning. - update orval and vite
  • change: - bump WolverineFx to version 6.24.4
  • change: Accept APP_VERSION build-arg for the frontend bundle
  • change: Add Cloudflare Worker host-rewrite proxy for devtest custom domain
  • change: Add CodeQL workflow (SAST parity with GitLab pipeline)
  • change: Add administration menu
  • change: Add design spec for CI warnings cleanup
  • change: Add design spec for GitHub Actions CI/CD pipeline
  • change: Add design spec for devtest SqlDurable transport + Service Bus removal
  • change: Add design spec for footer build version
  • change: Add design spec for free-tier devtest via Cloudflare Worker
  • change: Add implementation plan for CI warnings cleanup
  • change: Add implementation plan for GitHub Actions CI/CD
  • change: Add implementation plan for devtest SqlDurable transport switch
  • change: Add implementation plan for footer build version
  • …and 36 more

API surface

  • 3 added · 0 removed (a removed endpoint is potentially breaking)

Added endpoints (3)

  • GET /booking/dashboard/peak-hours
  • GET /booking/dashboard/stats
  • GET /crm/dashboard/new-customers

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

Survey your own repository

bravodev-hub/appointme was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.

About this page

  • The score is its most recent published measurement, taken on 21 September 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
  • Measured at commit 55d0b749a2ca3d216d7dc9422fe69bbedf422713 — the exact code this score is about.
  • Scored under rubric-2026.09.15 — the same rubric and the same method as every other entry in this index.
  • Measured by watchdog.canine.dev using codehealth-analyzer preprod-28e75b8e3254.