@testany/hephos 0.3.17 → 0.4.0-dev.3
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 +29 -0
- package/out/auth/AuthConfig.d.ts +54 -0
- package/out/auth/AuthConfig.d.ts.map +1 -0
- package/out/auth/AuthConfig.js +70 -0
- package/out/auth/AuthConfig.js.map +1 -0
- package/out/auth/AuthService.d.ts +74 -0
- package/out/auth/AuthService.d.ts.map +1 -0
- package/out/auth/AuthService.js +275 -0
- package/out/auth/AuthService.js.map +1 -0
- package/out/auth/CallbackServer.d.ts +15 -0
- package/out/auth/CallbackServer.d.ts.map +1 -0
- package/out/auth/CallbackServer.js +277 -0
- package/out/auth/CallbackServer.js.map +1 -0
- package/out/auth/TokenCache.d.ts +81 -0
- package/out/auth/TokenCache.d.ts.map +1 -0
- package/out/auth/TokenCache.js +191 -0
- package/out/auth/TokenCache.js.map +1 -0
- package/out/auth/index.d.ts +11 -0
- package/out/auth/index.d.ts.map +1 -0
- package/out/auth/index.js +13 -0
- package/out/auth/index.js.map +1 -0
- package/out/auth/types.d.ts +75 -0
- package/out/auth/types.d.ts.map +1 -0
- package/out/auth/types.js +15 -0
- package/out/auth/types.js.map +1 -0
- package/out/cli.d.ts.map +1 -1
- package/out/cli.js +223 -33
- package/out/cli.js.map +1 -1
- package/out/repl/ReplModeInk.d.ts +1 -0
- package/out/repl/ReplModeInk.d.ts.map +1 -1
- package/out/repl/ReplModeInk.js +124 -5
- package/out/repl/ReplModeInk.js.map +1 -1
- package/out/secure-config/BaseDirResolver.d.ts +5 -0
- package/out/secure-config/BaseDirResolver.d.ts.map +1 -0
- package/out/secure-config/BaseDirResolver.js +20 -0
- package/out/secure-config/BaseDirResolver.js.map +1 -0
- package/out/secure-config/DeviceKeyService.d.ts +13 -0
- package/out/secure-config/DeviceKeyService.d.ts.map +1 -0
- package/out/secure-config/DeviceKeyService.js +51 -0
- package/out/secure-config/DeviceKeyService.js.map +1 -0
- package/out/secure-config/DeviceStore.d.ts +13 -0
- package/out/secure-config/DeviceStore.d.ts.map +1 -0
- package/out/secure-config/DeviceStore.js +39 -0
- package/out/secure-config/DeviceStore.js.map +1 -0
- package/out/secure-config/InstructionNormalizer.d.ts +5 -0
- package/out/secure-config/InstructionNormalizer.d.ts.map +1 -0
- package/out/secure-config/InstructionNormalizer.js +20 -0
- package/out/secure-config/InstructionNormalizer.js.map +1 -0
- package/out/secure-config/KeysetService.d.ts +15 -0
- package/out/secure-config/KeysetService.d.ts.map +1 -0
- package/out/secure-config/KeysetService.js +88 -0
- package/out/secure-config/KeysetService.js.map +1 -0
- package/out/secure-config/SCPService.d.ts +14 -0
- package/out/secure-config/SCPService.d.ts.map +1 -0
- package/out/secure-config/SCPService.js +79 -0
- package/out/secure-config/SCPService.js.map +1 -0
- package/out/secure-config/SecureConfigClient.d.ts +30 -0
- package/out/secure-config/SecureConfigClient.d.ts.map +1 -0
- package/out/secure-config/SecureConfigClient.js +81 -0
- package/out/secure-config/SecureConfigClient.js.map +1 -0
- package/out/secure-config/errors.d.ts +8 -0
- package/out/secure-config/errors.d.ts.map +1 -0
- package/out/secure-config/errors.js +20 -0
- package/out/secure-config/errors.js.map +1 -0
- package/out/secure-config/index.d.ts +11 -0
- package/out/secure-config/index.d.ts.map +1 -0
- package/out/secure-config/index.js +11 -0
- package/out/secure-config/index.js.map +1 -0
- package/out/secure-config/rootKey.d.ts +3 -0
- package/out/secure-config/rootKey.d.ts.map +1 -0
- package/out/secure-config/rootKey.js +57 -0
- package/out/secure-config/rootKey.js.map +1 -0
- package/out/secure-config/signatureUtils.d.ts +3 -0
- package/out/secure-config/signatureUtils.d.ts.map +1 -0
- package/out/secure-config/signatureUtils.js +23 -0
- package/out/secure-config/signatureUtils.js.map +1 -0
- package/out/secure-config/types.d.ts +79 -0
- package/out/secure-config/types.d.ts.map +1 -0
- package/out/secure-config/types.js +2 -0
- package/out/secure-config/types.js.map +1 -0
- package/package.json +2 -2
- package/patches/ink-text-input+6.0.0.patch +176 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InstructionNormalizer.d.ts","sourceRoot":"","sources":["../../src/secure-config/InstructionNormalizer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAE7D,qBAAa,qBAAqB;IAChC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS;CAwB/C"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export class InstructionNormalizer {
|
|
2
|
+
static normalize(config) {
|
|
3
|
+
const team = config.team;
|
|
4
|
+
if (!team)
|
|
5
|
+
return config;
|
|
6
|
+
if (team.instructionContent === undefined) {
|
|
7
|
+
team.instructionContent = '';
|
|
8
|
+
}
|
|
9
|
+
if (Array.isArray(team.members)) {
|
|
10
|
+
team.members.forEach((member) => {
|
|
11
|
+
const memberWithInstruction = member;
|
|
12
|
+
if (memberWithInstruction.instructionContent === undefined) {
|
|
13
|
+
memberWithInstruction.instructionContent = '';
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
return config;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=InstructionNormalizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InstructionNormalizer.js","sourceRoot":"","sources":["../../src/secure-config/InstructionNormalizer.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,qBAAqB;IAChC,MAAM,CAAC,SAAS,CAAC,MAAiB;QAChC,MAAM,IAAI,GAAG,MAAM,CAAC,IAON,CAAC;QACf,IAAI,CAAC,IAAI;YAAE,OAAO,MAAM,CAAC;QAEzB,IAAI,IAAI,CAAC,kBAAkB,KAAK,SAAS,EAAE,CAAC;YAC1C,IAAI,CAAC,kBAAkB,GAAG,EAAE,CAAC;QAC/B,CAAC;QACD,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAChC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE;gBAC9B,MAAM,qBAAqB,GAAG,MAAyD,CAAC;gBACxF,IAAI,qBAAqB,CAAC,kBAAkB,KAAK,SAAS,EAAE,CAAC;oBAC3D,qBAAqB,CAAC,kBAAkB,GAAG,EAAE,CAAC;gBAChD,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;CACF"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import * as crypto from 'crypto';
|
|
2
|
+
import { SecureConfigClient } from './SecureConfigClient.js';
|
|
3
|
+
export declare class KeysetService {
|
|
4
|
+
private cachePath;
|
|
5
|
+
private client;
|
|
6
|
+
private rootPublicKey;
|
|
7
|
+
constructor(client: SecureConfigClient, region: 'us' | 'cn', rootPublicKeyPem: string, cachePath?: string);
|
|
8
|
+
getPublicKeyByKid(kid: string): Promise<crypto.KeyObject | null>;
|
|
9
|
+
refresh(): Promise<void>;
|
|
10
|
+
private verifyKeysetSignature;
|
|
11
|
+
private isExpired;
|
|
12
|
+
private loadCache;
|
|
13
|
+
private saveCache;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=KeysetService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"KeysetService.d.ts","sourceRoot":"","sources":["../../src/secure-config/KeysetService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AAKjC,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAW7D,qBAAa,aAAa;IACxB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,aAAa,CAAmB;gBAGtC,MAAM,EAAE,kBAAkB,EAC1B,MAAM,EAAE,IAAI,GAAG,IAAI,EACnB,gBAAgB,EAAE,MAAM,EACxB,SAAS,CAAC,EAAE,MAAM;IAYd,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC;IAQhE,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAyB9B,OAAO,CAAC,qBAAqB;IAY7B,OAAO,CAAC,SAAS;IAMjB,OAAO,CAAC,SAAS;IAUjB,OAAO,CAAC,SAAS;CAOlB"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import * as crypto from 'crypto';
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
import * as os from 'os';
|
|
5
|
+
import { canonicalize } from './signatureUtils.js';
|
|
6
|
+
const DEFAULT_TTL_MS = 24 * 60 * 60 * 1000;
|
|
7
|
+
export class KeysetService {
|
|
8
|
+
cachePath;
|
|
9
|
+
client;
|
|
10
|
+
rootPublicKey;
|
|
11
|
+
constructor(client, region, rootPublicKeyPem, cachePath) {
|
|
12
|
+
this.client = client;
|
|
13
|
+
this.rootPublicKey = crypto.createPublicKey(rootPublicKeyPem);
|
|
14
|
+
if (cachePath) {
|
|
15
|
+
this.cachePath = cachePath;
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
const baseDir = path.join(os.homedir(), '.agent-chatter', 'secure-config');
|
|
19
|
+
this.cachePath = path.join(baseDir, `keyset-${region}.json`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
async getPublicKeyByKid(kid) {
|
|
23
|
+
const cached = this.loadCache();
|
|
24
|
+
if (!cached || this.isExpired(cached))
|
|
25
|
+
return null;
|
|
26
|
+
const key = cached.keyset.keys.find((k) => k.kid === kid);
|
|
27
|
+
if (!key)
|
|
28
|
+
return null;
|
|
29
|
+
return crypto.createPublicKey(key.public_key_pem);
|
|
30
|
+
}
|
|
31
|
+
async refresh() {
|
|
32
|
+
const cached = this.loadCache();
|
|
33
|
+
const etag = cached?.etag ?? null;
|
|
34
|
+
const result = await this.client.fetchKeyset(etag);
|
|
35
|
+
if (result.notModified && cached) {
|
|
36
|
+
// Update fetched time to extend TTL
|
|
37
|
+
this.saveCache({ ...cached, fetched_at: new Date().toISOString() });
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (!result.keyset) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
if (!this.verifyKeysetSignature(result.keyset)) {
|
|
44
|
+
throw new Error('Keyset signature invalid');
|
|
45
|
+
}
|
|
46
|
+
this.saveCache({
|
|
47
|
+
keyset: result.keyset,
|
|
48
|
+
etag: result.etag,
|
|
49
|
+
fetched_at: new Date().toISOString(),
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
verifyKeysetSignature(keyset) {
|
|
53
|
+
const payload = {
|
|
54
|
+
region: keyset.region,
|
|
55
|
+
keys: keyset.keys,
|
|
56
|
+
};
|
|
57
|
+
const canonical = canonicalize(payload);
|
|
58
|
+
const signature = Buffer.from(keyset.signature, 'base64');
|
|
59
|
+
const verifier = crypto.createVerify('SHA256');
|
|
60
|
+
verifier.update(canonical);
|
|
61
|
+
return verifier.verify(this.rootPublicKey, signature);
|
|
62
|
+
}
|
|
63
|
+
isExpired(cache) {
|
|
64
|
+
const fetchedAt = Date.parse(cache.fetched_at);
|
|
65
|
+
if (!Number.isFinite(fetchedAt))
|
|
66
|
+
return true;
|
|
67
|
+
return Date.now() - fetchedAt > DEFAULT_TTL_MS;
|
|
68
|
+
}
|
|
69
|
+
loadCache() {
|
|
70
|
+
try {
|
|
71
|
+
if (!fs.existsSync(this.cachePath))
|
|
72
|
+
return null;
|
|
73
|
+
const raw = fs.readFileSync(this.cachePath, 'utf-8');
|
|
74
|
+
return JSON.parse(raw);
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
saveCache(cache) {
|
|
81
|
+
const dir = path.dirname(this.cachePath);
|
|
82
|
+
if (!fs.existsSync(dir)) {
|
|
83
|
+
fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
84
|
+
}
|
|
85
|
+
fs.writeFileSync(this.cachePath, JSON.stringify(cache, null, 2), { mode: 0o600 });
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=KeysetService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"KeysetService.js","sourceRoot":"","sources":["../../src/secure-config/KeysetService.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { SecureConfigPackage } from './types.js';
|
|
2
|
+
import type { CLIConfig } from '@testany/agent-chatter-core';
|
|
3
|
+
import { DeviceKeyService } from './DeviceKeyService.js';
|
|
4
|
+
import { KeysetService } from './KeysetService.js';
|
|
5
|
+
export declare class SCPService {
|
|
6
|
+
private deviceKeyService;
|
|
7
|
+
private keysetService;
|
|
8
|
+
constructor(deviceKeyService: DeviceKeyService, keysetService: KeysetService);
|
|
9
|
+
decryptSCP(scp: SecureConfigPackage, fetchSCPFn: () => Promise<SecureConfigPackage>): Promise<CLIConfig>;
|
|
10
|
+
private verifySignature;
|
|
11
|
+
private doDecrypt;
|
|
12
|
+
private decryptPayload;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=SCPService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SCPService.d.ts","sourceRoot":"","sources":["../../src/secure-config/SCPService.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAInD,qBAAa,UAAU;IAEnB,OAAO,CAAC,gBAAgB;IACxB,OAAO,CAAC,aAAa;gBADb,gBAAgB,EAAE,gBAAgB,EAClC,aAAa,EAAE,aAAa;IAGhC,UAAU,CACd,GAAG,EAAE,mBAAmB,EACxB,UAAU,EAAE,MAAM,OAAO,CAAC,mBAAmB,CAAC,GAC7C,OAAO,CAAC,SAAS,CAAC;YAoBP,eAAe;YA4Bf,SAAS;IAqBvB,OAAO,CAAC,cAAc;CAUvB"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import * as crypto from 'crypto';
|
|
2
|
+
import { canonicalize, sha256Hex } from './signatureUtils.js';
|
|
3
|
+
import { SecureConfigError } from './errors.js';
|
|
4
|
+
export class SCPService {
|
|
5
|
+
deviceKeyService;
|
|
6
|
+
keysetService;
|
|
7
|
+
constructor(deviceKeyService, keysetService) {
|
|
8
|
+
this.deviceKeyService = deviceKeyService;
|
|
9
|
+
this.keysetService = keysetService;
|
|
10
|
+
}
|
|
11
|
+
async decryptSCP(scp, fetchSCPFn) {
|
|
12
|
+
if (!(await this.verifySignature(scp))) {
|
|
13
|
+
throw new SecureConfigError('SIGNATURE_INVALID', 'SCP signature verification failed');
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
return await this.doDecrypt(scp);
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
const fresh = await fetchSCPFn();
|
|
20
|
+
if (!(await this.verifySignature(fresh))) {
|
|
21
|
+
throw new SecureConfigError('SIGNATURE_INVALID', 'SCP signature verification failed');
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
return await this.doDecrypt(fresh);
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
throw new SecureConfigError('DECRYPTION_FAILED', 'Failed to decrypt SCP payload');
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
async verifySignature(scp) {
|
|
32
|
+
const payloadEncBuffer = Buffer.from(scp.payload_enc, 'base64');
|
|
33
|
+
const keyEncBuffer = Buffer.from(scp.key_enc, 'base64');
|
|
34
|
+
const signData = {
|
|
35
|
+
manifest: scp.manifest,
|
|
36
|
+
payload_enc_hash: sha256Hex(payloadEncBuffer),
|
|
37
|
+
key_enc_hash: sha256Hex(keyEncBuffer),
|
|
38
|
+
};
|
|
39
|
+
const canonical = canonicalize(signData);
|
|
40
|
+
const signature = Buffer.from(scp.signature, 'base64');
|
|
41
|
+
const verify = crypto.createVerify('SHA256');
|
|
42
|
+
verify.update(canonical);
|
|
43
|
+
const publicKey = await this.keysetService.getPublicKeyByKid(scp.manifest.kid);
|
|
44
|
+
if (!publicKey) {
|
|
45
|
+
await this.keysetService.refresh();
|
|
46
|
+
}
|
|
47
|
+
const refreshedKey = await this.keysetService.getPublicKeyByKid(scp.manifest.kid);
|
|
48
|
+
if (!refreshedKey) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
return verify.verify(refreshedKey, signature);
|
|
52
|
+
}
|
|
53
|
+
async doDecrypt(scp) {
|
|
54
|
+
const keyEncBuffer = Buffer.from(scp.key_enc, 'base64');
|
|
55
|
+
const devicePrivateKey = this.deviceKeyService.loadPrivateKey();
|
|
56
|
+
const dek = crypto.privateDecrypt({
|
|
57
|
+
key: devicePrivateKey,
|
|
58
|
+
padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
|
|
59
|
+
oaepHash: 'sha256',
|
|
60
|
+
}, keyEncBuffer);
|
|
61
|
+
try {
|
|
62
|
+
const payloadEncBuffer = Buffer.from(scp.payload_enc, 'base64');
|
|
63
|
+
const plaintext = this.decryptPayload(payloadEncBuffer, dek);
|
|
64
|
+
return JSON.parse(plaintext.toString('utf-8'));
|
|
65
|
+
}
|
|
66
|
+
finally {
|
|
67
|
+
dek.fill(0);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
decryptPayload(encrypted, dek) {
|
|
71
|
+
const iv = encrypted.subarray(0, 12);
|
|
72
|
+
const authTag = encrypted.subarray(-16);
|
|
73
|
+
const ciphertext = encrypted.subarray(12, -16);
|
|
74
|
+
const decipher = crypto.createDecipheriv('aes-256-gcm', dek, iv);
|
|
75
|
+
decipher.setAuthTag(authTag);
|
|
76
|
+
return Buffer.concat([decipher.update(ciphertext), decipher.final()]);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=SCPService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SCPService.js","sourceRoot":"","sources":["../../src/secure-config/SCPService.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { SecureConfigResponse, SecureConfigKeyset, DeviceRegisterRequest, DeviceRegisterResponse, TeamListResponse, ClientType } from './types.js';
|
|
2
|
+
import type { AuthEnvironment } from '../auth/types.js';
|
|
3
|
+
export interface SecureConfigClientOptions {
|
|
4
|
+
region: 'us' | 'cn';
|
|
5
|
+
environment: AuthEnvironment;
|
|
6
|
+
accessToken: string;
|
|
7
|
+
deviceId: string;
|
|
8
|
+
clientType: ClientType;
|
|
9
|
+
clientVersion: string;
|
|
10
|
+
}
|
|
11
|
+
export interface KeysetFetchResult {
|
|
12
|
+
keyset?: SecureConfigKeyset;
|
|
13
|
+
etag?: string | null;
|
|
14
|
+
notModified?: boolean;
|
|
15
|
+
}
|
|
16
|
+
export declare class SecureConfigClient {
|
|
17
|
+
private baseUrl;
|
|
18
|
+
private accessToken;
|
|
19
|
+
private deviceId;
|
|
20
|
+
private clientType;
|
|
21
|
+
private clientVersion;
|
|
22
|
+
constructor(options: SecureConfigClientOptions);
|
|
23
|
+
fetchSCP(teamId: string): Promise<SecureConfigResponse['data']>;
|
|
24
|
+
registerDevice(payload: DeviceRegisterRequest): Promise<DeviceRegisterResponse['data']>;
|
|
25
|
+
fetchKeyset(etag?: string | null): Promise<KeysetFetchResult>;
|
|
26
|
+
listTeams(limit?: number): Promise<TeamListResponse['data']>;
|
|
27
|
+
private request;
|
|
28
|
+
private rawRequest;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=SecureConfigClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SecureConfigClient.d.ts","sourceRoot":"","sources":["../../src/secure-config/SecureConfigClient.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,oBAAoB,EAEpB,kBAAkB,EAClB,qBAAqB,EACrB,sBAAsB,EACtB,gBAAgB,EAChB,UAAU,EACX,MAAM,YAAY,CAAC;AAGpB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExD,MAAM,WAAW,yBAAyB;IACxC,MAAM,EAAE,IAAI,GAAG,IAAI,CAAC;IACpB,WAAW,EAAE,eAAe,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,UAAU,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,aAAa,CAAS;gBAElB,OAAO,EAAE,yBAAyB;IAQxC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAa/D,cAAc,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC;IAUvF,WAAW,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAyB7D,SAAS,CAAC,KAAK,SAAK,GAAG,OAAO,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;YAMhD,OAAO;YAiBP,UAAU;CAWzB"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { SecureConfigError } from './errors.js';
|
|
2
|
+
import { getApiBaseUrl } from '../auth/AuthConfig.js';
|
|
3
|
+
export class SecureConfigClient {
|
|
4
|
+
baseUrl;
|
|
5
|
+
accessToken;
|
|
6
|
+
deviceId;
|
|
7
|
+
clientType;
|
|
8
|
+
clientVersion;
|
|
9
|
+
constructor(options) {
|
|
10
|
+
this.baseUrl = getApiBaseUrl(options.region, options.environment);
|
|
11
|
+
this.accessToken = options.accessToken;
|
|
12
|
+
this.deviceId = options.deviceId;
|
|
13
|
+
this.clientType = options.clientType;
|
|
14
|
+
this.clientVersion = options.clientVersion;
|
|
15
|
+
}
|
|
16
|
+
async fetchSCP(teamId) {
|
|
17
|
+
const path = `/secure-config/teams/${teamId}`;
|
|
18
|
+
const result = await this.request(path, {
|
|
19
|
+
method: 'GET',
|
|
20
|
+
headers: {
|
|
21
|
+
'X-Device-Id': this.deviceId,
|
|
22
|
+
'X-Client-Type': this.clientType,
|
|
23
|
+
'X-Client-Version': this.clientVersion,
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
return result.data;
|
|
27
|
+
}
|
|
28
|
+
async registerDevice(payload) {
|
|
29
|
+
const path = '/secure-config/devices/register';
|
|
30
|
+
const result = await this.request(path, {
|
|
31
|
+
method: 'POST',
|
|
32
|
+
headers: { 'Content-Type': 'application/json' },
|
|
33
|
+
body: JSON.stringify(payload),
|
|
34
|
+
});
|
|
35
|
+
return result.data;
|
|
36
|
+
}
|
|
37
|
+
async fetchKeyset(etag) {
|
|
38
|
+
const path = '/secure-config/public-keys';
|
|
39
|
+
const headers = {};
|
|
40
|
+
if (etag)
|
|
41
|
+
headers['If-None-Match'] = etag;
|
|
42
|
+
const response = await this.rawRequest(path, { method: 'GET', headers });
|
|
43
|
+
if (response.status === 304) {
|
|
44
|
+
return { notModified: true, etag };
|
|
45
|
+
}
|
|
46
|
+
const parsed = (await response.json());
|
|
47
|
+
if (!response.ok || parsed.success === false) {
|
|
48
|
+
const err = parsed;
|
|
49
|
+
throw new SecureConfigError(err?.error?.code || 'SECURE_CONFIG_ERROR', err?.error?.message || 'Failed to fetch keyset', response.status, err?.error?.request_id);
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
keyset: parsed.data,
|
|
53
|
+
etag: response.headers.get('ETag'),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
async listTeams(limit = 50) {
|
|
57
|
+
const path = `/teams?limit=${limit}`;
|
|
58
|
+
const result = await this.request(path, { method: 'GET' });
|
|
59
|
+
return result.data;
|
|
60
|
+
}
|
|
61
|
+
async request(path, init) {
|
|
62
|
+
const response = await this.rawRequest(path, init);
|
|
63
|
+
const parsed = (await response.json());
|
|
64
|
+
if (!response.ok || parsed.success === false) {
|
|
65
|
+
const err = parsed;
|
|
66
|
+
throw new SecureConfigError(err?.error?.code || 'SECURE_CONFIG_ERROR', err?.error?.message || `Request failed with status ${response.status}`, response.status, err?.error?.request_id);
|
|
67
|
+
}
|
|
68
|
+
return parsed;
|
|
69
|
+
}
|
|
70
|
+
async rawRequest(path, init) {
|
|
71
|
+
const headers = {
|
|
72
|
+
Authorization: `Bearer ${this.accessToken}`,
|
|
73
|
+
...init.headers,
|
|
74
|
+
};
|
|
75
|
+
return await fetch(`${this.baseUrl}${path}`, {
|
|
76
|
+
...init,
|
|
77
|
+
headers,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=SecureConfigClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SecureConfigClient.js","sourceRoot":"","sources":["../../src/secure-config/SecureConfigClient.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare class SecureConfigError extends Error {
|
|
2
|
+
readonly code: string;
|
|
3
|
+
readonly status?: number | undefined;
|
|
4
|
+
readonly requestId?: string | undefined;
|
|
5
|
+
constructor(code: string, message: string, status?: number | undefined, requestId?: string | undefined);
|
|
6
|
+
}
|
|
7
|
+
export declare const SecureConfigExitCode: Record<string, number>;
|
|
8
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/secure-config/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,iBAAkB,SAAQ,KAAK;aAExB,IAAI,EAAE,MAAM;aAEZ,MAAM,CAAC,EAAE,MAAM;aACf,SAAS,CAAC,EAAE,MAAM;gBAHlB,IAAI,EAAE,MAAM,EAC5B,OAAO,EAAE,MAAM,EACC,MAAM,CAAC,EAAE,MAAM,YAAA,EACf,SAAS,CAAC,EAAE,MAAM,YAAA;CAKrC;AAED,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAMvD,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export class SecureConfigError extends Error {
|
|
2
|
+
code;
|
|
3
|
+
status;
|
|
4
|
+
requestId;
|
|
5
|
+
constructor(code, message, status, requestId) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.code = code;
|
|
8
|
+
this.status = status;
|
|
9
|
+
this.requestId = requestId;
|
|
10
|
+
this.name = 'SecureConfigError';
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export const SecureConfigExitCode = {
|
|
14
|
+
SIGNATURE_INVALID: 12,
|
|
15
|
+
DECRYPTION_FAILED: 13,
|
|
16
|
+
DEVICE_NOT_REGISTERED: 14,
|
|
17
|
+
USER_FROZEN: 20,
|
|
18
|
+
TEAM_ACCESS_DENIED: 21,
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/secure-config/errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IAExB;IAEA;IACA;IAJlB,YACkB,IAAY,EAC5B,OAAe,EACC,MAAe,EACf,SAAkB;QAElC,KAAK,CAAC,OAAO,CAAC,CAAC;QALC,SAAI,GAAJ,IAAI,CAAQ;QAEZ,WAAM,GAAN,MAAM,CAAS;QACf,cAAS,GAAT,SAAS,CAAS;QAGlC,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;IAClC,CAAC;CACF;AAED,MAAM,CAAC,MAAM,oBAAoB,GAA2B;IAC1D,iBAAiB,EAAE,EAAE;IACrB,iBAAiB,EAAE,EAAE;IACrB,qBAAqB,EAAE,EAAE;IACzB,WAAW,EAAE,EAAE;IACf,kBAAkB,EAAE,EAAE;CACvB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export * from './types.js';
|
|
2
|
+
export * from './errors.js';
|
|
3
|
+
export * from './DeviceStore.js';
|
|
4
|
+
export * from './DeviceKeyService.js';
|
|
5
|
+
export * from './SecureConfigClient.js';
|
|
6
|
+
export * from './KeysetService.js';
|
|
7
|
+
export * from './SCPService.js';
|
|
8
|
+
export * from './InstructionNormalizer.js';
|
|
9
|
+
export * from './BaseDirResolver.js';
|
|
10
|
+
export * from './rootKey.js';
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/secure-config/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,sBAAsB,CAAC;AACrC,cAAc,cAAc,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export * from './types.js';
|
|
2
|
+
export * from './errors.js';
|
|
3
|
+
export * from './DeviceStore.js';
|
|
4
|
+
export * from './DeviceKeyService.js';
|
|
5
|
+
export * from './SecureConfigClient.js';
|
|
6
|
+
export * from './KeysetService.js';
|
|
7
|
+
export * from './SCPService.js';
|
|
8
|
+
export * from './InstructionNormalizer.js';
|
|
9
|
+
export * from './BaseDirResolver.js';
|
|
10
|
+
export * from './rootKey.js';
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/secure-config/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,sBAAsB,CAAC;AACrC,cAAc,cAAc,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rootKey.d.ts","sourceRoot":"","sources":["../../src/secure-config/rootKey.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AA6CpE,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,eAAe,GAAG,MAAM,CAWxF"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
const DEFAULT_ROOT_PUBLIC_KEYS = {
|
|
2
|
+
us: {
|
|
3
|
+
staging: `-----BEGIN PUBLIC KEY-----
|
|
4
|
+
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvyY9G5YRo3gCVX6zCdCL
|
|
5
|
+
B2zJ+oAzazXHAMishHllBJxInvi/gnwlYbmzWifst17SKmyZL4ccTGxImjueH9aR
|
|
6
|
+
gleHr1NSm9OnNmJqLWUekEYvR6quxrY/shrLsDx8rRljHSyGo4aWAE+TCG4LV2D1
|
|
7
|
+
WvuudGvQbXd5U94dUDlx+Ft2MLPoW0v84W4zh93vciGXp6A4OK3zu/JicIs1y21p
|
|
8
|
+
i/B/Gk90jQBpUgIZvBWHLCk+sX0sN6LU8TkgfUaTpKCuDmDPFjoiPtTNNiahX/hU
|
|
9
|
+
WcuZBnd3LYBFKev+4hCjiSgNHp9ccXczMIftwTk8fgasyMaNr1uZROs6Rl+WhftN
|
|
10
|
+
MQIDAQAB
|
|
11
|
+
-----END PUBLIC KEY-----`,
|
|
12
|
+
prod: `-----BEGIN PUBLIC KEY-----
|
|
13
|
+
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqnRYIIqaGscRGTPoMRFS
|
|
14
|
+
wm2XJEYfySBVfK1kfHwF1hgn4PUHjziCAE8LMKVi9mwSR9EKAe0LfTOul2YbCE0S
|
|
15
|
+
kkoGopwcENx0+xGTaV3QVherhxrcoqewUHbbSDdDKLPsrTGkFPPNZ5h3q3h5TCjj
|
|
16
|
+
VtATDN6kj17q4iYIk53KJSnWq5Iye68nZk5NPoo0zS0L7jwhRW/yxtCRfDQz2QDI
|
|
17
|
+
AKADVsXZXSlfs4nTy/amE1xWhU+OC1P5ora26glUbWsOj2E/Th+5qNKu4dlKWQbM
|
|
18
|
+
W4roPJ/YjNxapfGb0aVeXXKbOCDYy/F8yXNMkVd3whYc5WTQ+obcQLvYWRDgiEyc
|
|
19
|
+
0wIDAQAB
|
|
20
|
+
-----END PUBLIC KEY-----`,
|
|
21
|
+
},
|
|
22
|
+
cn: {
|
|
23
|
+
staging: `-----BEGIN PUBLIC KEY-----
|
|
24
|
+
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1W/R74R3D1Ltr6zNa7Nx
|
|
25
|
+
V7QrdtOnknxhUF6u8b/DwfhGnbhhYW1S8YdpQYYxY/Uf75nCfeZkau0+K04tUhUP
|
|
26
|
+
qQHvlw3MzZyTDAijf7wRCrYDi5giLhnTZFX7yNWs0ypDgLjx97ectF0DNb76JOhb
|
|
27
|
+
M8vwKhAV3CLliD0VglT6DcT7aM2NM/rjbGCh64zF2AXBvWJ7D6sc/oNHPWX8FA+z
|
|
28
|
+
XMeM4917aaeqcCqFfhdx3udk0Cm+nrXpOUkvZeHCWFhL7nMZkKjutLyd9bUeokds
|
|
29
|
+
ply/y9ol45JwQnQ/k6lOZP14MFIS0pPd9djE3/rjougNf8jqY0I28uuJYSCNGdxV
|
|
30
|
+
CwIDAQAB
|
|
31
|
+
-----END PUBLIC KEY-----`,
|
|
32
|
+
prod: `-----BEGIN PUBLIC KEY-----
|
|
33
|
+
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyEPAAr99fdziOBMA48aD
|
|
34
|
+
ejTAyxcZmSkP+sbuZkJ71OXC9+PqXiDBWWYmz5D37PmErU85DYyDyRWKK1DrEVpW
|
|
35
|
+
IwcA+SOzsVqgXeYyNDp07GqjDsypgXd7W89juV1dBzLcE9qvDnxoqscDO600B2Mr
|
|
36
|
+
Y38Fpn1zOESL1By6MLvMl6gfbMWYir3+Eh2wSDfCcmDN2W1Nhj2YOORoIyTE9IqZ
|
|
37
|
+
0T5uU3lvgWAcwOaBE9OjGj5BDa5piBnWGn3FiSyZxdbZmemJ99GXH1YiKrvvxDNE
|
|
38
|
+
0ySbIiinTdvXLuNCXt2nx5hPu2kiOYh/IyvU9i9/tIbkmyqRGMkc0BeT90qombAY
|
|
39
|
+
VQIDAQAB
|
|
40
|
+
-----END PUBLIC KEY-----`,
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
export function resolveRootPublicKeyPem(region, env) {
|
|
44
|
+
const raw = process.env.SCP_ROOT_PUBLIC_KEY_PEM;
|
|
45
|
+
if (raw && raw.trim().length > 0) {
|
|
46
|
+
return normalizePem(raw);
|
|
47
|
+
}
|
|
48
|
+
const embedded = DEFAULT_ROOT_PUBLIC_KEYS[region]?.[env];
|
|
49
|
+
if (!embedded) {
|
|
50
|
+
throw new Error(`SCP_ROOT_PUBLIC_KEY_PEM is required for ${region}-${env}.`);
|
|
51
|
+
}
|
|
52
|
+
return embedded;
|
|
53
|
+
}
|
|
54
|
+
function normalizePem(raw) {
|
|
55
|
+
return raw.includes('\\n') ? raw.replace(/\\n/g, '\n') : raw;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=rootKey.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rootKey.js","sourceRoot":"","sources":["../../src/secure-config/rootKey.ts"],"names":[],"mappings":"AAEA,MAAM,wBAAwB,GAA0E;IACtG,EAAE,EAAE;QACF,OAAO,EAAE;;;;;;;;yBAQY;QACrB,IAAI,EAAE;;;;;;;;yBAQe;KACtB;IACD,EAAE,EAAE;QACF,OAAO,EAAE;;;;;;;;yBAQY;QACrB,IAAI,EAAE;;;;;;;;yBAQe;KACtB;CACF,CAAC;AAEF,MAAM,UAAU,uBAAuB,CAAC,MAAkB,EAAE,GAAoB;IAC9E,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC;IAChD,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACjC,OAAO,YAAY,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAED,MAAM,QAAQ,GAAG,wBAAwB,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;IACzD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,2CAA2C,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC;IAC/E,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,YAAY,CAAC,GAAW;IAC/B,OAAO,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;AAC/D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signatureUtils.d.ts","sourceRoot":"","sources":["../../src/secure-config/signatureUtils.ts"],"names":[],"mappings":"AAEA,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEnD"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as crypto from 'crypto';
|
|
2
|
+
export function sha256Hex(input) {
|
|
3
|
+
return crypto.createHash('sha256').update(input).digest('hex');
|
|
4
|
+
}
|
|
5
|
+
export function canonicalize(value) {
|
|
6
|
+
return JSON.stringify(sortKeys(value));
|
|
7
|
+
}
|
|
8
|
+
function sortKeys(value) {
|
|
9
|
+
if (Array.isArray(value)) {
|
|
10
|
+
return value.map(sortKeys);
|
|
11
|
+
}
|
|
12
|
+
if (value && typeof value === 'object') {
|
|
13
|
+
const record = value;
|
|
14
|
+
return Object.keys(record)
|
|
15
|
+
.sort()
|
|
16
|
+
.reduce((acc, key) => {
|
|
17
|
+
acc[key] = sortKeys(record[key]);
|
|
18
|
+
return acc;
|
|
19
|
+
}, {});
|
|
20
|
+
}
|
|
21
|
+
return value;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=signatureUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signatureUtils.js","sourceRoot":"","sources":["../../src/secure-config/signatureUtils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AAEjC,MAAM,UAAU,SAAS,CAAC,KAAa;IACrC,OAAO,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,KAAc;IACzC,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;AACzC,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC7B,CAAC;IACD,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvC,MAAM,MAAM,GAAG,KAAgC,CAAC;QAChD,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;aACvB,IAAI,EAAE;aACN,MAAM,CAA0B,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;YAC5C,GAAG,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YACjC,OAAO,GAAG,CAAC;QACb,CAAC,EAAE,EAAE,CAAC,CAAC;IACX,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
export type ClientType = 'cli' | 'desktop';
|
|
2
|
+
export interface SCPManifest {
|
|
3
|
+
team_id: string;
|
|
4
|
+
version: string;
|
|
5
|
+
ttl: number;
|
|
6
|
+
created_at: string;
|
|
7
|
+
kid: string;
|
|
8
|
+
}
|
|
9
|
+
export interface SecureConfigPackage {
|
|
10
|
+
manifest: SCPManifest;
|
|
11
|
+
payload_enc: string;
|
|
12
|
+
key_enc: string;
|
|
13
|
+
signature: string;
|
|
14
|
+
}
|
|
15
|
+
export interface SecureConfigKeyset {
|
|
16
|
+
region: 'us' | 'cn';
|
|
17
|
+
keys: Array<{
|
|
18
|
+
kid: string;
|
|
19
|
+
public_key_pem: string;
|
|
20
|
+
algorithm: 'RSASSA_PKCS1_V1_5_SHA_256';
|
|
21
|
+
status: 'active' | 'deprecated';
|
|
22
|
+
valid_from?: string;
|
|
23
|
+
valid_to?: string;
|
|
24
|
+
}>;
|
|
25
|
+
signature: string;
|
|
26
|
+
}
|
|
27
|
+
export interface SecureConfigKeysetResponse {
|
|
28
|
+
success: true;
|
|
29
|
+
data: SecureConfigKeyset;
|
|
30
|
+
request_id?: string;
|
|
31
|
+
}
|
|
32
|
+
export interface SecureConfigResponse {
|
|
33
|
+
success: true;
|
|
34
|
+
data: SecureConfigPackage;
|
|
35
|
+
request_id?: string;
|
|
36
|
+
}
|
|
37
|
+
export interface SecureConfigErrorResponse {
|
|
38
|
+
success: false;
|
|
39
|
+
error: {
|
|
40
|
+
code: string;
|
|
41
|
+
message: string;
|
|
42
|
+
details?: Record<string, unknown>;
|
|
43
|
+
request_id?: string;
|
|
44
|
+
retry_after_seconds?: number;
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
export interface DeviceRegisterRequest {
|
|
48
|
+
device_id: string;
|
|
49
|
+
public_key_pem: string;
|
|
50
|
+
device_name?: string;
|
|
51
|
+
}
|
|
52
|
+
export interface DeviceRegisterResponse {
|
|
53
|
+
success: true;
|
|
54
|
+
data: {
|
|
55
|
+
device_id: string;
|
|
56
|
+
registered_at: string;
|
|
57
|
+
};
|
|
58
|
+
request_id?: string;
|
|
59
|
+
}
|
|
60
|
+
export type ApiResponse<T> = T | SecureConfigErrorResponse;
|
|
61
|
+
export interface DeviceKeyInfo {
|
|
62
|
+
deviceId: string;
|
|
63
|
+
publicKeyPem: string;
|
|
64
|
+
}
|
|
65
|
+
export interface TeamListResponse {
|
|
66
|
+
success: true;
|
|
67
|
+
data: {
|
|
68
|
+
teams: Array<{
|
|
69
|
+
team_id: string;
|
|
70
|
+
display_name?: string;
|
|
71
|
+
name?: string;
|
|
72
|
+
status?: string;
|
|
73
|
+
}>;
|
|
74
|
+
next_cursor: string | null;
|
|
75
|
+
has_more: boolean;
|
|
76
|
+
};
|
|
77
|
+
request_id?: string;
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=types.d.ts.map
|