total-recall-brain 3.40.1 → 3.40.3

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 +413 -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 +368 -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,25 @@
1
+ {
2
+ "name": "tr-plugin-security",
3
+ "version": "0.3.1",
4
+ "type": "module",
5
+ "description": "Standalone security suite for Total Recall: static analysis, file and permission hardening schemes, AES-256-GCM encryption tools, and egress audit controls",
6
+ "scripts": {
7
+ "test": "node --test test/*.test.mjs",
8
+ "build:ui": "node scripts/build-ui.mjs"
9
+ },
10
+ "license": "MIT",
11
+ "files": [
12
+ "cli.mjs",
13
+ "plugin.json",
14
+ "README.md",
15
+ "LICENSE",
16
+ "src/",
17
+ "!src/**/*.spec.mjs",
18
+ "skills/",
19
+ "scripts/",
20
+ "ui/"
21
+ ],
22
+ "publishConfig": {
23
+ "access": "public"
24
+ }
25
+ }
@@ -0,0 +1,297 @@
1
+ {
2
+ "$schema": "https://github.com/gregiteen/total-recall/blob/main/metadata.plugin.schema.json",
3
+ "id": "security",
4
+ "name": "Security Assessments",
5
+ "version": "0.3.1",
6
+ "description": "Machine and device security assessments for macOS, Linux, Windows, Android, Chromebook, iPhone and iPad, with explicit measured and manual coverage.",
7
+ "license": "MIT",
8
+ "branding": {
9
+ "name": "Security Assessments",
10
+ "color": "#f43f5e",
11
+ "badge": "Security Enclave",
12
+ "font": "chivo-mono"
13
+ },
14
+ "auth": {
15
+ "plugin": "auth",
16
+ "methods": [
17
+ "passkey",
18
+ "google-oauth2"
19
+ ],
20
+ "session_verification": true
21
+ },
22
+ "card_face": {
23
+ "skin": "winamp-classic",
24
+ "theme": "vibrant",
25
+ "headline": "Security & Hardening Suite",
26
+ "quick_actions": [
27
+ {
28
+ "subcommand": "machine",
29
+ "label": "THIS MACHINE"
30
+ },
31
+ {
32
+ "subcommand": "fleet",
33
+ "label": "MESH FLEET"
34
+ },
35
+ {
36
+ "subcommand": "plugins",
37
+ "label": "PLUGINS"
38
+ },
39
+ {
40
+ "subcommand": "harden",
41
+ "label": "HARDENING PLAN"
42
+ }
43
+ ],
44
+ "touch_layout": "comfortable",
45
+ "interactive": true
46
+ },
47
+ "ssss_schemas": {
48
+ "categories": [
49
+ {
50
+ "name": "security-audits",
51
+ "description": "Security audit reports, static analysis findings, and compliance baseline records",
52
+ "node_type": "memory"
53
+ },
54
+ {
55
+ "name": "security-hardening",
56
+ "description": "Applied hardening profiles, permission policies, and egress firewall rules",
57
+ "node_type": "memory"
58
+ },
59
+ {
60
+ "name": "security-events",
61
+ "description": "SSSS security events, rotation logs, and threat telemetry",
62
+ "node_type": "memory"
63
+ }
64
+ ]
65
+ },
66
+ "deploy": {
67
+ "targets": [
68
+ "ssss-app",
69
+ "nextjs",
70
+ "react",
71
+ "flask"
72
+ ],
73
+ "required_ssss_version": ">=0.9.3",
74
+ "access_grants": [
75
+ "auth:session:verify",
76
+ "ssss:vault:read",
77
+ "ssss:vault:write",
78
+ "ssss:events:append"
79
+ ]
80
+ },
81
+ "secrets": [
82
+ {
83
+ "key": "SECURITY_MASTER_KEY",
84
+ "description": "Master encryption key for envelope encryption and credential hardening",
85
+ "required": false
86
+ },
87
+ {
88
+ "key": "CHALLENGE_SECRET_KEY",
89
+ "required": false,
90
+ "description": "Provider challenge verification credential; managed exclusively by auth"
91
+ }
92
+ ],
93
+ "cli": {
94
+ "command": "security",
95
+ "handler": "./cli.mjs",
96
+ "subcommands": [
97
+ {
98
+ "name": "platforms",
99
+ "description": "List native collectors and guided device review coverage",
100
+ "effect": "read"
101
+ },
102
+ {
103
+ "name": "device",
104
+ "description": "Guided review: --platform ios|ipados|android|chromeos|chromeos-flex|windows --device label [--stdin|--answers-json JSON]; never automatically verified",
105
+ "effect": "write"
106
+ },
107
+ {
108
+ "name": "android",
109
+ "description": "Limited device-property reads: --serial existing-authorized-adb-serial; never enables debugging",
110
+ "timeout_ms": 60000,
111
+ "effect": "read"
112
+ },
113
+ {
114
+ "name": "machine",
115
+ "description": "Inspect local firewall, disk protection, effective SSH policy and listeners; --apply-permissions verifies local SSH permission repair",
116
+ "timeout_ms": 120000,
117
+ "effect": "write"
118
+ },
119
+ {
120
+ "name": "network",
121
+ "description": "Inspect local network listeners and host security posture",
122
+ "timeout_ms": 120000,
123
+ "effect": "read"
124
+ },
125
+ {
126
+ "name": "fleet",
127
+ "description": "Audit discovered mesh machines; optional --target hostname",
128
+ "timeout_ms": 600000,
129
+ "effect": "read"
130
+ },
131
+ {
132
+ "name": "status",
133
+ "description": "Display active security suite modules and crypto status",
134
+ "effect": "read"
135
+ },
136
+ {
137
+ "name": "audit",
138
+ "description": "Execute comprehensive file permission, egress policy, and SAST audit",
139
+ "timeout_ms": 120000,
140
+ "effect": "read"
141
+ },
142
+ {
143
+ "name": "scan",
144
+ "description": "Run static analysis scanner for code injection and token leaks",
145
+ "effect": "read"
146
+ },
147
+ {
148
+ "name": "harden",
149
+ "description": "Prepare observed hardening plan; --apply-permissions repairs recognized local SSH metadata",
150
+ "timeout_ms": 120000,
151
+ "effect": "write"
152
+ },
153
+ {
154
+ "name": "plugins",
155
+ "description": "Audit installed plugin source and auth declarations; manifests are never auto-rewritten",
156
+ "timeout_ms": 120000,
157
+ "effect": "read"
158
+ },
159
+ {
160
+ "name": "secure-all",
161
+ "description": "Audit entire discovered mesh fleet with explicit coverage and remediation; no blanket secured claims",
162
+ "timeout_ms": 600000,
163
+ "effect": "write"
164
+ },
165
+ {
166
+ "name": "encrypt",
167
+ "description": "Perform AES-256-GCM authenticated envelope encryption",
168
+ "effect": "write"
169
+ },
170
+ {
171
+ "name": "decrypt",
172
+ "description": "Decrypt AES-256-GCM envelope payload",
173
+ "effect": "read"
174
+ },
175
+ {
176
+ "name": "probe",
177
+ "description": "Real HTTPS response and security-header presence check; requires --url",
178
+ "effect": "read"
179
+ },
180
+ {
181
+ "name": "token",
182
+ "description": "Inspect or save the auth-managed security master key through stdin",
183
+ "effect": "write"
184
+ },
185
+ {
186
+ "name": "challenge",
187
+ "description": "Create, solve or verify authenticated proof-of-work challenges",
188
+ "effect": "write"
189
+ },
190
+ {
191
+ "name": "bot-mitigate",
192
+ "description": "Evaluate submission risk with optional provider challenge verification",
193
+ "effect": "read"
194
+ },
195
+ {
196
+ "name": "site-audit",
197
+ "description": "Review actual website security headers on an authorized HTTPS target",
198
+ "effect": "read"
199
+ },
200
+ {
201
+ "name": "site-shield",
202
+ "description": "Generate application middleware for review; does not claim installation",
203
+ "effect": "write"
204
+ }
205
+ ]
206
+ },
207
+ "ui": {
208
+ "design_tokens": "ui/DESIGN.md",
209
+ "elements": [
210
+ {
211
+ "id": "panel",
212
+ "kind": "panel",
213
+ "tag": "security-panel",
214
+ "module": "ui/panel.js",
215
+ "description": "Machine, network and mesh security audit console",
216
+ "events": [],
217
+ "tokens": [
218
+ "color-text",
219
+ "color-surface",
220
+ "color-border",
221
+ "spacing-md",
222
+ "radius-md"
223
+ ],
224
+ "optional_tokens": [],
225
+ "props": {
226
+ "view": {
227
+ "type": "object",
228
+ "description": "Printed by `total-recall security token status --json`: { present, secretKey }"
229
+ }
230
+ }
231
+ },
232
+ {
233
+ "id": "card",
234
+ "kind": "card",
235
+ "tag": "tr-security-card",
236
+ "module": "ui/card.js",
237
+ "description": "Fortress Card Face"
238
+ }
239
+ ]
240
+ },
241
+ "skills": [
242
+ {
243
+ "path": "skills/security/SKILL.md",
244
+ "id": "security"
245
+ }
246
+ ],
247
+ "runtime": {
248
+ "modules": {
249
+ "machines": "src/machines.mjs",
250
+ "scanner": "src/scanner.mjs",
251
+ "website": "cli.mjs",
252
+ "devices": "src/devices.mjs",
253
+ "windows": "src/windows.mjs",
254
+ "android": "src/android.mjs"
255
+ }
256
+ },
257
+ "status": {
258
+ "command": "status",
259
+ "refresh_seconds": 60
260
+ },
261
+ "distribution": {
262
+ "tier": "official",
263
+ "license": "open"
264
+ },
265
+ "card_layout": {
266
+ "template": "vault",
267
+ "regions": [
268
+ {
269
+ "widget": "status",
270
+ "title": "Status"
271
+ },
272
+ {
273
+ "widget": "live",
274
+ "title": "Live view"
275
+ },
276
+ {
277
+ "widget": "list",
278
+ "title": "Details",
279
+ "source": {
280
+ "command": "platforms"
281
+ }
282
+ },
283
+ {
284
+ "widget": "actions",
285
+ "title": "Commands"
286
+ },
287
+ {
288
+ "widget": "credentials",
289
+ "title": "Credentials"
290
+ },
291
+ {
292
+ "widget": "activity",
293
+ "title": "Recent activity"
294
+ }
295
+ ]
296
+ }
297
+ }
@@ -0,0 +1,4 @@
1
+ import fs from 'node:fs';
2
+ const card = fs.readFileSync(new URL('../ui/card.js', import.meta.url), 'utf8');
3
+ // The host runs each interface from a standalone Blob module; bundle the shared class.
4
+ fs.writeFileSync(new URL('../ui/panel.js', import.meta.url), `${card}\nclass SecurityPanel extends SecuritySecurityCard {}\nif (!customElements.get('security-panel')) customElements.define('security-panel', SecurityPanel);\n`);
@@ -0,0 +1,37 @@
1
+ ---
2
+ name: security
3
+ description: Audit and harden machines, mesh networks, plugin credentials and websites using the security plugin, with measured coverage and verified remediation.
4
+ ---
5
+
6
+ # Security plugin
7
+
8
+ Discover `total-recall security status --json` and installed mesh/auth capabilities. Security owns audits and remediation; mesh owns machine discovery and remote execution; auth owns every credential. No ambient credential, default key, core secret store or alternate-machine fallback is permitted.
9
+
10
+ Use `security machine --json` for the current host or `security network --json` for its network posture. Reports include firewall, disk protection, effective SSH settings, TCP/UDP bindings and SSH file metadata. macOS additionally checks Gatekeeper, System Integrity Protection and update scheduling. Linux inspects UFW, root encryption ancestry and update-service configuration. Unsupported tools, privileges and storage layouts remain unavailable. An enabled firewall alone does not certify its rules; configured update services do not prove patch currency.
11
+
12
+ Use `security fleet --json` or `security fleet --target <discovered-hostname> --json` for mesh machines. `secure-all` is the fleet assessment workflow. The security plugin must already be installed on each peer; this operation never installs agents or substitutes another machine. Review observed/selected counts, offline machines, freshness, identity and unavailable checks before making a fleet claim. Mobile and ChromeOS peers without a connected collector remain unverified and route to device review; mesh presence never proves device security.
13
+
14
+ For each failed/review check, follow the report's remediation. `security harden --json` prepares the current machine's plan. `security machine --apply-permissions --json` restricts recognized local SSH permissions and verifies inode ownership and resulting modes. It refuses symlink traversal. Firewall, SSH daemon, disk-encryption and recovery changes require a concrete access/rollback plan; validate configuration and a second working administrative connection before applying those changes. Never label a generated recommendation as applied protection.
15
+
16
+ Use `security plugins --json` for installed plugin declarations and source findings, and `security scan <path> --json` for scoped source inspection. Findings omit matched values. Scanner findings are review evidence, not proof that all credentials or vulnerabilities have been found. Missing paths, coverage limits and unreadable files fail the operation. Manifest auth declarations do not prove runtime enforcement; follow credential reads/writes and route checks through the actual owner. Do not automatically add grants or rewrite manifests as a substitute for implementation.
17
+
18
+ Use `security probe --url https://authorized-site --json` for a real HTTPS response and header-presence check. Header presence does not prove correct policy. Restrict targets to authorized systems; do not widen scanning to arbitrary network ranges. `site-audit` provides additional website review; challenge, bot-mitigation and site-shield tools need application integration and verification.
19
+
20
+ Signing/encryption require SECURITY_MASTER_KEY stored through auth; use `security token set --stdin` for at least 32 bytes of random material. Remote challenge verification uses its separately declared provider credential. Never pass keys or plaintext in argv. `security encrypt --stdin --json` accepts plaintext on stdin. Explicit decryption exposes plaintext by design: route output only to the intended secure consumer and never capture it in audit logs or documentation.
21
+
22
+ Run meaningful clean/unsafe fixtures and the full owner suite on the configured sanctioned test node. Preserve raw exit status, tested source identity and cleanup evidence. Report findings, unavailable coverage, actual fixes and residual risks separately. Update the active project tracker and OpenWiki via its installed plugin; never store secrets in reports, hubs, SSSS audit records or UI output.
23
+
24
+ ## Windows, Android, Chromebook, iPhone and iPad
25
+
26
+ Run `security platforms --json` for the support matrix. Windows `machine` uses fixed read-only PowerShell queries for active firewall profiles, built-in antivirus, system-volume encryption, Secure Boot and TCP/UDP bindings. Missing cmdlets, editions and privileges stay unavailable. All firewall rules, alternate antivirus and Windows patch currency still require review. This collector never requests recovery-key material or applies administrative changes.
27
+
28
+ Use `security android --serial <already-authorized-serial> --json` only with an existing authorized ADB device. It reads four allowlisted boot, encryption and security-patch properties. It never connects, authorizes, roots, flashes or enables debugging. Properties are device-reported rather than hardware attestation; full posture stays incomplete. Android-native runtimes may use `machine`; Linux containers and Termux identified as Linux must not be assumed to certify Android.
29
+
30
+ Use `security device --platform ios|ipados|android|chromeos|chromeos-flex|windows --device <label> --json` for the device-specific guide. Initial checks are unverified. After observing settings on that device, submit `--stdin` with an object keyed by check ID, each containing only `status` (`secure`, `needs-attention`, `unknown`) and ISO `observedAt`. The UI supplies this same workflow through Review device / Evaluate review. Only changed answers receive timestamps. Answers expire after 24 hours. Never record passcodes, recovery codes, keys, profiles, arbitrary notes or other secret material.
31
+
32
+ Manual outcomes are user-attested: reviewed is never automatic passed; coverage.complete remains false and automatic remains zero. Incomplete/at-risk reviews exit 1; a complete manual review exits 0 within those limited semantics. Do not turn manual answers into native observations, invent device-management enrollment, or substitute a browser scan. iPhone/iPad have distinct guides; Safety Check is not assumed on iPad. Chromebook and ChromeOS Flex have distinct boot protection guidance; Crostini/container checks never certify the host. Network reviews cover saved Wi-Fi, VPN, hotspot and sharing; router firmware/rules need a separate authorized router assessment.
33
+
34
+ Windows/Android collectors are fixture-tested on the sanctioned Mac mini; live execution on those operating systems is not yet verified. No mobile management or Verified Access integration is connected. Keep these limitations visible until actual device evidence establishes coverage.
35
+
36
+
37
+ 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.
@@ -0,0 +1,21 @@
1
+ const properties = ['ro.boot.verifiedbootstate', 'ro.boot.flash.locked', 'ro.crypto.state', 'ro.build.version.security_patch'];
2
+ export function auditAndroid({ execute, serial, hostname = 'Android runtime' }) {
3
+ if (serial !== undefined) {
4
+ if (typeof serial !== 'string' || !/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/.test(serial)) throw new Error('Explicit authorized device serial required');
5
+ const inventory = execute('adb', ['devices']);
6
+ if (!inventory.ok || !inventory.output.split('\n').some(line => line.trim().split(/\s+/)[0] === serial && line.trim().split(/\s+/)[1] === 'device')) throw new Error('Device is not present and authorized; no connection or debugging changes were attempted');
7
+ hostname = serial;
8
+ }
9
+ const checks = properties.map(property => {
10
+ const result = serial ? execute('adb', ['-s', serial, 'shell', 'getprop', property]) : execute('getprop', [property]);
11
+ const value = result.ok ? result.output.trim() : '';
12
+ let state = 'unavailable', observed;
13
+ if (property.endsWith('verifiedbootstate') && ['green', 'yellow', 'orange', 'red'].includes(value)) { state = value === 'green' ? 'pass' : 'fail'; observed = value; }
14
+ if (property.endsWith('flash.locked') && ['0', '1'].includes(value)) { state = value === '1' ? 'pass' : 'fail'; observed = value; }
15
+ if (property === 'ro.crypto.state' && ['encrypted', 'unencrypted'].includes(value)) { state = value === 'encrypted' ? 'pass' : 'fail'; observed = value; }
16
+ if (property.endsWith('security_patch') && /^\d{4}-\d{2}-\d{2}$/.test(value) && Number.isFinite(Date.parse(value)) && new Date(value).toISOString().slice(0, 10) === value) { state = Date.parse(value) > Date.now() + 86400000 ? 'unavailable' : 'review'; observed = value; }
17
+ return { id: property, state, evidence: state === 'unavailable' ? 'none' : 'device-reported-property', ...(observed ? { observed } : {}), remediation: 'Review the manufacturer security settings and support policy. Properties are not hardware attestation; never flash, root or relock a device through this tool.' };
18
+ });
19
+ checks.push({ id: 'device-settings-review', state: 'unavailable', evidence: 'none', remediation: 'Complete security device --platform android for screen lock, app protection, permissions, accounts, debugging and network access.' });
20
+ return { schema: 'security-machine/v1', platform: 'android', hostname, timestamp: new Date().toISOString(), status: checks.some(v => v.state === 'fail') ? 'at-risk' : 'incomplete', coverage: { complete: false, observed: checks.filter(v => v.state !== 'unavailable').length, total: checks.length, limitations: ['Device-reported properties only; rooted devices may misreport state', 'No hardware attestation or full settings inspection', 'Never enable debugging solely for a scan; revoke unused debugging access after use'] }, checks, listeners: [] };
21
+ }
@@ -0,0 +1,94 @@
1
+ const apple = 'https://support.apple.com/guide/personal-safety/welcome/web';
2
+ const android = 'https://support.google.com/android/answer/7680439';
3
+ const chrome = 'https://support.google.com/chromebook/answer/9367166';
4
+ const windows = 'https://learn.microsoft.com/en-us/windows/security/';
5
+ const check = (id, title, remediation, source) => ({ id, title, remediation, source });
6
+ const appleChecks = [
7
+ check('updates', 'OS and security updates reviewed', 'Open Settings → General → Software Update. Install available supported updates and review Automatic Updates. A version number alone does not prove current protection.', apple),
8
+ check('screen-lock', 'Strong passcode and automatic lock', 'Review Face ID / Touch ID & Passcode and Display & Brightness → Auto-Lock. Use a strong unique passcode; never enter that passcode in this assessment.', apple),
9
+ check('account-recovery', 'Account protection and recovery reviewed', 'In Settings → your account → Sign-In & Security, review two-factor authentication, trusted devices and recovery options. Keep recovery material outside this report.', apple),
10
+ check('lost-device', 'Lost-device protection enabled', 'Review Find My and Activation Lock for this device. Confirm recovery access before changing account settings.', apple),
11
+ check('management', 'Management profiles and VPNs recognized', 'Review Settings → General → VPN & Device Management. Investigate unknown profiles or VPNs; coordinate legitimate managed policies with your administrator.', apple),
12
+ check('app-permissions', 'App access and sharing reviewed', 'Review Privacy & Security permissions, location access and installed apps. Restrict unnecessary camera, microphone, contacts and tracking access.', 'https://support.apple.com/en-us/102515'),
13
+ check('network', 'Wi-Fi and network exposure reviewed', 'Review known Wi-Fi networks, Auto-Join, hotspot access and sharing settings. Use trusted encrypted networks; inspect the router separately. An active VPN is not proof that the device is secure.', apple),
14
+ ];
15
+ const profiles = {
16
+ ios: { name: 'iPhone', limitations: ['No native device-posture collector or management enrollment is established', 'A browser cannot inspect passcodes, installed profiles or OS protection settings'], checks: [...appleChecks,
17
+ check('sharing-safety', 'Safety Check and theft protection reviewed', 'Use Settings → Privacy & Security → Safety Check → Manage Sharing & Access when available. Review Stolen Device Protection under Face ID / Touch ID & Passcode. Consider the personal impact before revoking sharing.', 'https://support.apple.com/en-euro/guide/personal-safety/-ips2aad835e1/web'),
18
+ check('targeted-threats', 'Targeted-threat protection considered', 'Review whether Lockdown Mode is appropriate for your threat model. It is optional and restricts functionality; leaving it off is not itself a failed baseline. Mark reviewed after making an informed choice.', 'https://support.apple.com/en-us/105120'),
19
+ ] },
20
+ ipados: { name: 'iPad', limitations: ['No native device-posture collector or management enrollment is established', 'iPhone Safety Check and Stolen Device Protection are not assumed available on iPad'], checks: [...appleChecks,
21
+ check('targeted-threats', 'Targeted-threat protection considered', 'Review Lockdown Mode in Privacy & Security for targeted threats. It is optional and restricts functionality; decide whether it fits your risk.', 'https://support.apple.com/en-us/105120'),
22
+ ] },
23
+ android: { name: 'Android', limitations: ['Native property checks require an existing authorized ADB session or an Android runtime', 'Property reads are not hardware attestation and cannot prove a rooted device is trustworthy'], checks: [
24
+ check('updates', 'OS, security patch and system updates reviewed', 'Review Settings → About phone/tablet → Android version and System → Software updates. Check OS, security-patch and system-update status plus your manufacturer support period.', android),
25
+ check('screen-lock', 'Strong screen lock and automatic locking', 'Review Security & Privacy → Device unlock / Screen lock. Use a strong unique PIN or password with automatic locking; never enter it in this assessment.', android),
26
+ check('app-protection', 'App protection and certification reviewed', 'On devices with Google Play, review Play Store → profile → Play Protect and Settings → About → certification. On another distribution, review its documented equivalent; do not assume Play services exist.', 'https://support.google.com/googleplay/answer/2812853'),
27
+ check('boot-integrity', 'Boot integrity and modifications reviewed', 'Review boot warnings and manufacturer bootloader/root status. Do not relock or flash a bootloader from this tool: those changes can erase data or prevent booting.', 'https://source.android.com/docs/core/architecture/bootloader/locking_unlocking'),
28
+ check('debugging', 'Debugging and unknown-app installation restricted', 'Review Developer options → USB/Wireless debugging and per-app Install unknown apps permissions. Revoke unneeded debugging authorizations; do not enable debugging solely for a security scan.', android),
29
+ check('permissions', 'Accessibility, device-admin and app access reviewed', 'Review Privacy & Security, Accessibility services, Device admin apps and special app access. Investigate unrecognized administrators or services before making changes.', android),
30
+ check('account-recovery', 'Account recovery and lost-device access reviewed', 'Review your account security, two-factor authentication and supported lost-device location/lock features. Confirm recovery access without recording keys or codes.', android),
31
+ check('network', 'Wi-Fi, hotspot and VPN access reviewed', 'Remove untrusted saved Wi-Fi networks, restrict hotspot access and inspect VPN permissions. Inspect router firmware, management and wireless encryption separately.', android),
32
+ ] },
33
+ chromeos: { name: 'Chromebook / ChromeOS', limitations: ['Linux development-container checks do not measure the ChromeOS host', 'Verified Access and enterprise device-management APIs are not connected'], checks: [
34
+ check('updates', 'OS update and support expiration reviewed', 'Open Settings → About ChromeOS → Check for updates and Additional details → Update schedule. Confirm the model still receives security updates and restart to complete pending updates.', chrome),
35
+ check('verified-boot', 'Verified boot and developer mode reviewed', 'Review boot warnings and developer-mode state. Preserve normal verified boot for everyday use. Leaving developer mode can erase local data; back up and follow the model-specific recovery procedure.', 'https://www.chromium.org/chromium-os/chromiumos-design-docs/verified-boot/'),
36
+ check('screen-lock', 'Screen lock and account authentication reviewed', 'Review Security and Privacy → Lock screen and sign-in. Require authentication after sleep; protect the account with a passkey or two-factor authentication.', chrome),
37
+ check('extensions', 'Browser extensions and site permissions reviewed', 'Review Chrome extensions and Safety Check. Remove unrecognized extensions and restrict site camera, microphone, notification and location permissions.', 'https://support.google.com/chrome/answer/3014197'),
38
+ check('containers', 'Linux/Android environments and sharing reviewed', 'Review Linux development-environment shared folders, forwarded ports and Android app permissions. Audit each container separately; its results cannot certify the host.', 'https://support.google.com/chromebook/answer/9145439'),
39
+ check('management', 'Device management and account access recognized', 'Review device management, signed-in accounts and administrator policies. Investigate unfamiliar control without removing legitimate managed configuration.', 'https://support.google.com/chrome/a/answer/1375678'),
40
+ check('network', 'Wi-Fi and private-service exposure reviewed', 'Review saved networks, VPN access, device sharing and container port forwarding. Inspect router access and encryption separately; mesh connectivity alone proves no security posture.', chrome),
41
+ ] },
42
+ windows: { name: 'Windows', limitations: ['Guided review is separate from the native machine collector', 'No administrative changes are applied by this assessment'], checks: [
43
+ check('updates', 'Supported Windows release and updates reviewed', 'Open Settings → Windows Update. Install available updates and confirm support or extended-security entitlement for this exact release. Update-service presence alone is insufficient.', windows),
44
+ check('antivirus', 'Active antivirus provider and real-time protection reviewed', 'Review Windows Security → Virus & threat protection, active security providers, real-time protection and definition updates. A disabled built-in provider may require reviewing another installed provider.', windows),
45
+ check('firewall', 'Firewall profiles and inbound rules reviewed', 'Review Windows Security → Firewall & network protection for Domain, Private and Public profiles and their rules. Preserve verified administrative access before changing rules.', windows),
46
+ check('encryption', 'Disk encryption and recovery custody reviewed', 'Review Device encryption or BitLocker, protection state and recovery-key custody. Never paste a recovery key in this assessment; enabling encryption needs a verified backup and recovery plan.', windows),
47
+ check('boot-integrity', 'Secure Boot and hardware protection reviewed', 'Review System Information and Windows Security → Device security. Firmware/boot changes require hardware-specific instructions and recovery access.', windows),
48
+ check('screen-lock', 'Sign-in, lock and account privilege reviewed', 'Review Accounts → Sign-in options, automatic locking and local administrator membership. Use strong authentication and least privilege.', windows),
49
+ check('network', 'Remote access and listening services reviewed', 'Review Remote Desktop, OpenSSH, file sharing and native machine listener findings. Remove unneeded exposure while retaining a tested management path.', windows),
50
+ ] },
51
+ };
52
+ profiles['chromeos-flex'] = { ...profiles.chromeos, name: 'ChromeOS Flex', limitations: [...profiles.chromeos.limitations, 'Flex has different boot-security and hardware guarantees from Chromebook hardware'], checks: profiles.chromeos.checks.filter(item => item.id !== 'verified-boot' && item.id !== 'containers').concat([
53
+ check('boot-integrity', 'UEFI Secure Boot and hardware support reviewed', 'Follow the certified-device guidance for UEFI Secure Boot. ChromeOS Flex does not provide Chromebook hardware verified-boot guarantees; do not equate those protections.', 'https://support.google.com/chrome/a/answer/11542901'),
54
+ ]) };
55
+
56
+ export function normalizePlatform(value) {
57
+ const aliases = { iphone: 'ios', ipad: 'ipados', chromebook: 'chromeos', win32: 'windows' };
58
+ const platform = aliases[value] || value;
59
+ if (!Object.hasOwn(profiles, platform)) throw new Error('Unknown device platform');
60
+ return platform;
61
+ }
62
+ export function deviceProfile(value) {
63
+ const platform = normalizePlatform(value);
64
+ return structuredClone({ schema: 'security-device-profile/v1', platform, ...profiles[platform], evidence: 'user-attested', instructions: 'Check each item on the named device. Unknown is an honest result. Never enter passwords, recovery keys or provider tokens.', outcomes: ['secure', 'needs-attention', 'unknown'] });
65
+ }
66
+ export function platformInventory() {
67
+ return { schema: 'security-platforms/v1', timestamp: new Date().toISOString(), platforms: [
68
+ { platform: 'darwin', name: 'macOS', automatic: 'native machine collector' },
69
+ { platform: 'linux', name: 'Linux', automatic: 'native runtime collector; containers do not certify hosts' },
70
+ { platform: 'windows', name: 'Windows', automatic: 'native PowerShell collector', guided: true },
71
+ { platform: 'android', name: 'Android', automatic: 'limited properties through authorized ADB or Android runtime', guided: true },
72
+ { platform: 'chromeos', name: 'Chromebook / ChromeOS', automatic: null, guided: true },
73
+ { platform: 'chromeos-flex', name: 'ChromeOS Flex', automatic: null, guided: true },
74
+ { platform: 'ios', name: 'iPhone', automatic: null, guided: true },
75
+ { platform: 'ipados', name: 'iPad', automatic: null, guided: true },
76
+ ], limitations: ['Guide availability is not automatic device inspection', 'Native Windows and Android collectors require live device verification; fixtures alone do not certify hardware'] };
77
+ }
78
+ export function assessDevice(input, { now = Date.now() } = {}) {
79
+ if (!input || typeof input !== 'object' || Array.isArray(input) || Object.keys(input).some(key => !['platform', 'deviceId', 'observations'].includes(key))) throw new Error('Unexpected device assessment fields');
80
+ const profile = deviceProfile(input.platform);
81
+ if (typeof input.deviceId !== 'string' || !/^[\p{L}\p{N} ._()-]{1,80}$/u.test(input.deviceId)) throw new Error('A bounded device label is required; do not include secret material');
82
+ const observations = input.observations === undefined ? {} : input.observations;
83
+ if (!observations || typeof observations !== 'object' || Array.isArray(observations) || Object.keys(observations).some(id => !profile.checks.some(item => item.id === id))) throw new Error('Unknown check identifiers');
84
+ const checks = profile.checks.map(item => {
85
+ const observation = observations[item.id];
86
+ if (Object.hasOwn(observations, item.id) && (!observation || typeof observation !== 'object' || Array.isArray(observation) || Object.keys(observation).some(key => !['status', 'observedAt'].includes(key)) || !profile.outcomes.includes(observation.status))) throw new Error('Invalid observation; only status and observation time are accepted');
87
+ if (observation && (typeof observation.observedAt !== 'string' || !/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?Z$/.test(observation.observedAt))) throw new Error('An ISO UTC observation timestamp is required');
88
+ const age = observation ? now - Date.parse(observation.observedAt) : NaN;
89
+ const fresh = Number.isFinite(age) && age >= -5000 && age <= 86400000;
90
+ return { ...item, state: !fresh || observation.status === 'unknown' ? 'unverified' : observation.status === 'secure' ? 'user-confirmed' : 'fail', evidence: observation && fresh ? 'user-attested' : 'none', observed_at: observation && fresh ? observation.observedAt : null, ...(observation && !fresh ? { reason: 'missing-stale-or-invalid-observation-time' } : {}) };
91
+ });
92
+ const reviewed = checks.filter(item => item.state !== 'unverified').length;
93
+ return { schema: 'security-device/v1', platform: profile.platform, name: profile.name, device_id: input.deviceId, timestamp: new Date(now).toISOString(), status: checks.some(item => item.state === 'fail') ? 'at-risk' : reviewed !== checks.length ? 'incomplete' : 'reviewed', verification: 'user-attested-not-automatically-verified', coverage: { complete: false, automatic: 0, reviewed, total: checks.length, manual_complete: reviewed === checks.length }, limitations: profile.limitations, checks };
94
+ }