Repository navigation
pt AI AGENTS
Languages: English | العربية | Čeština | Deutsch | Español | فارسی | Français | हिन्दी | Bahasa Indonesia | Italiano | 日本語 | 한국어 | Nederlands | Polski | Português | Русский | Svenska | ไทย | Türkçe | Tiếng Việt | 中文
O VDBackup é construído para que um assistente ou agente de IA possa administrar toda ação e conteúdo do módulo de forma headless, do mesmo jeito que uma pessoa faz pela WebUI. A WebUI é apenas um cliente de uma pequena API JSON; seu agente é outro. Use a API, não raspe a WebUI.
Tudo passa por um único ponto de entrada, executado como root no dispositivo:
sh /data/adb/modules/vdbackup/scripts/helper.sh <verb> <base64(JSON-args)>
- Os argumentos são um único objeto JSON, codificado em base64, passado como um único token argv.
- O comando imprime um objeto JSON no stdout:
{"ok":true,...}ou{"ok":false,"code":"ERR_...","message":"..."}. Faça o parse disso; nunca raspe texto. - Operações longas (
backup,restore,import) retornam{"ok":true,"opid":"..."}imediatamente e rodam destacadas (sobrevivem à saída do chamador/WebUI). Faça poll do progresso delas; elas não estão concluídas quando a chamada retorna. -
progressecancelrecebem o base64 da string opid crua, não um objeto JSON.
Um pequeno helper para o seu shell:
b64() { printf '%s' "$1" | base64 -w0; }
H=/data/adb/modules/vdbackup/scripts/helper.sh
sh "$H" backup "$(b64 '{"package":"com.example.app","mode":"full"}')"Para dirigi-lo a partir de uma estação de trabalho, rode isso pelo seu canal root habitual até o dispositivo
(adb shell como root, ou um setup de SSH-para-root). O módulo entrega binários embarcados, então
uma vez instalado ele não precisa de nenhuma internet para backup/restauração local; apenas destinos
de nuvem (rclone/restic/ssh) falam com a rede.
| Verbo | Args (JSON) | Retorna |
|---|---|---|
ping |
{} |
{ok,version,abi} |
overview |
{user?} |
{ok:true,apps,instances,path_backups,jobs,backups_size,free,total} contagens (tamanhos em bytes): apps com backups, total de instâncias de backup, backups de caminho avulsos, jobs agendados, tamanho total dos backups, e o livre/total do sistema de arquivos dos backups. Não destacada, retorna imediatamente; usada pelo overview inicial da WebUI. |
config-get |
{} |
{ok,config} |
config-set |
o objeto de config (ou {key,value}) |
{ok} |
keygen |
{} |
gera o par de chaves age para criptografia |
list-apps |
{user?} |
{ok,apps:[{package,label,system,versionCode}]} (dex, fallback shell) |
label |
{package,user?} |
{ok,label} (nome real localizado do app, sem contexto) |
icon |
{package,user?,vc?} |
{ok,package,icon} (PNG base64; cacheado por package+vc) |
backup |
veja abaixo |
{ok,opid} (destacada) |
restore |
veja abaixo |
{ok,opid} (destacada) |
import |
{from,ref,password,ssaid,user} |
{ok,opid} (destacada) |
import-scan |
{from,path} |
{ok,backups:[...]} |
progress |
base64(opid) | o progress-<opid>.json ao vivo |
cancel |
base64(opid) | {ok,cancelled} |
list-ops |
{} |
{ok,ops:[...]} (reatar após reconectar) |
list-apps/icons
|
{user?} / {user?,items:[{package,vc}]}
|
lista de apps / ícones base64 em lote |
list-backups |
{package?} |
{ok,backups:[{ref,package,label,versionName,versionCode,created_at,mode,items}]} |
list-users |
{} |
{ok,users:[{id,name}]} usuários Android do dispositivo (multiusuário). |
list-dirs |
{path} |
{ok,path,parent,dirs:[...]} subdiretórios de um caminho (seletor de pastas). |
path-list |
{user?} |
{ok,backups:[...]} backups avulsos de pasta/arquivo. |
provenance |
{} |
manifesto de auditoria dos binários embarcados (PROVENANCE.json). |
backup-info |
{ref} |
{ok,...} todos os detalhes de um backup (versão, fonte de instalação, estado, data, modo, tamanho, itens, contagens de permissão, dispositivo) |
backup-icon |
{ref} |
{ok,icon} PNG base64 do manifesto (funciona quando o app está desinstalado) |
delete-backup |
{ref} |
{ok,deleted} (ref deve estar sob o diretório de backups) |
prune |
{package,user?,keep} |
{ok,pruned:[...]} mantém os N mais recentes de um pacote |
log-read |
{limit?} |
{ok,entries:[...]} log de auditoria, do mais recente para o mais antigo |
log-export |
{user?} |
{ok:true,path} (caminho absoluto de um .txt gravado sob o diretório de backups) ou {ok:false,code:"ERR_LOG_EXPORT"}. Grava o log de atividades (audit.jsonl) mais um breve cabeçalho de build/dispositivo em um único arquivo de texto visível ao usuário, para que possa ser anexado a um relatório de bug. Não destacada, retorna imediatamente. |
special-categories |
{} |
{ok,categories:[{id,available}]} (messages/contacts/wifi/bluetooth/calendar/wallpaper/dns/system_settings) |
special-backup |
{categories,compression?,password?,portable?} |
{ok,opid} backup de todo o sistema (destacada) |
special-restore |
{ref,confirm:true,categories?,password?} |
{ok,opid} (precisa de reboot; confirm o protege) |
special-list |
{} |
{ok,backups:[{ref,created_at,categories}]} |
path-backup |
{path,compression?,password?} |
{ok,opid} faz backup de qualquer caminho absoluto como tar.zst+manifest.json sob .paths/ (destacada) |
path-restore |
{ref,confirm:true,password?} |
{ok,opid} restaura um backup de caminho para seu local original (confirm o protege; destacada) |
sysmount-status |
{} |
{ok,nomount,nm,ksu,live_capable} |
sysmount-add / sysmount-del / sysmount-list
|
{package,priv?} |
monta um app instalado como app de sistema (sub-módulo sem sistema; ao vivo via NoMount, senão no próximo boot) |
companion-status / companion-install
|
{} |
status do companheiro do Google Drive / instalação sob demanda |
dests-list / dest-add / dest-test / dest-del
|
{id,type,...} |
gerenciamento de destinos |
remote-add / remote-list / remote-del
|
{name,backend,params:{...}} |
gerenciamento de remotos rclone (cria a entrada rclone.conf para a qual um dest type:"rclone" aponta); backend pode ser qualquer backend rclone, sem lista de permissões |
remote-authorize |
{backend} |
{ok:true,url} (o motor já abriu o navegador do telefone nessa URL de consentimento via uma intent VIEW do Android) ou {ok:false,code:"ERR_AUTHORIZE"}. Roda rclone authorize <backend> num servidor de callback local (127.0.0.1:53682) para OAuth no dispositivo. |
remote-authorize-poll |
{} |
{ok:true,done:false,url} enquanto aguarda, {ok:true,done:true,token} quando o usuário consente (o token a passar para remote-add), ou {ok:false,code:"ERR_AUTHORIZE"}. |
remote-authorize-cancel |
{} |
{ok:true,cancelled:true}; interrompe uma autorização pendente. |
cloud-status |
{} |
{ok,rclone,restic,fetchable,size} (se os binários rclone/restic estão presentes, se esta edição lite consegue buscá-los, tamanho do download em bytes) |
cloud-fetch |
{} |
{ok,opid} (destacada) baixa+verifica+instala o addon rclone/restic numa edição lite
|
schedule-set / schedule-list / schedule-delete
|
veja abaixo | jobs agendados (um backup ou uma restauração; alvo de um app, um conjunto, ou todos os apps) |
scheduler-tick |
{} |
roda jobs vencidos + aplica retenção + o observador de auto-backup (o heartbeat de boot chama isto) |
update-check |
{} |
{ok,current_version,current_code,latest_version,latest_code,update_available,zipUrl,changelog,notes} (não destacada; retorna imediatamente; ERR_UPDATE_CHECK em caso de falha - veja abaixo) |
Fazer poll de progress retorna o progress-<opid>.json ao vivo da operação. Estes campos
estão sempre presentes:
| Campo | Tipo | Significado |
|---|---|---|
opid |
string | o id da operação |
percent |
int | 0-100 de conclusão |
phase |
string | o label da fase atual |
item |
string | o tipo de item sendo processado no momento |
done |
bool | true numa escrita terminal (finish / dry-run / restore-test) |
Uma operação em andamento também pode carregar estes campos ao vivo opcionais. Eles ficam ausentes ou vazios quando desconhecidos, e são omitidos nas escritas terminais (finish / dry-run / restore-test):
| Campo | Tipo | Significado |
|---|---|---|
rate |
string | velocidade de transferência, ex. "4.2 MiB/s" (vazio = desconhecido) |
eta |
string | tempo restante estimado, ex. "1m12s" (vazio = desconhecido) |
n |
int | índice do item atual (0 = desconhecido) |
of |
int | total de itens (0 = desconhecido) |
cur |
string | nome do item atual (vazio = nenhum) |
Transferências de nuvem preenchem rate/eta (o percent vem do rclone); backups Full locais
preenchem n/of/cur. Os labels de fase incluem a fase de selo de checksum verified e,
para transferências de nuvem, transfer e mirror <item>.
{
"package": "com.example.app",
"user": 0,
"mode": "full", // full | snapshot | mirror
"compression": "zstd:10", // none | lz4 | zstd[:N] | gzip
"items": ["apk","data","data_de","obb","external","media"],
"encrypt_data": false,
"encrypt_apk": false,
"dest": "local", // local | <destination id>
"verify": true, // re-hash each archive vs the manifest (default on for Full)
"dry_run": false, // true = report a size plan, write nothing
"ssaid": false, // OPT-IN, see below
"manual": false // true = single interactive backup, keeps these exact items;
// omit/false lets config.app_items (a per-app item map) override
// the set on bulk, auto and scheduled runs
}restore/import recebem {ref} (um dir de backup / ref de scan). restore também aceita:
"items" (um subconjunto dos tipos de item do backup a restaurar; omita para todos), "test": true
(extrai para um dir temporário e verifica, sem tocar no app vivo), "mode" para
snapshot/mirror, "password" para um backup criptografado, "ssaid" (opt-in), e as
opções de fonte de instalação "spoof_installer" (padrão vindo da config, define o instalador como a
Play Store no momento da instalação) e "deep_spoof": true (opt-in avançado; também forja o
pacote iniciador e a fonte do pacote editando o banco de pacotes, aplica-se após um
reboot). import recebe "from": "neo" | "databackup" e, para um backup Neo criptografado,
"password".
Um job de agendamento escolhe um alvo e uma ação:
{
"id": "nightly-games",
"action": "backup", // "backup" (padrão) | "restore"
"package": "com.example.app", // um app - OU -
"packages": ["com.a","com.b"], // um conjunto de apps - OU -
"all": true, // todos os apps, menos a lista de apps excluídos
"cron": "daily", // hourly | daily | weekly
"at": "02:30", // HH:MM
"mode": "full",
"dest": "local",
"keep": 5,
"items": ["apk","data"],
"require_wifi": false, // gate: só roda no Wi-Fi
"require_charging": false, // gate: só roda enquanto carregando
"min_battery": 0, // gate: só roda com bateria >= este % (0-100)
"days": [1,2,3,4,5] // gate: só roda nestes dias da semana (0=domingo)
}Dê exatamente um de package, packages ou all para o alvo. Um job backup
mantém os habituais mode/dest/keep/items. Um job restore (action: "restore")
restaura o backup mais recente de cada app-alvo (ou um ref explícito) e sobrescreve
os dados atuais do app a cada execução - é deliberado e opt-in, então defina isto só a um
pedido direto do usuário.
Um job agendado pode carregar condições de gate opcionais. Quando o gate de um job vencido
não é atendido, ele é pulado e tentado de novo no próximo tick, sem avançar seu agendamento
(seu last_run não é carimbado, então ele dispara assim que a condição se cumpre):
| Campo | Tipo | Gate |
|---|---|---|
require_wifi |
bool | só roda enquanto no Wi-Fi |
require_charging |
bool | só roda enquanto carregando |
min_battery |
int (0-100) | só roda com a bateria neste nível ou acima |
days |
array de int (0-6, 0=domingo) | só roda nestes dias da semana |
Uma checagem mínima de segurança térmica é sempre aplicada além destas: uma op agendada é
pulada enquanto o dispositivo está criticamente quente. Todo skip de gate é escrito na trilha de
auditoria como op:"scheduler-gated" com um reason de wifi / charging / battery / days
/ thermal.
Um destino de nuvem é um dest type:"rclone" que nomeia um remoto rclone; crie
esse remoto primeiro com remote-add. O backend pode ser qualquer backend rclone - não há
lista de permissões. O remote-add aceita qualquer nome de backend (dropbox, onedrive,
box, pcloud, mega, b2, s3, sftp, smb, webdav, ftp, drive e os ~70 outros que
o rclone suporta), e os params são repassados diretamente para a config do rclone como pares
key=value. Campos de senha são guardados obscurecidos, nunca em claro. Backends comuns e seus
params:
sftp : host, port, user, pass smb : host, port, user, pass
ftp : host, port, user, pass webdav: url, vendor, user, pass
s3 : provider, access_key_id, secret_access_key, endpoint, region
drive : token, scope (token = output of `rclone authorize "drive"`)
OAuth no dispositivo (sem PC). Backends que precisam de login no navegador (Google Drive,
Dropbox, OneDrive, Box, pCloud) não exigem um computador nem um token colado manualmente. Chame
remote-authorize com {backend}: o motor roda rclone authorize <backend> contra um servidor
de callback local (127.0.0.1:53682) e abre o próprio navegador do telefone na página de
consentimento do provedor via uma intent VIEW do Android, retornando {ok:true,url} (ou
{ok:false,code:"ERR_AUTHORIZE"}). Faça poll de remote-authorize-poll ({}): retorna
{ok:true,done:false,url} enquanto aguarda e {ok:true,done:true,token} quando o usuário aprova
- passe esse
tokenpararemote-add.remote-authorize-cancel({}) interrompe uma autorização pendente ({ok:true,cancelled:true}). Colar manualmente o output derclone authorize "<backend>"de qualquer computador ainda é suportado como fallback.
O Google Drive tem dois caminhos: este remoto drive (sem precisar de projeto Google Cloud, usa
o OAuth próprio do rclone - autorize no dispositivo com remote-authorize, ou rode
rclone authorize "drive" uma vez em qualquer computador e passe o token) ou o app companheiro
opt-in (seu próprio client id OAuth). Ambos terminam como destinos comuns.
O campo de config network_policy controla qual conexão as transferências de nuvem podem usar:
any (padrão), wifi, ou mobile. Defina-o com config-set. Quando for wifi ou
mobile, toda transferência de nuvem (upload Full rclone/Drive, sync Mirror, backup/restauração
de snapshot restic remoto, restauração Mirror) checa o transporte ativo primeiro e
aborta com ERR_NET_POLICY se não casar - tanto para jobs manuais quanto agendados.
Destinos locais nunca são gateados.
-
Selo de checksum (nuvem). Após uma cópia de nuvem bem-sucedida, o engine roda uma checagem
de checksum remota (
rclone check); uma divergência falha a op comERR_VERIFY. Backends que não compartilham nenhum hash em comum com o lado local são pulados (não é uma falha). -
Checagem de cota (nuvem, modo Full). Antes de um upload em modo Full para um remoto
rclone, o engine consulta o espaço livre do remoto (rclone about --json) e recusa comERR_QUOTAse o backup não couber. Remotos que não reportam informação de cota são pulados. O modo Mirror é um delta sync e está isento.
Uma edição full entrega todos os binários embarcados e nunca precisa de rede. A edição lite
omite os dois maiores, rclone e restic, e os busca sob demanda na primeira vez que você roda
uma ação de nuvem ou snapshot. cloud-status informa se eles já estão presentes, se esta edição
consegue buscá-los, e o tamanho do download em bytes. cloud-fetch roda destacada (faça poll
de progress com o opid dela): baixa o addon rclone+restic por arquitetura, verifica-o
contra o SHA-256 embutido no módulo, e o instala no cache de runtime. Suas fases de progresso são
downloading, verifying e installing; o código final é ERR_NONE em caso de sucesso, ou
ERR_FETCH (download falhou) / ERR_FETCH_VERIFY (checksum não bate, descartado) em caso de
falha. Numa edição full ela é desnecessária. Um backup/restore para um destino de nuvem ou
snapshot numa edição lite, antes de os binários estarem presentes, falha com
ERR_CLOUD_FETCHABLE; o cliente deve oferecer rodar cloud-fetch, e então tentar de novo.
special-categories informa quais categorias de todo o sistema um dispositivo tem;
special-backup captura as que você passa em categories e special-restore as reaplica.
As categorias são:
| Categoria | O que é | Semântica de restauração |
|---|---|---|
messages |
SMS/MMS | substituição no provider (apaga + extrai) |
contacts |
contatos e registro de chamadas | substituição no provider (apaga + extrai) |
wifi |
redes Wi-Fi salvas | substituição no provider (apaga + extrai) |
bluetooth |
pareamentos Bluetooth | substituição no provider (apaga + extrai) |
calendar |
o provider de calendário (com.android.providers.calendar, app + dados); também exportado de forma portátil para calendar.json
|
substituição no provider (apaga + extrai) |
wallpaper |
papel de parede da tela inicial e de bloqueio mais wallpaper_info.xml, guardado cru (binário) |
arquivos substituídos |
dns |
o modo e o especificador de DNS privado, lidos das settings |
settings put idempotente |
system_settings |
o dump completo das settings system/global/secure |
opt-in, settings put idempotente, sobrescreve as configurações do dispositivo |
system_settings é estritamente opt-in e destrutivo na restauração. Como o ssaid, ele
sobrescreve as configurações de todo o dispositivo quando é restaurado, então é protegido por
consentimento explícito do usuário e escrito na trilha de auditoria. Nunca o selecione por
padrão; só a um pedido direto e deliberado do usuário.
path-backup / path-restore fazem backup e restauram qualquer caminho absoluto - uma
pasta ou um único arquivo - no armazenamento compartilhado ou sob /data, fora do modelo
por-app. O archive é escrito como tar.zst mais um manifest.json no formato próprio do
VDBackup (selado com SHA-256, com um kit RECOVERY quando criptografado) sob .paths/ no
diretório de backups.
// path-backup
{ "path": "/sdcard/DCIM/Camera", "compression": "zstd:10", "password": "..." }
// path-restore
{ "ref": "<.paths ref>", "confirm": true, "password": "..." }- O caminho de origem deve ser absoluto e estar sob uma das roots permitidas:
/storage/emulated,/data/media,/sdcard,/data. Um caminho que não existe falha comERR_NO_PATH; um caminho fora das roots permitidas, ou um que contenha.., falha comERR_BAD_PATH. -
path-restoreescreve de volta no local original, então é destrutivo e exige"confirm": true- um portão de alto atrito, como ospecial-restore. Umrefque não é um backup de caminho válido falha comERR_BAD_REF. - Ambos rodam destacados; faça poll de
progresscom oopidretornado.
update-check informa se uma versão mais nova do módulo foi publicada, para que um agente
(ou a WebUI) possa exibi-la. É um verbo de leitura que retorna imediatamente - não é
destacado, então não há opid para fazer poll. Acionado somente por uma ação explícita do
usuário, ele busca o manifesto de atualização publicado do módulo (a URL updateJson do
module.prop) com o curl embarcado por uma requisição HTTP do lado root - isso roda fora do
WebView, então não está sujeito à CSP da WebUI - e compara o versionCode publicado com o
instalado. Não recebe nenhum argumento.
Em caso de sucesso retorna:
| Campo | Tipo | Significado |
|---|---|---|
ok |
bool | true |
current_version |
string | o versionName instalado |
current_code |
int | o versionCode instalado |
latest_version |
string | o versionName publicado |
latest_code |
int | o versionCode publicado |
update_available |
bool |
true quando latest_code é maior que current_code
|
zipUrl |
string | a URL do zip publicado |
changelog |
string | a URL do changelog publicado |
notes |
string | as notas de versão |
Se não houver URL updateJson, se a requisição de rede falhar, ou se o manifesto não puder ser
parseado, ele retorna {"ok":false,"code":"ERR_UPDATE_CHECK"}.
O update-check apenas informa a disponibilidade e as notas de versão; a atualização em si é
feita pelo seu gerenciador root (KernelSU / APatch / Magisk) através do updateJson do módulo,
nunca por este verbo.
-
ssaidé estritamente opt-in (padrão desligado). Ele faz backup / restaura o ANDROID_ID do dispositivo reescrevendo um arquivo de sistema; uma restauração se aplica só após um reboot, e o arquivo anterior é sempre salvo primeiro para rollback. Só envie"ssaid": truea pedido direto e deliberado do usuário - nunca por padrão. -
Ações mutáveis (restore, delete, import) são destrutivas e são logadas em uma
trilha de auditoria local (
logs/audit.jsonl). A restauração é fiel (apaga-depois-extrai), então ela reverte o app ao estado exato do backup. Confirme a intenção antes de chamá-las. -
system_settingsé opt-in e destrutivo, exatamente como ossaid. Restaurá-lo sobrescreve as configurações de todo o dispositivo, então envie-o só a um pedido direto do usuário; é protegido por consentimento explícito e registrado na trilha de auditoria. -
A restauração é idempotente. Restaurações cruas de provider (messages/contacts/wifi/
bluetooth/calendar) substituem em vez de mesclar - os dados do provider são apagados e o
archive é extraído por cima - então re-restaurar o mesmo backup não pode duplicar linhas.
dnsesystem_settingssão reaplicados comsettings putidempotente. -
A extração de archives é protegida contra path traversal. A restauração roda como root,
então todo archive (restore, import, special-restore, path-restore) é checado antes de qualquer
escrita: um cujos membros usem caminhos absolutos ou contenham
..é rejeitado de antemão comERR_UNSAFE_ARCHIVE, antes que uma única escrita destrutiva aconteça (o GNU tar também roda com--no-absolute-names). Um archive adulterado nunca pode escapar do seu diretório de destino. -
Nunca enfraqueça a preservação (SELinux/uid/gid/modos/xattr) ou a regra do APK (APKs
são sempre comprimidos, nunca criptografados a menos que
encrypt_apkesteja setado). - Trate a saída JSON como a fonte da verdade; cheque
ok/code, faça poll deprogress, e exponha os códigosERR_*em vez de adivinhar.
Veja ARCHITECTURE.md e FILE-STRUCTURE.md para os detalhes internos.
Esta documentação foi gerada com Claude (Anthropic) e é mantida por VD171. Correções e melhorias são bem-vindas - veja CONTRIBUTING.md.