@iola_adm/iola-cli 0.1.32 → 0.1.34
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 +5 -4
- package/package.json +1 -1
- package/src/cli.js +156 -8
- package/wiki//320/232/320/276/320/274/320/260/320/275/320/264/321/213.md +4 -0
- package/wiki//320/237/320/265/321/200/320/262/321/213/320/271-/320/267/320/260/320/277/321/203/321/201/320/272.md +21 -4
- package/wiki//320/237/320/276/320/264/320/272/320/273/321/216/321/207/320/265/320/275/320/270/320/265-/320/223/320/276/321/201/321/203/321/201/320/273/321/203/320/263.md +40 -12
package/README.md
CHANGED
|
@@ -26,16 +26,17 @@ npm --version
|
|
|
26
26
|
|
|
27
27
|
```bash
|
|
28
28
|
npm install -g @iola_adm/iola-cli
|
|
29
|
-
iola
|
|
30
|
-
iola --help
|
|
29
|
+
iola
|
|
31
30
|
```
|
|
32
31
|
|
|
33
32
|
Без глобальной установки:
|
|
34
33
|
|
|
35
34
|
```bash
|
|
36
|
-
npx -y @iola_adm/iola-cli
|
|
35
|
+
npx -y @iola_adm/iola-cli
|
|
37
36
|
```
|
|
38
37
|
|
|
38
|
+
При первом запуске `iola` открывает мастер настройки, затем запускает интерактивный агент. Короткая справка: `iola help`, полный список команд: `iola commands`.
|
|
39
|
+
|
|
39
40
|
Основные команды:
|
|
40
41
|
|
|
41
42
|
```bash
|
|
@@ -121,7 +122,7 @@ iola version --check
|
|
|
121
122
|
- subagents, skill bundles, layered settings, usage/budget accounting и trajectory export;
|
|
122
123
|
- полноценный локальный MCP server по stdio/http: tools, resources и prompts;
|
|
123
124
|
- браузерный runtime через Playwright: чтение страниц, скриншоты, PDF, клики, ввод и eval;
|
|
124
|
-
-
|
|
125
|
+
- личное локальное подключение Госуслуг с явным согласием пользователя и хранением доступа только на его ПК;
|
|
125
126
|
- управляемые локальные файловые операции с режимами `locked`, `read-only`, `workspace-write`, `full-access`;
|
|
126
127
|
- планы выполнения, traces, tasks, artifacts, snapshots и policy-профили;
|
|
127
128
|
- экспорт отчетов в Excel/Word-совместимые файлы;
|
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -31,6 +31,20 @@ const FILE_TOOLS = ["files_tree", "files_read", "files_search", "files_write", "
|
|
|
31
31
|
const ALL_LOCAL_TOOLS = [...LOCAL_TOOLS, ...FILE_TOOLS];
|
|
32
32
|
const HOOK_EVENTS = ["SessionStart", "BeforeTool", "AfterTool", "PreToolUse", "PostToolUse", "OnError", "AfterSync", "BeforeExport", "SessionEnd"];
|
|
33
33
|
const DAEMON_PORT = Number(process.env.IOLA_DAEMON_PORT || 18790);
|
|
34
|
+
const GOSUSLUGI_CONSENT_VERSION = "2026-05-26-personal-local-v1";
|
|
35
|
+
const GOSUSLUGI_CONSENT_TEXT = `Подключение личных Госуслуг
|
|
36
|
+
|
|
37
|
+
Вы подключаете личную учетную запись Госуслуг к локальному CLI-агенту iola-cli на этом компьютере.
|
|
38
|
+
|
|
39
|
+
Нажимая "Да", вы подтверждаете, что:
|
|
40
|
+
- используете собственную учетную запись Госуслуг;
|
|
41
|
+
- понимаете, что все действия, выполненные через CLI-агента после подключения, считаются действиями владельца этой учетной записи;
|
|
42
|
+
- разрешаете iola-cli локально сохранить данные доступа, необходимые для повторного входа или выполнения запросов от вашего имени;
|
|
43
|
+
- понимаете, что данные доступа хранятся только на этом компьютере в локальном хранилище пользователя и не передаются разработчикам CLI, администрации города или третьим лицам;
|
|
44
|
+
- обязуетесь не подключать чужие учетные записи и не передавать локальные файлы доступа другим лицам;
|
|
45
|
+
- понимаете, что перед юридически значимыми действиями, отправкой заявлений, оплатой, подписанием или изменением персональных данных CLI должен запросить отдельное подтверждение.
|
|
46
|
+
|
|
47
|
+
Продолжить подключение?`;
|
|
34
48
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
35
49
|
const BUILTIN_SKILLS_DIR = path.resolve(__dirname, "..", "skills");
|
|
36
50
|
const USER_SKILLS_DIR = path.join(CONFIG_DIR, "skills");
|
|
@@ -112,6 +126,7 @@ const DEFAULT_AI_CONFIG = {
|
|
|
112
126
|
},
|
|
113
127
|
gosuslugi: {
|
|
114
128
|
enabled: false,
|
|
129
|
+
mode: "personal-local",
|
|
115
130
|
authUrl: "",
|
|
116
131
|
tokenUrl: "",
|
|
117
132
|
userinfoUrl: "",
|
|
@@ -265,6 +280,7 @@ const BANNER = `\x1b[38;5;45m┌────────────────
|
|
|
265
280
|
|
|
266
281
|
const COMMANDS = new Map([
|
|
267
282
|
["help", showHelp],
|
|
283
|
+
["commands", showCommands],
|
|
268
284
|
["version", showVersion],
|
|
269
285
|
["update", checkUpdate],
|
|
270
286
|
["doctor", doctor],
|
|
@@ -340,7 +356,12 @@ const COMMANDS = new Map([
|
|
|
340
356
|
]);
|
|
341
357
|
|
|
342
358
|
export async function main(argv) {
|
|
343
|
-
if (argv.length === 0
|
|
359
|
+
if (argv.length === 0) {
|
|
360
|
+
await runDefaultCli();
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
if (argv[0] === "--help" || argv[0] === "-h") {
|
|
344
365
|
await showHelp();
|
|
345
366
|
return;
|
|
346
367
|
}
|
|
@@ -383,6 +404,35 @@ export async function main(argv) {
|
|
|
383
404
|
}
|
|
384
405
|
|
|
385
406
|
async function showHelp() {
|
|
407
|
+
showBanner();
|
|
408
|
+
console.log(`iola - локальный CLI и AI-агент для данных городского округа "Город Йошкар-Ола"
|
|
409
|
+
|
|
410
|
+
Запуск:
|
|
411
|
+
iola открыть интерактивный агент
|
|
412
|
+
iola onboard мастер настройки
|
|
413
|
+
iola ask "найди школу 29" задать вопрос
|
|
414
|
+
iola search "Петрова" поиск по открытым данным
|
|
415
|
+
|
|
416
|
+
Основные разделы:
|
|
417
|
+
iola agent интерактивный режим
|
|
418
|
+
iola ai setup настройка AI-профиля
|
|
419
|
+
iola browser status браузерный runtime
|
|
420
|
+
iola gosuslugi status личное подключение Госуслуг
|
|
421
|
+
iola mcp status MCP-подключение
|
|
422
|
+
iola doctor диагностика
|
|
423
|
+
iola wiki документация
|
|
424
|
+
|
|
425
|
+
Справка:
|
|
426
|
+
iola help короткая справка
|
|
427
|
+
iola commands полный список команд
|
|
428
|
+
iola version версия
|
|
429
|
+
|
|
430
|
+
Requirements:
|
|
431
|
+
Node.js >= ${MIN_NODE_VERSION}
|
|
432
|
+
`);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
async function showCommands() {
|
|
386
436
|
showBanner();
|
|
387
437
|
console.log(`iola - CLI для открытых данных городского округа "Город Йошкар-Ола"
|
|
388
438
|
|
|
@@ -402,7 +452,7 @@ Usage:
|
|
|
402
452
|
iola fork SESSION_ID [TEXT]
|
|
403
453
|
iola features list|enable|disable
|
|
404
454
|
iola settings list|get|validate|doctor|init
|
|
405
|
-
iola gosuslugi configure|status|login|logout|userinfo
|
|
455
|
+
iola gosuslugi terms|consent|configure|status|login|logout|userinfo
|
|
406
456
|
iola wiki [open|links]
|
|
407
457
|
iola context list|show|init
|
|
408
458
|
iola skills list|show|paths|enable|disable|bundles|bundle|doctor
|
|
@@ -494,6 +544,26 @@ Requirements:
|
|
|
494
544
|
`);
|
|
495
545
|
}
|
|
496
546
|
|
|
547
|
+
async function runDefaultCli() {
|
|
548
|
+
const nodeStatus = getNodeRequirementStatus();
|
|
549
|
+
if (!nodeStatus.ok) {
|
|
550
|
+
throw new Error(`Нужен Node.js ${MIN_NODE_VERSION} или новее. Сейчас: ${nodeStatus.current}. Запустите: iola init --upgrade-node`);
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
initDatabase();
|
|
554
|
+
if (!isFirstRunCompleted()) {
|
|
555
|
+
showBanner();
|
|
556
|
+
console.log("Первый запуск iola-cli. Сейчас откроется мастер настройки.");
|
|
557
|
+
console.log("После мастера запустится интерактивный агент.");
|
|
558
|
+
console.log("");
|
|
559
|
+
await onboard([]);
|
|
560
|
+
markFirstRunCompleted();
|
|
561
|
+
console.log("");
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
await startAgent([]);
|
|
565
|
+
}
|
|
566
|
+
|
|
497
567
|
async function startAgent() {
|
|
498
568
|
showBanner();
|
|
499
569
|
console.log("Интерактивный режим. Введите /help для списка команд, /exit для выхода.");
|
|
@@ -1726,13 +1796,27 @@ async function handleGosuslugi(args) {
|
|
|
1726
1796
|
const [action = "status", ...rest] = args;
|
|
1727
1797
|
const options = parseOptions(rest);
|
|
1728
1798
|
|
|
1799
|
+
if (action === "terms") {
|
|
1800
|
+
console.log(GOSUSLUGI_CONSENT_TEXT);
|
|
1801
|
+
return;
|
|
1802
|
+
}
|
|
1803
|
+
|
|
1804
|
+
if (action === "consent") {
|
|
1805
|
+
await acceptGosuslugiConsent(options);
|
|
1806
|
+
return;
|
|
1807
|
+
}
|
|
1808
|
+
|
|
1729
1809
|
if (action === "status") {
|
|
1730
1810
|
const config = await loadConfig();
|
|
1731
1811
|
const secrets = await loadSecrets();
|
|
1732
1812
|
const tokens = secrets.gosuslugi?.tokens || null;
|
|
1813
|
+
const consent = secrets.gosuslugiConsent || null;
|
|
1733
1814
|
printKeyValue({
|
|
1815
|
+
mode: config.gosuslugi?.mode || "personal-local",
|
|
1734
1816
|
enabled: config.gosuslugi?.enabled ? "yes" : "no",
|
|
1735
1817
|
configured: isGosuslugiConfigured(config) ? "yes" : "no",
|
|
1818
|
+
consent: consent?.version === GOSUSLUGI_CONSENT_VERSION ? "accepted" : "not accepted",
|
|
1819
|
+
consentAt: consent?.acceptedAt || "-",
|
|
1736
1820
|
clientId: config.gosuslugi?.clientId ? maskSecret(config.gosuslugi.clientId) : "-",
|
|
1737
1821
|
authUrl: config.gosuslugi?.authUrl || "-",
|
|
1738
1822
|
tokenUrl: config.gosuslugi?.tokenUrl || "-",
|
|
@@ -1750,6 +1834,7 @@ async function handleGosuslugi(args) {
|
|
|
1750
1834
|
const next = {
|
|
1751
1835
|
...(current.gosuslugi || {}),
|
|
1752
1836
|
enabled: true,
|
|
1837
|
+
mode: "personal-local",
|
|
1753
1838
|
authUrl: options["auth-url"] || current.gosuslugi?.authUrl || "",
|
|
1754
1839
|
tokenUrl: options["token-url"] || current.gosuslugi?.tokenUrl || "",
|
|
1755
1840
|
userinfoUrl: options["userinfo-url"] || current.gosuslugi?.userinfoUrl || "",
|
|
@@ -1761,7 +1846,7 @@ async function handleGosuslugi(args) {
|
|
|
1761
1846
|
redirectPath: options["redirect-path"] || current.gosuslugi?.redirectPath || "/gosuslugi/callback",
|
|
1762
1847
|
};
|
|
1763
1848
|
await saveConfig({ gosuslugi: next });
|
|
1764
|
-
console.log("Настройки подключения
|
|
1849
|
+
console.log("Настройки личного локального подключения Госуслуг сохранены.");
|
|
1765
1850
|
console.log(`Redirect URI: ${gosuslugiRedirectUri({ gosuslugi: next })}`);
|
|
1766
1851
|
return;
|
|
1767
1852
|
}
|
|
@@ -1787,7 +1872,7 @@ async function handleGosuslugi(args) {
|
|
|
1787
1872
|
return;
|
|
1788
1873
|
}
|
|
1789
1874
|
|
|
1790
|
-
throw new Error("Команды gosuslugi: configure, status, login, logout, userinfo.");
|
|
1875
|
+
throw new Error("Команды gosuslugi: terms, consent, configure, status, login, logout, userinfo.");
|
|
1791
1876
|
}
|
|
1792
1877
|
|
|
1793
1878
|
async function handleWiki(args) {
|
|
@@ -2734,8 +2819,9 @@ async function openUrl(url) {
|
|
|
2734
2819
|
async function gosuslugiLogin(options = {}) {
|
|
2735
2820
|
const config = await loadConfig();
|
|
2736
2821
|
if (!isGosuslugiConfigured(config)) {
|
|
2737
|
-
throw new Error("
|
|
2822
|
+
throw new Error("Личное подключение не настроено. Пример: iola gosuslugi configure --auth-url URL --token-url URL --client-id ID --scope openid");
|
|
2738
2823
|
}
|
|
2824
|
+
await ensureGosuslugiConsent(options);
|
|
2739
2825
|
|
|
2740
2826
|
const state = randomUrlSafe(24);
|
|
2741
2827
|
const codeVerifier = randomUrlSafe(64);
|
|
@@ -2751,8 +2837,8 @@ async function gosuslugiLogin(options = {}) {
|
|
|
2751
2837
|
authUrl.searchParams.set("code_challenge", codeChallenge);
|
|
2752
2838
|
authUrl.searchParams.set("code_challenge_method", "S256");
|
|
2753
2839
|
|
|
2754
|
-
console.log("Открываю
|
|
2755
|
-
console.log("После входа CLI примет callback на локальном адресе и сохранит
|
|
2840
|
+
console.log("Открываю экран входа Госуслуг в браузере для личного локального подключения.");
|
|
2841
|
+
console.log("После входа CLI примет callback на локальном адресе и сохранит данные доступа только на этом компьютере.");
|
|
2756
2842
|
await openUrl(authUrl.toString());
|
|
2757
2843
|
const params = await callback;
|
|
2758
2844
|
if (params.error) throw new Error(`Госуслуги вернули ошибку: ${params.error} ${params.error_description || ""}`.trim());
|
|
@@ -2781,6 +2867,31 @@ async function gosuslugiLogin(options = {}) {
|
|
|
2781
2867
|
};
|
|
2782
2868
|
}
|
|
2783
2869
|
|
|
2870
|
+
async function acceptGosuslugiConsent(options = {}) {
|
|
2871
|
+
console.log(GOSUSLUGI_CONSENT_TEXT);
|
|
2872
|
+
if (!options.yes) {
|
|
2873
|
+
const accepted = await confirm("Да, подключить личные Госуслуги к локальному iola-cli? [y/N] ");
|
|
2874
|
+
if (!accepted) {
|
|
2875
|
+
throw new Error("Подключение Госуслуг отменено пользователем.");
|
|
2876
|
+
}
|
|
2877
|
+
}
|
|
2878
|
+
const secrets = await loadSecrets();
|
|
2879
|
+
secrets.gosuslugiConsent = {
|
|
2880
|
+
version: GOSUSLUGI_CONSENT_VERSION,
|
|
2881
|
+
acceptedAt: new Date().toISOString(),
|
|
2882
|
+
user: os.userInfo().username,
|
|
2883
|
+
host: os.hostname(),
|
|
2884
|
+
};
|
|
2885
|
+
await saveSecrets(secrets);
|
|
2886
|
+
console.log("Согласие сохранено локально.");
|
|
2887
|
+
}
|
|
2888
|
+
|
|
2889
|
+
async function ensureGosuslugiConsent(options = {}) {
|
|
2890
|
+
const secrets = await loadSecrets();
|
|
2891
|
+
if (secrets.gosuslugiConsent?.version === GOSUSLUGI_CONSENT_VERSION) return;
|
|
2892
|
+
await acceptGosuslugiConsent(options);
|
|
2893
|
+
}
|
|
2894
|
+
|
|
2784
2895
|
function waitForOAuthCallback(settings, expectedState, timeoutMs) {
|
|
2785
2896
|
const host = settings.redirectHost || "127.0.0.1";
|
|
2786
2897
|
const port = Number(settings.redirectPort || 18791);
|
|
@@ -2826,6 +2937,7 @@ async function exchangeGosuslugiCode(config, { code, codeVerifier, redirectUri }
|
|
|
2826
2937
|
body.set("redirect_uri", redirectUri);
|
|
2827
2938
|
body.set("client_id", config.gosuslugi.clientId);
|
|
2828
2939
|
body.set("code_verifier", codeVerifier);
|
|
2940
|
+
body.set("client_mode", config.gosuslugi.mode || "personal-local");
|
|
2829
2941
|
if (config.gosuslugi.clientSecret) body.set("client_secret", config.gosuslugi.clientSecret);
|
|
2830
2942
|
|
|
2831
2943
|
const response = await fetch(config.gosuslugi.tokenUrl, {
|
|
@@ -4364,6 +4476,34 @@ function getDbStatus() {
|
|
|
4364
4476
|
}
|
|
4365
4477
|
}
|
|
4366
4478
|
|
|
4479
|
+
function getMetaValue(key) {
|
|
4480
|
+
initDatabase();
|
|
4481
|
+
const db = openDatabase();
|
|
4482
|
+
try {
|
|
4483
|
+
return db.prepare("SELECT value FROM meta WHERE key = ?").get(key)?.value || null;
|
|
4484
|
+
} finally {
|
|
4485
|
+
db.close();
|
|
4486
|
+
}
|
|
4487
|
+
}
|
|
4488
|
+
|
|
4489
|
+
function setMetaValue(key, value) {
|
|
4490
|
+
initDatabase();
|
|
4491
|
+
const db = openDatabase();
|
|
4492
|
+
try {
|
|
4493
|
+
db.prepare("INSERT INTO meta(key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value").run(key, String(value));
|
|
4494
|
+
} finally {
|
|
4495
|
+
db.close();
|
|
4496
|
+
}
|
|
4497
|
+
}
|
|
4498
|
+
|
|
4499
|
+
function isFirstRunCompleted() {
|
|
4500
|
+
return getMetaValue("first_run_completed") === "1";
|
|
4501
|
+
}
|
|
4502
|
+
|
|
4503
|
+
function markFirstRunCompleted() {
|
|
4504
|
+
setMetaValue("first_run_completed", "1");
|
|
4505
|
+
}
|
|
4506
|
+
|
|
4367
4507
|
function recordAskHistory({ question, answer, providerConfig, dataContext, error, sessionId }) {
|
|
4368
4508
|
try {
|
|
4369
4509
|
initDatabase();
|
|
@@ -6191,7 +6331,14 @@ async function onboard(args = []) {
|
|
|
6191
6331
|
initDatabase();
|
|
6192
6332
|
await handleConfig(["validate"]);
|
|
6193
6333
|
await doctor(["--summary"]);
|
|
6194
|
-
|
|
6334
|
+
if (options.full || options.install) {
|
|
6335
|
+
await ensureArchiveTool({ install: true });
|
|
6336
|
+
} else {
|
|
6337
|
+
const archiveTool = await findCommand(["7z", "7zz", "7za"], ["--help"]);
|
|
6338
|
+
if (!archiveTool) {
|
|
6339
|
+
console.log("7-Zip не найден. Для архивов можно позже запустить: iola archive doctor");
|
|
6340
|
+
}
|
|
6341
|
+
}
|
|
6195
6342
|
|
|
6196
6343
|
const components = options.yes ? ["workspace", "policy", "ollama", "openai", "openrouter", "codex", "codex-mcp", "index"] : await chooseOnboardComponents();
|
|
6197
6344
|
if (components.includes("workspace")) await handleWorkspace(["init"]);
|
|
@@ -6217,6 +6364,7 @@ async function onboard(args = []) {
|
|
|
6217
6364
|
await setFilesMode("read-only", await loadConfig());
|
|
6218
6365
|
console.log("Индекс документов можно запустить командой: iola index folder ./docs");
|
|
6219
6366
|
}
|
|
6367
|
+
markFirstRunCompleted();
|
|
6220
6368
|
console.log("Onboard завершен.");
|
|
6221
6369
|
}
|
|
6222
6370
|
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
6
|
iola --help
|
|
7
|
+
iola help
|
|
8
|
+
iola commands
|
|
7
9
|
iola init
|
|
8
10
|
iola doctor
|
|
9
11
|
iola doctor --fix
|
|
@@ -93,6 +95,8 @@ iola context list
|
|
|
93
95
|
iola settings list
|
|
94
96
|
iola settings validate
|
|
95
97
|
iola gosuslugi status
|
|
98
|
+
iola gosuslugi terms
|
|
99
|
+
iola gosuslugi consent
|
|
96
100
|
iola gosuslugi configure --auth-url URL --token-url URL --client-id ID --scope openid
|
|
97
101
|
iola gosuslugi login
|
|
98
102
|
iola gosuslugi userinfo --json
|
|
@@ -3,16 +3,33 @@
|
|
|
3
3
|
Первый запуск:
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
|
-
iola
|
|
6
|
+
iola
|
|
7
7
|
```
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
При первом запуске команда откроет мастер настройки, а затем запустит интерактивный агент.
|
|
10
|
+
|
|
11
|
+
Мастер проверит:
|
|
10
12
|
|
|
11
13
|
- Node.js и npm;
|
|
12
14
|
- локальную SQLite-БД;
|
|
13
15
|
- доступность публичного API/MCP;
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
+
- обновления npm-пакета;
|
|
17
|
+
- выбранные компоненты: workspace, policy, локальную модель, API-ключи, Codex, MCP, индекс документов.
|
|
18
|
+
|
|
19
|
+
Обычный последующий запуск:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
iola
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Команда сразу откроет интерактивный CLI-агент.
|
|
26
|
+
|
|
27
|
+
Справка:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
iola help
|
|
31
|
+
iola commands
|
|
32
|
+
```
|
|
16
33
|
|
|
17
34
|
Диагностика:
|
|
18
35
|
|
|
@@ -1,19 +1,47 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Личное подключение Госуслуг
|
|
2
2
|
|
|
3
|
-
`iola-cli` поддерживает
|
|
3
|
+
`iola-cli` поддерживает локальное подключение личной учетной записи Госуслуг на компьютере пользователя.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Сценарий рассчитан именно на пользователя, который ставит CLI на свой ПК и подключает свою учетную запись. Ключи организации или администрации в публичный пакет не вшиваются.
|
|
6
|
+
|
|
7
|
+
## Согласие пользователя
|
|
8
|
+
|
|
9
|
+
Перед входом CLI показывает текст согласия:
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
Вы подключаете личную учетную запись Госуслуг к локальному CLI-агенту iola-cli на этом компьютере.
|
|
13
|
+
|
|
14
|
+
Нажимая "Да", вы подтверждаете, что:
|
|
15
|
+
- используете собственную учетную запись Госуслуг;
|
|
16
|
+
- понимаете, что все действия, выполненные через CLI-агента после подключения, считаются действиями владельца этой учетной записи;
|
|
17
|
+
- разрешаете iola-cli локально сохранить данные доступа, необходимые для повторного входа или выполнения запросов от вашего имени;
|
|
18
|
+
- понимаете, что данные доступа хранятся только на этом компьютере в локальном хранилище пользователя и не передаются разработчикам CLI, администрации города или третьим лицам;
|
|
19
|
+
- обязуетесь не подключать чужие учетные записи и не передавать локальные файлы доступа другим лицам;
|
|
20
|
+
- понимаете, что перед юридически значимыми действиями, отправкой заявлений, оплатой, подписанием или изменением персональных данных CLI должен запросить отдельное подтверждение.
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Посмотреть текст:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
iola gosuslugi terms
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Принять заранее:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
iola gosuslugi consent
|
|
33
|
+
```
|
|
6
34
|
|
|
7
35
|
## Настройка
|
|
8
36
|
|
|
9
|
-
Для работы нужны параметры
|
|
37
|
+
Для работы нужны параметры пользовательского OAuth/OIDC-подключения:
|
|
10
38
|
|
|
11
39
|
- authorization endpoint;
|
|
12
40
|
- token endpoint;
|
|
13
41
|
- client ID;
|
|
14
42
|
- разрешенный redirect URI;
|
|
15
43
|
- scope;
|
|
16
|
-
-
|
|
44
|
+
- optional client secret, если он выдан именно пользователю или локальному приложению;
|
|
17
45
|
- optional userinfo endpoint.
|
|
18
46
|
|
|
19
47
|
Команда настройки:
|
|
@@ -34,7 +62,7 @@ CLI покажет redirect URI:
|
|
|
34
62
|
http://127.0.0.1:18791/gosuslugi/callback
|
|
35
63
|
```
|
|
36
64
|
|
|
37
|
-
Этот URI должен быть разрешен в настройках
|
|
65
|
+
Этот URI должен быть разрешен в настройках подключения.
|
|
38
66
|
|
|
39
67
|
## Вход
|
|
40
68
|
|
|
@@ -45,10 +73,11 @@ iola gosuslugi login
|
|
|
45
73
|
Что происходит:
|
|
46
74
|
|
|
47
75
|
1. CLI запускает локальный callback server на `127.0.0.1`.
|
|
48
|
-
2.
|
|
49
|
-
3.
|
|
50
|
-
4.
|
|
51
|
-
5.
|
|
76
|
+
2. Показывается и сохраняется согласие пользователя.
|
|
77
|
+
3. Открывается экран входа Госуслуг.
|
|
78
|
+
4. Пользователь сам вводит логин, пароль, SMS/2FA.
|
|
79
|
+
5. Госуслуги возвращают `authorization code` на локальный callback.
|
|
80
|
+
6. CLI обменивает code на токены и сохраняет их локально.
|
|
52
81
|
|
|
53
82
|
Токены хранятся в `~/.iola/secrets.json` на компьютере пользователя.
|
|
54
83
|
|
|
@@ -69,5 +98,4 @@ iola gosuslugi logout
|
|
|
69
98
|
|
|
70
99
|
## Ограничения
|
|
71
100
|
|
|
72
|
-
Без
|
|
73
|
-
|
|
101
|
+
Без параметров пользовательского подключения команда `login` не сможет завершить подключение. Все ключи, токены и настройки хранятся только локально у пользователя.
|