karnel-termux 4.7.7 → 4.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/README.md +39 -4
- package/karnel/cli/commands/backup.sh +8 -0
- package/karnel/cli/commands/doctor/system.sh +2 -0
- package/karnel/cli/commands/doctor.sh +8 -0
- package/karnel/cli/commands/install.sh +139 -84
- package/karnel/cli/commands/list.sh +32 -0
- package/karnel/cli/commands/open.sh +10 -6
- package/karnel/cli/commands/reinstall.sh +11 -0
- package/karnel/cli/commands/robin.sh +656 -0
- package/karnel/cli/commands/show.sh +1 -0
- package/karnel/cli/commands/start.sh +5 -0
- package/karnel/cli/commands/status.sh +11 -0
- package/karnel/cli/commands/uninstall.sh +9 -0
- package/karnel/cli/commands/update.sh +9 -0
- package/karnel/cli/commands/version.sh +2 -0
- package/karnel/cli/karnel.sh +35 -25
- package/karnel/modules/dev.sh +19 -46
- package/karnel/modules/osint.sh +123 -0
- package/karnel/tools/ai/crush/install.sh +1 -1
- package/karnel/tools/ai/omni-route/install.sh +1 -1
- package/karnel/tools/deploy/railway/install.sh +1 -1
- package/karnel/tools/dev/all.sh +45 -2
- package/karnel/tools/dev/fzf/install.sh +36 -9
- package/karnel/tools/npm/turbopack/install.sh +2 -0
- package/karnel/tools/osint/all.sh +65 -0
- package/karnel/tools/osint/robin/README.md +99 -0
- package/karnel/tools/osint/robin/common.sh +258 -0
- package/karnel/tools/osint/robin/install.sh +548 -0
- package/karnel/tools/osint/robin/requirements-termux.txt +33 -0
- package/karnel/utils/env.sh +16 -2
- package/karnel/utils/tools.sh +9 -2
- package/package.json +6 -1
- package/scripts/check-package.js +45 -0
- package/scripts/completion.bash +8 -3
- package/scripts/completion.zsh +8 -1
- package/karnel/tools/dev/applaunch/__pycache__/applaunch.cpython-314.pyc +0 -0
- package/karnel/tools/dev/fconv/__pycache__/fconv.cpython-314.pyc +0 -0
- package/karnel/tools/dev/filecheck/__pycache__/filecheck.cpython-314.pyc +0 -0
- package/karnel/tools/dev/notes/__pycache__/notes.cpython-314.pyc +0 -0
- package/karnel/tools/dev/passman/__pycache__/passman.cpython-314.pyc +0 -0
- package/karnel/tools/dev/splash/__pycache__/splash.cpython-314.pyc +0 -0
- package/karnel/tools/dev/websites/__pycache__/websites.cpython-314.pyc +0 -0
- package/karnel/tools/games/arcade/__pycache__/arcade.cpython-314.pyc +0 -0
- package/karnel/tools/games/buzz/__pycache__/buzz.cpython-314.pyc +0 -0
- package/karnel/tools/games/ctfgod/__pycache__/ctfgod.cpython-314.pyc +0 -0
- package/karnel/tools/games/detective/__pycache__/detective.cpython-314.pyc +0 -0
- package/karnel/tools/games/pet-friends/__pycache__/pet-friends.cpython-314.pyc +0 -0
- package/karnel/tools/games/tamagotchi/__pycache__/tamagotchi.cpython-314.pyc +0 -0
- package/karnel/tools/games/terminal-arcade/__pycache__/terminal-arcade.cpython-314.pyc +0 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Robin OSINT
|
|
2
|
+
|
|
3
|
+
Robin is an independent, AI-assisted dark-web OSINT project. Karnel installs a
|
|
4
|
+
tested Robin release, Tor, native Termux scientific packages, and a local
|
|
5
|
+
Streamlit interface.
|
|
6
|
+
|
|
7
|
+
Upstream project: https://github.com/apurvsinghgautam/robin
|
|
8
|
+
|
|
9
|
+
## Responsible Use
|
|
10
|
+
|
|
11
|
+
Use Robin only for lawful, authorized, and ethical research. Tor improves
|
|
12
|
+
connection privacy but does not guarantee anonymity. Robin automatically
|
|
13
|
+
retrieves web pages. Do not execute or open unknown files.
|
|
14
|
+
|
|
15
|
+
Queries, URLs, collected content, and summaries can be sent directly to the
|
|
16
|
+
configured LLM provider outside Tor. Third parties may process and retain that
|
|
17
|
+
data. Investigations are stored locally as plain JSON. Minimize personal data,
|
|
18
|
+
follow applicable laws and institutional policies, and independently verify AI
|
|
19
|
+
output before treating it as evidence.
|
|
20
|
+
|
|
21
|
+
The web interface is bound to `127.0.0.1`. Never expose port `8501` publicly.
|
|
22
|
+
|
|
23
|
+
## Install
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
karnel install osint --robin
|
|
27
|
+
karnel robin config
|
|
28
|
+
karnel robin doctor
|
|
29
|
+
karnel robin start
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Open `http://127.0.0.1:8501` after the health check succeeds.
|
|
33
|
+
|
|
34
|
+
For an intentional non-interactive first start:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
karnel robin start --accept-responsible-use
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Commands
|
|
41
|
+
|
|
42
|
+
| Command | Description |
|
|
43
|
+
| --- | --- |
|
|
44
|
+
| `karnel robin start` | Start Tor when needed and launch the local UI |
|
|
45
|
+
| `karnel robin stop` | Stop the managed Streamlit process |
|
|
46
|
+
| `karnel robin status` | Show installation, Tor, UI, config, and data status |
|
|
47
|
+
| `karnel robin config` | Show the protected configuration path and variables |
|
|
48
|
+
| `karnel robin doctor` | Run local dependency and service diagnostics |
|
|
49
|
+
| `karnel robin doctor --network` | Also verify an HTTP request through Tor |
|
|
50
|
+
| `karnel robin update` | Reconcile the installation with Karnel's pinned release |
|
|
51
|
+
| `karnel robin purge-data` | Permanently remove config and investigations after confirmation |
|
|
52
|
+
|
|
53
|
+
## Data Locations
|
|
54
|
+
|
|
55
|
+
Karnel separates executable code from persistent user data:
|
|
56
|
+
|
|
57
|
+
| Data | Location |
|
|
58
|
+
| --- | --- |
|
|
59
|
+
| Upstream source | `$KARNEL_TOOLS/osint/robin/app` |
|
|
60
|
+
| Python environment | `$KARNEL_TOOLS/osint/robin/.venv` |
|
|
61
|
+
| Provider configuration | `$KARNEL_CONFIG/robin/.env` |
|
|
62
|
+
| Saved investigations | `$KARNEL_DATA/robin/investigations` |
|
|
63
|
+
| Runtime log | `$KARNEL_LOGS/robin.log` |
|
|
64
|
+
| Installation log | `$KARNEL_CACHE/install_osint.log` |
|
|
65
|
+
|
|
66
|
+
Uninstall and reinstall preserve configuration and investigations. API keys and
|
|
67
|
+
investigations are intentionally excluded from ordinary Karnel backups. Use
|
|
68
|
+
`karnel robin purge-data` only when permanent deletion is intended.
|
|
69
|
+
|
|
70
|
+
## Provider Configuration
|
|
71
|
+
|
|
72
|
+
Supported variables include:
|
|
73
|
+
|
|
74
|
+
- `OPENAI_API_KEY`
|
|
75
|
+
- `ANTHROPIC_API_KEY`
|
|
76
|
+
- `GOOGLE_API_KEY`
|
|
77
|
+
- `OPENROUTER_API_KEY`
|
|
78
|
+
- `OPENROUTER_BASE_URL`
|
|
79
|
+
- `OLLAMA_BASE_URL`
|
|
80
|
+
- `LLAMA_CPP_BASE_URL`
|
|
81
|
+
- `CUSTOM_API_BASE_URL`
|
|
82
|
+
- `CUSTOM_API_KEY`
|
|
83
|
+
- `CUSTOM_API_MODEL`
|
|
84
|
+
|
|
85
|
+
Never commit or display secret values. Existing files are repaired to mode
|
|
86
|
+
`0600`; configuration directories use mode `0700`.
|
|
87
|
+
|
|
88
|
+
## Troubleshooting
|
|
89
|
+
|
|
90
|
+
Run `karnel robin doctor`. The default doctor is local and does not call an LLM
|
|
91
|
+
or consume provider credits. `--network` performs a small request through Tor.
|
|
92
|
+
|
|
93
|
+
Streamlit can take up to one minute to become healthy on a mobile device. The
|
|
94
|
+
start command waits for the health endpoint instead of relying only on a PID.
|
|
95
|
+
Android may still stop background processes because of battery optimization or
|
|
96
|
+
phantom-process limits.
|
|
97
|
+
|
|
98
|
+
Robin is third-party software distributed under its upstream license. Karnel is
|
|
99
|
+
not affiliated with the upstream author or any LLM provider.
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Public constants and layout state are consumed by separately imported modules.
|
|
3
|
+
# shellcheck disable=SC2034
|
|
4
|
+
|
|
5
|
+
ROBIN_REPO="https://github.com/apurvsinghgautam/robin.git"
|
|
6
|
+
ROBIN_DOCS_URL="https://github.com/apurvsinghgautam/robin"
|
|
7
|
+
ROBIN_VERSION="v2.8"
|
|
8
|
+
ROBIN_COMMIT="3c346fc6ba89034e71be38f3fa2912a633596435"
|
|
9
|
+
ROBIN_NOTICE_VERSION="2026-07-18.1"
|
|
10
|
+
|
|
11
|
+
ROBIN_ROOT="${ROBIN_ROOT:-$KARNEL_TOOLS/osint/robin}"
|
|
12
|
+
ROBIN_MANAGED_APP_DIR="$ROBIN_ROOT/app"
|
|
13
|
+
ROBIN_MANAGED_VENV_DIR="$ROBIN_ROOT/.venv"
|
|
14
|
+
ROBIN_CONFIG_DIR="${ROBIN_CONFIG_DIR:-$KARNEL_CONFIG/robin}"
|
|
15
|
+
ROBIN_ENV_FILE="$ROBIN_CONFIG_DIR/.env"
|
|
16
|
+
ROBIN_DATA_DIR="${ROBIN_DATA_DIR:-$KARNEL_DATA/robin}"
|
|
17
|
+
ROBIN_INVESTIGATIONS_DIR="$ROBIN_DATA_DIR/investigations"
|
|
18
|
+
ROBIN_PID_FILE="${ROBIN_PID_FILE:-$KARNEL_RUN/robin.pid}"
|
|
19
|
+
ROBIN_LOCK_DIR="${ROBIN_LOCK_DIR:-$KARNEL_RUN/robin.lock}"
|
|
20
|
+
ROBIN_LOG="${ROBIN_LOG:-$KARNEL_LOGS/robin.log}"
|
|
21
|
+
ROBIN_PORT="${ROBIN_PORT:-8501}"
|
|
22
|
+
ROBIN_START_TIMEOUT="${ROBIN_START_TIMEOUT:-60}"
|
|
23
|
+
ROBIN_PROC_ROOT="${ROBIN_PROC_ROOT:-/proc}"
|
|
24
|
+
ROBIN_ACK_FILE="$ROBIN_CONFIG_DIR/responsible-use"
|
|
25
|
+
|
|
26
|
+
_robin_refresh_layout() {
|
|
27
|
+
if [[ -d "$ROBIN_ROOT/.git" && ! -d "$ROBIN_MANAGED_APP_DIR/.git" ]]; then
|
|
28
|
+
ROBIN_LAYOUT="legacy"
|
|
29
|
+
ROBIN_APP_DIR="$ROBIN_ROOT"
|
|
30
|
+
ROBIN_VENV_DIR="$ROBIN_ROOT/.venv"
|
|
31
|
+
ROBIN_ACTIVE_ENV_FILE="$ROBIN_ROOT/.env"
|
|
32
|
+
ROBIN_ACTIVE_INVESTIGATIONS_DIR="$ROBIN_ROOT/investigations"
|
|
33
|
+
else
|
|
34
|
+
ROBIN_LAYOUT="managed"
|
|
35
|
+
ROBIN_APP_DIR="$ROBIN_MANAGED_APP_DIR"
|
|
36
|
+
ROBIN_VENV_DIR="$ROBIN_MANAGED_VENV_DIR"
|
|
37
|
+
ROBIN_ACTIVE_ENV_FILE="$ROBIN_ENV_FILE"
|
|
38
|
+
ROBIN_ACTIVE_INVESTIGATIONS_DIR="$ROBIN_INVESTIGATIONS_DIR"
|
|
39
|
+
fi
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
_robin_refresh_layout
|
|
43
|
+
|
|
44
|
+
_robin_is_installed() {
|
|
45
|
+
[[ -d "$ROBIN_APP_DIR/.git" && -x "$ROBIN_VENV_DIR/bin/python" ]]
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
_robin_python_path() {
|
|
49
|
+
if [[ -x "$ROBIN_VENV_DIR/bin/python" ]]; then
|
|
50
|
+
printf '%s\n' "$ROBIN_VENV_DIR/bin/python"
|
|
51
|
+
elif command -v python3 &>/dev/null; then
|
|
52
|
+
command -v python3
|
|
53
|
+
else
|
|
54
|
+
return 1
|
|
55
|
+
fi
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
_robin_socket_open() {
|
|
59
|
+
local host="$1"
|
|
60
|
+
local port="$2"
|
|
61
|
+
local python
|
|
62
|
+
python=$(_robin_python_path) || return 1
|
|
63
|
+
|
|
64
|
+
"$python" -c '
|
|
65
|
+
import socket
|
|
66
|
+
import sys
|
|
67
|
+
|
|
68
|
+
try:
|
|
69
|
+
with socket.create_connection((sys.argv[1], int(sys.argv[2])), timeout=1):
|
|
70
|
+
pass
|
|
71
|
+
except OSError:
|
|
72
|
+
raise SystemExit(1)
|
|
73
|
+
' "$host" "$port" &>/dev/null
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
_robin_http_healthy() {
|
|
77
|
+
if command -v curl &>/dev/null; then
|
|
78
|
+
[[ "$(curl --fail --silent --show-error --max-time 2 \
|
|
79
|
+
"http://127.0.0.1:$ROBIN_PORT/_stcore/health" 2>/dev/null)" == "ok" ]]
|
|
80
|
+
return $?
|
|
81
|
+
fi
|
|
82
|
+
|
|
83
|
+
local python
|
|
84
|
+
python=$(_robin_python_path) || return 1
|
|
85
|
+
"$python" -c '
|
|
86
|
+
import sys
|
|
87
|
+
import urllib.request
|
|
88
|
+
|
|
89
|
+
try:
|
|
90
|
+
with urllib.request.urlopen(sys.argv[1], timeout=2) as response:
|
|
91
|
+
body = response.read().decode().strip()
|
|
92
|
+
except Exception:
|
|
93
|
+
raise SystemExit(1)
|
|
94
|
+
raise SystemExit(0 if body == "ok" else 1)
|
|
95
|
+
' "http://127.0.0.1:$ROBIN_PORT/_stcore/health" &>/dev/null
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
_robin_proc_start_time() {
|
|
99
|
+
local pid="$1"
|
|
100
|
+
local -a stat_fields=()
|
|
101
|
+
[[ -r "$ROBIN_PROC_ROOT/$pid/stat" ]] || return 1
|
|
102
|
+
read -r -a stat_fields < "$ROBIN_PROC_ROOT/$pid/stat" || return 1
|
|
103
|
+
[[ ${#stat_fields[@]} -ge 22 ]] || return 1
|
|
104
|
+
[[ "${stat_fields[2]}" != "Z" && "${stat_fields[2]}" != "X" ]] || return 1
|
|
105
|
+
printf '%s\n' "${stat_fields[21]}"
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
_robin_process_matches() {
|
|
109
|
+
local pid="$1"
|
|
110
|
+
local recorded_start="${2:-}"
|
|
111
|
+
[[ "$pid" =~ ^[1-9][0-9]*$ ]] || return 1
|
|
112
|
+
kill -0 "$pid" 2>/dev/null || return 1
|
|
113
|
+
|
|
114
|
+
local current_start
|
|
115
|
+
current_start=$(_robin_proc_start_time "$pid") || return 1
|
|
116
|
+
if [[ -n "$recorded_start" && "$current_start" != "$recorded_start" ]]; then
|
|
117
|
+
return 1
|
|
118
|
+
fi
|
|
119
|
+
|
|
120
|
+
local cmdline=""
|
|
121
|
+
if [[ -r "$ROBIN_PROC_ROOT/$pid/cmdline" ]]; then
|
|
122
|
+
cmdline=$(tr '\0' ' ' < "$ROBIN_PROC_ROOT/$pid/cmdline")
|
|
123
|
+
fi
|
|
124
|
+
[[ "$cmdline" == *"streamlit"* && "$cmdline" == *"ui.py"* ]] || return 1
|
|
125
|
+
|
|
126
|
+
local process_cwd=""
|
|
127
|
+
process_cwd=$(readlink -f "$ROBIN_PROC_ROOT/$pid/cwd" 2>/dev/null || true)
|
|
128
|
+
[[ "$process_cwd" == "$ROBIN_APP_DIR" ]] || return 1
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
_robin_read_pid() {
|
|
132
|
+
ROBIN_PID=""
|
|
133
|
+
ROBIN_PID_START=""
|
|
134
|
+
[[ -r "$ROBIN_PID_FILE" ]] || return 1
|
|
135
|
+
read -r ROBIN_PID ROBIN_PID_START < "$ROBIN_PID_FILE" || return 1
|
|
136
|
+
[[ "$ROBIN_PID" =~ ^[1-9][0-9]*$ && "$ROBIN_PID_START" =~ ^[1-9][0-9]*$ ]]
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
_robin_managed_process_running() {
|
|
140
|
+
_robin_read_pid || return 1
|
|
141
|
+
_robin_process_matches "$ROBIN_PID" "$ROBIN_PID_START"
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
_robin_runtime_active() {
|
|
145
|
+
_robin_managed_process_running || _robin_socket_open 127.0.0.1 "$ROBIN_PORT"
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
_robin_find_matching_processes() {
|
|
149
|
+
local process_dir pid
|
|
150
|
+
for process_dir in "$ROBIN_PROC_ROOT"/[0-9]*; do
|
|
151
|
+
[[ -d "$process_dir" ]] || continue
|
|
152
|
+
pid=${process_dir##*/}
|
|
153
|
+
_robin_process_matches "$pid" && printf '%s\n' "$pid"
|
|
154
|
+
done
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
_robin_write_pid() {
|
|
158
|
+
local pid="$1"
|
|
159
|
+
local start_time
|
|
160
|
+
start_time=$(_robin_proc_start_time "$pid") || return 1
|
|
161
|
+
mkdir -p "$KARNEL_RUN"
|
|
162
|
+
chmod 700 "$KARNEL_RUN" 2>/dev/null || true
|
|
163
|
+
local temporary="$ROBIN_PID_FILE.tmp.$$"
|
|
164
|
+
(umask 077; printf '%s %s\n' "$pid" "$start_time" > "$temporary") || return 1
|
|
165
|
+
mv "$temporary" "$ROBIN_PID_FILE"
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
_robin_acquire_lock() {
|
|
169
|
+
mkdir -p "$KARNEL_RUN"
|
|
170
|
+
chmod 700 "$KARNEL_RUN" 2>/dev/null || true
|
|
171
|
+
|
|
172
|
+
if mkdir "$ROBIN_LOCK_DIR" 2>/dev/null; then
|
|
173
|
+
(umask 077; printf '%s\n' "$$" > "$ROBIN_LOCK_DIR/pid")
|
|
174
|
+
return 0
|
|
175
|
+
fi
|
|
176
|
+
|
|
177
|
+
local owner=""
|
|
178
|
+
[[ -r "$ROBIN_LOCK_DIR/pid" ]] && read -r owner < "$ROBIN_LOCK_DIR/pid"
|
|
179
|
+
if [[ "$owner" =~ ^[1-9][0-9]*$ ]] && kill -0 "$owner" 2>/dev/null; then
|
|
180
|
+
log_error "Another Robin operation is already running (PID: $owner)"
|
|
181
|
+
return 1
|
|
182
|
+
fi
|
|
183
|
+
|
|
184
|
+
rm -f "$ROBIN_LOCK_DIR/pid"
|
|
185
|
+
rmdir "$ROBIN_LOCK_DIR" 2>/dev/null || {
|
|
186
|
+
log_error "Could not clear stale Robin lock: $ROBIN_LOCK_DIR"
|
|
187
|
+
return 1
|
|
188
|
+
}
|
|
189
|
+
mkdir "$ROBIN_LOCK_DIR" || return 1
|
|
190
|
+
(umask 077; printf '%s\n' "$$" > "$ROBIN_LOCK_DIR/pid")
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
_robin_release_lock() {
|
|
194
|
+
rm -f "$ROBIN_LOCK_DIR/pid"
|
|
195
|
+
rmdir "$ROBIN_LOCK_DIR" 2>/dev/null || true
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
_robin_rotate_log() {
|
|
199
|
+
[[ -f "$ROBIN_LOG" ]] || return 0
|
|
200
|
+
local size
|
|
201
|
+
size=$(wc -c < "$ROBIN_LOG" 2>/dev/null || printf '0')
|
|
202
|
+
if (( size > 1048576 )); then
|
|
203
|
+
mv -f "$ROBIN_LOG" "$ROBIN_LOG.1"
|
|
204
|
+
fi
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
_robin_print_disclaimer() {
|
|
208
|
+
echo
|
|
209
|
+
box "ATENCAO - USO RESPONSAVEL"
|
|
210
|
+
echo
|
|
211
|
+
log_warn "Use Robin somente em pesquisas legais, autorizadas e eticas."
|
|
212
|
+
log_info "Tor melhora a privacidade da conexao, mas nao garante anonimato."
|
|
213
|
+
log_info "O Robin acessa paginas automaticamente; nao execute nem abra arquivos desconhecidos."
|
|
214
|
+
log_info "Consultas, URLs, conteudo coletado e resumos podem ser enviados diretamente"
|
|
215
|
+
log_info "ao provedor de IA configurado, fora da rede Tor, e processados por terceiros."
|
|
216
|
+
log_info "Investigacoes sao salvas localmente em texto simples. Minimize dados pessoais"
|
|
217
|
+
log_info "e siga as leis, politicas institucionais e termos dos provedores aplicaveis."
|
|
218
|
+
log_info "Resultados de IA podem estar errados e nao constituem evidencia verificada."
|
|
219
|
+
log_info "A interface deve permanecer em 127.0.0.1; nunca exponha a porta $ROBIN_PORT."
|
|
220
|
+
log_info "Robin e um projeto independente: $ROBIN_DOCS_URL"
|
|
221
|
+
echo
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
_robin_notice_accepted() {
|
|
225
|
+
[[ -r "$ROBIN_ACK_FILE" ]] || return 1
|
|
226
|
+
grep -qx "notice_version=$ROBIN_NOTICE_VERSION" "$ROBIN_ACK_FILE" 2>/dev/null
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
_robin_require_acknowledgement() {
|
|
230
|
+
local explicit_accept="${1:-false}"
|
|
231
|
+
_robin_notice_accepted && return 0
|
|
232
|
+
|
|
233
|
+
if [[ "$explicit_accept" == "true" ]]; then
|
|
234
|
+
:
|
|
235
|
+
elif [[ -t 0 ]]; then
|
|
236
|
+
log_info "Digite 'yes' para confirmar que leu e aceita o aviso acima:"
|
|
237
|
+
local confirmation=""
|
|
238
|
+
read -r confirmation
|
|
239
|
+
if [[ "$confirmation" != "yes" ]]; then
|
|
240
|
+
log_error "Confirmacao necessaria para iniciar o Robin"
|
|
241
|
+
return 1
|
|
242
|
+
fi
|
|
243
|
+
else
|
|
244
|
+
log_error "Uso nao interativo requer: karnel robin start --accept-responsible-use"
|
|
245
|
+
return 1
|
|
246
|
+
fi
|
|
247
|
+
|
|
248
|
+
mkdir -p "$ROBIN_CONFIG_DIR"
|
|
249
|
+
chmod 700 "$ROBIN_CONFIG_DIR" 2>/dev/null || true
|
|
250
|
+
local temporary="$ROBIN_ACK_FILE.tmp.$$"
|
|
251
|
+
{
|
|
252
|
+
umask 077
|
|
253
|
+
printf 'notice_version=%s\naccepted_at=%s\n' \
|
|
254
|
+
"$ROBIN_NOTICE_VERSION" "$(date -u +%Y-%m-%dT%H:%M:%SZ)" > "$temporary"
|
|
255
|
+
} || return 1
|
|
256
|
+
mv "$temporary" "$ROBIN_ACK_FILE"
|
|
257
|
+
log_success "Confirmacao registrada para o aviso $ROBIN_NOTICE_VERSION"
|
|
258
|
+
}
|