@getrift/rift 0.0.0 → 0.1.0-beta.1
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/README.dev.md +110 -0
- package/dist/src/auth/keychain.d.ts +25 -0
- package/dist/src/auth/keychain.d.ts.map +1 -0
- package/dist/src/auth/keychain.js +113 -0
- package/dist/src/auth/keychain.js.map +1 -0
- package/dist/src/auth/middleware.d.ts +20 -0
- package/dist/src/auth/middleware.d.ts.map +1 -0
- package/dist/src/auth/middleware.js +49 -0
- package/dist/src/auth/middleware.js.map +1 -0
- package/dist/src/auth/rate-limit.d.ts +16 -0
- package/dist/src/auth/rate-limit.d.ts.map +1 -0
- package/dist/src/auth/rate-limit.js +38 -0
- package/dist/src/auth/rate-limit.js.map +1 -0
- package/dist/src/auth/rotation.d.ts +67 -0
- package/dist/src/auth/rotation.d.ts.map +1 -0
- package/dist/src/auth/rotation.js +190 -0
- package/dist/src/auth/rotation.js.map +1 -0
- package/dist/src/backfill/project-context-batch-constructor.d.ts +127 -0
- package/dist/src/backfill/project-context-batch-constructor.d.ts.map +1 -0
- package/dist/src/backfill/project-context-batch-constructor.js +210 -0
- package/dist/src/backfill/project-context-batch-constructor.js.map +1 -0
- package/dist/src/capture/auto-capture.d.ts +162 -0
- package/dist/src/capture/auto-capture.d.ts.map +1 -0
- package/dist/src/capture/auto-capture.js +601 -0
- package/dist/src/capture/auto-capture.js.map +1 -0
- package/dist/src/capture/batch-budget.d.ts +90 -0
- package/dist/src/capture/batch-budget.d.ts.map +1 -0
- package/dist/src/capture/batch-budget.js +148 -0
- package/dist/src/capture/batch-budget.js.map +1 -0
- package/dist/src/capture/codex-cli-triage-provider.d.ts +17 -0
- package/dist/src/capture/codex-cli-triage-provider.d.ts.map +1 -0
- package/dist/src/capture/codex-cli-triage-provider.js +109 -0
- package/dist/src/capture/codex-cli-triage-provider.js.map +1 -0
- package/dist/src/capture/observability.d.ts +42 -0
- package/dist/src/capture/observability.d.ts.map +1 -0
- package/dist/src/capture/observability.js +87 -0
- package/dist/src/capture/observability.js.map +1 -0
- package/dist/src/capture/openai-triage-provider.d.ts +92 -0
- package/dist/src/capture/openai-triage-provider.d.ts.map +1 -0
- package/dist/src/capture/openai-triage-provider.js +267 -0
- package/dist/src/capture/openai-triage-provider.js.map +1 -0
- package/dist/src/capture/review-queue-index.d.ts +51 -0
- package/dist/src/capture/review-queue-index.d.ts.map +1 -0
- package/dist/src/capture/review-queue-index.js +204 -0
- package/dist/src/capture/review-queue-index.js.map +1 -0
- package/dist/src/capture/review-queue.d.ts +43 -0
- package/dist/src/capture/review-queue.d.ts.map +1 -0
- package/dist/src/capture/review-queue.js +116 -0
- package/dist/src/capture/review-queue.js.map +1 -0
- package/dist/src/capture/sources.d.ts +7 -0
- package/dist/src/capture/sources.d.ts.map +1 -0
- package/dist/src/capture/sources.js +3 -0
- package/dist/src/capture/sources.js.map +1 -0
- package/dist/src/capture/triage-lane.d.ts +39 -0
- package/dist/src/capture/triage-lane.d.ts.map +1 -0
- package/dist/src/capture/triage-lane.js +217 -0
- package/dist/src/capture/triage-lane.js.map +1 -0
- package/dist/src/capture/triage-provider.d.ts +75 -0
- package/dist/src/capture/triage-provider.d.ts.map +1 -0
- package/dist/src/capture/triage-provider.js +120 -0
- package/dist/src/capture/triage-provider.js.map +1 -0
- package/dist/src/capture/triage.d.ts +30 -0
- package/dist/src/capture/triage.d.ts.map +1 -0
- package/dist/src/capture/triage.js +48 -0
- package/dist/src/capture/triage.js.map +1 -0
- package/dist/src/cli/commands/backfill.d.ts +3 -0
- package/dist/src/cli/commands/backfill.d.ts.map +1 -0
- package/dist/src/cli/commands/backfill.js +1376 -0
- package/dist/src/cli/commands/backfill.js.map +1 -0
- package/dist/src/cli/commands/bulk-ingest.d.ts +3 -0
- package/dist/src/cli/commands/bulk-ingest.d.ts.map +1 -0
- package/dist/src/cli/commands/bulk-ingest.js +126 -0
- package/dist/src/cli/commands/bulk-ingest.js.map +1 -0
- package/dist/src/cli/commands/capture.d.ts +12 -0
- package/dist/src/cli/commands/capture.d.ts.map +1 -0
- package/dist/src/cli/commands/capture.js +123 -0
- package/dist/src/cli/commands/capture.js.map +1 -0
- package/dist/src/cli/commands/compact.d.ts +3 -0
- package/dist/src/cli/commands/compact.d.ts.map +1 -0
- package/dist/src/cli/commands/compact.js +70 -0
- package/dist/src/cli/commands/compact.js.map +1 -0
- package/dist/src/cli/commands/feedback.d.ts +22 -0
- package/dist/src/cli/commands/feedback.d.ts.map +1 -0
- package/dist/src/cli/commands/feedback.js +125 -0
- package/dist/src/cli/commands/feedback.js.map +1 -0
- package/dist/src/cli/commands/hooks-install.d.ts +19 -0
- package/dist/src/cli/commands/hooks-install.d.ts.map +1 -0
- package/dist/src/cli/commands/hooks-install.js +103 -0
- package/dist/src/cli/commands/hooks-install.js.map +1 -0
- package/dist/src/cli/commands/import.d.ts +19 -0
- package/dist/src/cli/commands/import.d.ts.map +1 -0
- package/dist/src/cli/commands/import.js +258 -0
- package/dist/src/cli/commands/import.js.map +1 -0
- package/dist/src/cli/commands/ingest.d.ts +3 -0
- package/dist/src/cli/commands/ingest.d.ts.map +1 -0
- package/dist/src/cli/commands/ingest.js +80 -0
- package/dist/src/cli/commands/ingest.js.map +1 -0
- package/dist/src/cli/commands/mcp-install.d.ts +25 -0
- package/dist/src/cli/commands/mcp-install.d.ts.map +1 -0
- package/dist/src/cli/commands/mcp-install.js +134 -0
- package/dist/src/cli/commands/mcp-install.js.map +1 -0
- package/dist/src/cli/commands/onboard.d.ts +98 -0
- package/dist/src/cli/commands/onboard.d.ts.map +1 -0
- package/dist/src/cli/commands/onboard.js +823 -0
- package/dist/src/cli/commands/onboard.js.map +1 -0
- package/dist/src/cli/commands/rebuild.d.ts +12 -0
- package/dist/src/cli/commands/rebuild.d.ts.map +1 -0
- package/dist/src/cli/commands/rebuild.js +164 -0
- package/dist/src/cli/commands/rebuild.js.map +1 -0
- package/dist/src/cli/commands/reconcile.d.ts +3 -0
- package/dist/src/cli/commands/reconcile.d.ts.map +1 -0
- package/dist/src/cli/commands/reconcile.js +56 -0
- package/dist/src/cli/commands/reconcile.js.map +1 -0
- package/dist/src/cli/commands/reindex.d.ts +3 -0
- package/dist/src/cli/commands/reindex.d.ts.map +1 -0
- package/dist/src/cli/commands/reindex.js +66 -0
- package/dist/src/cli/commands/reindex.js.map +1 -0
- package/dist/src/cli/commands/review.d.ts +13 -0
- package/dist/src/cli/commands/review.d.ts.map +1 -0
- package/dist/src/cli/commands/review.js +383 -0
- package/dist/src/cli/commands/review.js.map +1 -0
- package/dist/src/cli/commands/save.d.ts +3 -0
- package/dist/src/cli/commands/save.d.ts.map +1 -0
- package/dist/src/cli/commands/save.js +111 -0
- package/dist/src/cli/commands/save.js.map +1 -0
- package/dist/src/cli/commands/search.d.ts +35 -0
- package/dist/src/cli/commands/search.d.ts.map +1 -0
- package/dist/src/cli/commands/search.js +88 -0
- package/dist/src/cli/commands/search.js.map +1 -0
- package/dist/src/cli/commands/stats.d.ts +3 -0
- package/dist/src/cli/commands/stats.d.ts.map +1 -0
- package/dist/src/cli/commands/stats.js +42 -0
- package/dist/src/cli/commands/stats.js.map +1 -0
- package/dist/src/cli/commands/status.d.ts +15 -0
- package/dist/src/cli/commands/status.d.ts.map +1 -0
- package/dist/src/cli/commands/status.js +89 -0
- package/dist/src/cli/commands/status.js.map +1 -0
- package/dist/src/cli/commands/token-issue.d.ts +3 -0
- package/dist/src/cli/commands/token-issue.d.ts.map +1 -0
- package/dist/src/cli/commands/token-issue.js +25 -0
- package/dist/src/cli/commands/token-issue.js.map +1 -0
- package/dist/src/cli/commands/triage.d.ts +3 -0
- package/dist/src/cli/commands/triage.d.ts.map +1 -0
- package/dist/src/cli/commands/triage.js +125 -0
- package/dist/src/cli/commands/triage.js.map +1 -0
- package/dist/src/cli/commands/uninstall.d.ts +3 -0
- package/dist/src/cli/commands/uninstall.d.ts.map +1 -0
- package/dist/src/cli/commands/uninstall.js +238 -0
- package/dist/src/cli/commands/uninstall.js.map +1 -0
- package/dist/src/cli/feedback/feedback-config.d.ts +21 -0
- package/dist/src/cli/feedback/feedback-config.d.ts.map +1 -0
- package/dist/src/cli/feedback/feedback-config.js +43 -0
- package/dist/src/cli/feedback/feedback-config.js.map +1 -0
- package/dist/src/cli/feedback/feedback-history.d.ts +4 -0
- package/dist/src/cli/feedback/feedback-history.d.ts.map +1 -0
- package/dist/src/cli/feedback/feedback-history.js +115 -0
- package/dist/src/cli/feedback/feedback-history.js.map +1 -0
- package/dist/src/cli/feedback/feedback-payload.d.ts +53 -0
- package/dist/src/cli/feedback/feedback-payload.d.ts.map +1 -0
- package/dist/src/cli/feedback/feedback-payload.js +10 -0
- package/dist/src/cli/feedback/feedback-payload.js.map +1 -0
- package/dist/src/cli/feedback/feedback-relay.d.ts +15 -0
- package/dist/src/cli/feedback/feedback-relay.d.ts.map +1 -0
- package/dist/src/cli/feedback/feedback-relay.js +47 -0
- package/dist/src/cli/feedback/feedback-relay.js.map +1 -0
- package/dist/src/cli/feedback/feedback-status.d.ts +11 -0
- package/dist/src/cli/feedback/feedback-status.d.ts.map +1 -0
- package/dist/src/cli/feedback/feedback-status.js +122 -0
- package/dist/src/cli/feedback/feedback-status.js.map +1 -0
- package/dist/src/cli/hooks-writers/claude-code-policy-script.d.ts +25 -0
- package/dist/src/cli/hooks-writers/claude-code-policy-script.d.ts.map +1 -0
- package/dist/src/cli/hooks-writers/claude-code-policy-script.js +85 -0
- package/dist/src/cli/hooks-writers/claude-code-policy-script.js.map +1 -0
- package/dist/src/cli/hooks-writers/claude-code.d.ts +12 -0
- package/dist/src/cli/hooks-writers/claude-code.d.ts.map +1 -0
- package/dist/src/cli/hooks-writers/claude-code.js +228 -0
- package/dist/src/cli/hooks-writers/claude-code.js.map +1 -0
- package/dist/src/cli/hooks-writers/errors.d.ts +16 -0
- package/dist/src/cli/hooks-writers/errors.d.ts.map +1 -0
- package/dist/src/cli/hooks-writers/errors.js +24 -0
- package/dist/src/cli/hooks-writers/errors.js.map +1 -0
- package/dist/src/cli/hooks-writers/index.d.ts +13 -0
- package/dist/src/cli/hooks-writers/index.d.ts.map +1 -0
- package/dist/src/cli/hooks-writers/index.js +26 -0
- package/dist/src/cli/hooks-writers/index.js.map +1 -0
- package/dist/src/cli/hooks-writers/types.d.ts +27 -0
- package/dist/src/cli/hooks-writers/types.d.ts.map +1 -0
- package/dist/src/cli/hooks-writers/types.js +9 -0
- package/dist/src/cli/hooks-writers/types.js.map +1 -0
- package/dist/src/cli/http-client.d.ts +36 -0
- package/dist/src/cli/http-client.d.ts.map +1 -0
- package/dist/src/cli/http-client.js +153 -0
- package/dist/src/cli/http-client.js.map +1 -0
- package/dist/src/cli/index.d.ts +4 -0
- package/dist/src/cli/index.d.ts.map +1 -0
- package/dist/src/cli/index.js +68 -0
- package/dist/src/cli/index.js.map +1 -0
- package/dist/src/cli/job-poller.d.ts +13 -0
- package/dist/src/cli/job-poller.d.ts.map +1 -0
- package/dist/src/cli/job-poller.js +29 -0
- package/dist/src/cli/job-poller.js.map +1 -0
- package/dist/src/cli/mcp-config-writers/codex-toml.d.ts +10 -0
- package/dist/src/cli/mcp-config-writers/codex-toml.d.ts.map +1 -0
- package/dist/src/cli/mcp-config-writers/codex-toml.js +410 -0
- package/dist/src/cli/mcp-config-writers/codex-toml.js.map +1 -0
- package/dist/src/cli/mcp-config-writers/errors.d.ts +17 -0
- package/dist/src/cli/mcp-config-writers/errors.d.ts.map +1 -0
- package/dist/src/cli/mcp-config-writers/errors.js +13 -0
- package/dist/src/cli/mcp-config-writers/errors.js.map +1 -0
- package/dist/src/cli/mcp-config-writers/index.d.ts +18 -0
- package/dist/src/cli/mcp-config-writers/index.d.ts.map +1 -0
- package/dist/src/cli/mcp-config-writers/index.js +49 -0
- package/dist/src/cli/mcp-config-writers/index.js.map +1 -0
- package/dist/src/cli/mcp-config-writers/json-config.d.ts +12 -0
- package/dist/src/cli/mcp-config-writers/json-config.d.ts.map +1 -0
- package/dist/src/cli/mcp-config-writers/json-config.js +177 -0
- package/dist/src/cli/mcp-config-writers/json-config.js.map +1 -0
- package/dist/src/cli/mcp-config-writers/redact.d.ts +28 -0
- package/dist/src/cli/mcp-config-writers/redact.d.ts.map +1 -0
- package/dist/src/cli/mcp-config-writers/redact.js +48 -0
- package/dist/src/cli/mcp-config-writers/redact.js.map +1 -0
- package/dist/src/cli/mcp-config-writers/types.d.ts +32 -0
- package/dist/src/cli/mcp-config-writers/types.d.ts.map +1 -0
- package/dist/src/cli/mcp-config-writers/types.js +5 -0
- package/dist/src/cli/mcp-config-writers/types.js.map +1 -0
- package/dist/src/cli/output.d.ts +8 -0
- package/dist/src/cli/output.d.ts.map +1 -0
- package/dist/src/cli/output.js +34 -0
- package/dist/src/cli/output.js.map +1 -0
- package/dist/src/cli/status/friend-header.d.ts +33 -0
- package/dist/src/cli/status/friend-header.d.ts.map +1 -0
- package/dist/src/cli/status/friend-header.js +108 -0
- package/dist/src/cli/status/friend-header.js.map +1 -0
- package/dist/src/cli/status/local-signals.d.ts +14 -0
- package/dist/src/cli/status/local-signals.d.ts.map +1 -0
- package/dist/src/cli/status/local-signals.js +73 -0
- package/dist/src/cli/status/local-signals.js.map +1 -0
- package/dist/src/cli/token.d.ts +37 -0
- package/dist/src/cli/token.d.ts.map +1 -0
- package/dist/src/cli/token.js +105 -0
- package/dist/src/cli/token.js.map +1 -0
- package/dist/src/cli/uninstall/mcp-uninstall.d.ts +33 -0
- package/dist/src/cli/uninstall/mcp-uninstall.d.ts.map +1 -0
- package/dist/src/cli/uninstall/mcp-uninstall.js +181 -0
- package/dist/src/cli/uninstall/mcp-uninstall.js.map +1 -0
- package/dist/src/config/loader.d.ts +9 -0
- package/dist/src/config/loader.d.ts.map +1 -0
- package/dist/src/config/loader.js +73 -0
- package/dist/src/config/loader.js.map +1 -0
- package/dist/src/config/schema.d.ts +635 -0
- package/dist/src/config/schema.d.ts.map +1 -0
- package/dist/src/config/schema.js +208 -0
- package/dist/src/config/schema.js.map +1 -0
- package/dist/src/ingestion/bulk-ingest.d.ts +11 -0
- package/dist/src/ingestion/bulk-ingest.d.ts.map +1 -0
- package/dist/src/ingestion/bulk-ingest.js +11 -0
- package/dist/src/ingestion/bulk-ingest.js.map +1 -0
- package/dist/src/ingestion/extractor.d.ts +16 -0
- package/dist/src/ingestion/extractor.d.ts.map +1 -0
- package/dist/src/ingestion/extractor.js +85 -0
- package/dist/src/ingestion/extractor.js.map +1 -0
- package/dist/src/ingestion/extractors/docx.d.ts +3 -0
- package/dist/src/ingestion/extractors/docx.d.ts.map +1 -0
- package/dist/src/ingestion/extractors/docx.js +20 -0
- package/dist/src/ingestion/extractors/docx.js.map +1 -0
- package/dist/src/ingestion/extractors/pdf.d.ts +3 -0
- package/dist/src/ingestion/extractors/pdf.d.ts.map +1 -0
- package/dist/src/ingestion/extractors/pdf.js +32 -0
- package/dist/src/ingestion/extractors/pdf.js.map +1 -0
- package/dist/src/ingestion/historical-campaign.d.ts +340 -0
- package/dist/src/ingestion/historical-campaign.d.ts.map +1 -0
- package/dist/src/ingestion/historical-campaign.js +1010 -0
- package/dist/src/ingestion/historical-campaign.js.map +1 -0
- package/dist/src/ingestion/ignored-paths.d.ts +20 -0
- package/dist/src/ingestion/ignored-paths.d.ts.map +1 -0
- package/dist/src/ingestion/ignored-paths.js +45 -0
- package/dist/src/ingestion/ignored-paths.js.map +1 -0
- package/dist/src/ingestion/inbox-watcher.d.ts +12 -0
- package/dist/src/ingestion/inbox-watcher.d.ts.map +1 -0
- package/dist/src/ingestion/inbox-watcher.js +99 -0
- package/dist/src/ingestion/inbox-watcher.js.map +1 -0
- package/dist/src/ingestion/indexer.d.ts +32 -0
- package/dist/src/ingestion/indexer.d.ts.map +1 -0
- package/dist/src/ingestion/indexer.js +68 -0
- package/dist/src/ingestion/indexer.js.map +1 -0
- package/dist/src/ingestion/metadata-extraction.d.ts +53 -0
- package/dist/src/ingestion/metadata-extraction.d.ts.map +1 -0
- package/dist/src/ingestion/metadata-extraction.js +132 -0
- package/dist/src/ingestion/metadata-extraction.js.map +1 -0
- package/dist/src/ingestion/parsers/chatgpt-web.d.ts +29 -0
- package/dist/src/ingestion/parsers/chatgpt-web.d.ts.map +1 -0
- package/dist/src/ingestion/parsers/chatgpt-web.js +100 -0
- package/dist/src/ingestion/parsers/chatgpt-web.js.map +1 -0
- package/dist/src/ingestion/parsers/claude-code-jsonl.d.ts +16 -0
- package/dist/src/ingestion/parsers/claude-code-jsonl.d.ts.map +1 -0
- package/dist/src/ingestion/parsers/claude-code-jsonl.js +123 -0
- package/dist/src/ingestion/parsers/claude-code-jsonl.js.map +1 -0
- package/dist/src/ingestion/parsers/claude-web.d.ts +24 -0
- package/dist/src/ingestion/parsers/claude-web.d.ts.map +1 -0
- package/dist/src/ingestion/parsers/claude-web.js +78 -0
- package/dist/src/ingestion/parsers/claude-web.js.map +1 -0
- package/dist/src/ingestion/parsers/codex-jsonl.d.ts +18 -0
- package/dist/src/ingestion/parsers/codex-jsonl.d.ts.map +1 -0
- package/dist/src/ingestion/parsers/codex-jsonl.js +125 -0
- package/dist/src/ingestion/parsers/codex-jsonl.js.map +1 -0
- package/dist/src/ingestion/parsers/gemini-web.d.ts +16 -0
- package/dist/src/ingestion/parsers/gemini-web.d.ts.map +1 -0
- package/dist/src/ingestion/parsers/gemini-web.js +170 -0
- package/dist/src/ingestion/parsers/gemini-web.js.map +1 -0
- package/dist/src/ingestion/parsers/grok-web.d.ts +40 -0
- package/dist/src/ingestion/parsers/grok-web.d.ts.map +1 -0
- package/dist/src/ingestion/parsers/grok-web.js +67 -0
- package/dist/src/ingestion/parsers/grok-web.js.map +1 -0
- package/dist/src/ingestion/parsers/types.d.ts +34 -0
- package/dist/src/ingestion/parsers/types.d.ts.map +1 -0
- package/dist/src/ingestion/parsers/types.js +26 -0
- package/dist/src/ingestion/parsers/types.js.map +1 -0
- package/dist/src/ingestion/scanner.d.ts +48 -0
- package/dist/src/ingestion/scanner.d.ts.map +1 -0
- package/dist/src/ingestion/scanner.js +131 -0
- package/dist/src/ingestion/scanner.js.map +1 -0
- package/dist/src/ingestion/staging.d.ts +109 -0
- package/dist/src/ingestion/staging.d.ts.map +1 -0
- package/dist/src/ingestion/staging.js +411 -0
- package/dist/src/ingestion/staging.js.map +1 -0
- package/dist/src/ingestion/watcher.d.ts +65 -0
- package/dist/src/ingestion/watcher.d.ts.map +1 -0
- package/dist/src/ingestion/watcher.js +182 -0
- package/dist/src/ingestion/watcher.js.map +1 -0
- package/dist/src/jobs/codex-override-handler.d.ts +3 -0
- package/dist/src/jobs/codex-override-handler.d.ts.map +1 -0
- package/dist/src/jobs/codex-override-handler.js +16 -0
- package/dist/src/jobs/codex-override-handler.js.map +1 -0
- package/dist/src/jobs/handlers/compact.d.ts +30 -0
- package/dist/src/jobs/handlers/compact.d.ts.map +1 -0
- package/dist/src/jobs/handlers/compact.js +329 -0
- package/dist/src/jobs/handlers/compact.js.map +1 -0
- package/dist/src/jobs/handlers/ingest.d.ts +13 -0
- package/dist/src/jobs/handlers/ingest.d.ts.map +1 -0
- package/dist/src/jobs/handlers/ingest.js +255 -0
- package/dist/src/jobs/handlers/ingest.js.map +1 -0
- package/dist/src/jobs/handlers/reconcile.d.ts +29 -0
- package/dist/src/jobs/handlers/reconcile.d.ts.map +1 -0
- package/dist/src/jobs/handlers/reconcile.js +476 -0
- package/dist/src/jobs/handlers/reconcile.js.map +1 -0
- package/dist/src/jobs/handlers/reindex.d.ts +38 -0
- package/dist/src/jobs/handlers/reindex.d.ts.map +1 -0
- package/dist/src/jobs/handlers/reindex.js +52 -0
- package/dist/src/jobs/handlers/reindex.js.map +1 -0
- package/dist/src/jobs/handlers/save.d.ts +10 -0
- package/dist/src/jobs/handlers/save.d.ts.map +1 -0
- package/dist/src/jobs/handlers/save.js +206 -0
- package/dist/src/jobs/handlers/save.js.map +1 -0
- package/dist/src/jobs/handlers/triage.d.ts +47 -0
- package/dist/src/jobs/handlers/triage.d.ts.map +1 -0
- package/dist/src/jobs/handlers/triage.js +95 -0
- package/dist/src/jobs/handlers/triage.js.map +1 -0
- package/dist/src/jobs/queue.d.ts +107 -0
- package/dist/src/jobs/queue.d.ts.map +1 -0
- package/dist/src/jobs/queue.js +319 -0
- package/dist/src/jobs/queue.js.map +1 -0
- package/dist/src/jobs/types.d.ts +39 -0
- package/dist/src/jobs/types.d.ts.map +1 -0
- package/dist/src/jobs/types.js +29 -0
- package/dist/src/jobs/types.js.map +1 -0
- package/dist/src/jobs/worker-entry.d.ts +10 -0
- package/dist/src/jobs/worker-entry.d.ts.map +1 -0
- package/dist/src/jobs/worker-entry.js +210 -0
- package/dist/src/jobs/worker-entry.js.map +1 -0
- package/dist/src/jobs/worker-process.d.ts +50 -0
- package/dist/src/jobs/worker-process.d.ts.map +1 -0
- package/dist/src/jobs/worker-process.js +186 -0
- package/dist/src/jobs/worker-process.js.map +1 -0
- package/dist/src/jobs/worker.d.ts +11 -0
- package/dist/src/jobs/worker.d.ts.map +1 -0
- package/dist/src/jobs/worker.js +14 -0
- package/dist/src/jobs/worker.js.map +1 -0
- package/dist/src/main.d.ts +2 -0
- package/dist/src/main.d.ts.map +1 -0
- package/dist/src/main.js +425 -0
- package/dist/src/main.js.map +1 -0
- package/dist/src/mcp/errors.d.ts +8 -0
- package/dist/src/mcp/errors.d.ts.map +1 -0
- package/dist/src/mcp/errors.js +50 -0
- package/dist/src/mcp/errors.js.map +1 -0
- package/dist/src/mcp/server.d.ts +10 -0
- package/dist/src/mcp/server.d.ts.map +1 -0
- package/dist/src/mcp/server.js +94 -0
- package/dist/src/mcp/server.js.map +1 -0
- package/dist/src/mcp/tools/context-pack.d.ts +35 -0
- package/dist/src/mcp/tools/context-pack.d.ts.map +1 -0
- package/dist/src/mcp/tools/context-pack.js +97 -0
- package/dist/src/mcp/tools/context-pack.js.map +1 -0
- package/dist/src/mcp/tools/conversations-search.d.ts +38 -0
- package/dist/src/mcp/tools/conversations-search.d.ts.map +1 -0
- package/dist/src/mcp/tools/conversations-search.js +73 -0
- package/dist/src/mcp/tools/conversations-search.js.map +1 -0
- package/dist/src/mcp/tools/save.d.ts +32 -0
- package/dist/src/mcp/tools/save.d.ts.map +1 -0
- package/dist/src/mcp/tools/save.js +60 -0
- package/dist/src/mcp/tools/save.js.map +1 -0
- package/dist/src/mcp/tools/search.d.ts +33 -0
- package/dist/src/mcp/tools/search.d.ts.map +1 -0
- package/dist/src/mcp/tools/search.js +58 -0
- package/dist/src/mcp/tools/search.js.map +1 -0
- package/dist/src/mcp/tools/status.d.ts +17 -0
- package/dist/src/mcp/tools/status.d.ts.map +1 -0
- package/dist/src/mcp/tools/status.js +12 -0
- package/dist/src/mcp/tools/status.js.map +1 -0
- package/dist/src/observability/coverage.d.ts +100 -0
- package/dist/src/observability/coverage.d.ts.map +1 -0
- package/dist/src/observability/coverage.js +180 -0
- package/dist/src/observability/coverage.js.map +1 -0
- package/dist/src/observability/rift-context.d.ts +47 -0
- package/dist/src/observability/rift-context.d.ts.map +1 -0
- package/dist/src/observability/rift-context.js +118 -0
- package/dist/src/observability/rift-context.js.map +1 -0
- package/dist/src/observability/staleness.d.ts +43 -0
- package/dist/src/observability/staleness.d.ts.map +1 -0
- package/dist/src/observability/staleness.js +74 -0
- package/dist/src/observability/staleness.js.map +1 -0
- package/dist/src/observability/tool-usage-stats.d.ts +23 -0
- package/dist/src/observability/tool-usage-stats.d.ts.map +1 -0
- package/dist/src/observability/tool-usage-stats.js +83 -0
- package/dist/src/observability/tool-usage-stats.js.map +1 -0
- package/dist/src/observability/tool-usage.d.ts +68 -0
- package/dist/src/observability/tool-usage.d.ts.map +1 -0
- package/dist/src/observability/tool-usage.js +207 -0
- package/dist/src/observability/tool-usage.js.map +1 -0
- package/dist/src/onboarding/daemon-control.d.ts +33 -0
- package/dist/src/onboarding/daemon-control.d.ts.map +1 -0
- package/dist/src/onboarding/daemon-control.js +92 -0
- package/dist/src/onboarding/daemon-control.js.map +1 -0
- package/dist/src/onboarding/env-file.d.ts +18 -0
- package/dist/src/onboarding/env-file.d.ts.map +1 -0
- package/dist/src/onboarding/env-file.js +89 -0
- package/dist/src/onboarding/env-file.js.map +1 -0
- package/dist/src/onboarding/voyage-validate.d.ts +16 -0
- package/dist/src/onboarding/voyage-validate.d.ts.map +1 -0
- package/dist/src/onboarding/voyage-validate.js +85 -0
- package/dist/src/onboarding/voyage-validate.js.map +1 -0
- package/dist/src/providers/anthropic-digest.d.ts +23 -0
- package/dist/src/providers/anthropic-digest.d.ts.map +1 -0
- package/dist/src/providers/anthropic-digest.js +91 -0
- package/dist/src/providers/anthropic-digest.js.map +1 -0
- package/dist/src/providers/codex-cli-digest.d.ts +12 -0
- package/dist/src/providers/codex-cli-digest.d.ts.map +1 -0
- package/dist/src/providers/codex-cli-digest.js +70 -0
- package/dist/src/providers/codex-cli-digest.js.map +1 -0
- package/dist/src/providers/codex-cli-metadata-extraction.d.ts +14 -0
- package/dist/src/providers/codex-cli-metadata-extraction.d.ts.map +1 -0
- package/dist/src/providers/codex-cli-metadata-extraction.js +101 -0
- package/dist/src/providers/codex-cli-metadata-extraction.js.map +1 -0
- package/dist/src/providers/codex-cli-runner.d.ts +14 -0
- package/dist/src/providers/codex-cli-runner.d.ts.map +1 -0
- package/dist/src/providers/codex-cli-runner.js +272 -0
- package/dist/src/providers/codex-cli-runner.js.map +1 -0
- package/dist/src/providers/conversation-generation.d.ts +10 -0
- package/dist/src/providers/conversation-generation.d.ts.map +1 -0
- package/dist/src/providers/conversation-generation.js +54 -0
- package/dist/src/providers/conversation-generation.js.map +1 -0
- package/dist/src/providers/ollama-embed.d.ts +22 -0
- package/dist/src/providers/ollama-embed.d.ts.map +1 -0
- package/dist/src/providers/ollama-embed.js +133 -0
- package/dist/src/providers/ollama-embed.js.map +1 -0
- package/dist/src/providers/ollama.d.ts +42 -0
- package/dist/src/providers/ollama.d.ts.map +1 -0
- package/dist/src/providers/ollama.js +169 -0
- package/dist/src/providers/ollama.js.map +1 -0
- package/dist/src/providers/openai-metadata-extraction.d.ts +73 -0
- package/dist/src/providers/openai-metadata-extraction.d.ts.map +1 -0
- package/dist/src/providers/openai-metadata-extraction.js +161 -0
- package/dist/src/providers/openai-metadata-extraction.js.map +1 -0
- package/dist/src/providers/operator-overrides.d.ts +24 -0
- package/dist/src/providers/operator-overrides.d.ts.map +1 -0
- package/dist/src/providers/operator-overrides.js +84 -0
- package/dist/src/providers/operator-overrides.js.map +1 -0
- package/dist/src/providers/stub.d.ts +17 -0
- package/dist/src/providers/stub.d.ts.map +1 -0
- package/dist/src/providers/stub.js +72 -0
- package/dist/src/providers/stub.js.map +1 -0
- package/dist/src/providers/types.d.ts +82 -0
- package/dist/src/providers/types.d.ts.map +1 -0
- package/dist/src/providers/types.js +52 -0
- package/dist/src/providers/types.js.map +1 -0
- package/dist/src/providers/voyage.d.ts +23 -0
- package/dist/src/providers/voyage.d.ts.map +1 -0
- package/dist/src/providers/voyage.js +135 -0
- package/dist/src/providers/voyage.js.map +1 -0
- package/dist/src/retrieval/compact.d.ts +89 -0
- package/dist/src/retrieval/compact.d.ts.map +1 -0
- package/dist/src/retrieval/compact.js +348 -0
- package/dist/src/retrieval/compact.js.map +1 -0
- package/dist/src/retrieval/context-pack.d.ts +123 -0
- package/dist/src/retrieval/context-pack.d.ts.map +1 -0
- package/dist/src/retrieval/context-pack.js +553 -0
- package/dist/src/retrieval/context-pack.js.map +1 -0
- package/dist/src/retrieval/cwd.d.ts +25 -0
- package/dist/src/retrieval/cwd.d.ts.map +1 -0
- package/dist/src/retrieval/cwd.js +48 -0
- package/dist/src/retrieval/cwd.js.map +1 -0
- package/dist/src/retrieval/degraded.d.ts +20 -0
- package/dist/src/retrieval/degraded.d.ts.map +1 -0
- package/dist/src/retrieval/degraded.js +43 -0
- package/dist/src/retrieval/degraded.js.map +1 -0
- package/dist/src/retrieval/hybrid.d.ts +38 -0
- package/dist/src/retrieval/hybrid.d.ts.map +1 -0
- package/dist/src/retrieval/hybrid.js +82 -0
- package/dist/src/retrieval/hybrid.js.map +1 -0
- package/dist/src/retrieval/lexical.d.ts +28 -0
- package/dist/src/retrieval/lexical.d.ts.map +1 -0
- package/dist/src/retrieval/lexical.js +301 -0
- package/dist/src/retrieval/lexical.js.map +1 -0
- package/dist/src/retrieval/post-filter.d.ts +32 -0
- package/dist/src/retrieval/post-filter.d.ts.map +1 -0
- package/dist/src/retrieval/post-filter.js +57 -0
- package/dist/src/retrieval/post-filter.js.map +1 -0
- package/dist/src/retrieval/reranker.d.ts +72 -0
- package/dist/src/retrieval/reranker.d.ts.map +1 -0
- package/dist/src/retrieval/reranker.js +129 -0
- package/dist/src/retrieval/reranker.js.map +1 -0
- package/dist/src/retrieval/vector.d.ts +47 -0
- package/dist/src/retrieval/vector.d.ts.map +1 -0
- package/dist/src/retrieval/vector.js +112 -0
- package/dist/src/retrieval/vector.js.map +1 -0
- package/dist/src/runtime/legacy-migration.d.ts +27 -0
- package/dist/src/runtime/legacy-migration.d.ts.map +1 -0
- package/dist/src/runtime/legacy-migration.js +140 -0
- package/dist/src/runtime/legacy-migration.js.map +1 -0
- package/dist/src/runtime/legacy-name-guard.d.ts +35 -0
- package/dist/src/runtime/legacy-name-guard.d.ts.map +1 -0
- package/dist/src/runtime/legacy-name-guard.js +58 -0
- package/dist/src/runtime/legacy-name-guard.js.map +1 -0
- package/dist/src/runtime/rift-env.d.ts +14 -0
- package/dist/src/runtime/rift-env.d.ts.map +1 -0
- package/dist/src/runtime/rift-env.js +79 -0
- package/dist/src/runtime/rift-env.js.map +1 -0
- package/dist/src/runtime/watcher-startup.d.ts +2 -0
- package/dist/src/runtime/watcher-startup.d.ts.map +1 -0
- package/dist/src/runtime/watcher-startup.js +4 -0
- package/dist/src/runtime/watcher-startup.js.map +1 -0
- package/dist/src/security/archive.d.ts +23 -0
- package/dist/src/security/archive.d.ts.map +1 -0
- package/dist/src/security/archive.js +163 -0
- package/dist/src/security/archive.js.map +1 -0
- package/dist/src/security/paths.d.ts +21 -0
- package/dist/src/security/paths.d.ts.map +1 -0
- package/dist/src/security/paths.js +67 -0
- package/dist/src/security/paths.js.map +1 -0
- package/dist/src/server/app.d.ts +29 -0
- package/dist/src/server/app.d.ts.map +1 -0
- package/dist/src/server/app.js +226 -0
- package/dist/src/server/app.js.map +1 -0
- package/dist/src/server/build-info.d.ts +8 -0
- package/dist/src/server/build-info.d.ts.map +1 -0
- package/dist/src/server/build-info.js +61 -0
- package/dist/src/server/build-info.js.map +1 -0
- package/dist/src/server/lifecycle.d.ts +30 -0
- package/dist/src/server/lifecycle.d.ts.map +1 -0
- package/dist/src/server/lifecycle.js +59 -0
- package/dist/src/server/lifecycle.js.map +1 -0
- package/dist/src/server/middleware/multipart.d.ts +51 -0
- package/dist/src/server/middleware/multipart.d.ts.map +1 -0
- package/dist/src/server/middleware/multipart.js +86 -0
- package/dist/src/server/middleware/multipart.js.map +1 -0
- package/dist/src/server/routes/compact.d.ts +37 -0
- package/dist/src/server/routes/compact.d.ts.map +1 -0
- package/dist/src/server/routes/compact.js +77 -0
- package/dist/src/server/routes/compact.js.map +1 -0
- package/dist/src/server/routes/context.d.ts +5 -0
- package/dist/src/server/routes/context.d.ts.map +1 -0
- package/dist/src/server/routes/context.js +50 -0
- package/dist/src/server/routes/context.js.map +1 -0
- package/dist/src/server/routes/conversations-search.d.ts +4 -0
- package/dist/src/server/routes/conversations-search.d.ts.map +1 -0
- package/dist/src/server/routes/conversations-search.js +243 -0
- package/dist/src/server/routes/conversations-search.js.map +1 -0
- package/dist/src/server/routes/friend-status.d.ts +72 -0
- package/dist/src/server/routes/friend-status.d.ts.map +1 -0
- package/dist/src/server/routes/friend-status.js +71 -0
- package/dist/src/server/routes/friend-status.js.map +1 -0
- package/dist/src/server/routes/ingest.d.ts +15 -0
- package/dist/src/server/routes/ingest.d.ts.map +1 -0
- package/dist/src/server/routes/ingest.js +139 -0
- package/dist/src/server/routes/ingest.js.map +1 -0
- package/dist/src/server/routes/jobs.d.ts +10 -0
- package/dist/src/server/routes/jobs.d.ts.map +1 -0
- package/dist/src/server/routes/jobs.js +29 -0
- package/dist/src/server/routes/jobs.js.map +1 -0
- package/dist/src/server/routes/mcp-usage.d.ts +13 -0
- package/dist/src/server/routes/mcp-usage.d.ts.map +1 -0
- package/dist/src/server/routes/mcp-usage.js +17 -0
- package/dist/src/server/routes/mcp-usage.js.map +1 -0
- package/dist/src/server/routes/reconcile.d.ts +4 -0
- package/dist/src/server/routes/reconcile.d.ts.map +1 -0
- package/dist/src/server/routes/reconcile.js +43 -0
- package/dist/src/server/routes/reconcile.js.map +1 -0
- package/dist/src/server/routes/reindex.d.ts +4 -0
- package/dist/src/server/routes/reindex.d.ts.map +1 -0
- package/dist/src/server/routes/reindex.js +74 -0
- package/dist/src/server/routes/reindex.js.map +1 -0
- package/dist/src/server/routes/save.d.ts +40 -0
- package/dist/src/server/routes/save.d.ts.map +1 -0
- package/dist/src/server/routes/save.js +112 -0
- package/dist/src/server/routes/save.js.map +1 -0
- package/dist/src/server/routes/search.d.ts +5 -0
- package/dist/src/server/routes/search.d.ts.map +1 -0
- package/dist/src/server/routes/search.js +400 -0
- package/dist/src/server/routes/search.js.map +1 -0
- package/dist/src/server/routes/stats.d.ts +10 -0
- package/dist/src/server/routes/stats.d.ts.map +1 -0
- package/dist/src/server/routes/stats.js +15 -0
- package/dist/src/server/routes/stats.js.map +1 -0
- package/dist/src/server/routes/status.d.ts +20 -0
- package/dist/src/server/routes/status.d.ts.map +1 -0
- package/dist/src/server/routes/status.js +31 -0
- package/dist/src/server/routes/status.js.map +1 -0
- package/dist/src/server/routes/triage.d.ts +4 -0
- package/dist/src/server/routes/triage.d.ts.map +1 -0
- package/dist/src/server/routes/triage.js +94 -0
- package/dist/src/server/routes/triage.js.map +1 -0
- package/dist/src/server/save-quality.d.ts +21 -0
- package/dist/src/server/save-quality.d.ts.map +1 -0
- package/dist/src/server/save-quality.js +51 -0
- package/dist/src/server/save-quality.js.map +1 -0
- package/dist/src/storage/atomic.d.ts +8 -0
- package/dist/src/storage/atomic.d.ts.map +1 -0
- package/dist/src/storage/atomic.js +22 -0
- package/dist/src/storage/atomic.js.map +1 -0
- package/dist/src/storage/db.d.ts +15 -0
- package/dist/src/storage/db.d.ts.map +1 -0
- package/dist/src/storage/db.js +43 -0
- package/dist/src/storage/db.js.map +1 -0
- package/dist/src/storage/integrity.d.ts +11 -0
- package/dist/src/storage/integrity.d.ts.map +1 -0
- package/dist/src/storage/integrity.js +66 -0
- package/dist/src/storage/integrity.js.map +1 -0
- package/dist/src/storage/rebuild.d.ts +37 -0
- package/dist/src/storage/rebuild.d.ts.map +1 -0
- package/dist/src/storage/rebuild.js +353 -0
- package/dist/src/storage/rebuild.js.map +1 -0
- package/dist/src/storage/shadow-swap.d.ts +20 -0
- package/dist/src/storage/shadow-swap.d.ts.map +1 -0
- package/dist/src/storage/shadow-swap.js +163 -0
- package/dist/src/storage/shadow-swap.js.map +1 -0
- package/dist/src/storage/tables.d.ts +77 -0
- package/dist/src/storage/tables.d.ts.map +1 -0
- package/dist/src/storage/tables.js +196 -0
- package/dist/src/storage/tables.js.map +1 -0
- package/package.json +45 -14
- package/index.js +0 -3
package/README.dev.md
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Rift (`rift`)
|
|
2
|
+
|
|
3
|
+
Local-first personal memory + reasoning infrastructure. Captures local CLI sessions, web conversation exports, and project documents; routes them through triage, metadata extraction, and embedding; persists into LanceDB; exposes retrieval through a small MCP surface so agents can pull *capability, not payload*.
|
|
4
|
+
|
|
5
|
+
Designed to feel like a built-in capability for whatever assistant is in front of it, not like a giant preloaded briefing.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Architecture at a glance
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
┌─────────────────────────────────────────────────────────┐
|
|
13
|
+
│ Live capture (claude_code, codex_cli session JSONLs) │
|
|
14
|
+
│ Web exports (chatgpt_web, claude_web, gemini, grok) │
|
|
15
|
+
│ Project docs (filesystem watchers / scheduled scans) │
|
|
16
|
+
└────────────────────┬────────────────────────────────────┘
|
|
17
|
+
│
|
|
18
|
+
┌────▼────┐
|
|
19
|
+
│ Triage │ ← Codex CLI (default)
|
|
20
|
+
│ loop │
|
|
21
|
+
└────┬────┘
|
|
22
|
+
│ save / review / discard
|
|
23
|
+
│
|
|
24
|
+
┌────▼─────────────┐
|
|
25
|
+
│ Metadata extract │ ← Codex CLI (web/ingest path)
|
|
26
|
+
│ (POST /ingest) │
|
|
27
|
+
└────┬─────────────┘
|
|
28
|
+
│
|
|
29
|
+
┌────▼──────────────────────────────────┐
|
|
30
|
+
│ Voyage AI embedding (voyage-3-lite) │
|
|
31
|
+
└────┬──────────────────────────────────┘
|
|
32
|
+
│
|
|
33
|
+
┌────▼─────────────────────────────────┐
|
|
34
|
+
│ LanceDB │
|
|
35
|
+
│ conversations_hot / cold │
|
|
36
|
+
│ structured_docs │
|
|
37
|
+
│ digests ← Codex CLI digest job │
|
|
38
|
+
└────┬─────────────────────────────────┘
|
|
39
|
+
│
|
|
40
|
+
┌────▼──────────────────────────┐
|
|
41
|
+
│ MCP server (life_*) │
|
|
42
|
+
│ HTTP daemon on 127.0.0.1:3577 │
|
|
43
|
+
└───────────────────────────────┘
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Models & runtimes in use
|
|
47
|
+
|
|
48
|
+
| Stage | Runtime | Model |
|
|
49
|
+
|---|---|---|
|
|
50
|
+
| Triage (decide save/review/discard) | local `codex` CLI | CLI default |
|
|
51
|
+
| Metadata extraction (web/ingest path) | local `codex` CLI | CLI default |
|
|
52
|
+
| Digest summarization (compact job) | local `codex` CLI | CLI default |
|
|
53
|
+
| Embeddings | Voyage AI (cloud) | `voyage-3-lite` |
|
|
54
|
+
| Local-LLM override (optional) | Ollama at `localhost:11434` | configurable (`metadata_model`, `digest_model`) |
|
|
55
|
+
|
|
56
|
+
**Cloud mode (default)** — set `local_generation.enabled: false` in `config.json`. All LLM calls go through the operator's already-authenticated `codex` CLI. No Anthropic / OpenAI API key required.
|
|
57
|
+
|
|
58
|
+
**Local-LLM override** — set `local_generation.enabled: true`. Metadata + digest go through the configured Ollama models. Triage still uses Codex CLI.
|
|
59
|
+
|
|
60
|
+
The two modes are mutually exclusive — exactly one runtime owns LLM calls at a time.
|
|
61
|
+
|
|
62
|
+
## CLI vs API surface
|
|
63
|
+
|
|
64
|
+
**Local-only (no network)**:
|
|
65
|
+
- `codex` CLI subprocess (every triage / metadata / digest call).
|
|
66
|
+
- Filesystem watchers for project sources.
|
|
67
|
+
- LanceDB on disk under `data/lancedb/`.
|
|
68
|
+
- Daemon HTTP listens on `127.0.0.1:3577` (loopback only).
|
|
69
|
+
- MCP server speaks JSON-RPC over stdio.
|
|
70
|
+
|
|
71
|
+
**Network**:
|
|
72
|
+
- Voyage embedding API (`api.voyageai.com`) — only consumer.
|
|
73
|
+
|
|
74
|
+
**Provider classes preserved but not in the live default path** (kept for explicit batch/historical use): `OpenAITriageProvider`, `OpenAIMetadataExtractor`, `AnthropicDigestSummarizer`, `CliMetadataExtractor` (legacy Claude CLI subprocess).
|
|
75
|
+
|
|
76
|
+
## Main commands
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
# Live capture (Claude Code + Codex CLI session files)
|
|
80
|
+
rift capture # both sources
|
|
81
|
+
rift capture --source codex_cli # one source
|
|
82
|
+
rift capture --dry-run # preflight + triage, no saves
|
|
83
|
+
|
|
84
|
+
# Status + telemetry
|
|
85
|
+
rift status # daemon briefing + auto-capture summary
|
|
86
|
+
rift stats # table counts, source coverage
|
|
87
|
+
|
|
88
|
+
# Search
|
|
89
|
+
rift search "..."
|
|
90
|
+
|
|
91
|
+
# Daemon (managed by launchd)
|
|
92
|
+
launchctl kickstart -k gui/$UID/com.rift.daemon
|
|
93
|
+
launchctl print gui/$UID/com.rift.daemon
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
The macOS menu bar (SwiftBar plugin at `operator/swiftbar/rift.10s.sh`) shows daemon health and the live MCP-usage telemetry block (today / this week / this month / all-time call counts + tokens-saved estimate) at the top of its dropdown.
|
|
97
|
+
|
|
98
|
+
## Pointers
|
|
99
|
+
|
|
100
|
+
- [`TODO.md`](./TODO.md) — current/next/later tracker (updated end of every session).
|
|
101
|
+
- [`PROJECT_STATE.md`](./PROJECT_STATE.md) — what's currently in flight.
|
|
102
|
+
- [`CLAUDE.md`](./CLAUDE.md) — instructions for AI agents working in this repo.
|
|
103
|
+
- [`docs/`](./docs/) — design docs (current system, API/MCP spec, capture contract, intelligence direction, etc.).
|
|
104
|
+
|
|
105
|
+
## Conventions
|
|
106
|
+
|
|
107
|
+
- TypeScript strict; `pnpm check` (or `npm run check`) before ship.
|
|
108
|
+
- Vitest. Pretest generates fixtures.
|
|
109
|
+
- Local-first, file-native storage under `data/`, `jobs/`, `reports/`.
|
|
110
|
+
- Auto-capture triage depends on a working, authenticated `codex` CLI. Preflight failures here mean CLI auth/install/runtime issues (`codex login`, CLI upgrade/reinstall, or launchd PATH), not a missing `rift.openai` Keychain secret — that path was retired.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Low-level Keychain operations.
|
|
3
|
+
*
|
|
4
|
+
* Abstracted as an interface so rotation.ts can be tested with an
|
|
5
|
+
* in-memory implementation that never touches the real Keychain.
|
|
6
|
+
*/
|
|
7
|
+
export interface KeychainOps {
|
|
8
|
+
read(version: number): Promise<string | null>;
|
|
9
|
+
write(version: number, token: string): Promise<void>;
|
|
10
|
+
delete(version: number): Promise<void>;
|
|
11
|
+
findLatestVersion(): Promise<number>;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Production Keychain backend using the macOS `security` CLI.
|
|
15
|
+
*
|
|
16
|
+
* Token versioning: each version is stored as a separate generic-password
|
|
17
|
+
* entry. A metadata entry (`AUTH_TOKEN_CURRENT_VERSION`) tracks the
|
|
18
|
+
* latest version number so we avoid scanning the entire keychain.
|
|
19
|
+
*
|
|
20
|
+
* Error policy: only "item not found" (exit 44) is swallowed where
|
|
21
|
+
* appropriate. All other errors (locked keychain, permission denied,
|
|
22
|
+
* missing binary) propagate as thrown exceptions.
|
|
23
|
+
*/
|
|
24
|
+
export declare const macKeychain: KeychainOps;
|
|
25
|
+
//# sourceMappingURL=keychain.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keychain.d.ts","sourceRoot":"","sources":["../../../src/auth/keychain.ts"],"names":[],"mappings":"AAaA;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC9C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;CACtC;AAgBD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,WAAW,EAAE,WA0EzB,CAAC"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { promisify } from "node:util";
|
|
3
|
+
const execFileAsync = promisify(execFile);
|
|
4
|
+
const SERVICE = "com.getrift.daemon";
|
|
5
|
+
/**
|
|
6
|
+
* macOS `security` CLI exit code for errSecItemNotFound.
|
|
7
|
+
* This is the only error we treat as "success with empty result".
|
|
8
|
+
* All other non-zero exits are real failures that must propagate.
|
|
9
|
+
*/
|
|
10
|
+
const ERR_SEC_ITEM_NOT_FOUND = 44;
|
|
11
|
+
function accountName(version) {
|
|
12
|
+
return `AUTH_TOKEN_v${version}`;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Returns true only for the specific "item not found" error from
|
|
16
|
+
* the macOS `security` CLI. All other errors are real failures.
|
|
17
|
+
*/
|
|
18
|
+
function isItemNotFound(err) {
|
|
19
|
+
if (!(err instanceof Error))
|
|
20
|
+
return false;
|
|
21
|
+
const execErr = err;
|
|
22
|
+
return execErr.code === ERR_SEC_ITEM_NOT_FOUND;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Production Keychain backend using the macOS `security` CLI.
|
|
26
|
+
*
|
|
27
|
+
* Token versioning: each version is stored as a separate generic-password
|
|
28
|
+
* entry. A metadata entry (`AUTH_TOKEN_CURRENT_VERSION`) tracks the
|
|
29
|
+
* latest version number so we avoid scanning the entire keychain.
|
|
30
|
+
*
|
|
31
|
+
* Error policy: only "item not found" (exit 44) is swallowed where
|
|
32
|
+
* appropriate. All other errors (locked keychain, permission denied,
|
|
33
|
+
* missing binary) propagate as thrown exceptions.
|
|
34
|
+
*/
|
|
35
|
+
export const macKeychain = {
|
|
36
|
+
async read(version) {
|
|
37
|
+
try {
|
|
38
|
+
const { stdout } = await execFileAsync("security", [
|
|
39
|
+
"find-generic-password",
|
|
40
|
+
"-a",
|
|
41
|
+
accountName(version),
|
|
42
|
+
"-s",
|
|
43
|
+
SERVICE,
|
|
44
|
+
"-w",
|
|
45
|
+
]);
|
|
46
|
+
return stdout.trim() || null;
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
if (isItemNotFound(err))
|
|
50
|
+
return null;
|
|
51
|
+
throw err;
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
async write(version, token) {
|
|
55
|
+
await execFileAsync("security", [
|
|
56
|
+
"add-generic-password",
|
|
57
|
+
"-a",
|
|
58
|
+
accountName(version),
|
|
59
|
+
"-s",
|
|
60
|
+
SERVICE,
|
|
61
|
+
"-w",
|
|
62
|
+
token,
|
|
63
|
+
"-U",
|
|
64
|
+
]);
|
|
65
|
+
// Update version counter
|
|
66
|
+
await execFileAsync("security", [
|
|
67
|
+
"add-generic-password",
|
|
68
|
+
"-a",
|
|
69
|
+
"AUTH_TOKEN_CURRENT_VERSION",
|
|
70
|
+
"-s",
|
|
71
|
+
SERVICE,
|
|
72
|
+
"-w",
|
|
73
|
+
String(version),
|
|
74
|
+
"-U",
|
|
75
|
+
]);
|
|
76
|
+
},
|
|
77
|
+
async delete(version) {
|
|
78
|
+
try {
|
|
79
|
+
await execFileAsync("security", [
|
|
80
|
+
"delete-generic-password",
|
|
81
|
+
"-a",
|
|
82
|
+
accountName(version),
|
|
83
|
+
"-s",
|
|
84
|
+
SERVICE,
|
|
85
|
+
]);
|
|
86
|
+
}
|
|
87
|
+
catch (err) {
|
|
88
|
+
if (isItemNotFound(err))
|
|
89
|
+
return; // Already gone — fine.
|
|
90
|
+
throw err;
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
async findLatestVersion() {
|
|
94
|
+
try {
|
|
95
|
+
const { stdout } = await execFileAsync("security", [
|
|
96
|
+
"find-generic-password",
|
|
97
|
+
"-a",
|
|
98
|
+
"AUTH_TOKEN_CURRENT_VERSION",
|
|
99
|
+
"-s",
|
|
100
|
+
SERVICE,
|
|
101
|
+
"-w",
|
|
102
|
+
]);
|
|
103
|
+
const version = Number(stdout.trim());
|
|
104
|
+
return Number.isNaN(version) ? 0 : version;
|
|
105
|
+
}
|
|
106
|
+
catch (err) {
|
|
107
|
+
if (isItemNotFound(err))
|
|
108
|
+
return 0; // No tokens issued yet.
|
|
109
|
+
throw err;
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
//# sourceMappingURL=keychain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keychain.js","sourceRoot":"","sources":["../../../src/auth/keychain.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAC1C,MAAM,OAAO,GAAG,oBAAoB,CAAC;AAErC;;;;GAIG;AACH,MAAM,sBAAsB,GAAG,EAAE,CAAC;AAelC,SAAS,WAAW,CAAC,OAAe;IAClC,OAAO,eAAe,OAAO,EAAE,CAAC;AAClC,CAAC;AAED;;;GAGG;AACH,SAAS,cAAc,CAAC,GAAY;IAClC,IAAI,CAAC,CAAC,GAAG,YAAY,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC1C,MAAM,OAAO,GAAG,GAAwB,CAAC;IACzC,OAAO,OAAO,CAAC,IAAI,KAAK,sBAAsB,CAAC;AACjD,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,WAAW,GAAgB;IACtC,KAAK,CAAC,IAAI,CAAC,OAAO;QAChB,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CAAC,UAAU,EAAE;gBACjD,uBAAuB;gBACvB,IAAI;gBACJ,WAAW,CAAC,OAAO,CAAC;gBACpB,IAAI;gBACJ,OAAO;gBACP,IAAI;aACL,CAAC,CAAC;YACH,OAAO,MAAM,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC;QAC/B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,cAAc,CAAC,GAAG,CAAC;gBAAE,OAAO,IAAI,CAAC;YACrC,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK;QACxB,MAAM,aAAa,CAAC,UAAU,EAAE;YAC9B,sBAAsB;YACtB,IAAI;YACJ,WAAW,CAAC,OAAO,CAAC;YACpB,IAAI;YACJ,OAAO;YACP,IAAI;YACJ,KAAK;YACL,IAAI;SACL,CAAC,CAAC;QACH,yBAAyB;QACzB,MAAM,aAAa,CAAC,UAAU,EAAE;YAC9B,sBAAsB;YACtB,IAAI;YACJ,4BAA4B;YAC5B,IAAI;YACJ,OAAO;YACP,IAAI;YACJ,MAAM,CAAC,OAAO,CAAC;YACf,IAAI;SACL,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,OAAO;QAClB,IAAI,CAAC;YACH,MAAM,aAAa,CAAC,UAAU,EAAE;gBAC9B,yBAAyB;gBACzB,IAAI;gBACJ,WAAW,CAAC,OAAO,CAAC;gBACpB,IAAI;gBACJ,OAAO;aACR,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,cAAc,CAAC,GAAG,CAAC;gBAAE,OAAO,CAAC,uBAAuB;YACxD,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;IAED,KAAK,CAAC,iBAAiB;QACrB,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CAAC,UAAU,EAAE;gBACjD,uBAAuB;gBACvB,IAAI;gBACJ,4BAA4B;gBAC5B,IAAI;gBACJ,OAAO;gBACP,IAAI;aACL,CAAC,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;YACtC,OAAO,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;QAC7C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,cAAc,CAAC,GAAG,CAAC;gBAAE,OAAO,CAAC,CAAC,CAAC,wBAAwB;YAC3D,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { FastifyInstance } from "fastify";
|
|
2
|
+
import type { Config } from "../config/schema.js";
|
|
3
|
+
import type { TokenManager } from "./rotation.js";
|
|
4
|
+
import type { RateLimiter } from "./rate-limit.js";
|
|
5
|
+
/**
|
|
6
|
+
* Register the bearer-token auth hook and per-token rate limiter.
|
|
7
|
+
*
|
|
8
|
+
* Auth is skipped for /health, /ready, /version, and /stats/mcp-usage
|
|
9
|
+
* (unauthenticated probes used by health/operator surfaces).
|
|
10
|
+
*
|
|
11
|
+
* Test-only bypass: when `NODE_ENV=test` AND `config.auth.test_token`
|
|
12
|
+
* is set AND the bearer matches it, the request is allowed without
|
|
13
|
+
* consulting the TokenManager. This is the ONLY way to bypass Keychain
|
|
14
|
+
* in tests — it is never active in production config.
|
|
15
|
+
*
|
|
16
|
+
* Rate limiting is skipped for `DELETE /auth/token` so a leaked token
|
|
17
|
+
* that has hit the rate-limit cap can still revoke itself.
|
|
18
|
+
*/
|
|
19
|
+
export declare function registerAuth(server: FastifyInstance, config: Config, tokenManager: TokenManager | null, rateLimiter: RateLimiter): void;
|
|
20
|
+
//# sourceMappingURL=middleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../../src/auth/middleware.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAYnD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,eAAe,EACvB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,YAAY,GAAG,IAAI,EACjC,WAAW,EAAE,WAAW,GACvB,IAAI,CA8BN"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
const EXEMPT_ROUTES = new Set([
|
|
2
|
+
"/health",
|
|
3
|
+
"/ready",
|
|
4
|
+
"/version",
|
|
5
|
+
// SwiftBar polls this on every tick. Response carries only call counts
|
|
6
|
+
// and tool names — no user content — so unauthenticated is safe and
|
|
7
|
+
// matches the /health, /version posture.
|
|
8
|
+
"/stats/mcp-usage",
|
|
9
|
+
]);
|
|
10
|
+
/**
|
|
11
|
+
* Register the bearer-token auth hook and per-token rate limiter.
|
|
12
|
+
*
|
|
13
|
+
* Auth is skipped for /health, /ready, /version, and /stats/mcp-usage
|
|
14
|
+
* (unauthenticated probes used by health/operator surfaces).
|
|
15
|
+
*
|
|
16
|
+
* Test-only bypass: when `NODE_ENV=test` AND `config.auth.test_token`
|
|
17
|
+
* is set AND the bearer matches it, the request is allowed without
|
|
18
|
+
* consulting the TokenManager. This is the ONLY way to bypass Keychain
|
|
19
|
+
* in tests — it is never active in production config.
|
|
20
|
+
*
|
|
21
|
+
* Rate limiting is skipped for `DELETE /auth/token` so a leaked token
|
|
22
|
+
* that has hit the rate-limit cap can still revoke itself.
|
|
23
|
+
*/
|
|
24
|
+
export function registerAuth(server, config, tokenManager, rateLimiter) {
|
|
25
|
+
server.addHook("onRequest", async (request, reply) => {
|
|
26
|
+
const path = request.url.split("?")[0];
|
|
27
|
+
if (EXEMPT_ROUTES.has(path))
|
|
28
|
+
return;
|
|
29
|
+
const authHeader = request.headers.authorization;
|
|
30
|
+
if (!authHeader || !authHeader.startsWith("Bearer ")) {
|
|
31
|
+
return reply.code(401).send({ error: "missing_token" });
|
|
32
|
+
}
|
|
33
|
+
const token = authHeader.slice(7);
|
|
34
|
+
// Test-only bypass — double-gated.
|
|
35
|
+
const isTestBypass = process.env.NODE_ENV === "test" &&
|
|
36
|
+
config.auth.test_token !== undefined &&
|
|
37
|
+
token === config.auth.test_token;
|
|
38
|
+
if (!isTestBypass && (tokenManager === null || !tokenManager.validate(token))) {
|
|
39
|
+
return reply.code(401).send({ error: "invalid_token" });
|
|
40
|
+
}
|
|
41
|
+
// Rate limit — but exempt DELETE /auth/token so a leaked token
|
|
42
|
+
// that has already hit the cap can still revoke itself.
|
|
43
|
+
const isRateLimitExempt = path === "/auth/token" && request.method === "DELETE";
|
|
44
|
+
if (!isRateLimitExempt && !rateLimiter.check(token)) {
|
|
45
|
+
return reply.code(429).send({ error: "rate_limit_exceeded" });
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=middleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../../src/auth/middleware.ts"],"names":[],"mappings":"AAKA,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC;IAC5B,SAAS;IACT,QAAQ;IACR,UAAU;IACV,uEAAuE;IACvE,oEAAoE;IACpE,yCAAyC;IACzC,kBAAkB;CACnB,CAAC,CAAC;AAEH;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,YAAY,CAC1B,MAAuB,EACvB,MAAc,EACd,YAAiC,EACjC,WAAwB;IAExB,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACnD,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACvC,IAAI,aAAa,CAAC,GAAG,CAAC,IAAK,CAAC;YAAE,OAAO;QAErC,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC;QACjD,IAAI,CAAC,UAAU,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YACrD,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC,CAAC;QAC1D,CAAC;QAED,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAElC,mCAAmC;QACnC,MAAM,YAAY,GAChB,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,MAAM;YAC/B,MAAM,CAAC,IAAI,CAAC,UAAU,KAAK,SAAS;YACpC,KAAK,KAAK,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC;QAEnC,IAAI,CAAC,YAAY,IAAI,CAAC,YAAY,KAAK,IAAI,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;YAC9E,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC,CAAC;QAC1D,CAAC;QAED,+DAA+D;QAC/D,wDAAwD;QACxD,MAAM,iBAAiB,GACrB,IAAI,KAAK,aAAa,IAAI,OAAO,CAAC,MAAM,KAAK,QAAQ,CAAC;QACxD,IAAI,CAAC,iBAAiB,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;YACpD,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,qBAAqB,EAAE,CAAC,CAAC;QAChE,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-token sliding-window rate limiter.
|
|
3
|
+
*
|
|
4
|
+
* Tracks request timestamps per token. On each call to `check()`,
|
|
5
|
+
* expired entries are pruned and the count is compared to the limit.
|
|
6
|
+
*/
|
|
7
|
+
export declare class RateLimiter {
|
|
8
|
+
private windowMs;
|
|
9
|
+
private maxRequests;
|
|
10
|
+
private windows;
|
|
11
|
+
constructor(windowMs: number, maxRequests: number);
|
|
12
|
+
/** Returns `true` if the request is allowed, `false` if rate-limited. */
|
|
13
|
+
check(token: string): boolean;
|
|
14
|
+
reset(): void;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=rate-limit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../../src/auth/rate-limit.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,qBAAa,WAAW;IAIpB,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,WAAW;IAJrB,OAAO,CAAC,OAAO,CAA+B;gBAGpC,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM;IAG7B,yEAAyE;IACzE,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAuB7B,KAAK,IAAI,IAAI;CAGd"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-token sliding-window rate limiter.
|
|
3
|
+
*
|
|
4
|
+
* Tracks request timestamps per token. On each call to `check()`,
|
|
5
|
+
* expired entries are pruned and the count is compared to the limit.
|
|
6
|
+
*/
|
|
7
|
+
export class RateLimiter {
|
|
8
|
+
windowMs;
|
|
9
|
+
maxRequests;
|
|
10
|
+
windows = new Map();
|
|
11
|
+
constructor(windowMs, maxRequests) {
|
|
12
|
+
this.windowMs = windowMs;
|
|
13
|
+
this.maxRequests = maxRequests;
|
|
14
|
+
}
|
|
15
|
+
/** Returns `true` if the request is allowed, `false` if rate-limited. */
|
|
16
|
+
check(token) {
|
|
17
|
+
const now = Date.now();
|
|
18
|
+
const cutoff = now - this.windowMs;
|
|
19
|
+
let timestamps = this.windows.get(token);
|
|
20
|
+
if (!timestamps) {
|
|
21
|
+
timestamps = [];
|
|
22
|
+
this.windows.set(token, timestamps);
|
|
23
|
+
}
|
|
24
|
+
// Prune expired entries from the front.
|
|
25
|
+
while (timestamps.length > 0 && timestamps[0] < cutoff) {
|
|
26
|
+
timestamps.shift();
|
|
27
|
+
}
|
|
28
|
+
if (timestamps.length >= this.maxRequests) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
timestamps.push(now);
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
reset() {
|
|
35
|
+
this.windows.clear();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=rate-limit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limit.js","sourceRoot":"","sources":["../../../src/auth/rate-limit.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,OAAO,WAAW;IAIZ;IACA;IAJF,OAAO,GAAG,IAAI,GAAG,EAAoB,CAAC;IAE9C,YACU,QAAgB,EAChB,WAAmB;QADnB,aAAQ,GAAR,QAAQ,CAAQ;QAChB,gBAAW,GAAX,WAAW,CAAQ;IAC1B,CAAC;IAEJ,yEAAyE;IACzE,KAAK,CAAC,KAAa;QACjB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC;QAEnC,IAAI,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACzC,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,UAAU,GAAG,EAAE,CAAC;YAChB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;QACtC,CAAC;QAED,wCAAwC;QACxC,OAAO,UAAU,CAAC,MAAM,GAAG,CAAC,IAAI,UAAU,CAAC,CAAC,CAAE,GAAG,MAAM,EAAE,CAAC;YACxD,UAAU,CAAC,KAAK,EAAE,CAAC;QACrB,CAAC;QAED,IAAI,UAAU,CAAC,MAAM,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YAC1C,OAAO,KAAK,CAAC;QACf,CAAC;QAED,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK;QACH,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;CACF"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { KeychainOps } from "./keychain.js";
|
|
2
|
+
/**
|
|
3
|
+
* In-memory token state machine backed by a KeychainOps provider.
|
|
4
|
+
*
|
|
5
|
+
* Invariants:
|
|
6
|
+
* - At most 2 tokens are valid at once: current + grace (previous).
|
|
7
|
+
* - Grace expires after `gracePeriodMs` (default 60 s).
|
|
8
|
+
* - `load()` restores only the current version — no grace for old
|
|
9
|
+
* tokens on daemon restart (PRD: timer does not survive restart).
|
|
10
|
+
* - `revokeAll()` immediately invalidates everything and deletes
|
|
11
|
+
* ALL Keychain entries (versions 1..current) so revoked tokens
|
|
12
|
+
* don't resurface on restart and old secrets don't accumulate.
|
|
13
|
+
* - `issue()` eagerly deletes any superseded grace version from
|
|
14
|
+
* Keychain before setting up new grace, so rapid rotation
|
|
15
|
+
* (v1→v2→v3 within one grace window) never leaves old secrets.
|
|
16
|
+
* The latest grace version is cleaned up when its timer fires.
|
|
17
|
+
*/
|
|
18
|
+
export declare class TokenManager {
|
|
19
|
+
private keychain;
|
|
20
|
+
private gracePeriodMs;
|
|
21
|
+
private currentVersion;
|
|
22
|
+
private currentToken;
|
|
23
|
+
private graceToken;
|
|
24
|
+
private graceVersion;
|
|
25
|
+
private graceTimer;
|
|
26
|
+
constructor(keychain: KeychainOps, gracePeriodMs?: number);
|
|
27
|
+
/**
|
|
28
|
+
* Cold-load: restore the current token from keychain with no grace.
|
|
29
|
+
* Used at daemon startup — PRD: grace timer does not survive restart.
|
|
30
|
+
*/
|
|
31
|
+
load(): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* Hot-reload: pick up a new token from keychain (e.g. after CLI
|
|
34
|
+
* issues a token and sends SIGHUP).
|
|
35
|
+
*
|
|
36
|
+
* When `noGrace` is false (default), the old token enters a 60 s
|
|
37
|
+
* grace window. When `noGrace` is true, the old token is immediately
|
|
38
|
+
* invalidated and its Keychain entry deleted — used by `token issue`
|
|
39
|
+
* to enforce single-active-credential semantics (PRD: "makes it the
|
|
40
|
+
* sole active token").
|
|
41
|
+
*
|
|
42
|
+
* If the version hasn't changed, just refreshes the current value.
|
|
43
|
+
*/
|
|
44
|
+
reload(opts?: {
|
|
45
|
+
noGrace?: boolean;
|
|
46
|
+
}): Promise<void>;
|
|
47
|
+
/** Check if a token is currently valid (current or within grace). */
|
|
48
|
+
validate(token: string): boolean;
|
|
49
|
+
/** Issue a new token. Returns the new version number. */
|
|
50
|
+
issue(newToken: string): Promise<number>;
|
|
51
|
+
/**
|
|
52
|
+
* Immediately revoke all tokens. No grace period.
|
|
53
|
+
*
|
|
54
|
+
* Clears in-memory state first (immediate effect for the running
|
|
55
|
+
* daemon), then deletes ALL Keychain entries (versions 1..current)
|
|
56
|
+
* so revoked tokens cannot resurface on restart.
|
|
57
|
+
*
|
|
58
|
+
* Keychain delete errors propagate — the caller (route handler)
|
|
59
|
+
* should surface them so the operator knows cleanup may be incomplete.
|
|
60
|
+
*/
|
|
61
|
+
revokeAll(): Promise<void>;
|
|
62
|
+
/** Clean up timers. Call on daemon shutdown. */
|
|
63
|
+
shutdown(): void;
|
|
64
|
+
private clearGraceTimer;
|
|
65
|
+
private clearGrace;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=rotation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rotation.d.ts","sourceRoot":"","sources":["../../../src/auth/rotation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,YAAY;IAQrB,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,aAAa;IARvB,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,UAAU,CAA8C;gBAGtD,QAAQ,EAAE,WAAW,EACrB,aAAa,SAAS;IAGhC;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAS3B;;;;;;;;;;;OAWG;IACG,MAAM,CAAC,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAoEzD,qEAAqE;IACrE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAMhC,yDAAyD;IACnD,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IA6C9C;;;;;;;;;OASG;IACG,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAWhC,gDAAgD;IAChD,QAAQ,IAAI,IAAI;IAIhB,OAAO,CAAC,eAAe;IAOvB,OAAO,CAAC,UAAU;CAKnB"}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory token state machine backed by a KeychainOps provider.
|
|
3
|
+
*
|
|
4
|
+
* Invariants:
|
|
5
|
+
* - At most 2 tokens are valid at once: current + grace (previous).
|
|
6
|
+
* - Grace expires after `gracePeriodMs` (default 60 s).
|
|
7
|
+
* - `load()` restores only the current version — no grace for old
|
|
8
|
+
* tokens on daemon restart (PRD: timer does not survive restart).
|
|
9
|
+
* - `revokeAll()` immediately invalidates everything and deletes
|
|
10
|
+
* ALL Keychain entries (versions 1..current) so revoked tokens
|
|
11
|
+
* don't resurface on restart and old secrets don't accumulate.
|
|
12
|
+
* - `issue()` eagerly deletes any superseded grace version from
|
|
13
|
+
* Keychain before setting up new grace, so rapid rotation
|
|
14
|
+
* (v1→v2→v3 within one grace window) never leaves old secrets.
|
|
15
|
+
* The latest grace version is cleaned up when its timer fires.
|
|
16
|
+
*/
|
|
17
|
+
export class TokenManager {
|
|
18
|
+
keychain;
|
|
19
|
+
gracePeriodMs;
|
|
20
|
+
currentVersion = 0;
|
|
21
|
+
currentToken = null;
|
|
22
|
+
graceToken = null;
|
|
23
|
+
graceVersion = 0;
|
|
24
|
+
graceTimer = null;
|
|
25
|
+
constructor(keychain, gracePeriodMs = 60_000) {
|
|
26
|
+
this.keychain = keychain;
|
|
27
|
+
this.gracePeriodMs = gracePeriodMs;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Cold-load: restore the current token from keychain with no grace.
|
|
31
|
+
* Used at daemon startup — PRD: grace timer does not survive restart.
|
|
32
|
+
*/
|
|
33
|
+
async load() {
|
|
34
|
+
this.clearGrace();
|
|
35
|
+
this.currentVersion = await this.keychain.findLatestVersion();
|
|
36
|
+
this.currentToken =
|
|
37
|
+
this.currentVersion > 0
|
|
38
|
+
? await this.keychain.read(this.currentVersion)
|
|
39
|
+
: null;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Hot-reload: pick up a new token from keychain (e.g. after CLI
|
|
43
|
+
* issues a token and sends SIGHUP).
|
|
44
|
+
*
|
|
45
|
+
* When `noGrace` is false (default), the old token enters a 60 s
|
|
46
|
+
* grace window. When `noGrace` is true, the old token is immediately
|
|
47
|
+
* invalidated and its Keychain entry deleted — used by `token issue`
|
|
48
|
+
* to enforce single-active-credential semantics (PRD: "makes it the
|
|
49
|
+
* sole active token").
|
|
50
|
+
*
|
|
51
|
+
* If the version hasn't changed, just refreshes the current value.
|
|
52
|
+
*/
|
|
53
|
+
async reload(opts) {
|
|
54
|
+
const noGrace = opts?.noGrace ?? false;
|
|
55
|
+
const prevToken = this.currentToken;
|
|
56
|
+
const prevVersion = this.currentVersion;
|
|
57
|
+
const latestVersion = await this.keychain.findLatestVersion();
|
|
58
|
+
const latestToken = latestVersion > 0 ? await this.keychain.read(latestVersion) : null;
|
|
59
|
+
if (latestVersion === prevVersion) {
|
|
60
|
+
// Same version — just refresh the value (covers manual Keychain edit).
|
|
61
|
+
this.currentToken = latestToken;
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
// Version changed — handle the outgoing token.
|
|
65
|
+
if (prevToken !== null) {
|
|
66
|
+
// Clean up any existing grace entry before replacing it.
|
|
67
|
+
if (this.graceVersion > 0) {
|
|
68
|
+
try {
|
|
69
|
+
await this.keychain.delete(this.graceVersion);
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
process.stderr.write(`Warning: failed to clean up token v${this.graceVersion} from Keychain: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
this.clearGraceTimer();
|
|
76
|
+
if (noGrace) {
|
|
77
|
+
// Immediate invalidation: no grace window, delete old entry now.
|
|
78
|
+
this.graceToken = null;
|
|
79
|
+
this.graceVersion = 0;
|
|
80
|
+
if (prevVersion > 0) {
|
|
81
|
+
try {
|
|
82
|
+
await this.keychain.delete(prevVersion);
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
process.stderr.write(`Warning: failed to clean up token v${prevVersion} from Keychain: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
// Grace period: old token valid for gracePeriodMs.
|
|
91
|
+
this.graceToken = prevToken;
|
|
92
|
+
this.graceVersion = prevVersion;
|
|
93
|
+
const vToDelete = prevVersion;
|
|
94
|
+
this.graceTimer = setTimeout(() => {
|
|
95
|
+
this.graceToken = null;
|
|
96
|
+
this.graceTimer = null;
|
|
97
|
+
this.graceVersion = 0;
|
|
98
|
+
if (vToDelete > 0) {
|
|
99
|
+
this.keychain.delete(vToDelete).catch((err) => {
|
|
100
|
+
process.stderr.write(`Warning: failed to clean up token v${vToDelete} from Keychain: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}, this.gracePeriodMs);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
this.currentVersion = latestVersion;
|
|
107
|
+
this.currentToken = latestToken;
|
|
108
|
+
}
|
|
109
|
+
/** Check if a token is currently valid (current or within grace). */
|
|
110
|
+
validate(token) {
|
|
111
|
+
if (this.currentToken !== null && token === this.currentToken)
|
|
112
|
+
return true;
|
|
113
|
+
if (this.graceToken !== null && token === this.graceToken)
|
|
114
|
+
return true;
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
/** Issue a new token. Returns the new version number. */
|
|
118
|
+
async issue(newToken) {
|
|
119
|
+
const previousVersion = this.currentVersion;
|
|
120
|
+
const newVersion = this.currentVersion + 1;
|
|
121
|
+
await this.keychain.write(newVersion, newToken);
|
|
122
|
+
// Start grace period for the outgoing token.
|
|
123
|
+
if (this.currentToken !== null) {
|
|
124
|
+
// If there's an existing grace token being superseded by this
|
|
125
|
+
// rotation, eagerly delete its Keychain entry now — it is no
|
|
126
|
+
// longer valid in memory and must not linger in the vault.
|
|
127
|
+
if (this.graceVersion > 0) {
|
|
128
|
+
try {
|
|
129
|
+
await this.keychain.delete(this.graceVersion);
|
|
130
|
+
}
|
|
131
|
+
catch (err) {
|
|
132
|
+
process.stderr.write(`Warning: failed to clean up token v${this.graceVersion} from Keychain: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
this.clearGraceTimer();
|
|
136
|
+
this.graceToken = this.currentToken;
|
|
137
|
+
this.graceVersion = previousVersion;
|
|
138
|
+
// Timer cleans up THIS grace token's Keychain entry when it expires.
|
|
139
|
+
const vToDelete = previousVersion;
|
|
140
|
+
this.graceTimer = setTimeout(() => {
|
|
141
|
+
this.graceToken = null;
|
|
142
|
+
this.graceTimer = null;
|
|
143
|
+
this.graceVersion = 0;
|
|
144
|
+
if (vToDelete > 0) {
|
|
145
|
+
this.keychain.delete(vToDelete).catch((err) => {
|
|
146
|
+
process.stderr.write(`Warning: failed to clean up token v${vToDelete} from Keychain: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
}, this.gracePeriodMs);
|
|
150
|
+
}
|
|
151
|
+
this.currentVersion = newVersion;
|
|
152
|
+
this.currentToken = newToken;
|
|
153
|
+
return newVersion;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Immediately revoke all tokens. No grace period.
|
|
157
|
+
*
|
|
158
|
+
* Clears in-memory state first (immediate effect for the running
|
|
159
|
+
* daemon), then deletes ALL Keychain entries (versions 1..current)
|
|
160
|
+
* so revoked tokens cannot resurface on restart.
|
|
161
|
+
*
|
|
162
|
+
* Keychain delete errors propagate — the caller (route handler)
|
|
163
|
+
* should surface them so the operator knows cleanup may be incomplete.
|
|
164
|
+
*/
|
|
165
|
+
async revokeAll() {
|
|
166
|
+
this.clearGrace();
|
|
167
|
+
this.currentToken = null;
|
|
168
|
+
const deletions = [];
|
|
169
|
+
for (let v = 1; v <= this.currentVersion; v++) {
|
|
170
|
+
deletions.push(this.keychain.delete(v));
|
|
171
|
+
}
|
|
172
|
+
await Promise.all(deletions);
|
|
173
|
+
}
|
|
174
|
+
/** Clean up timers. Call on daemon shutdown. */
|
|
175
|
+
shutdown() {
|
|
176
|
+
this.clearGrace();
|
|
177
|
+
}
|
|
178
|
+
clearGraceTimer() {
|
|
179
|
+
if (this.graceTimer !== null) {
|
|
180
|
+
clearTimeout(this.graceTimer);
|
|
181
|
+
this.graceTimer = null;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
clearGrace() {
|
|
185
|
+
this.clearGraceTimer();
|
|
186
|
+
this.graceToken = null;
|
|
187
|
+
this.graceVersion = 0;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=rotation.js.map
|