@aalis/plugin-reach 0.0.0-stage → 0.2.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ace Nyan <ace@acenyan.com>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,21 @@
1
- # Temporary Holding Version
1
+ # @aalis/plugin-reach
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ 触及:按一次工具调用签发触及凭据(契约见 `@aalis/api-reach`)。主体取权限服务的 `principalOf`,场所与绑定取会话管理里的记录,档位与越界策略固定,三张受保护清单在激活时按家目录布局与真实路径算好,交给 `resolveReach` 定上限:主体是 owner 的调用有本地效果,不看会话的受众(主体的判法见权限服务的 `principalOf`:续做与子任务的类别随起它的那一轮,参与者按这次调用的)。另管本会话临时区(建、随会话删、定期清扫)与子进程环境(owner 的 login shell 环境,沙箱内同样完整,只去掉本实例的变量与 ssh-agent 的 socket)。
4
+
5
+ ## 角色
6
+
7
+ 运行时插件,提供 `reach` 服务。
8
+
9
+ ## 安装
10
+
11
+ ```bash
12
+ pnpm add @aalis/plugin-reach
13
+ ```
14
+
15
+ ## 使用
16
+
17
+ 参考 [docs/plugins/plugin-reach.md](../../docs/plugins/plugin-reach.md) 与 [docs/api/api-reach.md](../../docs/api/api-reach.md)。
18
+
19
+ ## 许可
20
+
21
+ MIT,见本目录 LICENSE。
@@ -0,0 +1,11 @@
1
+ import { type Reach, type ReachCredential } from '@aalis/api-reach';
2
+ interface CredentialDeps {
3
+ /** 操作系统用户的家目录:沙箱里 npm 的用户配置从这里的 .npmrc 去掉 npm 的认证键 */
4
+ userHome: string;
5
+ /** 在场所的主目录下取的 login shell 环境 */
6
+ loginEnv(home: string): Promise<Record<string, string>>;
7
+ }
8
+ /** current 每次调用都算出这次调用当时的触及 */
9
+ export declare function issueCredential(current: () => Reach, deps: CredentialDeps): ReachCredential;
10
+ export {};
11
+ //# sourceMappingURL=credential.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credential.d.ts","sourceRoot":"","sources":["../src/credential.ts"],"names":[],"mappings":"AAMA,OAAO,EAGL,KAAK,KAAK,EAEV,KAAK,eAAe,EAIrB,MAAM,kBAAkB,CAAC;AAG1B,UAAU,cAAc;IACtB,sDAAsD;IACtD,QAAQ,EAAE,MAAM,CAAC;IACjB,gCAAgC;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACzD;AAED,+BAA+B;AAC/B,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,KAAK,EAAE,IAAI,EAAE,cAAc,GAAG,eAAe,CAoB3F"}
@@ -0,0 +1,69 @@
1
+ // ============================================================
2
+ // 触及凭据:按一次工具调用签发,带品牌符号,冻结
3
+ //
4
+ // 签发时的触及定下命令在哪执行、场所的主目录与白纸、子进程环境;判定、存储兜底与沙箱策略每次按当时的触及。
5
+ // ============================================================
6
+ import { judgeReach, REACH_CREDENTIAL, sandboxPolicyOf, } from '@aalis/api-reach';
7
+ import { sandboxEnv } from './process-env.js';
8
+ /** current 每次调用都算出这次调用当时的触及 */
9
+ export function issueCredential(current, deps) {
10
+ const issued = current();
11
+ const local = issued.exec === 'none' ? undefined : issued;
12
+ const credential = {
13
+ exec: issued.exec,
14
+ ...(local && { home: local.home, paper: local.paper }),
15
+ async require(request) {
16
+ const decision = judgeReach(current(), request);
17
+ return decision.verdict === 'allow' ? { allowed: true } : { allowed: false, message: explain(decision, request) };
18
+ },
19
+ allows: (effect, realPath) => judgeReach(current(), { effect, path: realPath }).verdict === 'allow',
20
+ sandboxPolicy: () => sandboxPolicyOf(current()),
21
+ async processEnv(mode) {
22
+ if (!local)
23
+ throw new Error('这次调用没有本地效果,没有子进程环境');
24
+ const env = await deps.loginEnv(local.home);
25
+ return mode === 'host' ? { ...env } : sandboxEnv(env, local.sessionTmp, deps.userHome);
26
+ },
27
+ };
28
+ // 品牌不可枚举:展开或 Object.assign 复制出来、改了方法再转交的对象不带它
29
+ return Object.freeze(Object.defineProperty(credential, REACH_CREDENTIAL, { value: true }));
30
+ }
31
+ /** 回给模型的话:要做什么、为什么不行、能不能申请 */
32
+ function explain(decision, request) {
33
+ const subject = subjectOf(request);
34
+ if (decision.verdict === 'ask')
35
+ return `${subject}:${why(decision.reason)},要 owner 批准,这里没有可用的审批`;
36
+ switch (decision.rule) {
37
+ case 'no-local-effect':
38
+ return `${subject}:这一轮不只有 owner 的话,没有本地效果`;
39
+ case 'control-plane':
40
+ return `${subject}:在宿主控制面里,任何档位都不能写;不可申请,不要尝试绕过`;
41
+ case 'deny-read':
42
+ return `${subject}:在拒读清单里;不可申请,不要尝试绕过`;
43
+ case 'boundary-policy':
44
+ return `${subject}:${why(decision.reason)},越界策略是直接拒绝`;
45
+ }
46
+ }
47
+ function subjectOf(request) {
48
+ switch (request.effect) {
49
+ case 'read':
50
+ return `读 ${request.path}`;
51
+ case 'write':
52
+ return 'path' in request ? `写 ${request.path}` : `写编排定义 ${request.workflow}`;
53
+ case 'exec':
54
+ return request.host ? '在沙箱外执行命令' : '执行命令';
55
+ case 'network':
56
+ return { url: '访问模型给的网址', command: '执行要联网的命令', provider: '联网' }[request.via];
57
+ }
58
+ }
59
+ function why(reason) {
60
+ switch (reason.kind) {
61
+ case 'tier':
62
+ return '修改确认档里每一次写与执行都要问';
63
+ case 'boundary':
64
+ return { 'write-path': '超出了可写范围', 'host-exec': '要在沙箱外执行', network: '只读档里联网要问' }[reason.target];
65
+ case 'landing':
66
+ return '这里会被自动执行或用于持久化';
67
+ }
68
+ }
69
+ //# sourceMappingURL=credential.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credential.js","sourceRoot":"","sources":["../src/credential.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import { type ProtectedLists } from '@aalis/api-reach';
2
+ import type { Logger } from '@aalis/core';
3
+ /** 文件或目录不存在 */
4
+ export declare function isMissing(err: unknown): boolean;
5
+ /** 安装集的形态:下有 packages/ 目录的是源码形态,其余是 npm 形态(create-aalis 生成的项目) */
6
+ export declare function formOf(app: string): Promise<'source' | 'npm'>;
7
+ /** 守护进程的入口文件:启动脚本(process.argv[1])的真实路径;没有或取不到时为 undefined */
8
+ export declare function entryOf(): Promise<string | undefined>;
9
+ /**
10
+ * 清单里以具体路径为根的规则,各个根的真实路径(交给 api-reach 的 withRealRoots):不存在的不记;取不了的(没有权限、
11
+ * 链接成环)记 warn,这一条只按写法拦
12
+ */
13
+ export declare function realRootsOf(lists: ProtectedLists, logger: Pick<Logger, 'warn'>): Promise<Map<string, string>>;
14
+ /**
15
+ * 安装集以外、守护进程加载了代码的目录,归宿主控制面(安装集里的已由清单按安装集的目录覆盖):
16
+ * - 安装集 node_modules 顶层(含 `@scope/` 下)解析到安装集以外的包,整个目录;
17
+ * - 源码形态下 packages/ 里链接到安装集以外的包,与安装集里的包一样只算构建产物与依赖。
18
+ * 断掉的链接不是加载了的代码,跳过
19
+ */
20
+ export declare function codeDirsOf(app: string): Promise<string[]>;
21
+ /**
22
+ * 目录所在仓库的 git 目录(common dir,真实路径):从目录往上找 `.git`。文件形式的 `.git`(worktree、子模块)按里面的
23
+ * gitdir 与 commondir 找到共用的那个。找到的不像 git 目录(没有 HEAD 与 objects)的不算,免得一个 `.git` 把任意目录
24
+ * 指成可写。不在仓库里时为 undefined
25
+ */
26
+ export declare function gitDirOf(dir: string): Promise<string | undefined>;
27
+ //# sourceMappingURL=host-dirs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-dirs.d.ts","sourceRoot":"","sources":["../src/host-dirs.ts"],"names":[],"mappings":"AAQA,OAAO,EAAe,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACpE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,eAAe;AACf,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAE/C;AASD,kEAAkE;AAClE,wBAAsB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,KAAK,CAAC,CAMnE;AAED,8DAA8D;AAC9D,wBAAsB,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAG3D;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAAC,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAcnH;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAsB/D;AAED;;;;GAIG;AACH,wBAAsB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAoBvE"}
@@ -0,0 +1,120 @@
1
+ // ============================================================
2
+ // 按磁盘取的几样:安装集的形态与守护进程的入口、安装集以外守护进程加载了代码的目录、清单里各个根的真实路径、
3
+ // 绑定所在仓库的 git 目录
4
+ // ============================================================
5
+ // biome-ignore lint/style/noRestrictedImports: 安装集、入口、链接装进来的包与清单的根取真实路径、从绑定目录往上读 .git,这些路径不在存储根里
6
+ import { lstat, readdir, readFile, realpath, stat } from 'node:fs/promises';
7
+ import { dirname, join, resolve } from 'node:path';
8
+ import { matchesRule } from '@aalis/api-reach';
9
+ /** 文件或目录不存在 */
10
+ export function isMissing(err) {
11
+ return err?.code === 'ENOENT';
12
+ }
13
+ /** 目录里的条目;目录不存在、不是目录(断掉的链接、同名的文件)时为空 */
14
+ const entriesOf = (dir) => readdir(dir).catch(err => {
15
+ if (isMissing(err) || err.code === 'ENOTDIR')
16
+ return [];
17
+ throw err;
18
+ });
19
+ /** 安装集的形态:下有 packages/ 目录的是源码形态,其余是 npm 形态(create-aalis 生成的项目) */
20
+ export async function formOf(app) {
21
+ const packages = await stat(join(app, 'packages')).catch(err => {
22
+ if (isMissing(err))
23
+ return undefined;
24
+ throw err;
25
+ });
26
+ return packages?.isDirectory() ? 'source' : 'npm';
27
+ }
28
+ /** 守护进程的入口文件:启动脚本(process.argv[1])的真实路径;没有或取不到时为 undefined */
29
+ export async function entryOf() {
30
+ const script = process.argv[1];
31
+ return script ? realpath(script).catch(() => undefined) : undefined;
32
+ }
33
+ /**
34
+ * 清单里以具体路径为根的规则,各个根的真实路径(交给 api-reach 的 withRealRoots):不存在的不记;取不了的(没有权限、
35
+ * 链接成环)记 warn,这一条只按写法拦
36
+ */
37
+ export async function realRootsOf(lists, logger) {
38
+ const roots = new Set([...lists.control, ...lists.landing, ...lists.denyRead].flatMap(rule => ('path' in rule ? [rule.path] : [])));
39
+ const real = new Map();
40
+ for (const root of roots) {
41
+ const resolved = await realpath(root).catch(err => {
42
+ if (!isMissing(err) && err.code !== 'ENOTDIR')
43
+ logger.warn(`取不到 ${root} 的真实路径,受保护清单里它只按写法拦:`, err);
44
+ return undefined;
45
+ });
46
+ if (resolved)
47
+ real.set(root, resolved);
48
+ }
49
+ return real;
50
+ }
51
+ /**
52
+ * 安装集以外、守护进程加载了代码的目录,归宿主控制面(安装集里的已由清单按安装集的目录覆盖):
53
+ * - 安装集 node_modules 顶层(含 `@scope/` 下)解析到安装集以外的包,整个目录;
54
+ * - 源码形态下 packages/ 里链接到安装集以外的包,与安装集里的包一样只算构建产物与依赖。
55
+ * 断掉的链接不是加载了的代码,跳过
56
+ */
57
+ export async function codeDirsOf(app) {
58
+ const outsideApp = async (entry) => {
59
+ const real = await realpath(entry).catch(() => undefined);
60
+ return real && !matchesRule({ path: app }, real, process.platform) ? real : undefined;
61
+ };
62
+ const top = join(app, 'node_modules');
63
+ const modules = [];
64
+ for (const name of await entriesOf(top)) {
65
+ if (name.startsWith('.'))
66
+ continue;
67
+ if (name.startsWith('@'))
68
+ modules.push(...(await entriesOf(join(top, name))).map(sub => join(top, name, sub)));
69
+ else
70
+ modules.push(join(top, name));
71
+ }
72
+ const outside = new Set();
73
+ for (const entry of modules) {
74
+ const real = await outsideApp(entry);
75
+ if (real)
76
+ outside.add(real);
77
+ }
78
+ for (const name of await entriesOf(join(app, 'packages'))) {
79
+ const real = await outsideApp(join(app, 'packages', name));
80
+ if (real)
81
+ for (const sub of ['dist', 'node_modules'])
82
+ outside.add(join(real, sub));
83
+ }
84
+ return [...outside];
85
+ }
86
+ /**
87
+ * 目录所在仓库的 git 目录(common dir,真实路径):从目录往上找 `.git`。文件形式的 `.git`(worktree、子模块)按里面的
88
+ * gitdir 与 commondir 找到共用的那个。找到的不像 git 目录(没有 HEAD 与 objects)的不算,免得一个 `.git` 把任意目录
89
+ * 指成可写。不在仓库里时为 undefined
90
+ */
91
+ export async function gitDirOf(dir) {
92
+ for (let at = dir;; at = dirname(at)) {
93
+ const dotGit = join(at, '.git');
94
+ // 读不到(不存在或没有权限)按没有处理:少一个可写目录,不多一个。链接到目录的 .git 按它指向的目录算,不再往上找
95
+ const entry = await lstat(dotGit).catch(() => undefined);
96
+ if (entry?.isDirectory() || entry?.isSymbolicLink())
97
+ return asGitDir(dotGit);
98
+ if (entry?.isFile()) {
99
+ const content = await readFile(dotGit, 'utf8').catch(() => undefined);
100
+ const gitdir = content && /^gitdir:\s*(.+?)\s*$/m.exec(content)?.[1];
101
+ if (!gitdir)
102
+ return undefined;
103
+ const own = resolve(at, gitdir);
104
+ return asGitDir(await readFile(join(own, 'commondir'), 'utf8').then(text => resolve(own, text.trim()), () => own));
105
+ }
106
+ if (dirname(at) === at)
107
+ return undefined;
108
+ }
109
+ }
110
+ async function asGitDir(dir) {
111
+ const real = await realpath(dir).catch(() => undefined);
112
+ if (!real)
113
+ return undefined;
114
+ const [head, objects] = await Promise.all([
115
+ stat(join(real, 'HEAD')).catch(() => undefined),
116
+ stat(join(real, 'objects')).catch(() => undefined),
117
+ ]);
118
+ return head?.isFile() && objects?.isDirectory() ? real : undefined;
119
+ }
120
+ //# sourceMappingURL=host-dirs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-dirs.js","sourceRoot":"","sources":["../src/host-dirs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { type HostPaths } from '@aalis/api-host-paths';
2
+ declare const _default: import("@aalis/core").PluginDefinition<{
3
+ provide: import("@aalis/core").ServiceDescriptor<(identity: symbol) => import("@aalis/core").Provide, import("@aalis/core").Provide>;
4
+ events: import("@aalis/core").ServiceDescriptor<(identity: symbol) => import("@aalis/core").Events, import("@aalis/core").Events>;
5
+ lifecycle: import("@aalis/core").ServiceDescriptor<(identity: symbol) => import("@aalis/core").LifecycleCap, import("@aalis/core").LifecycleCap>;
6
+ logger: import("@aalis/core").ServiceDescriptor<(identity: symbol) => import("@aalis/core").Logger, import("@aalis/core").Logger>;
7
+ /** 家目录布局:三张清单、白纸与本会话临时区都按它 */
8
+ paths: import("@aalis/core").ServiceDescriptor<HostPaths, HostPaths>;
9
+ /** 会话记录与绑定 */
10
+ sessionManager: import("@aalis/core").ServiceDescriptor<import("@aalis/api-session-manager").SessionManagerService, import("@aalis/api-session-manager").SessionManagerService>;
11
+ /** 这一轮的主体;缺席时谁都不是 owner,一律没有本地效果 */
12
+ authority: import("@aalis/core").OptionalUse<import("@aalis/api-authority").AuthorityService, import("@aalis/api-authority").AuthorityService>;
13
+ /** 取 owner 的 login shell 环境;缺席时子进程用守护进程的环境 */
14
+ process: import("@aalis/core").OptionalUse<import("@aalis/api-process").ProcessService, import("@aalis/api-process").ProcessService>;
15
+ }>;
16
+ export default _default;
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,SAAS,EAAa,MAAM,uBAAuB,CAAC;;;;;;IAuChE,8BAA8B;;IAE9B,cAAc;;IAEd,oCAAoC;;IAEpC,8CAA8C;;;AAKhD,wBAOG"}
package/dist/index.js ADDED
@@ -0,0 +1,148 @@
1
+ // biome-ignore lint/style/noRestrictedImports: 安装集与用户家目录取真实路径;本会话临时区按 0700 建、随会话删
2
+ import { mkdir, realpath, rm } from 'node:fs/promises';
3
+ // biome-ignore lint/style/noRestrictedImports: 拒读清单与落点按操作系统用户的家目录生成
4
+ import { homedir } from 'node:os';
5
+ import { join } from 'node:path';
6
+ import { authority } from '@aalis/api-authority';
7
+ import { hostPaths } from '@aalis/api-host-paths';
8
+ import { processService } from '@aalis/api-process';
9
+ import { protectedLists, reach, resolveReach, withRealRoots, } from '@aalis/api-reach';
10
+ import { paperDirName, placePaperId, rootSessionOf, sessionManager } from '@aalis/api-session-manager';
11
+ import { definePlugin, events, lifecycle, logger, optional, provide } from '@aalis/core';
12
+ import { issueCredential } from './credential.js';
13
+ import { codeDirsOf, entryOf, formOf, gitDirOf, realRootsOf } from './host-dirs.js';
14
+ import { loginEnvs } from './process-env.js';
15
+ import { SWEEP_EVERY_MS, sessionTmpOf, sweepSessionTmp } from './session-tmp.js';
16
+ import { t } from './texts.js';
17
+ // ════════════════════════════════════════════════════════════
18
+ // plugin-reach —— 触及服务(契约见 @aalis/api-reach)
19
+ //
20
+ // 按一次工具调用签发凭据:主体取权限服务的 principalOf(类别为人亲手、这次调用的参与者都是 owner 的为 owner;续做与子任务的
21
+ // 类别随起它的那一轮,批过的调用参与者是批的人),不看会话的受众;场所与绑定取会话管理里的记录,档位与越界策略固定(工作区档、
22
+ // 越界要问),仓库的 git 目录按磁盘找,三张清单在激活时按家目录布局与真实路径算好;交给 api-reach 的 resolveReach 定上限。
23
+ // 绑定与 git 目录在签发时取好,场所每次判定时取当时的。另管本会话临时区与子进程环境。
24
+ // ════════════════════════════════════════════════════════════
25
+ /** 档位与越界策略:还不能按会话设,固定为工作区档、越界要问 */
26
+ const DEFAULT_TIER = 'workspace';
27
+ const DEFAULT_BOUNDARY = 'ask';
28
+ const uses = {
29
+ provide,
30
+ events,
31
+ lifecycle,
32
+ logger,
33
+ /** 家目录布局:三张清单、白纸与本会话临时区都按它 */
34
+ paths: hostPaths,
35
+ /** 会话记录与绑定 */
36
+ sessionManager,
37
+ /** 这一轮的主体;缺席时谁都不是 owner,一律没有本地效果 */
38
+ authority: optional(authority),
39
+ /** 取 owner 的 login shell 环境;缺席时子进程用守护进程的环境 */
40
+ process: optional(processService),
41
+ };
42
+ export default definePlugin({
43
+ name: '@aalis/plugin-reach',
44
+ displayName: t('displayName'),
45
+ subsystem: 'authority',
46
+ provides: [reach],
47
+ uses,
48
+ apply: run,
49
+ });
50
+ async function run(caps) {
51
+ const { events, lifecycle, logger } = caps;
52
+ const sm = caps.sessionManager.use;
53
+ const lookup = (id) => sm.getSession(id);
54
+ // 清单与路径比较一律用真实路径:安装集可能经符号链接给出,用户家目录同理;清单里链接出去的根按真实路径补一份
55
+ const given = caps.paths.use;
56
+ const app = await realpath(given.app);
57
+ const userHome = await realpath(homedir());
58
+ // 业务句柄是转发句柄,展开得不到成员:在它之上只换掉 app,其余沿原型链读
59
+ const paths = Object.assign(Object.create(given), { app });
60
+ const declared = protectedLists({
61
+ paths,
62
+ userHome,
63
+ platform: process.platform,
64
+ form: await formOf(app),
65
+ codeDirs: await codeDirsOf(app),
66
+ entry: await entryOf(),
67
+ });
68
+ const realRoots = await realRootsOf(declared, logger.use);
69
+ const lists = withRealRoots(declared, root => realRoots.get(root));
70
+ const loginEnv = loginEnvs({ process: caps.process, userHome, logger: logger.use });
71
+ /**
72
+ * 会话所在场所的白纸目录:白纸 id 由场所键算出,目录名与白纸插件同取 paperDirName。房间写的具名白纸只决定白纸任务用哪一块,
73
+ * 不换这里
74
+ */
75
+ const paperOf = (sessionId) => join(paths.stage.paper, paperDirName(placePaperId(sm.placeOf(sessionId).key)));
76
+ /** 删会话时在后台删着的临时区 */
77
+ const deleting = new Map();
78
+ /**
79
+ * 一个会话的触及,返回每次调用都重算的函数:绑定与仓库的 git 目录(按磁盘找,异步)在这里取好;场所在每次调用时取当时的
80
+ */
81
+ async function reachOf(sessionId, principal) {
82
+ const work = rootSessionOf(sm.getSession(sessionId), lookup)?.work;
83
+ const gitDir = work && (await gitDirOf(work.root));
84
+ return () => {
85
+ const paper = paperOf(sessionId);
86
+ return resolveReach({
87
+ principal,
88
+ tier: DEFAULT_TIER,
89
+ onBoundary: DEFAULT_BOUNDARY,
90
+ // 主目录:项目工作区是绑定目录,其余是场所的白纸
91
+ place: { home: work?.root ?? paper, paper },
92
+ binding: work,
93
+ gitDirs: gitDir ? [gitDir] : [],
94
+ sessionTmp: sessionTmpOf(paths.tmp, sessionId),
95
+ localPorts: [],
96
+ lists,
97
+ paths,
98
+ });
99
+ };
100
+ }
101
+ const service = {
102
+ async forCall(call) {
103
+ // 这一轮的主体:权限服务不在时是 other
104
+ const principal = caps.authority.present ? caps.authority.use.principalOf(call) : 'other';
105
+ const credential = issueCredential(await reachOf(call.sessionId, principal), {
106
+ userHome,
107
+ loginEnv,
108
+ });
109
+ if (credential.exec !== 'none') {
110
+ // 同一个 id 的会话删了又建:前一份还在删,先等它删完,免得删掉新建的
111
+ await deleting.get(call.sessionId);
112
+ await mkdir(sessionTmpOf(paths.tmp, call.sessionId), { recursive: true, mode: 0o700 });
113
+ }
114
+ return credential;
115
+ },
116
+ };
117
+ // 删会话时在后台删它的临时区,不拖住删会话;删不掉记 warn
118
+ events.use.on('session:deleted', sessionId => {
119
+ const dir = sessionTmpOf(paths.tmp, sessionId);
120
+ const done = rm(dir, { recursive: true, force: true })
121
+ .catch(err => logger.use.warn(`删不掉会话 ${sessionId} 的临时区 ${dir}:`, err))
122
+ .finally(() => {
123
+ if (deleting.get(sessionId) === done)
124
+ deleting.delete(sessionId);
125
+ });
126
+ deleting.set(sessionId, done);
127
+ });
128
+ // 清扫在后台排队跑,启动时的那一轮不拖住激活
129
+ let sweeping = Promise.resolve();
130
+ const sweep = () => {
131
+ sweeping = sweeping
132
+ .then(() => sweepSessionTmp(paths.tmp, lookup, Date.now(), logger.use))
133
+ .then(removed => {
134
+ if (removed.length > 0)
135
+ logger.use.debug(`清掉 ${removed.length} 个会话的临时区`);
136
+ })
137
+ .catch(err => logger.use.warn('清扫本会话临时区失败:', err));
138
+ };
139
+ sweep();
140
+ const sweepTimer = setInterval(sweep, SWEEP_EVERY_MS);
141
+ sweepTimer.unref();
142
+ lifecycle.use.onDispose(async () => {
143
+ clearInterval(sweepTimer);
144
+ await Promise.all([sweeping, ...deleting.values()]);
145
+ });
146
+ caps.provide.use(reach, service);
147
+ }
148
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ declare const _default: {
2
+ readonly displayName: "Reach";
3
+ };
4
+ export default _default;
5
+ //# sourceMappingURL=en.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"en.d.ts","sourceRoot":"","sources":["../../src/locales/en.ts"],"names":[],"mappings":";;;AAGA,wBAEG"}
@@ -0,0 +1,5 @@
1
+ import { defineLocale } from '@aalis/schema-i18n';
2
+ export default defineLocale()({
3
+ displayName: 'Reach',
4
+ });
5
+ //# sourceMappingURL=en.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"en.js","sourceRoot":"","sources":["../../src/locales/en.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGlD,eAAe,YAAY,EAAU,CAAC;IACpC,WAAW,EAAE,OAAO;CACrB,CAAC,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { ProcessService } from '@aalis/api-process';
2
+ import type { Logger, ServiceSelection } from '@aalis/core';
3
+ type Env = Record<string, string>;
4
+ /** 按 owner 的 login shell 取环境的入口:同一个主目录取到一次就一直用,同时来的调用共用一次取 */
5
+ export declare function loginEnvs(deps: {
6
+ process: ServiceSelection<ProcessService>;
7
+ userHome: string;
8
+ logger: Logger;
9
+ }): (home: string) => Promise<Env>;
10
+ /**
11
+ * 沙箱里的命令拿到的环境:完整的登录环境去掉本实例的变量与 ssh-agent 的 socket,注入 npm 的用户配置(去掉认证键的副本,写在
12
+ * 本会话临时区)、本机 Node 的头文件、浏览器的缓存目录,关掉 pnpm 的构建产物缓存(沙箱里构建出的产物不能被沙箱外的安装直接
13
+ * 复用),SSH 地址的拉取走 HTTPS
14
+ */
15
+ export declare function sandboxEnv(login: Env, sessionTmp: string, userHome: string): Promise<Env>;
16
+ export {};
17
+ //# sourceMappingURL=process-env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-env.d.ts","sourceRoot":"","sources":["../src/process-env.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAG5D,KAAK,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAmBlC,8DAA8D;AAC9D,wBAAgB,SAAS,CAAC,IAAI,EAAE;IAAE,OAAO,EAAE,gBAAgB,CAAC,cAAc,CAAC,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,IAuCrG,MAAM,MAAM,KAAG,OAAO,CAAC,GAAG,CAAC,CAcpC;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,KAAK,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CA8C/F"}
@@ -0,0 +1,145 @@
1
+ // ============================================================
2
+ // 子进程环境:owner 的 login shell 环境,沙箱内另去掉两样并注入沙箱要的几项
3
+ //
4
+ // 环境在场所的主目录下用 owner 的 login shell 取一次(项目的 .nvmrc、venv 这类按目录选的工具链与 owner 自己的终端一致),
5
+ // 缓存在内存,不落盘;取不到时用守护进程的环境,1 分钟后再取(一次超时不能让这个主目录一直用守护进程的环境)。
6
+ // 宿主执行与沙箱里的命令都拿到完整的登录环境,不按名字或值猜凭据:能进沙箱的只有主体是 owner 的一轮,密钥不靠出口过滤,
7
+ // 靠权限隔离。沙箱里只去掉本实例自己的变量与 ssh-agent 的 socket,git 的命令行配置接上沙箱要的几项,npm 的用户配置换成
8
+ // 去掉认证键的副本。
9
+ // ============================================================
10
+ // biome-ignore lint/style/noRestrictedImports: 读用户家目录的 .npmrc、在本会话临时区写去掉认证键的副本(不跟随链接)、按 PATH 找本机 Node 的头文件,这些路径不在存储根里
11
+ import { access, lstat, readFile, realpath, rename, stat, writeFile } from 'node:fs/promises';
12
+ // biome-ignore lint/style/noRestrictedImports: 没有 SHELL 时取操作系统账户登记的 login shell
13
+ import { userInfo } from 'node:os';
14
+ import { delimiter, dirname, join } from 'node:path';
15
+ import { isMissing } from './host-dirs.js';
16
+ /** 取环境的时限:rc 文件卡住(等输入、连网)时按取不到处理 */
17
+ const CAPTURE_TIMEOUT_MS = 10_000;
18
+ /** 取不到时这么久之后再取 */
19
+ const RETRY_AFTER_MS = 60_000;
20
+ /** AALIS_ 开头的是实例自己的命名空间(家目录这类本实例的配置),不交给沙箱里的命令 */
21
+ const INSTANCE_VARS = /^AALIS_/;
22
+ /** ssh-agent 的 socket:ssh-agent 不对沙箱开放,经 SSH 的推送要宿主执行 */
23
+ const SSH_AGENT_SOCK = 'SSH_AUTH_SOCK';
24
+ /**
25
+ * npm 定义的认证键:令牌、用户名与密码、客户端证书与私钥(文件或内联)。~/.npmrc 在拒读清单里,沙箱里的 npm 读的是去掉这些键
26
+ * 的副本
27
+ */
28
+ const NPMRC_SECRET = /(^|:)(_authToken|_auth|_password|username|password|(cert|key)(file)?)\s*=/i;
29
+ /** SSH 地址的拉取改走 HTTPS(沙箱里没有 SSH 凭据),推送仍是 SSH(沙箱里推不了,要宿主执行) */
30
+ const HTTPS_HOSTS = ['github.com', 'gitlab.com'];
31
+ /** 按 owner 的 login shell 取环境的入口:同一个主目录取到一次就一直用,同时来的调用共用一次取 */
32
+ export function loginEnvs(deps) {
33
+ const cache = new Map();
34
+ /** 取不到时为 undefined */
35
+ async function capture(home) {
36
+ try {
37
+ if (!deps.process.present)
38
+ throw new Error('没有进程服务');
39
+ const proc = deps.process.use;
40
+ const shell = process.env.SHELL || userInfo().shell;
41
+ if (!shell)
42
+ throw new Error('不知道 owner 的 login shell(没有 SHELL,账户也没登记)');
43
+ // 白纸首次写入时才建:主目录还不在时在用户家目录下取,与新开一个终端相同
44
+ const cwd = await stat(home).then(s => (s.isDirectory() ? home : deps.userHome), () => deps.userHome);
45
+ const mark = `__AALIS_ENV_${crypto.randomUUID()}__`;
46
+ const { stdout } = await proc.execFile(shell, ['-i', '-l', '-c', `printf '%s' '${mark}'; /usr/bin/env -0`], {
47
+ cwd,
48
+ timeout: CAPTURE_TIMEOUT_MS,
49
+ input: '',
50
+ });
51
+ const at = stdout.indexOf(mark);
52
+ if (at < 0)
53
+ throw new Error(`${shell} 的输出里没有环境`);
54
+ return Object.fromEntries(stdout
55
+ .slice(at + mark.length)
56
+ .split('\0')
57
+ .filter(line => line.includes('='))
58
+ .map(line => [line.slice(0, line.indexOf('=')), line.slice(line.indexOf('=') + 1)]));
59
+ }
60
+ catch (err) {
61
+ deps.logger.warn(`没取到 owner 的 login shell 环境(主目录 ${home}),子进程用守护进程的环境,1 分钟后再取:`, err);
62
+ return undefined;
63
+ }
64
+ }
65
+ return (home) => {
66
+ const cached = cache.get(home);
67
+ if (cached && Date.now() < cached.retryAt)
68
+ return cached.env;
69
+ const entry = {
70
+ retryAt: Number.POSITIVE_INFINITY,
71
+ env: capture(home).then(env => {
72
+ if (env)
73
+ return env;
74
+ entry.retryAt = Date.now() + RETRY_AFTER_MS;
75
+ return { ...process.env };
76
+ }),
77
+ };
78
+ cache.set(home, entry);
79
+ return entry.env;
80
+ };
81
+ }
82
+ /**
83
+ * 沙箱里的命令拿到的环境:完整的登录环境去掉本实例的变量与 ssh-agent 的 socket,注入 npm 的用户配置(去掉认证键的副本,写在
84
+ * 本会话临时区)、本机 Node 的头文件、浏览器的缓存目录,关掉 pnpm 的构建产物缓存(沙箱里构建出的产物不能被沙箱外的安装直接
85
+ * 复用),SSH 地址的拉取走 HTTPS
86
+ */
87
+ export async function sandboxEnv(login, sessionTmp, userHome) {
88
+ const env = Object.fromEntries(Object.entries(login).filter(([name]) => !INSTANCE_VARS.test(name) && name !== SSH_AGENT_SOCK));
89
+ const npmrc = join(sessionTmp, 'npmrc');
90
+ const owned = await readFile(join(userHome, '.npmrc'), 'utf8').catch(err => {
91
+ if (isMissing(err))
92
+ return '';
93
+ throw err;
94
+ });
95
+ // 临时区在沙箱里可写,沙箱里的命令能把 npmrc、甚至临时区本身换成符号链接,骗守护进程去改写别处:临时区本身要是目录,
96
+ // 副本先以随机名独占创建(不跟随链接),再改名盖过去(换掉的是链接本身)
97
+ if (!(await lstat(sessionTmp)).isDirectory()) {
98
+ throw new Error(`本会话临时区 ${sessionTmp} 不是目录(可能被换成了符号链接),不往里写 npm 的用户配置`);
99
+ }
100
+ const staging = join(sessionTmp, `.npmrc-${crypto.randomUUID()}`);
101
+ const kept = owned.split('\n').filter(line => !NPMRC_SECRET.test(line.trim()));
102
+ await writeFile(staging, kept.join('\n'), { mode: 0o600, flag: 'wx' });
103
+ await rename(staging, npmrc);
104
+ const nodeDir = await nodeDirOf(env.PATH);
105
+ const injected = {
106
+ npm_config_userconfig: npmrc,
107
+ npm_config_side_effects_cache: 'false',
108
+ PUPPETEER_CACHE_DIR: join(sessionTmp, 'puppeteer'),
109
+ ...(nodeDir ? { npm_config_nodedir: nodeDir } : {}),
110
+ };
111
+ // npm 的环境变量不分大小写:同名的旧值去掉,免得两份打架
112
+ for (const name of Object.keys(env)) {
113
+ if (Object.keys(injected).some(key => key.toLowerCase() === name.toLowerCase()))
114
+ delete env[name];
115
+ }
116
+ const git = HTTPS_HOSTS.flatMap((host) => [
117
+ [`url.https://${host}/.insteadOf`, `git@${host}:`],
118
+ [`url.https://${host}/.insteadOf`, `ssh://git@${host}/`],
119
+ [`url.git@${host}:.pushInsteadOf`, `git@${host}:`],
120
+ [`url.ssh://git@${host}/.pushInsteadOf`, `ssh://git@${host}/`],
121
+ ]);
122
+ // git 的命令行配置只有一组连续编号:沙箱要的几项接在登录环境原有的那组后面重新编号,原有的照留(计数不是数字时 git 本就
123
+ // 读不了那组,从 0 编号)
124
+ const base = /^\d+$/.test(env.GIT_CONFIG_COUNT ?? '') ? Number(env.GIT_CONFIG_COUNT) : 0;
125
+ git.forEach(([key, value], i) => {
126
+ env[`GIT_CONFIG_KEY_${base + i}`] = key;
127
+ env[`GIT_CONFIG_VALUE_${base + i}`] = value;
128
+ });
129
+ env.GIT_CONFIG_COUNT = String(base + git.length);
130
+ return { ...env, ...injected };
131
+ }
132
+ /** 这份 PATH 上的 node 所在的安装(带头文件的才算):源码编译原生模块时 node-gyp 用它,不必去下载头文件 */
133
+ async function nodeDirOf(path) {
134
+ for (const dir of (path ?? '').split(delimiter)) {
135
+ if (!dir)
136
+ continue;
137
+ const bin = await realpath(join(dir, 'node')).catch(() => undefined);
138
+ if (!bin)
139
+ continue;
140
+ const prefix = dirname(dirname(bin));
141
+ return access(join(prefix, 'include', 'node', 'node.h')).then(() => prefix, () => undefined);
142
+ }
143
+ return undefined;
144
+ }
145
+ //# sourceMappingURL=process-env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-env.js","sourceRoot":"","sources":["../src/process-env.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { SessionInfo } from '@aalis/api-session-manager';
2
+ import type { Logger } from '@aalis/core';
3
+ export declare const SWEEP_EVERY_MS: number;
4
+ export declare const sessionTmpOf: (tmp: string, sessionId: string) => string;
5
+ /** 清扫一遍,返回删掉的会话 id。逐个临时区处理:一个看不了或删不掉的记 warn(写明目录与原因),不挡别的 */
6
+ export declare function sweepSessionTmp(tmp: string, sessionOf: (sessionId: string) => SessionInfo | undefined, now: number, logger: Pick<Logger, 'warn'>): Promise<string[]>;
7
+ //# sourceMappingURL=session-tmp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-tmp.d.ts","sourceRoot":"","sources":["../src/session-tmp.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAM1C,eAAO,MAAM,cAAc,QAAS,CAAC;AAErC,eAAO,MAAM,YAAY,GAAI,KAAK,MAAM,EAAE,WAAW,MAAM,WACI,CAAC;AAEhE,6DAA6D;AAC7D,wBAAsB,eAAe,CACnC,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,WAAW,GAAG,SAAS,EACzD,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,GAC3B,OAAO,CAAC,MAAM,EAAE,CAAC,CAuBnB"}
@@ -0,0 +1,68 @@
1
+ // ============================================================
2
+ // 本会话临时区:tmp/sessions/<会话 id 的 UTF-8 十六进制>/,0700。十六进制只有小写,大小写不敏感的文件系统上两个会话也不会撞名
3
+ //
4
+ // 有本地效果的调用签发凭据时建好;删会话时删;启动时与每天清扫一次:7 天没有改动、会话也不在运行的删掉。会话表里查不到
5
+ // 的同样按 7 天算,不立即删:会话表读不出(记忆后端暂时连不上)时表是空的,不能当作会话都删了。删除与清扫都在后台跑,
6
+ // 不拖住激活与删会话。
7
+ // 插件自己的临时目录(浏览器截图、代码执行的脚本目录)不在这里,清扫不碰。
8
+ // ============================================================
9
+ // biome-ignore lint/style/noRestrictedImports: 清扫本会话临时区要按 lstat 不跟随链接地看修改时间,存储服务没有这个能力
10
+ import { lstat, readdir, rm } from 'node:fs/promises';
11
+ import { join } from 'node:path';
12
+ import { isMissing } from './host-dirs.js';
13
+ const DAY_MS = 24 * 60 * 60 * 1000;
14
+ /** 这么久没有改动的临时区,会话不在运行时清掉 */
15
+ const STALE_MS = 7 * DAY_MS;
16
+ export const SWEEP_EVERY_MS = DAY_MS;
17
+ export const sessionTmpOf = (tmp, sessionId) => join(tmp, 'sessions', Buffer.from(sessionId).toString('hex'));
18
+ /** 清扫一遍,返回删掉的会话 id。逐个临时区处理:一个看不了或删不掉的记 warn(写明目录与原因),不挡别的 */
19
+ export async function sweepSessionTmp(tmp, sessionOf, now, logger) {
20
+ const root = join(tmp, 'sessions');
21
+ const names = await readdir(root).catch(err => {
22
+ if (isMissing(err))
23
+ return [];
24
+ throw err;
25
+ });
26
+ const removed = [];
27
+ for (const name of names) {
28
+ const sessionId = Buffer.from(name, 'hex').toString();
29
+ // 名字不是某个会话 id 的编码:不是本会话临时区,不动
30
+ if (Buffer.from(sessionId).toString('hex') !== name)
31
+ continue;
32
+ const dir = join(root, name);
33
+ try {
34
+ if (sessionOf(sessionId)?.status === 'active' || (await changedSince(dir, now - STALE_MS)))
35
+ continue;
36
+ // 遍历期间会话可能开了新回合
37
+ if (sessionOf(sessionId)?.status === 'active')
38
+ continue;
39
+ await rm(dir, { recursive: true, force: true });
40
+ removed.push(sessionId);
41
+ }
42
+ catch (err) {
43
+ logger.warn(`清不掉会话 ${sessionId} 的临时区 ${dir}:`, err);
44
+ }
45
+ }
46
+ return removed;
47
+ }
48
+ /** 目录或它下面任何一项在 since 之后改过(不跟随符号链接);遍历中途被删掉的按刚改过算,这一轮不动它 */
49
+ async function changedSince(path, since) {
50
+ try {
51
+ const entry = await lstat(path);
52
+ if (entry.mtimeMs > since)
53
+ return true;
54
+ if (!entry.isDirectory())
55
+ return false;
56
+ for (const name of await readdir(path)) {
57
+ if (await changedSince(join(path, name), since))
58
+ return true;
59
+ }
60
+ return false;
61
+ }
62
+ catch (err) {
63
+ if (isMissing(err))
64
+ return true;
65
+ throw err;
66
+ }
67
+ }
68
+ //# sourceMappingURL=session-tmp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-tmp.js","sourceRoot":"","sources":["../src/session-tmp.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ declare const SOURCE: {
2
+ readonly displayName: "触及";
3
+ };
4
+ export type Source = typeof SOURCE;
5
+ export declare const t: import("@aalis/schema-i18n").TextFactory<{
6
+ readonly displayName: "触及";
7
+ }>;
8
+ export {};
9
+ //# sourceMappingURL=texts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"texts.d.ts","sourceRoot":"","sources":["../src/texts.ts"],"names":[],"mappings":"AAIA,QAAA,MAAM,MAAM;;CAEF,CAAC;AACX,MAAM,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC;AAEnC,eAAO,MAAM,CAAC;;EAAiG,CAAC"}
package/dist/texts.js ADDED
@@ -0,0 +1,8 @@
1
+ // 本插件自己的原文字典:显示名
2
+ import { defineTexts } from '@aalis/schema-i18n';
3
+ import en from './locales/en.js';
4
+ const SOURCE = {
5
+ displayName: '触及',
6
+ };
7
+ export const t = defineTexts({ ns: '@aalis/plugin-reach', language: 'zh-CN', source: SOURCE, locales: { en } });
8
+ //# sourceMappingURL=texts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"texts.js","sourceRoot":"","sources":["../src/texts.ts"],"names":[],"mappings":"AAAA,iBAAiB;AACjB,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAEjC,MAAM,MAAM,GAAG;IACb,WAAW,EAAE,IAAI;CACT,CAAC;AAGX,MAAM,CAAC,MAAM,CAAC,GAAG,WAAW,CAAC,EAAE,EAAE,EAAE,qBAAqB,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,65 @@
1
1
  {
2
2
  "name": "@aalis/plugin-reach",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.2.0",
4
+ "license": "MIT",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/AalisLabs/Aalis.git",
8
+ "directory": "packages/plugin-reach"
9
+ },
10
+ "author": "Ace Nyan <ace@acenyan.com>",
11
+ "bugs": {
12
+ "url": "https://github.com/AalisLabs/Aalis/issues"
13
+ },
14
+ "homepage": "https://github.com/AalisLabs/Aalis#readme",
15
+ "description": "触及:按一次工具调用签发触及凭据(这一轮的主体、档位与场所定下本机能读写执行什么),管本会话临时区与子进程环境",
16
+ "type": "module",
17
+ "keywords": [
18
+ "aalis",
19
+ "aalis-plugin"
20
+ ],
21
+ "main": "dist/index.js",
22
+ "types": "dist/index.d.ts",
23
+ "files": [
24
+ "dist"
25
+ ],
26
+ "dependencies": {
27
+ "@aalis/api-authority": ">=0.12.0 <1.0.0",
28
+ "@aalis/api-host-paths": ">=0.1.0 <1.0.0",
29
+ "@aalis/api-process": ">=0.10.0 <1.0.0",
30
+ "@aalis/api-reach": ">=0.2.0 <1.0.0",
31
+ "@aalis/api-session-manager": ">=0.12.0 <1.0.0",
32
+ "@aalis/schema-i18n": ">=0.1.0 <1.0.0"
33
+ },
34
+ "devDependencies": {
35
+ "@types/node": "^22.0.0",
36
+ "typescript": "^5.7.0",
37
+ "@aalis/core": "0.21.0"
38
+ },
39
+ "peerDependencies": {
40
+ "@aalis/core": ">=0.21.0 <1.0.0"
41
+ },
42
+ "aalis": {
43
+ "service": {
44
+ "optional": [
45
+ "authority",
46
+ "process"
47
+ ],
48
+ "provides": [
49
+ "reach"
50
+ ],
51
+ "required": [
52
+ "events",
53
+ "host-paths",
54
+ "lifecycle",
55
+ "logger",
56
+ "provide",
57
+ "session-manager"
58
+ ]
59
+ }
60
+ },
61
+ "scripts": {
62
+ "build": "tsc",
63
+ "dev": "tsc --watch"
64
+ }
6
65
  }