superlocalmemory 2.8.6 → 3.0.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/LICENSE +9 -1
- package/NOTICE +63 -0
- package/README.md +165 -480
- package/bin/slm +17 -449
- package/bin/slm-npm +1 -1
- package/conftest.py +5 -0
- package/docs/api-reference.md +284 -0
- package/docs/architecture.md +149 -0
- package/docs/auto-memory.md +150 -0
- package/docs/cli-reference.md +276 -0
- package/docs/compliance.md +191 -0
- package/docs/configuration.md +182 -0
- package/docs/getting-started.md +102 -0
- package/docs/ide-setup.md +261 -0
- package/docs/mcp-tools.md +220 -0
- package/docs/migration-from-v2.md +170 -0
- package/docs/profiles.md +173 -0
- package/docs/troubleshooting.md +310 -0
- package/{configs → ide/configs}/antigravity-mcp.json +3 -3
- package/ide/configs/chatgpt-desktop-mcp.json +16 -0
- package/{configs → ide/configs}/claude-desktop-mcp.json +3 -3
- package/{configs → ide/configs}/codex-mcp.toml +4 -4
- package/{configs → ide/configs}/continue-mcp.yaml +4 -3
- package/{configs → ide/configs}/continue-skills.yaml +6 -6
- package/ide/configs/cursor-mcp.json +15 -0
- package/{configs → ide/configs}/gemini-cli-mcp.json +2 -2
- package/{configs → ide/configs}/jetbrains-mcp.json +2 -2
- package/{configs → ide/configs}/opencode-mcp.json +2 -2
- package/{configs → ide/configs}/perplexity-mcp.json +2 -2
- package/{configs → ide/configs}/vscode-copilot-mcp.json +2 -2
- package/{configs → ide/configs}/windsurf-mcp.json +3 -3
- package/{configs → ide/configs}/zed-mcp.json +2 -2
- package/{hooks → ide/hooks}/context-hook.js +9 -20
- package/ide/hooks/memory-list-skill.js +70 -0
- package/ide/hooks/memory-profile-skill.js +101 -0
- package/ide/hooks/memory-recall-skill.js +62 -0
- package/ide/hooks/memory-remember-skill.js +68 -0
- package/ide/hooks/memory-reset-skill.js +160 -0
- package/{hooks → ide/hooks}/post-recall-hook.js +2 -2
- package/ide/integrations/langchain/README.md +106 -0
- package/ide/integrations/langchain/langchain_superlocalmemory/__init__.py +9 -0
- package/ide/integrations/langchain/langchain_superlocalmemory/chat_message_history.py +201 -0
- package/ide/integrations/langchain/pyproject.toml +38 -0
- package/{src/learning → ide/integrations/langchain}/tests/__init__.py +1 -0
- package/ide/integrations/langchain/tests/test_chat_message_history.py +215 -0
- package/ide/integrations/langchain/tests/test_security.py +117 -0
- package/ide/integrations/llamaindex/README.md +81 -0
- package/ide/integrations/llamaindex/llama_index/storage/chat_store/superlocalmemory/__init__.py +9 -0
- package/ide/integrations/llamaindex/llama_index/storage/chat_store/superlocalmemory/base.py +316 -0
- package/ide/integrations/llamaindex/pyproject.toml +43 -0
- package/{src/lifecycle → ide/integrations/llamaindex}/tests/__init__.py +1 -2
- package/ide/integrations/llamaindex/tests/test_chat_store.py +294 -0
- package/ide/integrations/llamaindex/tests/test_security.py +241 -0
- package/{skills → ide/skills}/slm-build-graph/SKILL.md +6 -6
- package/{skills → ide/skills}/slm-list-recent/SKILL.md +5 -5
- package/{skills → ide/skills}/slm-recall/SKILL.md +5 -5
- package/{skills → ide/skills}/slm-remember/SKILL.md +6 -6
- package/{skills → ide/skills}/slm-show-patterns/SKILL.md +7 -7
- package/{skills → ide/skills}/slm-status/SKILL.md +9 -9
- package/{skills → ide/skills}/slm-switch-profile/SKILL.md +9 -9
- package/package.json +13 -22
- package/pyproject.toml +85 -0
- package/scripts/build-dmg.sh +417 -0
- package/scripts/install-skills.ps1 +334 -0
- package/scripts/postinstall.js +2 -2
- package/scripts/start-dashboard.ps1 +52 -0
- package/scripts/start-dashboard.sh +41 -0
- package/scripts/sync-wiki.ps1 +127 -0
- package/scripts/sync-wiki.sh +82 -0
- package/scripts/test-dmg.sh +161 -0
- package/scripts/test-npm-package.ps1 +252 -0
- package/scripts/test-npm-package.sh +207 -0
- package/scripts/verify-install.ps1 +294 -0
- package/scripts/verify-install.sh +266 -0
- package/src/superlocalmemory/__init__.py +0 -0
- package/src/superlocalmemory/attribution/__init__.py +9 -0
- package/src/superlocalmemory/attribution/mathematical_dna.py +235 -0
- package/src/superlocalmemory/attribution/signer.py +153 -0
- package/src/superlocalmemory/attribution/watermark.py +189 -0
- package/src/superlocalmemory/cli/__init__.py +5 -0
- package/src/superlocalmemory/cli/commands.py +245 -0
- package/src/superlocalmemory/cli/main.py +89 -0
- package/src/superlocalmemory/cli/migrate_cmd.py +55 -0
- package/src/superlocalmemory/cli/post_install.py +99 -0
- package/src/superlocalmemory/cli/setup_wizard.py +129 -0
- package/src/superlocalmemory/compliance/__init__.py +0 -0
- package/src/superlocalmemory/compliance/abac.py +204 -0
- package/src/superlocalmemory/compliance/audit.py +314 -0
- package/src/superlocalmemory/compliance/eu_ai_act.py +131 -0
- package/src/superlocalmemory/compliance/gdpr.py +294 -0
- package/src/superlocalmemory/compliance/lifecycle.py +158 -0
- package/src/superlocalmemory/compliance/retention.py +232 -0
- package/src/superlocalmemory/compliance/scheduler.py +148 -0
- package/src/superlocalmemory/core/__init__.py +0 -0
- package/src/superlocalmemory/core/config.py +391 -0
- package/src/superlocalmemory/core/embeddings.py +293 -0
- package/src/superlocalmemory/core/engine.py +701 -0
- package/src/superlocalmemory/core/hooks.py +65 -0
- package/src/superlocalmemory/core/maintenance.py +172 -0
- package/src/superlocalmemory/core/modes.py +140 -0
- package/src/superlocalmemory/core/profiles.py +234 -0
- package/src/superlocalmemory/core/registry.py +117 -0
- package/src/superlocalmemory/dynamics/__init__.py +0 -0
- package/src/superlocalmemory/dynamics/fisher_langevin_coupling.py +223 -0
- package/src/superlocalmemory/encoding/__init__.py +0 -0
- package/src/superlocalmemory/encoding/consolidator.py +485 -0
- package/src/superlocalmemory/encoding/emotional.py +125 -0
- package/src/superlocalmemory/encoding/entity_resolver.py +525 -0
- package/src/superlocalmemory/encoding/entropy_gate.py +104 -0
- package/src/superlocalmemory/encoding/fact_extractor.py +775 -0
- package/src/superlocalmemory/encoding/foresight.py +91 -0
- package/src/superlocalmemory/encoding/graph_builder.py +302 -0
- package/src/superlocalmemory/encoding/observation_builder.py +160 -0
- package/src/superlocalmemory/encoding/scene_builder.py +183 -0
- package/src/superlocalmemory/encoding/signal_inference.py +90 -0
- package/src/superlocalmemory/encoding/temporal_parser.py +426 -0
- package/src/superlocalmemory/encoding/type_router.py +235 -0
- package/src/superlocalmemory/hooks/__init__.py +3 -0
- package/src/superlocalmemory/hooks/auto_capture.py +111 -0
- package/src/superlocalmemory/hooks/auto_recall.py +93 -0
- package/src/superlocalmemory/hooks/ide_connector.py +204 -0
- package/src/superlocalmemory/hooks/rules_engine.py +99 -0
- package/src/superlocalmemory/infra/__init__.py +3 -0
- package/src/superlocalmemory/infra/auth_middleware.py +82 -0
- package/src/superlocalmemory/infra/backup.py +317 -0
- package/src/superlocalmemory/infra/cache_manager.py +267 -0
- package/src/superlocalmemory/infra/event_bus.py +381 -0
- package/src/superlocalmemory/infra/rate_limiter.py +135 -0
- package/src/{webhook_dispatcher.py → superlocalmemory/infra/webhook_dispatcher.py} +104 -101
- package/src/superlocalmemory/learning/__init__.py +0 -0
- package/src/superlocalmemory/learning/adaptive.py +172 -0
- package/src/superlocalmemory/learning/behavioral.py +490 -0
- package/src/superlocalmemory/learning/behavioral_listener.py +94 -0
- package/src/superlocalmemory/learning/bootstrap.py +298 -0
- package/src/superlocalmemory/learning/cross_project.py +399 -0
- package/src/superlocalmemory/learning/database.py +376 -0
- package/src/superlocalmemory/learning/engagement.py +323 -0
- package/src/superlocalmemory/learning/features.py +138 -0
- package/src/superlocalmemory/learning/feedback.py +316 -0
- package/src/superlocalmemory/learning/outcomes.py +255 -0
- package/src/superlocalmemory/learning/project_context.py +366 -0
- package/src/superlocalmemory/learning/ranker.py +155 -0
- package/src/superlocalmemory/learning/source_quality.py +303 -0
- package/src/superlocalmemory/learning/workflows.py +309 -0
- package/src/superlocalmemory/llm/__init__.py +0 -0
- package/src/superlocalmemory/llm/backbone.py +316 -0
- package/src/superlocalmemory/math/__init__.py +0 -0
- package/src/superlocalmemory/math/fisher.py +356 -0
- package/src/superlocalmemory/math/langevin.py +398 -0
- package/src/superlocalmemory/math/sheaf.py +257 -0
- package/src/superlocalmemory/mcp/__init__.py +0 -0
- package/src/superlocalmemory/mcp/resources.py +245 -0
- package/src/superlocalmemory/mcp/server.py +61 -0
- package/src/superlocalmemory/mcp/tools.py +18 -0
- package/src/superlocalmemory/mcp/tools_core.py +305 -0
- package/src/superlocalmemory/mcp/tools_v28.py +223 -0
- package/src/superlocalmemory/mcp/tools_v3.py +286 -0
- package/src/superlocalmemory/retrieval/__init__.py +0 -0
- package/src/superlocalmemory/retrieval/agentic.py +295 -0
- package/src/superlocalmemory/retrieval/ann_index.py +223 -0
- package/src/superlocalmemory/retrieval/bm25_channel.py +185 -0
- package/src/superlocalmemory/retrieval/bridge_discovery.py +170 -0
- package/src/superlocalmemory/retrieval/engine.py +390 -0
- package/src/superlocalmemory/retrieval/entity_channel.py +179 -0
- package/src/superlocalmemory/retrieval/fusion.py +78 -0
- package/src/superlocalmemory/retrieval/profile_channel.py +105 -0
- package/src/superlocalmemory/retrieval/reranker.py +154 -0
- package/src/superlocalmemory/retrieval/semantic_channel.py +232 -0
- package/src/superlocalmemory/retrieval/strategy.py +96 -0
- package/src/superlocalmemory/retrieval/temporal_channel.py +175 -0
- package/src/superlocalmemory/server/__init__.py +1 -0
- package/src/superlocalmemory/server/api.py +248 -0
- package/src/superlocalmemory/server/routes/__init__.py +4 -0
- package/src/superlocalmemory/server/routes/agents.py +107 -0
- package/src/superlocalmemory/server/routes/backup.py +91 -0
- package/src/superlocalmemory/server/routes/behavioral.py +127 -0
- package/src/superlocalmemory/server/routes/compliance.py +160 -0
- package/src/superlocalmemory/server/routes/data_io.py +188 -0
- package/src/superlocalmemory/server/routes/events.py +183 -0
- package/src/superlocalmemory/server/routes/helpers.py +85 -0
- package/src/superlocalmemory/server/routes/learning.py +273 -0
- package/src/superlocalmemory/server/routes/lifecycle.py +116 -0
- package/src/superlocalmemory/server/routes/memories.py +399 -0
- package/src/superlocalmemory/server/routes/profiles.py +219 -0
- package/src/superlocalmemory/server/routes/stats.py +346 -0
- package/src/superlocalmemory/server/routes/v3_api.py +365 -0
- package/src/superlocalmemory/server/routes/ws.py +82 -0
- package/src/superlocalmemory/server/security_middleware.py +57 -0
- package/src/superlocalmemory/server/ui.py +245 -0
- package/src/superlocalmemory/storage/__init__.py +0 -0
- package/src/superlocalmemory/storage/access_control.py +182 -0
- package/src/superlocalmemory/storage/database.py +594 -0
- package/src/superlocalmemory/storage/migrations.py +303 -0
- package/src/superlocalmemory/storage/models.py +406 -0
- package/src/superlocalmemory/storage/schema.py +726 -0
- package/src/superlocalmemory/storage/v2_migrator.py +317 -0
- package/src/superlocalmemory/trust/__init__.py +0 -0
- package/src/superlocalmemory/trust/gate.py +130 -0
- package/src/superlocalmemory/trust/provenance.py +124 -0
- package/src/superlocalmemory/trust/scorer.py +347 -0
- package/src/superlocalmemory/trust/signals.py +153 -0
- package/ui/index.html +278 -5
- package/ui/js/auto-settings.js +70 -0
- package/ui/js/dashboard.js +90 -0
- package/ui/js/fact-detail.js +92 -0
- package/ui/js/feedback.js +2 -2
- package/ui/js/ide-status.js +102 -0
- package/ui/js/math-health.js +98 -0
- package/ui/js/recall-lab.js +127 -0
- package/ui/js/settings.js +2 -2
- package/ui/js/trust-dashboard.js +73 -0
- package/api_server.py +0 -724
- package/bin/aider-smart +0 -72
- package/bin/superlocalmemoryv2-learning +0 -4
- package/bin/superlocalmemoryv2-list +0 -3
- package/bin/superlocalmemoryv2-patterns +0 -4
- package/bin/superlocalmemoryv2-profile +0 -3
- package/bin/superlocalmemoryv2-recall +0 -3
- package/bin/superlocalmemoryv2-remember +0 -3
- package/bin/superlocalmemoryv2-reset +0 -3
- package/bin/superlocalmemoryv2-status +0 -3
- package/configs/chatgpt-desktop-mcp.json +0 -16
- package/configs/cursor-mcp.json +0 -15
- package/hooks/memory-list-skill.js +0 -139
- package/hooks/memory-profile-skill.js +0 -273
- package/hooks/memory-recall-skill.js +0 -114
- package/hooks/memory-remember-skill.js +0 -127
- package/hooks/memory-reset-skill.js +0 -274
- package/mcp_server.py +0 -1808
- package/requirements-core.txt +0 -22
- package/requirements-learning.txt +0 -12
- package/requirements.txt +0 -12
- package/src/agent_registry.py +0 -411
- package/src/auth_middleware.py +0 -61
- package/src/auto_backup.py +0 -459
- package/src/behavioral/__init__.py +0 -49
- package/src/behavioral/behavioral_listener.py +0 -203
- package/src/behavioral/behavioral_patterns.py +0 -275
- package/src/behavioral/cross_project_transfer.py +0 -206
- package/src/behavioral/outcome_inference.py +0 -194
- package/src/behavioral/outcome_tracker.py +0 -193
- package/src/behavioral/tests/__init__.py +0 -4
- package/src/behavioral/tests/test_behavioral_integration.py +0 -108
- package/src/behavioral/tests/test_behavioral_patterns.py +0 -150
- package/src/behavioral/tests/test_cross_project_transfer.py +0 -142
- package/src/behavioral/tests/test_mcp_behavioral.py +0 -139
- package/src/behavioral/tests/test_mcp_report_outcome.py +0 -117
- package/src/behavioral/tests/test_outcome_inference.py +0 -107
- package/src/behavioral/tests/test_outcome_tracker.py +0 -96
- package/src/cache_manager.py +0 -518
- package/src/compliance/__init__.py +0 -48
- package/src/compliance/abac_engine.py +0 -149
- package/src/compliance/abac_middleware.py +0 -116
- package/src/compliance/audit_db.py +0 -215
- package/src/compliance/audit_logger.py +0 -148
- package/src/compliance/retention_manager.py +0 -289
- package/src/compliance/retention_scheduler.py +0 -186
- package/src/compliance/tests/__init__.py +0 -4
- package/src/compliance/tests/test_abac_enforcement.py +0 -95
- package/src/compliance/tests/test_abac_engine.py +0 -124
- package/src/compliance/tests/test_abac_mcp_integration.py +0 -118
- package/src/compliance/tests/test_audit_db.py +0 -123
- package/src/compliance/tests/test_audit_logger.py +0 -98
- package/src/compliance/tests/test_mcp_audit.py +0 -128
- package/src/compliance/tests/test_mcp_retention_policy.py +0 -125
- package/src/compliance/tests/test_retention_manager.py +0 -131
- package/src/compliance/tests/test_retention_scheduler.py +0 -99
- package/src/compression/__init__.py +0 -25
- package/src/compression/cli.py +0 -150
- package/src/compression/cold_storage.py +0 -217
- package/src/compression/config.py +0 -72
- package/src/compression/orchestrator.py +0 -133
- package/src/compression/tier2_compressor.py +0 -228
- package/src/compression/tier3_compressor.py +0 -153
- package/src/compression/tier_classifier.py +0 -148
- package/src/db_connection_manager.py +0 -536
- package/src/embedding_engine.py +0 -63
- package/src/embeddings/__init__.py +0 -47
- package/src/embeddings/cache.py +0 -70
- package/src/embeddings/cli.py +0 -113
- package/src/embeddings/constants.py +0 -47
- package/src/embeddings/database.py +0 -91
- package/src/embeddings/engine.py +0 -247
- package/src/embeddings/model_loader.py +0 -145
- package/src/event_bus.py +0 -562
- package/src/graph/__init__.py +0 -36
- package/src/graph/build_helpers.py +0 -74
- package/src/graph/cli.py +0 -87
- package/src/graph/cluster_builder.py +0 -188
- package/src/graph/cluster_summary.py +0 -148
- package/src/graph/constants.py +0 -47
- package/src/graph/edge_builder.py +0 -162
- package/src/graph/entity_extractor.py +0 -95
- package/src/graph/graph_core.py +0 -226
- package/src/graph/graph_search.py +0 -231
- package/src/graph/hierarchical.py +0 -207
- package/src/graph/schema.py +0 -99
- package/src/graph_engine.py +0 -52
- package/src/hnsw_index.py +0 -628
- package/src/hybrid_search.py +0 -46
- package/src/learning/__init__.py +0 -217
- package/src/learning/adaptive_ranker.py +0 -682
- package/src/learning/bootstrap/__init__.py +0 -69
- package/src/learning/bootstrap/constants.py +0 -93
- package/src/learning/bootstrap/db_queries.py +0 -316
- package/src/learning/bootstrap/sampling.py +0 -82
- package/src/learning/bootstrap/text_utils.py +0 -71
- package/src/learning/cross_project_aggregator.py +0 -857
- package/src/learning/db/__init__.py +0 -40
- package/src/learning/db/constants.py +0 -44
- package/src/learning/db/schema.py +0 -279
- package/src/learning/engagement_tracker.py +0 -628
- package/src/learning/feature_extractor.py +0 -708
- package/src/learning/feedback_collector.py +0 -806
- package/src/learning/learning_db.py +0 -915
- package/src/learning/project_context_manager.py +0 -572
- package/src/learning/ranking/__init__.py +0 -33
- package/src/learning/ranking/constants.py +0 -84
- package/src/learning/ranking/helpers.py +0 -278
- package/src/learning/source_quality_scorer.py +0 -676
- package/src/learning/synthetic_bootstrap.py +0 -755
- package/src/learning/tests/test_adaptive_ranker.py +0 -325
- package/src/learning/tests/test_adaptive_ranker_v28.py +0 -60
- package/src/learning/tests/test_aggregator.py +0 -306
- package/src/learning/tests/test_auto_retrain_v28.py +0 -35
- package/src/learning/tests/test_e2e_ranking_v28.py +0 -82
- package/src/learning/tests/test_feature_extractor_v28.py +0 -93
- package/src/learning/tests/test_feedback_collector.py +0 -294
- package/src/learning/tests/test_learning_db.py +0 -602
- package/src/learning/tests/test_learning_db_v28.py +0 -110
- package/src/learning/tests/test_learning_init_v28.py +0 -48
- package/src/learning/tests/test_outcome_signals.py +0 -48
- package/src/learning/tests/test_project_context.py +0 -292
- package/src/learning/tests/test_schema_migration.py +0 -319
- package/src/learning/tests/test_signal_inference.py +0 -397
- package/src/learning/tests/test_source_quality.py +0 -351
- package/src/learning/tests/test_synthetic_bootstrap.py +0 -429
- package/src/learning/tests/test_workflow_miner.py +0 -318
- package/src/learning/workflow_pattern_miner.py +0 -655
- package/src/lifecycle/__init__.py +0 -54
- package/src/lifecycle/bounded_growth.py +0 -239
- package/src/lifecycle/compaction_engine.py +0 -226
- package/src/lifecycle/lifecycle_engine.py +0 -355
- package/src/lifecycle/lifecycle_evaluator.py +0 -257
- package/src/lifecycle/lifecycle_scheduler.py +0 -130
- package/src/lifecycle/retention_policy.py +0 -285
- package/src/lifecycle/tests/test_bounded_growth.py +0 -193
- package/src/lifecycle/tests/test_compaction.py +0 -179
- package/src/lifecycle/tests/test_lifecycle_engine.py +0 -137
- package/src/lifecycle/tests/test_lifecycle_evaluation.py +0 -177
- package/src/lifecycle/tests/test_lifecycle_scheduler.py +0 -127
- package/src/lifecycle/tests/test_lifecycle_search.py +0 -109
- package/src/lifecycle/tests/test_mcp_compact.py +0 -149
- package/src/lifecycle/tests/test_mcp_lifecycle_status.py +0 -114
- package/src/lifecycle/tests/test_retention_policy.py +0 -162
- package/src/mcp_tools_v28.py +0 -281
- package/src/memory/__init__.py +0 -36
- package/src/memory/cli.py +0 -205
- package/src/memory/constants.py +0 -39
- package/src/memory/helpers.py +0 -28
- package/src/memory/schema.py +0 -166
- package/src/memory-profiles.py +0 -595
- package/src/memory-reset.py +0 -491
- package/src/memory_compression.py +0 -989
- package/src/memory_store_v2.py +0 -1155
- package/src/migrate_v1_to_v2.py +0 -629
- package/src/pattern_learner.py +0 -34
- package/src/patterns/__init__.py +0 -24
- package/src/patterns/analyzers.py +0 -251
- package/src/patterns/learner.py +0 -271
- package/src/patterns/scoring.py +0 -171
- package/src/patterns/store.py +0 -225
- package/src/patterns/terminology.py +0 -140
- package/src/provenance_tracker.py +0 -312
- package/src/qualixar_attribution.py +0 -139
- package/src/qualixar_watermark.py +0 -78
- package/src/query_optimizer.py +0 -511
- package/src/rate_limiter.py +0 -83
- package/src/search/__init__.py +0 -20
- package/src/search/cli.py +0 -77
- package/src/search/constants.py +0 -26
- package/src/search/engine.py +0 -241
- package/src/search/fusion.py +0 -122
- package/src/search/index_loader.py +0 -114
- package/src/search/methods.py +0 -162
- package/src/search_engine_v2.py +0 -401
- package/src/setup_validator.py +0 -482
- package/src/subscription_manager.py +0 -391
- package/src/tree/__init__.py +0 -59
- package/src/tree/builder.py +0 -185
- package/src/tree/nodes.py +0 -202
- package/src/tree/queries.py +0 -257
- package/src/tree/schema.py +0 -80
- package/src/tree_manager.py +0 -19
- package/src/trust/__init__.py +0 -45
- package/src/trust/constants.py +0 -66
- package/src/trust/queries.py +0 -157
- package/src/trust/schema.py +0 -95
- package/src/trust/scorer.py +0 -299
- package/src/trust/signals.py +0 -95
- package/src/trust_scorer.py +0 -44
- package/ui/app.js +0 -1588
- package/ui/js/graph-cytoscape-monolithic-backup.js +0 -1168
- package/ui/js/graph-cytoscape.js +0 -1168
- package/ui/js/graph-d3-backup.js +0 -32
- package/ui/js/graph.js +0 -32
- package/ui_server.py +0 -286
- /package/docs/{ACCESSIBILITY.md → v2-archive/ACCESSIBILITY.md} +0 -0
- /package/docs/{ARCHITECTURE.md → v2-archive/ARCHITECTURE.md} +0 -0
- /package/docs/{CLI-COMMANDS-REFERENCE.md → v2-archive/CLI-COMMANDS-REFERENCE.md} +0 -0
- /package/docs/{COMPRESSION-README.md → v2-archive/COMPRESSION-README.md} +0 -0
- /package/docs/{FRAMEWORK-INTEGRATIONS.md → v2-archive/FRAMEWORK-INTEGRATIONS.md} +0 -0
- /package/docs/{MCP-MANUAL-SETUP.md → v2-archive/MCP-MANUAL-SETUP.md} +0 -0
- /package/docs/{MCP-TROUBLESHOOTING.md → v2-archive/MCP-TROUBLESHOOTING.md} +0 -0
- /package/docs/{PATTERN-LEARNING.md → v2-archive/PATTERN-LEARNING.md} +0 -0
- /package/docs/{PROFILES-GUIDE.md → v2-archive/PROFILES-GUIDE.md} +0 -0
- /package/docs/{RESET-GUIDE.md → v2-archive/RESET-GUIDE.md} +0 -0
- /package/docs/{SEARCH-ENGINE-V2.2.0.md → v2-archive/SEARCH-ENGINE-V2.2.0.md} +0 -0
- /package/docs/{SEARCH-INTEGRATION-GUIDE.md → v2-archive/SEARCH-INTEGRATION-GUIDE.md} +0 -0
- /package/docs/{UI-SERVER.md → v2-archive/UI-SERVER.md} +0 -0
- /package/docs/{UNIVERSAL-INTEGRATION.md → v2-archive/UNIVERSAL-INTEGRATION.md} +0 -0
- /package/docs/{V2.2.0-OPTIONAL-SEARCH.md → v2-archive/V2.2.0-OPTIONAL-SEARCH.md} +0 -0
- /package/docs/{WINDOWS-INSTALL-README.txt → v2-archive/WINDOWS-INSTALL-README.txt} +0 -0
- /package/docs/{WINDOWS-POST-INSTALL.txt → v2-archive/WINDOWS-POST-INSTALL.txt} +0 -0
- /package/docs/{example_graph_usage.py → v2-archive/example_graph_usage.py} +0 -0
- /package/{completions → ide/completions}/slm.bash +0 -0
- /package/{completions → ide/completions}/slm.zsh +0 -0
- /package/{configs → ide/configs}/cody-commands.json +0 -0
- /package/{install-skills.sh → scripts/install-skills.sh} +0 -0
- /package/{install.ps1 → scripts/install.ps1} +0 -0
- /package/{install.sh → scripts/install.sh} +0 -0
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
# SPDX-License-Identifier: MIT
|
|
2
|
-
# Copyright (c) 2026 SuperLocalMemory (superlocalmemory.com)
|
|
3
|
-
"""ABAC middleware for MCP tool integration.
|
|
4
|
-
|
|
5
|
-
Provides a simple interface for MCP tools to check access before
|
|
6
|
-
executing memory operations. Delegates to ABACEngine for policy
|
|
7
|
-
evaluation.
|
|
8
|
-
"""
|
|
9
|
-
import threading
|
|
10
|
-
from pathlib import Path
|
|
11
|
-
from typing import Any, Dict, Optional
|
|
12
|
-
|
|
13
|
-
from .abac_engine import ABACEngine
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class ABACMiddleware:
|
|
17
|
-
"""Thin middleware between MCP tools and ABAC policy engine.
|
|
18
|
-
|
|
19
|
-
Usage from MCP tools:
|
|
20
|
-
mw = ABACMiddleware(db_path)
|
|
21
|
-
result = mw.check_access(agent_id="agent_1", action="read",
|
|
22
|
-
resource={"access_level": "private"})
|
|
23
|
-
if not result["allowed"]:
|
|
24
|
-
return error_response(result["reason"])
|
|
25
|
-
"""
|
|
26
|
-
|
|
27
|
-
def __init__(
|
|
28
|
-
self,
|
|
29
|
-
db_path: Optional[str] = None,
|
|
30
|
-
policy_path: Optional[str] = None,
|
|
31
|
-
) -> None:
|
|
32
|
-
if db_path is None:
|
|
33
|
-
db_path = str(Path.home() / ".claude-memory" / "memory.db")
|
|
34
|
-
self._db_path = str(db_path)
|
|
35
|
-
|
|
36
|
-
if policy_path is None:
|
|
37
|
-
policy_path = str(
|
|
38
|
-
Path(self._db_path).parent / "abac_policies.json"
|
|
39
|
-
)
|
|
40
|
-
|
|
41
|
-
self._lock = threading.Lock()
|
|
42
|
-
self.denied_count = 0
|
|
43
|
-
self.allowed_count = 0
|
|
44
|
-
|
|
45
|
-
try:
|
|
46
|
-
self._engine = ABACEngine(config_path=policy_path)
|
|
47
|
-
except Exception:
|
|
48
|
-
self._engine = None
|
|
49
|
-
|
|
50
|
-
def check_access(
|
|
51
|
-
self,
|
|
52
|
-
agent_id: str,
|
|
53
|
-
action: str,
|
|
54
|
-
resource: Optional[Dict[str, Any]] = None,
|
|
55
|
-
) -> Dict[str, Any]:
|
|
56
|
-
"""Check if an agent has access to perform an action.
|
|
57
|
-
|
|
58
|
-
Args:
|
|
59
|
-
agent_id: Identifier for the requesting agent.
|
|
60
|
-
action: The action being performed (read, write, delete).
|
|
61
|
-
resource: Resource attributes (access_level, project, tags).
|
|
62
|
-
|
|
63
|
-
Returns:
|
|
64
|
-
Dict with ``allowed`` (bool), ``reason`` (str), and
|
|
65
|
-
optionally ``policy_name``.
|
|
66
|
-
"""
|
|
67
|
-
if self._engine is None:
|
|
68
|
-
return {
|
|
69
|
-
"allowed": True,
|
|
70
|
-
"reason": "ABAC engine unavailable — default allow",
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
subject = {"agent_id": agent_id}
|
|
74
|
-
result = self._engine.evaluate(
|
|
75
|
-
subject=subject,
|
|
76
|
-
resource=resource or {},
|
|
77
|
-
action=action,
|
|
78
|
-
)
|
|
79
|
-
|
|
80
|
-
with self._lock:
|
|
81
|
-
if result["allowed"]:
|
|
82
|
-
self.allowed_count += 1
|
|
83
|
-
else:
|
|
84
|
-
self.denied_count += 1
|
|
85
|
-
|
|
86
|
-
return result
|
|
87
|
-
|
|
88
|
-
def build_agent_context(
|
|
89
|
-
self,
|
|
90
|
-
agent_id: str = "user",
|
|
91
|
-
protocol: str = "mcp",
|
|
92
|
-
) -> Dict[str, Any]:
|
|
93
|
-
"""Build an agent context dict for passing to MemoryStoreV2.
|
|
94
|
-
|
|
95
|
-
Args:
|
|
96
|
-
agent_id: Agent identifier.
|
|
97
|
-
protocol: Access protocol (mcp, cli, dashboard).
|
|
98
|
-
|
|
99
|
-
Returns:
|
|
100
|
-
Dict suitable for ``MemoryStoreV2.search(agent_context=...)``.
|
|
101
|
-
"""
|
|
102
|
-
return {
|
|
103
|
-
"agent_id": agent_id,
|
|
104
|
-
"protocol": protocol,
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
def get_status(self) -> Dict[str, Any]:
|
|
108
|
-
"""Return middleware status."""
|
|
109
|
-
return {
|
|
110
|
-
"engine_available": self._engine is not None,
|
|
111
|
-
"policies_loaded": (
|
|
112
|
-
len(self._engine.policies) if self._engine else 0
|
|
113
|
-
),
|
|
114
|
-
"allowed_count": self.allowed_count,
|
|
115
|
-
"denied_count": self.denied_count,
|
|
116
|
-
}
|
|
@@ -1,215 +0,0 @@
|
|
|
1
|
-
# SPDX-License-Identifier: MIT
|
|
2
|
-
# Copyright (c) 2026 SuperLocalMemory (superlocalmemory.com)
|
|
3
|
-
"""Audit database management with hash chain tamper detection.
|
|
4
|
-
|
|
5
|
-
Provides a tamper-evident audit trail stored in a separate audit.db.
|
|
6
|
-
Each entry's hash incorporates the previous entry's hash, forming a
|
|
7
|
-
chain that can detect any modification to historical records.
|
|
8
|
-
"""
|
|
9
|
-
import hashlib
|
|
10
|
-
import json
|
|
11
|
-
import sqlite3
|
|
12
|
-
import threading
|
|
13
|
-
from datetime import datetime, timezone
|
|
14
|
-
from typing import Any, Dict, List, Optional
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
_GENESIS = "genesis"
|
|
18
|
-
|
|
19
|
-
_SCHEMA = """
|
|
20
|
-
CREATE TABLE IF NOT EXISTS audit_events (
|
|
21
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
22
|
-
event_type TEXT NOT NULL,
|
|
23
|
-
actor TEXT NOT NULL,
|
|
24
|
-
resource_id INTEGER,
|
|
25
|
-
details TEXT DEFAULT '{}',
|
|
26
|
-
prev_hash TEXT NOT NULL,
|
|
27
|
-
entry_hash TEXT NOT NULL,
|
|
28
|
-
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
29
|
-
)
|
|
30
|
-
"""
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
def _compute_hash(
|
|
34
|
-
event_type: str,
|
|
35
|
-
actor: str,
|
|
36
|
-
resource_id: Optional[int],
|
|
37
|
-
details: str,
|
|
38
|
-
prev_hash: str,
|
|
39
|
-
created_at: str,
|
|
40
|
-
) -> str:
|
|
41
|
-
"""Compute SHA-256 hash for an audit entry."""
|
|
42
|
-
payload = (
|
|
43
|
-
f"{event_type}{actor}{resource_id}{details}{prev_hash}{created_at}"
|
|
44
|
-
)
|
|
45
|
-
return hashlib.sha256(payload.encode("utf-8")).hexdigest()
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
class AuditDB:
|
|
49
|
-
"""Manages audit.db -- tamper-evident compliance audit trail.
|
|
50
|
-
|
|
51
|
-
The hash chain guarantees that any modification to a stored event
|
|
52
|
-
will be detected by verify_chain(). The first entry uses a fixed
|
|
53
|
-
genesis value as its previous hash.
|
|
54
|
-
"""
|
|
55
|
-
|
|
56
|
-
def __init__(self, db_path: Optional[str] = None):
|
|
57
|
-
self._db_path = db_path
|
|
58
|
-
self._lock = threading.Lock()
|
|
59
|
-
if db_path:
|
|
60
|
-
self._init_db()
|
|
61
|
-
|
|
62
|
-
# ------------------------------------------------------------------
|
|
63
|
-
# Internal helpers
|
|
64
|
-
# ------------------------------------------------------------------
|
|
65
|
-
|
|
66
|
-
def _get_conn(self) -> sqlite3.Connection:
|
|
67
|
-
conn = sqlite3.connect(self._db_path)
|
|
68
|
-
conn.execute("PRAGMA journal_mode=WAL")
|
|
69
|
-
conn.execute("PRAGMA foreign_keys=ON")
|
|
70
|
-
conn.row_factory = sqlite3.Row
|
|
71
|
-
return conn
|
|
72
|
-
|
|
73
|
-
def _init_db(self) -> None:
|
|
74
|
-
conn = self._get_conn()
|
|
75
|
-
try:
|
|
76
|
-
conn.executescript(_SCHEMA)
|
|
77
|
-
conn.commit()
|
|
78
|
-
finally:
|
|
79
|
-
conn.close()
|
|
80
|
-
|
|
81
|
-
# ------------------------------------------------------------------
|
|
82
|
-
# Public API
|
|
83
|
-
# ------------------------------------------------------------------
|
|
84
|
-
|
|
85
|
-
def log_event(
|
|
86
|
-
self,
|
|
87
|
-
event_type: str,
|
|
88
|
-
actor: str = "system",
|
|
89
|
-
resource_id: Optional[int] = None,
|
|
90
|
-
details: Optional[Dict[str, Any]] = None,
|
|
91
|
-
) -> int:
|
|
92
|
-
"""Append an event to the audit trail and return its row id."""
|
|
93
|
-
details_str = json.dumps(details or {}, sort_keys=True)
|
|
94
|
-
created_at = datetime.now(timezone.utc).isoformat()
|
|
95
|
-
|
|
96
|
-
with self._lock:
|
|
97
|
-
conn = self._get_conn()
|
|
98
|
-
try:
|
|
99
|
-
# Fetch the hash of the most recent entry (or genesis)
|
|
100
|
-
row = conn.execute(
|
|
101
|
-
"SELECT entry_hash FROM audit_events "
|
|
102
|
-
"ORDER BY id DESC LIMIT 1"
|
|
103
|
-
).fetchone()
|
|
104
|
-
prev_hash = row["entry_hash"] if row else _GENESIS
|
|
105
|
-
|
|
106
|
-
entry_hash = _compute_hash(
|
|
107
|
-
event_type, actor, resource_id,
|
|
108
|
-
details_str, prev_hash, created_at,
|
|
109
|
-
)
|
|
110
|
-
|
|
111
|
-
cursor = conn.execute(
|
|
112
|
-
"INSERT INTO audit_events "
|
|
113
|
-
"(event_type, actor, resource_id, details, "
|
|
114
|
-
" prev_hash, entry_hash, created_at) "
|
|
115
|
-
"VALUES (?, ?, ?, ?, ?, ?, ?)",
|
|
116
|
-
(
|
|
117
|
-
event_type, actor, resource_id,
|
|
118
|
-
details_str, prev_hash, entry_hash, created_at,
|
|
119
|
-
),
|
|
120
|
-
)
|
|
121
|
-
conn.commit()
|
|
122
|
-
return cursor.lastrowid
|
|
123
|
-
finally:
|
|
124
|
-
conn.close()
|
|
125
|
-
|
|
126
|
-
def query_events(
|
|
127
|
-
self,
|
|
128
|
-
event_type: Optional[str] = None,
|
|
129
|
-
actor: Optional[str] = None,
|
|
130
|
-
resource_id: Optional[int] = None,
|
|
131
|
-
limit: int = 100,
|
|
132
|
-
) -> List[Dict[str, Any]]:
|
|
133
|
-
"""Query audit events with optional filters."""
|
|
134
|
-
clauses: List[str] = []
|
|
135
|
-
params: List[Any] = []
|
|
136
|
-
|
|
137
|
-
if event_type is not None:
|
|
138
|
-
clauses.append("event_type = ?")
|
|
139
|
-
params.append(event_type)
|
|
140
|
-
if actor is not None:
|
|
141
|
-
clauses.append("actor = ?")
|
|
142
|
-
params.append(actor)
|
|
143
|
-
if resource_id is not None:
|
|
144
|
-
clauses.append("resource_id = ?")
|
|
145
|
-
params.append(resource_id)
|
|
146
|
-
|
|
147
|
-
where = f"WHERE {' AND '.join(clauses)}" if clauses else ""
|
|
148
|
-
sql = (
|
|
149
|
-
f"SELECT id, event_type, actor, resource_id, details, "
|
|
150
|
-
f"prev_hash, entry_hash, created_at "
|
|
151
|
-
f"FROM audit_events {where} "
|
|
152
|
-
f"ORDER BY id DESC LIMIT ?"
|
|
153
|
-
)
|
|
154
|
-
params.append(limit)
|
|
155
|
-
|
|
156
|
-
conn = self._get_conn()
|
|
157
|
-
try:
|
|
158
|
-
rows = conn.execute(sql, params).fetchall()
|
|
159
|
-
return [dict(r) for r in rows]
|
|
160
|
-
finally:
|
|
161
|
-
conn.close()
|
|
162
|
-
|
|
163
|
-
def verify_chain(self) -> Dict[str, Any]:
|
|
164
|
-
"""Verify the integrity of the entire hash chain.
|
|
165
|
-
|
|
166
|
-
Returns a dict with:
|
|
167
|
-
valid -- bool, True if chain is intact
|
|
168
|
-
entries_checked -- int, number of entries verified
|
|
169
|
-
error -- str or None, description of first failure
|
|
170
|
-
"""
|
|
171
|
-
conn = self._get_conn()
|
|
172
|
-
try:
|
|
173
|
-
rows = conn.execute(
|
|
174
|
-
"SELECT id, event_type, actor, resource_id, details, "
|
|
175
|
-
"prev_hash, entry_hash, created_at "
|
|
176
|
-
"FROM audit_events ORDER BY id"
|
|
177
|
-
).fetchall()
|
|
178
|
-
finally:
|
|
179
|
-
conn.close()
|
|
180
|
-
|
|
181
|
-
if not rows:
|
|
182
|
-
return {"valid": True, "entries_checked": 0, "error": None}
|
|
183
|
-
|
|
184
|
-
expected_prev = _GENESIS
|
|
185
|
-
for row in rows:
|
|
186
|
-
row = dict(row)
|
|
187
|
-
# Check the prev_hash link
|
|
188
|
-
if row["prev_hash"] != expected_prev:
|
|
189
|
-
return {
|
|
190
|
-
"valid": False,
|
|
191
|
-
"entries_checked": row["id"],
|
|
192
|
-
"error": f"prev_hash mismatch at entry {row['id']}",
|
|
193
|
-
}
|
|
194
|
-
# Recompute the entry hash
|
|
195
|
-
computed = _compute_hash(
|
|
196
|
-
row["event_type"],
|
|
197
|
-
row["actor"],
|
|
198
|
-
row["resource_id"],
|
|
199
|
-
row["details"],
|
|
200
|
-
row["prev_hash"],
|
|
201
|
-
row["created_at"],
|
|
202
|
-
)
|
|
203
|
-
if computed != row["entry_hash"]:
|
|
204
|
-
return {
|
|
205
|
-
"valid": False,
|
|
206
|
-
"entries_checked": row["id"],
|
|
207
|
-
"error": f"entry_hash mismatch at entry {row['id']}",
|
|
208
|
-
}
|
|
209
|
-
expected_prev = row["entry_hash"]
|
|
210
|
-
|
|
211
|
-
return {
|
|
212
|
-
"valid": True,
|
|
213
|
-
"entries_checked": len(rows),
|
|
214
|
-
"error": None,
|
|
215
|
-
}
|
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
# SPDX-License-Identifier: MIT
|
|
2
|
-
# Copyright (c) 2026 SuperLocalMemory (superlocalmemory.com)
|
|
3
|
-
"""EventBus listener that writes all events to audit.db.
|
|
4
|
-
|
|
5
|
-
Bridges the EventBus (real-time event emission) with AuditDB (tamper-evident
|
|
6
|
-
audit trail). Every event that passes through the EventBus gets persisted
|
|
7
|
-
into audit.db with full hash-chain integrity.
|
|
8
|
-
|
|
9
|
-
Thread-safe: handle_event() runs on the emitter's thread and must be fast.
|
|
10
|
-
Graceful: malformed events are logged defensively, never crash the caller.
|
|
11
|
-
"""
|
|
12
|
-
import json
|
|
13
|
-
import logging
|
|
14
|
-
import threading
|
|
15
|
-
from typing import Any, Dict, Optional
|
|
16
|
-
|
|
17
|
-
from .audit_db import AuditDB
|
|
18
|
-
|
|
19
|
-
logger = logging.getLogger("superlocalmemory.compliance.audit_logger")
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
class AuditLogger:
|
|
23
|
-
"""Listens to EventBus events and writes them to audit.db.
|
|
24
|
-
|
|
25
|
-
Usage:
|
|
26
|
-
audit_logger = AuditLogger("/path/to/audit.db")
|
|
27
|
-
audit_logger.register_with_eventbus() # auto-subscribe
|
|
28
|
-
|
|
29
|
-
Or manually:
|
|
30
|
-
event_bus.add_listener(audit_logger.handle_event)
|
|
31
|
-
"""
|
|
32
|
-
|
|
33
|
-
def __init__(self, audit_db_path: str):
|
|
34
|
-
self._audit_db = AuditDB(audit_db_path)
|
|
35
|
-
self._lock = threading.Lock()
|
|
36
|
-
self._events_logged: int = 0
|
|
37
|
-
self._errors: int = 0
|
|
38
|
-
self._registered: bool = False
|
|
39
|
-
|
|
40
|
-
# ------------------------------------------------------------------
|
|
41
|
-
# Public API
|
|
42
|
-
# ------------------------------------------------------------------
|
|
43
|
-
|
|
44
|
-
@property
|
|
45
|
-
def events_logged(self) -> int:
|
|
46
|
-
"""Total number of events successfully written to audit.db."""
|
|
47
|
-
return self._events_logged
|
|
48
|
-
|
|
49
|
-
def handle_event(self, event: Dict[str, Any]) -> None:
|
|
50
|
-
"""Process a single EventBus event and write it to audit.db.
|
|
51
|
-
|
|
52
|
-
Extracts event_type, source_agent (actor), memory_id (resource_id),
|
|
53
|
-
and payload (details) from the event dict, then delegates to
|
|
54
|
-
AuditDB.log_event().
|
|
55
|
-
|
|
56
|
-
This method MUST NOT raise — it runs on the emitter's thread.
|
|
57
|
-
Any failure is caught, logged, and counted in self._errors.
|
|
58
|
-
|
|
59
|
-
Args:
|
|
60
|
-
event: Dict emitted by EventBus. Expected keys:
|
|
61
|
-
event_type, source_agent, memory_id, payload, timestamp.
|
|
62
|
-
All keys are optional for graceful degradation.
|
|
63
|
-
"""
|
|
64
|
-
try:
|
|
65
|
-
if not isinstance(event, dict):
|
|
66
|
-
logger.warning("AuditLogger received non-dict event: %s", type(event))
|
|
67
|
-
return
|
|
68
|
-
|
|
69
|
-
event_type = event.get("event_type", "unknown")
|
|
70
|
-
actor = event.get("source_agent", "system")
|
|
71
|
-
resource_id = event.get("memory_id")
|
|
72
|
-
payload = event.get("payload", {})
|
|
73
|
-
|
|
74
|
-
# Build details dict including any extra context
|
|
75
|
-
details = {}
|
|
76
|
-
if isinstance(payload, dict):
|
|
77
|
-
details.update(payload)
|
|
78
|
-
else:
|
|
79
|
-
details["raw_payload"] = str(payload)
|
|
80
|
-
|
|
81
|
-
# Include timestamp from event if present
|
|
82
|
-
ts = event.get("timestamp")
|
|
83
|
-
if ts:
|
|
84
|
-
details["event_timestamp"] = ts
|
|
85
|
-
|
|
86
|
-
with self._lock:
|
|
87
|
-
self._audit_db.log_event(
|
|
88
|
-
event_type=event_type,
|
|
89
|
-
actor=actor,
|
|
90
|
-
resource_id=resource_id,
|
|
91
|
-
details=details,
|
|
92
|
-
)
|
|
93
|
-
self._events_logged += 1
|
|
94
|
-
|
|
95
|
-
except Exception as exc:
|
|
96
|
-
self._errors += 1
|
|
97
|
-
logger.error(
|
|
98
|
-
"AuditLogger failed to log event: %s (event=%s)",
|
|
99
|
-
exc,
|
|
100
|
-
_safe_repr(event),
|
|
101
|
-
)
|
|
102
|
-
|
|
103
|
-
def register_with_eventbus(self) -> bool:
|
|
104
|
-
"""Register this logger as an EventBus listener.
|
|
105
|
-
|
|
106
|
-
Attempts to find the EventBus singleton and subscribe
|
|
107
|
-
handle_event as a listener. Returns True on success,
|
|
108
|
-
False if EventBus is unavailable.
|
|
109
|
-
|
|
110
|
-
Graceful: never raises; returns False on any failure.
|
|
111
|
-
"""
|
|
112
|
-
try:
|
|
113
|
-
from event_bus import EventBus as EB
|
|
114
|
-
|
|
115
|
-
bus = EB.get_instance()
|
|
116
|
-
bus.add_listener(self.handle_event)
|
|
117
|
-
self._registered = True
|
|
118
|
-
logger.info("AuditLogger registered with EventBus")
|
|
119
|
-
return True
|
|
120
|
-
except Exception as exc:
|
|
121
|
-
logger.warning("AuditLogger could not register with EventBus: %s", exc)
|
|
122
|
-
self._registered = False
|
|
123
|
-
return False
|
|
124
|
-
|
|
125
|
-
def get_status(self) -> Dict[str, Any]:
|
|
126
|
-
"""Return diagnostic status of this audit logger.
|
|
127
|
-
|
|
128
|
-
Returns:
|
|
129
|
-
Dict with keys: events_logged, errors, registered.
|
|
130
|
-
"""
|
|
131
|
-
return {
|
|
132
|
-
"events_logged": self._events_logged,
|
|
133
|
-
"errors": self._errors,
|
|
134
|
-
"registered": self._registered,
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
# ------------------------------------------------------------------
|
|
139
|
-
# Internal helpers
|
|
140
|
-
# ------------------------------------------------------------------
|
|
141
|
-
|
|
142
|
-
def _safe_repr(obj: Any, max_len: int = 200) -> str:
|
|
143
|
-
"""Safe repr that truncates and never raises."""
|
|
144
|
-
try:
|
|
145
|
-
r = repr(obj)
|
|
146
|
-
return r[:max_len] + "..." if len(r) > max_len else r
|
|
147
|
-
except Exception:
|
|
148
|
-
return "<unrepresentable>"
|