Skip to content

Admin Dashboard#19

Open
adrw wants to merge 17 commits intomainfrom
adrw/admin-dashboard
Open

Admin Dashboard#19
adrw wants to merge 17 commits intomainfrom
adrw/admin-dashboard

Conversation

@adrw
Copy link
Copy Markdown
Collaborator

@adrw adrw commented Feb 19, 2026

Description
Add a comprehensive admin dashboard module (kairo-admin) with server-side HTML rendering (kotlinx.html), Stimulus.js controllers, and Tailwind CSS styling. The dashboard provides introspection into endpoint definitions, database tables, dependencies, health checks, logging configuration, and runtime metrics. Includes a full-featured sample application (kairo-admin-sample) with Authors and Library Books APIs.

Key features:

Endpoint reflection with request/response schema visualization
Database table inspection with SQL query execution
Real-time dependency injection introspection
Responsive sidebar navigation
Hotwire Stimulus controllers for interactivity

adrw and others added 17 commits February 12, 2026 09:28
Introduces kairo-admin, a server-rendered admin dashboard providing
endpoint exploration, config viewing, JVM monitoring, and database
browsing via kotlinx.html SSR with Tailwind CSS and Hotwire. Includes
kairo-admin-sample demonstrating the dashboard with LibraryBook and
Author entities backed by PostgreSQL.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add 8 new tabs (Features, Health, Dependencies, Integrations, Logging,
Errors, Connection Pool in Database, and sorted sidebar) with models,
collectors, and views. Implement responsive sidebar with hamburger menu
for mobile, fix JVM text overflow, and inline database query results.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…s, and UI polish

- Use reflection to extract request/response body fields from endpoint data classes
- Add collapsible schema tables for request body and response fields
- Sort home page dashboard cards alphabetically
- Fix sidebar external link icon alignment and sizing
- Add toggle, filter, and headers Stimulus controllers
- Expand dependencies view with detail metadata and search filtering

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace hardcoded endpoint classes, feature names, health checks,
connection factory, Koin, config sources, and integrations with
lifecycle-based auto-discovery. Services now install the admin
dashboard with just AdminDashboardFeature(config = ...).

- Store endpoint classes on Ktor Application attributes via route(),
  following the existing Application.json/Application.koin pattern
- Expose health checks from HealthCheckFeature.registeredHealthChecks
- Expose Koin from DependencyInjectionFeature.koin
- Add implementation deps on health-check and DI to kairo-admin
- Auto-detect config sources from CONFIG env var + classpath
- Auto-detect database integrations from available ConnectionFactory
- Sample Main.kt reduced from 116 to 52 lines

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds an optional serverName field to AdminDashboardConfig, used in the
page title, sidebar header, and home view greeting. Falls back to the
existing title when serverName is not set.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add kairo-kdocs module to serve Dokka-generated KDoc HTML
- Auto-detect KDocs availability and add sidebar link
- Show merged effective config on the config page
- Refactor sidebar nav links and external links to use sorted lists

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add a reusable pageHeader component with a Documentation toggle dropdown
on every tab. Add conditional Slack, Auth (Stytch), and Email (MailerSend)
tabs that auto-appear when features are detected at runtime. Switch all
Kairo module dependencies to compileOnly with NoClassDefFoundError guards
for graceful degradation when modules are absent.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix 29 detekt lint issues (unused imports, safe call chains, argument
wrapping, complexity suppressions, import ordering). Make database
schema card collapsible with chevron toggle. Add README docs for
kairo-admin, kairo-admin-sample, and kairo-kdocs modules.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…own to endpoint card

Rename the sample module with a sample- prefix to distinguish it from
publishable library modules. Replace the endpoint class name in the
endpoint detail card header with a collapsible "Details" button that
reveals endpoint metadata on click.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…lus scoping

- Move request/response field sections into the collapsible Details dropdown
- Fix Stimulus placeholder to scope targets and actions to their own controller,
  preventing nested toggle controllers from interfering with each other
- Remove Custom Headers title, float-right Send Request button, remove response label
- Update Details button hover styling to match Documentation button
- Update sample server name to "Sample"

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…king

- New json-editor Stimulus controller with syntax highlighting overlay,
  JSON parse validation, schema validation (required fields, unknown fields,
  type checking), auto-resize, and paste auto-formatting
- Fix Stimulus placeholder to handle kebab-case controller names via
  kebabToCamel conversion for dataset property access
- Validation errors shown as Tailwind-styled red alert banner
- Schema passed as data attribute from endpoint requestBodyFields

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add GET handlers for /database/query and /endpoints/{index} so
  shareable URLs with base64-encoded query/response params render
  server-side without requiring JS
- Intercept database form POST to redirect as GET with encoded params
- Add SavedResponse model for decoding response data from URL params
- Add keyboard_controller with shortcuts: ?, /, g-prefixed nav, Escape
- Group endpoint dropdown by path prefix using <optgroup> (dynamic,
  works for any service)
- Default-fill database SQL textarea with sample query when table selected
- Remove unused apiDocsUrl config field

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…page

Encode query results into the URL so permalinks render saved results
instead of re-executing against the live database. Group database tables
in the dropdown by schema namespace using optgroup.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Accepts an optional `auth: (suspend AuthReceiver<*>.() -> Unit)?` parameter
on AdminDashboardFeature that is applied to all dashboard routes. Adds
AuthReceiver.forCall() factory for use outside REST endpoints.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@adrw adrw requested a review from hudson155 as a code owner February 19, 2026 20:15
Copilot AI review requested due to automatic review settings February 19, 2026 20:15
Copy link
Copy Markdown

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

This PR adds a comprehensive admin dashboard feature to the Kairo framework. The dashboard provides server-rendered UI for inspecting endpoints, configuration, JVM metrics, database tables, health checks, features, logging, dependencies, integrations, and errors. It includes auto-discovery of components from registered features and optional tabs for Slack, Stytch auth, and MailerSend email integrations.

Changes:

  • New kairo-admin module with complete admin dashboard implementation
  • New kairo-kdocs module for serving Dokka-generated API documentation
  • Sample application demonstrating admin dashboard usage with library book/author CRUD
  • REST endpoint tracking enhancements to capture registered endpoints
  • Enhanced DependencyInjectionFeature and HealthCheckFeature for admin dashboard integration

Reviewed changes

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

Show a summary per file
File Description
settings.gradle.kts Added new modules: kairo-admin, kairo-kdocs, sample-kairo-admin
kairo-admin/* Complete admin dashboard implementation with collectors, handlers, views, and models
kairo-kdocs/* Feature for serving Dokka-generated documentation as static resources
sample-kairo-admin/* Sample application with LibraryBook and Author CRUD demonstrating admin dashboard
kairo-rest/* Added endpoint tracking and AuthReceiver enhancements for admin dashboard
kairo-dependency-injection/feature/* Exposed Koin instance for admin dashboard access
kairo-health-check/feature/* Exposed registered health checks for admin dashboard
buildSrc/* Added kairo-service-dokka Gradle plugin for packaging documentation
gradle/libs.versions.toml Added kotlinxHtml and ktorServer-htmlBuilder dependencies

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

?: return SqlQueryResult(emptyList(), emptyList(), 0, 0, "No database connection available.")
val connection = factory.create().awaitFirst()
try {
connection.createStatement("SET TRANSACTION READ ONLY").execute().awaitFirst()
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

The read-only transaction setting is applied but may not be effective for all database backends. PostgreSQL respects this, but the implementation should handle cases where the database doesn't support read-only transactions or where the setting fails silently. Consider wrapping this in a try-catch and logging a warning if it fails rather than failing the entire query.

Copilot uses AI. Check for mistakes.
Comment on lines +22 to +36
public fun validate(sql: String): String? {
val trimmed = stripComments(sql).trim()
if (trimmed.isEmpty()) {
return "Query cannot be empty."
}
val firstKeyword = trimmed.split("\\s+".toRegex()).firstOrNull()?.uppercase() ?: return "Invalid query."
if (firstKeyword in forbiddenKeywords) {
return "Only read-only queries are allowed. '$firstKeyword' statements are not permitted."
}
val allowedFirstKeywords = setOf("SELECT", "WITH", "EXPLAIN", "SHOW")
if (firstKeyword !in allowedFirstKeywords) {
return "Only SELECT, WITH, EXPLAIN, and SHOW statements are allowed. Got '$firstKeyword'."
}
return null
}
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

The SQL validator checks for forbidden keywords at the start of the query, but doesn't prevent these keywords from appearing in subqueries or CTEs. A malicious user could potentially use a WITH clause followed by an UPDATE/DELETE. For example: "WITH data AS (SELECT 1) UPDATE table SET...". Consider implementing more robust SQL parsing or using a whitelist approach that only allows specific patterns.

Copilot uses AI. Check for mistakes.
@adrw
Copy link
Copy Markdown
Collaborator Author

adrw commented Apr 17, 2026

New version of this existing PR https://github.com/hudson155/kairo/pull/1149

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.

2 participants