@stackmemoryai/stackmemory 0.2.8 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/core/agent-task-manager.js +512 -0
- package/dist/agents/core/agent-task-manager.js.map +7 -0
- package/dist/agents/verifiers/base-verifier.js +129 -0
- package/dist/agents/verifiers/base-verifier.js.map +7 -0
- package/dist/agents/verifiers/formatter-verifier.js +126 -0
- package/dist/agents/verifiers/formatter-verifier.js.map +7 -0
- package/dist/agents/verifiers/llm-judge.js +248 -0
- package/dist/agents/verifiers/llm-judge.js.map +7 -0
- package/dist/cli/__tests__/index.test.js +290 -0
- package/dist/cli/__tests__/index.test.js.map +7 -0
- package/dist/cli/auto-detect.js +317 -0
- package/dist/cli/auto-detect.js.map +7 -0
- package/dist/cli/browser-test.js +29 -0
- package/dist/cli/browser-test.js.map +7 -0
- package/dist/cli/claude-sm.js +369 -0
- package/dist/cli/claude-sm.js.map +7 -0
- package/dist/cli/codex-sm.js +283 -0
- package/dist/cli/codex-sm.js.map +7 -0
- package/dist/cli/commands/agent.js +286 -0
- package/dist/cli/commands/agent.js.map +7 -0
- package/dist/cli/commands/config.js +199 -0
- package/dist/cli/commands/config.js.map +7 -0
- package/dist/cli/commands/context.js +327 -0
- package/dist/cli/commands/context.js.map +7 -0
- package/dist/cli/commands/handoff.js +191 -0
- package/dist/cli/commands/handoff.js.map +7 -0
- package/dist/cli/commands/linear-test.js +115 -0
- package/dist/cli/commands/linear-test.js.map +7 -0
- package/dist/cli/commands/linear.js +378 -0
- package/dist/cli/commands/linear.js.map +7 -0
- package/dist/cli/commands/log.js +165 -0
- package/dist/cli/commands/log.js.map +7 -0
- package/dist/cli/commands/onboard.js +349 -0
- package/dist/cli/commands/onboard.js.map +7 -0
- package/dist/cli/commands/projects.js +195 -0
- package/dist/cli/commands/projects.js.map +7 -0
- package/dist/cli/commands/search.js +152 -0
- package/dist/cli/commands/search.js.map +7 -0
- package/dist/cli/commands/session.js +179 -0
- package/dist/cli/commands/session.js.map +7 -0
- package/dist/cli/commands/tasks.js +205 -0
- package/dist/cli/commands/tasks.js.map +7 -0
- package/dist/cli/commands/webhook.js +131 -0
- package/dist/cli/commands/webhook.js.map +7 -0
- package/dist/cli/commands/worktree.js +276 -0
- package/dist/cli/commands/worktree.js.map +7 -0
- package/dist/cli/index.js +953 -0
- package/dist/cli/index.js.map +7 -0
- package/dist/cli/utils/viewer.js +92 -0
- package/dist/cli/utils/viewer.js.map +7 -0
- package/dist/core/config/__tests__/config-manager.test.js +248 -0
- package/dist/core/config/__tests__/config-manager.test.js.map +7 -0
- package/dist/core/config/config-manager.js +368 -0
- package/dist/core/config/config-manager.js.map +7 -0
- package/dist/core/config/types.js +140 -0
- package/dist/core/config/types.js.map +7 -0
- package/dist/core/context/__tests__/frame-manager.test.js +879 -0
- package/dist/core/context/__tests__/frame-manager.test.js.map +7 -0
- package/dist/core/context/auto-context.js +72 -0
- package/dist/core/context/auto-context.js.map +7 -0
- package/dist/core/context/compaction-handler.js +326 -0
- package/dist/core/context/compaction-handler.js.map +7 -0
- package/dist/core/context/frame-database.js +376 -0
- package/dist/core/context/frame-database.js.map +7 -0
- package/dist/core/context/frame-digest.js +239 -0
- package/dist/core/context/frame-digest.js.map +7 -0
- package/dist/core/context/frame-manager.js +682 -0
- package/dist/core/context/frame-manager.js.map +7 -0
- package/dist/core/context/frame-stack.js +270 -0
- package/dist/core/context/frame-stack.js.map +7 -0
- package/dist/core/context/frame-types.js +1 -0
- package/dist/core/context/frame-types.js.map +7 -0
- package/dist/core/context/index.js +33 -0
- package/dist/core/context/index.js.map +7 -0
- package/dist/core/context/model-aware-compaction.js +619 -0
- package/dist/core/context/model-aware-compaction.js.map +7 -0
- package/dist/core/context/refactored-frame-manager.js +393 -0
- package/dist/core/context/refactored-frame-manager.js.map +7 -0
- package/dist/core/database/batch-operations.js +329 -0
- package/dist/core/database/batch-operations.js.map +7 -0
- package/dist/core/database/connection-pool.js +224 -0
- package/dist/core/database/connection-pool.js.map +7 -0
- package/dist/core/database/query-cache.js +284 -0
- package/dist/core/database/query-cache.js.map +7 -0
- package/dist/core/digest/__tests__/enhanced-hybrid-digest.test.js +379 -0
- package/dist/core/digest/__tests__/enhanced-hybrid-digest.test.js.map +7 -0
- package/dist/core/digest/__tests__/frame-digest-integration.test.js +230 -0
- package/dist/core/digest/__tests__/frame-digest-integration.test.js.map +7 -0
- package/dist/core/digest/enhanced-hybrid-digest.js +267 -0
- package/dist/core/digest/enhanced-hybrid-digest.js.map +7 -0
- package/dist/core/digest/frame-digest-integration.js +172 -0
- package/dist/core/digest/frame-digest-integration.js.map +7 -0
- package/dist/core/digest/hybrid-digest-generator.js +549 -0
- package/dist/core/digest/hybrid-digest-generator.js.map +7 -0
- package/dist/core/digest/index.js +5 -0
- package/dist/core/digest/index.js.map +7 -0
- package/dist/core/digest/types.js +21 -0
- package/dist/core/digest/types.js.map +7 -0
- package/dist/core/errors/__tests__/error-handling.test.js +270 -0
- package/dist/core/errors/__tests__/error-handling.test.js.map +7 -0
- package/dist/core/errors/index.js +239 -0
- package/dist/core/errors/index.js.map +7 -0
- package/dist/core/errors/recovery.js +258 -0
- package/dist/core/errors/recovery.js.map +7 -0
- package/dist/core/merge/__tests__/conflict-scenarios.test.js +414 -0
- package/dist/core/merge/__tests__/conflict-scenarios.test.js.map +7 -0
- package/dist/core/merge/conflict-detector.js +424 -0
- package/dist/core/merge/conflict-detector.js.map +7 -0
- package/dist/core/merge/index.js +5 -0
- package/dist/core/merge/index.js.map +7 -0
- package/dist/core/merge/resolution-engine.js +565 -0
- package/dist/core/merge/resolution-engine.js.map +7 -0
- package/dist/core/merge/stack-diff.js +528 -0
- package/dist/core/merge/stack-diff.js.map +7 -0
- package/dist/core/merge/types.js +1 -0
- package/dist/core/merge/types.js.map +7 -0
- package/dist/core/monitoring/error-handler.js +278 -0
- package/dist/core/monitoring/error-handler.js.map +7 -0
- package/dist/core/monitoring/logger.js +115 -0
- package/dist/core/monitoring/logger.js.map +7 -0
- package/dist/core/monitoring/metrics.js +157 -0
- package/dist/core/monitoring/metrics.js.map +7 -0
- package/dist/core/monitoring/progress-tracker.js +174 -0
- package/dist/core/monitoring/progress-tracker.js.map +7 -0
- package/dist/core/performance/context-cache.js +269 -0
- package/dist/core/performance/context-cache.js.map +7 -0
- package/dist/core/performance/index.js +7 -0
- package/dist/core/performance/index.js.map +7 -0
- package/dist/core/performance/lazy-context-loader.js +319 -0
- package/dist/core/performance/lazy-context-loader.js.map +7 -0
- package/dist/core/performance/monitor.js +217 -0
- package/dist/core/performance/monitor.js.map +7 -0
- package/dist/core/performance/optimized-frame-context.js +326 -0
- package/dist/core/performance/optimized-frame-context.js.map +7 -0
- package/dist/core/performance/performance-benchmark.js +269 -0
- package/dist/core/performance/performance-benchmark.js.map +7 -0
- package/dist/core/performance/performance-profiler.js +318 -0
- package/dist/core/performance/performance-profiler.js.map +7 -0
- package/dist/core/performance/streaming-jsonl-parser.js +187 -0
- package/dist/core/performance/streaming-jsonl-parser.js.map +7 -0
- package/dist/core/persistence/postgres-adapter.js +345 -0
- package/dist/core/persistence/postgres-adapter.js.map +7 -0
- package/dist/core/projects/project-manager.js +699 -0
- package/dist/core/projects/project-manager.js.map +7 -0
- package/dist/core/query/__tests__/query-parser.test.js +301 -0
- package/dist/core/query/__tests__/query-parser.test.js.map +7 -0
- package/dist/core/query/__tests__/query-templates.test.js +210 -0
- package/dist/core/query/__tests__/query-templates.test.js.map +7 -0
- package/dist/core/query/query-parser.js +366 -0
- package/dist/core/query/query-parser.js.map +7 -0
- package/dist/core/query/query-templates.js +317 -0
- package/dist/core/query/query-templates.js.map +7 -0
- package/dist/core/retrieval/index.js +4 -0
- package/dist/core/retrieval/index.js.map +7 -0
- package/dist/core/retrieval/llm-context-retrieval.js +577 -0
- package/dist/core/retrieval/llm-context-retrieval.js.map +7 -0
- package/dist/core/retrieval/summary-generator.js +585 -0
- package/dist/core/retrieval/summary-generator.js.map +7 -0
- package/dist/core/retrieval/types.js +17 -0
- package/dist/core/retrieval/types.js.map +7 -0
- package/dist/core/session/index.js +11 -0
- package/dist/core/session/index.js.map +7 -0
- package/dist/core/session/session-manager.js +297 -0
- package/dist/core/session/session-manager.js.map +7 -0
- package/dist/core/trace/cli-trace-wrapper.js +110 -0
- package/dist/core/trace/cli-trace-wrapper.js.map +7 -0
- package/dist/core/trace/db-trace-wrapper.js +215 -0
- package/dist/core/trace/db-trace-wrapper.js.map +7 -0
- package/dist/core/trace/debug-trace.js +385 -0
- package/dist/core/trace/debug-trace.js.map +7 -0
- package/dist/core/trace/index.js +158 -0
- package/dist/core/trace/index.js.map +7 -0
- package/dist/core/trace/linear-api-wrapper.js +169 -0
- package/dist/core/trace/linear-api-wrapper.js.map +7 -0
- package/dist/core/trace/trace-demo.js +135 -0
- package/dist/core/trace/trace-demo.js.map +7 -0
- package/dist/core/trace/trace-detector.demo.js +138 -0
- package/dist/core/trace/trace-detector.demo.js.map +7 -0
- package/dist/core/trace/trace-detector.js +386 -0
- package/dist/core/trace/trace-detector.js.map +7 -0
- package/dist/core/trace/trace-detector.test.js +401 -0
- package/dist/core/trace/trace-detector.test.js.map +7 -0
- package/dist/core/trace/trace-store.js +341 -0
- package/dist/core/trace/trace-store.js.map +7 -0
- package/dist/core/trace/types.js +73 -0
- package/dist/core/trace/types.js.map +7 -0
- package/dist/core/types.js +1 -0
- package/dist/core/types.js.map +7 -0
- package/dist/core/utils/update-checker.js +214 -0
- package/dist/core/utils/update-checker.js.map +7 -0
- package/dist/core/worktree/worktree-manager.js +450 -0
- package/dist/core/worktree/worktree-manager.js.map +7 -0
- package/dist/features/analytics/api/analytics-api.js +283 -0
- package/dist/features/analytics/api/analytics-api.js.map +7 -0
- package/dist/features/analytics/core/analytics-service.js +267 -0
- package/dist/features/analytics/core/analytics-service.js.map +7 -0
- package/dist/features/analytics/index.js +14 -0
- package/dist/features/analytics/index.js.map +7 -0
- package/dist/features/analytics/queries/metrics-queries.js +273 -0
- package/dist/features/analytics/queries/metrics-queries.js.map +7 -0
- package/dist/features/analytics/types/metrics.js +1 -0
- package/dist/features/analytics/types/metrics.js.map +7 -0
- package/dist/features/browser/browser-mcp.js +488 -0
- package/dist/features/browser/browser-mcp.js.map +7 -0
- package/dist/features/tasks/__tests__/pebbles-task-store.test.js +747 -0
- package/dist/features/tasks/__tests__/pebbles-task-store.test.js.map +7 -0
- package/dist/features/tasks/pebbles-task-store.js +647 -0
- package/dist/features/tasks/pebbles-task-store.js.map +7 -0
- package/dist/features/tasks/task-aware-context.js +406 -0
- package/dist/features/tasks/task-aware-context.js.map +7 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +7 -0
- package/dist/integrations/linear/__tests__/auth.test.js +558 -0
- package/dist/integrations/linear/__tests__/auth.test.js.map +7 -0
- package/dist/integrations/linear/__tests__/sync-service.test.js +760 -0
- package/dist/integrations/linear/__tests__/sync-service.test.js.map +7 -0
- package/dist/integrations/linear/auth.js +308 -0
- package/dist/integrations/linear/auth.js.map +7 -0
- package/dist/integrations/linear/auto-sync.js +244 -0
- package/dist/integrations/linear/auto-sync.js.map +7 -0
- package/dist/integrations/linear/client.js +448 -0
- package/dist/integrations/linear/client.js.map +7 -0
- package/dist/integrations/linear/config.js +115 -0
- package/dist/integrations/linear/config.js.map +7 -0
- package/dist/integrations/linear/sync-manager.js +233 -0
- package/dist/integrations/linear/sync-manager.js.map +7 -0
- package/dist/integrations/linear/sync-service.js +214 -0
- package/dist/integrations/linear/sync-service.js.map +7 -0
- package/dist/integrations/linear/sync.js +565 -0
- package/dist/integrations/linear/sync.js.map +7 -0
- package/dist/integrations/linear/types.js +1 -0
- package/dist/integrations/linear/types.js.map +7 -0
- package/dist/integrations/linear/webhook-server.js +204 -0
- package/dist/integrations/linear/webhook-server.js.map +7 -0
- package/dist/integrations/linear/webhook.js +269 -0
- package/dist/integrations/linear/webhook.js.map +7 -0
- package/dist/integrations/mcp/__tests__/server.test.js +798 -0
- package/dist/integrations/mcp/__tests__/server.test.js.map +7 -0
- package/dist/integrations/mcp/handlers/context-handlers.js +253 -0
- package/dist/integrations/mcp/handlers/context-handlers.js.map +7 -0
- package/dist/integrations/mcp/handlers/index.js +134 -0
- package/dist/integrations/mcp/handlers/index.js.map +7 -0
- package/dist/integrations/mcp/handlers/linear-handlers.js +243 -0
- package/dist/integrations/mcp/handlers/linear-handlers.js.map +7 -0
- package/dist/integrations/mcp/handlers/task-handlers.js +235 -0
- package/dist/integrations/mcp/handlers/task-handlers.js.map +7 -0
- package/dist/integrations/mcp/handlers/trace-handlers.js +304 -0
- package/dist/integrations/mcp/handlers/trace-handlers.js.map +7 -0
- package/dist/integrations/mcp/index.js +19 -0
- package/dist/integrations/mcp/index.js.map +7 -0
- package/dist/integrations/mcp/refactored-server.js +331 -0
- package/dist/integrations/mcp/refactored-server.js.map +7 -0
- package/dist/integrations/mcp/server.js +1621 -0
- package/dist/integrations/mcp/server.js.map +7 -0
- package/dist/integrations/mcp/tool-definitions.js +562 -0
- package/dist/integrations/mcp/tool-definitions.js.map +7 -0
- package/dist/integrations/mcp/trace-test.js +44 -0
- package/dist/integrations/mcp/trace-test.js.map +7 -0
- package/dist/integrations/pg-aiguide/embedding-provider.js +174 -0
- package/dist/integrations/pg-aiguide/embedding-provider.js.map +7 -0
- package/dist/integrations/pg-aiguide/semantic-search.js +183 -0
- package/dist/integrations/pg-aiguide/semantic-search.js.map +7 -0
- package/dist/integrations/pg-aiguide/timescale-analytics.js +220 -0
- package/dist/integrations/pg-aiguide/timescale-analytics.js.map +7 -0
- package/dist/mcp/stackmemory-mcp-server.js +550 -0
- package/dist/mcp/stackmemory-mcp-server.js.map +7 -0
- package/dist/middleware/exponential-rate-limiter.js +285 -0
- package/dist/middleware/exponential-rate-limiter.js.map +7 -0
- package/dist/models/user.model.js +351 -0
- package/dist/models/user.model.js.map +7 -0
- package/dist/scripts/benchmark-performance.d.ts +7 -0
- package/dist/scripts/benchmark-performance.d.ts.map +1 -0
- package/dist/scripts/benchmark-performance.js +44 -0
- package/dist/scripts/benchmark-performance.js.map +1 -0
- package/dist/scripts/cleanup-duplicate-tasks.d.ts +12 -0
- package/dist/scripts/cleanup-duplicate-tasks.d.ts.map +1 -0
- package/dist/scripts/cleanup-duplicate-tasks.js +215 -0
- package/dist/scripts/cleanup-duplicate-tasks.js.map +1 -0
- package/dist/servers/production/auth-middleware.js +513 -0
- package/dist/servers/production/auth-middleware.js.map +7 -0
- package/dist/servers/railway/index.js +390 -0
- package/dist/servers/railway/index.js.map +7 -0
- package/dist/services/config-service.js +62 -0
- package/dist/services/config-service.js.map +7 -0
- package/dist/services/context-service.js +191 -0
- package/dist/services/context-service.js.map +7 -0
- package/dist/src/agents/core/agent-task-manager.d.ts +154 -0
- package/dist/src/agents/core/agent-task-manager.d.ts.map +1 -0
- package/dist/src/agents/core/agent-task-manager.js +504 -0
- package/dist/src/agents/core/agent-task-manager.js.map +1 -0
- package/dist/src/agents/verifiers/base-verifier.d.ts +112 -0
- package/dist/src/agents/verifiers/base-verifier.d.ts.map +1 -0
- package/dist/src/agents/verifiers/base-verifier.js +130 -0
- package/dist/src/agents/verifiers/base-verifier.js.map +1 -0
- package/dist/src/agents/verifiers/formatter-verifier.d.ts +14 -0
- package/dist/src/agents/verifiers/formatter-verifier.d.ts.map +1 -0
- package/dist/src/agents/verifiers/formatter-verifier.js +107 -0
- package/dist/src/agents/verifiers/formatter-verifier.js.map +1 -0
- package/dist/src/agents/verifiers/llm-judge.d.ts +46 -0
- package/dist/src/agents/verifiers/llm-judge.d.ts.map +1 -0
- package/dist/src/agents/verifiers/llm-judge.js +248 -0
- package/dist/src/agents/verifiers/llm-judge.js.map +1 -0
- package/dist/src/cli/claude-sm.js +55 -0
- package/dist/src/cli/claude-sm.js.map +1 -1
- package/dist/src/cli/commands/agent.d.ts +9 -0
- package/dist/src/cli/commands/agent.d.ts.map +1 -0
- package/dist/src/cli/commands/agent.js +303 -0
- package/dist/src/cli/commands/agent.js.map +1 -0
- package/dist/src/cli/commands/handoff.d.ts +6 -0
- package/dist/src/cli/commands/handoff.d.ts.map +1 -0
- package/dist/src/cli/commands/handoff.js +212 -0
- package/dist/src/cli/commands/handoff.js.map +1 -0
- package/dist/src/cli/index.d.ts.map +1 -1
- package/dist/src/cli/index.js +4 -0
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/core/context/compaction-handler.d.ts.map +1 -1
- package/dist/src/core/context/compaction-handler.js +1 -1
- package/dist/src/core/context/compaction-handler.js.map +1 -1
- package/dist/src/core/context/frame-database.d.ts +59 -0
- package/dist/src/core/context/frame-database.d.ts.map +1 -0
- package/dist/src/core/context/frame-database.js +333 -0
- package/dist/src/core/context/frame-database.js.map +1 -0
- package/dist/src/core/context/frame-digest.d.ts +59 -0
- package/dist/src/core/context/frame-digest.d.ts.map +1 -0
- package/dist/src/core/context/frame-digest.js +264 -0
- package/dist/src/core/context/frame-digest.js.map +1 -0
- package/dist/src/core/context/frame-manager.d.ts +2 -0
- package/dist/src/core/context/frame-manager.d.ts.map +1 -1
- package/dist/src/core/context/frame-manager.js +7 -0
- package/dist/src/core/context/frame-manager.js.map +1 -1
- package/dist/src/core/context/frame-stack.d.ts +85 -0
- package/dist/src/core/context/frame-stack.d.ts.map +1 -0
- package/dist/src/core/context/frame-stack.js +287 -0
- package/dist/src/core/context/frame-stack.js.map +1 -0
- package/dist/src/core/context/frame-types.d.ts +67 -0
- package/dist/src/core/context/frame-types.d.ts.map +1 -0
- package/dist/src/core/context/frame-types.js +6 -0
- package/dist/src/core/context/frame-types.js.map +1 -0
- package/dist/src/core/context/index.d.ts +11 -0
- package/dist/src/core/context/index.d.ts.map +1 -0
- package/dist/src/core/context/index.js +14 -0
- package/dist/src/core/context/index.js.map +1 -0
- package/dist/src/core/context/refactored-frame-manager.d.ts +99 -0
- package/dist/src/core/context/refactored-frame-manager.d.ts.map +1 -0
- package/dist/src/core/context/refactored-frame-manager.js +340 -0
- package/dist/src/core/context/refactored-frame-manager.js.map +1 -0
- package/dist/src/core/database/batch-operations.d.ts +118 -0
- package/dist/src/core/database/batch-operations.d.ts.map +1 -0
- package/dist/src/core/database/batch-operations.js +339 -0
- package/dist/src/core/database/batch-operations.js.map +1 -0
- package/dist/src/core/database/connection-pool.d.ts +79 -0
- package/dist/src/core/database/connection-pool.d.ts.map +1 -0
- package/dist/src/core/database/connection-pool.js +236 -0
- package/dist/src/core/database/connection-pool.js.map +1 -0
- package/dist/src/core/database/query-cache.d.ts +135 -0
- package/dist/src/core/database/query-cache.d.ts.map +1 -0
- package/dist/src/core/database/query-cache.js +294 -0
- package/dist/src/core/database/query-cache.js.map +1 -0
- package/dist/src/core/digest/enhanced-hybrid-digest.d.ts +125 -0
- package/dist/src/core/digest/enhanced-hybrid-digest.d.ts.map +1 -0
- package/dist/src/core/digest/enhanced-hybrid-digest.js +282 -0
- package/dist/src/core/digest/enhanced-hybrid-digest.js.map +1 -0
- package/dist/src/core/digest/frame-digest-integration.d.ts +67 -0
- package/dist/src/core/digest/frame-digest-integration.d.ts.map +1 -0
- package/dist/src/core/digest/frame-digest-integration.js +198 -0
- package/dist/src/core/digest/frame-digest-integration.js.map +1 -0
- package/dist/src/core/digest/hybrid-digest-generator.d.ts +76 -0
- package/dist/src/core/digest/hybrid-digest-generator.d.ts.map +1 -0
- package/dist/src/core/digest/hybrid-digest-generator.js +629 -0
- package/dist/src/core/digest/hybrid-digest-generator.js.map +1 -0
- package/dist/src/core/digest/index.d.ts +9 -0
- package/dist/src/core/digest/index.d.ts.map +1 -0
- package/dist/src/core/digest/index.js +9 -0
- package/dist/src/core/digest/index.js.map +1 -0
- package/dist/src/core/digest/types.d.ts +154 -0
- package/dist/src/core/digest/types.d.ts.map +1 -0
- package/dist/src/core/digest/types.js +18 -0
- package/dist/src/core/digest/types.js.map +1 -0
- package/dist/src/core/errors/index.d.ts +13 -5
- package/dist/src/core/errors/index.d.ts.map +1 -1
- package/dist/src/core/errors/index.js +13 -5
- package/dist/src/core/errors/index.js.map +1 -1
- package/dist/src/core/merge/conflict-detector.d.ts +122 -0
- package/dist/src/core/merge/conflict-detector.d.ts.map +1 -0
- package/dist/src/core/merge/conflict-detector.js +468 -0
- package/dist/src/core/merge/conflict-detector.js.map +1 -0
- package/dist/src/core/merge/index.d.ts +9 -0
- package/dist/src/core/merge/index.d.ts.map +1 -0
- package/dist/src/core/merge/index.js +9 -0
- package/dist/src/core/merge/index.js.map +1 -0
- package/dist/src/core/merge/resolution-engine.d.ts +120 -0
- package/dist/src/core/merge/resolution-engine.d.ts.map +1 -0
- package/dist/src/core/merge/resolution-engine.js +573 -0
- package/dist/src/core/merge/resolution-engine.js.map +1 -0
- package/dist/src/core/merge/stack-diff.d.ts +97 -0
- package/dist/src/core/merge/stack-diff.d.ts.map +1 -0
- package/dist/src/core/merge/stack-diff.js +516 -0
- package/dist/src/core/merge/stack-diff.js.map +1 -0
- package/dist/src/core/merge/types.d.ts +110 -0
- package/dist/src/core/merge/types.d.ts.map +1 -0
- package/dist/src/core/merge/types.js +6 -0
- package/dist/src/core/merge/types.js.map +1 -0
- package/dist/src/core/monitoring/logger.d.ts +2 -2
- package/dist/src/core/monitoring/logger.d.ts.map +1 -1
- package/dist/src/core/monitoring/logger.js +10 -5
- package/dist/src/core/monitoring/logger.js.map +1 -1
- package/dist/src/core/monitoring/metrics.d.ts +3 -0
- package/dist/src/core/monitoring/metrics.d.ts.map +1 -1
- package/dist/src/core/monitoring/metrics.js +142 -3
- package/dist/src/core/monitoring/metrics.js.map +1 -1
- package/dist/src/core/performance/context-cache.d.ts +109 -0
- package/dist/src/core/performance/context-cache.d.ts.map +1 -0
- package/dist/src/core/performance/context-cache.js +280 -0
- package/dist/src/core/performance/context-cache.js.map +1 -0
- package/dist/src/core/performance/index.d.ts +3 -0
- package/dist/src/core/performance/index.d.ts.map +1 -0
- package/dist/src/core/performance/index.js +3 -0
- package/dist/src/core/performance/index.js.map +1 -0
- package/dist/src/core/performance/lazy-context-loader.d.ts +93 -0
- package/dist/src/core/performance/lazy-context-loader.d.ts.map +1 -0
- package/dist/src/core/performance/lazy-context-loader.js +332 -0
- package/dist/src/core/performance/lazy-context-loader.js.map +1 -0
- package/dist/src/core/performance/monitor.d.ts +48 -0
- package/dist/src/core/performance/monitor.d.ts.map +1 -0
- package/dist/src/core/performance/monitor.js +226 -0
- package/dist/src/core/performance/monitor.js.map +1 -0
- package/dist/src/core/performance/optimized-frame-context.d.ts +74 -0
- package/dist/src/core/performance/optimized-frame-context.d.ts.map +1 -0
- package/dist/src/core/performance/optimized-frame-context.js +330 -0
- package/dist/src/core/performance/optimized-frame-context.js.map +1 -0
- package/dist/src/core/performance/performance-benchmark.d.ts +50 -0
- package/dist/src/core/performance/performance-benchmark.d.ts.map +1 -0
- package/dist/src/core/performance/performance-benchmark.js +290 -0
- package/dist/src/core/performance/performance-benchmark.js.map +1 -0
- package/dist/src/core/performance/performance-profiler.d.ts +151 -0
- package/dist/src/core/performance/performance-profiler.d.ts.map +1 -0
- package/dist/src/core/performance/performance-profiler.js +346 -0
- package/dist/src/core/performance/performance-profiler.js.map +1 -0
- package/dist/src/core/performance/streaming-jsonl-parser.d.ts +41 -0
- package/dist/src/core/performance/streaming-jsonl-parser.d.ts.map +1 -0
- package/dist/src/core/performance/streaming-jsonl-parser.js +193 -0
- package/dist/src/core/performance/streaming-jsonl-parser.js.map +1 -0
- package/dist/src/core/persistence/postgres-adapter.d.ts +31 -0
- package/dist/src/core/persistence/postgres-adapter.d.ts.map +1 -0
- package/dist/src/core/persistence/postgres-adapter.js +330 -0
- package/dist/src/core/persistence/postgres-adapter.js.map +1 -0
- package/dist/src/core/query/query-parser.d.ts +5 -0
- package/dist/src/core/query/query-parser.d.ts.map +1 -1
- package/dist/src/core/query/query-parser.js +86 -18
- package/dist/src/core/query/query-parser.js.map +1 -1
- package/dist/src/core/query/query-templates.d.ts +44 -0
- package/dist/src/core/query/query-templates.d.ts.map +1 -0
- package/dist/src/core/query/query-templates.js +326 -0
- package/dist/src/core/query/query-templates.js.map +1 -0
- package/dist/src/core/retrieval/llm-context-retrieval.d.ts +5 -3
- package/dist/src/core/retrieval/llm-context-retrieval.d.ts.map +1 -1
- package/dist/src/core/retrieval/llm-context-retrieval.js +73 -21
- package/dist/src/core/retrieval/llm-context-retrieval.js.map +1 -1
- package/dist/src/core/trace/cli-trace-wrapper.d.ts +23 -0
- package/dist/src/core/trace/cli-trace-wrapper.d.ts.map +1 -0
- package/dist/src/core/trace/cli-trace-wrapper.js +141 -0
- package/dist/src/core/trace/cli-trace-wrapper.js.map +1 -0
- package/dist/src/core/trace/db-trace-wrapper.d.ts +36 -0
- package/dist/src/core/trace/db-trace-wrapper.d.ts.map +1 -0
- package/dist/src/core/trace/db-trace-wrapper.js +252 -0
- package/dist/src/core/trace/db-trace-wrapper.js.map +1 -0
- package/dist/src/core/trace/debug-trace.d.ts +84 -0
- package/dist/src/core/trace/debug-trace.d.ts.map +1 -0
- package/dist/src/core/trace/debug-trace.js +402 -0
- package/dist/src/core/trace/debug-trace.js.map +1 -0
- package/dist/src/core/trace/error-test.d.ts +6 -0
- package/dist/src/core/trace/error-test.d.ts.map +1 -0
- package/dist/src/core/trace/error-test.js +128 -0
- package/dist/src/core/trace/error-test.js.map +1 -0
- package/dist/src/core/trace/index.d.ts +25 -0
- package/dist/src/core/trace/index.d.ts.map +1 -0
- package/dist/src/core/trace/index.js +121 -0
- package/dist/src/core/trace/index.js.map +1 -0
- package/dist/src/core/trace/linear-api-wrapper.d.ts +17 -0
- package/dist/src/core/trace/linear-api-wrapper.d.ts.map +1 -0
- package/dist/src/core/trace/linear-api-wrapper.js +205 -0
- package/dist/src/core/trace/linear-api-wrapper.js.map +1 -0
- package/dist/src/core/trace/performance-test.d.ts +6 -0
- package/dist/src/core/trace/performance-test.d.ts.map +1 -0
- package/dist/src/core/trace/performance-test.js +111 -0
- package/dist/src/core/trace/performance-test.js.map +1 -0
- package/dist/src/core/trace/trace-demo.d.ts +8 -0
- package/dist/src/core/trace/trace-demo.d.ts.map +1 -0
- package/dist/src/core/trace/trace-demo.js +154 -0
- package/dist/src/core/trace/trace-demo.js.map +1 -0
- package/dist/src/core/trace/trace-detector.d.ts +2 -2
- package/dist/src/core/trace/trace-detector.d.ts.map +1 -1
- package/dist/src/core/trace/trace-detector.demo.js +6 -6
- package/dist/src/core/trace/trace-detector.demo.js.map +1 -1
- package/dist/src/core/trace/trace-detector.js +3 -3
- package/dist/src/core/trace/trace-detector.js.map +1 -1
- package/dist/src/core/types.d.ts +35 -0
- package/dist/src/core/types.d.ts.map +1 -0
- package/dist/src/core/types.js +2 -0
- package/dist/src/core/types.js.map +1 -0
- package/dist/src/features/tasks/pebbles-task-store.d.ts +9 -2
- package/dist/src/features/tasks/pebbles-task-store.d.ts.map +1 -1
- package/dist/src/features/tasks/pebbles-task-store.js +97 -18
- package/dist/src/features/tasks/pebbles-task-store.js.map +1 -1
- package/dist/src/integrations/linear/auth.d.ts.map +1 -1
- package/dist/src/integrations/linear/auth.js.map +1 -1
- package/dist/src/integrations/linear/client.d.ts +15 -1
- package/dist/src/integrations/linear/client.d.ts.map +1 -1
- package/dist/src/integrations/linear/client.js +85 -3
- package/dist/src/integrations/linear/client.js.map +1 -1
- package/dist/src/integrations/linear/sync-manager.d.ts +2 -0
- package/dist/src/integrations/linear/sync-manager.d.ts.map +1 -1
- package/dist/src/integrations/linear/sync-manager.js +16 -4
- package/dist/src/integrations/linear/sync-manager.js.map +1 -1
- package/dist/src/integrations/linear/sync-service.d.ts +23 -2
- package/dist/src/integrations/linear/sync-service.d.ts.map +1 -1
- package/dist/src/integrations/linear/sync-service.js +44 -25
- package/dist/src/integrations/linear/sync-service.js.map +1 -1
- package/dist/src/integrations/linear/sync.d.ts +6 -0
- package/dist/src/integrations/linear/sync.d.ts.map +1 -1
- package/dist/src/integrations/linear/sync.js +27 -2
- package/dist/src/integrations/linear/sync.js.map +1 -1
- package/dist/src/integrations/linear/types.d.ts +16 -1
- package/dist/src/integrations/linear/types.d.ts.map +1 -1
- package/dist/src/integrations/linear/webhook-server.d.ts.map +1 -1
- package/dist/src/integrations/linear/webhook-server.js +10 -8
- package/dist/src/integrations/linear/webhook-server.js.map +1 -1
- package/dist/src/integrations/linear/webhook.d.ts +13 -0
- package/dist/src/integrations/linear/webhook.d.ts.map +1 -1
- package/dist/src/integrations/linear/webhook.js +101 -14
- package/dist/src/integrations/linear/webhook.js.map +1 -1
- package/dist/src/integrations/mcp/handlers/context-handlers.d.ts +39 -0
- package/dist/src/integrations/mcp/handlers/context-handlers.d.ts.map +1 -0
- package/dist/src/integrations/mcp/handlers/context-handlers.js +266 -0
- package/dist/src/integrations/mcp/handlers/context-handlers.js.map +1 -0
- package/dist/src/integrations/mcp/handlers/index.d.ts +37 -0
- package/dist/src/integrations/mcp/handlers/index.d.ts.map +1 -0
- package/dist/src/integrations/mcp/handlers/index.js +134 -0
- package/dist/src/integrations/mcp/handlers/index.js.map +1 -0
- package/dist/src/integrations/mcp/handlers/linear-handlers.d.ts +33 -0
- package/dist/src/integrations/mcp/handlers/linear-handlers.d.ts.map +1 -0
- package/dist/src/integrations/mcp/handlers/linear-handlers.js +251 -0
- package/dist/src/integrations/mcp/handlers/linear-handlers.js.map +1 -0
- package/dist/src/integrations/mcp/handlers/task-handlers.d.ts +42 -0
- package/dist/src/integrations/mcp/handlers/task-handlers.d.ts.map +1 -0
- package/dist/src/integrations/mcp/handlers/task-handlers.js +238 -0
- package/dist/src/integrations/mcp/handlers/task-handlers.js.map +1 -0
- package/dist/src/integrations/mcp/handlers/trace-handlers.d.ts +41 -0
- package/dist/src/integrations/mcp/handlers/trace-handlers.d.ts.map +1 -0
- package/dist/src/integrations/mcp/handlers/trace-handlers.js +298 -0
- package/dist/src/integrations/mcp/handlers/trace-handlers.js.map +1 -0
- package/dist/src/integrations/mcp/index.d.ts +13 -0
- package/dist/src/integrations/mcp/index.d.ts.map +1 -0
- package/dist/src/integrations/mcp/index.js +17 -0
- package/dist/src/integrations/mcp/index.js.map +1 -0
- package/dist/src/integrations/mcp/refactored-server.d.ts +76 -0
- package/dist/src/integrations/mcp/refactored-server.d.ts.map +1 -0
- package/dist/src/integrations/mcp/refactored-server.js +351 -0
- package/dist/src/integrations/mcp/refactored-server.js.map +1 -0
- package/dist/src/integrations/mcp/server.js +2 -2
- package/dist/src/integrations/mcp/server.js.map +1 -1
- package/dist/src/integrations/mcp/tool-definitions.d.ts +44 -0
- package/dist/src/integrations/mcp/tool-definitions.d.ts.map +1 -0
- package/dist/src/integrations/mcp/tool-definitions.js +563 -0
- package/dist/src/integrations/mcp/tool-definitions.js.map +1 -0
- package/dist/src/integrations/pg-aiguide/embedding-provider.d.ts +48 -0
- package/dist/src/integrations/pg-aiguide/embedding-provider.d.ts.map +1 -0
- package/dist/src/integrations/pg-aiguide/embedding-provider.js +190 -0
- package/dist/src/integrations/pg-aiguide/embedding-provider.js.map +1 -0
- package/dist/src/integrations/pg-aiguide/semantic-search.d.ts +34 -0
- package/dist/src/integrations/pg-aiguide/semantic-search.d.ts.map +1 -0
- package/dist/src/integrations/pg-aiguide/semantic-search.js +176 -0
- package/dist/src/integrations/pg-aiguide/semantic-search.js.map +1 -0
- package/dist/src/integrations/pg-aiguide/timescale-analytics.d.ts +44 -0
- package/dist/src/integrations/pg-aiguide/timescale-analytics.d.ts.map +1 -0
- package/dist/src/integrations/pg-aiguide/timescale-analytics.js +215 -0
- package/dist/src/integrations/pg-aiguide/timescale-analytics.js.map +1 -0
- package/dist/src/mcp/stackmemory-mcp-server.d.ts +9 -0
- package/dist/src/mcp/stackmemory-mcp-server.d.ts.map +1 -0
- package/dist/src/mcp/stackmemory-mcp-server.js +519 -0
- package/dist/src/mcp/stackmemory-mcp-server.js.map +1 -0
- package/dist/src/middleware/exponential-rate-limiter.d.ts +78 -0
- package/dist/src/middleware/exponential-rate-limiter.d.ts.map +1 -0
- package/dist/src/middleware/exponential-rate-limiter.js +293 -0
- package/dist/src/middleware/exponential-rate-limiter.js.map +1 -0
- package/dist/src/models/user.model.d.ts +62 -0
- package/dist/src/models/user.model.d.ts.map +1 -0
- package/dist/src/models/user.model.js +311 -0
- package/dist/src/models/user.model.js.map +1 -0
- package/dist/src/servers/production/auth-middleware.d.ts +12 -2
- package/dist/src/servers/production/auth-middleware.d.ts.map +1 -1
- package/dist/src/servers/production/auth-middleware.js +240 -28
- package/dist/src/servers/production/auth-middleware.js.map +1 -1
- package/dist/src/servers/railway/index.js.map +1 -1
- package/dist/src/services/context-service.d.ts.map +1 -1
- package/dist/src/services/context-service.js +86 -1
- package/dist/src/services/context-service.js.map +1 -1
- package/dist/src/validation/schemas.d.ts +633 -0
- package/dist/src/validation/schemas.d.ts.map +1 -0
- package/dist/src/validation/schemas.js +347 -0
- package/dist/src/validation/schemas.js.map +1 -0
- package/dist/types/task.js +1 -0
- package/dist/types/task.js.map +7 -0
- package/dist/utils/logger.js +52 -0
- package/dist/utils/logger.js.map +7 -0
- package/dist/validation/schemas.js +218 -0
- package/dist/validation/schemas.js.map +7 -0
- package/package.json +12 -3
|
@@ -0,0 +1,513 @@
|
|
|
1
|
+
import jwt from "jsonwebtoken";
|
|
2
|
+
import jwksRsa from "jwks-rsa";
|
|
3
|
+
import { RateLimiterRedis } from "rate-limiter-flexible";
|
|
4
|
+
import Redis from "ioredis";
|
|
5
|
+
import BetterSqlite3 from "better-sqlite3";
|
|
6
|
+
import { logger } from "../../core/monitoring/logger.js";
|
|
7
|
+
import { metrics } from "../../core/monitoring/metrics.js";
|
|
8
|
+
import { getUserModel } from "../../models/user.model.js";
|
|
9
|
+
class AuthMiddleware {
|
|
10
|
+
constructor(config) {
|
|
11
|
+
this.config = config;
|
|
12
|
+
this.redis = new Redis(config.redisUrl);
|
|
13
|
+
const dbPath = config.dbPath || process.env.STACKMEMORY_DB || ".stackmemory/auth.db";
|
|
14
|
+
this.db = new BetterSqlite3(dbPath);
|
|
15
|
+
this.userModel = getUserModel(this.db);
|
|
16
|
+
this.jwksClient = jwksRsa({
|
|
17
|
+
jwksUri: `https://${config.auth0Domain}/.well-known/jwks.json`,
|
|
18
|
+
cache: true,
|
|
19
|
+
cacheMaxAge: 6e5,
|
|
20
|
+
// 10 minutes
|
|
21
|
+
rateLimit: true,
|
|
22
|
+
jwksRequestsPerMinute: 5
|
|
23
|
+
});
|
|
24
|
+
this.initializeRateLimiters();
|
|
25
|
+
this.setupTokenBlacklistSync();
|
|
26
|
+
}
|
|
27
|
+
jwksClient;
|
|
28
|
+
redis;
|
|
29
|
+
rateLimiters;
|
|
30
|
+
blacklistedTokens = /* @__PURE__ */ new Set();
|
|
31
|
+
userModel;
|
|
32
|
+
db;
|
|
33
|
+
mockUser;
|
|
34
|
+
mockUserInitializing = false;
|
|
35
|
+
initializeRateLimiters() {
|
|
36
|
+
this.rateLimiters = /* @__PURE__ */ new Map([
|
|
37
|
+
[
|
|
38
|
+
"free",
|
|
39
|
+
new RateLimiterRedis({
|
|
40
|
+
storeClient: this.redis,
|
|
41
|
+
keyPrefix: "rl:free",
|
|
42
|
+
points: 100,
|
|
43
|
+
// requests
|
|
44
|
+
duration: 900,
|
|
45
|
+
// per 15 minutes
|
|
46
|
+
blockDuration: 900
|
|
47
|
+
// block for 15 minutes
|
|
48
|
+
})
|
|
49
|
+
],
|
|
50
|
+
[
|
|
51
|
+
"pro",
|
|
52
|
+
new RateLimiterRedis({
|
|
53
|
+
storeClient: this.redis,
|
|
54
|
+
keyPrefix: "rl:pro",
|
|
55
|
+
points: 1e3,
|
|
56
|
+
duration: 900,
|
|
57
|
+
blockDuration: 300
|
|
58
|
+
})
|
|
59
|
+
],
|
|
60
|
+
[
|
|
61
|
+
"enterprise",
|
|
62
|
+
new RateLimiterRedis({
|
|
63
|
+
storeClient: this.redis,
|
|
64
|
+
keyPrefix: "rl:enterprise",
|
|
65
|
+
points: 1e4,
|
|
66
|
+
duration: 900,
|
|
67
|
+
blockDuration: 60
|
|
68
|
+
})
|
|
69
|
+
]
|
|
70
|
+
]);
|
|
71
|
+
this.rateLimiters.set(
|
|
72
|
+
"auth",
|
|
73
|
+
new RateLimiterRedis({
|
|
74
|
+
storeClient: this.redis,
|
|
75
|
+
keyPrefix: "rl:auth",
|
|
76
|
+
points: 10,
|
|
77
|
+
// Only 10 auth attempts
|
|
78
|
+
duration: 900,
|
|
79
|
+
blockDuration: 3600
|
|
80
|
+
// Block for 1 hour on excessive auth attempts
|
|
81
|
+
})
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
setupTokenBlacklistSync() {
|
|
85
|
+
const subscriber = new Redis(this.config.redisUrl);
|
|
86
|
+
subscriber.subscribe("token:revoked");
|
|
87
|
+
subscriber.on("message", (channel, token) => {
|
|
88
|
+
if (channel === "token:revoked") {
|
|
89
|
+
this.blacklistedTokens.add(token);
|
|
90
|
+
if (this.blacklistedTokens.size > 1e4) {
|
|
91
|
+
this.blacklistedTokens.clear();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
async getSigningKey(kid) {
|
|
97
|
+
return new Promise((resolve, reject) => {
|
|
98
|
+
this.jwksClient.getSigningKey(kid, (err, key) => {
|
|
99
|
+
if (err) {
|
|
100
|
+
reject(err);
|
|
101
|
+
} else {
|
|
102
|
+
const signingKey = key?.getPublicKey();
|
|
103
|
+
if (!signingKey) {
|
|
104
|
+
reject(new Error("No signing key found"));
|
|
105
|
+
} else {
|
|
106
|
+
resolve(signingKey);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Main authentication middleware
|
|
114
|
+
*/
|
|
115
|
+
authenticate = async (req, res, next) => {
|
|
116
|
+
const startTime = Date.now();
|
|
117
|
+
try {
|
|
118
|
+
if (req.path === "/health" || req.path === "/metrics") {
|
|
119
|
+
return next();
|
|
120
|
+
}
|
|
121
|
+
if (this.config.bypassAuth && process.env.NODE_ENV === "development") {
|
|
122
|
+
req.user = this.getMockUser();
|
|
123
|
+
return next();
|
|
124
|
+
}
|
|
125
|
+
const token = this.extractToken(req);
|
|
126
|
+
const apiKey = this.extractApiKey(req);
|
|
127
|
+
if (!token && !apiKey) {
|
|
128
|
+
metrics.increment("auth.missing_credentials");
|
|
129
|
+
return res.status(401).json({
|
|
130
|
+
error: "Authentication required",
|
|
131
|
+
code: "MISSING_CREDENTIALS"
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
if (apiKey) {
|
|
135
|
+
const user2 = await this.userModel.validateApiKey(apiKey);
|
|
136
|
+
if (!user2) {
|
|
137
|
+
metrics.increment("auth.invalid_api_key");
|
|
138
|
+
return res.status(401).json({
|
|
139
|
+
error: "Invalid API key",
|
|
140
|
+
code: "INVALID_API_KEY"
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
req.user = {
|
|
144
|
+
id: user2.id,
|
|
145
|
+
sub: user2.sub,
|
|
146
|
+
email: user2.email,
|
|
147
|
+
name: user2.name,
|
|
148
|
+
picture: user2.avatar,
|
|
149
|
+
tier: user2.tier,
|
|
150
|
+
permissions: user2.permissions,
|
|
151
|
+
organizations: user2.organizations.map((org) => org.id),
|
|
152
|
+
metadata: { ...user2.metadata, authMethod: "api_key" }
|
|
153
|
+
};
|
|
154
|
+
metrics.increment("auth.api_key_success");
|
|
155
|
+
await metrics.timing("auth.api_key_duration", Date.now() - startTime);
|
|
156
|
+
return next();
|
|
157
|
+
}
|
|
158
|
+
if (token && this.blacklistedTokens.has(token)) {
|
|
159
|
+
metrics.increment("auth.blacklisted_token");
|
|
160
|
+
return res.status(401).json({
|
|
161
|
+
error: "Token has been revoked",
|
|
162
|
+
code: "TOKEN_REVOKED"
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
if (!token) {
|
|
166
|
+
return res.status(401).json({
|
|
167
|
+
error: "No token provided",
|
|
168
|
+
code: "NO_TOKEN"
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
const decoded = jwt.decode(token, { complete: true });
|
|
172
|
+
if (!decoded) {
|
|
173
|
+
metrics.increment("auth.invalid_token");
|
|
174
|
+
return res.status(401).json({
|
|
175
|
+
error: "Invalid token format",
|
|
176
|
+
code: "INVALID_TOKEN"
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
const signingKey = await this.getSigningKey(decoded.header.kid);
|
|
180
|
+
const verified = jwt.verify(token, signingKey, {
|
|
181
|
+
algorithms: ["RS256"],
|
|
182
|
+
audience: this.config.auth0Audience,
|
|
183
|
+
issuer: `https://${this.config.auth0Domain}/`
|
|
184
|
+
});
|
|
185
|
+
const user = await this.loadUser(verified.sub, verified);
|
|
186
|
+
if (!user) {
|
|
187
|
+
metrics.increment("auth.user_not_found");
|
|
188
|
+
return res.status(403).json({
|
|
189
|
+
error: "User not found",
|
|
190
|
+
code: "USER_NOT_FOUND"
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
if (user.metadata?.suspended) {
|
|
194
|
+
metrics.increment("auth.user_suspended");
|
|
195
|
+
return res.status(403).json({
|
|
196
|
+
error: "Account suspended",
|
|
197
|
+
code: "ACCOUNT_SUSPENDED"
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
const rateLimiter = this.rateLimiters.get(user.tier) || this.rateLimiters.get("free");
|
|
201
|
+
try {
|
|
202
|
+
const rateLimitRes = await rateLimiter.consume(user.id);
|
|
203
|
+
req.rateLimitInfo = rateLimitRes;
|
|
204
|
+
res.setHeader("X-RateLimit-Limit", rateLimiter.points.toString());
|
|
205
|
+
res.setHeader(
|
|
206
|
+
"X-RateLimit-Remaining",
|
|
207
|
+
rateLimitRes.remainingPoints.toString()
|
|
208
|
+
);
|
|
209
|
+
res.setHeader(
|
|
210
|
+
"X-RateLimit-Reset",
|
|
211
|
+
new Date(Date.now() + rateLimitRes.msBeforeNext).toISOString()
|
|
212
|
+
);
|
|
213
|
+
} catch (rateLimitError) {
|
|
214
|
+
metrics.increment("auth.rate_limited");
|
|
215
|
+
res.setHeader(
|
|
216
|
+
"Retry-After",
|
|
217
|
+
Math.round(rateLimitError.msBeforeNext / 1e3).toString()
|
|
218
|
+
);
|
|
219
|
+
return res.status(429).json({
|
|
220
|
+
error: "Too many requests",
|
|
221
|
+
code: "RATE_LIMITED",
|
|
222
|
+
retryAfter: rateLimitError.msBeforeNext
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
req.user = user;
|
|
226
|
+
metrics.increment("auth.success", { tier: user.tier });
|
|
227
|
+
metrics.timing("auth.duration", Date.now() - startTime);
|
|
228
|
+
logger.info("Authentication successful", {
|
|
229
|
+
userId: user.id,
|
|
230
|
+
tier: user.tier,
|
|
231
|
+
path: req.path
|
|
232
|
+
});
|
|
233
|
+
next();
|
|
234
|
+
} catch (error) {
|
|
235
|
+
metrics.increment("auth.error");
|
|
236
|
+
logger.error("Authentication error", error);
|
|
237
|
+
if (error.name === "TokenExpiredError") {
|
|
238
|
+
return res.status(401).json({
|
|
239
|
+
error: "Token expired",
|
|
240
|
+
code: "TOKEN_EXPIRED"
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
if (error.name === "JsonWebTokenError") {
|
|
244
|
+
return res.status(401).json({
|
|
245
|
+
error: "Invalid token",
|
|
246
|
+
code: "INVALID_TOKEN"
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
res.status(500).json({
|
|
250
|
+
error: "Authentication failed",
|
|
251
|
+
code: "AUTH_ERROR"
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
/**
|
|
256
|
+
* WebSocket authentication handler
|
|
257
|
+
*/
|
|
258
|
+
authenticateWebSocket = async (token) => {
|
|
259
|
+
try {
|
|
260
|
+
const decoded = jwt.decode(token, { complete: true });
|
|
261
|
+
if (!decoded || this.blacklistedTokens.has(token)) {
|
|
262
|
+
return null;
|
|
263
|
+
}
|
|
264
|
+
const signingKey = await this.getSigningKey(decoded.header.kid);
|
|
265
|
+
const verified = jwt.verify(token, signingKey, {
|
|
266
|
+
algorithms: ["RS256"],
|
|
267
|
+
audience: this.config.auth0Audience,
|
|
268
|
+
issuer: `https://${this.config.auth0Domain}/`
|
|
269
|
+
});
|
|
270
|
+
return await this.loadUser(verified.sub, verified);
|
|
271
|
+
} catch (error) {
|
|
272
|
+
logger.error(
|
|
273
|
+
"WebSocket authentication failed",
|
|
274
|
+
error instanceof Error ? error : void 0
|
|
275
|
+
);
|
|
276
|
+
return null;
|
|
277
|
+
}
|
|
278
|
+
};
|
|
279
|
+
/**
|
|
280
|
+
* Permission checking middleware
|
|
281
|
+
*/
|
|
282
|
+
requirePermission = (permission) => {
|
|
283
|
+
return (req, res, next) => {
|
|
284
|
+
if (!req.user) {
|
|
285
|
+
return res.status(401).json({
|
|
286
|
+
error: "Authentication required",
|
|
287
|
+
code: "NOT_AUTHENTICATED"
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
if (!req.user.permissions.includes(permission)) {
|
|
291
|
+
metrics.increment("auth.permission_denied", { permission });
|
|
292
|
+
return res.status(403).json({
|
|
293
|
+
error: "Insufficient permissions",
|
|
294
|
+
code: "PERMISSION_DENIED",
|
|
295
|
+
required: permission
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
return next();
|
|
299
|
+
};
|
|
300
|
+
};
|
|
301
|
+
/**
|
|
302
|
+
* Organization access middleware
|
|
303
|
+
*/
|
|
304
|
+
requireOrganization = (req, res, next) => {
|
|
305
|
+
const orgId = req.params.orgId || req.query.orgId;
|
|
306
|
+
if (!req.user || !orgId) {
|
|
307
|
+
return res.status(401).json({
|
|
308
|
+
error: "Authentication required",
|
|
309
|
+
code: "NOT_AUTHENTICATED"
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
if (!req.user.organizations?.includes(orgId)) {
|
|
313
|
+
return res.status(403).json({
|
|
314
|
+
error: "Organization access denied",
|
|
315
|
+
code: "ORG_ACCESS_DENIED"
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
return next();
|
|
319
|
+
};
|
|
320
|
+
extractApiKey(req) {
|
|
321
|
+
const authHeader = req.headers.authorization;
|
|
322
|
+
if (authHeader?.startsWith("Bearer sk-")) {
|
|
323
|
+
return authHeader.substring(7);
|
|
324
|
+
}
|
|
325
|
+
const apiKeyHeader = req.headers["x-api-key"];
|
|
326
|
+
if (apiKeyHeader?.startsWith("sk-")) {
|
|
327
|
+
return apiKeyHeader;
|
|
328
|
+
}
|
|
329
|
+
return null;
|
|
330
|
+
}
|
|
331
|
+
extractToken(req) {
|
|
332
|
+
const authHeader = req.headers.authorization;
|
|
333
|
+
if (authHeader?.startsWith("Bearer ") && !authHeader.startsWith("Bearer sk-")) {
|
|
334
|
+
return authHeader.substring(7);
|
|
335
|
+
}
|
|
336
|
+
return req.cookies?.access_token || null;
|
|
337
|
+
}
|
|
338
|
+
async loadUser(sub, tokenPayload) {
|
|
339
|
+
const cached = await this.redis.get(`user:${sub}`);
|
|
340
|
+
if (cached) {
|
|
341
|
+
const cachedUser = JSON.parse(cached);
|
|
342
|
+
this.userModel.updateLastLogin(cachedUser.id).catch((err) => logger.error("Failed to update last login", err));
|
|
343
|
+
return cachedUser;
|
|
344
|
+
}
|
|
345
|
+
let dbUser = await this.userModel.findUserBySub(sub);
|
|
346
|
+
if (!dbUser && tokenPayload) {
|
|
347
|
+
dbUser = await this.userModel.createUser({
|
|
348
|
+
sub,
|
|
349
|
+
email: tokenPayload.email || `${sub}@auth.local`,
|
|
350
|
+
name: tokenPayload.name,
|
|
351
|
+
avatar: tokenPayload.picture,
|
|
352
|
+
tier: this.determineTier(tokenPayload),
|
|
353
|
+
permissions: this.determinePermissions(tokenPayload),
|
|
354
|
+
organizations: this.extractOrganizations(tokenPayload),
|
|
355
|
+
metadata: {
|
|
356
|
+
auth0: tokenPayload,
|
|
357
|
+
signupSource: "auth0",
|
|
358
|
+
createdVia: "auth-middleware"
|
|
359
|
+
}
|
|
360
|
+
});
|
|
361
|
+
logger.info("Auto-created user from auth token", {
|
|
362
|
+
sub,
|
|
363
|
+
email: dbUser.email
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
if (!dbUser) {
|
|
367
|
+
return null;
|
|
368
|
+
}
|
|
369
|
+
await this.userModel.updateLastLogin(dbUser.id);
|
|
370
|
+
const user = {
|
|
371
|
+
id: dbUser.id,
|
|
372
|
+
sub: dbUser.sub,
|
|
373
|
+
email: dbUser.email,
|
|
374
|
+
name: dbUser.name,
|
|
375
|
+
picture: dbUser.avatar,
|
|
376
|
+
tier: dbUser.tier,
|
|
377
|
+
permissions: dbUser.permissions,
|
|
378
|
+
organizations: dbUser.organizations.map((org) => org.id),
|
|
379
|
+
metadata: dbUser.metadata
|
|
380
|
+
};
|
|
381
|
+
await this.redis.setex(`user:${sub}`, 300, JSON.stringify(user));
|
|
382
|
+
return user;
|
|
383
|
+
}
|
|
384
|
+
determineTier(tokenPayload) {
|
|
385
|
+
if (tokenPayload["https://stackmemory.ai/tier"]) {
|
|
386
|
+
return tokenPayload["https://stackmemory.ai/tier"];
|
|
387
|
+
}
|
|
388
|
+
if (tokenPayload.subscription?.plan) {
|
|
389
|
+
const plan = tokenPayload.subscription.plan.toLowerCase();
|
|
390
|
+
if (plan.includes("enterprise")) return "enterprise";
|
|
391
|
+
if (plan.includes("pro") || plan.includes("premium")) return "pro";
|
|
392
|
+
}
|
|
393
|
+
return "free";
|
|
394
|
+
}
|
|
395
|
+
determinePermissions(tokenPayload) {
|
|
396
|
+
const permissions = ["read", "write"];
|
|
397
|
+
if (tokenPayload["https://stackmemory.ai/permissions"]) {
|
|
398
|
+
return tokenPayload["https://stackmemory.ai/permissions"];
|
|
399
|
+
}
|
|
400
|
+
if (tokenPayload.permissions && Array.isArray(tokenPayload.permissions)) {
|
|
401
|
+
return tokenPayload.permissions;
|
|
402
|
+
}
|
|
403
|
+
if (tokenPayload.roles && Array.isArray(tokenPayload.roles)) {
|
|
404
|
+
if (tokenPayload.roles.includes("admin")) {
|
|
405
|
+
permissions.push("admin", "delete");
|
|
406
|
+
}
|
|
407
|
+
if (tokenPayload.roles.includes("moderator")) {
|
|
408
|
+
permissions.push("moderate");
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
return permissions;
|
|
412
|
+
}
|
|
413
|
+
extractOrganizations(tokenPayload) {
|
|
414
|
+
const orgs = [];
|
|
415
|
+
if (tokenPayload["https://stackmemory.ai/organizations"]) {
|
|
416
|
+
return tokenPayload["https://stackmemory.ai/organizations"];
|
|
417
|
+
}
|
|
418
|
+
if (tokenPayload.org_id) {
|
|
419
|
+
orgs.push({
|
|
420
|
+
id: tokenPayload.org_id,
|
|
421
|
+
name: tokenPayload.org_name || tokenPayload.org_id,
|
|
422
|
+
role: tokenPayload.org_role || "member"
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
return orgs;
|
|
426
|
+
}
|
|
427
|
+
async initializeMockUser() {
|
|
428
|
+
const mockSub = "dev-sub";
|
|
429
|
+
let dbUser = await this.userModel.findUserBySub(mockSub);
|
|
430
|
+
if (!dbUser) {
|
|
431
|
+
dbUser = await this.userModel.createUser({
|
|
432
|
+
sub: mockSub,
|
|
433
|
+
email: "dev@stackmemory.local",
|
|
434
|
+
name: "Development User",
|
|
435
|
+
tier: "enterprise",
|
|
436
|
+
permissions: ["read", "write", "admin", "delete"],
|
|
437
|
+
organizations: [
|
|
438
|
+
{
|
|
439
|
+
id: "dev-org",
|
|
440
|
+
name: "Development Organization",
|
|
441
|
+
role: "admin"
|
|
442
|
+
}
|
|
443
|
+
],
|
|
444
|
+
metadata: {
|
|
445
|
+
isDevelopmentUser: true,
|
|
446
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
447
|
+
}
|
|
448
|
+
});
|
|
449
|
+
logger.info("Created development mock user");
|
|
450
|
+
}
|
|
451
|
+
return {
|
|
452
|
+
id: dbUser.id,
|
|
453
|
+
sub: dbUser.sub,
|
|
454
|
+
email: dbUser.email,
|
|
455
|
+
name: dbUser.name,
|
|
456
|
+
picture: dbUser.avatar,
|
|
457
|
+
tier: dbUser.tier,
|
|
458
|
+
permissions: dbUser.permissions,
|
|
459
|
+
organizations: dbUser.organizations.map((org) => org.id),
|
|
460
|
+
metadata: dbUser.metadata
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
getMockUser() {
|
|
464
|
+
if (this.mockUser) {
|
|
465
|
+
return this.mockUser;
|
|
466
|
+
}
|
|
467
|
+
if (!this.mockUserInitializing) {
|
|
468
|
+
this.mockUserInitializing = true;
|
|
469
|
+
this.initializeMockUser().then((user) => {
|
|
470
|
+
this.mockUser = user;
|
|
471
|
+
this.mockUserInitializing = false;
|
|
472
|
+
logger.info("Mock user initialized and cached");
|
|
473
|
+
}).catch((err) => {
|
|
474
|
+
logger.error("Failed to initialize mock user", err);
|
|
475
|
+
this.mockUserInitializing = false;
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
return {
|
|
479
|
+
id: "temp-dev-user-id",
|
|
480
|
+
sub: "dev-sub",
|
|
481
|
+
email: "dev@stackmemory.local",
|
|
482
|
+
name: "Development User",
|
|
483
|
+
tier: "enterprise",
|
|
484
|
+
permissions: ["read", "write", "admin", "delete"],
|
|
485
|
+
organizations: ["dev-org"],
|
|
486
|
+
metadata: { temporary: true }
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
/**
|
|
490
|
+
* Revoke a token (add to blacklist)
|
|
491
|
+
*/
|
|
492
|
+
async revokeToken(token) {
|
|
493
|
+
this.blacklistedTokens.add(token);
|
|
494
|
+
await this.redis.publish("token:revoked", token);
|
|
495
|
+
const decoded = jwt.decode(token);
|
|
496
|
+
if (decoded?.exp) {
|
|
497
|
+
const ttl = decoded.exp - Math.floor(Date.now() / 1e3);
|
|
498
|
+
if (ttl > 0) {
|
|
499
|
+
await this.redis.setex(`blacklist:${token}`, ttl, "1");
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
/**
|
|
504
|
+
* Cleanup resources
|
|
505
|
+
*/
|
|
506
|
+
async close() {
|
|
507
|
+
await this.redis.quit();
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
export {
|
|
511
|
+
AuthMiddleware
|
|
512
|
+
};
|
|
513
|
+
//# sourceMappingURL=auth-middleware.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/servers/production/auth-middleware.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Production Authentication Middleware for Runway MCP Server\n * Implements JWT validation with Auth0, refresh tokens, and rate limiting\n */\n\nimport jwt from 'jsonwebtoken';\nimport jwksRsa from 'jwks-rsa';\nimport { Request, Response, NextFunction } from 'express';\nimport { RateLimiterRedis, RateLimiterRes } from 'rate-limiter-flexible';\nimport Redis from 'ioredis';\nimport BetterSqlite3 from 'better-sqlite3';\nimport { logger } from '../../core/monitoring/logger.js';\nimport { metrics } from '../../core/monitoring/metrics.js';\nimport { getUserModel, UserModel, User } from '../../models/user.model.js';\n\nexport interface AuthUser {\n id: string;\n email: string;\n sub: string;\n name?: string;\n picture?: string;\n tier: 'free' | 'pro' | 'enterprise';\n organizations?: string[];\n permissions: string[];\n metadata?: Record<string, any>;\n}\n\nexport interface AuthRequest extends Request {\n user?: AuthUser;\n rateLimitInfo?: RateLimiterRes;\n}\n\nexport class AuthMiddleware {\n private jwksClient: jwksRsa.JwksClient;\n private redis: Redis;\n private rateLimiters!: Map<string, RateLimiterRedis>;\n private blacklistedTokens: Set<string> = new Set();\n private userModel: UserModel;\n private db: BetterSqlite3.Database;\n private mockUser?: AuthUser;\n private mockUserInitializing = false;\n\n constructor(\n private config: {\n auth0Domain: string;\n auth0Audience: string;\n redisUrl: string;\n jwtSecret?: string;\n bypassAuth?: boolean; // For testing\n dbPath?: string; // Path to SQLite database\n }\n ) {\n this.redis = new Redis(config.redisUrl);\n\n // Initialize database\n const dbPath =\n config.dbPath || process.env.STACKMEMORY_DB || '.stackmemory/auth.db';\n this.db = new BetterSqlite3(dbPath);\n this.userModel = getUserModel(this.db);\n\n this.jwksClient = jwksRsa({\n jwksUri: `https://${config.auth0Domain}/.well-known/jwks.json`,\n cache: true,\n cacheMaxAge: 600000, // 10 minutes\n rateLimit: true,\n jwksRequestsPerMinute: 5,\n });\n\n this.initializeRateLimiters();\n this.setupTokenBlacklistSync();\n }\n\n private initializeRateLimiters(): void {\n // Different rate limits for different tiers\n this.rateLimiters = new Map([\n [\n 'free',\n new RateLimiterRedis({\n storeClient: this.redis,\n keyPrefix: 'rl:free',\n points: 100, // requests\n duration: 900, // per 15 minutes\n blockDuration: 900, // block for 15 minutes\n }),\n ],\n [\n 'pro',\n new RateLimiterRedis({\n storeClient: this.redis,\n keyPrefix: 'rl:pro',\n points: 1000,\n duration: 900,\n blockDuration: 300,\n }),\n ],\n [\n 'enterprise',\n new RateLimiterRedis({\n storeClient: this.redis,\n keyPrefix: 'rl:enterprise',\n points: 10000,\n duration: 900,\n blockDuration: 60,\n }),\n ],\n ]);\n\n // Special rate limiter for auth endpoints\n this.rateLimiters.set(\n 'auth',\n new RateLimiterRedis({\n storeClient: this.redis,\n keyPrefix: 'rl:auth',\n points: 10, // Only 10 auth attempts\n duration: 900,\n blockDuration: 3600, // Block for 1 hour on excessive auth attempts\n })\n );\n }\n\n private setupTokenBlacklistSync(): void {\n // Subscribe to token revocation events\n const subscriber = new Redis(this.config.redisUrl);\n subscriber.subscribe('token:revoked');\n\n subscriber.on('message', (channel, token) => {\n if (channel === 'token:revoked') {\n this.blacklistedTokens.add(token);\n // Clean up old tokens periodically\n if (this.blacklistedTokens.size > 10000) {\n this.blacklistedTokens.clear();\n }\n }\n });\n }\n\n private async getSigningKey(kid: string): Promise<string> {\n return new Promise((resolve, reject) => {\n this.jwksClient.getSigningKey(kid, (err, key) => {\n if (err) {\n reject(err);\n } else {\n const signingKey = key?.getPublicKey();\n if (!signingKey) {\n reject(new Error('No signing key found'));\n } else {\n resolve(signingKey);\n }\n }\n });\n });\n }\n\n /**\n * Main authentication middleware\n */\n public authenticate = async (\n req: AuthRequest,\n res: Response,\n next: NextFunction\n ): Promise<any> => {\n const startTime = Date.now();\n\n try {\n // Bypass auth for health checks\n if (req.path === '/health' || req.path === '/metrics') {\n return next();\n }\n\n // Development bypass\n if (this.config.bypassAuth && process.env.NODE_ENV === 'development') {\n req.user = this.getMockUser();\n return next();\n }\n\n // Extract token or API key\n const token = this.extractToken(req);\n const apiKey = this.extractApiKey(req);\n\n if (!token && !apiKey) {\n metrics.increment('auth.missing_credentials');\n return res.status(401).json({\n error: 'Authentication required',\n code: 'MISSING_CREDENTIALS',\n });\n }\n\n // API Key authentication\n if (apiKey) {\n const user = await this.userModel.validateApiKey(apiKey);\n if (!user) {\n metrics.increment('auth.invalid_api_key');\n return res.status(401).json({\n error: 'Invalid API key',\n code: 'INVALID_API_KEY',\n });\n }\n\n // Convert to AuthUser format\n req.user = {\n id: user.id,\n sub: user.sub,\n email: user.email,\n name: user.name,\n picture: user.avatar,\n tier: user.tier,\n permissions: user.permissions,\n organizations: user.organizations.map((org) => org.id),\n metadata: { ...user.metadata, authMethod: 'api_key' },\n };\n\n metrics.increment('auth.api_key_success');\n await metrics.timing('auth.api_key_duration', Date.now() - startTime);\n return next();\n }\n\n // Check blacklist for JWT tokens\n if (token && this.blacklistedTokens.has(token)) {\n metrics.increment('auth.blacklisted_token');\n return res.status(401).json({\n error: 'Token has been revoked',\n code: 'TOKEN_REVOKED',\n });\n }\n\n // Ensure token exists for JWT processing\n if (!token) {\n // This should not happen as we checked earlier, but TypeScript needs this\n return res.status(401).json({\n error: 'No token provided',\n code: 'NO_TOKEN',\n });\n }\n\n // Decode and verify token\n const decoded = jwt.decode(token, { complete: true }) as any;\n if (!decoded) {\n metrics.increment('auth.invalid_token');\n return res.status(401).json({\n error: 'Invalid token format',\n code: 'INVALID_TOKEN',\n });\n }\n\n // Get signing key and verify\n const signingKey = await this.getSigningKey(decoded.header.kid);\n const verified = jwt.verify(token, signingKey, {\n algorithms: ['RS256'],\n audience: this.config.auth0Audience,\n issuer: `https://${this.config.auth0Domain}/`,\n }) as any;\n\n // Load user from database or cache\n const user = await this.loadUser(verified.sub, verified);\n if (!user) {\n metrics.increment('auth.user_not_found');\n return res.status(403).json({\n error: 'User not found',\n code: 'USER_NOT_FOUND',\n });\n }\n\n // Check user suspension\n if (user.metadata?.suspended) {\n metrics.increment('auth.user_suspended');\n return res.status(403).json({\n error: 'Account suspended',\n code: 'ACCOUNT_SUSPENDED',\n });\n }\n\n // Apply rate limiting\n const rateLimiter =\n this.rateLimiters.get(user.tier) || this.rateLimiters.get('free')!;\n try {\n const rateLimitRes = await rateLimiter.consume(user.id);\n req.rateLimitInfo = rateLimitRes;\n\n // Add rate limit headers\n res.setHeader('X-RateLimit-Limit', rateLimiter.points.toString());\n res.setHeader(\n 'X-RateLimit-Remaining',\n rateLimitRes.remainingPoints.toString()\n );\n res.setHeader(\n 'X-RateLimit-Reset',\n new Date(Date.now() + rateLimitRes.msBeforeNext).toISOString()\n );\n } catch (rateLimitError: any) {\n metrics.increment('auth.rate_limited');\n res.setHeader(\n 'Retry-After',\n Math.round(rateLimitError.msBeforeNext / 1000).toString()\n );\n return res.status(429).json({\n error: 'Too many requests',\n code: 'RATE_LIMITED',\n retryAfter: rateLimitError.msBeforeNext,\n });\n }\n\n // Attach user to request\n req.user = user;\n\n // Track metrics\n metrics.increment('auth.success', { tier: user.tier });\n metrics.timing('auth.duration', Date.now() - startTime);\n\n logger.info('Authentication successful', {\n userId: user.id,\n tier: user.tier,\n path: req.path,\n });\n\n next();\n } catch (error: any) {\n metrics.increment('auth.error');\n logger.error('Authentication error', error);\n\n if (error.name === 'TokenExpiredError') {\n return res.status(401).json({\n error: 'Token expired',\n code: 'TOKEN_EXPIRED',\n });\n }\n\n if (error.name === 'JsonWebTokenError') {\n return res.status(401).json({\n error: 'Invalid token',\n code: 'INVALID_TOKEN',\n });\n }\n\n res.status(500).json({\n error: 'Authentication failed',\n code: 'AUTH_ERROR',\n });\n }\n };\n\n /**\n * WebSocket authentication handler\n */\n public authenticateWebSocket = async (\n token: string\n ): Promise<AuthUser | null> => {\n try {\n const decoded = jwt.decode(token, { complete: true }) as any;\n if (!decoded || this.blacklistedTokens.has(token)) {\n return null;\n }\n\n const signingKey = await this.getSigningKey(decoded.header.kid);\n const verified = jwt.verify(token, signingKey, {\n algorithms: ['RS256'],\n audience: this.config.auth0Audience,\n issuer: `https://${this.config.auth0Domain}/`,\n }) as any;\n\n return await this.loadUser(verified.sub, verified);\n } catch (error) {\n logger.error(\n 'WebSocket authentication failed',\n error instanceof Error ? error : undefined\n );\n return null;\n }\n };\n\n /**\n * Permission checking middleware\n */\n public requirePermission = (permission: string) => {\n return (req: AuthRequest, res: Response, next: NextFunction) => {\n if (!req.user) {\n return res.status(401).json({\n error: 'Authentication required',\n code: 'NOT_AUTHENTICATED',\n });\n }\n\n if (!req.user.permissions.includes(permission)) {\n metrics.increment('auth.permission_denied', { permission });\n return res.status(403).json({\n error: 'Insufficient permissions',\n code: 'PERMISSION_DENIED',\n required: permission,\n });\n }\n\n return next();\n };\n };\n\n /**\n * Organization access middleware\n */\n public requireOrganization = (\n req: AuthRequest,\n res: Response,\n next: NextFunction\n ) => {\n const orgId = req.params.orgId || req.query.orgId;\n\n if (!req.user || !orgId) {\n return res.status(401).json({\n error: 'Authentication required',\n code: 'NOT_AUTHENTICATED',\n });\n }\n\n if (!req.user.organizations?.includes(orgId as string)) {\n return res.status(403).json({\n error: 'Organization access denied',\n code: 'ORG_ACCESS_DENIED',\n });\n }\n\n return next();\n };\n\n private extractApiKey(req: Request): string | null {\n // Check Authorization header for API key\n const authHeader = req.headers.authorization;\n if (authHeader?.startsWith('Bearer sk-')) {\n return authHeader.substring(7);\n }\n\n // Check X-API-Key header\n const apiKeyHeader = req.headers['x-api-key'] as string;\n if (apiKeyHeader?.startsWith('sk-')) {\n return apiKeyHeader;\n }\n\n // Query parameter support removed for security reasons\n // API keys should only be sent via headers to prevent:\n // - URL logging exposure\n // - Browser history leakage\n // - Referer header transmission\n\n return null;\n }\n\n private extractToken(req: Request): string | null {\n const authHeader = req.headers.authorization;\n if (\n authHeader?.startsWith('Bearer ') &&\n !authHeader.startsWith('Bearer sk-')\n ) {\n return authHeader.substring(7);\n }\n\n // Also check cookie for web clients\n return req.cookies?.access_token || null;\n }\n\n private async loadUser(\n sub: string,\n tokenPayload?: any\n ): Promise<AuthUser | null> {\n // Try cache first\n const cached = await this.redis.get(`user:${sub}`);\n if (cached) {\n const cachedUser = JSON.parse(cached);\n // Update last login time in background\n this.userModel\n .updateLastLogin(cachedUser.id)\n .catch((err) => logger.error('Failed to update last login', err));\n return cachedUser;\n }\n\n // Load from database\n let dbUser = await this.userModel.findUserBySub(sub);\n\n // If user doesn't exist, create from token payload\n if (!dbUser && tokenPayload) {\n dbUser = await this.userModel.createUser({\n sub,\n email: tokenPayload.email || `${sub}@auth.local`,\n name: tokenPayload.name,\n avatar: tokenPayload.picture,\n tier: this.determineTier(tokenPayload),\n permissions: this.determinePermissions(tokenPayload),\n organizations: this.extractOrganizations(tokenPayload),\n metadata: {\n auth0: tokenPayload,\n signupSource: 'auth0',\n createdVia: 'auth-middleware',\n },\n });\n logger.info('Auto-created user from auth token', {\n sub,\n email: dbUser.email,\n });\n }\n\n if (!dbUser) {\n return null;\n }\n\n // Update last login\n await this.userModel.updateLastLogin(dbUser.id);\n\n // Convert to AuthUser format\n const user: AuthUser = {\n id: dbUser.id,\n sub: dbUser.sub,\n email: dbUser.email,\n name: dbUser.name,\n picture: dbUser.avatar,\n tier: dbUser.tier,\n permissions: dbUser.permissions,\n organizations: dbUser.organizations.map((org) => org.id),\n metadata: dbUser.metadata,\n };\n\n // Cache for 5 minutes\n await this.redis.setex(`user:${sub}`, 300, JSON.stringify(user));\n\n return user;\n }\n\n private determineTier(tokenPayload: any): 'free' | 'pro' | 'enterprise' {\n // Check custom claims or metadata\n if (tokenPayload['https://stackmemory.ai/tier']) {\n return tokenPayload['https://stackmemory.ai/tier'];\n }\n\n // Check for subscription info\n if (tokenPayload.subscription?.plan) {\n const plan = tokenPayload.subscription.plan.toLowerCase();\n if (plan.includes('enterprise')) return 'enterprise';\n if (plan.includes('pro') || plan.includes('premium')) return 'pro';\n }\n\n // Default to free\n return 'free';\n }\n\n private determinePermissions(tokenPayload: any): string[] {\n const permissions: string[] = ['read', 'write'];\n\n // Check custom permissions claim\n if (tokenPayload['https://stackmemory.ai/permissions']) {\n return tokenPayload['https://stackmemory.ai/permissions'];\n }\n\n // Check standard permissions\n if (tokenPayload.permissions && Array.isArray(tokenPayload.permissions)) {\n return tokenPayload.permissions;\n }\n\n // Check roles\n if (tokenPayload.roles && Array.isArray(tokenPayload.roles)) {\n if (tokenPayload.roles.includes('admin')) {\n permissions.push('admin', 'delete');\n }\n if (tokenPayload.roles.includes('moderator')) {\n permissions.push('moderate');\n }\n }\n\n return permissions;\n }\n\n private extractOrganizations(\n tokenPayload: any\n ): Array<{ id: string; name: string; role: string }> {\n const orgs: Array<{ id: string; name: string; role: string }> = [];\n\n // Check custom organization claim\n if (tokenPayload['https://stackmemory.ai/organizations']) {\n return tokenPayload['https://stackmemory.ai/organizations'];\n }\n\n // Check Auth0 organizations\n if (tokenPayload.org_id) {\n orgs.push({\n id: tokenPayload.org_id,\n name: tokenPayload.org_name || tokenPayload.org_id,\n role: tokenPayload.org_role || 'member',\n });\n }\n\n return orgs;\n }\n\n private async initializeMockUser(): Promise<AuthUser> {\n const mockSub = 'dev-sub';\n\n // Check if user exists in database\n let dbUser = await this.userModel.findUserBySub(mockSub);\n\n if (!dbUser) {\n // Create mock user in database\n dbUser = await this.userModel.createUser({\n sub: mockSub,\n email: 'dev@stackmemory.local',\n name: 'Development User',\n tier: 'enterprise',\n permissions: ['read', 'write', 'admin', 'delete'],\n organizations: [\n {\n id: 'dev-org',\n name: 'Development Organization',\n role: 'admin',\n },\n ],\n metadata: {\n isDevelopmentUser: true,\n createdAt: new Date().toISOString(),\n },\n });\n logger.info('Created development mock user');\n }\n\n return {\n id: dbUser.id,\n sub: dbUser.sub,\n email: dbUser.email,\n name: dbUser.name,\n picture: dbUser.avatar,\n tier: dbUser.tier,\n permissions: dbUser.permissions,\n organizations: dbUser.organizations.map((org) => org.id),\n metadata: dbUser.metadata,\n };\n }\n\n private getMockUser(): AuthUser {\n // Return cached mock user if available\n if (this.mockUser) {\n return this.mockUser;\n }\n\n // Initialize mock user synchronously to prevent race conditions\n // This runs during constructor or first use\n if (!this.mockUserInitializing) {\n this.mockUserInitializing = true;\n\n // Initialize asynchronously but return a temporary user immediately\n this.initializeMockUser()\n .then((user) => {\n this.mockUser = user;\n this.mockUserInitializing = false;\n logger.info('Mock user initialized and cached');\n })\n .catch((err) => {\n logger.error('Failed to initialize mock user', err);\n this.mockUserInitializing = false;\n });\n }\n\n // Return temporary mock user while initialization is in progress\n return {\n id: 'temp-dev-user-id',\n sub: 'dev-sub',\n email: 'dev@stackmemory.local',\n name: 'Development User',\n tier: 'enterprise',\n permissions: ['read', 'write', 'admin', 'delete'],\n organizations: ['dev-org'],\n metadata: { temporary: true },\n };\n }\n\n /**\n * Revoke a token (add to blacklist)\n */\n public async revokeToken(token: string): Promise<void> {\n this.blacklistedTokens.add(token);\n await this.redis.publish('token:revoked', token);\n\n // Also store in Redis with TTL matching token expiry\n const decoded = jwt.decode(token) as any;\n if (decoded?.exp) {\n const ttl = decoded.exp - Math.floor(Date.now() / 1000);\n if (ttl > 0) {\n await this.redis.setex(`blacklist:${token}`, ttl, '1');\n }\n }\n }\n\n /**\n * Cleanup resources\n */\n public async close(): Promise<void> {\n await this.redis.quit();\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["user"]
|
|
7
|
+
}
|