@dsh-enhanced/lark-channel 0.1.47 → 0.1.49
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 +19 -8
- package/docs/rsi-setup.md +123 -11
- package/docs/setup.md +27 -14
- package/docs/supervised-growth.md +2 -0
- package/lib/adapter.d.ts +6 -0
- package/lib/adapter.d.ts.map +1 -1
- package/lib/adapter.js +79 -8
- package/lib/adapter.js.map +1 -1
- package/lib/business-cli-install.d.ts +9 -0
- package/lib/business-cli-install.d.ts.map +1 -0
- package/lib/business-cli-install.js +367 -0
- package/lib/business-cli-install.js.map +1 -0
- package/lib/business-environment.d.ts +2 -0
- package/lib/business-environment.d.ts.map +1 -0
- package/lib/business-environment.js +16 -0
- package/lib/business-environment.js.map +1 -0
- package/lib/business-skill.d.ts +32 -0
- package/lib/business-skill.d.ts.map +1 -0
- package/lib/business-skill.js +202 -0
- package/lib/business-skill.js.map +1 -0
- package/lib/rsi-authority-config.d.ts +29 -0
- package/lib/rsi-authority-config.d.ts.map +1 -0
- package/lib/rsi-authority-config.js +233 -0
- package/lib/rsi-authority-config.js.map +1 -0
- package/lib/rsi-authority-resources.d.ts +36 -0
- package/lib/rsi-authority-resources.d.ts.map +1 -0
- package/lib/rsi-authority-resources.js +139 -0
- package/lib/rsi-authority-resources.js.map +1 -0
- package/lib/rsi-authority-runtime.d.ts +50 -0
- package/lib/rsi-authority-runtime.d.ts.map +1 -0
- package/lib/rsi-authority-runtime.js +393 -0
- package/lib/rsi-authority-runtime.js.map +1 -0
- package/lib/rsi-bootstrap-manifest.d.ts +39 -0
- package/lib/rsi-bootstrap-manifest.d.ts.map +1 -0
- package/lib/rsi-bootstrap-manifest.js +366 -0
- package/lib/rsi-bootstrap-manifest.js.map +1 -0
- package/lib/rsi-bootstrap.d.ts +30 -0
- package/lib/rsi-bootstrap.d.ts.map +1 -0
- package/lib/rsi-bootstrap.js +363 -0
- package/lib/rsi-bootstrap.js.map +1 -0
- package/lib/rsi-build.d.ts +45 -0
- package/lib/rsi-build.d.ts.map +1 -0
- package/lib/rsi-build.js +404 -0
- package/lib/rsi-build.js.map +1 -0
- package/lib/rsi-creation-build.d.ts +47 -0
- package/lib/rsi-creation-build.d.ts.map +1 -0
- package/lib/rsi-creation-build.js +333 -0
- package/lib/rsi-creation-build.js.map +1 -0
- package/lib/rsi-host-authorities.d.ts +18 -0
- package/lib/rsi-host-authorities.d.ts.map +1 -0
- package/lib/rsi-host-authorities.js +129 -0
- package/lib/rsi-host-authorities.js.map +1 -0
- package/lib/rsi-host-update.d.ts +113 -0
- package/lib/rsi-host-update.d.ts.map +1 -0
- package/lib/rsi-host-update.js +316 -0
- package/lib/rsi-host-update.js.map +1 -0
- package/lib/rsi-install-inputs.d.ts +43 -0
- package/lib/rsi-install-inputs.d.ts.map +1 -0
- package/lib/rsi-install-inputs.js +342 -0
- package/lib/rsi-install-inputs.js.map +1 -0
- package/lib/rsi-install.d.ts +54 -0
- package/lib/rsi-install.d.ts.map +1 -0
- package/lib/rsi-install.js +404 -0
- package/lib/rsi-install.js.map +1 -0
- package/lib/rsi-local-activation.d.ts +78 -0
- package/lib/rsi-local-activation.d.ts.map +1 -0
- package/lib/rsi-local-activation.js +485 -0
- package/lib/rsi-local-activation.js.map +1 -0
- package/lib/rsi-local-cohort.d.ts +70 -0
- package/lib/rsi-local-cohort.d.ts.map +1 -0
- package/lib/rsi-local-cohort.js +781 -0
- package/lib/rsi-local-cohort.js.map +1 -0
- package/lib/rsi-local-install.d.ts +40 -0
- package/lib/rsi-local-install.d.ts.map +1 -0
- package/lib/rsi-local-install.js +221 -0
- package/lib/rsi-local-install.js.map +1 -0
- package/lib/rsi-local-pair-install.d.ts +38 -0
- package/lib/rsi-local-pair-install.d.ts.map +1 -0
- package/lib/rsi-local-pair-install.js +200 -0
- package/lib/rsi-local-pair-install.js.map +1 -0
- package/lib/rsi-local-profile-update.d.ts +25 -0
- package/lib/rsi-local-profile-update.d.ts.map +1 -0
- package/lib/rsi-local-profile-update.js +226 -0
- package/lib/rsi-local-profile-update.js.map +1 -0
- package/lib/rsi-local-resources.d.ts +37 -0
- package/lib/rsi-local-resources.d.ts.map +1 -0
- package/lib/rsi-local-resources.js +184 -0
- package/lib/rsi-local-resources.js.map +1 -0
- package/lib/rsi-local-roots-extension.d.ts +11 -0
- package/lib/rsi-local-roots-extension.d.ts.map +1 -0
- package/lib/rsi-local-roots-extension.js +31 -0
- package/lib/rsi-local-roots-extension.js.map +1 -0
- package/lib/rsi-local-update-build.d.ts +18 -0
- package/lib/rsi-local-update-build.d.ts.map +1 -0
- package/lib/rsi-local-update-build.js +37 -0
- package/lib/rsi-local-update-build.js.map +1 -0
- package/lib/rsi-local-update.d.ts +39 -0
- package/lib/rsi-local-update.d.ts.map +1 -0
- package/lib/rsi-local-update.js +205 -0
- package/lib/rsi-local-update.js.map +1 -0
- package/lib/rsi-memory-learning.d.ts +22 -0
- package/lib/rsi-memory-learning.d.ts.map +1 -0
- package/lib/rsi-memory-learning.js +76 -0
- package/lib/rsi-memory-learning.js.map +1 -0
- package/lib/rsi-owner-profile.d.ts +37 -0
- package/lib/rsi-owner-profile.d.ts.map +1 -0
- package/lib/rsi-owner-profile.js +178 -0
- package/lib/rsi-owner-profile.js.map +1 -0
- package/lib/rsi-plugin-creation.d.ts +31 -0
- package/lib/rsi-plugin-creation.d.ts.map +1 -0
- package/lib/rsi-plugin-creation.js +179 -0
- package/lib/rsi-plugin-creation.js.map +1 -0
- package/lib/rsi-profile.d.ts +23 -0
- package/lib/rsi-profile.d.ts.map +1 -1
- package/lib/rsi-profile.js +154 -43
- package/lib/rsi-profile.js.map +1 -1
- package/lib/rsi-release-build.d.ts +41 -0
- package/lib/rsi-release-build.d.ts.map +1 -0
- package/lib/rsi-release-build.js +223 -0
- package/lib/rsi-release-build.js.map +1 -0
- package/lib/rsi-service-environment.d.ts +6 -0
- package/lib/rsi-service-environment.d.ts.map +1 -0
- package/lib/rsi-service-environment.js +113 -0
- package/lib/rsi-service-environment.js.map +1 -0
- package/lib/rsi-service-setup.d.ts +10 -0
- package/lib/rsi-service-setup.d.ts.map +1 -0
- package/lib/rsi-service-setup.js +34 -0
- package/lib/rsi-service-setup.js.map +1 -0
- package/lib/rsi-setup.d.ts +35 -2
- package/lib/rsi-setup.d.ts.map +1 -1
- package/lib/rsi-setup.js +459 -32
- package/lib/rsi-setup.js.map +1 -1
- package/lib/rsi-source-maintenance.d.ts +25 -0
- package/lib/rsi-source-maintenance.d.ts.map +1 -0
- package/lib/rsi-source-maintenance.js +348 -0
- package/lib/rsi-source-maintenance.js.map +1 -0
- package/lib/rsi-source-update.d.ts +26 -0
- package/lib/rsi-source-update.d.ts.map +1 -0
- package/lib/rsi-source-update.js +276 -0
- package/lib/rsi-source-update.js.map +1 -0
- package/lib/rsi-source.d.ts +34 -0
- package/lib/rsi-source.d.ts.map +1 -0
- package/lib/rsi-source.js +375 -0
- package/lib/rsi-source.js.map +1 -0
- package/lib/rsi-systemd-bootstrap.d.ts +46 -0
- package/lib/rsi-systemd-bootstrap.d.ts.map +1 -0
- package/lib/rsi-systemd-bootstrap.js +271 -0
- package/lib/rsi-systemd-bootstrap.js.map +1 -0
- package/lib/sdk.d.ts.map +1 -1
- package/lib/sdk.js +26 -1
- package/lib/sdk.js.map +1 -1
- package/lib/setup-business.d.ts +49 -0
- package/lib/setup-business.d.ts.map +1 -0
- package/lib/setup-business.js +335 -0
- package/lib/setup-business.js.map +1 -0
- package/lib/setup-profile.d.ts +1 -1
- package/lib/setup-profile.d.ts.map +1 -1
- package/lib/setup-profile.js +25 -2
- package/lib/setup-profile.js.map +1 -1
- package/lib/setup.d.ts +12 -1
- package/lib/setup.d.ts.map +1 -1
- package/lib/setup.js +138 -34
- package/lib/setup.js.map +1 -1
- package/lib/systemd.d.ts +10 -0
- package/lib/systemd.d.ts.map +1 -1
- package/lib/systemd.js +23 -6
- package/lib/systemd.js.map +1 -1
- package/lib/types.d.ts +7 -0
- package/lib/types.d.ts.map +1 -1
- package/lib/types.js.map +1 -1
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/package.json +32 -20
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
3
|
+
import { chmod, lstat, mkdir, readFile, rename, unlink, writeFile } from 'node:fs/promises';
|
|
4
|
+
import { isAbsolute, join } from 'node:path';
|
|
5
|
+
import { installLarkBusinessSkill, reconcileLarkBusinessSkill } from './business-skill.js';
|
|
6
|
+
import { LARK_BUSINESS_CLEARED_ENV } from './business-environment.js';
|
|
7
|
+
const keyPattern = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/u;
|
|
8
|
+
const revisionPattern = /^[a-f0-9-]{36}$/u;
|
|
9
|
+
const cliProfile = 'dsh-owner';
|
|
10
|
+
const bindingSizeLimit = 256 * 1024;
|
|
11
|
+
/** Each process uses the same private config and Linux credential directories. */
|
|
12
|
+
export function larkBusinessEnvironment(configDir, dataDir) {
|
|
13
|
+
const env = { ...process.env };
|
|
14
|
+
for (const key of LARK_BUSINESS_CLEARED_ENV)
|
|
15
|
+
delete env[key];
|
|
16
|
+
env.LARKSUITE_CLI_CONFIG_DIR = configDir;
|
|
17
|
+
env.LARKSUITE_CLI_DATA_DIR = dataDir;
|
|
18
|
+
env.LARKSUITE_CLI_NO_UPDATE_NOTIFIER = '1';
|
|
19
|
+
env.LARKSUITE_CLI_NO_SKILLS_NOTIFIER = '1';
|
|
20
|
+
return env;
|
|
21
|
+
}
|
|
22
|
+
/** Never echo CLI output from a credential-bearing command into an error. */
|
|
23
|
+
export async function runBusinessCli(request) {
|
|
24
|
+
return new Promise((resolve, reject) => {
|
|
25
|
+
const child = spawn(request.command, request.args, {
|
|
26
|
+
env: request.env, shell: false, stdio: ['pipe', 'pipe', 'pipe'], windowsHide: true,
|
|
27
|
+
});
|
|
28
|
+
const chunks = [];
|
|
29
|
+
const errors = [];
|
|
30
|
+
let bytes = 0;
|
|
31
|
+
let failed = false;
|
|
32
|
+
const stop = () => {
|
|
33
|
+
failed = true;
|
|
34
|
+
child.kill('SIGKILL');
|
|
35
|
+
};
|
|
36
|
+
const timer = setTimeout(stop, request.timeoutMs);
|
|
37
|
+
child.stdout.on('data', (chunk) => {
|
|
38
|
+
bytes += chunk.length;
|
|
39
|
+
if (bytes > 1024 * 1024)
|
|
40
|
+
stop();
|
|
41
|
+
else
|
|
42
|
+
chunks.push(chunk);
|
|
43
|
+
});
|
|
44
|
+
child.stderr.on('data', (chunk) => {
|
|
45
|
+
bytes += chunk.length;
|
|
46
|
+
if (bytes > 1024 * 1024)
|
|
47
|
+
stop();
|
|
48
|
+
else
|
|
49
|
+
errors.push(chunk);
|
|
50
|
+
});
|
|
51
|
+
child.stdin.on('error', () => { });
|
|
52
|
+
child.once('error', () => {
|
|
53
|
+
clearTimeout(timer);
|
|
54
|
+
reject(new Error('lark business setup: CLI could not start'));
|
|
55
|
+
});
|
|
56
|
+
child.once('close', (code, signal) => {
|
|
57
|
+
clearTimeout(timer);
|
|
58
|
+
if (failed || signal !== null)
|
|
59
|
+
reject(new Error('lark business setup: CLI timed out or exceeded its output limit'));
|
|
60
|
+
else
|
|
61
|
+
resolve({ code, stdout: Buffer.concat(chunks).toString('utf8'), stderr: Buffer.concat(errors).toString('utf8') });
|
|
62
|
+
});
|
|
63
|
+
child.stdin.end(request.input);
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
function object(value) {
|
|
67
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
68
|
+
? value : undefined;
|
|
69
|
+
}
|
|
70
|
+
export function isVerifiedLarkBusinessOwner(value, appId, ownerUserId) {
|
|
71
|
+
const status = object(value);
|
|
72
|
+
const user = object(object(status?.identities)?.user);
|
|
73
|
+
return status?.appId === appId && status.identity === 'user' && status.verified === true
|
|
74
|
+
&& user?.openId === ownerUserId && user.available === true && user.verified === true
|
|
75
|
+
&& (user.status === 'ready' || user.status === 'needs_refresh');
|
|
76
|
+
}
|
|
77
|
+
async function privateDirectory(path) {
|
|
78
|
+
await mkdir(path, { recursive: true, mode: 0o700 });
|
|
79
|
+
const info = await lstat(path);
|
|
80
|
+
if (!info.isDirectory() || info.isSymbolicLink())
|
|
81
|
+
throw new Error('lark business setup: managed directory is not a real directory');
|
|
82
|
+
await chmod(path, 0o700);
|
|
83
|
+
}
|
|
84
|
+
function parseJson(text) {
|
|
85
|
+
try {
|
|
86
|
+
return JSON.parse(text);
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
throw new Error('lark business setup: CLI returned invalid JSON');
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function scopeList(value) {
|
|
93
|
+
if (!Array.isArray(value) || value.length > 4096
|
|
94
|
+
|| value.some(scope => typeof scope !== 'string' || !/^[A-Za-z0-9_.:-]{1,256}$/u.test(scope))
|
|
95
|
+
|| new Set(value).size !== value.length)
|
|
96
|
+
return undefined;
|
|
97
|
+
return value;
|
|
98
|
+
}
|
|
99
|
+
function scopeString(value) {
|
|
100
|
+
return typeof value === 'string' ? scopeList(value.trim().split(/\s+/u).filter(Boolean)) : undefined;
|
|
101
|
+
}
|
|
102
|
+
function authorizationEvidence(value) {
|
|
103
|
+
const evidence = object(value);
|
|
104
|
+
const requestedScopes = scopeList(evidence?.requestedScopes);
|
|
105
|
+
const grantedScopes = scopeList(evidence?.grantedScopes);
|
|
106
|
+
const missingScopes = scopeList(evidence?.missingScopes);
|
|
107
|
+
if (!requestedScopes?.length || !grantedScopes || !missingScopes)
|
|
108
|
+
return undefined;
|
|
109
|
+
const granted = new Set(grantedScopes);
|
|
110
|
+
const expectedMissing = requestedScopes.filter(scope => !granted.has(scope));
|
|
111
|
+
if (expectedMissing.length !== missingScopes.length
|
|
112
|
+
|| expectedMissing.some(scope => !missingScopes.includes(scope)))
|
|
113
|
+
return undefined;
|
|
114
|
+
const permissionCompletion = missingScopes.length ? 'partial' : 'complete';
|
|
115
|
+
if (evidence?.permissionCompletion !== permissionCompletion)
|
|
116
|
+
return undefined;
|
|
117
|
+
return { permissionCompletion, requestedScopes, grantedScopes, missingScopes };
|
|
118
|
+
}
|
|
119
|
+
/** v1.0.85's ExitAuth (3) also reports a saved login with missing scopes. */
|
|
120
|
+
function completedAuthorization(result, ownerUserId) {
|
|
121
|
+
const payload = object(parseJson(result.stdout));
|
|
122
|
+
const evidence = authorizationEvidence({ permissionCompletion: Array.isArray(payload?.missing) && payload.missing.length ? 'partial' : 'complete',
|
|
123
|
+
requestedScopes: payload?.requested, grantedScopes: payload?.granted, missingScopes: payload?.missing });
|
|
124
|
+
const warning = object(payload?.warning);
|
|
125
|
+
const newly = scopeList(payload?.newly_granted);
|
|
126
|
+
const already = scopeList(payload?.already_granted);
|
|
127
|
+
const classified = newly && already ? [...newly, ...already] : undefined;
|
|
128
|
+
const requestedGranted = evidence?.requestedScopes.filter(scope => evidence.grantedScopes.includes(scope));
|
|
129
|
+
const scope = scopeString(payload?.scope);
|
|
130
|
+
if (payload?.event !== 'authorization_complete' || payload.user_open_id !== ownerUserId || !evidence
|
|
131
|
+
|| !classified || new Set(classified).size !== classified.length
|
|
132
|
+
|| classified.length !== requestedGranted?.length || classified.some(scope => !requestedGranted.includes(scope))
|
|
133
|
+
|| !scope || scope.length !== evidence.grantedScopes.length || scope.some(item => !evidence.grantedScopes.includes(item))
|
|
134
|
+
|| (evidence.permissionCompletion === 'partial'
|
|
135
|
+
? result.code !== 3 || warning?.type !== 'missing_scope'
|
|
136
|
+
: result.code !== 0 || payload.warning !== undefined)) {
|
|
137
|
+
throw new Error('lark business setup: user authorization is incomplete; business skill was not activated');
|
|
138
|
+
}
|
|
139
|
+
return evidence;
|
|
140
|
+
}
|
|
141
|
+
/** Completes user authorization after channel owner binding; publishes a skill only after readback. */
|
|
142
|
+
export async function setupLarkBusinessTools(input, runtime = {}) {
|
|
143
|
+
if (!isAbsolute(input.dshHome) || !isAbsolute(input.cli.command)
|
|
144
|
+
|| !keyPattern.test(input.profile) || !keyPattern.test(input.account)
|
|
145
|
+
|| !/^cli_[0-9a-f]{16}$/iu.test(input.appId) || !/^ou_[A-Za-z0-9_-]+$/u.test(input.ownerUserId)
|
|
146
|
+
|| !['feishu', 'lark'].includes(input.domain)
|
|
147
|
+
|| !input.appSecret || ['\r', '\n', '\0'].some(character => input.appSecret.includes(character))
|
|
148
|
+
|| !Number.isSafeInteger(input.timeoutMs) || input.timeoutMs < 30_000 || input.timeoutMs > 900_000) {
|
|
149
|
+
throw new Error('lark business setup: invalid binding inputs');
|
|
150
|
+
}
|
|
151
|
+
await reconcileLarkBusinessSkill({ ...input, enabled: true });
|
|
152
|
+
const root = join(input.dshHome, 'lark-business');
|
|
153
|
+
await privateDirectory(root);
|
|
154
|
+
const id = createHash('sha256').update(JSON.stringify([input.profile, input.account])).digest('hex').slice(0, 24);
|
|
155
|
+
const directory = join(root, id);
|
|
156
|
+
await privateDirectory(directory);
|
|
157
|
+
const activePath = join(directory, 'active.json');
|
|
158
|
+
const pendingPath = join(directory, 'pending.json');
|
|
159
|
+
const run = runtime.run ?? runBusinessCli;
|
|
160
|
+
const publishSkill = runtime.installSkill ?? installLarkBusinessSkill;
|
|
161
|
+
const paths = (revision) => ({ configDir: join(directory, revision, 'config'), dataDir: join(directory, revision, 'data') });
|
|
162
|
+
const invoke = async (revision, args, secret, timeoutMs = 30_000) => {
|
|
163
|
+
const { configDir, dataDir } = paths(revision);
|
|
164
|
+
return run({ command: input.cli.command, args: ['--profile', cliProfile, ...args],
|
|
165
|
+
env: larkBusinessEnvironment(configDir, dataDir), timeoutMs,
|
|
166
|
+
...(secret === undefined ? {} : { input: secret }) });
|
|
167
|
+
};
|
|
168
|
+
const verified = async (revision) => {
|
|
169
|
+
const result = await invoke(revision, ['auth', 'status', '--json', '--verify']);
|
|
170
|
+
if (result.code !== 0)
|
|
171
|
+
return false;
|
|
172
|
+
let status = parseJson(result.stdout);
|
|
173
|
+
if (!isVerifiedLarkBusinessOwner(status, input.appId, input.ownerUserId))
|
|
174
|
+
return false;
|
|
175
|
+
// `auth status` labels the user with the local profile openId. Independently
|
|
176
|
+
// compare the server's current user_info response with the paired owner.
|
|
177
|
+
const readback = await invoke(revision, ['api', 'GET', '/open-apis/authen/v1/user_info', '--as', 'user']);
|
|
178
|
+
if (readback.code !== 0)
|
|
179
|
+
return false;
|
|
180
|
+
const identity = object(parseJson(readback.stdout));
|
|
181
|
+
if (identity?.ok !== true || identity.identity !== 'user' || object(identity.data)?.open_id !== input.ownerUserId)
|
|
182
|
+
return false;
|
|
183
|
+
// The first status can report scope fields collected before token refresh.
|
|
184
|
+
// Read the current token scope list after verified user_info has used it.
|
|
185
|
+
const refreshed = await invoke(revision, ['auth', 'status', '--json', '--verify']);
|
|
186
|
+
if (refreshed.code !== 0)
|
|
187
|
+
return false;
|
|
188
|
+
status = parseJson(refreshed.stdout);
|
|
189
|
+
if (!isVerifiedLarkBusinessOwner(status, input.appId, input.ownerUserId))
|
|
190
|
+
return false;
|
|
191
|
+
return { scopes: scopeString(object(object(object(status)?.identities)?.user)?.scope) };
|
|
192
|
+
};
|
|
193
|
+
const configure = async (revision) => {
|
|
194
|
+
const result = await invoke(revision, ['config', 'init', '--name', cliProfile, '--app-id', input.appId,
|
|
195
|
+
'--app-secret-stdin', '--brand', input.domain], `${input.appSecret}\n`);
|
|
196
|
+
if (result.code !== 0)
|
|
197
|
+
throw new Error('lark business setup: CLI app configuration failed; channel binding is retained');
|
|
198
|
+
};
|
|
199
|
+
const skill = async (revision) => {
|
|
200
|
+
const { configDir, dataDir } = paths(revision);
|
|
201
|
+
return (await publishSkill({ dshHome: input.dshHome, profile: input.profile, account: input.account,
|
|
202
|
+
appId: input.appId, ownerUserId: input.ownerUserId, cliCommand: input.cli.command,
|
|
203
|
+
cliConfigDir: configDir, cliDataDir: dataDir, cliProfile })).path;
|
|
204
|
+
};
|
|
205
|
+
const readBinding = async (path) => {
|
|
206
|
+
try {
|
|
207
|
+
const info = await lstat(path);
|
|
208
|
+
if (!info.isFile() || info.isSymbolicLink() || info.size > bindingSizeLimit)
|
|
209
|
+
throw new Error('lark business setup: invalid binding file');
|
|
210
|
+
return object(parseJson(await readFile(path, 'utf8')));
|
|
211
|
+
}
|
|
212
|
+
catch (error) {
|
|
213
|
+
if (error.code !== 'ENOENT')
|
|
214
|
+
throw error;
|
|
215
|
+
return undefined;
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
const matches = (binding) => binding?.schema === 1 && typeof binding.revision === 'string' && revisionPattern.test(binding.revision)
|
|
219
|
+
&& binding.appId === input.appId && binding.ownerUserId === input.ownerUserId
|
|
220
|
+
&& binding.domain === input.domain && binding.cliVersion === input.cli.version && binding.requestedDomains === 'all';
|
|
221
|
+
const validatePaths = async (revision) => {
|
|
222
|
+
const current = paths(revision);
|
|
223
|
+
for (const path of [join(directory, revision), current.configDir, current.dataDir]) {
|
|
224
|
+
const info = await lstat(path);
|
|
225
|
+
if (!info.isDirectory() || info.isSymbolicLink())
|
|
226
|
+
throw new Error('lark business setup: active CLI directory changed');
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
const writeBinding = async (path, binding) => {
|
|
230
|
+
const temporary = join(directory, `binding.${randomUUID()}.tmp`);
|
|
231
|
+
const content = `${JSON.stringify(binding)}\n`;
|
|
232
|
+
if (Buffer.byteLength(content) > bindingSizeLimit)
|
|
233
|
+
throw new Error('lark business setup: authorization evidence exceeded its limit');
|
|
234
|
+
await writeFile(temporary, content, { mode: 0o600, flag: 'wx' });
|
|
235
|
+
await rename(temporary, path);
|
|
236
|
+
};
|
|
237
|
+
const result = (skillPath, reusedAuthorization, evidence) => ({
|
|
238
|
+
skillPath, reusedAuthorization, permissionCompletion: evidence?.permissionCompletion ?? 'unknown',
|
|
239
|
+
requestedScopes: evidence?.requestedScopes ?? [], grantedScopes: evidence?.grantedScopes ?? [], missingScopes: evidence?.missingScopes ?? [],
|
|
240
|
+
});
|
|
241
|
+
const currentEvidence = (evidence, scopes) => {
|
|
242
|
+
// The receipt records a login snapshot. Subsequent tokens can lose scopes;
|
|
243
|
+
// current result claims use the verified CLI identity's token scope list.
|
|
244
|
+
if (!evidence || !scopes)
|
|
245
|
+
return undefined;
|
|
246
|
+
const missingScopes = evidence.requestedScopes.filter(scope => !scopes.includes(scope));
|
|
247
|
+
return { permissionCompletion: missingScopes.length ? 'partial' : 'complete', requestedScopes: evidence.requestedScopes,
|
|
248
|
+
grantedScopes: scopes, missingScopes };
|
|
249
|
+
};
|
|
250
|
+
const existing = await readBinding(activePath);
|
|
251
|
+
if (matches(existing)) {
|
|
252
|
+
await validatePaths(existing.revision);
|
|
253
|
+
const evidence = authorizationEvidence(existing.authorization);
|
|
254
|
+
if (existing.authorization !== undefined && !evidence)
|
|
255
|
+
throw new Error('lark business setup: invalid authorization evidence');
|
|
256
|
+
// Application secrets may have rotated since the previous setup. Updating
|
|
257
|
+
// this same named profile retains its user session without another login.
|
|
258
|
+
await configure(existing.revision);
|
|
259
|
+
const identity = await verified(existing.revision);
|
|
260
|
+
if (identity) {
|
|
261
|
+
return result(await skill(existing.revision), true, currentEvidence(evidence, identity.scopes));
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
// Only a captured completion can recover publication after interrupted owner
|
|
265
|
+
// readback/skill installation. Tokens or an all-domain request alone do not
|
|
266
|
+
// prove which scopes were granted, including for older orphan revisions.
|
|
267
|
+
const pending = await readBinding(pendingPath);
|
|
268
|
+
if (matches(pending)) {
|
|
269
|
+
const evidence = authorizationEvidence(pending.authorization);
|
|
270
|
+
if (pending.authorization !== undefined && !evidence)
|
|
271
|
+
throw new Error('lark business setup: invalid pending authorization evidence');
|
|
272
|
+
if (evidence) {
|
|
273
|
+
await validatePaths(pending.revision);
|
|
274
|
+
await configure(pending.revision);
|
|
275
|
+
const identity = await verified(pending.revision);
|
|
276
|
+
if (!identity)
|
|
277
|
+
throw new Error('lark business setup: authorized user does not match the bound owner; business skill was not activated');
|
|
278
|
+
const skillPath = await skill(pending.revision);
|
|
279
|
+
await writeBinding(activePath, { schema: 1, revision: pending.revision, appId: input.appId, ownerUserId: input.ownerUserId,
|
|
280
|
+
domain: input.domain, cliVersion: input.cli.version, requestedDomains: 'all', authorization: evidence });
|
|
281
|
+
await unlink(pendingPath);
|
|
282
|
+
return result(skillPath, true, currentEvidence(evidence, identity.scopes));
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
const revision = randomUUID();
|
|
286
|
+
const { configDir, dataDir } = paths(revision);
|
|
287
|
+
await privateDirectory(join(directory, revision));
|
|
288
|
+
await privateDirectory(configDir);
|
|
289
|
+
await privateDirectory(dataDir);
|
|
290
|
+
await configure(revision);
|
|
291
|
+
const binding = { schema: 1, revision, appId: input.appId, ownerUserId: input.ownerUserId,
|
|
292
|
+
domain: input.domain, cliVersion: input.cli.version, requestedDomains: 'all' };
|
|
293
|
+
await writeBinding(pendingPath, binding);
|
|
294
|
+
const started = await invoke(revision, ['auth', 'login', '--domain', 'all', '--no-wait', '--json']);
|
|
295
|
+
if (started.code !== 0)
|
|
296
|
+
throw new Error('lark business setup: user authorization could not start; check application permissions');
|
|
297
|
+
if (/failed to (?:cache requested|load cached requested) scopes/iu.test(started.stderr ?? '')) {
|
|
298
|
+
throw new Error('lark business setup: requested scope evidence could not be saved');
|
|
299
|
+
}
|
|
300
|
+
const authorization = object(parseJson(started.stdout));
|
|
301
|
+
if (typeof authorization?.verification_url !== 'string' || typeof authorization.device_code !== 'string'
|
|
302
|
+
|| !authorization.device_code || authorization.device_code.length > 4096) {
|
|
303
|
+
throw new Error('lark business setup: invalid device authorization response');
|
|
304
|
+
}
|
|
305
|
+
let url;
|
|
306
|
+
try {
|
|
307
|
+
url = new URL(authorization.verification_url);
|
|
308
|
+
}
|
|
309
|
+
catch {
|
|
310
|
+
throw new Error('lark business setup: invalid authorization URL');
|
|
311
|
+
}
|
|
312
|
+
const verificationUrl = authorization.verification_url;
|
|
313
|
+
if (url.protocol !== 'https:' || url.username || url.password || ['\r', '\n', '\0'].some(character => verificationUrl.includes(character))) {
|
|
314
|
+
throw new Error('lark business setup: invalid authorization URL');
|
|
315
|
+
}
|
|
316
|
+
await input.onAuthorization(authorization.verification_url);
|
|
317
|
+
const authorized = await invoke(revision, ['auth', 'login', '--device-code', authorization.device_code, '--json'], undefined, input.timeoutMs);
|
|
318
|
+
if (/failed to (?:cache requested|load cached requested) scopes/iu.test(authorized.stderr ?? '')) {
|
|
319
|
+
throw new Error('lark business setup: requested scope evidence could not be read; business skill was not activated');
|
|
320
|
+
}
|
|
321
|
+
const evidence = completedAuthorization(authorized, input.ownerUserId);
|
|
322
|
+
binding.authorization = evidence;
|
|
323
|
+
await writeBinding(pendingPath, binding);
|
|
324
|
+
const identity = await verified(revision);
|
|
325
|
+
if (!identity)
|
|
326
|
+
throw new Error('lark business setup: authorized user does not match the bound owner; business skill was not activated');
|
|
327
|
+
// Retain old configuration files while publishing. macOS/Windows native
|
|
328
|
+
// keychains can share app/user entries; only Linux data paths are isolated.
|
|
329
|
+
// Setup sends no business writes, only authentication and identity readback.
|
|
330
|
+
const skillPath = await skill(revision);
|
|
331
|
+
await writeBinding(activePath, binding);
|
|
332
|
+
await unlink(pendingPath);
|
|
333
|
+
return result(skillPath, false, currentEvidence(evidence, identity.scopes));
|
|
334
|
+
}
|
|
335
|
+
//# sourceMappingURL=setup-business.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup-business.js","sourceRoot":"","sources":["../src/setup-business.ts"],"names":[],"mappings":"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"}
|
package/lib/setup-profile.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ export interface LarkProfileSetupInput {
|
|
|
10
10
|
keychainAccount: string;
|
|
11
11
|
credentialProvider?: 'linux-protected-file' | 'linux-secret-service' | 'macos-keychain' | 'windows-dpapi';
|
|
12
12
|
credentialPath?: string;
|
|
13
|
-
agentTools?: 'disable' | 'enable' | 'preserve';
|
|
13
|
+
agentTools?: 'disable' | 'enable' | 'preserve' | 'auto';
|
|
14
14
|
}
|
|
15
15
|
export interface LarkAgentPolicyRefreshInput {
|
|
16
16
|
profilePatch: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup-profile.d.ts","sourceRoot":"","sources":["../src/setup-profile.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,qBAAqB;IACpC,YAAY,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,QAAQ,GAAG,MAAM,CAAA;IACzB,WAAW,EAAE,MAAM,CAAA;IACnB,eAAe,EAAE,MAAM,CAAA;IACvB,eAAe,EAAE,MAAM,CAAA;IACvB,kBAAkB,CAAC,EAAE,sBAAsB,GAAG,sBAAsB,GAAG,gBAAgB,GAAG,eAAe,CAAA;IACzG,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,UAAU,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"setup-profile.d.ts","sourceRoot":"","sources":["../src/setup-profile.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,qBAAqB;IACpC,YAAY,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,QAAQ,GAAG,MAAM,CAAA;IACzB,WAAW,EAAE,MAAM,CAAA;IACnB,eAAe,EAAE,MAAM,CAAA;IACvB,eAAe,EAAE,MAAM,CAAA;IACvB,kBAAkB,CAAC,EAAE,sBAAsB,GAAG,sBAAsB,GAAG,gBAAgB,GAAG,eAAe,CAAA;IACzG,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,UAAU,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,UAAU,GAAG,MAAM,CAAA;CACxD;AAED,MAAM,WAAW,2BAA2B;IAC1C,YAAY,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,SAAS,GAAG,QAAQ,CAAA;CACjC;AAi9BD,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,2BAA2B,GAAG,MAAM,CA+GtF;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,qBAAqB,GAAG,MAAM,CAoP9E"}
|
package/lib/setup-profile.js
CHANGED
|
@@ -1017,8 +1017,8 @@ export function configureLarkProfilePatch(input) {
|
|
|
1017
1017
|
.includes(credentialProvider)) {
|
|
1018
1018
|
throw new Error('lark-channel setup: invalid credentialProvider');
|
|
1019
1019
|
}
|
|
1020
|
-
|
|
1021
|
-
if (!['disable', 'enable', 'preserve'].includes(agentToolsMode)) {
|
|
1020
|
+
let agentToolsMode = input.agentTools ?? 'auto';
|
|
1021
|
+
if (!['disable', 'enable', 'preserve', 'auto'].includes(agentToolsMode)) {
|
|
1022
1022
|
throw new Error('lark-channel setup: invalid agentTools mode');
|
|
1023
1023
|
}
|
|
1024
1024
|
const credentialHandle = `lark-app-secret-${account}`;
|
|
@@ -1030,8 +1030,11 @@ export function configureLarkProfilePatch(input) {
|
|
|
1030
1030
|
assertManagedProfileRowIntegrity(rows);
|
|
1031
1031
|
const existingLarkRow = findRow(rows, 'dsh-enhanced-lark-channel');
|
|
1032
1032
|
let previousAccount;
|
|
1033
|
+
let existingAppConfigured = false;
|
|
1033
1034
|
if (existingLarkRow !== undefined) {
|
|
1034
1035
|
const existingChannel = asMap(existingLarkRow.get('config', true), 'lark-channel config');
|
|
1036
|
+
const existingAppId = existingChannel.get('appId');
|
|
1037
|
+
existingAppConfigured = existingAppId !== undefined && existingAppId !== '';
|
|
1035
1038
|
const existingAccount = existingChannel.get('account');
|
|
1036
1039
|
if (existingAccount !== undefined) {
|
|
1037
1040
|
if (typeof existingAccount !== 'string') {
|
|
@@ -1053,6 +1056,26 @@ export function configureLarkProfilePatch(input) {
|
|
|
1053
1056
|
assertManagedForegroundRuleIntegrity(rules);
|
|
1054
1057
|
assertManagedFixedRuleIntegrity(rules, account);
|
|
1055
1058
|
const sourceOwnerPrincipal = configuredOwnerPrincipal(rules, grantSourceAccount);
|
|
1059
|
+
if (agentToolsMode === 'auto') {
|
|
1060
|
+
// A new owner gets the install-time capability default. Existing bindings,
|
|
1061
|
+
// explicit restrictions and remnants of retired bindings retain the old
|
|
1062
|
+
// preserve path; re-running onboarding must not re-enable revoked tools.
|
|
1063
|
+
const hasOwnerHistory = rules.items.some(item => {
|
|
1064
|
+
if (!isMap(item))
|
|
1065
|
+
return false;
|
|
1066
|
+
const id = item.get('id');
|
|
1067
|
+
return typeof id === 'string' && id.startsWith('lark-owner-');
|
|
1068
|
+
});
|
|
1069
|
+
const hasForegroundRestriction = rules.items.some(item => {
|
|
1070
|
+
if (!isMap(item))
|
|
1071
|
+
return false;
|
|
1072
|
+
const id = item.get('id');
|
|
1073
|
+
return typeof id === 'string' && isManagedForegroundRuleId(id)
|
|
1074
|
+
&& !isUnrestrictedForegroundAllow(item);
|
|
1075
|
+
});
|
|
1076
|
+
agentToolsMode = existingAppConfigured || hasOwnerHistory || hasForegroundRestriction
|
|
1077
|
+
? 'preserve' : 'enable';
|
|
1078
|
+
}
|
|
1056
1079
|
const preserveOwnerPrincipal = sourceOwnerPrincipal
|
|
1057
1080
|
?? (previousAccount === undefined ? principalId : undefined);
|
|
1058
1081
|
if (agentToolsMode === 'preserve'
|