feat(logs): add admin aggregated logs endpoint#10
Open
whoabuddy wants to merge 15 commits into
Open
Conversation
- Add staging/production environments in wrangler.jsonc - Add fork notice and maintenance docs to CLAUDE.md Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove logs.wbd.host route from top-level (only used for local dev) - Use staging KV namespace ID for local development - The previous ID was from whoabuddy account, not aibtcdev Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Previously DELETE /apps/:id required the app's own API key. Now admins can also delete apps using the X-Admin-Key header, consistent with other admin operations. Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* feat: allow admin key to delete apps Previously DELETE /apps/:id required the app's own API key. Now admins can also delete apps using the X-Admin-Key header, consistent with other admin operations. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(dashboard): overhaul with unified view and advanced filtering (#3) - Add unified overview page showing all apps with error trends and health status - Add enhanced app detail page with 7-day stats chart (Chart.js) - Add advanced filtering: date range picker, request ID, context field filters - Add server-side search and context filtering to Durable Object - Modularize dashboard into separate files for maintainability - Integrate Alpine.js for declarative client-side state management - Add SVG sparklines and trend indicators for quick status overview New file structure: src/dashboard/ index.ts - Main router auth.ts - Session management styles.ts - Shared styles types.ts - Dashboard types pages/ - Login, overview, app-detail api/ - Overview aggregation endpoint components/ - Layout, charts utilities Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> * chore: remove deprecated dashboard.ts Replaced by modular src/dashboard/ directory. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
…tilities (#4) (#6) * refactor: remove dead code and extract shared utilities - Delete unused src/services/stats.ts (legacy KV-based stats, replaced by DO SQLite) - Extract getAppDO and countByLevel to src/utils.ts - countByLevel now uses Map for O(n) instead of O(n²) array scanning * refactor: consolidate duplicated code and remove unused functions Dashboard: - Extract getAppList, getAppName, getHealthUrls to shared helpers.ts - Fix type safety: replace `any` with proper Context type Result utilities: - Add wrapError() for consistent error handling in catch blocks - Remove unused exports: isOk, isErr, getErrorStatus, ErrorStatusMap Registry service: - Use wrapError() instead of inline error handling (6 occurrences) - Remove unused validateApiKey and regenerateApiKey functions * chore: remove unused dashboard code - Remove unused loadingSpinner component from layout.ts - Remove unused appOptions variable from header function - Remove unused types: SavedFilter, FilterState, HealthSummary - Remove unused HealthCheck import from types.ts --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
- Add GitHub Actions workflow for release-please - Configure extra-files to update version in src/index.ts - Sync package.json version to 0.4.0 to match API response - Add x-release-please-version marker for automatic version updates Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* feat(dashboard): apply AIBTC brand guidelines to dashboard UI Add AIBTC brand identity across all dashboard pages: logo, favicon, Roc Grotesk font, brand orange (#FF4F03) accent color, dark gradient background with pattern overlay, and card glow/hover effects matching the x402-api and x402-sponsor-relay dashboards. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * use css var over direct def Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * add safari explicit Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fix(dashboard): address PR review feedback - Use event delegation for card glow mouse tracking instead of per-element listeners to prevent memory leaks with dynamic content - Scope focus ring to focus-visible with opt-out classes (log-level, icon-button) so semantic elements keep default focus styling - Broaden text-blue-400 override to all elements except .log-level so non-anchor brand links also get orange accent - Replace hardcoded color values in Tailwind overrides with CSS variables (--bg-table-header, --bg-input, --bg-input-hover, etc.) - Add --accent-hover CSS variable, replace inline onmouseover/onmouseout on login button with .btn-accent CSS class - Add z-index layering to card glow (z-index: 0 on ::after, z-index: 1 on .brand-card > * children) so content renders above glow effect - Replace hardcoded #111 dropdown background with var(--bg-card) - Remove unused brand color object from styles.ts (CSS variables used) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* feat(dashboard): add BrandConfig type and getBrandConfig env reader Phase 1 of configurable branding quest. Defines BrandConfig interface with all brand values, AIBTC defaults, and getBrandConfig() that reads BRAND_* environment variables with automatic accent color derivation and CDN URL composition. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor(dashboard): generate brand CSS from BrandConfig Phase 2 of configurable branding quest. Replaces static brandCss with buildBrandCss(config) that generates CSS from BrandConfig values. Updates htmlDocument and header to accept brand config via LayoutOptions. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor(dashboard): thread BrandConfig through router and pages Phase 3 of configurable branding quest. Resolves brand config from env vars once per request via middleware. All page functions accept BrandConfig and forward it to layout components. Changes: - Add middleware to resolve brand config from env on each request - Update Hono generic to include Variables with brand config - Thread brand config through all page functions (login, overview, app-detail) - Update page functions to pass brand to layout components - Type helper functions to accept contexts with Variables Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(dashboard): add brand env vars to wrangler and brand config tests Add BRAND_NAME, BRAND_ACCENT, and BRAND_CDN_URL environment variables to staging and production wrangler.jsonc environments with AIBTC defaults. Add comprehensive tests for getBrandConfig() covering defaults, env overrides, CDN URL derivation, accent color derivation, and individual URL overrides. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(dashboard): address PR review feedback on brand config - Validate hex colors with regex, fallback to default on invalid input - Remove unused accentRgb variable - Add BrandEnv type to eliminate unsafe cast in router middleware - Escape brand values in HTML attributes (defense-in-depth) - Add tests for invalid hex inputs and accent fallback Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
The health-urls endpoint only accepted per-app API keys, preventing admin users from configuring health check URLs. Switch to requireApiKeyOrAdmin middleware to match the pattern used by other app management endpoints. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
When admin calls GET /logs without X-App-ID, iterates all registered apps from KV, queries each app's DO in parallel, and returns combined log entries with app_id field on each entry. Preserves existing single-app behavior when X-App-ID header is provided (for both API key and admin auth paths). Per-app limit is calculated as max(10, ceil(globalLimit / numApps)) to avoid overloading any single DO. Results are merged, sorted by timestamp DESC, and truncated to the global limit. Also exports AggregatedLogEntry type (LogEntry + app_id) from types.ts for consumers that need to type-check aggregated responses. Co-Authored-By: Claude <noreply@anthropic.com>
Tests cover: - GET /logs with admin key and no X-App-ID returns combined entries from all registered apps, each with an app_id field - Level filter (e.g., ?level=ERROR) is forwarded to each app's DO - Global limit (e.g., ?limit=2) caps the total results returned - GET /logs with admin key AND X-App-ID falls through to single-app path, returning raw DO response without app_id field Adds beforeAll setup that creates two apps (agg-app-1, agg-app-2) and writes distinct log levels to each so assertions can verify cross-app aggregation. Co-Authored-By: Claude <noreply@anthropic.com>
…ndpoint Extend the "Admin aggregated logs" integration test suite with 7 new tests that cover scenarios not already tested in Phase 1: Auth edge cases: - No auth (missing both X-Admin-Key and X-App-ID) returns 400 - Invalid admin key returns 401 Aggregated filter scenarios (new nested describe with isolated app fixtures): - since=far-future timestamp returns empty array (filter applied per-app) - until=far-past timestamp returns empty array - search filter returns matching entries across multiple apps - context.* filter returns entries with matching JSON context field - request_id filter returns exactly the one matching entry with correct app_id Each test verifies that app_id field is present on aggregated results and that filters are correctly propagated to per-app DO queries. Co-Authored-By: Claude <noreply@anthropic.com>
…sed test variables Replace verbose has/get/parseInt pattern with Number() + nullish fallback for the globalLimit parameter. Remove dead-code queryString conditional since perAppParams always contains at least the limit key. Remove unused filterApiKey1/filterApiKey2 variables from test setup -- the filter tests authenticate exclusively via admin key. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
GET /logswithoutX-App-IDheader now returns logs from all registered apps, withapp_idon each entryTest plan
npm test)GET /logsbehavior unchangedX-App-IDstill returns single-app logsX-App-IDreturns aggregated logs withapp_idfield🤖 Generated with Claude Code