superlocalmemory 4.1.13 → 4.1.15
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/.claude-plugin/marketplace.json +2 -2
- package/CHANGELOG.md +103 -0
- package/README.md +3 -3
- package/package.json +1 -8
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/CLAUDE.md +3 -3
- package/plugin/agents/slm-governance-advisor.md +1 -1
- package/plugin/agents/slm-loop-runner.md +1 -1
- package/plugin/agents/slm-memory-advisor.md +1 -1
- package/plugin/agents/slm-optimize-advisor.md +1 -1
- package/plugin/requirements.txt +1 -1
- package/plugin/skills/slm-cache/SKILL.md +1 -1
- package/plugin/skills/slm-compress/SKILL.md +1 -1
- package/plugin/skills/slm-governance/SKILL.md +1 -1
- package/plugin/skills/slm-graph/SKILL.md +1 -1
- package/plugin/skills/slm-loop/SKILL.md +1 -1
- package/plugin/skills/slm-mesh/SKILL.md +1 -1
- package/plugin/skills/slm-profile/SKILL.md +1 -1
- package/plugin/skills/slm-recall/SKILL.md +1 -1
- package/plugin/skills/slm-remember/SKILL.md +1 -1
- package/plugin/skills/slm-scope/SKILL.md +1 -1
- package/plugin/skills/slm-session/SKILL.md +1 -1
- package/plugin/skills/slm-status/SKILL.md +1 -1
- package/plugin-src/agents/slm-memory-advisor.md +1 -1
- package/plugin-src/agents/slm-optimize-advisor.md +1 -1
- package/plugin-src/rules/AGENTS.md +1 -1
- package/plugin-src/skills/slm-cache/SKILL.md +1 -1
- package/plugin-src/skills/slm-compress/SKILL.md +1 -1
- package/plugin-src/skills/slm-governance/SKILL.md +1 -1
- package/plugin-src/skills/slm-graph/SKILL.md +1 -1
- package/plugin-src/skills/slm-loop/SKILL.md +1 -1
- package/plugin-src/skills/slm-mesh/SKILL.md +1 -1
- package/plugin-src/skills/slm-profile/SKILL.md +1 -1
- package/plugin-src/skills/slm-recall/SKILL.md +1 -1
- package/plugin-src/skills/slm-remember/SKILL.md +1 -1
- package/plugin-src/skills/slm-scope/SKILL.md +1 -1
- package/plugin-src/skills/slm-session/SKILL.md +1 -1
- package/plugin-src/skills/slm-status/SKILL.md +1 -1
- package/scripts/postinstall.js +71 -2
- package/pyproject.toml +0 -250
- package/src/superlocalmemory/__init__.py +0 -82
- package/src/superlocalmemory/access/__init__.py +0 -3
- package/src/superlocalmemory/access/rbac.py +0 -575
- package/src/superlocalmemory/attribution/__init__.py +0 -9
- package/src/superlocalmemory/attribution/signer.py +0 -173
- package/src/superlocalmemory/attribution/watermark.py +0 -189
- package/src/superlocalmemory/brain/__init__.py +0 -5
- package/src/superlocalmemory/brain/truth.py +0 -418
- package/src/superlocalmemory/cli/__init__.py +0 -5
- package/src/superlocalmemory/cli/__main__.py +0 -17
- package/src/superlocalmemory/cli/_lazy_init.py +0 -115
- package/src/superlocalmemory/cli/cache_cmd.py +0 -198
- package/src/superlocalmemory/cli/commands.py +0 -4710
- package/src/superlocalmemory/cli/compress_cmd.py +0 -151
- package/src/superlocalmemory/cli/context_commands.py +0 -193
- package/src/superlocalmemory/cli/daemon.py +0 -909
- package/src/superlocalmemory/cli/db_migrate.py +0 -150
- package/src/superlocalmemory/cli/diagnostics_cmd.py +0 -101
- package/src/superlocalmemory/cli/escape_hatch.py +0 -220
- package/src/superlocalmemory/cli/evidence_cmd.py +0 -103
- package/src/superlocalmemory/cli/gdpr_cmd.py +0 -792
- package/src/superlocalmemory/cli/gdpr_io.py +0 -109
- package/src/superlocalmemory/cli/help_cmd.py +0 -197
- package/src/superlocalmemory/cli/host_upgrades.py +0 -189
- package/src/superlocalmemory/cli/ingest_cmd.py +0 -327
- package/src/superlocalmemory/cli/json_output.py +0 -81
- package/src/superlocalmemory/cli/loop_cmd.py +0 -187
- package/src/superlocalmemory/cli/main.py +0 -1145
- package/src/superlocalmemory/cli/mesh_cmd.py +0 -38
- package/src/superlocalmemory/cli/migrate_cmd.py +0 -55
- package/src/superlocalmemory/cli/ops_cmd.py +0 -281
- package/src/superlocalmemory/cli/optimize_cmd.py +0 -179
- package/src/superlocalmemory/cli/optimize_constants.py +0 -31
- package/src/superlocalmemory/cli/pending_store.py +0 -296
- package/src/superlocalmemory/cli/proxy_cmd.py +0 -108
- package/src/superlocalmemory/cli/scale_engine_cmd.py +0 -56
- package/src/superlocalmemory/cli/service_installer.py +0 -373
- package/src/superlocalmemory/cli/setup_wizard.py +0 -1162
- package/src/superlocalmemory/cli/summary_cmd.py +0 -215
- package/src/superlocalmemory/cli/version_banner.py +0 -202
- package/src/superlocalmemory/cli/wizard_v3426_options.py +0 -129
- package/src/superlocalmemory/code_graph/__init__.py +0 -46
- package/src/superlocalmemory/code_graph/blast_radius.py +0 -177
- package/src/superlocalmemory/code_graph/bridge/__init__.py +0 -36
- package/src/superlocalmemory/code_graph/bridge/entity_resolver.py +0 -490
- package/src/superlocalmemory/code_graph/bridge/event_listeners.py +0 -206
- package/src/superlocalmemory/code_graph/bridge/fact_enricher.py +0 -159
- package/src/superlocalmemory/code_graph/bridge/hebbian_linker.py +0 -170
- package/src/superlocalmemory/code_graph/bridge/maintenance.py +0 -220
- package/src/superlocalmemory/code_graph/bridge/temporal_checker.py +0 -152
- package/src/superlocalmemory/code_graph/changes.py +0 -363
- package/src/superlocalmemory/code_graph/communities.py +0 -299
- package/src/superlocalmemory/code_graph/config.py +0 -154
- package/src/superlocalmemory/code_graph/database.py +0 -526
- package/src/superlocalmemory/code_graph/extractors/__init__.py +0 -95
- package/src/superlocalmemory/code_graph/extractors/python.py +0 -413
- package/src/superlocalmemory/code_graph/extractors/typescript.py +0 -556
- package/src/superlocalmemory/code_graph/flows.py +0 -350
- package/src/superlocalmemory/code_graph/git_hooks.py +0 -226
- package/src/superlocalmemory/code_graph/graph_engine.py +0 -295
- package/src/superlocalmemory/code_graph/graph_store.py +0 -335
- package/src/superlocalmemory/code_graph/incremental.py +0 -200
- package/src/superlocalmemory/code_graph/models.py +0 -130
- package/src/superlocalmemory/code_graph/parser.py +0 -687
- package/src/superlocalmemory/code_graph/resolver.py +0 -321
- package/src/superlocalmemory/code_graph/search.py +0 -460
- package/src/superlocalmemory/code_graph/service.py +0 -95
- package/src/superlocalmemory/code_graph/watcher.py +0 -207
- package/src/superlocalmemory/compliance/__init__.py +0 -0
- package/src/superlocalmemory/compliance/abac.py +0 -204
- package/src/superlocalmemory/compliance/audit.py +0 -385
- package/src/superlocalmemory/compliance/eu_ai_act.py +0 -101
- package/src/superlocalmemory/compliance/gdpr.py +0 -1479
- package/src/superlocalmemory/compliance/lifecycle.py +0 -158
- package/src/superlocalmemory/compliance/retention.py +0 -415
- package/src/superlocalmemory/compliance/scheduler.py +0 -217
- package/src/superlocalmemory/contracts/__init__.py +0 -1
- package/src/superlocalmemory/contracts/schemas/agent-experience-v1.schema.json +0 -92
- package/src/superlocalmemory/contracts/schemas/agent-integration-contract-v2.schema.json +0 -46
- package/src/superlocalmemory/contracts/schemas/cognitive-turn-receipt-v1.schema.json +0 -59
- package/src/superlocalmemory/contracts/v402.py +0 -62
- package/src/superlocalmemory/core/__init__.py +0 -0
- package/src/superlocalmemory/core/actor_context.py +0 -166
- package/src/superlocalmemory/core/admission.py +0 -769
- package/src/superlocalmemory/core/backend_orchestrator.py +0 -637
- package/src/superlocalmemory/core/block_hygiene.py +0 -147
- package/src/superlocalmemory/core/community_summary.py +0 -267
- package/src/superlocalmemory/core/component_healer.py +0 -144
- package/src/superlocalmemory/core/component_registry.py +0 -514
- package/src/superlocalmemory/core/config.py +0 -2204
- package/src/superlocalmemory/core/consolidation_engine.py +0 -983
- package/src/superlocalmemory/core/context_cache.py +0 -574
- package/src/superlocalmemory/core/derivation_lineage.py +0 -246
- package/src/superlocalmemory/core/embedding_worker.py +0 -208
- package/src/superlocalmemory/core/embeddings.py +0 -1052
- package/src/superlocalmemory/core/engine.py +0 -1395
- package/src/superlocalmemory/core/engine_capabilities.py +0 -24
- package/src/superlocalmemory/core/engine_ingestion.py +0 -983
- package/src/superlocalmemory/core/engine_lock.py +0 -75
- package/src/superlocalmemory/core/engine_wiring.py +0 -776
- package/src/superlocalmemory/core/entity_community.py +0 -178
- package/src/superlocalmemory/core/error_envelope.py +0 -60
- package/src/superlocalmemory/core/evidence_bundle.py +0 -528
- package/src/superlocalmemory/core/fact_consolidator.py +0 -812
- package/src/superlocalmemory/core/file_lock.py +0 -92
- package/src/superlocalmemory/core/graph_analyzer.py +0 -456
- package/src/superlocalmemory/core/graph_metrics.py +0 -597
- package/src/superlocalmemory/core/graph_pruner.py +0 -939
- package/src/superlocalmemory/core/health_monitor.py +0 -338
- package/src/superlocalmemory/core/hooks.py +0 -65
- package/src/superlocalmemory/core/ingest_gate.py +0 -133
- package/src/superlocalmemory/core/ingest_policy.py +0 -38
- package/src/superlocalmemory/core/ingestion_command.py +0 -1042
- package/src/superlocalmemory/core/injection.py +0 -434
- package/src/superlocalmemory/core/install_detector.py +0 -131
- package/src/superlocalmemory/core/key_expander.py +0 -138
- package/src/superlocalmemory/core/lifecycle_state.py +0 -153
- package/src/superlocalmemory/core/maintenance.py +0 -777
- package/src/superlocalmemory/core/maintenance_scheduler.py +0 -507
- package/src/superlocalmemory/core/materialization_control.py +0 -20
- package/src/superlocalmemory/core/mcp_embedder_proxy.py +0 -89
- package/src/superlocalmemory/core/memory_health.py +0 -266
- package/src/superlocalmemory/core/mode_capability.py +0 -111
- package/src/superlocalmemory/core/modes.py +0 -168
- package/src/superlocalmemory/core/mutations.py +0 -688
- package/src/superlocalmemory/core/ollama_embedder.py +0 -266
- package/src/superlocalmemory/core/ollama_validator.py +0 -315
- package/src/superlocalmemory/core/operation_policy.py +0 -92
- package/src/superlocalmemory/core/operation_policy_registry.py +0 -542
- package/src/superlocalmemory/core/operation_request.py +0 -127
- package/src/superlocalmemory/core/ops_remediation.py +0 -542
- package/src/superlocalmemory/core/pii.py +0 -105
- package/src/superlocalmemory/core/platform_utils.py +0 -138
- package/src/superlocalmemory/core/profiles.py +0 -234
- package/src/superlocalmemory/core/progressive_abstraction.py +0 -208
- package/src/superlocalmemory/core/projection_drain.py +0 -380
- package/src/superlocalmemory/core/queue_consumer.py +0 -168
- package/src/superlocalmemory/core/ram_lock.py +0 -160
- package/src/superlocalmemory/core/rate_limit.py +0 -151
- package/src/superlocalmemory/core/recall_gate.py +0 -95
- package/src/superlocalmemory/core/recall_pipeline.py +0 -1337
- package/src/superlocalmemory/core/recall_queue.py +0 -377
- package/src/superlocalmemory/core/recall_worker.py +0 -414
- package/src/superlocalmemory/core/registry.py +0 -121
- package/src/superlocalmemory/core/remember_admission.py +0 -161
- package/src/superlocalmemory/core/remember_runtime.py +0 -1190
- package/src/superlocalmemory/core/remote_mode.py +0 -214
- package/src/superlocalmemory/core/reranker_worker.py +0 -338
- package/src/superlocalmemory/core/safe_fs.py +0 -108
- package/src/superlocalmemory/core/scale_autopromote.py +0 -196
- package/src/superlocalmemory/core/scale_engine.py +0 -915
- package/src/superlocalmemory/core/score_contract.py +0 -82
- package/src/superlocalmemory/core/security_primitives.py +0 -672
- package/src/superlocalmemory/core/session_identity.py +0 -98
- package/src/superlocalmemory/core/shadow_router.py +0 -319
- package/src/superlocalmemory/core/slm_disabled.py +0 -85
- package/src/superlocalmemory/core/status_contract.py +0 -108
- package/src/superlocalmemory/core/store_pipeline.py +0 -1404
- package/src/superlocalmemory/core/summarizer.py +0 -200
- package/src/superlocalmemory/core/tier_manager.py +0 -461
- package/src/superlocalmemory/core/topic_signature.py +0 -156
- package/src/superlocalmemory/core/transactions/__init__.py +0 -78
- package/src/superlocalmemory/core/transactions/concrete_owners.py +0 -604
- package/src/superlocalmemory/core/transactions/erasure.py +0 -825
- package/src/superlocalmemory/core/transactions/manifest.py +0 -255
- package/src/superlocalmemory/core/transactions/manifest_key.py +0 -155
- package/src/superlocalmemory/core/transactions/obligations.py +0 -272
- package/src/superlocalmemory/core/transactions/owners.py +0 -114
- package/src/superlocalmemory/core/transactions/reconciler.py +0 -285
- package/src/superlocalmemory/core/transactions/service.py +0 -330
- package/src/superlocalmemory/core/worker_pool.py +0 -377
- package/src/superlocalmemory/core/working_memory.py +0 -288
- package/src/superlocalmemory/dynamics/__init__.py +0 -0
- package/src/superlocalmemory/dynamics/activation_guided_quantization.py +0 -374
- package/src/superlocalmemory/dynamics/eap_scheduler.py +0 -294
- package/src/superlocalmemory/dynamics/ebbinghaus_langevin_coupling.py +0 -171
- package/src/superlocalmemory/dynamics/fisher_langevin_coupling.py +0 -227
- package/src/superlocalmemory/encoding/__init__.py +0 -0
- package/src/superlocalmemory/encoding/auto_linker.py +0 -308
- package/src/superlocalmemory/encoding/cognitive_consolidator.py +0 -899
- package/src/superlocalmemory/encoding/consolidator.py +0 -472
- package/src/superlocalmemory/encoding/context_generator.py +0 -175
- package/src/superlocalmemory/encoding/emotional.py +0 -189
- package/src/superlocalmemory/encoding/entity_reflexion.py +0 -200
- package/src/superlocalmemory/encoding/entity_resolver.py +0 -687
- package/src/superlocalmemory/encoding/entropy_gate.py +0 -101
- package/src/superlocalmemory/encoding/fact_extractor.py +0 -877
- package/src/superlocalmemory/encoding/foresight.py +0 -93
- package/src/superlocalmemory/encoding/graph_builder.py +0 -346
- package/src/superlocalmemory/encoding/observation_builder.py +0 -177
- package/src/superlocalmemory/encoding/prospective_markers.py +0 -262
- package/src/superlocalmemory/encoding/scene_builder.py +0 -410
- package/src/superlocalmemory/encoding/signal_inference.py +0 -90
- package/src/superlocalmemory/encoding/temporal_parser.py +0 -432
- package/src/superlocalmemory/encoding/temporal_validator.py +0 -572
- package/src/superlocalmemory/encoding/type_router.py +0 -237
- package/src/superlocalmemory/evaluation/__init__.py +0 -13
- package/src/superlocalmemory/evaluation/calibration.py +0 -308
- package/src/superlocalmemory/evolution/__init__.py +0 -29
- package/src/superlocalmemory/evolution/blind_verifier.py +0 -122
- package/src/superlocalmemory/evolution/budget.py +0 -356
- package/src/superlocalmemory/evolution/evolution_store.py +0 -619
- package/src/superlocalmemory/evolution/llm_dispatch.py +0 -559
- package/src/superlocalmemory/evolution/model_selection.py +0 -175
- package/src/superlocalmemory/evolution/mutation_generator.py +0 -226
- package/src/superlocalmemory/evolution/skill_activator.py +0 -270
- package/src/superlocalmemory/evolution/skill_evolver.py +0 -928
- package/src/superlocalmemory/evolution/triggers.py +0 -376
- package/src/superlocalmemory/evolution/types.py +0 -114
- package/src/superlocalmemory/graph/__init__.py +0 -9
- package/src/superlocalmemory/graph/cozo_adjacency.py +0 -122
- package/src/superlocalmemory/graph/cozo_backend.py +0 -751
- package/src/superlocalmemory/hooks/__init__.py +0 -3
- package/src/superlocalmemory/hooks/_outcome_common.py +0 -523
- package/src/superlocalmemory/hooks/adapter_base.py +0 -347
- package/src/superlocalmemory/hooks/antigravity_adapter.py +0 -171
- package/src/superlocalmemory/hooks/auto_capture.py +0 -133
- package/src/superlocalmemory/hooks/auto_invoker.py +0 -521
- package/src/superlocalmemory/hooks/auto_parameterize.py +0 -147
- package/src/superlocalmemory/hooks/auto_recall.py +0 -191
- package/src/superlocalmemory/hooks/auto_recall_hook.py +0 -251
- package/src/superlocalmemory/hooks/before_web_hook.py +0 -131
- package/src/superlocalmemory/hooks/claude_code_hooks.py +0 -637
- package/src/superlocalmemory/hooks/codex_assets.py +0 -251
- package/src/superlocalmemory/hooks/codex_hooks.py +0 -186
- package/src/superlocalmemory/hooks/context_payload.py +0 -311
- package/src/superlocalmemory/hooks/copilot_adapter.py +0 -208
- package/src/superlocalmemory/hooks/cross_platform_connector.py +0 -90
- package/src/superlocalmemory/hooks/cursor_adapter.py +0 -173
- package/src/superlocalmemory/hooks/hook_daemon.py +0 -295
- package/src/superlocalmemory/hooks/hook_handlers.py +0 -822
- package/src/superlocalmemory/hooks/ide_connector.py +0 -246
- package/src/superlocalmemory/hooks/memory_protocol.py +0 -158
- package/src/superlocalmemory/hooks/portable_kit.py +0 -755
- package/src/superlocalmemory/hooks/post_tool_async_hook.py +0 -183
- package/src/superlocalmemory/hooks/post_tool_outcome_hook.py +0 -351
- package/src/superlocalmemory/hooks/prewarm_auth.py +0 -187
- package/src/superlocalmemory/hooks/rules_engine.py +0 -99
- package/src/superlocalmemory/hooks/session_registry.py +0 -330
- package/src/superlocalmemory/hooks/stop_outcome_hook.py +0 -138
- package/src/superlocalmemory/hooks/sync_loop.py +0 -114
- package/src/superlocalmemory/hooks/topic_shift_hook.py +0 -302
- package/src/superlocalmemory/hooks/user_prompt_hook.py +0 -131
- package/src/superlocalmemory/hooks/user_prompt_rehash_hook.py +0 -210
- package/src/superlocalmemory/infra/__init__.py +0 -3
- package/src/superlocalmemory/infra/auth_middleware.py +0 -145
- package/src/superlocalmemory/infra/backup.py +0 -974
- package/src/superlocalmemory/infra/backup_obligations.py +0 -423
- package/src/superlocalmemory/infra/cache_manager.py +0 -267
- package/src/superlocalmemory/infra/cloud_backup.py +0 -788
- package/src/superlocalmemory/infra/daemon_identity.py +0 -300
- package/src/superlocalmemory/infra/data_root.py +0 -238
- package/src/superlocalmemory/infra/event_bus.py +0 -637
- package/src/superlocalmemory/infra/local_diagnostics.py +0 -327
- package/src/superlocalmemory/infra/pid_manager.py +0 -193
- package/src/superlocalmemory/infra/process_identity.py +0 -180
- package/src/superlocalmemory/infra/process_reaper.py +0 -624
- package/src/superlocalmemory/infra/rate_limiter.py +0 -228
- package/src/superlocalmemory/infra/self_heal.py +0 -401
- package/src/superlocalmemory/infra/version_integrity.py +0 -229
- package/src/superlocalmemory/ingestion/__init__.py +0 -13
- package/src/superlocalmemory/ingestion/adapter_manager.py +0 -255
- package/src/superlocalmemory/ingestion/base_adapter.py +0 -171
- package/src/superlocalmemory/ingestion/calendar_adapter.py +0 -349
- package/src/superlocalmemory/ingestion/credentials.py +0 -125
- package/src/superlocalmemory/ingestion/gmail_adapter.py +0 -378
- package/src/superlocalmemory/ingestion/parsers.py +0 -100
- package/src/superlocalmemory/ingestion/transcript_adapter.py +0 -161
- package/src/superlocalmemory/integrations/__init__.py +0 -1
- package/src/superlocalmemory/integrations/bounded_loops_mcp.py +0 -431
- package/src/superlocalmemory/integrations/bounded_loops_v051.py +0 -236
- package/src/superlocalmemory/learning/__init__.py +0 -0
- package/src/superlocalmemory/learning/adaptive.py +0 -172
- package/src/superlocalmemory/learning/arm_catalog.py +0 -97
- package/src/superlocalmemory/learning/assertion_miner.py +0 -403
- package/src/superlocalmemory/learning/bandit.py +0 -654
- package/src/superlocalmemory/learning/bandit_cache.py +0 -131
- package/src/superlocalmemory/learning/behavioral.py +0 -542
- package/src/superlocalmemory/learning/bootstrap.py +0 -298
- package/src/superlocalmemory/learning/consolidation_cycle.py +0 -398
- package/src/superlocalmemory/learning/consolidation_quantization_worker.py +0 -115
- package/src/superlocalmemory/learning/consolidation_worker.py +0 -261
- package/src/superlocalmemory/learning/cross_project.py +0 -408
- package/src/superlocalmemory/learning/database.py +0 -698
- package/src/superlocalmemory/learning/dedup_hnsw.py +0 -413
- package/src/superlocalmemory/learning/engagement.py +0 -487
- package/src/superlocalmemory/learning/engagement_features.py +0 -279
- package/src/superlocalmemory/learning/ensemble.py +0 -309
- package/src/superlocalmemory/learning/entity_compiler.py +0 -356
- package/src/superlocalmemory/learning/fact_outcome_joins.py +0 -207
- package/src/superlocalmemory/learning/features.py +0 -138
- package/src/superlocalmemory/learning/feedback.py +0 -724
- package/src/superlocalmemory/learning/forgetting_scheduler.py +0 -375
- package/src/superlocalmemory/learning/hnsw_dedup.py +0 -69
- package/src/superlocalmemory/learning/labeler.py +0 -85
- package/src/superlocalmemory/learning/legacy_migration.py +0 -316
- package/src/superlocalmemory/learning/lightgbm_subprocess.py +0 -236
- package/src/superlocalmemory/learning/memory_merge.py +0 -175
- package/src/superlocalmemory/learning/model_cache.py +0 -267
- package/src/superlocalmemory/learning/model_rollback.py +0 -281
- package/src/superlocalmemory/learning/outcome_queue.py +0 -306
- package/src/superlocalmemory/learning/outcomes.py +0 -286
- package/src/superlocalmemory/learning/pattern_miner.py +0 -465
- package/src/superlocalmemory/learning/pattern_miner_constants.py +0 -90
- package/src/superlocalmemory/learning/pcos.py +0 -291
- package/src/superlocalmemory/learning/project_context.py +0 -366
- package/src/superlocalmemory/learning/propensity.py +0 -131
- package/src/superlocalmemory/learning/ranker.py +0 -300
- package/src/superlocalmemory/learning/ranker_common.py +0 -163
- package/src/superlocalmemory/learning/ranker_retrain_legacy.py +0 -210
- package/src/superlocalmemory/learning/ranker_retrain_online.py +0 -423
- package/src/superlocalmemory/learning/reward.py +0 -888
- package/src/superlocalmemory/learning/reward_archive.py +0 -223
- package/src/superlocalmemory/learning/reward_boost.py +0 -211
- package/src/superlocalmemory/learning/reward_from_outcomes.py +0 -365
- package/src/superlocalmemory/learning/reward_model.py +0 -144
- package/src/superlocalmemory/learning/reward_proxy.py +0 -578
- package/src/superlocalmemory/learning/shadow_test.py +0 -524
- package/src/superlocalmemory/learning/signal_kinds.py +0 -79
- package/src/superlocalmemory/learning/signal_worker.py +0 -268
- package/src/superlocalmemory/learning/signals.py +0 -646
- package/src/superlocalmemory/learning/skill_performance_miner.py +0 -422
- package/src/superlocalmemory/learning/source_quality.py +0 -828
- package/src/superlocalmemory/learning/trigram_index.py +0 -548
- package/src/superlocalmemory/learning/workflows.py +0 -309
- package/src/superlocalmemory/llm/__init__.py +0 -0
- package/src/superlocalmemory/llm/backbone.py +0 -364
- package/src/superlocalmemory/loops/__init__.py +0 -58
- package/src/superlocalmemory/loops/budget.py +0 -58
- package/src/superlocalmemory/loops/engine.py +0 -174
- package/src/superlocalmemory/loops/ledger.py +0 -298
- package/src/superlocalmemory/loops/models.py +0 -152
- package/src/superlocalmemory/loops/rules.py +0 -52
- package/src/superlocalmemory/math/__init__.py +0 -0
- package/src/superlocalmemory/math/ebbinghaus.py +0 -352
- package/src/superlocalmemory/math/fisher.py +0 -356
- package/src/superlocalmemory/math/fisher_quantized.py +0 -255
- package/src/superlocalmemory/math/hopfield.py +0 -282
- package/src/superlocalmemory/math/langevin.py +0 -411
- package/src/superlocalmemory/math/polar_quant.py +0 -414
- package/src/superlocalmemory/math/qjl.py +0 -115
- package/src/superlocalmemory/math/sheaf.py +0 -261
- package/src/superlocalmemory/math/turbo_quant.py +0 -318
- package/src/superlocalmemory/mcp/__init__.py +0 -0
- package/src/superlocalmemory/mcp/_daemon_proxy.py +0 -203
- package/src/superlocalmemory/mcp/_pool_adapter.py +0 -181
- package/src/superlocalmemory/mcp/_stdin_guard.py +0 -60
- package/src/superlocalmemory/mcp/agent_context.py +0 -115
- package/src/superlocalmemory/mcp/cli_fallback.py +0 -602
- package/src/superlocalmemory/mcp/http_transport.py +0 -85
- package/src/superlocalmemory/mcp/profiles.py +0 -154
- package/src/superlocalmemory/mcp/resources.py +0 -281
- package/src/superlocalmemory/mcp/server.py +0 -480
- package/src/superlocalmemory/mcp/session_binding.py +0 -98
- package/src/superlocalmemory/mcp/shared.py +0 -112
- package/src/superlocalmemory/mcp/tools.py +0 -18
- package/src/superlocalmemory/mcp/tools_active.py +0 -958
- package/src/superlocalmemory/mcp/tools_brain.py +0 -298
- package/src/superlocalmemory/mcp/tools_code_graph.py +0 -1717
- package/src/superlocalmemory/mcp/tools_context.py +0 -239
- package/src/superlocalmemory/mcp/tools_core.py +0 -1112
- package/src/superlocalmemory/mcp/tools_evolution.py +0 -343
- package/src/superlocalmemory/mcp/tools_learning.py +0 -393
- package/src/superlocalmemory/mcp/tools_loops.py +0 -345
- package/src/superlocalmemory/mcp/tools_mesh.py +0 -429
- package/src/superlocalmemory/mcp/tools_ops.py +0 -115
- package/src/superlocalmemory/mcp/tools_optimize.py +0 -322
- package/src/superlocalmemory/mcp/tools_summaries.py +0 -147
- package/src/superlocalmemory/mcp/tools_v28.py +0 -292
- package/src/superlocalmemory/mcp/tools_v3.py +0 -398
- package/src/superlocalmemory/mcp/tools_v33.py +0 -507
- package/src/superlocalmemory/mesh/__init__.py +0 -12
- package/src/superlocalmemory/mesh/broker.py +0 -812
- package/src/superlocalmemory/mesh/broker_security.py +0 -470
- package/src/superlocalmemory/mesh/discovery.py +0 -365
- package/src/superlocalmemory/mesh/lock_protocol.py +0 -313
- package/src/superlocalmemory/mesh/node_identity.py +0 -97
- package/src/superlocalmemory/mesh/outbox_remote.py +0 -429
- package/src/superlocalmemory/mesh/remote_sync.py +0 -829
- package/src/superlocalmemory/mesh/state_sync.py +0 -286
- package/src/superlocalmemory/migrations/__init__.py +0 -5
- package/src/superlocalmemory/migrations/v3_4_25_to_v3_4_26.py +0 -144
- package/src/superlocalmemory/optimize/NOTICE +0 -6
- package/src/superlocalmemory/optimize/__init__.py +0 -0
- package/src/superlocalmemory/optimize/adapters/__init__.py +0 -68
- package/src/superlocalmemory/optimize/adapters/_agent_registry.py +0 -120
- package/src/superlocalmemory/optimize/adapters/anthropic_adapter.py +0 -112
- package/src/superlocalmemory/optimize/adapters/openai_adapter.py +0 -122
- package/src/superlocalmemory/optimize/adapters/wrap.py +0 -228
- package/src/superlocalmemory/optimize/cache/__init__.py +0 -31
- package/src/superlocalmemory/optimize/cache/boundary_store.py +0 -488
- package/src/superlocalmemory/optimize/cache/centroid_store.py +0 -199
- package/src/superlocalmemory/optimize/cache/context_key.py +0 -67
- package/src/superlocalmemory/optimize/cache/exact.py +0 -88
- package/src/superlocalmemory/optimize/cache/invalidation.py +0 -36
- package/src/superlocalmemory/optimize/cache/key_builder.py +0 -111
- package/src/superlocalmemory/optimize/cache/manager.py +0 -737
- package/src/superlocalmemory/optimize/cache/semantic.py +0 -637
- package/src/superlocalmemory/optimize/cache/stampede.py +0 -50
- package/src/superlocalmemory/optimize/compress/__init__.py +0 -17
- package/src/superlocalmemory/optimize/compress/align.py +0 -159
- package/src/superlocalmemory/optimize/compress/ccr.py +0 -116
- package/src/superlocalmemory/optimize/compress/prose_llmlingua.py +0 -71
- package/src/superlocalmemory/optimize/compress/router.py +0 -667
- package/src/superlocalmemory/optimize/config/__init__.py +0 -56
- package/src/superlocalmemory/optimize/config/defaults.py +0 -43
- package/src/superlocalmemory/optimize/config/schema.py +0 -327
- package/src/superlocalmemory/optimize/config/store.py +0 -270
- package/src/superlocalmemory/optimize/metrics/__init__.py +0 -8
- package/src/superlocalmemory/optimize/metrics/counters.py +0 -155
- package/src/superlocalmemory/optimize/metrics/estimator.py +0 -87
- package/src/superlocalmemory/optimize/metrics/exporters.py +0 -77
- package/src/superlocalmemory/optimize/metrics/persistence.py +0 -115
- package/src/superlocalmemory/optimize/proxy/__init__.py +0 -28
- package/src/superlocalmemory/optimize/proxy/_helpers.py +0 -730
- package/src/superlocalmemory/optimize/proxy/anthropic_surface.py +0 -375
- package/src/superlocalmemory/optimize/proxy/capture.py +0 -550
- package/src/superlocalmemory/optimize/proxy/gemini_surface.py +0 -528
- package/src/superlocalmemory/optimize/proxy/lifecycle.py +0 -126
- package/src/superlocalmemory/optimize/proxy/openai_surface.py +0 -465
- package/src/superlocalmemory/optimize/proxy/server.py +0 -199
- package/src/superlocalmemory/optimize/proxy/vertex_surface.py +0 -246
- package/src/superlocalmemory/optimize/storage/__init__.py +0 -0
- package/src/superlocalmemory/optimize/storage/db.py +0 -1185
- package/src/superlocalmemory/optimize/storage/schema.py +0 -205
- package/src/superlocalmemory/parameterization/__init__.py +0 -47
- package/src/superlocalmemory/parameterization/cross_project.py +0 -12
- package/src/superlocalmemory/parameterization/pattern_extractor.py +0 -584
- package/src/superlocalmemory/parameterization/pii_filter.py +0 -106
- package/src/superlocalmemory/parameterization/prompt_injector.py +0 -219
- package/src/superlocalmemory/parameterization/prompt_lifecycle.py +0 -281
- package/src/superlocalmemory/parameterization/soft_prompt_generator.py +0 -542
- package/src/superlocalmemory/parameterization/workflow_miner.py +0 -17
- package/src/superlocalmemory/reliability/__init__.py +0 -45
- package/src/superlocalmemory/reliability/join_liveness.py +0 -301
- package/src/superlocalmemory/reliability/prior_distance.py +0 -243
- package/src/superlocalmemory/retrieval/__init__.py +0 -0
- package/src/superlocalmemory/retrieval/agentic.py +0 -367
- package/src/superlocalmemory/retrieval/ann_index.py +0 -235
- package/src/superlocalmemory/retrieval/bm25_channel.py +0 -451
- package/src/superlocalmemory/retrieval/bridge_discovery.py +0 -253
- package/src/superlocalmemory/retrieval/channel_registry.py +0 -154
- package/src/superlocalmemory/retrieval/channel_status.py +0 -117
- package/src/superlocalmemory/retrieval/engine.py +0 -1615
- package/src/superlocalmemory/retrieval/entity_channel.py +0 -994
- package/src/superlocalmemory/retrieval/forgetting_filter.py +0 -160
- package/src/superlocalmemory/retrieval/fusion.py +0 -81
- package/src/superlocalmemory/retrieval/graph_adjacency.py +0 -219
- package/src/superlocalmemory/retrieval/hopfield_channel.py +0 -465
- package/src/superlocalmemory/retrieval/profile_channel.py +0 -105
- package/src/superlocalmemory/retrieval/quantization_aware_search.py +0 -147
- package/src/superlocalmemory/retrieval/remote_reranker.py +0 -758
- package/src/superlocalmemory/retrieval/reranker.py +0 -674
- package/src/superlocalmemory/retrieval/scope_policy.py +0 -126
- package/src/superlocalmemory/retrieval/semantic_channel.py +0 -638
- package/src/superlocalmemory/retrieval/spreading.py +0 -288
- package/src/superlocalmemory/retrieval/spreading_activation.py +0 -616
- package/src/superlocalmemory/retrieval/strategy.py +0 -248
- package/src/superlocalmemory/retrieval/temporal_channel.py +0 -433
- package/src/superlocalmemory/retrieval/temporal_frame.py +0 -102
- package/src/superlocalmemory/retrieval/temporal_utils.py +0 -122
- package/src/superlocalmemory/retrieval/temporal_validity_filter.py +0 -499
- package/src/superlocalmemory/retrieval/time_window.py +0 -181
- package/src/superlocalmemory/retrieval/vector_store.py +0 -863
- package/src/superlocalmemory/server/__init__.py +0 -1
- package/src/superlocalmemory/server/api.py +0 -310
- package/src/superlocalmemory/server/asset_versions.py +0 -171
- package/src/superlocalmemory/server/bandit_loops.py +0 -158
- package/src/superlocalmemory/server/config_file.py +0 -90
- package/src/superlocalmemory/server/consolidation_runner.py +0 -140
- package/src/superlocalmemory/server/egress_policy.py +0 -258
- package/src/superlocalmemory/server/loopback.py +0 -85
- package/src/superlocalmemory/server/middleware/__init__.py +0 -11
- package/src/superlocalmemory/server/middleware/security_headers.py +0 -144
- package/src/superlocalmemory/server/origin.py +0 -55
- package/src/superlocalmemory/server/profile_runtime.py +0 -515
- package/src/superlocalmemory/server/rbac_enforce.py +0 -194
- package/src/superlocalmemory/server/recall_health.py +0 -343
- package/src/superlocalmemory/server/recall_serializer.py +0 -320
- package/src/superlocalmemory/server/route_mutations.py +0 -104
- package/src/superlocalmemory/server/routes/__init__.py +0 -4
- package/src/superlocalmemory/server/routes/abstraction.py +0 -314
- package/src/superlocalmemory/server/routes/adapters.py +0 -63
- package/src/superlocalmemory/server/routes/agents.py +0 -303
- package/src/superlocalmemory/server/routes/backup.py +0 -869
- package/src/superlocalmemory/server/routes/behavioral.py +0 -659
- package/src/superlocalmemory/server/routes/brain.py +0 -1892
- package/src/superlocalmemory/server/routes/chat.py +0 -393
- package/src/superlocalmemory/server/routes/compliance.py +0 -533
- package/src/superlocalmemory/server/routes/config_api.py +0 -703
- package/src/superlocalmemory/server/routes/data_io.py +0 -329
- package/src/superlocalmemory/server/routes/entity.py +0 -237
- package/src/superlocalmemory/server/routes/events.py +0 -214
- package/src/superlocalmemory/server/routes/evolution.py +0 -510
- package/src/superlocalmemory/server/routes/helpers.py +0 -499
- package/src/superlocalmemory/server/routes/ingest.py +0 -137
- package/src/superlocalmemory/server/routes/insights.py +0 -366
- package/src/superlocalmemory/server/routes/learning.py +0 -834
- package/src/superlocalmemory/server/routes/learning_telemetry.py +0 -154
- package/src/superlocalmemory/server/routes/lifecycle.py +0 -184
- package/src/superlocalmemory/server/routes/memories.py +0 -1661
- package/src/superlocalmemory/server/routes/mesh.py +0 -517
- package/src/superlocalmemory/server/routes/mesh_lock.py +0 -54
- package/src/superlocalmemory/server/routes/mesh_state.py +0 -63
- package/src/superlocalmemory/server/routes/optimize.py +0 -197
- package/src/superlocalmemory/server/routes/prewarm.py +0 -173
- package/src/superlocalmemory/server/routes/profiles.py +0 -292
- package/src/superlocalmemory/server/routes/ratelimit.py +0 -132
- package/src/superlocalmemory/server/routes/rbac.py +0 -366
- package/src/superlocalmemory/server/routes/stats.py +0 -385
- package/src/superlocalmemory/server/routes/tiers.py +0 -222
- package/src/superlocalmemory/server/routes/timeline.py +0 -258
- package/src/superlocalmemory/server/routes/token.py +0 -90
- package/src/superlocalmemory/server/routes/v3_api.py +0 -3023
- package/src/superlocalmemory/server/routes/ws.py +0 -171
- package/src/superlocalmemory/server/security_middleware.py +0 -89
- package/src/superlocalmemory/server/ui.py +0 -354
- package/src/superlocalmemory/server/unified_daemon.py +0 -6326
- package/src/superlocalmemory/server/write_identity.py +0 -195
- package/src/superlocalmemory/storage/__init__.py +0 -0
- package/src/superlocalmemory/storage/_migration_internals.py +0 -638
- package/src/superlocalmemory/storage/_schema_version.py +0 -174
- package/src/superlocalmemory/storage/access_log.py +0 -170
- package/src/superlocalmemory/storage/admission_codec.py +0 -129
- package/src/superlocalmemory/storage/admission_journal.py +0 -843
- package/src/superlocalmemory/storage/agent_experience.py +0 -546
- package/src/superlocalmemory/storage/backup.py +0 -531
- package/src/superlocalmemory/storage/correction_cases.py +0 -670
- package/src/superlocalmemory/storage/database.py +0 -3180
- package/src/superlocalmemory/storage/deferred_writes.py +0 -209
- package/src/superlocalmemory/storage/embedding_codec.py +0 -200
- package/src/superlocalmemory/storage/embedding_migrator.py +0 -672
- package/src/superlocalmemory/storage/erasure_fence.py +0 -45
- package/src/superlocalmemory/storage/execution_learning.py +0 -285
- package/src/superlocalmemory/storage/external_evidence.py +0 -359
- package/src/superlocalmemory/storage/generation_fence.py +0 -63
- package/src/superlocalmemory/storage/lineage_retention.py +0 -236
- package/src/superlocalmemory/storage/logical_edges.py +0 -86
- package/src/superlocalmemory/storage/memory_write.py +0 -115
- package/src/superlocalmemory/storage/migration_runner.py +0 -895
- package/src/superlocalmemory/storage/migration_v33.py +0 -140
- package/src/superlocalmemory/storage/migrations/M001_add_signal_features_columns.py +0 -67
- package/src/superlocalmemory/storage/migrations/M002_model_state_history.py +0 -107
- package/src/superlocalmemory/storage/migrations/M003_migration_log.py +0 -38
- package/src/superlocalmemory/storage/migrations/M004_cross_platform_sync_log.py +0 -46
- package/src/superlocalmemory/storage/migrations/M005_bandit_tables.py +0 -75
- package/src/superlocalmemory/storage/migrations/M006_action_outcomes_reward.py +0 -75
- package/src/superlocalmemory/storage/migrations/M007_pending_outcomes.py +0 -63
- package/src/superlocalmemory/storage/migrations/M009_model_lineage.py +0 -94
- package/src/superlocalmemory/storage/migrations/M010_evolution_config.py +0 -80
- package/src/superlocalmemory/storage/migrations/M011_archive_and_merge.py +0 -87
- package/src/superlocalmemory/storage/migrations/M012_shadow_observations.py +0 -72
- package/src/superlocalmemory/storage/migrations/M013_bi_temporal_columns.py +0 -55
- package/src/superlocalmemory/storage/migrations/M014_v345_scale_ready.py +0 -45
- package/src/superlocalmemory/storage/migrations/M015_add_pinned_column.py +0 -58
- package/src/superlocalmemory/storage/migrations/M016_add_scope_support.py +0 -120
- package/src/superlocalmemory/storage/migrations/M017_ccq_scope_column.py +0 -79
- package/src/superlocalmemory/storage/migrations/M018_ingestion_operations.py +0 -120
- package/src/superlocalmemory/storage/migrations/M019_derivation_lineage.py +0 -54
- package/src/superlocalmemory/storage/migrations/M020_model_state_integrity.py +0 -52
- package/src/superlocalmemory/storage/migrations/M021_ingestion_log_profile.py +0 -108
- package/src/superlocalmemory/storage/migrations/M022_entity_aliases_profile.py +0 -86
- package/src/superlocalmemory/storage/migrations/M023_mesh_profile_isolation.py +0 -194
- package/src/superlocalmemory/storage/migrations/M024_rbac_users_roles.py +0 -87
- package/src/superlocalmemory/storage/migrations/M025_perf_indexes.py +0 -90
- package/src/superlocalmemory/storage/migrations/M026_rbac_memberships_fk.py +0 -136
- package/src/superlocalmemory/storage/migrations/M027_transferable_patterns_profile.py +0 -163
- package/src/superlocalmemory/storage/migrations/M028_fact_entity_associations.py +0 -305
- package/src/superlocalmemory/storage/migrations/M029_behavioral_history_indexes.py +0 -137
- package/src/superlocalmemory/storage/migrations/M030_entity_explorer_indexes.py +0 -93
- package/src/superlocalmemory/storage/migrations/M031_dead_letter_operations.py +0 -80
- package/src/superlocalmemory/storage/migrations/M032_write_coordinator_admission.py +0 -188
- package/src/superlocalmemory/storage/migrations/M033_projection_transactions.py +0 -148
- package/src/superlocalmemory/storage/migrations/M034_obligation_integrity.py +0 -58
- package/src/superlocalmemory/storage/migrations/M035_erasure_receipts.py +0 -113
- package/src/superlocalmemory/storage/migrations/M036_vector_row_map.py +0 -107
- package/src/superlocalmemory/storage/migrations/M037_manifest_hmac_version.py +0 -162
- package/src/superlocalmemory/storage/migrations/M038_learning_feedback_channel.py +0 -77
- package/src/superlocalmemory/storage/migrations/M039_scene_fact_members.py +0 -137
- package/src/superlocalmemory/storage/migrations/M040_agent_experience_receipts.py +0 -254
- package/src/superlocalmemory/storage/migrations/M041_external_evidence_receipts.py +0 -189
- package/src/superlocalmemory/storage/migrations/M042_correction_case_ledger.py +0 -245
- package/src/superlocalmemory/storage/migrations/M043_quarantine_display_summaries.py +0 -512
- package/src/superlocalmemory/storage/migrations/M044_play_carries_its_own_evidence.py +0 -127
- package/src/superlocalmemory/storage/migrations/M045_fact_outcome_score.py +0 -158
- package/src/superlocalmemory/storage/migrations/M046_prospective_memory_has_its_own_name.py +0 -620
- package/src/superlocalmemory/storage/migrations/M047_fisher_vectors_are_stored_like_every_other_vector.py +0 -306
- package/src/superlocalmemory/storage/migrations/M048_upcoming_holds_only_what_is_upcoming.py +0 -229
- package/src/superlocalmemory/storage/migrations/M049_a_schema_version_marker_is_one_row.py +0 -201
- package/src/superlocalmemory/storage/migrations/M050_execution_learning_v2.py +0 -70
- package/src/superlocalmemory/storage/migrations/__init__.py +0 -103
- package/src/superlocalmemory/storage/migrations.py +0 -333
- package/src/superlocalmemory/storage/models.py +0 -500
- package/src/superlocalmemory/storage/projection_outbox.py +0 -346
- package/src/superlocalmemory/storage/quantized_store.py +0 -280
- package/src/superlocalmemory/storage/read_connection.py +0 -115
- package/src/superlocalmemory/storage/retention_policy.py +0 -860
- package/src/superlocalmemory/storage/schema.py +0 -1108
- package/src/superlocalmemory/storage/schema_code_graph.py +0 -282
- package/src/superlocalmemory/storage/schema_v32.py +0 -382
- package/src/superlocalmemory/storage/schema_v3410.py +0 -159
- package/src/superlocalmemory/storage/schema_v3411.py +0 -149
- package/src/superlocalmemory/storage/schema_v343.py +0 -315
- package/src/superlocalmemory/storage/schema_v345.py +0 -109
- package/src/superlocalmemory/storage/schema_v347.py +0 -140
- package/src/superlocalmemory/storage/sqlite_vectors.py +0 -169
- package/src/superlocalmemory/storage/v2_migrator.py +0 -466
- package/src/superlocalmemory/storage/write_coordinator.py +0 -949
- package/src/superlocalmemory/storage/write_lock.py +0 -88
- package/src/superlocalmemory/summaries/__init__.py +0 -37
- package/src/superlocalmemory/summaries/base.py +0 -267
- package/src/superlocalmemory/summaries/daily_reflection.py +0 -340
- package/src/superlocalmemory/summaries/non_answer.py +0 -223
- package/src/superlocalmemory/summaries/project_work_log.py +0 -440
- package/src/superlocalmemory/summaries/session_summary.py +0 -311
- package/src/superlocalmemory/trust/__init__.py +0 -0
- package/src/superlocalmemory/trust/gate.py +0 -171
- package/src/superlocalmemory/trust/provenance.py +0 -124
- package/src/superlocalmemory/trust/scorer.py +0 -413
- package/src/superlocalmemory/trust/signals.py +0 -153
- package/src/superlocalmemory/ui/assets/slm-icon-white.svg +0 -64
- package/src/superlocalmemory/ui/assets/slm-icon.svg +0 -36
- package/src/superlocalmemory/ui/css/brain.css +0 -409
- package/src/superlocalmemory/ui/css/design-system.css +0 -696
- package/src/superlocalmemory/ui/css/legacy-dashboard.css +0 -663
- package/src/superlocalmemory/ui/css/neural-glass.css +0 -1599
- package/src/superlocalmemory/ui/css/od-bridge.css +0 -158
- package/src/superlocalmemory/ui/favicon.svg +0 -36
- package/src/superlocalmemory/ui/index.html +0 -1638
- package/src/superlocalmemory/ui/js/agents.js +0 -192
- package/src/superlocalmemory/ui/js/auto-settings.js +0 -624
- package/src/superlocalmemory/ui/js/brain.js +0 -1400
- package/src/superlocalmemory/ui/js/clusters.js +0 -326
- package/src/superlocalmemory/ui/js/compliance.js +0 -307
- package/src/superlocalmemory/ui/js/core.js +0 -566
- package/src/superlocalmemory/ui/js/dashboard.js +0 -503
- package/src/superlocalmemory/ui/js/event-delegation.js +0 -113
- package/src/superlocalmemory/ui/js/events.js +0 -178
- package/src/superlocalmemory/ui/js/fact-detail.js +0 -142
- package/src/superlocalmemory/ui/js/feedback.js +0 -339
- package/src/superlocalmemory/ui/js/graph-event-bus.js +0 -83
- package/src/superlocalmemory/ui/js/graph-filters.js +0 -220
- package/src/superlocalmemory/ui/js/graph-ui.js +0 -214
- package/src/superlocalmemory/ui/js/ide-status.js +0 -115
- package/src/superlocalmemory/ui/js/init.js +0 -54
- package/src/superlocalmemory/ui/js/knowledge-graph.js +0 -945
- package/src/superlocalmemory/ui/js/lifecycle.js +0 -387
- package/src/superlocalmemory/ui/js/math-health.js +0 -114
- package/src/superlocalmemory/ui/js/memories.js +0 -394
- package/src/superlocalmemory/ui/js/memory-chat.js +0 -371
- package/src/superlocalmemory/ui/js/memory-timeline.js +0 -265
- package/src/superlocalmemory/ui/js/modal.js +0 -733
- package/src/superlocalmemory/ui/js/ng-entities.js +0 -298
- package/src/superlocalmemory/ui/js/ng-health.js +0 -208
- package/src/superlocalmemory/ui/js/ng-ingestion.js +0 -203
- package/src/superlocalmemory/ui/js/ng-mesh.js +0 -374
- package/src/superlocalmemory/ui/js/ng-shell.js +0 -524
- package/src/superlocalmemory/ui/js/ng-skills.js +0 -663
- package/src/superlocalmemory/ui/js/od-agents.js +0 -588
- package/src/superlocalmemory/ui/js/od-auth-gate.js +0 -257
- package/src/superlocalmemory/ui/js/od-backup.js +0 -878
- package/src/superlocalmemory/ui/js/od-boundedloops.js +0 -324
- package/src/superlocalmemory/ui/js/od-brain.js +0 -1095
- package/src/superlocalmemory/ui/js/od-compliance-ext.js +0 -301
- package/src/superlocalmemory/ui/js/od-components.js +0 -147
- package/src/superlocalmemory/ui/js/od-entities.js +0 -622
- package/src/superlocalmemory/ui/js/od-graph.js +0 -776
- package/src/superlocalmemory/ui/js/od-health.js +0 -579
- package/src/superlocalmemory/ui/js/od-mcp.js +0 -508
- package/src/superlocalmemory/ui/js/od-memories.js +0 -1499
- package/src/superlocalmemory/ui/js/od-mesh.js +0 -645
- package/src/superlocalmemory/ui/js/od-operations.js +0 -1268
- package/src/superlocalmemory/ui/js/od-ops-health.js +0 -417
- package/src/superlocalmemory/ui/js/od-optimize.js +0 -828
- package/src/superlocalmemory/ui/js/od-settings.js +0 -1275
- package/src/superlocalmemory/ui/js/od-shell.js +0 -819
- package/src/superlocalmemory/ui/js/od-skills.js +0 -600
- package/src/superlocalmemory/ui/js/od-team.js +0 -265
- package/src/superlocalmemory/ui/js/optimize.js +0 -191
- package/src/superlocalmemory/ui/js/profiles.js +0 -362
- package/src/superlocalmemory/ui/js/quick-actions.js +0 -334
- package/src/superlocalmemory/ui/js/recall-lab.js +0 -373
- package/src/superlocalmemory/ui/js/search.js +0 -86
- package/src/superlocalmemory/ui/js/settings.js +0 -556
- package/src/superlocalmemory/ui/js/timeline.js +0 -62
- package/src/superlocalmemory/ui/js/trust-dashboard.js +0 -225
- package/src/superlocalmemory/ui/vendor/bootstrap-icons/bootstrap-icons.css +0 -2018
- package/src/superlocalmemory/ui/vendor/bootstrap-icons/fonts/bootstrap-icons.woff +0 -0
- package/src/superlocalmemory/ui/vendor/bootstrap-icons/fonts/bootstrap-icons.woff2 +0 -0
- package/src/superlocalmemory/ui/vendor/bootstrap.bundle.min.js +0 -7
- package/src/superlocalmemory/ui/vendor/bootstrap.min.css +0 -6
- package/src/superlocalmemory/ui/vendor/d3.v7.min.js +0 -2
- package/src/superlocalmemory/ui/vendor/graphology-library.min.js +0 -2
- package/src/superlocalmemory/ui/vendor/graphology.umd.min.js +0 -2
- package/src/superlocalmemory/ui/vendor/inter-ui/inter-variable.min.css +0 -8
- package/src/superlocalmemory/ui/vendor/inter-ui/variable/InterVariable-Italic.woff2 +0 -0
- package/src/superlocalmemory/ui/vendor/inter-ui/variable/InterVariable.woff2 +0 -0
- package/src/superlocalmemory/ui/vendor/sigma.min.js +0 -1
- package/src/superlocalmemory/vector/__init__.py +0 -9
- package/src/superlocalmemory/vector/lancedb_backend.py +0 -366
|
@@ -1,575 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
|
|
2
|
-
# Licensed under AGPL-3.0-or-later - see LICENSE file
|
|
3
|
-
# Part of SuperLocalMemory V3 — RBAC / teams (C3)
|
|
4
|
-
|
|
5
|
-
"""Role-based access control for the memory tenancy model.
|
|
6
|
-
|
|
7
|
-
The tenancy boundary is the *profile* (individual / team / company). This
|
|
8
|
-
engine adds real, persisted user identity and role grants on top of that
|
|
9
|
-
boundary, following the Cognee reference model (Tenant -> User -> Role).
|
|
10
|
-
|
|
11
|
-
Design principles
|
|
12
|
-
-----------------
|
|
13
|
-
* **Additive / self-hosting-correct.** With zero users the daemon stays
|
|
14
|
-
single-operator: the machine operator (install token / daemon capability
|
|
15
|
-
over loopback) is the implicit *owner* with every permission, so individual
|
|
16
|
-
use has no login friction. Once an org creates users + memberships from the
|
|
17
|
-
dashboard, logged-in users are enforced against their role.
|
|
18
|
-
* **Enforced, not decorative.** ``has_permission`` is called from the write /
|
|
19
|
-
delete / share / manage routes. This module is the single source of truth
|
|
20
|
-
for the role -> permission matrix.
|
|
21
|
-
* **No plaintext secrets.** Passwords are hashed with ``hashlib.scrypt`` and a
|
|
22
|
-
per-user random salt; session tokens are stored only as SHA-256 hashes and
|
|
23
|
-
compared in constant time.
|
|
24
|
-
|
|
25
|
-
All state lives in memory.db (tables from migration M024). Connections are
|
|
26
|
-
short-lived (opened per call) with a bounded busy timeout, matching the mesh
|
|
27
|
-
broker's concurrency-safe pattern.
|
|
28
|
-
"""
|
|
29
|
-
|
|
30
|
-
from __future__ import annotations
|
|
31
|
-
|
|
32
|
-
import hashlib
|
|
33
|
-
import hmac
|
|
34
|
-
import logging
|
|
35
|
-
import os
|
|
36
|
-
import secrets
|
|
37
|
-
import sqlite3
|
|
38
|
-
import uuid
|
|
39
|
-
from datetime import datetime, timedelta, timezone
|
|
40
|
-
from enum import Enum
|
|
41
|
-
from pathlib import Path
|
|
42
|
-
|
|
43
|
-
from superlocalmemory.storage.memory_write import memory_write
|
|
44
|
-
|
|
45
|
-
logger = logging.getLogger("superlocalmemory.access.rbac")
|
|
46
|
-
|
|
47
|
-
# Match the daemon's default (SLM_DB_BUSY_TIMEOUT_MS, default 10 000 ms).
|
|
48
|
-
# Reads use this via _conn(); writes go through memory_write() which reads the
|
|
49
|
-
# same env var internally, so in-process writers never see SQLITE_BUSY.
|
|
50
|
-
_BUSY_TIMEOUT_MS: int = max(0, int(os.environ.get("SLM_DB_BUSY_TIMEOUT_MS", "10000")))
|
|
51
|
-
_SESSION_TTL_HOURS = 12
|
|
52
|
-
|
|
53
|
-
# scrypt cost parameters (OWASP-recommended interactive-login range).
|
|
54
|
-
_SCRYPT_N = 2 ** 14
|
|
55
|
-
_SCRYPT_R = 8
|
|
56
|
-
_SCRYPT_P = 1
|
|
57
|
-
_SCRYPT_DKLEN = 32
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
class Role(str, Enum):
|
|
61
|
-
ADMIN = "admin"
|
|
62
|
-
MEMBER = "member"
|
|
63
|
-
VIEWER = "viewer"
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
class Permission(str, Enum):
|
|
67
|
-
READ = "read"
|
|
68
|
-
WRITE = "write"
|
|
69
|
-
DELETE = "delete"
|
|
70
|
-
SHARE = "share"
|
|
71
|
-
MANAGE = "manage" # manage users, roles, profile settings
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
# Role -> permission set. This is the single source of truth for authorization.
|
|
75
|
-
_ROLE_PERMISSIONS: dict[Role, frozenset[Permission]] = {
|
|
76
|
-
Role.ADMIN: frozenset(Permission),
|
|
77
|
-
Role.MEMBER: frozenset({Permission.READ, Permission.WRITE, Permission.SHARE}),
|
|
78
|
-
Role.VIEWER: frozenset({Permission.READ}),
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
def permissions_for_role(role: Role) -> frozenset[Permission]:
|
|
83
|
-
return _ROLE_PERMISSIONS.get(role, frozenset())
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
class RbacError(ValueError):
|
|
87
|
-
"""Raised for invalid RBAC operations (bad role, duplicate user, ...)."""
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
def _now() -> str:
|
|
91
|
-
return datetime.now(timezone.utc).isoformat()
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
def _uid() -> str:
|
|
95
|
-
return uuid.uuid4().hex[:16]
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
def _hash_password(password: str) -> str:
|
|
99
|
-
"""scrypt$N$r$p$salt_hex$dk_hex — self-describing so params can evolve."""
|
|
100
|
-
if not password or len(password) < 8:
|
|
101
|
-
raise RbacError("Password must be at least 8 characters.")
|
|
102
|
-
salt = secrets.token_bytes(16)
|
|
103
|
-
dk = hashlib.scrypt(
|
|
104
|
-
password.encode("utf-8"), salt=salt,
|
|
105
|
-
n=_SCRYPT_N, r=_SCRYPT_R, p=_SCRYPT_P, dklen=_SCRYPT_DKLEN,
|
|
106
|
-
)
|
|
107
|
-
return f"scrypt${_SCRYPT_N}${_SCRYPT_R}${_SCRYPT_P}${salt.hex()}${dk.hex()}"
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
def _verify_password(password: str, stored: str) -> bool:
|
|
111
|
-
try:
|
|
112
|
-
scheme, n, r, p, salt_hex, dk_hex = stored.split("$")
|
|
113
|
-
if scheme != "scrypt":
|
|
114
|
-
return False
|
|
115
|
-
dk = hashlib.scrypt(
|
|
116
|
-
password.encode("utf-8"), salt=bytes.fromhex(salt_hex),
|
|
117
|
-
n=int(n), r=int(r), p=int(p), dklen=len(bytes.fromhex(dk_hex)),
|
|
118
|
-
)
|
|
119
|
-
return hmac.compare_digest(dk.hex(), dk_hex)
|
|
120
|
-
except (ValueError, TypeError):
|
|
121
|
-
return False
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
def _hash_token(raw_token: str) -> str:
|
|
125
|
-
return hashlib.sha256(raw_token.encode("utf-8")).hexdigest()
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
# Constant dummy hash so verify_credentials spends ~equal time on unknown and
|
|
129
|
-
# known usernames (defeats the username-enumeration timing oracle). Computed
|
|
130
|
-
# once at import.
|
|
131
|
-
_DUMMY_PASSWORD_HASH = _hash_password("__slm_dummy_sentinel__never_a_real_pw__")
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
class RbacEngine:
|
|
135
|
-
"""Persisted user / membership / session store with role enforcement."""
|
|
136
|
-
|
|
137
|
-
def __init__(self, db_path: str | Path) -> None:
|
|
138
|
-
self._db_path = str(db_path)
|
|
139
|
-
|
|
140
|
-
# -- connection -------------------------------------------------------
|
|
141
|
-
|
|
142
|
-
def _conn(self) -> sqlite3.Connection:
|
|
143
|
-
conn = sqlite3.connect(self._db_path, timeout=_BUSY_TIMEOUT_MS / 1000)
|
|
144
|
-
conn.execute(f"PRAGMA busy_timeout={_BUSY_TIMEOUT_MS}")
|
|
145
|
-
conn.row_factory = sqlite3.Row
|
|
146
|
-
return conn
|
|
147
|
-
|
|
148
|
-
# -- users ------------------------------------------------------------
|
|
149
|
-
|
|
150
|
-
def user_count(self) -> int:
|
|
151
|
-
conn = self._conn()
|
|
152
|
-
try:
|
|
153
|
-
return int(conn.execute("SELECT COUNT(*) FROM rbac_users").fetchone()[0])
|
|
154
|
-
finally:
|
|
155
|
-
conn.close()
|
|
156
|
-
|
|
157
|
-
def create_user(self, username: str, password: str, display_name: str = "",
|
|
158
|
-
created_by: str = "owner") -> dict:
|
|
159
|
-
username = (username or "").strip()
|
|
160
|
-
if not username:
|
|
161
|
-
raise RbacError("Username is required.")
|
|
162
|
-
pw_hash = _hash_password(password)
|
|
163
|
-
user_id = _uid()
|
|
164
|
-
# memory_write: process write lock + busy_timeout.
|
|
165
|
-
with memory_write(self._db_path) as conn:
|
|
166
|
-
# The UNIQUE(username) constraint is the source of truth; the SELECT
|
|
167
|
-
# is a fast path. Two concurrent creates can both pass the SELECT, so
|
|
168
|
-
# the loser's INSERT hits the constraint — convert that to RbacError
|
|
169
|
-
# (409) instead of leaking a raw IntegrityError as a 500.
|
|
170
|
-
if conn.execute(
|
|
171
|
-
"SELECT 1 FROM rbac_users WHERE username=?", (username,)
|
|
172
|
-
).fetchone():
|
|
173
|
-
raise RbacError(f"User '{username}' already exists.")
|
|
174
|
-
try:
|
|
175
|
-
conn.execute(
|
|
176
|
-
"INSERT INTO rbac_users (user_id, username, display_name, "
|
|
177
|
-
"password_hash, status, created_at, created_by) "
|
|
178
|
-
"VALUES (?, ?, ?, ?, 'active', ?, ?)",
|
|
179
|
-
(user_id, username, display_name or username, pw_hash,
|
|
180
|
-
_now(), created_by),
|
|
181
|
-
)
|
|
182
|
-
except sqlite3.IntegrityError:
|
|
183
|
-
raise RbacError(f"User '{username}' already exists.")
|
|
184
|
-
logger.info("RBAC: created user '%s' (%s)", username, user_id)
|
|
185
|
-
return {"user_id": user_id, "username": username,
|
|
186
|
-
"display_name": display_name or username, "status": "active"}
|
|
187
|
-
|
|
188
|
-
def set_password(self, user_id: str, password: str) -> None:
|
|
189
|
-
pw_hash = _hash_password(password)
|
|
190
|
-
with memory_write(self._db_path) as conn:
|
|
191
|
-
cur = conn.execute(
|
|
192
|
-
"UPDATE rbac_users SET password_hash=? WHERE user_id=?",
|
|
193
|
-
(pw_hash, user_id),
|
|
194
|
-
)
|
|
195
|
-
if cur.rowcount == 0:
|
|
196
|
-
raise RbacError("User not found.")
|
|
197
|
-
# A password change invalidates every existing session.
|
|
198
|
-
conn.execute("DELETE FROM rbac_sessions WHERE user_id=?", (user_id,))
|
|
199
|
-
|
|
200
|
-
def set_status(self, user_id: str, status: str) -> None:
|
|
201
|
-
if status not in ("active", "disabled"):
|
|
202
|
-
raise RbacError("status must be 'active' or 'disabled'.")
|
|
203
|
-
with memory_write(self._db_path) as conn:
|
|
204
|
-
cur = conn.execute(
|
|
205
|
-
"UPDATE rbac_users SET status=? WHERE user_id=?", (status, user_id)
|
|
206
|
-
)
|
|
207
|
-
if cur.rowcount == 0:
|
|
208
|
-
raise RbacError("User not found.")
|
|
209
|
-
if status == "disabled":
|
|
210
|
-
conn.execute("DELETE FROM rbac_sessions WHERE user_id=?", (user_id,))
|
|
211
|
-
|
|
212
|
-
def delete_user(self, user_id: str) -> None:
|
|
213
|
-
with memory_write(self._db_path) as conn:
|
|
214
|
-
conn.execute("DELETE FROM rbac_sessions WHERE user_id=?", (user_id,))
|
|
215
|
-
conn.execute("DELETE FROM rbac_memberships WHERE user_id=?", (user_id,))
|
|
216
|
-
cur = conn.execute("DELETE FROM rbac_users WHERE user_id=?", (user_id,))
|
|
217
|
-
if cur.rowcount == 0:
|
|
218
|
-
raise RbacError("User not found.")
|
|
219
|
-
|
|
220
|
-
def get_user(self, user_id: str) -> dict | None:
|
|
221
|
-
conn = self._conn()
|
|
222
|
-
try:
|
|
223
|
-
row = conn.execute(
|
|
224
|
-
"SELECT user_id, username, display_name, status, created_at, created_by "
|
|
225
|
-
"FROM rbac_users WHERE user_id=?", (user_id,)
|
|
226
|
-
).fetchone()
|
|
227
|
-
return dict(row) if row else None
|
|
228
|
-
finally:
|
|
229
|
-
conn.close()
|
|
230
|
-
|
|
231
|
-
def list_users(self) -> list[dict]:
|
|
232
|
-
conn = self._conn()
|
|
233
|
-
try:
|
|
234
|
-
rows = conn.execute(
|
|
235
|
-
"SELECT user_id, username, display_name, status, created_at, created_by "
|
|
236
|
-
"FROM rbac_users ORDER BY username"
|
|
237
|
-
).fetchall()
|
|
238
|
-
return [dict(r) for r in rows]
|
|
239
|
-
finally:
|
|
240
|
-
conn.close()
|
|
241
|
-
|
|
242
|
-
# -- credentials / sessions ------------------------------------------
|
|
243
|
-
|
|
244
|
-
def verify_credentials(self, username: str, password: str) -> dict | None:
|
|
245
|
-
conn = self._conn()
|
|
246
|
-
try:
|
|
247
|
-
row = conn.execute(
|
|
248
|
-
"SELECT user_id, username, display_name, password_hash, status "
|
|
249
|
-
"FROM rbac_users WHERE username=?", ((username or "").strip(),)
|
|
250
|
-
).fetchone()
|
|
251
|
-
finally:
|
|
252
|
-
conn.close()
|
|
253
|
-
if not row or row["status"] != "active":
|
|
254
|
-
# Run a verify against a constant dummy hash so an unknown/disabled
|
|
255
|
-
# username costs the same wall-time as a wrong password — no timing
|
|
256
|
-
# oracle for username enumeration.
|
|
257
|
-
_verify_password(password, _DUMMY_PASSWORD_HASH)
|
|
258
|
-
return None
|
|
259
|
-
if not _verify_password(password, row["password_hash"]):
|
|
260
|
-
return None
|
|
261
|
-
return {"user_id": row["user_id"], "username": row["username"],
|
|
262
|
-
"display_name": row["display_name"]}
|
|
263
|
-
|
|
264
|
-
def create_session(self, user_id: str, ttl_hours: int = _SESSION_TTL_HOURS) -> str:
|
|
265
|
-
"""Mint an opaque session token; only its hash is stored. Returns the
|
|
266
|
-
raw token (shown to the client once)."""
|
|
267
|
-
raw = secrets.token_urlsafe(32)
|
|
268
|
-
now = datetime.now(timezone.utc)
|
|
269
|
-
expires = (now + timedelta(hours=ttl_hours)).isoformat()
|
|
270
|
-
with memory_write(self._db_path) as conn:
|
|
271
|
-
conn.execute(
|
|
272
|
-
"INSERT INTO rbac_sessions (token_hash, user_id, created_at, "
|
|
273
|
-
"expires_at, last_seen) VALUES (?, ?, ?, ?, ?)",
|
|
274
|
-
(_hash_token(raw), user_id, now.isoformat(), expires, now.isoformat()),
|
|
275
|
-
)
|
|
276
|
-
return raw
|
|
277
|
-
|
|
278
|
-
def resolve_session(self, raw_token: str) -> dict | None:
|
|
279
|
-
"""Return the active user for a session token, or None if invalid /
|
|
280
|
-
expired / disabled. Updates last_seen. Constant-time by hash lookup.
|
|
281
|
-
|
|
282
|
-
Concurrency design
|
|
283
|
-
------------------
|
|
284
|
-
Phase 1 (read): WAL allows concurrent readers without blocking the
|
|
285
|
-
writer — ``_conn()`` with ``busy_timeout`` only. The write lock is
|
|
286
|
-
NOT taken here so a burst of concurrent requests doesn't serialise
|
|
287
|
-
through the single writer on every call.
|
|
288
|
-
|
|
289
|
-
Phase 2 (conditional write): only if the session is expired/stale.
|
|
290
|
-
``memory_write()`` is opened AFTER the read connection is closed
|
|
291
|
-
(lock-ordering invariant: get_write_lock is outermost).
|
|
292
|
-
"""
|
|
293
|
-
if not raw_token:
|
|
294
|
-
return None
|
|
295
|
-
token_hash = _hash_token(raw_token)
|
|
296
|
-
now = datetime.now(timezone.utc)
|
|
297
|
-
|
|
298
|
-
# -- Phase 1: read-only lookup ----------------------------------------
|
|
299
|
-
conn = self._conn()
|
|
300
|
-
try:
|
|
301
|
-
row = conn.execute(
|
|
302
|
-
"SELECT s.user_id, s.expires_at, s.last_seen, "
|
|
303
|
-
"u.username, u.display_name, u.status "
|
|
304
|
-
"FROM rbac_sessions s JOIN rbac_users u ON u.user_id = s.user_id "
|
|
305
|
-
"WHERE s.token_hash=?", (token_hash,)
|
|
306
|
-
).fetchone()
|
|
307
|
-
if not row:
|
|
308
|
-
return None
|
|
309
|
-
try:
|
|
310
|
-
expired = datetime.fromisoformat(row["expires_at"]) <= now
|
|
311
|
-
except ValueError:
|
|
312
|
-
expired = True
|
|
313
|
-
row_status = row["status"]
|
|
314
|
-
row_last_seen = row["last_seen"]
|
|
315
|
-
user_dict = {
|
|
316
|
-
"user_id": row["user_id"],
|
|
317
|
-
"username": row["username"],
|
|
318
|
-
"display_name": row["display_name"],
|
|
319
|
-
}
|
|
320
|
-
finally:
|
|
321
|
-
conn.close()
|
|
322
|
-
|
|
323
|
-
# -- Phase 2: write if needed (read conn closed above) ----------------
|
|
324
|
-
if expired or row_status != "active":
|
|
325
|
-
with memory_write(self._db_path) as wconn:
|
|
326
|
-
wconn.execute(
|
|
327
|
-
"DELETE FROM rbac_sessions WHERE token_hash=?", (token_hash,)
|
|
328
|
-
)
|
|
329
|
-
return None
|
|
330
|
-
|
|
331
|
-
# Debounce last_seen: only write when stale (>60 s), so a burst of
|
|
332
|
-
# authenticated requests does not serialise through the writer every call.
|
|
333
|
-
stale = True
|
|
334
|
-
try:
|
|
335
|
-
stale = (now - datetime.fromisoformat(row_last_seen)).total_seconds() > 60
|
|
336
|
-
except (ValueError, TypeError, KeyError):
|
|
337
|
-
stale = True
|
|
338
|
-
if stale:
|
|
339
|
-
with memory_write(self._db_path) as wconn:
|
|
340
|
-
wconn.execute(
|
|
341
|
-
"UPDATE rbac_sessions SET last_seen=? WHERE token_hash=?",
|
|
342
|
-
(now.isoformat(), token_hash),
|
|
343
|
-
)
|
|
344
|
-
return user_dict
|
|
345
|
-
|
|
346
|
-
def revoke_session(self, raw_token: str) -> None:
|
|
347
|
-
with memory_write(self._db_path) as conn:
|
|
348
|
-
conn.execute(
|
|
349
|
-
"DELETE FROM rbac_sessions WHERE token_hash=?",
|
|
350
|
-
(_hash_token(raw_token),),
|
|
351
|
-
)
|
|
352
|
-
|
|
353
|
-
def purge_expired_sessions(self) -> int:
|
|
354
|
-
with memory_write(self._db_path) as conn:
|
|
355
|
-
cur = conn.execute(
|
|
356
|
-
"DELETE FROM rbac_sessions WHERE expires_at <= ?", (_now(),)
|
|
357
|
-
)
|
|
358
|
-
return cur.rowcount or 0
|
|
359
|
-
|
|
360
|
-
# -- memberships ------------------------------------------------------
|
|
361
|
-
|
|
362
|
-
def set_membership(self, profile_id: str, user_id: str, role: str,
|
|
363
|
-
added_by: str = "owner") -> dict:
|
|
364
|
-
try:
|
|
365
|
-
role_enum = Role(role)
|
|
366
|
-
except ValueError:
|
|
367
|
-
raise RbacError(f"Invalid role '{role}'. Use admin/member/viewer.")
|
|
368
|
-
with memory_write(self._db_path) as conn:
|
|
369
|
-
if not conn.execute(
|
|
370
|
-
"SELECT 1 FROM rbac_users WHERE user_id=?", (user_id,)
|
|
371
|
-
).fetchone():
|
|
372
|
-
raise RbacError("User not found.")
|
|
373
|
-
conn.execute(
|
|
374
|
-
"INSERT INTO rbac_memberships (profile_id, user_id, role, added_at, added_by) "
|
|
375
|
-
"VALUES (?, ?, ?, ?, ?) "
|
|
376
|
-
"ON CONFLICT(profile_id, user_id) DO UPDATE SET role=excluded.role, "
|
|
377
|
-
"added_at=excluded.added_at, added_by=excluded.added_by",
|
|
378
|
-
(profile_id, user_id, role_enum.value, _now(), added_by),
|
|
379
|
-
)
|
|
380
|
-
return {"profile_id": profile_id, "user_id": user_id, "role": role_enum.value}
|
|
381
|
-
|
|
382
|
-
def remove_membership(self, profile_id: str, user_id: str) -> None:
|
|
383
|
-
with memory_write(self._db_path) as conn:
|
|
384
|
-
conn.execute(
|
|
385
|
-
"DELETE FROM rbac_memberships WHERE profile_id=? AND user_id=?",
|
|
386
|
-
(profile_id, user_id),
|
|
387
|
-
)
|
|
388
|
-
|
|
389
|
-
def get_role(self, user_id: str, profile_id: str) -> Role | None:
|
|
390
|
-
conn = self._conn()
|
|
391
|
-
try:
|
|
392
|
-
row = conn.execute(
|
|
393
|
-
"SELECT role FROM rbac_memberships WHERE user_id=? AND profile_id=?",
|
|
394
|
-
(user_id, profile_id),
|
|
395
|
-
).fetchone()
|
|
396
|
-
finally:
|
|
397
|
-
conn.close()
|
|
398
|
-
if not row:
|
|
399
|
-
return None
|
|
400
|
-
try:
|
|
401
|
-
return Role(row["role"])
|
|
402
|
-
except ValueError:
|
|
403
|
-
return None
|
|
404
|
-
|
|
405
|
-
def list_members(self, profile_id: str) -> list[dict]:
|
|
406
|
-
conn = self._conn()
|
|
407
|
-
try:
|
|
408
|
-
rows = conn.execute(
|
|
409
|
-
"SELECT m.user_id, u.username, u.display_name, m.role, m.added_at "
|
|
410
|
-
"FROM rbac_memberships m JOIN rbac_users u ON u.user_id = m.user_id "
|
|
411
|
-
"WHERE m.profile_id=? ORDER BY u.username", (profile_id,)
|
|
412
|
-
).fetchall()
|
|
413
|
-
return [dict(r) for r in rows]
|
|
414
|
-
finally:
|
|
415
|
-
conn.close()
|
|
416
|
-
|
|
417
|
-
def list_user_profiles(self, user_id: str) -> list[dict]:
|
|
418
|
-
conn = self._conn()
|
|
419
|
-
try:
|
|
420
|
-
rows = conn.execute(
|
|
421
|
-
"SELECT profile_id, role FROM rbac_memberships WHERE user_id=?",
|
|
422
|
-
(user_id,)
|
|
423
|
-
).fetchall()
|
|
424
|
-
return [dict(r) for r in rows]
|
|
425
|
-
finally:
|
|
426
|
-
conn.close()
|
|
427
|
-
|
|
428
|
-
# -- policy settings --------------------------------------------------
|
|
429
|
-
|
|
430
|
-
def get_policy(self, key: str, default: str = "") -> str:
|
|
431
|
-
conn = self._conn()
|
|
432
|
-
try:
|
|
433
|
-
row = conn.execute(
|
|
434
|
-
"SELECT value FROM rbac_settings WHERE key=?", (key,)
|
|
435
|
-
).fetchone()
|
|
436
|
-
return row["value"] if row else default
|
|
437
|
-
finally:
|
|
438
|
-
conn.close()
|
|
439
|
-
|
|
440
|
-
def set_policy(self, key: str, value: str) -> None:
|
|
441
|
-
with memory_write(self._db_path) as conn:
|
|
442
|
-
conn.execute(
|
|
443
|
-
"INSERT INTO rbac_settings (key, value) VALUES (?, ?) "
|
|
444
|
-
"ON CONFLICT(key) DO UPDATE SET value=excluded.value",
|
|
445
|
-
(key, value),
|
|
446
|
-
)
|
|
447
|
-
|
|
448
|
-
def require_login(self) -> bool:
|
|
449
|
-
"""Company mode: mutations require a valid user session (no owner
|
|
450
|
-
bypass). Default off (personal / single-operator use)."""
|
|
451
|
-
return self.get_policy("require_login", "0") == "1"
|
|
452
|
-
|
|
453
|
-
def set_require_login(self, enabled: bool) -> None:
|
|
454
|
-
self.set_policy("require_login", "1" if enabled else "0")
|
|
455
|
-
|
|
456
|
-
# -- correction review policy -----------------------------------------
|
|
457
|
-
|
|
458
|
-
# Key prefix used in rbac_settings. One entry per profile_id.
|
|
459
|
-
_CORRECTION_POLICY_PREFIX = "correction_review_policy:"
|
|
460
|
-
|
|
461
|
-
def set_correction_review_policy(
|
|
462
|
-
self,
|
|
463
|
-
profile_id: str,
|
|
464
|
-
policy: dict,
|
|
465
|
-
*,
|
|
466
|
-
authorizer_user_id: str,
|
|
467
|
-
) -> dict:
|
|
468
|
-
"""Attach a correction-case review policy for ``profile_id``.
|
|
469
|
-
|
|
470
|
-
Authorization rules
|
|
471
|
-
-------------------
|
|
472
|
-
* PERSONAL install (no users yet / user_count == 0): the machine
|
|
473
|
-
owner is the implicit admin and may attach a policy without a
|
|
474
|
-
role check. This matches the additive / self-hosting-correct
|
|
475
|
-
principle in the RBAC design.
|
|
476
|
-
* TEAM / ENTERPRISE install (user_count > 0): the authorizer MUST
|
|
477
|
-
hold Role.ADMIN for the target profile. Any other role raises
|
|
478
|
-
RbacError. This prevents a MEMBER or VIEWER from escalating their
|
|
479
|
-
own correction authority.
|
|
480
|
-
|
|
481
|
-
Governance invariants (CRIT-hardened)
|
|
482
|
-
--------------------------------------
|
|
483
|
-
C1 Non-admins cannot attach a policy (role check above).
|
|
484
|
-
C2 ``automatic_application`` is never silently promoted to True.
|
|
485
|
-
The field defaults to False; an authorizer must set it
|
|
486
|
-
explicitly, and it is recorded with the authorizer's user_id and
|
|
487
|
-
a timestamp so the action is auditable.
|
|
488
|
-
C3 Personal installs do NOT auto-create a policy. The machine
|
|
489
|
-
owner must call this method explicitly. Until they do,
|
|
490
|
-
``get_correction_review_policy`` returns None and BrainTruth
|
|
491
|
-
reports the policy as not_configured.
|
|
492
|
-
|
|
493
|
-
Returns the stored policy dict.
|
|
494
|
-
"""
|
|
495
|
-
import json as _json
|
|
496
|
-
|
|
497
|
-
if not profile_id:
|
|
498
|
-
raise RbacError("profile_id must be non-empty.")
|
|
499
|
-
if not authorizer_user_id:
|
|
500
|
-
raise RbacError("authorizer_user_id must be non-empty.")
|
|
501
|
-
|
|
502
|
-
# CRIT-C1: enforce admin role in multi-user (team/enterprise) mode.
|
|
503
|
-
# In personal mode (zero registered users) the machine owner is the
|
|
504
|
-
# implicit admin — deny-by-default still applies to defined users.
|
|
505
|
-
user_count = self.user_count()
|
|
506
|
-
if user_count > 0:
|
|
507
|
-
role = self.get_role(authorizer_user_id, profile_id)
|
|
508
|
-
if role != Role.ADMIN:
|
|
509
|
-
raise RbacError(
|
|
510
|
-
f"Attaching a correction review policy requires Role.ADMIN. "
|
|
511
|
-
f"User '{authorizer_user_id}' has role={role!r} on "
|
|
512
|
-
f"profile '{profile_id}'."
|
|
513
|
-
)
|
|
514
|
-
|
|
515
|
-
# CRIT-C2: automatic_application is never silently set to True.
|
|
516
|
-
# The authorizer must explicitly include it in the policy dict;
|
|
517
|
-
# it is still coerced to bool so a truthy non-bool value doesn't slip through.
|
|
518
|
-
auto_apply = bool(policy.get("automatic_application", False))
|
|
519
|
-
|
|
520
|
-
safe_policy = {
|
|
521
|
-
"policy_id": str(policy.get("policy_id") or _uid()),
|
|
522
|
-
"authorized_by": authorizer_user_id,
|
|
523
|
-
"authorized_at": _now(),
|
|
524
|
-
"automatic_application": auto_apply,
|
|
525
|
-
"enabled": bool(policy.get("enabled", True)),
|
|
526
|
-
"applies_to_profile": str(policy.get("applies_to_profile", profile_id)),
|
|
527
|
-
}
|
|
528
|
-
key = f"{self._CORRECTION_POLICY_PREFIX}{profile_id}"
|
|
529
|
-
self.set_policy(key, _json.dumps(safe_policy))
|
|
530
|
-
logger.info(
|
|
531
|
-
"RBAC: correction review policy attached for profile '%s' by '%s' "
|
|
532
|
-
"(automatic_application=%s)",
|
|
533
|
-
profile_id, authorizer_user_id, auto_apply,
|
|
534
|
-
)
|
|
535
|
-
return safe_policy
|
|
536
|
-
|
|
537
|
-
def get_correction_review_policy(self, profile_id: str) -> dict | None:
|
|
538
|
-
"""Return the attached correction review policy for ``profile_id``.
|
|
539
|
-
|
|
540
|
-
Returns None when no policy has been attached. The caller (host
|
|
541
|
-
integration) should pass this to
|
|
542
|
-
``BrainTruthService(review_policy=...)``.
|
|
543
|
-
|
|
544
|
-
This method is safe to call in personal mode (no users configured).
|
|
545
|
-
"""
|
|
546
|
-
import json as _json
|
|
547
|
-
|
|
548
|
-
key = f"{self._CORRECTION_POLICY_PREFIX}{profile_id}"
|
|
549
|
-
raw = self.get_policy(key)
|
|
550
|
-
if not raw:
|
|
551
|
-
return None
|
|
552
|
-
try:
|
|
553
|
-
return _json.loads(raw)
|
|
554
|
-
except (ValueError, TypeError):
|
|
555
|
-
logger.warning(
|
|
556
|
-
"RBAC: malformed correction review policy for profile '%s' — "
|
|
557
|
-
"returning None (treat as not_configured)",
|
|
558
|
-
profile_id,
|
|
559
|
-
)
|
|
560
|
-
return None
|
|
561
|
-
|
|
562
|
-
# -- authorization ----------------------------------------------------
|
|
563
|
-
|
|
564
|
-
def has_permission(self, user_id: str, profile_id: str,
|
|
565
|
-
permission: Permission | str) -> bool:
|
|
566
|
-
"""True iff the user's role on the profile grants ``permission``.
|
|
567
|
-
|
|
568
|
-
A user with no membership on the profile has NO access (deny-by-default).
|
|
569
|
-
The implicit machine owner is handled by the caller, not here.
|
|
570
|
-
"""
|
|
571
|
-
perm = permission if isinstance(permission, Permission) else Permission(permission)
|
|
572
|
-
role = self.get_role(user_id, profile_id)
|
|
573
|
-
if role is None:
|
|
574
|
-
return False
|
|
575
|
-
return perm in permissions_for_role(role)
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
"""Attribution — Multi-layer provenance and ownership protection.
|
|
2
|
-
|
|
3
|
-
Part of Qualixar | Author: Varun Pratap Bhardwaj
|
|
4
|
-
"""
|
|
5
|
-
|
|
6
|
-
from superlocalmemory.attribution.signer import QualixarSigner
|
|
7
|
-
from superlocalmemory.attribution.watermark import QualixarWatermark
|
|
8
|
-
|
|
9
|
-
__all__ = ["QualixarSigner", "QualixarWatermark"]
|