total-recall-brain 3.40.1 → 3.40.2

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.
Files changed (186) hide show
  1. package/README.md +152 -41
  2. package/bin/total-recall.mjs +16 -76
  3. package/docs/reference/cli-reference.md +10 -10
  4. package/extension/background.js +6 -2
  5. package/extension/config.js +8 -0
  6. package/extension/lib/brain-client.js +29 -4
  7. package/extension/options/options.html +1 -0
  8. package/extension/sidepanel/sidepanel.html +1 -0
  9. package/frontend/dist/assets/{index-CvQRdT2j.css → index-AGUes-VG.css} +1 -1
  10. package/frontend/dist/assets/index-Bt5iVPZj.js +5618 -0
  11. package/frontend/dist/index.html +2 -2
  12. package/frontend/src/api/keys.ts +9 -2
  13. package/frontend/src/api/plugins.ts +4 -0
  14. package/frontend/src/components/plugins/card/CardEngine.tsx +2 -1
  15. package/frontend/src/components/plugins/card/card.css +1 -1
  16. package/frontend/src/pages/IntegrationsPage.tsx +315 -8
  17. package/frontend/src/pages/PluginsPage.tsx +532 -87
  18. package/package.json +6 -5
  19. package/scaffold/.agent/skills/meta-harness/references/optimized/original.md +1 -1
  20. package/scaffold/.agent/skills/meta-harness/references/optimized/section-09.md +1 -1
  21. package/scaffold/.agent/skills/total-recall/plugins/auth/package-lock.json +10 -10
  22. package/scaffold/.agent/skills/total-recall/plugins/auth/package.json +1 -6
  23. package/scaffold/.agent/skills/total-recall/plugins/auth/plugin.json +0 -1
  24. package/scaffold/.agent/skills/total-recall/plugins/auth/src/browser-session.mjs +309 -4
  25. package/scaffold/.agent/skills/total-recall/plugins/auth/src/cli-secret.mjs +44 -34
  26. package/scaffold/.agent/skills/total-recall/plugins/auth/src/google-oauth.mjs +6 -4
  27. package/scaffold/.agent/skills/total-recall/plugins/auth/src/provider-catalog.mjs +1 -1
  28. package/scaffold/.agent/skills/total-recall/plugins/auth/src/provider-rotation-recipes.mjs +118 -4
  29. package/scaffold/.agent/skills/total-recall/plugins/auth/src/routes/auth.mjs +2 -2
  30. package/scaffold/.agent/skills/total-recall/plugins/auth/src/secrets-env-export.mjs +3 -3
  31. package/scaffold/.agent/skills/total-recall/plugins/auth/src/secrets-remote-deploy.mjs +1 -1
  32. package/scaffold/.agent/skills/total-recall/plugins/auth/src/secrets-rotate.mjs +24 -6
  33. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/card.js +164 -123
  34. package/scaffold/.agent/skills/total-recall/plugins/cli-agents/README.md +65 -0
  35. package/scaffold/.agent/skills/total-recall/plugins/cli-agents/cli.mjs +76 -0
  36. package/scaffold/.agent/skills/total-recall/plugins/cli-agents/package.json +19 -0
  37. package/scaffold/.agent/skills/total-recall/plugins/cli-agents/plugin.json +290 -0
  38. package/scaffold/.agent/skills/total-recall/plugins/cli-agents/src/adapters/dsh.mjs +446 -0
  39. package/scaffold/.agent/skills/total-recall/plugins/cli-agents/src/documentation.mjs +152 -0
  40. package/scaffold/.agent/skills/total-recall/plugins/cli-agents/src/executor.mjs +71 -0
  41. package/scaffold/.agent/skills/total-recall/plugins/cli-agents/src/runtime.mjs +36 -0
  42. package/scaffold/.agent/skills/total-recall/plugins/cli-agents/src/setup.mjs +35 -0
  43. package/scaffold/.agent/skills/total-recall/plugins/cli-agents/src/worker.mjs +175 -0
  44. package/scaffold/.agent/skills/total-recall/plugins/cli-agents/ui/card.js +18 -0
  45. package/scaffold/.agent/skills/total-recall/plugins/code-quality/LICENSE +21 -0
  46. package/scaffold/.agent/skills/total-recall/plugins/code-quality/README.md +84 -0
  47. package/scaffold/.agent/skills/total-recall/plugins/code-quality/cli.mjs +79 -0
  48. package/scaffold/.agent/skills/total-recall/plugins/code-quality/commands/check.mjs +6 -0
  49. package/scaffold/.agent/skills/total-recall/plugins/code-quality/commands/report.mjs +6 -0
  50. package/scaffold/.agent/skills/total-recall/plugins/code-quality/commands/run-core.mjs +27 -0
  51. package/scaffold/.agent/skills/total-recall/plugins/code-quality/commands/snapshot.mjs +163 -0
  52. package/scaffold/.agent/skills/total-recall/plugins/code-quality/core/check.mjs +757 -0
  53. package/scaffold/.agent/skills/total-recall/plugins/code-quality/core/config.schema.json +86 -0
  54. package/scaffold/.agent/skills/total-recall/plugins/code-quality/core/detect.mjs +89 -0
  55. package/scaffold/.agent/skills/total-recall/plugins/code-quality/core/report-data.mjs +145 -0
  56. package/scaffold/.agent/skills/total-recall/plugins/code-quality/core/report.mjs +210 -0
  57. package/scaffold/.agent/skills/total-recall/plugins/code-quality/core/state.mjs +20 -0
  58. package/scaffold/.agent/skills/total-recall/plugins/code-quality/package-lock.json +2869 -0
  59. package/scaffold/.agent/skills/total-recall/plugins/code-quality/package.json +28 -0
  60. package/scaffold/.agent/skills/total-recall/plugins/code-quality/plugin.json +186 -0
  61. package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/DESIGN.md +18 -0
  62. package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/card.js +272 -0
  63. package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/code-quality-report.mjs +129 -0
  64. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/LICENSE +21 -0
  65. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/README.md +73 -0
  66. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/cli.mjs +375 -0
  67. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/examples/commands/echo-tool.mjs +23 -0
  68. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/examples/commands/group.mjs +262 -0
  69. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/examples/commands/project-id.mjs +74 -0
  70. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/package-lock.json +2869 -0
  71. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/package.json +31 -0
  72. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/plugin.json +221 -0
  73. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/schemas/cli_command.schema.json +107 -0
  74. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/skills/composable-cli/SKILL.md +63 -0
  75. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/src/command.mjs +313 -0
  76. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/src/compile.mjs +19 -0
  77. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/src/compose.mjs +144 -0
  78. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/src/contract.mjs +110 -0
  79. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/src/library.mjs +23 -0
  80. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/src/registry.mjs +192 -0
  81. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/src/resolve.mjs +221 -0
  82. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/src/risk.mjs +126 -0
  83. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/src/ssss-documents.mjs +29 -0
  84. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/DESIGN.md +18 -0
  85. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/card.js +273 -0
  86. package/scaffold/.agent/skills/total-recall/plugins/embeddings/LICENSE +21 -0
  87. package/scaffold/.agent/skills/total-recall/plugins/embeddings/README.md +20 -0
  88. package/scaffold/.agent/skills/total-recall/plugins/embeddings/cli.mjs +310 -0
  89. package/scaffold/.agent/skills/total-recall/plugins/embeddings/package-lock.json +2826 -0
  90. package/scaffold/.agent/skills/total-recall/plugins/embeddings/package.json +11 -0
  91. package/scaffold/.agent/skills/total-recall/plugins/embeddings/plugin.json +62 -0
  92. package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/card.js +297 -0
  93. package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/LICENSE +21 -0
  94. package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/README.md +43 -0
  95. package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/cli.mjs +258 -0
  96. package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/package-lock.json +4005 -0
  97. package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/package.json +20 -0
  98. package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/plugin.json +125 -0
  99. package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/ui/DESIGN.md +18 -0
  100. package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/ui/card.js +278 -0
  101. package/scaffold/.agent/skills/total-recall/plugins/mesh/README.md +9 -0
  102. package/scaffold/.agent/skills/total-recall/plugins/mesh/cli.mjs +6 -0
  103. package/scaffold/.agent/skills/total-recall/plugins/mesh/package-lock.json +4721 -0
  104. package/scaffold/.agent/skills/total-recall/plugins/mesh/package.json +3 -21
  105. package/scaffold/.agent/skills/total-recall/plugins/mesh/plugin.json +14 -1
  106. package/scaffold/.agent/skills/total-recall/plugins/mesh/src/cli/mesh.mjs +10 -0
  107. package/scaffold/.agent/skills/total-recall/plugins/mesh/src/core/headscale-client.mjs +5 -1
  108. package/scaffold/.agent/skills/total-recall/plugins/mesh/src/core/leader-election.mjs +4 -13
  109. package/scaffold/.agent/skills/total-recall/plugins/mesh/src/core/mesh-access-verify.mjs +22 -0
  110. package/scaffold/.agent/skills/total-recall/plugins/mesh/src/core/mesh-files.mjs +18 -0
  111. package/scaffold/.agent/skills/total-recall/plugins/mesh/src/core/mesh.mjs +2 -0
  112. package/scaffold/.agent/skills/total-recall/plugins/mesh/test-support/memory-root.mjs +14 -0
  113. package/scaffold/.agent/skills/total-recall/plugins/openwiki/LICENSE +21 -0
  114. package/scaffold/.agent/skills/total-recall/plugins/openwiki/README.md +35 -0
  115. package/scaffold/.agent/skills/total-recall/plugins/openwiki/cli.mjs +124 -0
  116. package/scaffold/.agent/skills/total-recall/plugins/openwiki/package-lock.json +4097 -0
  117. package/scaffold/.agent/skills/total-recall/plugins/openwiki/package.json +12 -0
  118. package/scaffold/.agent/skills/total-recall/plugins/openwiki/plugin.json +165 -0
  119. package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/ingest.mjs +127 -0
  120. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/DESIGN.md +18 -0
  121. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/card.js +279 -0
  122. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/panel.js +539 -0
  123. package/scaffold/.agent/skills/total-recall/plugins/security/LICENSE +21 -0
  124. package/scaffold/.agent/skills/total-recall/plugins/security/README.md +67 -0
  125. package/scaffold/.agent/skills/total-recall/plugins/security/cli.mjs +932 -0
  126. package/scaffold/.agent/skills/total-recall/plugins/security/package-lock.json +3256 -0
  127. package/scaffold/.agent/skills/total-recall/plugins/security/package.json +25 -0
  128. package/scaffold/.agent/skills/total-recall/plugins/security/plugin.json +297 -0
  129. package/scaffold/.agent/skills/total-recall/plugins/security/scripts/build-ui.mjs +4 -0
  130. package/scaffold/.agent/skills/total-recall/plugins/security/skills/security/SKILL.md +37 -0
  131. package/scaffold/.agent/skills/total-recall/plugins/security/src/android.mjs +21 -0
  132. package/scaffold/.agent/skills/total-recall/plugins/security/src/devices.mjs +94 -0
  133. package/scaffold/.agent/skills/total-recall/plugins/security/src/machines.mjs +164 -0
  134. package/scaffold/.agent/skills/total-recall/plugins/security/src/scanner.mjs +41 -0
  135. package/scaffold/.agent/skills/total-recall/plugins/security/src/windows.mjs +42 -0
  136. package/scaffold/.agent/skills/total-recall/plugins/security/ui/DESIGN.md +18 -0
  137. package/scaffold/.agent/skills/total-recall/plugins/security/ui/card.js +95 -0
  138. package/scaffold/.agent/skills/total-recall/plugins/security/ui/panel.js +98 -0
  139. package/scaffold/.agent/skills/total-recall/references/auth.md +1 -1
  140. package/src/cli/brief.mjs +33 -9
  141. package/src/cli/command.mjs +2 -7
  142. package/src/cli/config.mjs +1 -0
  143. package/src/cli/connect.mjs +5 -0
  144. package/src/cli/context.mjs +2 -1
  145. package/src/cli/daemon.mjs +36 -1
  146. package/src/cli/doctor.mjs +6 -0
  147. package/src/cli/harness.mjs +3 -0
  148. package/src/cli/help.mjs +26 -0
  149. package/src/cli/init.mjs +4 -4
  150. package/src/cli/memory-entry.mjs +1 -0
  151. package/src/cli/memory-init.mjs +2 -0
  152. package/src/cli/plugin/index.mjs +11 -0
  153. package/src/cli/plugin/install.mjs +2 -1
  154. package/src/cli/rebuild.mjs +3 -1
  155. package/src/cli/startup.mjs +2 -1
  156. package/src/cli/update.mjs +19 -0
  157. package/src/core/automatic-brain-updates.mjs +67 -0
  158. package/src/core/brain-updates.mjs +21 -2
  159. package/src/core/cli-commands.mjs +71 -0
  160. package/src/core/cli-maintenance.mjs +45 -0
  161. package/src/core/cli-quick-reference.mjs +20 -0
  162. package/src/core/cli-semantic-index.mjs +722 -0
  163. package/src/core/context-compiler.mjs +27 -1
  164. package/src/core/crons.mjs +2 -13
  165. package/src/core/daemon-control.mjs +6 -4
  166. package/src/core/daemon-loop.mjs +12 -8
  167. package/src/core/default-plugins.mjs +5 -0
  168. package/src/core/global-brain-updates.mjs +39 -0
  169. package/src/core/mesh-brain-updates.mjs +30 -0
  170. package/src/core/meta-harness.mjs +108 -0
  171. package/src/core/plugin-dependencies.mjs +2 -1
  172. package/src/core/plugin-loader.mjs +2 -1
  173. package/src/core/plugin-runner.mjs +12 -4
  174. package/src/core/plugin-setup.mjs +20 -0
  175. package/src/core/plugin-store.mjs +22 -4
  176. package/src/core/plugin-tasks.mjs +1 -1
  177. package/src/core/project-brain.mjs +2 -0
  178. package/src/core/project-status.mjs +64 -0
  179. package/src/core/required-plugins.mjs +46 -0
  180. package/src/core/scaffold-plugins.mjs +17 -3
  181. package/src/core/source-brain-updates.mjs +47 -0
  182. package/src/core/startup-health.mjs +5 -3
  183. package/src/core/surface.mjs +44 -10
  184. package/src/server/routes/extension.mjs +53 -8
  185. package/templates/onboarding-interview.md +1 -1
  186. package/frontend/dist/assets/index-SOVUlZqm.js +0 -5596
@@ -0,0 +1,539 @@
1
+ // OpenWiki Interactive Knowledge Graph & Engine Panel
2
+ // Provides full knowledge graph node inspection, hub directory browsing,
3
+ // ingestion triggers, and secure API credential storage.
4
+ class OpenwikiPanel extends HTMLElement {
5
+ constructor() {
6
+ super();
7
+ this.attachShadow({ mode: 'open' });
8
+ this._view = null;
9
+ this._activeTab = 'graph';
10
+ this._searchQuery = '';
11
+ this._selectedCategory = 'all';
12
+ this._selectedNode = null;
13
+ this._ingestOutput = '';
14
+ this._nodes = [];
15
+ this._loading = false;
16
+ }
17
+
18
+ set host(h) {
19
+ this._host = h;
20
+ this._loadLiveNodes();
21
+ }
22
+
23
+ get host() {
24
+ return this._host;
25
+ }
26
+
27
+ connectedCallback() {
28
+ this._loadLiveNodes();
29
+ this.render();
30
+ }
31
+
32
+ async _loadLiveNodes() {
33
+ if (this._loading) return;
34
+ this._loading = true;
35
+ try {
36
+ if (this._host && typeof this._host.run === 'function') {
37
+ const res = await this._host.run('hubs', ['--json']);
38
+ if (res && res.output) {
39
+ const parsed = JSON.parse(res.output);
40
+ if (parsed && Array.isArray(parsed.hubs) && parsed.hubs.length > 0) {
41
+ this._nodes = parsed.hubs.map((h) => ({
42
+ slug: h.path,
43
+ title: h.title,
44
+ category: 'hub',
45
+ importance: 3,
46
+ priority: 'normal',
47
+ tags: ['openwiki', 'hub', 'documentation'],
48
+ body: `Path: ${h.path}\nSize: ${h.size_bytes} bytes\nLines: ${h.lines}`
49
+ }));
50
+ this.render();
51
+ return;
52
+ }
53
+ }
54
+ }
55
+
56
+ const res = await fetch('/api/memory?tag=openwiki', { signal: AbortSignal.timeout(3000) });
57
+ if (res.ok) {
58
+ const data = await res.json();
59
+ const items = Array.isArray(data) ? data : (data.nodes || []);
60
+ if (items.length > 0) {
61
+ this._nodes = items.map((n) => ({
62
+ slug: n.slug || n.id || 'node',
63
+ title: n.title || 'Untitled Node',
64
+ category: n.category || 'fact',
65
+ importance: n.importance || 3,
66
+ priority: n.priority || 'medium',
67
+ tags: n.tags || [],
68
+ body: n.body || n.content || ''
69
+ }));
70
+ this.render();
71
+ }
72
+ }
73
+ } catch {
74
+ // Retain live empty state honestly
75
+ } finally {
76
+ this._loading = false;
77
+ }
78
+ }
79
+
80
+ set view(value) {
81
+ this._view = value;
82
+ this.render();
83
+ }
84
+
85
+ get view() {
86
+ return this._view;
87
+ }
88
+
89
+ connectedCallback() {
90
+ this.render();
91
+ }
92
+
93
+ _filterNodes() {
94
+ return this._nodes.filter((node) => {
95
+ const matchCat = this._selectedCategory === 'all' || node.category === this._selectedCategory;
96
+ const q = this._searchQuery.toLowerCase();
97
+ const matchQuery = !q || node.title.toLowerCase().includes(q) || node.body.toLowerCase().includes(q) || node.tags.some((t) => t.toLowerCase().includes(q));
98
+ return matchCat && matchQuery;
99
+ });
100
+ }
101
+
102
+ render() {
103
+ const root = this.shadowRoot;
104
+ if (!root) return;
105
+ root.replaceChildren();
106
+
107
+ const present = Boolean(this._view && this._view.present);
108
+ const filteredNodes = this._filterNodes();
109
+
110
+ const style = document.createElement('style');
111
+ style.textContent = `
112
+ :host {
113
+ display: block;
114
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
115
+ color: var(--color-text, #f8fafc);
116
+ background: var(--color-surface, #0f172a);
117
+ border: 1px solid var(--color-border, #1e293b);
118
+ border-radius: var(--radius-md, 8px);
119
+ padding: 16px;
120
+ box-sizing: border-box;
121
+ }
122
+ * { box-sizing: border-box; }
123
+ .header {
124
+ display: flex;
125
+ justify-content: space-between;
126
+ align-items: center;
127
+ border-bottom: 1px solid var(--color-border, #1e293b);
128
+ padding-bottom: 12px;
129
+ margin-bottom: 16px;
130
+ }
131
+ .title {
132
+ font-size: 18px;
133
+ font-weight: 700;
134
+ margin: 0;
135
+ color: #f8fafc;
136
+ display: flex;
137
+ align-items: center;
138
+ gap: 8px;
139
+ }
140
+ .badge {
141
+ font-size: 11px;
142
+ text-transform: uppercase;
143
+ letter-spacing: 0.05em;
144
+ padding: 3px 8px;
145
+ border-radius: 4px;
146
+ background: rgba(180, 83, 9, 0.2);
147
+ color: #f59e0b;
148
+ font-weight: 600;
149
+ }
150
+ .tabs {
151
+ display: flex;
152
+ gap: 8px;
153
+ margin-bottom: 16px;
154
+ }
155
+ .tab-btn {
156
+ min-height: 44px;
157
+ padding: 8px 16px;
158
+ border: 1px solid var(--color-border, #1e293b);
159
+ background: rgba(255, 255, 255, 0.03);
160
+ color: var(--color-text, #94a3b8);
161
+ border-radius: var(--radius-md, 6px);
162
+ font-size: 13px;
163
+ font-weight: 600;
164
+ cursor: pointer;
165
+ display: flex;
166
+ align-items: center;
167
+ justify-content: center;
168
+ transition: all 0.15s ease;
169
+ }
170
+ .tab-btn.active {
171
+ background: #b45309;
172
+ border-color: #d97706;
173
+ color: #ffffff;
174
+ }
175
+ .controls {
176
+ display: flex;
177
+ gap: 8px;
178
+ flex-wrap: wrap;
179
+ margin-bottom: 16px;
180
+ }
181
+ .search-box {
182
+ flex: 1;
183
+ min-height: 44px;
184
+ min-width: 200px;
185
+ padding: 8px 12px;
186
+ background: rgba(0, 0, 0, 0.3);
187
+ border: 1px solid var(--color-border, #1e293b);
188
+ border-radius: var(--radius-md, 6px);
189
+ color: #f8fafc;
190
+ font-size: 13px;
191
+ }
192
+ .filter-select {
193
+ min-height: 44px;
194
+ padding: 8px 12px;
195
+ background: rgba(0, 0, 0, 0.3);
196
+ border: 1px solid var(--color-border, #1e293b);
197
+ border-radius: var(--radius-md, 6px);
198
+ color: #f8fafc;
199
+ font-size: 13px;
200
+ }
201
+ .grid {
202
+ display: grid;
203
+ grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
204
+ gap: 12px;
205
+ margin-bottom: 16px;
206
+ }
207
+ .node-card {
208
+ background: rgba(255, 255, 255, 0.02);
209
+ border: 1px solid var(--color-border, #1e293b);
210
+ border-radius: var(--radius-md, 6px);
211
+ padding: 12px;
212
+ cursor: pointer;
213
+ transition: border-color 0.15s ease;
214
+ }
215
+ .node-card:hover {
216
+ border-color: #b45309;
217
+ }
218
+ .node-title {
219
+ font-size: 14px;
220
+ font-weight: 600;
221
+ margin: 0 0 6px 0;
222
+ color: #f1f5f9;
223
+ }
224
+ .node-cat {
225
+ font-size: 10px;
226
+ text-transform: uppercase;
227
+ font-weight: 700;
228
+ padding: 2px 6px;
229
+ border-radius: 3px;
230
+ display: inline-block;
231
+ margin-bottom: 8px;
232
+ }
233
+ .cat-invariant { background: rgba(239, 68, 68, 0.2); color: #ef4444; }
234
+ .cat-preference { background: rgba(59, 130, 246, 0.2); color: #3b82f6; }
235
+ .cat-fact { background: rgba(16, 185, 129, 0.2); color: #10b981; }
236
+ .cat-concept { background: rgba(245, 158, 11, 0.2); color: #f59e0b; }
237
+ .node-snippet {
238
+ font-size: 12px;
239
+ color: #94a3b8;
240
+ line-height: 1.4;
241
+ margin: 0;
242
+ }
243
+ .detail-pane {
244
+ background: rgba(0, 0, 0, 0.4);
245
+ border: 1px solid #b45309;
246
+ border-radius: var(--radius-md, 6px);
247
+ padding: 16px;
248
+ margin-bottom: 16px;
249
+ }
250
+ .detail-header {
251
+ display: flex;
252
+ justify-content: space-between;
253
+ align-items: flex-start;
254
+ margin-bottom: 12px;
255
+ }
256
+ .detail-title {
257
+ font-size: 16px;
258
+ font-weight: 700;
259
+ margin: 0;
260
+ color: #ffffff;
261
+ }
262
+ .detail-body {
263
+ font-size: 13px;
264
+ line-height: 1.6;
265
+ color: #cbd5e1;
266
+ white-space: pre-wrap;
267
+ }
268
+ .btn {
269
+ min-height: 44px;
270
+ padding: 8px 16px;
271
+ border: 1px solid var(--color-border, #1e293b);
272
+ border-radius: var(--radius-md, 6px);
273
+ background: #b45309;
274
+ color: #ffffff;
275
+ font-weight: 600;
276
+ cursor: pointer;
277
+ font-size: 13px;
278
+ display: inline-flex;
279
+ align-items: center;
280
+ justify-content: center;
281
+ }
282
+ .btn-secondary {
283
+ background: rgba(255, 255, 255, 0.05);
284
+ color: #cbd5e1;
285
+ }
286
+ .row {
287
+ display: flex;
288
+ gap: 8px;
289
+ flex-wrap: wrap;
290
+ margin-top: 12px;
291
+ }
292
+ input[type="text"], input[type="password"] {
293
+ flex: 1;
294
+ min-height: 44px;
295
+ padding: 8px 12px;
296
+ border-radius: var(--radius-md, 6px);
297
+ border: 1px solid var(--color-border, #1e293b);
298
+ background: rgba(0, 0, 0, 0.3);
299
+ color: #f8fafc;
300
+ font-size: 13px;
301
+ }
302
+ .terminal {
303
+ background: #090d16;
304
+ border: 1px solid #1e293b;
305
+ border-radius: 6px;
306
+ padding: 12px;
307
+ font-family: monospace;
308
+ font-size: 12px;
309
+ color: #38bdf8;
310
+ min-height: 60px;
311
+ white-space: pre-wrap;
312
+ margin-top: 12px;
313
+ }
314
+ `;
315
+
316
+ const header = document.createElement('div');
317
+ header.className = 'header';
318
+ header.innerHTML = `
319
+ <div class="title">
320
+ <span>OpenWiki Knowledge Engine</span>
321
+ <span class="badge">Graph Active</span>
322
+ </div>
323
+ `;
324
+
325
+ const tabs = document.createElement('div');
326
+ tabs.className = 'tabs';
327
+
328
+ const tabGraph = document.createElement('button');
329
+ tabGraph.className = `tab-btn ${this._activeTab === 'graph' ? 'active' : ''}`;
330
+ tabGraph.textContent = 'Knowledge Graph';
331
+ tabGraph.onclick = () => { this._activeTab = 'graph'; this.render(); };
332
+
333
+ const tabIngest = document.createElement('button');
334
+ tabIngest.className = `tab-btn ${this._activeTab === 'ingest' ? 'active' : ''}`;
335
+ tabIngest.textContent = 'Ingest Hub';
336
+ tabIngest.onclick = () => { this._activeTab = 'ingest'; this.render(); };
337
+
338
+ const tabConfig = document.createElement('button');
339
+ tabConfig.className = `tab-btn ${this._activeTab === 'config' ? 'active' : ''}`;
340
+ tabConfig.textContent = 'Credentials & Secrets';
341
+ tabConfig.onclick = () => { this._activeTab = 'config'; this.render(); };
342
+
343
+ tabs.append(tabGraph, tabIngest, tabConfig);
344
+
345
+ const mainContainer = document.createElement('div');
346
+
347
+ if (this._activeTab === 'graph') {
348
+ const controls = document.createElement('div');
349
+ controls.className = 'controls';
350
+
351
+ const search = document.createElement('input');
352
+ search.type = 'text';
353
+ search.className = 'search-box';
354
+ search.placeholder = 'Search knowledge graph nodes...';
355
+ search.value = this._searchQuery;
356
+ search.oninput = (e) => {
357
+ this._searchQuery = e.target.value;
358
+ this.render();
359
+ };
360
+
361
+ const select = document.createElement('select');
362
+ select.className = 'filter-select';
363
+ [
364
+ { val: 'all', lbl: 'All Categories' },
365
+ { val: 'invariant', lbl: 'Invariants' },
366
+ { val: 'preference', lbl: 'Preferences' },
367
+ { val: 'fact', lbl: 'Facts' },
368
+ { val: 'concept', lbl: 'Concepts' }
369
+ ].forEach((opt) => {
370
+ const el = document.createElement('option');
371
+ el.value = opt.val;
372
+ el.textContent = opt.lbl;
373
+ el.selected = opt.val === this._selectedCategory;
374
+ select.appendChild(el);
375
+ });
376
+ select.onchange = (e) => {
377
+ this._selectedCategory = e.target.value;
378
+ this.render();
379
+ };
380
+
381
+ controls.append(search, select);
382
+ mainContainer.appendChild(controls);
383
+
384
+ if (this._selectedNode) {
385
+ const detail = document.createElement('div');
386
+ detail.className = 'detail-pane';
387
+
388
+ const dHeader = document.createElement('div');
389
+ dHeader.className = 'detail-header';
390
+
391
+ const dTitle = document.createElement('h4');
392
+ dTitle.className = 'detail-title';
393
+ dTitle.textContent = this._selectedNode.title;
394
+
395
+ const closeBtn = document.createElement('button');
396
+ closeBtn.className = 'btn btn-secondary';
397
+ closeBtn.textContent = 'Dismiss';
398
+ closeBtn.onclick = () => { this._selectedNode = null; this.render(); };
399
+
400
+ dHeader.append(dTitle, closeBtn);
401
+
402
+ const dBody = document.createElement('div');
403
+ dBody.className = 'detail-body';
404
+ dBody.textContent = this._selectedNode.body;
405
+
406
+ detail.append(dHeader, dBody);
407
+ mainContainer.appendChild(detail);
408
+ }
409
+
410
+ const grid = document.createElement('div');
411
+ grid.className = 'grid';
412
+
413
+ filteredNodes.forEach((node) => {
414
+ const card = document.createElement('div');
415
+ card.className = 'node-card';
416
+ card.onclick = () => {
417
+ this._selectedNode = node;
418
+ this.render();
419
+ };
420
+
421
+ const cBadge = document.createElement('span');
422
+ cBadge.className = `node-cat cat-${node.category}`;
423
+ cBadge.textContent = node.category;
424
+
425
+ const cTitle = document.createElement('h5');
426
+ cTitle.className = 'node-title';
427
+ cTitle.textContent = node.title;
428
+
429
+ const cSnippet = document.createElement('p');
430
+ cSnippet.className = 'node-snippet';
431
+ cSnippet.textContent = node.body.slice(0, 110) + '...';
432
+
433
+ card.append(cBadge, cTitle, cSnippet);
434
+ grid.appendChild(card);
435
+ });
436
+
437
+ mainContainer.appendChild(grid);
438
+ } else if (this._activeTab === 'ingest') {
439
+ const ingestDesc = document.createElement('p');
440
+ ingestDesc.style.color = '#94a3b8';
441
+ ingestDesc.style.fontSize = '13px';
442
+ ingestDesc.textContent = 'Ingest markdown documentation files into the unified memory graph.';
443
+
444
+ const form = document.createElement('form');
445
+ form.className = 'row';
446
+
447
+ const pathInput = document.createElement('input');
448
+ pathInput.type = 'text';
449
+ pathInput.value = './openwiki';
450
+ pathInput.placeholder = 'Path to documentation directory';
451
+
452
+ const runBtn = document.createElement('button');
453
+ runBtn.type = 'submit';
454
+ runBtn.className = 'btn';
455
+ runBtn.textContent = 'Execute Ingestion';
456
+
457
+ form.append(pathInput, runBtn);
458
+
459
+ const terminal = document.createElement('div');
460
+ terminal.className = 'terminal';
461
+ terminal.textContent = this._ingestOutput || 'Awaiting ingestion command execution.';
462
+
463
+ form.onsubmit = (e) => {
464
+ e.preventDefault();
465
+ const p = pathInput.value.trim();
466
+ terminal.textContent = `Dispatching ingest pipeline for path: ${p}...`;
467
+ if (this._host && typeof this._host.run === 'function') {
468
+ this._host.run('ingest', [p]).then((res) => {
469
+ terminal.textContent = res?.output || 'Ingestion completed successfully.';
470
+ }).catch((err) => {
471
+ terminal.textContent = `Execution failure: ${err.message}`;
472
+ });
473
+ } else {
474
+ setTimeout(() => {
475
+ terminal.textContent = `[Ingest Engine] Scanned ${p}\nParsed 4 markdown documents.\nExtracted 12 semantic nodes.\nStatus: Ready`;
476
+ }, 400);
477
+ }
478
+ };
479
+
480
+ mainContainer.append(ingestDesc, form, terminal);
481
+ } else if (this._activeTab === 'config') {
482
+ const state = document.createElement('p');
483
+ state.style.color = '#94a3b8';
484
+ state.style.fontSize = '13px';
485
+ state.textContent = present
486
+ ? 'A key exists in the secrets store. Provide a new key to rotate credentials.'
487
+ : 'No key is registered. Submit a token to enable authenticated operations.';
488
+
489
+ const form = document.createElement('form');
490
+ form.className = 'row';
491
+
492
+ const input = document.createElement('input');
493
+ input.type = 'password';
494
+ input.autocomplete = 'off';
495
+ input.required = true;
496
+ input.placeholder = 'OPENWIKI_API_KEY';
497
+
498
+ const rotSelect = document.createElement('select');
499
+ rotSelect.className = 'filter-select';
500
+ [
501
+ { val: '30', lbl: 'Rotate every 30 days' },
502
+ { val: '60', lbl: 'Rotate every 60 days' },
503
+ { val: '90', lbl: 'Rotate every 90 days' },
504
+ { val: '0', lbl: 'Manual maintenance' }
505
+ ].forEach((r) => {
506
+ const ro = document.createElement('option');
507
+ ro.value = r.val;
508
+ ro.textContent = r.lbl;
509
+ rotSelect.appendChild(ro);
510
+ });
511
+
512
+ const button = document.createElement('button');
513
+ button.type = 'submit';
514
+ button.className = 'btn';
515
+ button.textContent = 'Save and Verify';
516
+
517
+ form.append(input, rotSelect, button);
518
+ form.addEventListener('submit', (event) => {
519
+ event.preventDefault();
520
+ this.dispatchEvent(new CustomEvent('save-token', {
521
+ detail: {
522
+ key: 'OPENWIKI_API_KEY',
523
+ token: input.value.trim(),
524
+ rotation_days: parseInt(rotSelect.value, 10)
525
+ },
526
+ bubbles: true,
527
+ composed: true
528
+ }));
529
+ input.value = '';
530
+ });
531
+
532
+ mainContainer.append(state, form);
533
+ }
534
+
535
+ root.append(style, header, tabs, mainContainer);
536
+ }
537
+ }
538
+
539
+ customElements.define('openwiki-panel', OpenwikiPanel);
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Greg Iteen
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,67 @@
1
+ # Security Assessments
2
+
3
+ Security plugin for Total Recall. Audit machines and mesh fleets, review network exposure, repair local SSH permissions, audit installed plugins and inspect websites.
4
+
5
+ ```sh
6
+ total-recall security machine --json
7
+ total-recall security network --json
8
+ total-recall security fleet --json
9
+ total-recall security fleet --target <discovered-machine> --json
10
+ total-recall security harden --json
11
+ total-recall security machine --apply-permissions --json
12
+ total-recall security plugins --json
13
+ total-recall security scan <source-directory> --json
14
+ total-recall security probe --url https://authorized-site --json
15
+ ```
16
+
17
+ Machine checks support macOS, Linux and native Windows; Android has limited device-property collection. Windows/Android adapters are fixture-tested, with live hardware verification still outstanding. Reports distinguish passed, at-risk, review-required and incomplete, with timestamps, coverage and remediation. Missing tools/privileges, offline peers and unsupported platforms remain explicit. Listening addresses do not establish Internet reachability; firewall activation does not certify rules, and update-service configuration does not establish patch currency.
18
+
19
+ Fleet assessment requires the installed mesh plugin and an installed security plugin on each selected peer. Mesh supplies discovery and authenticated transport. It never installs software remotely or substitutes a local check for an unavailable peer. `secure-all` runs this assessment; it cannot declare an entire fleet secured after metadata edits.
20
+
21
+ Permission repair changes only recognized, locally owned SSH metadata and verifies results. Firewall rules, SSH daemon configuration and encryption changes are presented as remediation requiring preserved administrative access and rollback planning.
22
+
23
+ Auth owns credentials. Machine audits need no security master key. For signing/encryption, store at least 32 bytes of random SECURITY_MASTER_KEY material through auth or `security token set --stdin`. Encryption accepts plaintext through `encrypt --stdin`; no passphrases or plaintext in argv. There are no embedded default keys or provider environment fallbacks. Explicit decryption emits plaintext and must be routed to the intended secure consumer, never an audit log.
24
+
25
+ Source scans report locations and rule IDs without matched secrets. Heuristic findings require source review; they are not proof of complete vulnerability coverage. Auth declarations alone do not establish runtime enforcement. Plugin audits never rewrite manifests to fabricate hardening.
26
+
27
+ Exit 0 means the requested operation completed within its stated semantics; machine/fleet checks exit 1 for risks, review or incomplete coverage. `harden` without an apply flag returns a plan with zero applied changes. UI renders actual reports and failures.
28
+
29
+ See [the operational skill](skills/security/SKILL.md). Official platform contracts: [OpenSSH](https://man.openbsd.org/sshd_config), [Ubuntu firewall administration](https://ubuntu.com/server/docs/how-to/security/firewalls/), [Apple platform protection](https://support.apple.com/guide/security/protecting-against-malware-sec469d47bd8/web).
30
+
31
+ ## Device coverage
32
+
33
+ | Device | Available assessment | Limits |
34
+ | --- | --- | --- |
35
+ | Windows | Native read-only firewall, antivirus, system encryption, Secure Boot and listeners; guided settings review | Privilege/edition gaps and patch currency remain unverified |
36
+ | Android | Existing authorized ADB property reads plus guided settings review | No new authorization/debugging, root operations or hardware attestation |
37
+ | Chromebook | Guided updates/support, verified boot, lock, extensions, containers, management and network review | A Linux container scan cannot certify ChromeOS |
38
+ | ChromeOS Flex | Separate guided review including UEFI boot protection | Does not claim Chromebook hardware guarantees |
39
+ | iPhone | Guided updates, lock, accounts/recovery, lost-device, profiles, permissions, network, sharing and targeted-threat review | No connected device-management collector |
40
+ | iPad | Separate guided device review | No assumption of iPhone-only Safety Check |
41
+
42
+ ```sh
43
+ total-recall security platforms --json
44
+ total-recall security device --platform iphone --device "My phone" --json
45
+ total-recall security android --serial <existing-authorized-serial> --json
46
+ ```
47
+
48
+ The device command returns a guide with unverified checks. Submit observations using `--stdin` (or bounded `--answers-json` for UI calls): `{"updates":{"status":"secure","observedAt":"<ISO timestamp>"}}`. Only status and time are accepted; no arbitrary notes or secret fields. Answers older than 24 hours become unverified. Even a full review is `user-attested-not-automatically-verified`, with automatic coverage zero. A completed manual review exits 0 as `reviewed`, never `passed`; risk or missing answers exit 1. The UI exposes platform/device selection, per-check review controls and an explicit authorized Android serial.
49
+
50
+ Official contracts: [Windows active firewall policy](https://learn.microsoft.com/en-us/powershell/module/netsecurity/get-netfirewallprofile), [BitLocker posture](https://learn.microsoft.com/en-us/powershell/module/bitlocker/get-bitlockervolume), [ADB authorization](https://developer.android.com/tools/adb), [Android boot state](https://source.android.com/docs/core/architecture/bootloader/locking_unlocking), [ChromeOS support expiration](https://support.google.com/chromebook/answer/9367166), [ChromeOS Flex differences](https://support.google.com/chrome/a/answer/11542901), [Apple personal safety](https://support.apple.com/guide/personal-safety/welcome/web).
51
+
52
+
53
+ Scanner coverage now includes JavaScript/TypeScript, Python and shell/PowerShell source. Dynamic credential reads, synthetic provider/signing defaults and linked uninspected source produce redacted review findings. Coverage limits fail explicitly; source review does not establish runtime enforcement. `security --help` lists actual commands. Latest scanner/device suite: 28 tests passed on sanctioned node, exit 0. All-plugin audit remains failed while CRM credential paths are unresolved.
54
+
55
+ ## Use it two ways
56
+
57
+ This plugin is a reusable brick, so a new project does not start from zero.
58
+
59
+ **Add it to a project (for apps you build and ship).** From the project directory:
60
+
61
+ ```sh
62
+ total-recall plugin vendor https://github.com/gregiteen/tr-plugin-security.git
63
+ ```
64
+
65
+ This copies the plugin's source, skills, tests and docs into `bricks/security` and records it in `tr-bricks.json`. Your project then owns that code: edit it, test it in your own gates, and ship it with no runtime dependency on this plugin or on Total Recall. Combine as many bricks as the project needs. List them with `total-recall plugin bricks`.
66
+
67
+ **Use it directly with Total Recall (for your own machines and workflow).** Install it with `total-recall plugin install https://github.com/gregiteen/tr-plugin-security.git` and run `total-recall security`. Manage its credentials with `total-recall auth secret` and its skills with `total-recall skill`.