summaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
authorPeter Stone <thepeterstone@gmail.com>2026-01-28 22:19:28 -1000
committerPeter Stone <thepeterstone@gmail.com>2026-01-28 22:19:28 -1000
commit05b1930e04ac222d73ffb2f45c1b1febb69f893d (patch)
treebc451d72b5265ff044c4655ed90685c601688b6d /cmd
parent058ff7d699f088edb851336928dd3eea2934cc07 (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.go33
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