superlocalmemory 3.7.8 → 3.8.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/.claude-plugin/marketplace.json +1 -1
- package/ATTRIBUTION.md +1 -3
- package/CHANGELOG.md +69 -0
- package/README.md +199 -29
- package/package.json +4 -2
- package/plugin/.claude-plugin/plugin.json +2 -2
- package/plugin/CLAUDE.md +8 -8
- package/plugin/agents/slm-governance-advisor.md +80 -0
- package/plugin/agents/slm-loop-runner.md +71 -0
- package/plugin/agents/slm-memory-advisor.md +10 -5
- package/plugin/agents/slm-optimize-advisor.md +9 -3
- package/plugin/commands/slm-loop.md +31 -0
- package/plugin/hooks/hooks.json +79 -0
- package/plugin/requirements.txt +1 -1
- package/plugin/scripts/slm-launch +46 -7
- package/plugin/settings.json +9 -0
- package/plugin/skills/slm-cache/SKILL.md +9 -1
- package/plugin/skills/slm-compress/SKILL.md +8 -1
- package/plugin/skills/slm-governance/SKILL.md +248 -0
- package/plugin/skills/slm-graph/SKILL.md +17 -3
- package/plugin/skills/slm-loop/SKILL.md +99 -0
- package/plugin/skills/slm-mesh/SKILL.md +282 -0
- package/plugin/skills/slm-profile/SKILL.md +148 -0
- package/plugin/skills/slm-recall/SKILL.md +46 -10
- package/plugin/skills/slm-remember/SKILL.md +48 -1
- package/plugin/skills/slm-scope/SKILL.md +176 -0
- package/plugin/skills/slm-session/SKILL.md +24 -1
- package/plugin/skills/slm-status/SKILL.md +18 -1
- package/plugin-src/agents/slm-governance-advisor.md +80 -0
- package/plugin-src/agents/slm-loop-runner.md +71 -0
- package/plugin-src/agents/slm-memory-advisor.md +10 -5
- package/plugin-src/agents/slm-optimize-advisor.md +9 -3
- package/plugin-src/commands/slm-loop.md +31 -0
- package/plugin-src/hooks/hooks.json +79 -0
- package/plugin-src/manifest.json +7 -2
- package/plugin-src/requirements.txt +1 -1
- package/plugin-src/rules/AGENTS.md +57 -18
- package/plugin-src/rules/CLAUDE.md.fragment +8 -8
- package/plugin-src/scripts/slm-launch +46 -7
- package/plugin-src/settings.json +9 -0
- package/plugin-src/skills/slm-cache/SKILL.md +9 -1
- package/plugin-src/skills/slm-compress/SKILL.md +8 -1
- package/plugin-src/skills/slm-governance/SKILL.md +248 -0
- package/plugin-src/skills/slm-graph/SKILL.md +17 -3
- package/plugin-src/skills/slm-loop/SKILL.md +99 -0
- package/plugin-src/skills/slm-mesh/SKILL.md +282 -0
- package/plugin-src/skills/slm-profile/SKILL.md +148 -0
- package/plugin-src/skills/slm-recall/SKILL.md +46 -10
- package/plugin-src/skills/slm-remember/SKILL.md +48 -1
- package/plugin-src/skills/slm-scope/SKILL.md +176 -0
- package/plugin-src/skills/slm-session/SKILL.md +24 -1
- package/plugin-src/skills/slm-status/SKILL.md +18 -1
- package/pyproject.toml +1 -1
- package/scripts/postinstall/validation.js +2 -0
- package/scripts/postinstall-interactive.js +74 -2
- package/src/superlocalmemory/__init__.py +1 -1
- package/src/superlocalmemory/access/__init__.py +3 -0
- package/src/superlocalmemory/access/rbac.py +477 -0
- package/src/superlocalmemory/cli/commands.py +94 -10
- package/src/superlocalmemory/cli/compress_cmd.py +17 -7
- package/src/superlocalmemory/cli/loop_cmd.py +192 -0
- package/src/superlocalmemory/cli/main.py +39 -4
- package/src/superlocalmemory/cli/mesh_cmd.py +38 -0
- package/src/superlocalmemory/cli/optimize_cmd.py +3 -0
- package/src/superlocalmemory/cli/pending_store.py +49 -13
- package/src/superlocalmemory/cli/proxy_cmd.py +4 -0
- package/src/superlocalmemory/cli/scale_engine_cmd.py +6 -0
- package/src/superlocalmemory/cli/setup_wizard.py +22 -13
- package/src/superlocalmemory/compliance/audit.py +6 -0
- package/src/superlocalmemory/compliance/gdpr.py +128 -138
- package/src/superlocalmemory/compliance/retention.py +176 -45
- package/src/superlocalmemory/core/backend_orchestrator.py +5 -43
- package/src/superlocalmemory/core/community_summary.py +267 -0
- package/src/superlocalmemory/core/config.py +216 -3
- package/src/superlocalmemory/core/consolidation_engine.py +95 -22
- package/src/superlocalmemory/core/context_cache.py +61 -18
- package/src/superlocalmemory/core/embedding_worker.py +17 -2
- package/src/superlocalmemory/core/embeddings.py +12 -1
- package/src/superlocalmemory/core/engine.py +17 -1
- package/src/superlocalmemory/core/engine_ingestion.py +29 -0
- package/src/superlocalmemory/core/engine_wiring.py +13 -0
- package/src/superlocalmemory/core/entity_community.py +178 -0
- package/src/superlocalmemory/core/graph_analyzer.py +39 -2
- package/src/superlocalmemory/core/graph_pruner.py +13 -8
- package/src/superlocalmemory/core/key_expander.py +138 -0
- package/src/superlocalmemory/core/maintenance.py +23 -0
- package/src/superlocalmemory/core/modes.py +1 -1
- package/src/superlocalmemory/core/mutations.py +2 -2
- package/src/superlocalmemory/core/pii.py +105 -0
- package/src/superlocalmemory/core/progressive_abstraction.py +208 -0
- package/src/superlocalmemory/core/recall_pipeline.py +2 -0
- package/src/superlocalmemory/core/recall_worker.py +20 -6
- package/src/superlocalmemory/core/scale_engine.py +60 -1
- package/src/superlocalmemory/core/security_primitives.py +40 -2
- package/src/superlocalmemory/core/store_pipeline.py +35 -11
- package/src/superlocalmemory/core/worker_pool.py +21 -6
- package/src/superlocalmemory/encoding/entity_reflexion.py +200 -0
- package/src/superlocalmemory/encoding/entity_resolver.py +34 -24
- package/src/superlocalmemory/encoding/fact_extractor.py +26 -1
- package/src/superlocalmemory/encoding/temporal_validator.py +64 -1
- package/src/superlocalmemory/evolution/evolution_store.py +122 -45
- package/src/superlocalmemory/evolution/llm_dispatch.py +12 -1
- package/src/superlocalmemory/evolution/model_selection.py +160 -0
- package/src/superlocalmemory/evolution/mutation_generator.py +16 -0
- package/src/superlocalmemory/evolution/skill_evolver.py +127 -42
- package/src/superlocalmemory/evolution/triggers.py +22 -13
- package/src/superlocalmemory/graph/cozo_backend.py +43 -20
- package/src/superlocalmemory/hooks/adapter_base.py +5 -1
- package/src/superlocalmemory/hooks/auto_recall.py +13 -1
- package/src/superlocalmemory/hooks/claude_code_hooks.py +11 -0
- package/src/superlocalmemory/hooks/codex_assets.py +64 -5
- package/src/superlocalmemory/hooks/hook_daemon.py +20 -3
- package/src/superlocalmemory/hooks/memory_protocol.py +54 -0
- package/src/superlocalmemory/hooks/portable_kit.py +114 -1
- package/src/superlocalmemory/infra/backup.py +12 -1
- package/src/superlocalmemory/infra/daemon_identity.py +40 -4
- package/src/superlocalmemory/infra/data_root.py +43 -4
- package/src/superlocalmemory/infra/event_bus.py +107 -24
- package/src/superlocalmemory/infra/rate_limiter.py +93 -0
- package/src/superlocalmemory/ingestion/adapter_manager.py +4 -1
- package/src/superlocalmemory/ingestion/credentials.py +1 -1
- package/src/superlocalmemory/learning/cross_project.py +28 -19
- package/src/superlocalmemory/learning/reward_proxy.py +42 -9
- package/src/superlocalmemory/loops/__init__.py +56 -0
- package/src/superlocalmemory/loops/budget.py +58 -0
- package/src/superlocalmemory/loops/engine.py +164 -0
- package/src/superlocalmemory/loops/ledger.py +243 -0
- package/src/superlocalmemory/loops/models.py +152 -0
- package/src/superlocalmemory/loops/rules.py +52 -0
- package/src/superlocalmemory/mcp/_daemon_proxy.py +3 -0
- package/src/superlocalmemory/mcp/_pool_adapter.py +2 -0
- package/src/superlocalmemory/mcp/profiles.py +103 -0
- package/src/superlocalmemory/mcp/server.py +21 -49
- package/src/superlocalmemory/mcp/tools_active.py +4 -7
- package/src/superlocalmemory/mcp/tools_code_graph.py +51 -5
- package/src/superlocalmemory/mcp/tools_core.py +8 -1
- package/src/superlocalmemory/mcp/tools_evolution.py +6 -3
- package/src/superlocalmemory/mcp/tools_loops.py +300 -0
- package/src/superlocalmemory/mcp/tools_mesh.py +140 -4
- package/src/superlocalmemory/mcp/tools_optimize.py +15 -8
- package/src/superlocalmemory/mesh/broker.py +237 -129
- package/src/superlocalmemory/mesh/remote_sync.py +50 -8
- package/src/superlocalmemory/optimize/NOTICE +1 -6
- package/src/superlocalmemory/optimize/adapters/anthropic_adapter.py +1 -4
- package/src/superlocalmemory/optimize/adapters/openai_adapter.py +1 -4
- package/src/superlocalmemory/optimize/cache/semantic.py +27 -19
- package/src/superlocalmemory/optimize/compress/align.py +32 -26
- package/src/superlocalmemory/optimize/compress/ccr.py +14 -71
- package/src/superlocalmemory/optimize/compress/router.py +105 -22
- package/src/superlocalmemory/optimize/config/defaults.py +1 -1
- package/src/superlocalmemory/optimize/config/schema.py +87 -4
- package/src/superlocalmemory/optimize/metrics/counters.py +13 -4
- package/src/superlocalmemory/optimize/metrics/estimator.py +0 -3
- package/src/superlocalmemory/optimize/proxy/_helpers.py +31 -4
- package/src/superlocalmemory/optimize/storage/db.py +38 -9
- package/src/superlocalmemory/optimize/storage/schema.py +10 -0
- package/src/superlocalmemory/parameterization/pattern_extractor.py +6 -3
- package/src/superlocalmemory/retrieval/agentic.py +1 -1
- package/src/superlocalmemory/retrieval/bm25_channel.py +68 -10
- package/src/superlocalmemory/retrieval/engine.py +168 -26
- package/src/superlocalmemory/retrieval/entity_channel.py +7 -5
- package/src/superlocalmemory/retrieval/hopfield_channel.py +9 -2
- package/src/superlocalmemory/retrieval/semantic_channel.py +114 -21
- package/src/superlocalmemory/retrieval/spreading_activation.py +11 -2
- package/src/superlocalmemory/retrieval/temporal_channel.py +48 -9
- package/src/superlocalmemory/retrieval/temporal_frame.py +102 -0
- package/src/superlocalmemory/retrieval/temporal_validity_filter.py +135 -0
- package/src/superlocalmemory/retrieval/time_window.py +181 -0
- package/src/superlocalmemory/server/api.py +4 -4
- package/src/superlocalmemory/server/profile_runtime.py +125 -8
- package/src/superlocalmemory/server/rbac_enforce.py +142 -0
- package/src/superlocalmemory/server/recall_health.py +24 -3
- package/src/superlocalmemory/server/recall_serializer.py +19 -1
- package/src/superlocalmemory/server/routes/abstraction.py +115 -0
- package/src/superlocalmemory/server/routes/agents.py +128 -38
- package/src/superlocalmemory/server/routes/backup.py +34 -10
- package/src/superlocalmemory/server/routes/behavioral.py +13 -12
- package/src/superlocalmemory/server/routes/brain.py +21 -5
- package/src/superlocalmemory/server/routes/chat.py +10 -5
- package/src/superlocalmemory/server/routes/compliance.py +171 -21
- package/src/superlocalmemory/server/routes/config_api.py +436 -0
- package/src/superlocalmemory/server/routes/data_io.py +30 -8
- package/src/superlocalmemory/server/routes/entity.py +9 -4
- package/src/superlocalmemory/server/routes/events.py +24 -8
- package/src/superlocalmemory/server/routes/evolution.py +135 -17
- package/src/superlocalmemory/server/routes/helpers.py +16 -1
- package/src/superlocalmemory/server/routes/ingest.py +7 -4
- package/src/superlocalmemory/server/routes/insights.py +3 -3
- package/src/superlocalmemory/server/routes/learning.py +14 -14
- package/src/superlocalmemory/server/routes/lifecycle.py +59 -8
- package/src/superlocalmemory/server/routes/memories.py +182 -57
- package/src/superlocalmemory/server/routes/mesh.py +95 -15
- package/src/superlocalmemory/server/routes/optimize.py +33 -1
- package/src/superlocalmemory/server/routes/prewarm.py +2 -0
- package/src/superlocalmemory/server/routes/profiles.py +63 -17
- package/src/superlocalmemory/server/routes/ratelimit.py +124 -0
- package/src/superlocalmemory/server/routes/rbac.py +367 -0
- package/src/superlocalmemory/server/routes/stats.py +13 -6
- package/src/superlocalmemory/server/routes/tiers.py +11 -9
- package/src/superlocalmemory/server/routes/v3_api.py +183 -69
- package/src/superlocalmemory/server/routes/ws.py +5 -2
- package/src/superlocalmemory/server/security_middleware.py +12 -5
- package/src/superlocalmemory/server/ui.py +20 -5
- package/src/superlocalmemory/server/unified_daemon.py +384 -56
- package/src/superlocalmemory/server/write_identity.py +38 -8
- package/src/superlocalmemory/storage/database.py +265 -53
- package/src/superlocalmemory/storage/migration_runner.py +53 -0
- package/src/superlocalmemory/storage/migrations/M021_ingestion_log_profile.py +108 -0
- package/src/superlocalmemory/storage/migrations/M022_entity_aliases_profile.py +86 -0
- package/src/superlocalmemory/storage/migrations/M023_mesh_profile_isolation.py +194 -0
- package/src/superlocalmemory/storage/migrations/M024_rbac_users_roles.py +87 -0
- package/src/superlocalmemory/storage/migrations/M025_perf_indexes.py +90 -0
- package/src/superlocalmemory/storage/migrations/M026_rbac_memberships_fk.py +136 -0
- package/src/superlocalmemory/storage/migrations/M027_transferable_patterns_profile.py +163 -0
- package/src/superlocalmemory/storage/models.py +4 -0
- package/src/superlocalmemory/storage/schema.py +87 -0
- package/src/superlocalmemory/storage/schema_v343.py +24 -12
- package/src/superlocalmemory/trust/gate.py +49 -8
- package/src/superlocalmemory/ui/assets/slm-icon-white.svg +64 -0
- package/src/superlocalmemory/ui/assets/slm-icon.svg +36 -0
- package/src/superlocalmemory/ui/css/design-system.css +621 -0
- package/src/superlocalmemory/ui/css/neural-glass.css +6 -0
- package/src/superlocalmemory/ui/css/od-bridge.css +158 -0
- package/src/superlocalmemory/ui/favicon.svg +35 -4
- package/src/superlocalmemory/ui/index.html +306 -173
- package/src/superlocalmemory/ui/js/brain.js +5 -20
- package/src/superlocalmemory/ui/js/core.js +47 -31
- package/src/superlocalmemory/ui/js/dashboard.js +314 -63
- package/src/superlocalmemory/ui/js/event-delegation.js +102 -0
- package/src/superlocalmemory/ui/js/knowledge-graph.js +11 -11
- package/src/superlocalmemory/ui/js/math-health.js +1 -1
- package/src/superlocalmemory/ui/js/memories.js +15 -4
- package/src/superlocalmemory/ui/js/memory-chat.js +7 -7
- package/src/superlocalmemory/ui/js/ng-entities.js +6 -8
- package/src/superlocalmemory/ui/js/ng-ingestion.js +4 -4
- package/src/superlocalmemory/ui/js/ng-mesh.js +4 -9
- package/src/superlocalmemory/ui/js/ng-shell.js +8 -8
- package/src/superlocalmemory/ui/js/ng-skills.js +54 -2
- package/src/superlocalmemory/ui/js/od-agents.js +544 -0
- package/src/superlocalmemory/ui/js/od-auth-gate.js +257 -0
- package/src/superlocalmemory/ui/js/od-backup.js +780 -0
- package/src/superlocalmemory/ui/js/od-brain.js +779 -0
- package/src/superlocalmemory/ui/js/od-entities.js +579 -0
- package/src/superlocalmemory/ui/js/od-graph.js +593 -0
- package/src/superlocalmemory/ui/js/od-health.js +539 -0
- package/src/superlocalmemory/ui/js/od-mcp.js +508 -0
- package/src/superlocalmemory/ui/js/od-memories.js +887 -0
- package/src/superlocalmemory/ui/js/od-mesh.js +539 -0
- package/src/superlocalmemory/ui/js/od-operations.js +1250 -0
- package/src/superlocalmemory/ui/js/od-optimize.js +787 -0
- package/src/superlocalmemory/ui/js/od-settings.js +1053 -0
- package/src/superlocalmemory/ui/js/od-shell.js +593 -0
- package/src/superlocalmemory/ui/js/od-skills.js +573 -0
- package/src/superlocalmemory/ui/js/od-team.js +258 -0
- package/src/superlocalmemory/ui/js/profiles.js +159 -46
- package/src/superlocalmemory/ui/js/settings.js +2 -2
- package/src/superlocalmemory/ui/js/timeline.js +34 -5
- package/src/superlocalmemory/ui/js/trust-dashboard.js +2 -2
- package/src/superlocalmemory/vector/lancedb_backend.py +8 -6
- package/src/superlocalmemory/learning/behavioral_listener.py +0 -94
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
// od-auth-gate.js — product-wide login gate (v3.8.0)
|
|
2
|
+
//
|
|
3
|
+
// Personal mode (require_login = false): no gate — the loopback machine owner
|
|
4
|
+
// is trusted, exactly as before. Backward compatible: single-operator users
|
|
5
|
+
// never see a login screen.
|
|
6
|
+
//
|
|
7
|
+
// Company/Enterprise mode (require_login = true):
|
|
8
|
+
// * First run (user_count == 0): a "Create admin" screen. The operator picks
|
|
9
|
+
// the username AND password — SLM ships NO default credentials and never
|
|
10
|
+
// writes a plaintext password to disk (the backend stores an scrypt hash).
|
|
11
|
+
// * Thereafter: a "Sign in" screen unless the caller already holds a valid
|
|
12
|
+
// HttpOnly session cookie (set by POST /api/rbac/login).
|
|
13
|
+
//
|
|
14
|
+
// The gate is UX + attribution only. The daemon independently enforces auth on
|
|
15
|
+
// every sensitive read/mutation server-side, so this screen fails OPEN on a
|
|
16
|
+
// transient status error (never locks the operator out of a working daemon).
|
|
17
|
+
//
|
|
18
|
+
// CSP-safe: no inline handlers, no on*= attributes — every control is wired via
|
|
19
|
+
// addEventListener. All server-supplied text is inserted via textContent.
|
|
20
|
+
//
|
|
21
|
+
// Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar — AGPL-3.0
|
|
22
|
+
|
|
23
|
+
/* global window, document, fetch */
|
|
24
|
+
(function () {
|
|
25
|
+
'use strict';
|
|
26
|
+
|
|
27
|
+
var OVERLAY_ID = 'slm-auth-gate';
|
|
28
|
+
|
|
29
|
+
// ─── DOM helpers (CSP-safe, XSS-safe) ───────────────────────────────────────
|
|
30
|
+
function elmt(tag, opts) {
|
|
31
|
+
opts = opts || {};
|
|
32
|
+
var e = document.createElement(tag);
|
|
33
|
+
if (opts.cls) e.className = opts.cls;
|
|
34
|
+
if (opts.id) e.id = opts.id;
|
|
35
|
+
if (opts.text != null) e.textContent = String(opts.text);
|
|
36
|
+
if (opts.type) e.type = opts.type;
|
|
37
|
+
if (opts.placeholder) e.placeholder = opts.placeholder;
|
|
38
|
+
if (opts.autocomplete) e.setAttribute('autocomplete', opts.autocomplete);
|
|
39
|
+
if (opts.style) e.style.cssText = opts.style;
|
|
40
|
+
if (opts.attrs) {
|
|
41
|
+
Object.keys(opts.attrs).forEach(function (k) { e.setAttribute(k, opts.attrs[k]); });
|
|
42
|
+
}
|
|
43
|
+
return e;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function overlay() {
|
|
47
|
+
var d = document.getElementById(OVERLAY_ID);
|
|
48
|
+
if (d) return d;
|
|
49
|
+
d = elmt('div', {
|
|
50
|
+
id: OVERLAY_ID,
|
|
51
|
+
attrs: { role: 'dialog', 'aria-modal': 'true', 'aria-label': 'Sign in' },
|
|
52
|
+
style: [
|
|
53
|
+
'position:fixed', 'inset:0', 'z-index:100000',
|
|
54
|
+
'display:flex', 'align-items:center', 'justify-content:center',
|
|
55
|
+
'background:#0b0d10', 'background:var(--bg,#0b0d10)',
|
|
56
|
+
'padding:24px',
|
|
57
|
+
].join(';'),
|
|
58
|
+
});
|
|
59
|
+
document.body.appendChild(d);
|
|
60
|
+
return d;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function removeOverlay() {
|
|
64
|
+
var d = document.getElementById(OVERLAY_ID);
|
|
65
|
+
if (d && d.parentNode) d.parentNode.removeChild(d);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function card() {
|
|
69
|
+
var c = elmt('div', {
|
|
70
|
+
style: [
|
|
71
|
+
'width:100%', 'max-width:380px',
|
|
72
|
+
'background:#16181d', 'background:var(--card,#16181d)',
|
|
73
|
+
'border:1px solid rgba(255,255,255,0.08)', 'border-radius:14px',
|
|
74
|
+
'padding:28px', 'box-shadow:0 12px 40px rgba(0,0,0,0.45)',
|
|
75
|
+
'color:#e8eaed', 'color:var(--text,#e8eaed)',
|
|
76
|
+
'font-family:Inter,system-ui,sans-serif',
|
|
77
|
+
].join(';'),
|
|
78
|
+
});
|
|
79
|
+
var brand = elmt('div', { style: 'display:flex;align-items:center;gap:10px;margin-bottom:18px' });
|
|
80
|
+
var logo = elmt('img', { attrs: { src: 'static/assets/slm-icon.svg', alt: '', width: '28', height: '28' } });
|
|
81
|
+
var name = elmt('div');
|
|
82
|
+
name.appendChild(elmt('div', { text: 'SuperLocalMemory', style: 'font-weight:650;font-size:15px' }));
|
|
83
|
+
name.appendChild(elmt('div', { text: 'by Qualixar', style: 'font-size:12px;opacity:0.6' }));
|
|
84
|
+
brand.appendChild(logo);
|
|
85
|
+
brand.appendChild(name);
|
|
86
|
+
c.appendChild(brand);
|
|
87
|
+
return c;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function field(labelText, inputOpts) {
|
|
91
|
+
var wrap = elmt('div', { style: 'margin-bottom:12px' });
|
|
92
|
+
var lbl = elmt('label', { text: labelText, style: 'display:block;font-size:12px;opacity:0.75;margin-bottom:4px' });
|
|
93
|
+
var input = elmt('input', inputOpts);
|
|
94
|
+
input.style.cssText = [
|
|
95
|
+
'width:100%', 'box-sizing:border-box', 'padding:9px 11px',
|
|
96
|
+
'background:rgba(255,255,255,0.05)', 'border:1px solid rgba(255,255,255,0.12)',
|
|
97
|
+
'border-radius:8px', 'color:inherit', 'font-size:14px',
|
|
98
|
+
].join(';');
|
|
99
|
+
if (inputOpts && inputOpts.id) lbl.setAttribute('for', inputOpts.id);
|
|
100
|
+
wrap.appendChild(lbl);
|
|
101
|
+
wrap.appendChild(input);
|
|
102
|
+
return wrap;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function primaryBtn(text) {
|
|
106
|
+
var b = elmt('button', { text: text, type: 'button' });
|
|
107
|
+
b.style.cssText = [
|
|
108
|
+
'width:100%', 'padding:10px', 'margin-top:6px', 'border:none',
|
|
109
|
+
'border-radius:8px', 'background:#6c5ce7', 'background:var(--violet,#6c5ce7)',
|
|
110
|
+
'color:#fff', 'font-size:14px', 'font-weight:600', 'cursor:pointer',
|
|
111
|
+
].join(';');
|
|
112
|
+
return b;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function msgLine() {
|
|
116
|
+
return elmt('p', { style: 'font-size:12.5px;margin:10px 0 0;min-height:16px;color:#ff7b7b' });
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// ─── API (uses the globally patched fetch: X-Install-Token on POST) ──────────
|
|
120
|
+
function api(url, method, body) {
|
|
121
|
+
var init = { method: method || 'GET', credentials: 'same-origin' };
|
|
122
|
+
if (body) {
|
|
123
|
+
init.headers = { 'Content-Type': 'application/json' };
|
|
124
|
+
init.body = JSON.stringify(body);
|
|
125
|
+
}
|
|
126
|
+
return fetch(url, init).then(function (r) {
|
|
127
|
+
return r.json().catch(function () { return {}; }).then(function (d) {
|
|
128
|
+
return { ok: r.ok, status: r.status, data: d };
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// ─── Screens ────────────────────────────────────────────────────────────────
|
|
134
|
+
function showSpinner() {
|
|
135
|
+
var o = overlay();
|
|
136
|
+
o.textContent = '';
|
|
137
|
+
var c = card();
|
|
138
|
+
c.appendChild(elmt('p', { text: 'Checking access…', style: 'opacity:0.7;font-size:13px;margin:0' }));
|
|
139
|
+
o.appendChild(c);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function showLogin(prefillMsg) {
|
|
143
|
+
var o = overlay();
|
|
144
|
+
o.textContent = '';
|
|
145
|
+
var c = card();
|
|
146
|
+
c.appendChild(elmt('h2', { text: 'Sign in', style: 'font-size:18px;margin:0 0 6px' }));
|
|
147
|
+
c.appendChild(elmt('p', {
|
|
148
|
+
text: 'Use the admin username and password created when this workspace '
|
|
149
|
+
+ 'was set up. SuperLocalMemory has no default password. Forgot it? '
|
|
150
|
+
+ 'An admin can reset it from Settings › Access.',
|
|
151
|
+
style: 'font-size:12.5px;opacity:0.7;margin:0 0 16px',
|
|
152
|
+
}));
|
|
153
|
+
var user = { id: 'slm-gate-user', placeholder: 'Username', autocomplete: 'username' };
|
|
154
|
+
var pass = { id: 'slm-gate-pass', type: 'password', placeholder: 'Password', autocomplete: 'current-password' };
|
|
155
|
+
c.appendChild(field('Username', user));
|
|
156
|
+
c.appendChild(field('Password', pass));
|
|
157
|
+
var btn = primaryBtn('Sign in');
|
|
158
|
+
var msg = msgLine();
|
|
159
|
+
if (prefillMsg) { msg.style.color = '#7bd88f'; msg.textContent = prefillMsg; }
|
|
160
|
+
c.appendChild(btn);
|
|
161
|
+
c.appendChild(msg);
|
|
162
|
+
o.appendChild(c);
|
|
163
|
+
|
|
164
|
+
function submit() {
|
|
165
|
+
var u = (document.getElementById('slm-gate-user') || {}).value || '';
|
|
166
|
+
var p = (document.getElementById('slm-gate-pass') || {}).value || '';
|
|
167
|
+
if (!u || !p) { msg.style.color = '#ff7b7b'; msg.textContent = 'Enter your username and password.'; return; }
|
|
168
|
+
btn.disabled = true;
|
|
169
|
+
api('/api/rbac/login', 'POST', { username: u, password: p }).then(function (r) {
|
|
170
|
+
btn.disabled = false;
|
|
171
|
+
if (r.ok) { window.location.reload(); return; }
|
|
172
|
+
msg.style.color = '#ff7b7b';
|
|
173
|
+
msg.textContent = (r.data && r.data.detail) || 'Sign in failed.';
|
|
174
|
+
}).catch(function () {
|
|
175
|
+
btn.disabled = false;
|
|
176
|
+
msg.style.color = '#ff7b7b';
|
|
177
|
+
msg.textContent = 'Could not reach the daemon.';
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
btn.addEventListener('click', submit);
|
|
181
|
+
c.addEventListener('keydown', function (e) { if (e.key === 'Enter') submit(); });
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function showCreateAdmin() {
|
|
185
|
+
var o = overlay();
|
|
186
|
+
o.textContent = '';
|
|
187
|
+
var c = card();
|
|
188
|
+
c.appendChild(elmt('h2', { text: 'Welcome — create your admin account', style: 'font-size:18px;margin:0 0 6px' }));
|
|
189
|
+
c.appendChild(elmt('p', {
|
|
190
|
+
text: 'This is the first time SuperLocalMemory has opened on this '
|
|
191
|
+
+ 'workspace. Choose an admin username and password right here in your '
|
|
192
|
+
+ 'browser — no config files or terminal needed. For your security '
|
|
193
|
+
+ 'there is no default login. You can add people or change this later '
|
|
194
|
+
+ 'under Settings › Access.',
|
|
195
|
+
style: 'font-size:12.5px;opacity:0.7;margin:0 0 16px',
|
|
196
|
+
}));
|
|
197
|
+
c.appendChild(field('Username', { id: 'slm-gate-nu', placeholder: 'e.g. admin', autocomplete: 'username' }));
|
|
198
|
+
c.appendChild(field('Display name (optional)', { id: 'slm-gate-nn', placeholder: 'Full name', autocomplete: 'name' }));
|
|
199
|
+
c.appendChild(field('Password (min 8 characters)', { id: 'slm-gate-np', type: 'password', placeholder: 'Password', autocomplete: 'new-password' }));
|
|
200
|
+
c.appendChild(field('Confirm password', { id: 'slm-gate-nc', type: 'password', placeholder: 'Re-enter password', autocomplete: 'new-password' }));
|
|
201
|
+
var btn = primaryBtn('Create admin & sign in');
|
|
202
|
+
var msg = msgLine();
|
|
203
|
+
c.appendChild(btn);
|
|
204
|
+
c.appendChild(msg);
|
|
205
|
+
o.appendChild(c);
|
|
206
|
+
|
|
207
|
+
function submit() {
|
|
208
|
+
var u = (document.getElementById('slm-gate-nu') || {}).value || '';
|
|
209
|
+
var n = (document.getElementById('slm-gate-nn') || {}).value || '';
|
|
210
|
+
var p = (document.getElementById('slm-gate-np') || {}).value || '';
|
|
211
|
+
var cc = (document.getElementById('slm-gate-nc') || {}).value || '';
|
|
212
|
+
if (!u) { msg.textContent = 'Choose a username.'; return; }
|
|
213
|
+
if (p.length < 8) { msg.textContent = 'Password must be at least 8 characters.'; return; }
|
|
214
|
+
if (p !== cc) { msg.textContent = 'Passwords do not match.'; return; }
|
|
215
|
+
btn.disabled = true;
|
|
216
|
+
api('/api/rbac/users', 'POST', { username: u, password: p, display_name: n, role: 'admin' })
|
|
217
|
+
.then(function (r) {
|
|
218
|
+
if (!r.ok) {
|
|
219
|
+
btn.disabled = false;
|
|
220
|
+
msg.style.color = '#ff7b7b';
|
|
221
|
+
msg.textContent = (r.data && r.data.detail) || 'Could not create the admin account.';
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
// Auto sign-in so the operator lands straight in the dashboard.
|
|
225
|
+
return api('/api/rbac/login', 'POST', { username: u, password: p }).then(function () {
|
|
226
|
+
window.location.reload();
|
|
227
|
+
});
|
|
228
|
+
}).catch(function () {
|
|
229
|
+
btn.disabled = false;
|
|
230
|
+
msg.style.color = '#ff7b7b';
|
|
231
|
+
msg.textContent = 'Could not reach the daemon.';
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
btn.addEventListener('click', submit);
|
|
235
|
+
c.addEventListener('keydown', function (e) { if (e.key === 'Enter') submit(); });
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// ─── Decision flow ──────────────────────────────────────────────────────────
|
|
239
|
+
function decide() {
|
|
240
|
+
api('/api/rbac/status', 'GET').then(function (r) {
|
|
241
|
+
var s = (r && r.data) || {};
|
|
242
|
+
if (!r.ok || !s.require_login) { removeOverlay(); return; } // Personal mode
|
|
243
|
+
if ((s.user_count || 0) === 0) { showCreateAdmin(); return; } // First run
|
|
244
|
+
api('/api/rbac/whoami', 'GET').then(function (w) {
|
|
245
|
+
var who = (w && w.data) || {};
|
|
246
|
+
if (w.ok && who.kind === 'user') { removeOverlay(); return; } // Already signed in
|
|
247
|
+
showLogin();
|
|
248
|
+
}).catch(function () { removeOverlay(); }); // Fail open
|
|
249
|
+
}).catch(function () { removeOverlay(); }); // Fail open
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// Paint the overlay immediately (this script is at end of <body>, so body
|
|
253
|
+
// exists) to avoid flashing dashboard content to unauthenticated users in
|
|
254
|
+
// company mode, then resolve the real state.
|
|
255
|
+
showSpinner();
|
|
256
|
+
decide();
|
|
257
|
+
}());
|