@atbash/sdk 0.10.6-dev.0 → 0.10.7-dev.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/dist/browser.d.mts +74 -1
- package/dist/browser.mjs +111 -14
- package/dist/browser.mjs.map +1 -1
- package/dist/index.d.mts +74 -1
- package/dist/index.d.ts +74 -1
- package/dist/index.js +143 -22
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +142 -26
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
package/dist/index.mjs
CHANGED
|
@@ -3051,19 +3051,32 @@ var HttpClient = class {
|
|
|
3051
3051
|
};
|
|
3052
3052
|
|
|
3053
3053
|
// src-ts/keyLoader.ts
|
|
3054
|
-
import { readFileSync } from "fs";
|
|
3054
|
+
import { existsSync, readFileSync } from "fs";
|
|
3055
|
+
|
|
3056
|
+
// src-ts/key-path.ts
|
|
3055
3057
|
import { homedir } from "os";
|
|
3056
3058
|
import { join } from "path";
|
|
3057
|
-
var
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
return join(home, DEFAULT_KEY_PATH_REL);
|
|
3059
|
+
var KEY_DIR_REL = ".config/atbash";
|
|
3060
|
+
var KEY_FILENAMES = ["guard-client-key", "atbash-client-key"];
|
|
3061
|
+
function home() {
|
|
3062
|
+
return process.env.HOME || homedir() || "";
|
|
3062
3063
|
}
|
|
3063
3064
|
function expandHome(p) {
|
|
3064
3065
|
if (!p.startsWith("~/")) return p;
|
|
3065
|
-
|
|
3066
|
-
|
|
3066
|
+
return join(home(), p.slice(2));
|
|
3067
|
+
}
|
|
3068
|
+
function keyPathCandidates() {
|
|
3069
|
+
return KEY_FILENAMES.map((name2) => join(home(), KEY_DIR_REL, name2));
|
|
3070
|
+
}
|
|
3071
|
+
function chooseKeyPath(input, exists) {
|
|
3072
|
+
if (input) return expandHome(input);
|
|
3073
|
+
const candidates = keyPathCandidates();
|
|
3074
|
+
return candidates.find(exists) ?? candidates[0];
|
|
3075
|
+
}
|
|
3076
|
+
|
|
3077
|
+
// src-ts/keyLoader.ts
|
|
3078
|
+
function resolveKeyPath(input) {
|
|
3079
|
+
return chooseKeyPath(input, existsSync);
|
|
3067
3080
|
}
|
|
3068
3081
|
function readKeyFile(keyPath) {
|
|
3069
3082
|
const content = String(readFileSync(keyPath, "utf8") || "").trim();
|
|
@@ -3093,6 +3106,12 @@ function readKeyFile(keyPath) {
|
|
|
3093
3106
|
}
|
|
3094
3107
|
function loadAgentFromFile(keyPath) {
|
|
3095
3108
|
const resolved = resolveKeyPath(keyPath);
|
|
3109
|
+
if (!existsSync(resolved)) {
|
|
3110
|
+
const looked = keyPath ? [resolved] : keyPathCandidates();
|
|
3111
|
+
throw new Error(
|
|
3112
|
+
`atbash key file not found. Looked for: ${looked.join(", ")}`
|
|
3113
|
+
);
|
|
3114
|
+
}
|
|
3096
3115
|
const { privKey } = readKeyFile(resolved);
|
|
3097
3116
|
return native.loadAgent(privKey);
|
|
3098
3117
|
}
|
|
@@ -3138,8 +3157,8 @@ var durationHistogram = null;
|
|
|
3138
3157
|
var defaultSource = "sdk";
|
|
3139
3158
|
function isTelemetryOptedOut() {
|
|
3140
3159
|
try {
|
|
3141
|
-
const
|
|
3142
|
-
const filePath = join2(
|
|
3160
|
+
const home2 = process.env.HOME || homedir2() || "";
|
|
3161
|
+
const filePath = join2(home2, ".config", "atbash", "telemetry.json");
|
|
3143
3162
|
const raw2 = readFileSync2(filePath, "utf-8").trim();
|
|
3144
3163
|
if (!raw2) return false;
|
|
3145
3164
|
const config2 = JSON.parse(raw2);
|
|
@@ -3217,7 +3236,7 @@ async function shutdownTelemetry() {
|
|
|
3217
3236
|
// src-ts/userConfig.ts
|
|
3218
3237
|
import {
|
|
3219
3238
|
chmodSync,
|
|
3220
|
-
existsSync,
|
|
3239
|
+
existsSync as existsSync2,
|
|
3221
3240
|
mkdirSync,
|
|
3222
3241
|
readFileSync as readFileSync3,
|
|
3223
3242
|
writeFileSync
|
|
@@ -3230,11 +3249,12 @@ var ENV_MAP = {
|
|
|
3230
3249
|
judgeEndpoint: "ATBASH_ENDPOINT",
|
|
3231
3250
|
blockchainRid: "ATBASH_BLOCKCHAIN_RID",
|
|
3232
3251
|
provider: "ATBASH_PROVIDER",
|
|
3233
|
-
providerModel: "ATBASH_PROVIDER_MODEL"
|
|
3252
|
+
providerModel: "ATBASH_PROVIDER_MODEL",
|
|
3253
|
+
debug: "ATBASH_DEBUG"
|
|
3234
3254
|
};
|
|
3235
3255
|
function getConfigDir() {
|
|
3236
|
-
const
|
|
3237
|
-
return join3(
|
|
3256
|
+
const home2 = process.env.HOME || homedir3() || "";
|
|
3257
|
+
return join3(home2, ".config", "atbash");
|
|
3238
3258
|
}
|
|
3239
3259
|
function getConfigPath() {
|
|
3240
3260
|
return join3(getConfigDir(), "config.json");
|
|
@@ -3242,7 +3262,7 @@ function getConfigPath() {
|
|
|
3242
3262
|
function loadUserConfig() {
|
|
3243
3263
|
try {
|
|
3244
3264
|
const p = getConfigPath();
|
|
3245
|
-
if (!
|
|
3265
|
+
if (!existsSync2(p)) return {};
|
|
3246
3266
|
const raw2 = readFileSync3(p, "utf-8").trim();
|
|
3247
3267
|
if (!raw2) return {};
|
|
3248
3268
|
return JSON.parse(raw2);
|
|
@@ -3253,7 +3273,7 @@ function loadUserConfig() {
|
|
|
3253
3273
|
}
|
|
3254
3274
|
function saveUserConfig(config2) {
|
|
3255
3275
|
const dir = getConfigDir();
|
|
3256
|
-
if (!
|
|
3276
|
+
if (!existsSync2(dir)) {
|
|
3257
3277
|
mkdirSync(dir, { recursive: true, mode: 448 });
|
|
3258
3278
|
}
|
|
3259
3279
|
const filePath = getConfigPath();
|
|
@@ -3293,6 +3313,7 @@ var Atbash = class _Atbash {
|
|
|
3293
3313
|
failClosed;
|
|
3294
3314
|
/** Org key learned from the last agent-exists check, for this agent only. */
|
|
3295
3315
|
_orgKeyFromChain = null;
|
|
3316
|
+
debug;
|
|
3296
3317
|
logger;
|
|
3297
3318
|
http;
|
|
3298
3319
|
/**
|
|
@@ -3306,6 +3327,8 @@ var Atbash = class _Atbash {
|
|
|
3306
3327
|
* server-side replay protection windows never expire it mid-session.
|
|
3307
3328
|
*/
|
|
3308
3329
|
_authBearer = null;
|
|
3330
|
+
/** Guards `logEnvironmentOnce` — hosts construct several clients. */
|
|
3331
|
+
static environmentLogged = false;
|
|
3309
3332
|
constructor(privkey, options = {}) {
|
|
3310
3333
|
this.auth = native.loadAgent(privkey);
|
|
3311
3334
|
this.endpoint = (options.endpoint ?? DEFAULT_ENDPOINT).replace(/\/+$/, "") || DEFAULT_ENDPOINT;
|
|
@@ -3315,8 +3338,10 @@ var Atbash = class _Atbash {
|
|
|
3315
3338
|
this.verifyPubKey = options.verifyPubKey;
|
|
3316
3339
|
this.orgEncryptionPubKey = options.orgEncryptionPubKey;
|
|
3317
3340
|
this.failClosed = options.failClosed !== false;
|
|
3341
|
+
this.debug = options.debug === true;
|
|
3318
3342
|
this.logger = options.logger ?? {};
|
|
3319
3343
|
this.http = new HttpClient(this.endpoint, options.timeoutMs ?? 3e4);
|
|
3344
|
+
this.logEnvironmentOnce();
|
|
3320
3345
|
if (this.endpoint !== DEFAULT_ENDPOINT) {
|
|
3321
3346
|
this.logger.warn?.("[atbash] running on non-default judge endpoint", {
|
|
3322
3347
|
endpoint: this.endpoint,
|
|
@@ -3324,6 +3349,31 @@ var Atbash = class _Atbash {
|
|
|
3324
3349
|
});
|
|
3325
3350
|
}
|
|
3326
3351
|
}
|
|
3352
|
+
/**
|
|
3353
|
+
* Say which environment this build talks to, once per process.
|
|
3354
|
+
*
|
|
3355
|
+
* The endpoint and both chain RIDs are compiled in, chosen by the npm tag,
|
|
3356
|
+
* and no configuration repoints a released build. So installing the build
|
|
3357
|
+
* for the wrong environment is invisible: the plugin loads, the hook fires,
|
|
3358
|
+
* and every judge call fails because the agent does not exist on the chain
|
|
3359
|
+
* this build targets. Organisation names are not unique across environments
|
|
3360
|
+
* either, so an org resolving is not evidence the build is right.
|
|
3361
|
+
*/
|
|
3362
|
+
logEnvironmentOnce() {
|
|
3363
|
+
if (_Atbash.environmentLogged) return;
|
|
3364
|
+
_Atbash.environmentLogged = true;
|
|
3365
|
+
const brief = (rid) => rid ? `${rid.slice(0, 8)}\u2026` : "(unset)";
|
|
3366
|
+
this.logger.info?.(
|
|
3367
|
+
`[atbash] environment \u2014 judge=${this.endpoint} publicChain=${brief(native.DEFAULT_BLOCKCHAIN_RID)} privateChain=${brief(native.DEFAULT_PRIVATE_BLOCKCHAIN_RID)} activeChain=${brief(this.blockchainRid)} responseSignatureCheck=${this.verifyPubKey ? "on" : "off"}`,
|
|
3368
|
+
{
|
|
3369
|
+
judgeEndpoint: this.endpoint,
|
|
3370
|
+
publicBlockchainRid: native.DEFAULT_BLOCKCHAIN_RID,
|
|
3371
|
+
privateBlockchainRid: native.DEFAULT_PRIVATE_BLOCKCHAIN_RID,
|
|
3372
|
+
activeBlockchainRid: this.blockchainRid,
|
|
3373
|
+
responseSignatureCheck: Boolean(this.verifyPubKey)
|
|
3374
|
+
}
|
|
3375
|
+
);
|
|
3376
|
+
}
|
|
3327
3377
|
/**
|
|
3328
3378
|
* Construct from resolved config: explicit overrides → env vars → the
|
|
3329
3379
|
* `~/.config/atbash/config.json` file (see userConfig.resolve). The private
|
|
@@ -3347,6 +3397,9 @@ var Atbash = class _Atbash {
|
|
|
3347
3397
|
orgName: options.orgName,
|
|
3348
3398
|
verifyPubKey: validated.verifyPubKey ?? void 0,
|
|
3349
3399
|
failClosed: options.failClosed,
|
|
3400
|
+
// ATBASH_DEBUG lets an operator turn diagnostics on without editing a
|
|
3401
|
+
// host's plugin config, which is usually the harder half.
|
|
3402
|
+
debug: options.debug ?? /^(1|true|yes)$/i.test(resolve("debug")),
|
|
3350
3403
|
logger: options.logger
|
|
3351
3404
|
});
|
|
3352
3405
|
}
|
|
@@ -3592,8 +3645,9 @@ var Atbash = class _Atbash {
|
|
|
3592
3645
|
});
|
|
3593
3646
|
if (result.verdict === "No verdict") {
|
|
3594
3647
|
if (result.status !== "logged") {
|
|
3595
|
-
return this.
|
|
3648
|
+
return this.failJudge(
|
|
3596
3649
|
`judge returned no verdict without an audit-tier marker (status: ${result.status || "absent"})`,
|
|
3650
|
+
void 0,
|
|
3597
3651
|
result.toolCallId
|
|
3598
3652
|
);
|
|
3599
3653
|
}
|
|
@@ -3645,16 +3699,38 @@ var Atbash = class _Atbash {
|
|
|
3645
3699
|
toolCallId: result.toolCallId
|
|
3646
3700
|
};
|
|
3647
3701
|
}
|
|
3648
|
-
return this.
|
|
3702
|
+
return this.failJudge(
|
|
3649
3703
|
"unrecognized action_type from judge",
|
|
3704
|
+
void 0,
|
|
3650
3705
|
result.toolCallId
|
|
3651
3706
|
);
|
|
3652
3707
|
} catch (err) {
|
|
3653
|
-
|
|
3654
|
-
this.logger.warn?.("[atbash] judge API failed", { reason: message });
|
|
3655
|
-
return this.fail(message);
|
|
3708
|
+
return this.failJudge(errorMessage(err), err);
|
|
3656
3709
|
}
|
|
3657
3710
|
}
|
|
3711
|
+
/**
|
|
3712
|
+
* One exit for every judge failure.
|
|
3713
|
+
*
|
|
3714
|
+
* Status and reason go in the *message*, not only in the meta object: hosts
|
|
3715
|
+
* print the message and drop the meta, which is why this read as a bare
|
|
3716
|
+
* "judge API failed" while the judge was answering with a precise reason.
|
|
3717
|
+
* The response body follows only under `debug`, since it can echo the action.
|
|
3718
|
+
*/
|
|
3719
|
+
failJudge(reason, cause, toolCallId) {
|
|
3720
|
+
const api2 = cause instanceof AtbashAPIError ? cause : null;
|
|
3721
|
+
const status = api2 ? ` status=${api2.status || "no-response"}` : "";
|
|
3722
|
+
const body = this.debug && api2?.body ? ` body=${truncate(api2.body, 500)}` : "";
|
|
3723
|
+
this.logger.warn?.(
|
|
3724
|
+
`[atbash] judge API failed \u2014${status} reason=${truncate(reason, 300)}${body}`,
|
|
3725
|
+
{
|
|
3726
|
+
reason,
|
|
3727
|
+
...api2 ? { status: api2.status, body: api2.body } : {},
|
|
3728
|
+
endpoint: this.endpoint,
|
|
3729
|
+
...toolCallId ? { toolCallId } : {}
|
|
3730
|
+
}
|
|
3731
|
+
);
|
|
3732
|
+
return this.fail(reason, toolCallId);
|
|
3733
|
+
}
|
|
3658
3734
|
fail(reason, toolCallId) {
|
|
3659
3735
|
return { allow: !this.failClosed, verdict: "ERROR", reason, toolCallId };
|
|
3660
3736
|
}
|
|
@@ -4142,9 +4218,9 @@ function stringifyArgs(args) {
|
|
|
4142
4218
|
}
|
|
4143
4219
|
}
|
|
4144
4220
|
var MAX_ACTION_LEN = 4e3;
|
|
4145
|
-
function truncate(text) {
|
|
4146
|
-
if (text.length <=
|
|
4147
|
-
return text.slice(0,
|
|
4221
|
+
function truncate(text, limit = MAX_ACTION_LEN) {
|
|
4222
|
+
if (text.length <= limit) return text;
|
|
4223
|
+
return text.slice(0, limit) + "\u2026";
|
|
4148
4224
|
}
|
|
4149
4225
|
|
|
4150
4226
|
// src-ts/redact.ts
|
|
@@ -4187,6 +4263,17 @@ function verifyJudgeResponseSignature(bodyBytes, signatureHex, pubKeyHex) {
|
|
|
4187
4263
|
};
|
|
4188
4264
|
}
|
|
4189
4265
|
|
|
4266
|
+
// src-ts/memory/boot-sync-message.ts
|
|
4267
|
+
var BOOT_SYNC_HINT = "check the chain endpoint and orgName if the cause above does not explain it";
|
|
4268
|
+
function bootSyncFailureLine(cause) {
|
|
4269
|
+
const reason = cause instanceof Error ? cause.message : String(cause);
|
|
4270
|
+
const trimmed = reason.trim();
|
|
4271
|
+
return trimmed ? `[atbash] boot memory sync failed: ${trimmed}` : (
|
|
4272
|
+
// No cause to show: fall back to the advice rather than a bare colon.
|
|
4273
|
+
`[atbash] boot memory sync failed \u2014 ${BOOT_SYNC_HINT}`
|
|
4274
|
+
);
|
|
4275
|
+
}
|
|
4276
|
+
|
|
4190
4277
|
// src-ts/memory/crypto.ts
|
|
4191
4278
|
async function deriveMemoryKey(privkey) {
|
|
4192
4279
|
return native.deriveMemoryKey(privkey);
|
|
@@ -4212,6 +4299,19 @@ async function scanMemory(entry, auth, opts) {
|
|
|
4212
4299
|
toolArgsJson: opts?.toolArgsJson ?? JSON.stringify({ key: entry.key, source: entry.source }),
|
|
4213
4300
|
mode: "memory-scan"
|
|
4214
4301
|
});
|
|
4302
|
+
const knownAction = result.actionType === "allow" || result.actionType === "block" || result.actionType === "hold_for_user_confirm";
|
|
4303
|
+
const missingVerdict = result.verdict === "No verdict" && result.status !== "logged";
|
|
4304
|
+
const unknownAction = result.actionType !== "" && !knownAction;
|
|
4305
|
+
if (missingVerdict || unknownAction) {
|
|
4306
|
+
return {
|
|
4307
|
+
safe: false,
|
|
4308
|
+
verdict: "red",
|
|
4309
|
+
reason: unknownAction ? `judge returned unrecognised action_type "${result.actionType}"` : "judge returned no verdict",
|
|
4310
|
+
confidence: result.confidence,
|
|
4311
|
+
score: native.defaultScoreForVerdict("red"),
|
|
4312
|
+
toolCallId: result.toolCallId
|
|
4313
|
+
};
|
|
4314
|
+
}
|
|
4215
4315
|
const verdict = native.mapVerdict(
|
|
4216
4316
|
result.actionType,
|
|
4217
4317
|
result.confidence,
|
|
@@ -42362,6 +42462,10 @@ var index = /* @__PURE__ */ getDefaultExportFromCjs(builtExports);
|
|
|
42362
42462
|
|
|
42363
42463
|
// src-ts/memory/chain.ts
|
|
42364
42464
|
var { createClient, encryption: encryption2, newSignatureProvider: newSignatureProvider2, Buffer: PolyBuffer } = index;
|
|
42465
|
+
var FAILOVER_CONFIG = {
|
|
42466
|
+
strategy: "tryNextOnError",
|
|
42467
|
+
attemptsPerEndpoint: 1
|
|
42468
|
+
};
|
|
42365
42469
|
function toGtxBytes(bytes) {
|
|
42366
42470
|
return PolyBuffer.from(new Uint8Array(bytes));
|
|
42367
42471
|
}
|
|
@@ -42391,7 +42495,11 @@ function materializeChain(chainOpts) {
|
|
|
42391
42495
|
}
|
|
42392
42496
|
async function buildChainClient(chainOpts) {
|
|
42393
42497
|
const { nodeUrls, blockchainRid } = materializeChain(chainOpts);
|
|
42394
|
-
return createClient({
|
|
42498
|
+
return createClient({
|
|
42499
|
+
nodeUrlPool: [...nodeUrls],
|
|
42500
|
+
blockchainRid,
|
|
42501
|
+
failOverConfig: FAILOVER_CONFIG
|
|
42502
|
+
});
|
|
42395
42503
|
}
|
|
42396
42504
|
function buildSigner(auth) {
|
|
42397
42505
|
const privKeyBuf = Buffer.from(auth.privkey, "hex");
|
|
@@ -42829,7 +42937,10 @@ var MemoryGuardManager = class {
|
|
|
42829
42937
|
await this.pointerStore.set(this.agentPubkeyHex, result.pointer);
|
|
42830
42938
|
} catch (err) {
|
|
42831
42939
|
const msg = err instanceof Error ? err.message : String(err);
|
|
42832
|
-
this.logger.warn(
|
|
42940
|
+
this.logger.warn(bootSyncFailureLine(err), {
|
|
42941
|
+
error: msg,
|
|
42942
|
+
hint: BOOT_SYNC_HINT
|
|
42943
|
+
});
|
|
42833
42944
|
}
|
|
42834
42945
|
}
|
|
42835
42946
|
/**
|
|
@@ -43057,6 +43168,7 @@ function diffMemorySnapshots(before, after) {
|
|
|
43057
43168
|
export {
|
|
43058
43169
|
Atbash,
|
|
43059
43170
|
AtbashAPIError,
|
|
43171
|
+
BOOT_SYNC_HINT,
|
|
43060
43172
|
DEFAULT_BLOCKCHAIN_RID,
|
|
43061
43173
|
DEFAULT_CHROMIA_NODE_URLS,
|
|
43062
43174
|
DEFAULT_ENDPOINT,
|
|
@@ -43064,11 +43176,14 @@ export {
|
|
|
43064
43176
|
DEFAULT_MEMORY_READ_TOOL_NAMES,
|
|
43065
43177
|
DEFAULT_MEMORY_WRITE_TOOL_NAMES,
|
|
43066
43178
|
EciesDomain,
|
|
43179
|
+
KEY_FILENAMES,
|
|
43067
43180
|
MemoryGuardManager,
|
|
43068
43181
|
MemoryIntegrityError,
|
|
43069
43182
|
PointerStore,
|
|
43070
43183
|
SignatureVerificationError,
|
|
43184
|
+
bootSyncFailureLine,
|
|
43071
43185
|
buildAllowedJudgeHosts,
|
|
43186
|
+
chooseKeyPath,
|
|
43072
43187
|
claimHashHex,
|
|
43073
43188
|
classifyMemoryRead,
|
|
43074
43189
|
classifyMemoryWrite,
|
|
@@ -43103,6 +43218,7 @@ export {
|
|
|
43103
43218
|
isEnvelope,
|
|
43104
43219
|
isValidPrivateKey,
|
|
43105
43220
|
keyFingerprintOf,
|
|
43221
|
+
keyPathCandidates,
|
|
43106
43222
|
loadAgent,
|
|
43107
43223
|
loadAgentFromFile,
|
|
43108
43224
|
loadUserConfig,
|