diff options
| author | Peter Stone <thepeterstone@gmail.com> | 2026-01-28 22:19:28 -1000 |
|---|---|---|
| committer | Peter Stone <thepeterstone@gmail.com> | 2026-01-28 22:19:28 -1000 |
| commit | 05b1930e04ac222d73ffb2f45c1b1febb69f893d (patch) | |
| tree | bc451d72b5265ff044c4655ed90685c601688b6d /cmd | |
| parent | 058ff7d699f088edb851336928dd3eea2934cc07 (diff) | |
Add Agent Context API for external agent integration
Phase 1: Authentication and read-only context
- POST /agent/auth/request - request access with name + agent_id
- GET /agent/auth/poll - poll for approval status
- POST /agent/auth/approve|deny - user approval (browser auth required)
- GET /agent/context - 7-day timeline context (agent session required)
Phase 1.5: Browser-only agent endpoints (HTML pages)
- GET /agent/web/request - request page with token
- GET /agent/web/status - status page with polling
- GET /agent/web/context - context page with timeline data
WebSocket notifications:
- GET /ws/notifications - push agent requests to browsers
- Approval modal with trust indicators and countdown timer
Database:
- agents table for registered agent tracking
- agent_sessions table for pending/active sessions
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Diffstat (limited to 'cmd')
| -rw-r--r-- | cmd/dashboard/main.go | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/cmd/dashboard/main.go b/cmd/dashboard/main.go index ce91e6e..8f87e30 100644 --- a/cmd/dashboard/main.go +++ b/cmd/dashboard/main.go @@ -136,6 +136,9 @@ func main() { // Rate limiter for auth endpoints authRateLimiter := appmiddleware.NewRateLimiter(config.AuthRateLimitRequests, config.AuthRateLimitWindow) + // Rate limiter for agent auth (stricter - 10 requests/minute per IP) + agentAuthRateLimiter := appmiddleware.NewRateLimiter(10, time.Minute) + // Public routes (no auth required) r.Get("/login", authHandlers.HandleLoginPage) r.With(authRateLimiter.Limit).Post("/login", authHandlers.HandleLogin) @@ -148,6 +151,33 @@ func main() { // Conditions page (public - no auth required) r.Get("/conditions", h.HandleConditionsPage) + // Agent API + r.Route("/agent", func(r chi.Router) { + // Public endpoints (no browser auth, but rate limited) + r.With(agentAuthRateLimiter.Limit).Post("/auth/request", h.HandleAgentAuthRequest) + r.Get("/auth/poll", h.HandleAgentAuthPoll) + + // Browser auth required for approve/deny + r.Group(func(r chi.Router) { + r.Use(authHandlers.Middleware().RequireAuth) + r.Post("/auth/approve", h.HandleAgentAuthApprove) + r.Post("/auth/deny", h.HandleAgentAuthDeny) + }) + + // Agent session required for context + r.Group(func(r chi.Router) { + r.Use(h.AgentAuthMiddleware) + r.Get("/context", h.HandleAgentContext) + }) + + // HTML endpoints for browser-only agents (GET requests only) + r.Route("/web", func(r chi.Router) { + r.With(agentAuthRateLimiter.Limit).Get("/request", h.HandleAgentWebRequest) + r.Get("/status", h.HandleAgentWebStatus) + r.Get("/context", h.HandleAgentWebContext) + }) + }) + // Protected routes (auth required) r.Group(func(r chi.Router) { r.Use(authHandlers.Middleware().RequireAuth) @@ -201,6 +231,9 @@ func main() { // Shopping mode (focused single-store view) r.Get("/shopping/mode/{store}", h.HandleShoppingMode) r.Post("/shopping/mode/{store}/toggle", h.HandleShoppingModeToggle) + + // WebSocket for notifications + r.Get("/ws/notifications", h.HandleWebSocket) }) // Start server |
