@encorearia/install 1.1.1 → 1.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/bin/install.mjs CHANGED
@@ -6,9 +6,11 @@ import { atomicInstall } from '../lib/atomic-install.mjs';
6
6
  import { loadCredentials } from '../lib/credentials.mjs';
7
7
  import { detectTargets, targetRoot } from '../lib/targets.mjs';
8
8
  import { loadTrustedKeys, verifyPackage } from '../lib/verify.mjs';
9
+ import { bindApiOrigin } from '../lib/credentials.mjs';
9
10
 
10
11
  const args = process.argv.slice(2);
11
12
  const baseURL = String(valueAfter('--api') || process.env.ENCOREARIA_API_BASE || 'https://encorearia.com').replace(/\/$/, '');
13
+ bindApiOrigin(baseURL);
12
14
  const targetArg = valueAfter('--target');
13
15
  const installerVersion = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version;
14
16
 
@@ -2,10 +2,30 @@ import fs from 'node:fs/promises';
2
2
  import os from 'node:os';
3
3
  import path from 'node:path';
4
4
 
5
+ import { createHash } from 'node:crypto';
6
+
5
7
  const service = 'encorearia-agent';
6
- const account = 'default';
8
+ export const OFFICIAL_API = 'https://encorearia.com';
9
+ let originSuffix = '';
10
+
11
+ // 凭据按 API 来源隔离:官方地址用默认文件;其它地址仅限本机调试或显式允许,
12
+ // 且各用独立文件——防止 `--api` 指向任意第三方后把官方登录凭据发过去(钓鱼偷 token)。
13
+ export function bindApiOrigin(baseURL) {
14
+ let canonical;
15
+ try { canonical = new URL(String(baseURL || '')).origin; } catch { canonical = String(baseURL || '').replace(/\/+$/, ''); }
16
+ if (canonical === OFFICIAL_API) { originSuffix = ''; return; }
17
+ let host = '';
18
+ try { host = new URL(canonical).hostname; } catch { host = ''; }
19
+ const loopback = host === 'localhost' || host === '127.0.0.1' || host === '::1' || host === '[::1]';
20
+ if (!loopback && process.env.ENCOREARIA_ALLOW_CUSTOM_API !== '1') {
21
+ throw new Error('--api 只允许官方地址或本机调试地址;如确需自定义请设 ENCOREARIA_ALLOW_CUSTOM_API=1(凭据将与官方隔离)');
22
+ }
23
+ originSuffix = '-' + createHash('sha256').update(canonical).digest('hex').slice(0, 12);
24
+ }
25
+
26
+ const account = () => 'default' + originSuffix;
7
27
  export const credentialsDirectory = () => process.env.ENCOREARIA_CONFIG_DIR || path.join(os.homedir(), '.encorearia');
8
- const file = () => path.join(credentialsDirectory(), 'credentials.json');
28
+ const file = () => path.join(credentialsDirectory(), 'credentials' + originSuffix + '.json');
9
29
 
10
30
  async function keytar() {
11
31
  try { return (await import('keytar')).default; } catch { return null; }
@@ -14,7 +34,7 @@ async function keytar() {
14
34
  export async function loadCredentials() {
15
35
  const keychain = await keytar();
16
36
  if (keychain) {
17
- const raw = await keychain.getPassword(service, account);
37
+ const raw = await keychain.getPassword(service, account());
18
38
  if (raw) return JSON.parse(raw);
19
39
  }
20
40
  try { return JSON.parse(await fs.readFile(file(), 'utf8')); } catch { return null; }
@@ -23,7 +43,7 @@ export async function loadCredentials() {
23
43
  export async function saveCredentials(value) {
24
44
  const keychain = await keytar();
25
45
  if (keychain) {
26
- await keychain.setPassword(service, account, JSON.stringify(value));
46
+ await keychain.setPassword(service, account(), JSON.stringify(value));
27
47
  return;
28
48
  }
29
49
  const dir = path.dirname(file());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@encorearia/install",
3
- "version": "1.1.1",
3
+ "version": "1.2.0",
4
4
  "description": "Verify and install signed Encore Aria call-shell skills for Codex and Claude Code.",
5
5
  "type": "module",
6
6
  "bin": {