@cortexkit/anthropic-auth-core 2.3.0 → 2.4.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/accounts.d.ts +2 -0
- package/dist/cachekeep.d.ts +6 -0
- package/dist/holder-registry.d.ts +159 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.js +1387 -546
- package/dist/internal-types/claustrum/enrollment.d.ts +9 -0
- package/dist/internal-types/setup/flags.d.ts +50 -0
- package/dist/internal-types/setup/index.d.ts +1 -0
- package/dist/internal-types/setup/types.d.ts +7 -1
- package/dist/native-account-runtime.d.ts +7 -0
- package/dist/native-vault-paths.d.ts +11 -2
- package/dist/pool-paths.d.ts +8 -1
- package/dist/relocation-guard.d.ts +48 -0
- package/dist/state-layout-paths.d.ts +193 -0
- package/dist/sticky-routing.d.ts +8 -0
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1036,8 +1036,15 @@ async function acquireRefreshFileLockWithClock(options) {
|
|
|
1036
1036
|
return "missing";
|
|
1037
1037
|
throw error;
|
|
1038
1038
|
}
|
|
1039
|
-
if (windowsPrivateFiles)
|
|
1040
|
-
|
|
1039
|
+
if (windowsPrivateFiles) {
|
|
1040
|
+
try {
|
|
1041
|
+
await verifyPrivate(evictPath, "directory", true);
|
|
1042
|
+
} catch (error) {
|
|
1043
|
+
if (error.code === "ENOENT")
|
|
1044
|
+
return "missing";
|
|
1045
|
+
throw error;
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1041
1048
|
if (evictStat.mtimeMs + EVICT_TTL > now())
|
|
1042
1049
|
return "fresh";
|
|
1043
1050
|
if (options.onStep)
|
|
@@ -1062,8 +1069,8 @@ async function acquireRefreshFileLockWithClock(options) {
|
|
|
1062
1069
|
} catch (error) {
|
|
1063
1070
|
if (error.code === "EEXIST") {
|
|
1064
1071
|
if (windowsPrivateFiles) {
|
|
1065
|
-
await verifyPrivate(evictPath, "directory", true);
|
|
1066
1072
|
try {
|
|
1073
|
+
await verifyPrivate(evictPath, "directory", true);
|
|
1067
1074
|
await readPrivateText(evictOwnerPath, true);
|
|
1068
1075
|
} catch (ownerError) {
|
|
1069
1076
|
if (ownerError.code !== "ENOENT")
|
|
@@ -1624,7 +1631,7 @@ async function refuseWritableAncestor(parent, options = {}) {
|
|
|
1624
1631
|
throw new ClaustrumConsumerError("unsafe-file", `Claustrum enrollment parent refused: ${error.path} (${error.reason ?? error.code}). Use a folder that other users cannot write or replace.`);
|
|
1625
1632
|
}
|
|
1626
1633
|
}
|
|
1627
|
-
async function
|
|
1634
|
+
async function ensureClaustrumPrivateDirectory(directory, options = {}, what = "enrollment directory") {
|
|
1628
1635
|
if (windowsPrivateFiles) {
|
|
1629
1636
|
await ensurePrivateDirectory(directory, false, ancestorPolicyOptions(options));
|
|
1630
1637
|
return;
|
|
@@ -1633,14 +1640,14 @@ async function ensurePrivateDirectory2(directory, options = {}) {
|
|
|
1633
1640
|
const metadata = await stat2(directory);
|
|
1634
1641
|
const uid = process.geteuid?.();
|
|
1635
1642
|
if (uid !== undefined && metadata.uid !== uid) {
|
|
1636
|
-
throw new ClaustrumConsumerError("unsafe-file",
|
|
1643
|
+
throw new ClaustrumConsumerError("unsafe-file", `Claustrum ${what} must be owned by the current user`);
|
|
1637
1644
|
}
|
|
1638
1645
|
if ((metadata.mode & 63) !== 0)
|
|
1639
1646
|
await chmod(directory, 448);
|
|
1640
1647
|
}
|
|
1641
1648
|
async function writeStateAtomic(path, state, ancestorOptions = {}) {
|
|
1642
1649
|
const parent = dirname4(path);
|
|
1643
|
-
await
|
|
1650
|
+
await ensureClaustrumPrivateDirectory(parent, ancestorOptions);
|
|
1644
1651
|
await refuseWritableAncestor(parent, ancestorOptions);
|
|
1645
1652
|
const bytes = `${JSON.stringify(state)}
|
|
1646
1653
|
`;
|
|
@@ -1808,7 +1815,7 @@ class ClaustrumEnrollmentManager {
|
|
|
1808
1815
|
return statusFromState(blocked);
|
|
1809
1816
|
}
|
|
1810
1817
|
async reconcile() {
|
|
1811
|
-
await
|
|
1818
|
+
await ensureClaustrumPrivateDirectory(dirname4(this.#paths.statePath), this.#ancestorOptions);
|
|
1812
1819
|
const lock = await acquireRefreshFileLock({
|
|
1813
1820
|
name: "ceremony",
|
|
1814
1821
|
path: this.#paths.statePath,
|
|
@@ -1931,7 +1938,7 @@ class ClaustrumEnrollmentManager {
|
|
|
1931
1938
|
await writeStateAtomic(this.#paths.statePath, denied, this.#ancestorOptions);
|
|
1932
1939
|
return statusFromState(denied);
|
|
1933
1940
|
}
|
|
1934
|
-
await
|
|
1941
|
+
await ensureClaustrumPrivateDirectory(dirname4(this.#paths.tokenPath), this.#ancestorOptions);
|
|
1935
1942
|
await refuseWritableAncestor(dirname4(this.#paths.tokenPath), this.#ancestorOptions);
|
|
1936
1943
|
await this.#writeTokenFile(this.#paths.tokenPath, {
|
|
1937
1944
|
token: outcome.token,
|
|
@@ -1967,7 +1974,7 @@ class ClaustrumEnrollmentManager {
|
|
|
1967
1974
|
}
|
|
1968
1975
|
}
|
|
1969
1976
|
async function resetClaustrumEnrollmentState(paths, proposedName) {
|
|
1970
|
-
await
|
|
1977
|
+
await ensureClaustrumPrivateDirectory(dirname4(paths.statePath));
|
|
1971
1978
|
const lock = await acquireRefreshFileLock({
|
|
1972
1979
|
name: "ceremony",
|
|
1973
1980
|
path: paths.statePath,
|
|
@@ -2005,7 +2012,7 @@ async function removeIfPresent(path) {
|
|
|
2005
2012
|
}
|
|
2006
2013
|
}
|
|
2007
2014
|
async function disconnectClaustrumEnrollment(paths, proposedName) {
|
|
2008
|
-
await
|
|
2015
|
+
await ensureClaustrumPrivateDirectory(dirname4(paths.statePath));
|
|
2009
2016
|
const lock = await acquireRefreshFileLock({
|
|
2010
2017
|
name: "ceremony",
|
|
2011
2018
|
path: paths.statePath,
|
|
@@ -2916,6 +2923,117 @@ async function connectSetupHost(plugin, host, io, terminal, fence) {
|
|
|
2916
2923
|
}
|
|
2917
2924
|
}
|
|
2918
2925
|
|
|
2926
|
+
// ../../node_modules/@cortexkit/common-auth/dist/setup/flags.js
|
|
2927
|
+
var UNAVAILABLE_HOST_MESSAGE = "Requested setup host is unknown or unavailable. Use --host=opencode or --host=pi with a detected host.";
|
|
2928
|
+
var SETUP_FLAGS = [
|
|
2929
|
+
{
|
|
2930
|
+
name: "--yes",
|
|
2931
|
+
key: "yes",
|
|
2932
|
+
description: "Run without questions and set up every found host. Does not choose the vault."
|
|
2933
|
+
},
|
|
2934
|
+
{
|
|
2935
|
+
name: "--dry-run",
|
|
2936
|
+
key: "dryRun",
|
|
2937
|
+
description: "Print what setup would do without changing anything."
|
|
2938
|
+
},
|
|
2939
|
+
{
|
|
2940
|
+
name: "--host",
|
|
2941
|
+
key: "hosts",
|
|
2942
|
+
values: ["opencode", "pi"],
|
|
2943
|
+
spaceForm: true,
|
|
2944
|
+
invalid: UNAVAILABLE_HOST_MESSAGE,
|
|
2945
|
+
description: "Set up only this host; repeat the flag for both. Also written --host=<host>."
|
|
2946
|
+
},
|
|
2947
|
+
{
|
|
2948
|
+
name: "--opencode",
|
|
2949
|
+
key: "opencode",
|
|
2950
|
+
values: ["1", "2", "both"],
|
|
2951
|
+
description: "Register for this OpenCode generation."
|
|
2952
|
+
},
|
|
2953
|
+
{
|
|
2954
|
+
name: "--claustrum",
|
|
2955
|
+
key: "claustrum",
|
|
2956
|
+
description: "Connect the hosts to the Claustrum vault."
|
|
2957
|
+
},
|
|
2958
|
+
{
|
|
2959
|
+
name: "--no-claustrum",
|
|
2960
|
+
key: "noClaustrum",
|
|
2961
|
+
description: "Do not offer the Claustrum vault; sign in locally."
|
|
2962
|
+
},
|
|
2963
|
+
{
|
|
2964
|
+
name: "--login",
|
|
2965
|
+
key: "login",
|
|
2966
|
+
description: "Sign in locally instead of using the Claustrum vault."
|
|
2967
|
+
},
|
|
2968
|
+
{
|
|
2969
|
+
name: "--enroll-only",
|
|
2970
|
+
key: "enrollOnly",
|
|
2971
|
+
description: "Only connect the hosts to the Claustrum vault; register nothing and migrate nothing."
|
|
2972
|
+
}
|
|
2973
|
+
];
|
|
2974
|
+
function unknownArgument(arg) {
|
|
2975
|
+
return new Error(`Unknown setup argument: ${arg}. Run the plugin's own setup --help to list the flags setup accepts.`);
|
|
2976
|
+
}
|
|
2977
|
+
function parseSetupFlags(argv) {
|
|
2978
|
+
const result = {
|
|
2979
|
+
yes: false,
|
|
2980
|
+
dryRun: false,
|
|
2981
|
+
claustrum: false,
|
|
2982
|
+
noClaustrum: false,
|
|
2983
|
+
login: false,
|
|
2984
|
+
enrollOnly: false,
|
|
2985
|
+
hosts: [],
|
|
2986
|
+
opencode: undefined
|
|
2987
|
+
};
|
|
2988
|
+
for (let index = 0;index < argv.length; index++) {
|
|
2989
|
+
const arg = argv[index];
|
|
2990
|
+
const equals = arg.indexOf("=");
|
|
2991
|
+
const name = equals === -1 ? arg : arg.slice(0, equals);
|
|
2992
|
+
const flag = SETUP_FLAGS.find((entry) => entry.name === name);
|
|
2993
|
+
if (!flag)
|
|
2994
|
+
throw unknownArgument(arg);
|
|
2995
|
+
if (!("values" in flag)) {
|
|
2996
|
+
if (equals !== -1)
|
|
2997
|
+
throw unknownArgument(arg);
|
|
2998
|
+
result[flag.key] = true;
|
|
2999
|
+
continue;
|
|
3000
|
+
}
|
|
3001
|
+
let value;
|
|
3002
|
+
if (equals !== -1)
|
|
3003
|
+
value = arg.slice(equals + 1);
|
|
3004
|
+
else if (flag.spaceForm)
|
|
3005
|
+
value = argv[++index];
|
|
3006
|
+
else
|
|
3007
|
+
throw unknownArgument(arg);
|
|
3008
|
+
if (value === undefined || !flag.values.includes(value))
|
|
3009
|
+
throw flag.invalid ? new Error(flag.invalid) : unknownArgument(arg);
|
|
3010
|
+
if (flag.key === "hosts")
|
|
3011
|
+
result.hosts.push(value);
|
|
3012
|
+
else
|
|
3013
|
+
result.opencode = value;
|
|
3014
|
+
}
|
|
3015
|
+
if (result.claustrum && result.noClaustrum)
|
|
3016
|
+
throw new Error("--claustrum and --no-claustrum cannot be used together.");
|
|
3017
|
+
if (result.login && result.claustrum)
|
|
3018
|
+
throw new Error("--login and --claustrum cannot be used together.");
|
|
3019
|
+
if (result.enrollOnly && result.login)
|
|
3020
|
+
throw new Error("--enroll-only and --login cannot be used together.");
|
|
3021
|
+
if (result.enrollOnly && result.noClaustrum)
|
|
3022
|
+
throw new Error("--enroll-only and --no-claustrum cannot be used together.");
|
|
3023
|
+
return result;
|
|
3024
|
+
}
|
|
3025
|
+
function setupUsage(options = {}) {
|
|
3026
|
+
const labels = SETUP_FLAGS.map((flag) => ("values" in flag) ? `${flag.name}${flag.spaceForm ? " " : "="}${flag.values.join("|")}` : flag.name);
|
|
3027
|
+
const width = Math.max(...labels.map((label) => label.length));
|
|
3028
|
+
const lines = SETUP_FLAGS.map((flag, index) => ` ${labels[index].padEnd(width)} ${flag.description}`);
|
|
3029
|
+
return [
|
|
3030
|
+
...options.command ? [`Usage: ${options.command} [flags]`, ""] : [],
|
|
3031
|
+
"Flags:",
|
|
3032
|
+
...lines
|
|
3033
|
+
].join(`
|
|
3034
|
+
`);
|
|
3035
|
+
}
|
|
3036
|
+
|
|
2919
3037
|
// ../../node_modules/@cortexkit/common-auth/dist/setup/prompts.js
|
|
2920
3038
|
async function selectSetupHosts(terminal, found) {
|
|
2921
3039
|
const selected = new Set(found);
|
|
@@ -3177,51 +3295,6 @@ async function registerPi(plugin, executable, io = {}) {
|
|
|
3177
3295
|
|
|
3178
3296
|
// ../../node_modules/@cortexkit/common-auth/dist/setup/command.js
|
|
3179
3297
|
var AMBIGUOUS_OPENCODE_MESSAGE = "Multiple OpenCode generations found. Choose --opencode=1|2|both before running noninteractive setup.";
|
|
3180
|
-
var UNAVAILABLE_HOST_MESSAGE = "Requested setup host is unknown or unavailable. Use --host=opencode or --host=pi with a detected host.";
|
|
3181
|
-
function flags(argv) {
|
|
3182
|
-
const result = {
|
|
3183
|
-
yes: false,
|
|
3184
|
-
dryRun: false,
|
|
3185
|
-
claustrum: false,
|
|
3186
|
-
noClaustrum: false,
|
|
3187
|
-
login: false,
|
|
3188
|
-
enrollOnly: false,
|
|
3189
|
-
hosts: [],
|
|
3190
|
-
opencode: undefined
|
|
3191
|
-
};
|
|
3192
|
-
for (const arg of argv) {
|
|
3193
|
-
if (arg === "--yes")
|
|
3194
|
-
result.yes = true;
|
|
3195
|
-
else if (arg === "--dry-run")
|
|
3196
|
-
result.dryRun = true;
|
|
3197
|
-
else if (arg === "--claustrum")
|
|
3198
|
-
result.claustrum = true;
|
|
3199
|
-
else if (arg === "--no-claustrum")
|
|
3200
|
-
result.noClaustrum = true;
|
|
3201
|
-
else if (arg === "--login")
|
|
3202
|
-
result.login = true;
|
|
3203
|
-
else if (arg === "--enroll-only")
|
|
3204
|
-
result.enrollOnly = true;
|
|
3205
|
-
else if (arg.startsWith("--host=")) {
|
|
3206
|
-
const host = arg.slice("--host=".length);
|
|
3207
|
-
if (host !== "opencode" && host !== "pi")
|
|
3208
|
-
throw new Error(UNAVAILABLE_HOST_MESSAGE);
|
|
3209
|
-
result.hosts.push(host);
|
|
3210
|
-
} else if (/^--opencode=(1|2|both)$/.test(arg))
|
|
3211
|
-
result.opencode = arg.slice("--opencode=".length);
|
|
3212
|
-
else
|
|
3213
|
-
throw new Error(`Unknown setup argument: ${arg}`);
|
|
3214
|
-
}
|
|
3215
|
-
if (result.claustrum && result.noClaustrum)
|
|
3216
|
-
throw new Error("--claustrum and --no-claustrum cannot be used together.");
|
|
3217
|
-
if (result.login && result.claustrum)
|
|
3218
|
-
throw new Error("--login and --claustrum cannot be used together.");
|
|
3219
|
-
if (result.enrollOnly && result.login)
|
|
3220
|
-
throw new Error("--enroll-only and --login cannot be used together.");
|
|
3221
|
-
if (result.enrollOnly && result.noClaustrum)
|
|
3222
|
-
throw new Error("--enroll-only and --no-claustrum cannot be used together.");
|
|
3223
|
-
return result;
|
|
3224
|
-
}
|
|
3225
3298
|
function validatePlugin(plugin) {
|
|
3226
3299
|
for (const pkg of Object.values(plugin.packages)) {
|
|
3227
3300
|
if (!/^(?:@[a-z0-9._-]+\/)?[a-z0-9._-]+$/.test(pkg))
|
|
@@ -3251,7 +3324,7 @@ async function enrollmentReport(plugin, hosts, recorded) {
|
|
|
3251
3324
|
return report;
|
|
3252
3325
|
}
|
|
3253
3326
|
async function runSetup(plugin, argv = [], io = {}) {
|
|
3254
|
-
const options =
|
|
3327
|
+
const options = parseSetupFlags(argv);
|
|
3255
3328
|
validatePlugin(plugin);
|
|
3256
3329
|
const terminal = io.terminal ?? processTerminal();
|
|
3257
3330
|
const detection = await detectHosts(plugin, io);
|
|
@@ -3362,7 +3435,7 @@ async function runSetup(plugin, argv = [], io = {}) {
|
|
|
3362
3435
|
${write.content}`);
|
|
3363
3436
|
if (!options.enrollOnly && hosts.includes("pi"))
|
|
3364
3437
|
printLine(terminal, `Would run ${detection.pi.executable} install npm:${plugin.packages.pi}@${plugin.version}`);
|
|
3365
|
-
if (!options.enrollOnly)
|
|
3438
|
+
if (!options.enrollOnly && plugin.migrate)
|
|
3366
3439
|
for (const host of hosts)
|
|
3367
3440
|
printLine(terminal, `Would migrate ${host} using the plugin callback (provider-specific writes).`);
|
|
3368
3441
|
} else {
|
|
@@ -3400,7 +3473,7 @@ ${write.content}`);
|
|
|
3400
3473
|
else
|
|
3401
3474
|
await registerPi(plugin, detection.pi.executable, io);
|
|
3402
3475
|
await stopped();
|
|
3403
|
-
await plugin.migrate(host, context);
|
|
3476
|
+
await plugin.migrate?.(host, context);
|
|
3404
3477
|
}
|
|
3405
3478
|
} catch (error) {
|
|
3406
3479
|
if (enrollment.size === 0)
|
|
@@ -4283,14 +4356,14 @@ var DEFAULT_MINIMUM_REMAINING = {
|
|
|
4283
4356
|
};
|
|
4284
4357
|
var DEFAULT_FAIL_CLOSED_ON_UNKNOWN_QUOTA = true;
|
|
4285
4358
|
var FALLBACK_BACKGROUND_TICK_MS = 60000;
|
|
4286
|
-
function
|
|
4287
|
-
if (
|
|
4288
|
-
return
|
|
4359
|
+
function getOpenCodeConfigDir(env = process.env, home = homedir2()) {
|
|
4360
|
+
if (env.OPENCODE_CONFIG_DIR?.trim()) {
|
|
4361
|
+
return env.OPENCODE_CONFIG_DIR.trim();
|
|
4289
4362
|
}
|
|
4290
|
-
return join7(
|
|
4363
|
+
return join7(env.XDG_CONFIG_HOME || join7(home, ".config"), "opencode");
|
|
4291
4364
|
}
|
|
4292
4365
|
function getAccountStoragePath() {
|
|
4293
|
-
return process.env.OPENCODE_ANTHROPIC_AUTH_FILE?.trim() || join7(
|
|
4366
|
+
return process.env.OPENCODE_ANTHROPIC_AUTH_FILE?.trim() || join7(getOpenCodeConfigDir(), ACCOUNT_FILE_NAME);
|
|
4294
4367
|
}
|
|
4295
4368
|
function getAccountStatePath(configPath = getAccountStoragePath()) {
|
|
4296
4369
|
const explicit = process.env.OPENCODE_ANTHROPIC_AUTH_STATE_FILE?.trim();
|
|
@@ -8394,6 +8467,13 @@ class CacheKeepManager {
|
|
|
8394
8467
|
trackedCount() {
|
|
8395
8468
|
return this.targets.size;
|
|
8396
8469
|
}
|
|
8470
|
+
dropExpiredTargets(now = this.options.now?.() ?? Date.now()) {
|
|
8471
|
+
this.pruneTargets(now);
|
|
8472
|
+
let earliest;
|
|
8473
|
+
for (const target of this.targets.values())
|
|
8474
|
+
earliest = Math.min(earliest ?? target.cacheExpiresAt, target.cacheExpiresAt);
|
|
8475
|
+
return earliest;
|
|
8476
|
+
}
|
|
8397
8477
|
publishTrackedSessions() {
|
|
8398
8478
|
const callback = this.options.onTrackedSessionsChanged;
|
|
8399
8479
|
if (!callback)
|
|
@@ -8715,18 +8795,766 @@ class CacheKeepManager {
|
|
|
8715
8795
|
}
|
|
8716
8796
|
}
|
|
8717
8797
|
// src/cachekeep-registry.ts
|
|
8718
|
-
import { randomUUID as
|
|
8798
|
+
import { randomUUID as randomUUID9 } from "node:crypto";
|
|
8719
8799
|
import {
|
|
8720
8800
|
link,
|
|
8721
|
-
mkdir as
|
|
8801
|
+
mkdir as mkdir8,
|
|
8722
8802
|
readdir as readdir2,
|
|
8723
|
-
readFile as
|
|
8803
|
+
readFile as readFile8,
|
|
8724
8804
|
rename as rename8,
|
|
8725
8805
|
rm as rm5,
|
|
8726
8806
|
writeFile as writeFile3
|
|
8727
8807
|
} from "node:fs/promises";
|
|
8728
8808
|
import { tmpdir as tmpdir6 } from "node:os";
|
|
8729
|
-
import { join as
|
|
8809
|
+
import { join as join13 } from "node:path";
|
|
8810
|
+
|
|
8811
|
+
// src/holder-registry.ts
|
|
8812
|
+
import { execFile } from "node:child_process";
|
|
8813
|
+
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
8814
|
+
import { readFileSync as readFileSync2 } from "node:fs";
|
|
8815
|
+
import { lstat as lstat5, mkdir as mkdir7, readFile as readFile7 } from "node:fs/promises";
|
|
8816
|
+
import { basename as basename5, dirname as dirname9, join as join12 } from "node:path";
|
|
8817
|
+
|
|
8818
|
+
// src/native-lock-observer.ts
|
|
8819
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
8820
|
+
var detachedLocks = new AsyncLocalStorage;
|
|
8821
|
+
function withDetachedNativeLocks(work) {
|
|
8822
|
+
return detachedLocks.run(true, work);
|
|
8823
|
+
}
|
|
8824
|
+
function nativeLockObserver(observer) {
|
|
8825
|
+
if (!observer)
|
|
8826
|
+
return;
|
|
8827
|
+
return (event) => {
|
|
8828
|
+
try {
|
|
8829
|
+
const result = observer(detachedLocks.getStore() ? { ...event, detached: true } : event);
|
|
8830
|
+
if (result !== null && (typeof result === "object" || typeof result === "function") && "then" in result && typeof result.then === "function") {
|
|
8831
|
+
Promise.resolve(result).catch(() => {});
|
|
8832
|
+
}
|
|
8833
|
+
} catch {}
|
|
8834
|
+
};
|
|
8835
|
+
}
|
|
8836
|
+
async function withNativeLock(path2, options, run, acquire = withLock) {
|
|
8837
|
+
const observer = nativeLockObserver(options.onLockEvent);
|
|
8838
|
+
if (!observer)
|
|
8839
|
+
return acquire(path2, options, run);
|
|
8840
|
+
observer({ type: "acquiring", name: options.name, path: path2 });
|
|
8841
|
+
let acquired = false;
|
|
8842
|
+
try {
|
|
8843
|
+
return await acquire(path2, options, async (lease) => {
|
|
8844
|
+
acquired = true;
|
|
8845
|
+
observer({ type: "acquired", name: options.name, path: path2 });
|
|
8846
|
+
return run(lease);
|
|
8847
|
+
});
|
|
8848
|
+
} finally {
|
|
8849
|
+
if (acquired)
|
|
8850
|
+
observer({ type: "released", name: options.name, path: path2 });
|
|
8851
|
+
}
|
|
8852
|
+
}
|
|
8853
|
+
function observeNativeLocks(acquire, observer) {
|
|
8854
|
+
return (path2, options, run) => withNativeLock(path2, { ...options, onLockEvent: options.onLockEvent ?? observer }, run, acquire());
|
|
8855
|
+
}
|
|
8856
|
+
|
|
8857
|
+
// src/native-vault-paths.ts
|
|
8858
|
+
import { createHash as createHash6 } from "node:crypto";
|
|
8859
|
+
import { basename as basename4, dirname as dirname8, join as join11 } from "node:path";
|
|
8860
|
+
|
|
8861
|
+
// src/state-layout-paths.ts
|
|
8862
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
8863
|
+
import { realpathSync as realpathSync2 } from "node:fs";
|
|
8864
|
+
import { open as open5 } from "node:fs/promises";
|
|
8865
|
+
import { homedir as homedir3 } from "node:os";
|
|
8866
|
+
import * as nodePath from "node:path";
|
|
8867
|
+
var LEGACY_STATE_LAYOUT = Object.freeze({
|
|
8868
|
+
kind: "legacy"
|
|
8869
|
+
});
|
|
8870
|
+
function processStateLayout() {
|
|
8871
|
+
return LEGACY_STATE_LAYOUT;
|
|
8872
|
+
}
|
|
8873
|
+
function anthropicAuthStateRoot(inputs, pathApi = nodePath) {
|
|
8874
|
+
const { xdgStateHome, home, acceptRelative = false } = inputs;
|
|
8875
|
+
const base = xdgStateHome && (acceptRelative || pathApi.isAbsolute(xdgStateHome)) ? xdgStateHome : pathApi.join(home, ".local", "state");
|
|
8876
|
+
return pathApi.join(base, "cortexkit", "anthropic-auth");
|
|
8877
|
+
}
|
|
8878
|
+
function errorCode2(error) {
|
|
8879
|
+
return error instanceof Error && "code" in error ? error.code : undefined;
|
|
8880
|
+
}
|
|
8881
|
+
function configFolderIdentity(configDir = getOpenCodeConfigDir()) {
|
|
8882
|
+
try {
|
|
8883
|
+
return realpathSync2.native(configDir);
|
|
8884
|
+
} catch (error) {
|
|
8885
|
+
const code = errorCode2(error);
|
|
8886
|
+
if (code === "ENOENT" || code === "ENOTDIR")
|
|
8887
|
+
return;
|
|
8888
|
+
throw error;
|
|
8889
|
+
}
|
|
8890
|
+
}
|
|
8891
|
+
function homeDefaultConfigDir(home = homedir3(), pathApi = nodePath) {
|
|
8892
|
+
return pathApi.join(home, ".config", "opencode");
|
|
8893
|
+
}
|
|
8894
|
+
function stateSubfolderName(identity2, homeDefaultIdentity) {
|
|
8895
|
+
if (identity2 === homeDefaultIdentity)
|
|
8896
|
+
return "opencode";
|
|
8897
|
+
const hash = createHash5("sha256").update(identity2).digest("hex");
|
|
8898
|
+
return `opencode-${hash.slice(0, 16)}`;
|
|
8899
|
+
}
|
|
8900
|
+
function resolveStateHomeTarget(options = {}) {
|
|
8901
|
+
const env = options.env ?? process.env;
|
|
8902
|
+
const home = options.home ?? homedir3();
|
|
8903
|
+
const identity2 = configFolderIdentity(getOpenCodeConfigDir(env, home));
|
|
8904
|
+
if (identity2 === undefined)
|
|
8905
|
+
return;
|
|
8906
|
+
const stateRoot = anthropicAuthStateRoot({
|
|
8907
|
+
xdgStateHome: env.XDG_STATE_HOME,
|
|
8908
|
+
home
|
|
8909
|
+
});
|
|
8910
|
+
const name = stateSubfolderName(identity2, configFolderIdentity(homeDefaultConfigDir(home)));
|
|
8911
|
+
return { identity: identity2, stateRoot, dir: nodePath.join(stateRoot, name) };
|
|
8912
|
+
}
|
|
8913
|
+
var STATE_HOME_FILE_NAMES = Object.freeze({
|
|
8914
|
+
localPoolState: "anthropic-auth-pool-state.json",
|
|
8915
|
+
localRuntime: "anthropic-auth-native-state.json",
|
|
8916
|
+
journal: "anthropic-auth-migration.json",
|
|
8917
|
+
localRoster: "anthropic-auth-custody-roster.json",
|
|
8918
|
+
vaultStoreState: "anthropic-auth-vault-store-state.json",
|
|
8919
|
+
vaultRuntime: "anthropic-auth-vault-state.json",
|
|
8920
|
+
vaultRoster: "anthropic-auth-vault-roster.json",
|
|
8921
|
+
vaultRouting: "anthropic-auth-vault-routing-state.json",
|
|
8922
|
+
requestGzip: "anthropic-auth-request-gzip.json",
|
|
8923
|
+
configDirMarker: "config-dir.json",
|
|
8924
|
+
layoutMarker: "layout.json"
|
|
8925
|
+
});
|
|
8926
|
+
function stateHomeFilePaths(dir, pathApi = nodePath) {
|
|
8927
|
+
const paths = {};
|
|
8928
|
+
for (const [role, name] of Object.entries(STATE_HOME_FILE_NAMES))
|
|
8929
|
+
paths[role] = pathApi.join(dir, name);
|
|
8930
|
+
return Object.freeze(paths);
|
|
8931
|
+
}
|
|
8932
|
+
var DEFAULT_ACCOUNT_FILE = "anthropic-auth.json";
|
|
8933
|
+
var DEFAULT_ACCOUNT_STATE_FILE = "anthropic-auth-state.json";
|
|
8934
|
+
function stateHomeDatasetFiles(layout, legacyConfig, legacyState) {
|
|
8935
|
+
if (!nodePath.isAbsolute(layout.dir))
|
|
8936
|
+
throw new Error("The state-home folder must be an absolute path");
|
|
8937
|
+
if (nodePath.basename(legacyConfig) !== DEFAULT_ACCOUNT_FILE || nodePath.basename(legacyState) !== DEFAULT_ACCOUNT_STATE_FILE || nodePath.dirname(legacyConfig) !== nodePath.dirname(legacyState))
|
|
8938
|
+
throw new Error("The state-home layout applies only to the default account files of a config folder");
|
|
8939
|
+
return stateHomeFilePaths(layout.dir);
|
|
8940
|
+
}
|
|
8941
|
+
|
|
8942
|
+
class StateLayoutFileError extends Error {
|
|
8943
|
+
code;
|
|
8944
|
+
path;
|
|
8945
|
+
constructor(code, path2, cause) {
|
|
8946
|
+
super(code === "invalid" ? `anthropic-auth state layout file ${path2} is invalid` : `anthropic-auth state layout file ${path2} cannot be read`, cause === undefined ? undefined : { cause });
|
|
8947
|
+
this.name = "StateLayoutFileError";
|
|
8948
|
+
this.code = code;
|
|
8949
|
+
this.path = path2;
|
|
8950
|
+
}
|
|
8951
|
+
}
|
|
8952
|
+
var MARKER_MAX_BYTES = 1024 * 1024;
|
|
8953
|
+
var POINTER_MAX_BYTES = 64 * 1024;
|
|
8954
|
+
async function readSmallFile(path2, maxBytes) {
|
|
8955
|
+
let handle;
|
|
8956
|
+
try {
|
|
8957
|
+
handle = await open5(path2, "r");
|
|
8958
|
+
} catch (error) {
|
|
8959
|
+
const code = errorCode2(error);
|
|
8960
|
+
if (code === "ENOENT")
|
|
8961
|
+
return { status: "absent" };
|
|
8962
|
+
if (code === "EISDIR")
|
|
8963
|
+
return { status: "not-small-file" };
|
|
8964
|
+
throw error;
|
|
8965
|
+
}
|
|
8966
|
+
try {
|
|
8967
|
+
const info = await handle.stat();
|
|
8968
|
+
if (!info.isFile() || info.size > maxBytes)
|
|
8969
|
+
return { status: "not-small-file" };
|
|
8970
|
+
const bytes = await handle.readFile();
|
|
8971
|
+
if (bytes.length > maxBytes)
|
|
8972
|
+
return { status: "not-small-file" };
|
|
8973
|
+
return { status: "read", text: bytes.toString("utf8") };
|
|
8974
|
+
} finally {
|
|
8975
|
+
await handle.close();
|
|
8976
|
+
}
|
|
8977
|
+
}
|
|
8978
|
+
function isRecord4(value) {
|
|
8979
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8980
|
+
}
|
|
8981
|
+
function nonEmptyString2(value) {
|
|
8982
|
+
return typeof value === "string" && value.length > 0;
|
|
8983
|
+
}
|
|
8984
|
+
async function readMarker(path2, parse3) {
|
|
8985
|
+
let file;
|
|
8986
|
+
try {
|
|
8987
|
+
file = await readSmallFile(path2, MARKER_MAX_BYTES);
|
|
8988
|
+
} catch (error) {
|
|
8989
|
+
throw new StateLayoutFileError("unreadable", path2, error);
|
|
8990
|
+
}
|
|
8991
|
+
if (file.status === "absent")
|
|
8992
|
+
return;
|
|
8993
|
+
if (file.status !== "read")
|
|
8994
|
+
throw new StateLayoutFileError("invalid", path2);
|
|
8995
|
+
let value;
|
|
8996
|
+
try {
|
|
8997
|
+
value = parseJsonRedacted(file.text);
|
|
8998
|
+
} catch {
|
|
8999
|
+
throw new StateLayoutFileError("invalid", path2);
|
|
9000
|
+
}
|
|
9001
|
+
const parsed = parse3(value);
|
|
9002
|
+
if (parsed === undefined)
|
|
9003
|
+
throw new StateLayoutFileError("invalid", path2);
|
|
9004
|
+
return parsed;
|
|
9005
|
+
}
|
|
9006
|
+
async function readConfigDirMarker(dir) {
|
|
9007
|
+
return readMarker(nodePath.join(dir, STATE_HOME_FILE_NAMES.configDirMarker), (value) => isRecord4(value) && value.version === 1 && nonEmptyString2(value.identity) ? Object.freeze({ version: 1, identity: value.identity }) : undefined);
|
|
9008
|
+
}
|
|
9009
|
+
var STATE_LAYOUT_PHASES = [
|
|
9010
|
+
"preparing",
|
|
9011
|
+
"committed",
|
|
9012
|
+
"rolled-back",
|
|
9013
|
+
"restoring",
|
|
9014
|
+
"restore-staged",
|
|
9015
|
+
"restored"
|
|
9016
|
+
];
|
|
9017
|
+
var CLEANUP_STATES = ["pending", "done", "kept"];
|
|
9018
|
+
var RESTORE_CLEANUP_STATES = ["pending", "done"];
|
|
9019
|
+
function oneOf(values, value) {
|
|
9020
|
+
return typeof value === "string" && values.includes(value);
|
|
9021
|
+
}
|
|
9022
|
+
function parseLayoutMarker(value) {
|
|
9023
|
+
if (!isRecord4(value) || value.version !== 1)
|
|
9024
|
+
return;
|
|
9025
|
+
const { phase, attempt, identity: identity2, stateRoot, sub, oldDir, storageIds } = value;
|
|
9026
|
+
if (!oneOf(STATE_LAYOUT_PHASES, phase) || !nonEmptyString2(attempt) || !nonEmptyString2(identity2) || !nonEmptyString2(stateRoot) || !nonEmptyString2(sub) || !nonEmptyString2(oldDir) || !isRecord4(storageIds) || !nonEmptyString2(storageIds.local) || !nonEmptyString2(storageIds.vault))
|
|
9027
|
+
return;
|
|
9028
|
+
const rawCleanup = value.cleanup;
|
|
9029
|
+
let cleanup;
|
|
9030
|
+
if (rawCleanup === undefined) {
|
|
9031
|
+
if (phase === "committed")
|
|
9032
|
+
return;
|
|
9033
|
+
} else if (oneOf(CLEANUP_STATES, rawCleanup))
|
|
9034
|
+
cleanup = rawCleanup;
|
|
9035
|
+
else
|
|
9036
|
+
return;
|
|
9037
|
+
let restore;
|
|
9038
|
+
if (value.restore !== undefined) {
|
|
9039
|
+
if (!isRecord4(value.restore))
|
|
9040
|
+
return;
|
|
9041
|
+
const restoreCleanup = value.restore.cleanup;
|
|
9042
|
+
if (restoreCleanup !== undefined && !oneOf(RESTORE_CLEANUP_STATES, restoreCleanup))
|
|
9043
|
+
return;
|
|
9044
|
+
restore = Object.freeze(restoreCleanup === undefined ? {} : { cleanup: restoreCleanup });
|
|
9045
|
+
} else if (phase === "restored")
|
|
9046
|
+
return;
|
|
9047
|
+
return Object.freeze({
|
|
9048
|
+
version: 1,
|
|
9049
|
+
phase,
|
|
9050
|
+
attempt,
|
|
9051
|
+
identity: identity2,
|
|
9052
|
+
stateRoot,
|
|
9053
|
+
sub,
|
|
9054
|
+
oldDir,
|
|
9055
|
+
storageIds: Object.freeze({
|
|
9056
|
+
local: storageIds.local,
|
|
9057
|
+
vault: storageIds.vault
|
|
9058
|
+
}),
|
|
9059
|
+
...cleanup === undefined ? {} : { cleanup },
|
|
9060
|
+
...restore === undefined ? {} : { restore }
|
|
9061
|
+
});
|
|
9062
|
+
}
|
|
9063
|
+
async function readStateLayoutMarker(dir) {
|
|
9064
|
+
return readMarker(nodePath.join(dir, STATE_HOME_FILE_NAMES.layoutMarker), parseLayoutMarker);
|
|
9065
|
+
}
|
|
9066
|
+
async function readRelocationPointer(runtimePath) {
|
|
9067
|
+
const file = await readSmallFile(runtimePath, POINTER_MAX_BYTES);
|
|
9068
|
+
if (file.status !== "read")
|
|
9069
|
+
return;
|
|
9070
|
+
let value;
|
|
9071
|
+
try {
|
|
9072
|
+
value = parseJsonRedacted(file.text);
|
|
9073
|
+
} catch {
|
|
9074
|
+
return;
|
|
9075
|
+
}
|
|
9076
|
+
if (!isRecord4(value) || value.version !== 0)
|
|
9077
|
+
return;
|
|
9078
|
+
const { relocatedTo, stateRoot, identity: identity2, attempt, by } = value;
|
|
9079
|
+
if (!nonEmptyString2(relocatedTo) || !nonEmptyString2(stateRoot) || !nonEmptyString2(identity2) || !nonEmptyString2(attempt) || !nonEmptyString2(by))
|
|
9080
|
+
return;
|
|
9081
|
+
return Object.freeze({ relocatedTo, stateRoot, identity: identity2, attempt, by });
|
|
9082
|
+
}
|
|
9083
|
+
|
|
9084
|
+
// src/native-vault-paths.ts
|
|
9085
|
+
function sibling(path2, expected, name, suffix) {
|
|
9086
|
+
return basename4(path2) === expected ? join11(dirname8(path2), name) : path2.replace(/(?:\.json)?$/, `.${suffix}.json`);
|
|
9087
|
+
}
|
|
9088
|
+
function nativeVaultPaths(local, layout = processStateLayout()) {
|
|
9089
|
+
const config = sibling(local.legacyConfig, "anthropic-auth.json", "anthropic-auth-vault-settings.json", "vault-settings");
|
|
9090
|
+
const legacyLayoutState = sibling(local.legacyState, "anthropic-auth-state.json", "anthropic-auth-vault-store-state.json", "vault-store");
|
|
9091
|
+
let state = legacyLayoutState;
|
|
9092
|
+
let runtime = sibling(local.legacyState, "anthropic-auth-state.json", "anthropic-auth-vault-state.json", "vault-native");
|
|
9093
|
+
let roster = sibling(local.legacyState, "anthropic-auth-state.json", "anthropic-auth-vault-roster.json", "vault-roster");
|
|
9094
|
+
let routing = sibling(local.legacyState, "anthropic-auth-state.json", "anthropic-auth-vault-routing-state.json", "vault-routing");
|
|
9095
|
+
if (layout.kind === "state-home") {
|
|
9096
|
+
const moved = stateHomeDatasetFiles(layout, local.legacyConfig, local.legacyState);
|
|
9097
|
+
state = moved.vaultStoreState;
|
|
9098
|
+
runtime = moved.vaultRuntime;
|
|
9099
|
+
roster = moved.vaultRoster;
|
|
9100
|
+
routing = moved.vaultRouting;
|
|
9101
|
+
}
|
|
9102
|
+
const destinations = [config, state, runtime, roster, routing];
|
|
9103
|
+
const localFiles = [
|
|
9104
|
+
local.legacyConfig,
|
|
9105
|
+
local.legacyState,
|
|
9106
|
+
local.config,
|
|
9107
|
+
local.state,
|
|
9108
|
+
local.runtime,
|
|
9109
|
+
local.journal,
|
|
9110
|
+
local.roster
|
|
9111
|
+
];
|
|
9112
|
+
if (new Set([...localFiles, ...destinations]).size !== localFiles.length + destinations.length)
|
|
9113
|
+
throw new Error("Vault storage overlaps local account storage");
|
|
9114
|
+
return {
|
|
9115
|
+
legacySeedConfig: local.legacyConfig,
|
|
9116
|
+
config,
|
|
9117
|
+
state,
|
|
9118
|
+
runtime,
|
|
9119
|
+
roster,
|
|
9120
|
+
routing,
|
|
9121
|
+
storageId: createHash6("sha256").update(JSON.stringify(["anthropic-vault", config, legacyLayoutState])).digest("hex")
|
|
9122
|
+
};
|
|
9123
|
+
}
|
|
9124
|
+
|
|
9125
|
+
// src/relocation-guard.ts
|
|
9126
|
+
import { lstat as lstat4 } from "node:fs/promises";
|
|
9127
|
+
var RELOCATED_MESSAGE = "Anthropic account state was moved to a new folder by a newer anthropic-auth version. Update anthropic-auth in every OpenCode and Pi that uses this folder, then restart them.";
|
|
9128
|
+
|
|
9129
|
+
class RelocatedError extends Error {
|
|
9130
|
+
code = "relocated";
|
|
9131
|
+
runtimePath;
|
|
9132
|
+
relocatedTo;
|
|
9133
|
+
constructor(runtimePath, pointer) {
|
|
9134
|
+
super(RELOCATED_MESSAGE);
|
|
9135
|
+
this.name = "RelocatedError";
|
|
9136
|
+
this.runtimePath = runtimePath;
|
|
9137
|
+
this.relocatedTo = pointer.relocatedTo;
|
|
9138
|
+
}
|
|
9139
|
+
}
|
|
9140
|
+
var TOMBSTONE_MAX_BYTES = 16 * 1024;
|
|
9141
|
+
var MAX_OBSERVED_PATHS = 256;
|
|
9142
|
+
var observations = new Map;
|
|
9143
|
+
var reported = new Set;
|
|
9144
|
+
async function pointerAt(path2) {
|
|
9145
|
+
let info;
|
|
9146
|
+
try {
|
|
9147
|
+
info = await lstat4(path2, { bigint: true });
|
|
9148
|
+
} catch {
|
|
9149
|
+
observations.delete(path2);
|
|
9150
|
+
return;
|
|
9151
|
+
}
|
|
9152
|
+
const identity2 = `${info.dev}:${info.ino}:${info.size}:${info.mtimeNs}:${info.ctimeNs}`;
|
|
9153
|
+
const last = observations.get(path2);
|
|
9154
|
+
if (last?.identity === identity2)
|
|
9155
|
+
return last.pointer;
|
|
9156
|
+
let pointer;
|
|
9157
|
+
if (info.isFile() && info.size <= BigInt(TOMBSTONE_MAX_BYTES)) {
|
|
9158
|
+
try {
|
|
9159
|
+
pointer = await readRelocationPointer(path2);
|
|
9160
|
+
} catch {
|
|
9161
|
+
pointer = undefined;
|
|
9162
|
+
}
|
|
9163
|
+
}
|
|
9164
|
+
observations.delete(path2);
|
|
9165
|
+
if (observations.size >= MAX_OBSERVED_PATHS) {
|
|
9166
|
+
const oldest = observations.keys().next().value;
|
|
9167
|
+
if (oldest !== undefined)
|
|
9168
|
+
observations.delete(oldest);
|
|
9169
|
+
}
|
|
9170
|
+
observations.set(path2, { identity: identity2, pointer });
|
|
9171
|
+
return pointer;
|
|
9172
|
+
}
|
|
9173
|
+
async function findRelocationTombstone(runtimePaths) {
|
|
9174
|
+
for (const path2 of runtimePaths) {
|
|
9175
|
+
const pointer = await pointerAt(path2);
|
|
9176
|
+
if (pointer)
|
|
9177
|
+
return { path: path2, pointer };
|
|
9178
|
+
}
|
|
9179
|
+
return;
|
|
9180
|
+
}
|
|
9181
|
+
function reportRelocation(path2, pointer) {
|
|
9182
|
+
if (reported.has(path2))
|
|
9183
|
+
return;
|
|
9184
|
+
reported.add(path2);
|
|
9185
|
+
logger.error("state-layout", "anthropic-auth state was moved by a newer version; this process refuses to use the old files", { runtimePath: path2, relocatedTo: pointer.relocatedTo, by: pointer.by });
|
|
9186
|
+
}
|
|
9187
|
+
function createRelocationGuard(runtimePaths) {
|
|
9188
|
+
const paths = [...runtimePaths];
|
|
9189
|
+
return {
|
|
9190
|
+
async assertNotRelocated() {
|
|
9191
|
+
const found = await findRelocationTombstone(paths);
|
|
9192
|
+
if (!found)
|
|
9193
|
+
return;
|
|
9194
|
+
reportRelocation(found.path, found.pointer);
|
|
9195
|
+
throw new RelocatedError(found.path, found.pointer);
|
|
9196
|
+
},
|
|
9197
|
+
async isRelocated() {
|
|
9198
|
+
const found = await findRelocationTombstone(paths);
|
|
9199
|
+
if (found)
|
|
9200
|
+
reportRelocation(found.path, found.pointer);
|
|
9201
|
+
return found !== undefined;
|
|
9202
|
+
}
|
|
9203
|
+
};
|
|
9204
|
+
}
|
|
9205
|
+
function nativeRelocationRuntimePaths(paths) {
|
|
9206
|
+
return [paths.runtime, nativeVaultPaths(paths, LEGACY_STATE_LAYOUT).runtime];
|
|
9207
|
+
}
|
|
9208
|
+
function nativeRelocationGuard(paths) {
|
|
9209
|
+
return createRelocationGuard(nativeRelocationRuntimePaths(paths));
|
|
9210
|
+
}
|
|
9211
|
+
|
|
9212
|
+
// src/holder-registry.ts
|
|
9213
|
+
var HOLDER_FILE_NAME = "anthropic-auth-holders.json";
|
|
9214
|
+
var HOLDER_LOCK_NAME = "holders";
|
|
9215
|
+
var HOLDER_LOCK_TIMEOUT_MS = 120000;
|
|
9216
|
+
var HOLDER_RETRY_INTERVAL_MS = 60000;
|
|
9217
|
+
var HOLDER_LOCK_TTL_MS = 1e4;
|
|
9218
|
+
var HOLDER_FILE_MAX_BYTES = 4 * 1024 * 1024;
|
|
9219
|
+
var RELEASE_PACKAGES = new Set([
|
|
9220
|
+
"@cortexkit/anthropic-auth-core",
|
|
9221
|
+
"@cortexkit/opencode-anthropic-auth",
|
|
9222
|
+
"@cortexkit/pi-anthropic-auth"
|
|
9223
|
+
]);
|
|
9224
|
+
var release;
|
|
9225
|
+
function anthropicAuthRelease() {
|
|
9226
|
+
if (release !== undefined)
|
|
9227
|
+
return release;
|
|
9228
|
+
release = "unknown";
|
|
9229
|
+
try {
|
|
9230
|
+
const manifest = JSON.parse(readFileSync2(new URL("../package.json", import.meta.url), "utf8"));
|
|
9231
|
+
if (typeof manifest.name === "string" && RELEASE_PACKAGES.has(manifest.name) && typeof manifest.version === "string" && manifest.version.trim())
|
|
9232
|
+
release = manifest.version.trim();
|
|
9233
|
+
} catch {}
|
|
9234
|
+
return release;
|
|
9235
|
+
}
|
|
9236
|
+
function writerStamp() {
|
|
9237
|
+
return { protocol: 1, release: anthropicAuthRelease() };
|
|
9238
|
+
}
|
|
9239
|
+
function nativeHolderDatasetFiles(paths) {
|
|
9240
|
+
const vault = nativeVaultPaths(paths, LEGACY_STATE_LAYOUT);
|
|
9241
|
+
return [
|
|
9242
|
+
...new Set([
|
|
9243
|
+
paths.state,
|
|
9244
|
+
paths.runtime,
|
|
9245
|
+
paths.journal,
|
|
9246
|
+
paths.roster,
|
|
9247
|
+
vault.state,
|
|
9248
|
+
vault.runtime,
|
|
9249
|
+
vault.roster,
|
|
9250
|
+
vault.routing
|
|
9251
|
+
])
|
|
9252
|
+
].sort();
|
|
9253
|
+
}
|
|
9254
|
+
function isDestinationShapedDirectory(dir) {
|
|
9255
|
+
const name = basename5(dir);
|
|
9256
|
+
const parent = dirname9(dir);
|
|
9257
|
+
return (name === "opencode" || /^opencode-[0-9a-f]{16}$/.test(name)) && basename5(parent) === "anthropic-auth" && basename5(dirname9(parent)) === "cortexkit";
|
|
9258
|
+
}
|
|
9259
|
+
function openCodeHolderKind(env = process.env) {
|
|
9260
|
+
return env.OPENCODE_ANTHROPIC_AUTH_FILE?.trim() || env.OPENCODE_ANTHROPIC_AUTH_STATE_FILE?.trim() ? "explicit" : "legacy";
|
|
9261
|
+
}
|
|
9262
|
+
var HOLDER_REGISTRATION_MESSAGES = {
|
|
9263
|
+
"lock-timeout": "Another anthropic-auth process is moving or restoring state for this folder; start again in a minute.",
|
|
9264
|
+
"managed-folder": "An anthropic-auth path override points into anthropic-auth's managed state folder. Remove the override.",
|
|
9265
|
+
malformed: "anthropic-auth could not record its use of its state folder: the holder file there is invalid.",
|
|
9266
|
+
unavailable: "anthropic-auth could not record its use of its state folder, so it refuses to use that folder."
|
|
9267
|
+
};
|
|
9268
|
+
|
|
9269
|
+
class HolderRegistrationError extends Error {
|
|
9270
|
+
code;
|
|
9271
|
+
directory;
|
|
9272
|
+
constructor(code, directory, cause) {
|
|
9273
|
+
super(HOLDER_REGISTRATION_MESSAGES[code], cause === undefined ? undefined : { cause });
|
|
9274
|
+
this.name = "HolderRegistrationError";
|
|
9275
|
+
this.code = code;
|
|
9276
|
+
this.directory = directory;
|
|
9277
|
+
}
|
|
9278
|
+
}
|
|
9279
|
+
var HOLDER_REGISTRATION_ERROR_MESSAGES = Object.values(HOLDER_REGISTRATION_MESSAGES);
|
|
9280
|
+
function stateRefusalCause(error) {
|
|
9281
|
+
let current = error;
|
|
9282
|
+
for (let depth = 0;depth < 4 && current instanceof Error; depth++) {
|
|
9283
|
+
if (current instanceof RelocatedError || current instanceof HolderRegistrationError)
|
|
9284
|
+
return current;
|
|
9285
|
+
current = current.cause;
|
|
9286
|
+
}
|
|
9287
|
+
return;
|
|
9288
|
+
}
|
|
9289
|
+
function pidAlive(pid) {
|
|
9290
|
+
try {
|
|
9291
|
+
process.kill(pid, 0);
|
|
9292
|
+
return true;
|
|
9293
|
+
} catch (error) {
|
|
9294
|
+
return error.code === "EPERM";
|
|
9295
|
+
}
|
|
9296
|
+
}
|
|
9297
|
+
var bootId;
|
|
9298
|
+
async function linuxIncarnation(pid) {
|
|
9299
|
+
bootId ??= readFile7("/proc/sys/kernel/random/boot_id", "utf8").then((text) => text.trim() || null, () => null);
|
|
9300
|
+
const boot = await bootId;
|
|
9301
|
+
if (!boot)
|
|
9302
|
+
return null;
|
|
9303
|
+
try {
|
|
9304
|
+
const stat6 = await readFile7(`/proc/${pid}/stat`, "utf8");
|
|
9305
|
+
const fields = stat6.slice(stat6.lastIndexOf(")") + 2).split(" ");
|
|
9306
|
+
const start = fields[19];
|
|
9307
|
+
return start && /^\d+$/.test(start) ? `${boot}:${start}` : null;
|
|
9308
|
+
} catch {
|
|
9309
|
+
return null;
|
|
9310
|
+
}
|
|
9311
|
+
}
|
|
9312
|
+
function macosIncarnation(pid) {
|
|
9313
|
+
return new Promise((resolve5) => {
|
|
9314
|
+
execFile("ps", ["-o", "lstart=", "-p", String(pid)], { env: { ...process.env, TZ: "UTC0" }, timeout: 5000 }, (error, stdout) => {
|
|
9315
|
+
const text = String(stdout ?? "").trim();
|
|
9316
|
+
resolve5(error || !text ? null : text);
|
|
9317
|
+
});
|
|
9318
|
+
});
|
|
9319
|
+
}
|
|
9320
|
+
function processIncarnation(pid) {
|
|
9321
|
+
if (process.platform === "linux")
|
|
9322
|
+
return linuxIncarnation(pid);
|
|
9323
|
+
if (process.platform === "darwin")
|
|
9324
|
+
return macosIncarnation(pid);
|
|
9325
|
+
return Promise.resolve(null);
|
|
9326
|
+
}
|
|
9327
|
+
var defaultLiveness = {
|
|
9328
|
+
pidAlive,
|
|
9329
|
+
incarnation: processIncarnation
|
|
9330
|
+
};
|
|
9331
|
+
async function holderEntryIsLive(entry, liveness = defaultLiveness) {
|
|
9332
|
+
if (!liveness.pidAlive(entry.pid))
|
|
9333
|
+
return false;
|
|
9334
|
+
if (entry.incarnation === null)
|
|
9335
|
+
return true;
|
|
9336
|
+
let current;
|
|
9337
|
+
try {
|
|
9338
|
+
current = await liveness.incarnation(entry.pid);
|
|
9339
|
+
} catch {
|
|
9340
|
+
current = null;
|
|
9341
|
+
}
|
|
9342
|
+
return current === null || current === entry.incarnation;
|
|
9343
|
+
}
|
|
9344
|
+
function isRecord5(value) {
|
|
9345
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
9346
|
+
}
|
|
9347
|
+
function entryLiveness(value) {
|
|
9348
|
+
if (!isRecord5(value))
|
|
9349
|
+
return;
|
|
9350
|
+
const { pid, incarnation } = value;
|
|
9351
|
+
if (typeof pid !== "number" || !Number.isSafeInteger(pid) || pid <= 0)
|
|
9352
|
+
return;
|
|
9353
|
+
if (incarnation !== null && typeof incarnation !== "string")
|
|
9354
|
+
return;
|
|
9355
|
+
return { pid, incarnation };
|
|
9356
|
+
}
|
|
9357
|
+
function sameRegistration(value, entry) {
|
|
9358
|
+
if (!isRecord5(value))
|
|
9359
|
+
return false;
|
|
9360
|
+
const files = value.files;
|
|
9361
|
+
return value.pid === entry.pid && value.incarnation === entry.incarnation && value.role === entry.role && value.kind === entry.kind && Array.isArray(files) && files.length === entry.files.length && files.every((file, index) => file === entry.files[index]);
|
|
9362
|
+
}
|
|
9363
|
+
async function readHolderFile(path2) {
|
|
9364
|
+
let text;
|
|
9365
|
+
try {
|
|
9366
|
+
const info = await lstat5(path2);
|
|
9367
|
+
if (!info.isFile() || info.size > HOLDER_FILE_MAX_BYTES)
|
|
9368
|
+
throw new HolderRegistrationError("malformed", dirname9(path2));
|
|
9369
|
+
text = await readFile7(path2, "utf8");
|
|
9370
|
+
} catch (error) {
|
|
9371
|
+
if (error.code === "ENOENT")
|
|
9372
|
+
return;
|
|
9373
|
+
throw error;
|
|
9374
|
+
}
|
|
9375
|
+
let value;
|
|
9376
|
+
try {
|
|
9377
|
+
value = parseJsonRedacted(text);
|
|
9378
|
+
} catch (cause) {
|
|
9379
|
+
throw new HolderRegistrationError("malformed", dirname9(path2), cause);
|
|
9380
|
+
}
|
|
9381
|
+
if (!isRecord5(value) || value.version !== 1 || !Array.isArray(value.entries))
|
|
9382
|
+
throw new HolderRegistrationError("malformed", dirname9(path2));
|
|
9383
|
+
return { entries: value.entries };
|
|
9384
|
+
}
|
|
9385
|
+
async function exists(path2) {
|
|
9386
|
+
try {
|
|
9387
|
+
await lstat5(path2);
|
|
9388
|
+
return true;
|
|
9389
|
+
} catch {
|
|
9390
|
+
return false;
|
|
9391
|
+
}
|
|
9392
|
+
}
|
|
9393
|
+
async function anyExists(paths) {
|
|
9394
|
+
for (const path2 of paths)
|
|
9395
|
+
if (await exists(path2))
|
|
9396
|
+
return true;
|
|
9397
|
+
return false;
|
|
9398
|
+
}
|
|
9399
|
+
async function isManagedDirectory(dir) {
|
|
9400
|
+
return await exists(join12(dir, STATE_HOME_FILE_NAMES.configDirMarker)) || await exists(join12(dir, STATE_HOME_FILE_NAMES.layoutMarker));
|
|
9401
|
+
}
|
|
9402
|
+
var instance = randomUUID8();
|
|
9403
|
+
var ownIncarnation;
|
|
9404
|
+
var published = new Set;
|
|
9405
|
+
var warned = new Set;
|
|
9406
|
+
function registrationKey(holderFile, entry) {
|
|
9407
|
+
return JSON.stringify([holderFile, entry.kind, entry.role, entry.files]);
|
|
9408
|
+
}
|
|
9409
|
+
async function assertNoTombstone(paths) {
|
|
9410
|
+
const found = await findRelocationTombstone(nativeRelocationRuntimePaths(paths));
|
|
9411
|
+
if (found) {
|
|
9412
|
+
logger.error("state-layout", "anthropic-auth state was moved by a newer version; this process refuses to use the old files", {
|
|
9413
|
+
runtimePath: found.path,
|
|
9414
|
+
relocatedTo: found.pointer.relocatedTo,
|
|
9415
|
+
by: found.pointer.by
|
|
9416
|
+
});
|
|
9417
|
+
throw new RelocatedError(found.path, found.pointer);
|
|
9418
|
+
}
|
|
9419
|
+
}
|
|
9420
|
+
async function publishEntry(holderFile, entry, options, mandatory) {
|
|
9421
|
+
const dir = dirname9(holderFile);
|
|
9422
|
+
if (mandatory)
|
|
9423
|
+
await mkdir7(dir, { recursive: true, mode: 448 });
|
|
9424
|
+
await withNativeLock(holderFile, {
|
|
9425
|
+
name: HOLDER_LOCK_NAME,
|
|
9426
|
+
ttlMs: HOLDER_LOCK_TTL_MS,
|
|
9427
|
+
timeoutMs: options.lockTimeoutMs ?? HOLDER_LOCK_TIMEOUT_MS,
|
|
9428
|
+
renew: true,
|
|
9429
|
+
onLockEvent: options.onLockEvent
|
|
9430
|
+
}, async (lease) => {
|
|
9431
|
+
await assertNoTombstone(options.paths);
|
|
9432
|
+
if (entry.kind !== "legacy" && await isManagedDirectory(dir))
|
|
9433
|
+
throw new HolderRegistrationError("managed-folder", dir);
|
|
9434
|
+
const current = await readHolderFile(holderFile);
|
|
9435
|
+
const liveness = options.liveness ?? defaultLiveness;
|
|
9436
|
+
const kept = [];
|
|
9437
|
+
for (const value of current?.entries ?? []) {
|
|
9438
|
+
const life = entryLiveness(value);
|
|
9439
|
+
if (!life || await holderEntryIsLive(life, liveness))
|
|
9440
|
+
kept.push(value);
|
|
9441
|
+
}
|
|
9442
|
+
if (kept.some((value) => sameRegistration(value, entry)))
|
|
9443
|
+
return;
|
|
9444
|
+
kept.push(entry);
|
|
9445
|
+
await writeJsonAtomic(holderFile, { version: 1, entries: kept }, { beforeRename: () => lease.assertOwned() });
|
|
9446
|
+
});
|
|
9447
|
+
published.add(registrationKey(holderFile, entry));
|
|
9448
|
+
}
|
|
9449
|
+
async function buildEntry(options) {
|
|
9450
|
+
ownIncarnation ??= (options.liveness ?? defaultLiveness).incarnation(process.pid).catch(() => null);
|
|
9451
|
+
let identity2 = null;
|
|
9452
|
+
if (options.kind === "legacy") {
|
|
9453
|
+
try {
|
|
9454
|
+
identity2 = configFolderIdentity(dirname9(options.paths.legacyConfig)) ?? null;
|
|
9455
|
+
} catch {
|
|
9456
|
+
identity2 = null;
|
|
9457
|
+
}
|
|
9458
|
+
}
|
|
9459
|
+
return Object.freeze({
|
|
9460
|
+
pid: process.pid,
|
|
9461
|
+
incarnation: await ownIncarnation,
|
|
9462
|
+
instance,
|
|
9463
|
+
role: options.role,
|
|
9464
|
+
release: anthropicAuthRelease(),
|
|
9465
|
+
kind: options.kind,
|
|
9466
|
+
identity: identity2,
|
|
9467
|
+
files: Object.freeze(nativeHolderDatasetFiles(options.paths)),
|
|
9468
|
+
registeredAt: (options.now ?? Date.now)()
|
|
9469
|
+
});
|
|
9470
|
+
}
|
|
9471
|
+
async function registerNativePoolHolder(options) {
|
|
9472
|
+
const entry = await buildEntry(options);
|
|
9473
|
+
const dirs = [...new Set(entry.files.map((file) => dirname9(file)))].sort();
|
|
9474
|
+
const holderFiles = dirs.map((dir) => join12(dir, HOLDER_FILE_NAME));
|
|
9475
|
+
const done = {
|
|
9476
|
+
status: "registered",
|
|
9477
|
+
settled: Promise.resolve(),
|
|
9478
|
+
close() {}
|
|
9479
|
+
};
|
|
9480
|
+
if (holderFiles.every((file) => published.has(registrationKey(file, entry))))
|
|
9481
|
+
return done;
|
|
9482
|
+
await assertNoTombstone(options.paths);
|
|
9483
|
+
if (entry.kind !== "legacy") {
|
|
9484
|
+
for (const dir of dirs)
|
|
9485
|
+
if (await isManagedDirectory(dir))
|
|
9486
|
+
throw new HolderRegistrationError("managed-folder", dir);
|
|
9487
|
+
}
|
|
9488
|
+
const mandatory = entry.kind !== "legacy" && dirs.some(isDestinationShapedDirectory);
|
|
9489
|
+
const attempt = async () => {
|
|
9490
|
+
let complete = true;
|
|
9491
|
+
for (const holderFile of holderFiles) {
|
|
9492
|
+
if (published.has(registrationKey(holderFile, entry)))
|
|
9493
|
+
continue;
|
|
9494
|
+
const dir = dirname9(holderFile);
|
|
9495
|
+
try {
|
|
9496
|
+
if (!mandatory && !await anyExists(entry.files.filter((file) => dirname9(file) === dir))) {
|
|
9497
|
+
complete = false;
|
|
9498
|
+
continue;
|
|
9499
|
+
}
|
|
9500
|
+
await publishEntry(holderFile, entry, options, mandatory);
|
|
9501
|
+
} catch (error) {
|
|
9502
|
+
if (error instanceof RelocatedError || error instanceof HolderRegistrationError && error.code === "managed-folder")
|
|
9503
|
+
throw error;
|
|
9504
|
+
if (mandatory)
|
|
9505
|
+
throw error instanceof HolderRegistrationError ? error : new HolderRegistrationError(error instanceof LockContentionError ? "lock-timeout" : "unavailable", dir, error);
|
|
9506
|
+
complete = false;
|
|
9507
|
+
if (!warned.has(dir)) {
|
|
9508
|
+
warned.add(dir);
|
|
9509
|
+
logger.warn("state-layout", `anthropic-auth could not record that it is using ${dir}; if a newer version moves these files while this process runs, this process will stop and ask for a restart`, {
|
|
9510
|
+
code: error instanceof HolderRegistrationError ? error.code : error instanceof LockContentionError ? "lock-timeout" : error?.code ?? "unknown"
|
|
9511
|
+
});
|
|
9512
|
+
}
|
|
9513
|
+
}
|
|
9514
|
+
}
|
|
9515
|
+
return complete;
|
|
9516
|
+
};
|
|
9517
|
+
if (await attempt())
|
|
9518
|
+
return done;
|
|
9519
|
+
let timer;
|
|
9520
|
+
let closed = false;
|
|
9521
|
+
let settle = () => {};
|
|
9522
|
+
const settled = new Promise((resolve5) => {
|
|
9523
|
+
settle = resolve5;
|
|
9524
|
+
});
|
|
9525
|
+
const schedule = () => {
|
|
9526
|
+
if (closed)
|
|
9527
|
+
return;
|
|
9528
|
+
timer = setTimeout(() => {
|
|
9529
|
+
timer = undefined;
|
|
9530
|
+
withDetachedNativeLocks(attempt).then((complete) => {
|
|
9531
|
+
if (complete)
|
|
9532
|
+
settle();
|
|
9533
|
+
else
|
|
9534
|
+
schedule();
|
|
9535
|
+
}, () => {});
|
|
9536
|
+
}, options.retryIntervalMs ?? HOLDER_RETRY_INTERVAL_MS);
|
|
9537
|
+
timer.unref?.();
|
|
9538
|
+
};
|
|
9539
|
+
schedule();
|
|
9540
|
+
return {
|
|
9541
|
+
status: "pending",
|
|
9542
|
+
settled,
|
|
9543
|
+
close() {
|
|
9544
|
+
closed = true;
|
|
9545
|
+
if (timer)
|
|
9546
|
+
clearTimeout(timer);
|
|
9547
|
+
timer = undefined;
|
|
9548
|
+
}
|
|
9549
|
+
};
|
|
9550
|
+
}
|
|
9551
|
+
function resetNativeHolderRegistryForTests() {
|
|
9552
|
+
published.clear();
|
|
9553
|
+
warned.clear();
|
|
9554
|
+
ownIncarnation = undefined;
|
|
9555
|
+
}
|
|
9556
|
+
|
|
9557
|
+
// src/cachekeep-registry.ts
|
|
8730
9558
|
var CACHE_KEEP_REGISTRY_LEASE_MS = 3 * 60000;
|
|
8731
9559
|
function normalizeSession(value) {
|
|
8732
9560
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
@@ -8761,7 +9589,7 @@ function isExpiredRecord(record, now, leaseMs) {
|
|
|
8761
9589
|
return record.updatedAt <= now && now - record.updatedAt > leaseMs;
|
|
8762
9590
|
}
|
|
8763
9591
|
function getDefaultCacheKeepRegistryDirectory(scope) {
|
|
8764
|
-
return
|
|
9592
|
+
return join13(tmpdir6(), "opencode-anthropic-auth", "cachekeep-sessions", scope);
|
|
8765
9593
|
}
|
|
8766
9594
|
|
|
8767
9595
|
class CacheKeepSessionRegistry {
|
|
@@ -8771,8 +9599,8 @@ class CacheKeepSessionRegistry {
|
|
|
8771
9599
|
lastSweepAt;
|
|
8772
9600
|
constructor(options) {
|
|
8773
9601
|
this.options = options;
|
|
8774
|
-
const instanceId = options.instanceId ?? `${process.pid}-${
|
|
8775
|
-
this.filePath =
|
|
9602
|
+
const instanceId = options.instanceId ?? `${process.pid}-${randomUUID9()}`;
|
|
9603
|
+
this.filePath = join13(options.directory, `${instanceId}.json`);
|
|
8776
9604
|
}
|
|
8777
9605
|
publish(sessions) {
|
|
8778
9606
|
const snapshot = sessions.map((session) => ({ ...session }));
|
|
@@ -8782,12 +9610,13 @@ class CacheKeepSessionRegistry {
|
|
|
8782
9610
|
if (snapshot.length === 0) {
|
|
8783
9611
|
await rm5(this.filePath, { force: true });
|
|
8784
9612
|
} else {
|
|
8785
|
-
await
|
|
8786
|
-
const tempPath = `${this.filePath}.${
|
|
9613
|
+
await mkdir8(this.options.directory, { recursive: true, mode: 448 });
|
|
9614
|
+
const tempPath = `${this.filePath}.${randomUUID9()}.tmp`;
|
|
8787
9615
|
const record = {
|
|
8788
9616
|
version: 1,
|
|
8789
9617
|
updatedAt: now,
|
|
8790
|
-
sessions: snapshot
|
|
9618
|
+
sessions: snapshot,
|
|
9619
|
+
writer: writerStamp()
|
|
8791
9620
|
};
|
|
8792
9621
|
await writeFile3(tempPath, `${JSON.stringify(record)}
|
|
8793
9622
|
`, {
|
|
@@ -8812,7 +9641,7 @@ class CacheKeepSessionRegistry {
|
|
|
8812
9641
|
}
|
|
8813
9642
|
const records = await Promise.all(names.map(async (name) => {
|
|
8814
9643
|
try {
|
|
8815
|
-
const raw = await
|
|
9644
|
+
const raw = await readFile8(join13(this.options.directory, name), "utf8");
|
|
8816
9645
|
return normalizeRecord(JSON.parse(raw));
|
|
8817
9646
|
} catch {
|
|
8818
9647
|
return;
|
|
@@ -8854,19 +9683,19 @@ class CacheKeepSessionRegistry {
|
|
|
8854
9683
|
return;
|
|
8855
9684
|
}
|
|
8856
9685
|
await Promise.all(names.map(async (name) => {
|
|
8857
|
-
const recordPath =
|
|
9686
|
+
const recordPath = join13(this.options.directory, name);
|
|
8858
9687
|
if (recordPath === this.filePath)
|
|
8859
9688
|
return;
|
|
8860
9689
|
let initialRecord;
|
|
8861
9690
|
try {
|
|
8862
|
-
initialRecord = normalizeRecord(JSON.parse(await
|
|
9691
|
+
initialRecord = normalizeRecord(JSON.parse(await readFile8(recordPath, "utf8")));
|
|
8863
9692
|
} catch {
|
|
8864
9693
|
return;
|
|
8865
9694
|
}
|
|
8866
9695
|
if (!initialRecord || !isExpiredRecord(initialRecord, now, leaseMs)) {
|
|
8867
9696
|
return;
|
|
8868
9697
|
}
|
|
8869
|
-
const sweptPath = `${recordPath}.${
|
|
9698
|
+
const sweptPath = `${recordPath}.${randomUUID9()}.sweep`;
|
|
8870
9699
|
try {
|
|
8871
9700
|
await rename8(recordPath, sweptPath);
|
|
8872
9701
|
} catch {
|
|
@@ -8875,7 +9704,7 @@ class CacheKeepSessionRegistry {
|
|
|
8875
9704
|
let raw;
|
|
8876
9705
|
let record;
|
|
8877
9706
|
try {
|
|
8878
|
-
raw = await
|
|
9707
|
+
raw = await readFile8(sweptPath, "utf8");
|
|
8879
9708
|
record = normalizeRecord(JSON.parse(raw));
|
|
8880
9709
|
} catch {}
|
|
8881
9710
|
if (record && isExpiredRecord(record, now, leaseMs)) {
|
|
@@ -8918,24 +9747,24 @@ class CacheKeepSessionRegistry {
|
|
|
8918
9747
|
}
|
|
8919
9748
|
}
|
|
8920
9749
|
// src/claustrum-enrollment.ts
|
|
8921
|
-
import { createHash as
|
|
9750
|
+
import { createHash as createHash7, randomBytes as randomBytes4, randomUUID as randomUUID10 } from "node:crypto";
|
|
8922
9751
|
import { constants as fsConstants2 } from "node:fs";
|
|
8923
9752
|
import {
|
|
8924
9753
|
chmod as chmod2,
|
|
8925
|
-
mkdir as
|
|
8926
|
-
open as
|
|
9754
|
+
mkdir as mkdir9,
|
|
9755
|
+
open as open6,
|
|
8927
9756
|
realpath as realpath2,
|
|
8928
9757
|
rename as rename9,
|
|
8929
9758
|
stat as stat6,
|
|
8930
9759
|
unlink as unlink5
|
|
8931
9760
|
} from "node:fs/promises";
|
|
8932
|
-
import { homedir as
|
|
9761
|
+
import { homedir as homedir4 } from "node:os";
|
|
8933
9762
|
import {
|
|
8934
|
-
basename as
|
|
8935
|
-
dirname as
|
|
9763
|
+
basename as basename6,
|
|
9764
|
+
dirname as dirname11,
|
|
8936
9765
|
extname as extname2,
|
|
8937
|
-
isAbsolute as
|
|
8938
|
-
join as
|
|
9766
|
+
isAbsolute as isAbsolute3,
|
|
9767
|
+
join as join14,
|
|
8939
9768
|
resolve as resolve5
|
|
8940
9769
|
} from "node:path";
|
|
8941
9770
|
import {
|
|
@@ -8945,8 +9774,8 @@ import {
|
|
|
8945
9774
|
} from "@cortexkit/claustrum-client";
|
|
8946
9775
|
|
|
8947
9776
|
// src/owner-only.ts
|
|
8948
|
-
import { lstat as
|
|
8949
|
-
import { dirname as
|
|
9777
|
+
import { lstat as lstat6 } from "node:fs/promises";
|
|
9778
|
+
import { dirname as dirname10 } from "node:path";
|
|
8950
9779
|
import { types as utilTypes3 } from "node:util";
|
|
8951
9780
|
async function windowsBackend(options) {
|
|
8952
9781
|
if ((options.platform ?? process.platform) !== "win32")
|
|
@@ -9010,9 +9839,9 @@ async function ensureWindowsOwnerOnlyDirectory(path2, options = {}) {
|
|
|
9010
9839
|
const descriptor = Object.getOwnPropertyDescriptor(error, key);
|
|
9011
9840
|
return descriptor && "value" in descriptor ? descriptor.value : undefined;
|
|
9012
9841
|
};
|
|
9013
|
-
async function
|
|
9842
|
+
async function exists2(directory) {
|
|
9014
9843
|
try {
|
|
9015
|
-
const metadata = await
|
|
9844
|
+
const metadata = await lstat6(directory);
|
|
9016
9845
|
if (metadata.isSymbolicLink())
|
|
9017
9846
|
throw refused("verify", "reparse-point");
|
|
9018
9847
|
if (!metadata.isDirectory())
|
|
@@ -9046,21 +9875,21 @@ async function ensureWindowsOwnerOnlyDirectory(path2, options = {}) {
|
|
|
9046
9875
|
if (field(error, "code") !== "EEXIST" && !(field(error, "reason") === "io-error" && typeof win32Code === "number" && [80, 183].includes(win32Code)))
|
|
9047
9876
|
throw error;
|
|
9048
9877
|
}
|
|
9049
|
-
if (!await
|
|
9878
|
+
if (!await exists2(directory))
|
|
9050
9879
|
throw refused("verify", "io-error");
|
|
9051
9880
|
await privateDirectory(directory);
|
|
9052
9881
|
}
|
|
9053
9882
|
async function ancestors(directory) {
|
|
9054
|
-
if (await
|
|
9883
|
+
if (await exists2(directory))
|
|
9055
9884
|
return safe(directory);
|
|
9056
|
-
const parent =
|
|
9885
|
+
const parent = dirname10(directory);
|
|
9057
9886
|
if (parent === directory)
|
|
9058
9887
|
throw refused("safe-parent", "io-error");
|
|
9059
9888
|
await ancestors(parent);
|
|
9060
9889
|
await create(directory);
|
|
9061
9890
|
}
|
|
9062
|
-
await ancestors(
|
|
9063
|
-
if (await
|
|
9891
|
+
await ancestors(dirname10(path2));
|
|
9892
|
+
if (await exists2(path2))
|
|
9064
9893
|
await privateDirectory(path2);
|
|
9065
9894
|
else
|
|
9066
9895
|
await create(path2);
|
|
@@ -9087,18 +9916,22 @@ function connectClaustrumEnrollmentClient2(options = {}) {
|
|
|
9087
9916
|
}
|
|
9088
9917
|
function getClaustrumEnrollmentPaths2(tokenPath) {
|
|
9089
9918
|
const extension = extname2(tokenPath) || ".json";
|
|
9090
|
-
const stem =
|
|
9919
|
+
const stem = basename6(tokenPath, extname2(tokenPath));
|
|
9091
9920
|
return {
|
|
9092
|
-
statePath:
|
|
9921
|
+
statePath: join14(dirname11(tokenPath), `${stem}-state${extension}`),
|
|
9093
9922
|
tokenPath
|
|
9094
9923
|
};
|
|
9095
9924
|
}
|
|
9096
9925
|
function getHostClaustrumEnrollmentPaths(host, env = process.env, cwd = process.cwd()) {
|
|
9097
9926
|
const configured = env[`${host.toUpperCase()}_ANTHROPIC_AUTH_CLAUSTRUM_ENROLLMENT_FILE`]?.trim();
|
|
9098
|
-
const tokenPath = configured ?
|
|
9927
|
+
const tokenPath = configured ? isAbsolute3(configured) ? configured : resolve5(cwd, configured) : join14(anthropicAuthStateRoot({
|
|
9928
|
+
xdgStateHome: env.XDG_STATE_HOME,
|
|
9929
|
+
home: homedir4(),
|
|
9930
|
+
acceptRelative: true
|
|
9931
|
+
}), `${host}-enrollment.json`);
|
|
9099
9932
|
return getClaustrumEnrollmentPaths2(tokenPath);
|
|
9100
9933
|
}
|
|
9101
|
-
function
|
|
9934
|
+
function isRecord6(value) {
|
|
9102
9935
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
9103
9936
|
}
|
|
9104
9937
|
function validTimestamp2(value) {
|
|
@@ -9108,7 +9941,7 @@ function validGeneration2(value) {
|
|
|
9108
9941
|
return typeof value === "number" && Number.isSafeInteger(value) && value >= 1;
|
|
9109
9942
|
}
|
|
9110
9943
|
function decodeEnrollmentState2(value) {
|
|
9111
|
-
if (!
|
|
9944
|
+
if (!isRecord6(value) || value.version !== ENROLLMENT_SCHEMA2 || typeof value.proposedName !== "string" || value.proposedName.length === 0) {
|
|
9112
9945
|
throw new Error("invalid Claustrum enrollment state");
|
|
9113
9946
|
}
|
|
9114
9947
|
if (value.phase === "pending") {
|
|
@@ -9159,7 +9992,7 @@ function decodeEnrollmentState2(value) {
|
|
|
9159
9992
|
throw new Error("invalid Claustrum enrollment state");
|
|
9160
9993
|
}
|
|
9161
9994
|
function decodeTokenFile2(value) {
|
|
9162
|
-
if (!
|
|
9995
|
+
if (!isRecord6(value) || !TOKEN_RE2.test(String(value.token ?? "")) || !validGeneration2(value.token_generation)) {
|
|
9163
9996
|
throw new Error("invalid Claustrum enrollment token file");
|
|
9164
9997
|
}
|
|
9165
9998
|
return {
|
|
@@ -9188,7 +10021,7 @@ async function readBoundedJson2(path2, ownership = {}) {
|
|
|
9188
10021
|
throw new Error("Claustrum enrollment file is too large");
|
|
9189
10022
|
return parseJsonRedacted(bytes.toString("utf8"));
|
|
9190
10023
|
}
|
|
9191
|
-
descriptor = await
|
|
10024
|
+
descriptor = await open6(path2, fsConstants2.O_RDONLY | fsConstants2.O_NOFOLLOW);
|
|
9192
10025
|
} catch (error) {
|
|
9193
10026
|
if (error.code === "ENOENT")
|
|
9194
10027
|
return;
|
|
@@ -9225,26 +10058,26 @@ async function refuseWritableAncestor2(parent, ownership = {}, metadataAt = (pat
|
|
|
9225
10058
|
if (metadata && (metadata.mode & 18) !== 0 && (metadata.mode & 512) === 0) {
|
|
9226
10059
|
throw new Error("Claustrum enrollment path has an unsafe writable ancestor");
|
|
9227
10060
|
}
|
|
9228
|
-
const next =
|
|
10061
|
+
const next = dirname11(component);
|
|
9229
10062
|
if (next === component)
|
|
9230
10063
|
return;
|
|
9231
10064
|
component = next;
|
|
9232
10065
|
}
|
|
9233
10066
|
}
|
|
9234
10067
|
async function writeStateAtomic2(path2, state, beforeRename) {
|
|
9235
|
-
const parent =
|
|
9236
|
-
await
|
|
10068
|
+
const parent = dirname11(path2);
|
|
10069
|
+
await mkdir9(parent, { recursive: true, mode: 448 });
|
|
9237
10070
|
await refuseWritableAncestor2(parent);
|
|
9238
10071
|
const bytes = `${JSON.stringify(state)}
|
|
9239
10072
|
`;
|
|
9240
10073
|
if (Buffer.byteLength(bytes) > ENROLLMENT_FILE_MAX_BYTES2) {
|
|
9241
10074
|
throw new Error("Claustrum enrollment state is too large");
|
|
9242
10075
|
}
|
|
9243
|
-
const temporary =
|
|
10076
|
+
const temporary = join14(parent, `.${basename6(path2)}.${process.pid}.${randomUUID10()}.tmp`);
|
|
9244
10077
|
let descriptor;
|
|
9245
10078
|
try {
|
|
9246
10079
|
const nativeCreated = await createWindowsOwnerOnly(temporary, bytes);
|
|
9247
|
-
descriptor = await
|
|
10080
|
+
descriptor = await open6(temporary, nativeCreated ? fsConstants2.O_RDWR : "wx", 384);
|
|
9248
10081
|
if (!nativeCreated)
|
|
9249
10082
|
await descriptor.writeFile(bytes, "utf8");
|
|
9250
10083
|
await descriptor.sync();
|
|
@@ -9259,7 +10092,7 @@ async function writeStateAtomic2(path2, state, beforeRename) {
|
|
|
9259
10092
|
}
|
|
9260
10093
|
}
|
|
9261
10094
|
async function writeTokenAtomic(path2, value, writeTokenFile, beforeRename) {
|
|
9262
|
-
const staged =
|
|
10095
|
+
const staged = join14(dirname11(path2), `.${basename6(path2)}.${process.pid}.${randomUUID10()}.tmp`);
|
|
9263
10096
|
try {
|
|
9264
10097
|
await writeTokenFile(staged, value);
|
|
9265
10098
|
await beforeRename();
|
|
@@ -9363,7 +10196,7 @@ class ClaustrumEnrollmentManager2 {
|
|
|
9363
10196
|
return resetClaustrumEnrollmentState2(this.#paths, this.#proposedName);
|
|
9364
10197
|
}
|
|
9365
10198
|
async reconcile() {
|
|
9366
|
-
await
|
|
10199
|
+
await mkdir9(dirname11(this.#paths.statePath), {
|
|
9367
10200
|
recursive: true,
|
|
9368
10201
|
mode: 448
|
|
9369
10202
|
});
|
|
@@ -9433,7 +10266,7 @@ class ClaustrumEnrollmentManager2 {
|
|
|
9433
10266
|
}
|
|
9434
10267
|
if (!state.requestId) {
|
|
9435
10268
|
try {
|
|
9436
|
-
const requestSecretHash =
|
|
10269
|
+
const requestSecretHash = createHash7("sha256").update(Buffer.from(state.requestSecret, "hex")).digest("hex");
|
|
9437
10270
|
const proposed = await this.#client.enrollPropose({
|
|
9438
10271
|
name: state.proposedName,
|
|
9439
10272
|
requestSecretHash
|
|
@@ -9527,7 +10360,7 @@ class ClaustrumEnrollmentManager2 {
|
|
|
9527
10360
|
}
|
|
9528
10361
|
}
|
|
9529
10362
|
async function resetClaustrumEnrollmentState2(paths, proposedName) {
|
|
9530
|
-
await
|
|
10363
|
+
await mkdir9(dirname11(paths.statePath), { recursive: true, mode: 448 });
|
|
9531
10364
|
const lock = await acquireRefreshFileLock2({
|
|
9532
10365
|
name: "ceremony",
|
|
9533
10366
|
path: paths.statePath,
|
|
@@ -10307,7 +11140,7 @@ function executeLoggingCommand(input) {
|
|
|
10307
11140
|
`);
|
|
10308
11141
|
}
|
|
10309
11142
|
// src/mid-conversation-output-config.ts
|
|
10310
|
-
function
|
|
11143
|
+
function isRecord7(value) {
|
|
10311
11144
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
10312
11145
|
}
|
|
10313
11146
|
function normalizeAdaptiveEffort(value) {
|
|
@@ -10327,7 +11160,7 @@ function sendsPerTurnControlBeta(model) {
|
|
|
10327
11160
|
function supportsPerMessageEffort(body) {
|
|
10328
11161
|
if (pinsEffortOnEveryRequest(body.model))
|
|
10329
11162
|
return true;
|
|
10330
|
-
return usesPerTurnControl(body.model) &&
|
|
11163
|
+
return usesPerTurnControl(body.model) && isRecord7(body.thinking) && body.thinking.type === "adaptive";
|
|
10331
11164
|
}
|
|
10332
11165
|
function defaultAdaptiveEffort(model) {
|
|
10333
11166
|
return resolveClaudeModelCapabilities(model)?.efforts.default ?? "high";
|
|
@@ -10362,7 +11195,7 @@ function applyMidConversationOutputConfig(body, transitions) {
|
|
|
10362
11195
|
if (!pinsEveryRequest && compacted.length < 2) {
|
|
10363
11196
|
return { applied: false, inserted: 0 };
|
|
10364
11197
|
}
|
|
10365
|
-
const currentOutputConfig =
|
|
11198
|
+
const currentOutputConfig = isRecord7(body.output_config) ? body.output_config : {};
|
|
10366
11199
|
const baseline = compacted[0]?.effort ?? normalizeAdaptiveEffort(currentOutputConfig.effort) ?? defaultAdaptiveEffort(body.model);
|
|
10367
11200
|
const pinnedOutputConfig = { ...currentOutputConfig, effort: baseline };
|
|
10368
11201
|
if (pinsEveryRequest)
|
|
@@ -10379,7 +11212,7 @@ function applyMidConversationOutputConfig(body, transitions) {
|
|
|
10379
11212
|
let inserted = 0;
|
|
10380
11213
|
const rewritten = [];
|
|
10381
11214
|
for (const message of messages) {
|
|
10382
|
-
if (
|
|
11215
|
+
if (isRecord7(message) && message.role === "user" && transitionsByBoundary.has(assistantMessages)) {
|
|
10383
11216
|
const effort = transitionsByBoundary.get(assistantMessages);
|
|
10384
11217
|
if (effort && effort !== activeEffort) {
|
|
10385
11218
|
rewritten.push({
|
|
@@ -10392,7 +11225,7 @@ function applyMidConversationOutputConfig(body, transitions) {
|
|
|
10392
11225
|
}
|
|
10393
11226
|
}
|
|
10394
11227
|
rewritten.push(message);
|
|
10395
|
-
if (
|
|
11228
|
+
if (isRecord7(message) && message.role === "assistant")
|
|
10396
11229
|
assistantMessages++;
|
|
10397
11230
|
}
|
|
10398
11231
|
if (!pinsEveryRequest && inserted === 0) {
|
|
@@ -10574,7 +11407,7 @@ function isOpenAIReasoningSignature(value) {
|
|
|
10574
11407
|
}
|
|
10575
11408
|
}
|
|
10576
11409
|
// src/native-account-runtime.ts
|
|
10577
|
-
import { randomUUID as
|
|
11410
|
+
import { randomUUID as randomUUID16 } from "node:crypto";
|
|
10578
11411
|
|
|
10579
11412
|
// ../../node_modules/@cortexkit/common-auth/dist/store/errors.js
|
|
10580
11413
|
class PoolOperationError extends Error {
|
|
@@ -10651,8 +11484,8 @@ function recordIdentityIn(tx, id, identity2) {
|
|
|
10651
11484
|
import { setTimeout as snapshotDelay } from "node:timers/promises";
|
|
10652
11485
|
|
|
10653
11486
|
// ../../node_modules/@cortexkit/common-auth/dist/store/hooks.js
|
|
10654
|
-
import { AsyncLocalStorage } from "node:async_hooks";
|
|
10655
|
-
var insideHook = new
|
|
11487
|
+
import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
|
|
11488
|
+
var insideHook = new AsyncLocalStorage2;
|
|
10656
11489
|
function assertNotInsideHook(operation) {
|
|
10657
11490
|
if (insideHook.getStore() !== undefined)
|
|
10658
11491
|
throw new PoolReentryError(operation);
|
|
@@ -10800,7 +11633,7 @@ function assertNotReserved(operation, id, reservation) {
|
|
|
10800
11633
|
}
|
|
10801
11634
|
|
|
10802
11635
|
// ../../node_modules/@cortexkit/common-auth/dist/store/schema.js
|
|
10803
|
-
import { createHash as
|
|
11636
|
+
import { createHash as createHash8 } from "node:crypto";
|
|
10804
11637
|
var POOL_KEY = "commonAuthPool";
|
|
10805
11638
|
var POOL_SCHEMA_VERSION = 1;
|
|
10806
11639
|
var POOL_ROWS_KEY = "rows";
|
|
@@ -10813,22 +11646,22 @@ function canonicalJson(value) {
|
|
|
10813
11646
|
const encode = (item) => {
|
|
10814
11647
|
if (Array.isArray(item))
|
|
10815
11648
|
return `[${item.map(encode).join(",")}]`;
|
|
10816
|
-
if (
|
|
11649
|
+
if (isRecord8(item))
|
|
10817
11650
|
return `{${Object.keys(item).sort().map((key) => `${JSON.stringify(key)}:${encode(item[key])}`).join(",")}}`;
|
|
10818
11651
|
return JSON.stringify(item);
|
|
10819
11652
|
};
|
|
10820
11653
|
return encode(normalized);
|
|
10821
11654
|
}
|
|
10822
11655
|
function canonicalDigest(value) {
|
|
10823
|
-
return
|
|
11656
|
+
return createHash8("sha256").update(canonicalJson(value)).digest("hex");
|
|
10824
11657
|
}
|
|
10825
11658
|
function parseReservation(raw) {
|
|
10826
|
-
if (!
|
|
11659
|
+
if (!isRecord8(raw) || Object.keys(raw).length !== 1 || typeof raw.reservation !== "string" || !raw.reservation)
|
|
10827
11660
|
return;
|
|
10828
11661
|
return { reservation: raw.reservation };
|
|
10829
11662
|
}
|
|
10830
11663
|
function parseStagedStamp(raw) {
|
|
10831
|
-
if (!
|
|
11664
|
+
if (!isRecord8(raw) || typeof raw.reservation !== "string" || !raw.reservation || typeof raw.disabledReason !== "string")
|
|
10832
11665
|
return;
|
|
10833
11666
|
if (Object.keys(raw).some((key) => !["reservation", "label", "disabledReason", "providerState"].includes(key)))
|
|
10834
11667
|
return;
|
|
@@ -10839,7 +11672,7 @@ function parseStagedStamp(raw) {
|
|
|
10839
11672
|
return raw;
|
|
10840
11673
|
}
|
|
10841
11674
|
var PROVIDER_STATE_KEY = "commonAuthProviderState";
|
|
10842
|
-
function
|
|
11675
|
+
function isRecord8(value) {
|
|
10843
11676
|
return value != null && typeof value === "object" && !Array.isArray(value);
|
|
10844
11677
|
}
|
|
10845
11678
|
var UNSAFE_IDS = new Set(["__proto__", "constructor", "prototype"]);
|
|
@@ -10867,10 +11700,10 @@ function secretOf(credential) {
|
|
|
10867
11700
|
return credential.type === "oauth" ? `oauth\x00${credential.refresh}` : `api\x00${credential.apiKey}`;
|
|
10868
11701
|
}
|
|
10869
11702
|
function fingerprintOf(credential) {
|
|
10870
|
-
return
|
|
11703
|
+
return createHash8("sha256").update(secretOf(credential)).digest("hex");
|
|
10871
11704
|
}
|
|
10872
11705
|
function credentialDigest(credential) {
|
|
10873
|
-
return
|
|
11706
|
+
return createHash8("sha256").update(`credential-stamp\x00${secretOf(credential)}`).digest("hex");
|
|
10874
11707
|
}
|
|
10875
11708
|
function dispatchDigest(credential) {
|
|
10876
11709
|
const parts = credential.type === "oauth" ? [
|
|
@@ -10884,7 +11717,7 @@ function dispatchDigest(credential) {
|
|
|
10884
11717
|
credential.baseURL.trim(),
|
|
10885
11718
|
credential.authHeader ?? "authorization-bearer"
|
|
10886
11719
|
];
|
|
10887
|
-
return
|
|
11720
|
+
return createHash8("sha256").update(`credential-dispatch\x00${JSON.stringify(parts)}`).digest("hex");
|
|
10888
11721
|
}
|
|
10889
11722
|
function stampFor(credential, credentialEpoch, binding, options = {}) {
|
|
10890
11723
|
return {
|
|
@@ -10898,12 +11731,12 @@ function stampFor(credential, credentialEpoch, binding, options = {}) {
|
|
|
10898
11731
|
}
|
|
10899
11732
|
function providerStateDigest(codec, value) {
|
|
10900
11733
|
const bound = codec?.credentialBound ? codec.credentialBound(value) : value;
|
|
10901
|
-
return
|
|
11734
|
+
return createHash8("sha256").update(`provider-state\x00${JSON.stringify(bound ?? null)}`).digest("hex");
|
|
10902
11735
|
}
|
|
10903
11736
|
function boundProviderStateDigest(account, credential, credentialEpoch, identity2) {
|
|
10904
11737
|
if (!credential || credentialEpoch === undefined)
|
|
10905
11738
|
return;
|
|
10906
|
-
if (!
|
|
11739
|
+
if (!isRecord8(account) || !Object.hasOwn(account, PROVIDER_STATE_KEY))
|
|
10907
11740
|
return;
|
|
10908
11741
|
const stamp = parseStamp(account[CREDENTIAL_STAMP_KEY]);
|
|
10909
11742
|
if (!stamp || stamp.providerState === undefined || stamp.digest !== credentialDigest(credential) || stamp.credentialEpoch !== credentialEpoch || stamp.binding?.identity !== identity2)
|
|
@@ -10914,7 +11747,7 @@ function isCredentialEpoch(value) {
|
|
|
10914
11747
|
return Number.isSafeInteger(value) && value >= 1;
|
|
10915
11748
|
}
|
|
10916
11749
|
function parseStamp(raw) {
|
|
10917
|
-
if (!
|
|
11750
|
+
if (!isRecord8(raw))
|
|
10918
11751
|
return;
|
|
10919
11752
|
const epoch = raw.credentialEpoch;
|
|
10920
11753
|
if (!isCredentialEpoch(epoch))
|
|
@@ -10939,7 +11772,7 @@ function parseStamp(raw) {
|
|
|
10939
11772
|
if (!("binding" in raw))
|
|
10940
11773
|
return "dispatch" in raw || "replace" in raw || "providerState" in raw || "staged" in raw ? undefined : { credentialEpoch: epoch, digest: raw.digest };
|
|
10941
11774
|
const binding = raw.binding;
|
|
10942
|
-
if (!
|
|
11775
|
+
if (!isRecord8(binding))
|
|
10943
11776
|
return;
|
|
10944
11777
|
if ("identity" in binding && (typeof binding.identity !== "string" || !binding.identity))
|
|
10945
11778
|
return;
|
|
@@ -10970,7 +11803,7 @@ function bindingAgrees(binding, credential, identity2) {
|
|
|
10970
11803
|
function stampStatusOf(credential, credentialEpoch, identity2, account) {
|
|
10971
11804
|
if (!credential)
|
|
10972
11805
|
return "none";
|
|
10973
|
-
if (!
|
|
11806
|
+
if (!isRecord8(account) || !Object.hasOwn(account, CREDENTIAL_STAMP_KEY))
|
|
10974
11807
|
return "missing";
|
|
10975
11808
|
const stamp = parseStamp(account[CREDENTIAL_STAMP_KEY]);
|
|
10976
11809
|
if (!stamp)
|
|
@@ -10993,7 +11826,7 @@ function classifyConfig(read) {
|
|
|
10993
11826
|
if ("parseError" in read)
|
|
10994
11827
|
return { status: "error", reason: "config file is not valid JSON" };
|
|
10995
11828
|
const value = read.value;
|
|
10996
|
-
if (!
|
|
11829
|
+
if (!isRecord8(value))
|
|
10997
11830
|
return { status: "error", reason: "config root is not an object" };
|
|
10998
11831
|
if ("accounts" in value && !Array.isArray(value.accounts))
|
|
10999
11832
|
return { status: "error", reason: "config accounts is not an array" };
|
|
@@ -11001,7 +11834,7 @@ function classifyConfig(read) {
|
|
|
11001
11834
|
return Array.isArray(value.accounts) ? { status: "pending-migration", config: value } : { status: "ready", exists: true, config: value };
|
|
11002
11835
|
}
|
|
11003
11836
|
const pool = value[POOL_KEY];
|
|
11004
|
-
if (!
|
|
11837
|
+
if (!isRecord8(pool))
|
|
11005
11838
|
return { status: "error", reason: `${POOL_KEY} is not an object` };
|
|
11006
11839
|
const version = pool.schemaVersion;
|
|
11007
11840
|
if (typeof version !== "number" || !Number.isInteger(version) || version < 1)
|
|
@@ -11011,7 +11844,7 @@ function classifyConfig(read) {
|
|
|
11011
11844
|
status: "error",
|
|
11012
11845
|
reason: `${POOL_KEY}.schemaVersion ${version} is newer than ${POOL_SCHEMA_VERSION}`
|
|
11013
11846
|
};
|
|
11014
|
-
if (POOL_ROWS_KEY in pool && !
|
|
11847
|
+
if (POOL_ROWS_KEY in pool && !isRecord8(pool[POOL_ROWS_KEY]))
|
|
11015
11848
|
return {
|
|
11016
11849
|
status: "error",
|
|
11017
11850
|
reason: `${POOL_KEY}.${POOL_ROWS_KEY} is not an object`
|
|
@@ -11023,9 +11856,9 @@ function classifyState(read) {
|
|
|
11023
11856
|
return { status: "ready", exists: false, state: {} };
|
|
11024
11857
|
if ("parseError" in read)
|
|
11025
11858
|
return { status: "error", reason: "state file is not valid JSON" };
|
|
11026
|
-
if (!
|
|
11859
|
+
if (!isRecord8(read.value))
|
|
11027
11860
|
return { status: "error", reason: "state root is not an object" };
|
|
11028
|
-
if ("accounts" in read.value && !
|
|
11861
|
+
if ("accounts" in read.value && !isRecord8(read.value.accounts))
|
|
11029
11862
|
return { status: "error", reason: "state accounts is not an object" };
|
|
11030
11863
|
return { status: "ready", exists: true, state: read.value };
|
|
11031
11864
|
}
|
|
@@ -11034,16 +11867,16 @@ function rosterOf(config) {
|
|
|
11034
11867
|
}
|
|
11035
11868
|
function entriesOf(config) {
|
|
11036
11869
|
const pool = config[POOL_KEY];
|
|
11037
|
-
if (!
|
|
11870
|
+
if (!isRecord8(pool))
|
|
11038
11871
|
return {};
|
|
11039
11872
|
const rows = pool[POOL_ROWS_KEY];
|
|
11040
|
-
return
|
|
11873
|
+
return isRecord8(rows) ? rows : {};
|
|
11041
11874
|
}
|
|
11042
11875
|
function stateAccountsOf(state) {
|
|
11043
|
-
return
|
|
11876
|
+
return isRecord8(state.accounts) ? state.accounts : {};
|
|
11044
11877
|
}
|
|
11045
11878
|
function rosterRowProblem(raw) {
|
|
11046
|
-
if (!
|
|
11879
|
+
if (!isRecord8(raw))
|
|
11047
11880
|
return "not an object";
|
|
11048
11881
|
const problem = idProblem(raw.id);
|
|
11049
11882
|
if (problem)
|
|
@@ -11055,7 +11888,7 @@ function rosterRowProblem(raw) {
|
|
|
11055
11888
|
return "unknown type";
|
|
11056
11889
|
}
|
|
11057
11890
|
function parseEntry(raw, codec) {
|
|
11058
|
-
if (!
|
|
11891
|
+
if (!isRecord8(raw))
|
|
11059
11892
|
return;
|
|
11060
11893
|
const epoch = raw.credentialEpoch;
|
|
11061
11894
|
if (!isCredentialEpoch(epoch))
|
|
@@ -11077,7 +11910,7 @@ function parseEntry(raw, codec) {
|
|
|
11077
11910
|
};
|
|
11078
11911
|
}
|
|
11079
11912
|
function credentialFor(raw, stateEntry) {
|
|
11080
|
-
if (!
|
|
11913
|
+
if (!isRecord8(stateEntry))
|
|
11081
11914
|
return;
|
|
11082
11915
|
if (raw.type === "api") {
|
|
11083
11916
|
const apiKey = typeof stateEntry.apiKey === "string" ? stateEntry.apiKey.trim() : "";
|
|
@@ -11104,23 +11937,23 @@ function credentialFor(raw, stateEntry) {
|
|
|
11104
11937
|
};
|
|
11105
11938
|
}
|
|
11106
11939
|
function rosterRowIn(config, id) {
|
|
11107
|
-
return rosterOf(config).find((raw) =>
|
|
11940
|
+
return rosterOf(config).find((raw) => isRecord8(raw) && raw.id === id);
|
|
11108
11941
|
}
|
|
11109
11942
|
function ensurePool(config) {
|
|
11110
|
-
if (!
|
|
11943
|
+
if (!isRecord8(config[POOL_KEY]))
|
|
11111
11944
|
config[POOL_KEY] = {};
|
|
11112
11945
|
return config[POOL_KEY];
|
|
11113
11946
|
}
|
|
11114
11947
|
function ensureEntries(config) {
|
|
11115
11948
|
const pool = ensurePool(config);
|
|
11116
|
-
if (!
|
|
11949
|
+
if (!isRecord8(pool[POOL_ROWS_KEY]))
|
|
11117
11950
|
pool[POOL_ROWS_KEY] = {};
|
|
11118
11951
|
return pool[POOL_ROWS_KEY];
|
|
11119
11952
|
}
|
|
11120
11953
|
function entryIn(config, id) {
|
|
11121
11954
|
const entries = entriesOf(config);
|
|
11122
11955
|
const entry = Object.hasOwn(entries, id) ? entries[id] : undefined;
|
|
11123
|
-
return
|
|
11956
|
+
return isRecord8(entry) ? entry : undefined;
|
|
11124
11957
|
}
|
|
11125
11958
|
function setEntryIn(config, id, entry) {
|
|
11126
11959
|
Object.defineProperty(ensureEntries(config), id, {
|
|
@@ -11132,10 +11965,10 @@ function setEntryIn(config, id, entry) {
|
|
|
11132
11965
|
}
|
|
11133
11966
|
function retiredEpochIn(config, id) {
|
|
11134
11967
|
const pool = config[POOL_KEY];
|
|
11135
|
-
if (!
|
|
11968
|
+
if (!isRecord8(pool))
|
|
11136
11969
|
return;
|
|
11137
11970
|
const retired = pool[POOL_RETIRED_EPOCHS_KEY];
|
|
11138
|
-
if (!
|
|
11971
|
+
if (!isRecord8(retired) || !Object.hasOwn(retired, id))
|
|
11139
11972
|
return;
|
|
11140
11973
|
const epoch = retired[id];
|
|
11141
11974
|
return isCredentialEpoch(epoch) ? epoch : undefined;
|
|
@@ -11152,7 +11985,7 @@ function retireEpochsIn(config, dropped) {
|
|
|
11152
11985
|
if (ids.length === 0)
|
|
11153
11986
|
return;
|
|
11154
11987
|
const pool = ensurePool(config);
|
|
11155
|
-
const previous =
|
|
11988
|
+
const previous = isRecord8(pool[POOL_RETIRED_EPOCHS_KEY]) ? pool[POOL_RETIRED_EPOCHS_KEY] : {};
|
|
11156
11989
|
const next = {};
|
|
11157
11990
|
const define = (id, epoch) => Object.defineProperty(next, id, {
|
|
11158
11991
|
value: epoch,
|
|
@@ -11174,17 +12007,17 @@ function buildRawRows(config, state, codec, providerCodec) {
|
|
|
11174
12007
|
const rows = [];
|
|
11175
12008
|
for (const raw of rosterOf(config)) {
|
|
11176
12009
|
const problem = rosterRowProblem(raw);
|
|
11177
|
-
const id =
|
|
12010
|
+
const id = isRecord8(raw) && typeof raw.id === "string" ? raw.id : undefined;
|
|
11178
12011
|
const rawEntry = id === undefined ? undefined : entries[id];
|
|
11179
|
-
const reserved =
|
|
12012
|
+
const reserved = isRecord8(rawEntry) && Object.hasOwn(rawEntry, "staged");
|
|
11180
12013
|
const staged = reserved ? parseReservation(rawEntry.staged) : undefined;
|
|
11181
|
-
if (problem || !
|
|
12014
|
+
if (problem || !isRecord8(raw) || id === undefined || seen.has(id)) {
|
|
11182
12015
|
if (id !== undefined && !seen.has(id))
|
|
11183
12016
|
seen.add(id);
|
|
11184
12017
|
if (id !== undefined)
|
|
11185
12018
|
rows.push({
|
|
11186
12019
|
id,
|
|
11187
|
-
type:
|
|
12020
|
+
type: isRecord8(raw) && raw.type === "api" ? "api" : "oauth",
|
|
11188
12021
|
enabled: false,
|
|
11189
12022
|
needsFirstReading: true,
|
|
11190
12023
|
hasEntry: Object.hasOwn(entries, id),
|
|
@@ -11231,7 +12064,7 @@ function buildRawRows(config, state, codec, providerCodec) {
|
|
|
11231
12064
|
return rows;
|
|
11232
12065
|
}
|
|
11233
12066
|
function providerStateFields(account, credential, credentialEpoch, identity2, codec) {
|
|
11234
|
-
if (!
|
|
12067
|
+
if (!isRecord8(account) || !Object.hasOwn(account, PROVIDER_STATE_KEY))
|
|
11235
12068
|
return {};
|
|
11236
12069
|
const digest = boundProviderStateDigest(account, credential, credentialEpoch, identity2);
|
|
11237
12070
|
if (digest === undefined)
|
|
@@ -11291,7 +12124,7 @@ function storedCredential(credential, lastRefreshedAt) {
|
|
|
11291
12124
|
};
|
|
11292
12125
|
}
|
|
11293
12126
|
function credentialProblem(credential, options = {}) {
|
|
11294
|
-
if (!
|
|
12127
|
+
if (!isRecord8(credential))
|
|
11295
12128
|
return "credential must be an object";
|
|
11296
12129
|
if (credential.type === "oauth") {
|
|
11297
12130
|
if (typeof credential.refresh !== "string" || !credential.refresh.trim())
|
|
@@ -11315,10 +12148,10 @@ function credentialProblem(credential, options = {}) {
|
|
|
11315
12148
|
var TRANSITION_STAMP_KEY = "transition";
|
|
11316
12149
|
var TRANSITION_MARK_KEY = "transitionMark";
|
|
11317
12150
|
function stampedTransition(rawStamp) {
|
|
11318
|
-
if (!
|
|
12151
|
+
if (!isRecord8(rawStamp))
|
|
11319
12152
|
return;
|
|
11320
12153
|
const raw = rawStamp[TRANSITION_STAMP_KEY];
|
|
11321
|
-
if (!
|
|
12154
|
+
if (!isRecord8(raw))
|
|
11322
12155
|
return;
|
|
11323
12156
|
if (typeof raw.mark !== "string" || raw.mark.length === 0)
|
|
11324
12157
|
return;
|
|
@@ -11361,13 +12194,13 @@ function isReplaceStamp(stamp) {
|
|
|
11361
12194
|
return stamp.replace === true || stamp.dispatch === undefined;
|
|
11362
12195
|
}
|
|
11363
12196
|
function tornStamps(config, state, codec, options = {}) {
|
|
11364
|
-
const accounts =
|
|
12197
|
+
const accounts = isRecord8(state.accounts) ? state.accounts : {};
|
|
11365
12198
|
const torn = new Map;
|
|
11366
12199
|
for (const row of buildRawRows(config, state, codec)) {
|
|
11367
12200
|
if (row.invalid || row.staged || !row.credential)
|
|
11368
12201
|
continue;
|
|
11369
12202
|
const account = Object.hasOwn(accounts, row.id) ? accounts[row.id] : undefined;
|
|
11370
|
-
if (!
|
|
12203
|
+
if (!isRecord8(account))
|
|
11371
12204
|
continue;
|
|
11372
12205
|
const stamp = parseStamp(account[CREDENTIAL_STAMP_KEY]);
|
|
11373
12206
|
if (!stamp?.binding)
|
|
@@ -11575,7 +12408,7 @@ class Transaction {
|
|
|
11575
12408
|
return entry && Object.hasOwn(entry, "staged") ? entry.staged : undefined;
|
|
11576
12409
|
}
|
|
11577
12410
|
const stamp = this.stateAccount(id)?.[CREDENTIAL_STAMP_KEY];
|
|
11578
|
-
return
|
|
12411
|
+
return isRecord8(stamp) && Object.hasOwn(stamp, "staged") ? stamp.staged : undefined;
|
|
11579
12412
|
}
|
|
11580
12413
|
assertNotStaged(id) {
|
|
11581
12414
|
assertNotReserved(this.info.operation, id, this.reservation(id));
|
|
@@ -11591,7 +12424,7 @@ class Transaction {
|
|
|
11591
12424
|
}
|
|
11592
12425
|
dropRosterRows(id) {
|
|
11593
12426
|
const roster = this.roster();
|
|
11594
|
-
const kept = roster.filter((raw) => !(
|
|
12427
|
+
const kept = roster.filter((raw) => !(isRecord8(raw) && raw.id === id));
|
|
11595
12428
|
this.config.accounts = kept;
|
|
11596
12429
|
return roster.length - kept.length;
|
|
11597
12430
|
}
|
|
@@ -11613,16 +12446,16 @@ class Transaction {
|
|
|
11613
12446
|
await this.commitConfig({ counted: false });
|
|
11614
12447
|
}
|
|
11615
12448
|
stateAccount(id) {
|
|
11616
|
-
const accounts =
|
|
12449
|
+
const accounts = isRecord8(this.state.accounts) ? this.state.accounts : {};
|
|
11617
12450
|
const entry = Object.hasOwn(accounts, id) ? accounts[id] : undefined;
|
|
11618
|
-
return
|
|
12451
|
+
return isRecord8(entry) ? entry : undefined;
|
|
11619
12452
|
}
|
|
11620
12453
|
dropStateAccount(id) {
|
|
11621
|
-
if (
|
|
12454
|
+
if (isRecord8(this.state.accounts) && Object.hasOwn(this.state.accounts, id))
|
|
11622
12455
|
delete this.state.accounts[id];
|
|
11623
12456
|
}
|
|
11624
12457
|
setStateAccount(id, fields) {
|
|
11625
|
-
if (!
|
|
12458
|
+
if (!isRecord8(this.state.accounts))
|
|
11626
12459
|
this.state.accounts = {};
|
|
11627
12460
|
Object.defineProperty(this.state.accounts, id, {
|
|
11628
12461
|
value: fields,
|
|
@@ -11635,11 +12468,11 @@ class Transaction {
|
|
|
11635
12468
|
const roster = this.roster();
|
|
11636
12469
|
const rosterIds = new Set;
|
|
11637
12470
|
for (const raw of roster)
|
|
11638
|
-
if (
|
|
12471
|
+
if (isRecord8(raw) && typeof raw.id === "string")
|
|
11639
12472
|
rosterIds.add(raw.id);
|
|
11640
12473
|
const dropped = new Set;
|
|
11641
12474
|
for (const raw of rosterOf(this.snapshot.config))
|
|
11642
|
-
if (
|
|
12475
|
+
if (isRecord8(raw) && typeof raw.id === "string" && !rosterIds.has(raw.id))
|
|
11643
12476
|
dropped.add(raw.id);
|
|
11644
12477
|
for (const id of Object.keys(this.entries()))
|
|
11645
12478
|
if (!rosterIds.has(id))
|
|
@@ -11681,7 +12514,7 @@ class Transaction {
|
|
|
11681
12514
|
const next = {
|
|
11682
12515
|
...this.state,
|
|
11683
12516
|
version: LEGACY_STORE_VERSION,
|
|
11684
|
-
accounts:
|
|
12517
|
+
accounts: isRecord8(this.state.accounts) ? this.state.accounts : {}
|
|
11685
12518
|
};
|
|
11686
12519
|
await this.write(this.ctx.statePath, next, "state", true, options.durable ?? false);
|
|
11687
12520
|
this.state = next;
|
|
@@ -11876,11 +12709,11 @@ async function readRow(rt, operation, id) {
|
|
|
11876
12709
|
const row = result.rows.find((candidate) => candidate.id === id);
|
|
11877
12710
|
const entry = entryIn(result.config, id);
|
|
11878
12711
|
const accounts = result.state.accounts;
|
|
11879
|
-
const account =
|
|
11880
|
-
const stamp =
|
|
12712
|
+
const account = isRecord8(accounts) && Object.hasOwn(accounts, id) ? accounts[id] : undefined;
|
|
12713
|
+
const stamp = isRecord8(account) ? account[CREDENTIAL_STAMP_KEY] : undefined;
|
|
11881
12714
|
if (row && !["enable", "disable"].includes(operation) && entry && Object.hasOwn(entry, "staged"))
|
|
11882
12715
|
assertNotReserved(operation, id, entry.staged);
|
|
11883
|
-
if (!row &&
|
|
12716
|
+
if (!row && isRecord8(stamp) && Object.hasOwn(stamp, "staged"))
|
|
11884
12717
|
assertNotReserved(operation, id, stamp.staged);
|
|
11885
12718
|
if (!row)
|
|
11886
12719
|
throw unknownRow(operation, id);
|
|
@@ -12024,7 +12857,7 @@ async function updateProviderStateRow(rt, id, fence, mutator, options = {}) {
|
|
|
12024
12857
|
throw refusal(operation, id, "invalid-input", "the store was opened without a provider-state codec");
|
|
12025
12858
|
if (typeof mutator !== "function")
|
|
12026
12859
|
throw refusal(operation, id, "invalid-input", "a mutator is required");
|
|
12027
|
-
const captured =
|
|
12860
|
+
const captured = isRecord8(fence) ? fence.credentialEpoch : undefined;
|
|
12028
12861
|
if (!isCredentialEpoch(captured))
|
|
12029
12862
|
throw refusal(operation, id, "invalid-input", "the credential epoch the provider state was read at is required");
|
|
12030
12863
|
const { row: seen } = await readRow(rt, operation, id);
|
|
@@ -12068,7 +12901,7 @@ async function planProviderStateIn(tx, codec, operation, row, mutator, declinabl
|
|
|
12068
12901
|
const account = tx.stateAccount(id);
|
|
12069
12902
|
const rawStamp = account?.[CREDENTIAL_STAMP_KEY];
|
|
12070
12903
|
const stamp = parseStamp(rawStamp);
|
|
12071
|
-
if (!
|
|
12904
|
+
if (!isRecord8(rawStamp) || !stamp?.binding || stamp.digest !== credentialDigest(credential) || stamp.credentialEpoch !== epoch || stamp.binding.identity !== row.identity)
|
|
12072
12905
|
throw refusal(operation, id, "unbound-credential", `row ${id}'s credential carries no stamp of this store to bind a provider state to (stamp ${row.stamp}); rotate or replace it first`);
|
|
12073
12906
|
const current = row.providerState === undefined ? undefined : structuredClone(row.providerState);
|
|
12074
12907
|
const returned = await runInsideHook(operation, () => mutator(current, row));
|
|
@@ -12098,7 +12931,7 @@ async function planProviderStateIn(tx, codec, operation, row, mutator, declinabl
|
|
|
12098
12931
|
}
|
|
12099
12932
|
|
|
12100
12933
|
// ../../node_modules/@cortexkit/common-auth/dist/store/rows.js
|
|
12101
|
-
import { randomUUID as
|
|
12934
|
+
import { randomUUID as randomUUID11 } from "node:crypto";
|
|
12102
12935
|
async function protectIn(tx, id, protect) {
|
|
12103
12936
|
if (!protect)
|
|
12104
12937
|
return;
|
|
@@ -12144,7 +12977,7 @@ function onRowEndpoint(tx, id, credential) {
|
|
|
12144
12977
|
if (credential.type !== "api")
|
|
12145
12978
|
return credential;
|
|
12146
12979
|
const raw = tx.rosterRow(id);
|
|
12147
|
-
if (!
|
|
12980
|
+
if (!isRecord8(raw)) {
|
|
12148
12981
|
if (credential.baseURL === undefined)
|
|
12149
12982
|
throw refusal(tx.info.operation, id, "invalid-input", "api credential needs a valid baseURL");
|
|
12150
12983
|
return { ...credential, baseURL: credential.baseURL };
|
|
@@ -12163,7 +12996,7 @@ function onRowEndpoint(tx, id, credential) {
|
|
|
12163
12996
|
function bindingInTx(tx, id, stored, learnt) {
|
|
12164
12997
|
const raw = tx.rosterRow(id);
|
|
12165
12998
|
const projected = tx.row(id);
|
|
12166
|
-
const identity2 = learnt ?? (projected ? projected.identity :
|
|
12999
|
+
const identity2 = learnt ?? (projected ? projected.identity : isRecord8(raw) && typeof raw.accountId === "string" && raw.accountId ? raw.accountId : undefined);
|
|
12167
13000
|
return {
|
|
12168
13001
|
...identity2 !== undefined ? { identity: identity2 } : {},
|
|
12169
13002
|
...stored.type === "api" ? {
|
|
@@ -12247,7 +13080,7 @@ function requireUsableRow(operation, id, row, credential) {
|
|
|
12247
13080
|
return row;
|
|
12248
13081
|
}
|
|
12249
13082
|
function validateAttribution(operation, id, fence) {
|
|
12250
|
-
if (fence !== undefined && !isCredentialEpoch(
|
|
13083
|
+
if (fence !== undefined && !isCredentialEpoch(isRecord8(fence) ? fence.credentialEpoch : undefined))
|
|
12251
13084
|
throw refusal(operation, id, "invalid-input", "the attribution must name a credential epoch that is a positive safe integer");
|
|
12252
13085
|
}
|
|
12253
13086
|
function assertRowAttribution(operation, id, row, fence) {
|
|
@@ -12402,7 +13235,7 @@ async function addRow(rt, input, options = {}) {
|
|
|
12402
13235
|
const mode = options.onExisting ?? "rotate";
|
|
12403
13236
|
if (input.stage !== undefined && mode === "rotate")
|
|
12404
13237
|
throw refusal("add", id, "invalid-input", "a staged add needs onExisting: 'refuse' or 'stage-duplicate'");
|
|
12405
|
-
if (!["rotate", "refuse", "stage-duplicate"].includes(mode) || input.stage !== undefined && (label !== undefined && typeof label !== "string" || identity2 !== undefined && (typeof identity2 !== "string" || !identity2)) || input.disabled !== undefined && (!
|
|
13238
|
+
if (!["rotate", "refuse", "stage-duplicate"].includes(mode) || input.stage !== undefined && (label !== undefined && typeof label !== "string" || identity2 !== undefined && (typeof identity2 !== "string" || !identity2)) || input.disabled !== undefined && (!isRecord8(input.disabled) || typeof input.disabled.reason !== "string") || input.stage !== undefined && (!isRecord8(input.stage) || typeof input.stage.reservation !== "string" || !input.stage.reservation || !input.disabled) || mode === "stage-duplicate" && (!input.disabled || !input.stage))
|
|
12406
13239
|
throw refusal("add", id, "invalid-input", "staging requires a reservation and a disabled reason");
|
|
12407
13240
|
const incoming = input.providerState === undefined ? undefined : acceptProviderState(ctx.providerState, "add", id, input.providerState);
|
|
12408
13241
|
await locks.acquire(rowLockSpec(rt, { id, identity: identity2 }));
|
|
@@ -12412,12 +13245,12 @@ async function addRow(rt, input, options = {}) {
|
|
|
12412
13245
|
await locks.acquire(extra);
|
|
12413
13246
|
return withTransaction(ctx, locks, progress, { operation: "add", rowId: id }, async (tx) => {
|
|
12414
13247
|
await protectIn(tx, id, options.protect);
|
|
12415
|
-
const stateAccounts =
|
|
13248
|
+
const stateAccounts = isRecord8(tx.state.accounts) ? tx.state.accounts : {};
|
|
12416
13249
|
const stagedOrphan = Object.entries(stateAccounts).find(([orphanId, account]) => {
|
|
12417
|
-
if (orphanId === id || tx.rosterRow(orphanId) || !
|
|
13250
|
+
if (orphanId === id || tx.rosterRow(orphanId) || !isRecord8(account))
|
|
12418
13251
|
return false;
|
|
12419
13252
|
const stamp = account[CREDENTIAL_STAMP_KEY];
|
|
12420
|
-
if (!
|
|
13253
|
+
if (!isRecord8(stamp) || !Object.hasOwn(stamp, "staged"))
|
|
12421
13254
|
return false;
|
|
12422
13255
|
return credential.type === "oauth" ? account.refresh === credential.refresh : typeof account.apiKey === "string" && account.apiKey.trim() === credential.apiKey.trim();
|
|
12423
13256
|
});
|
|
@@ -12435,9 +13268,9 @@ async function addRow(rt, input, options = {}) {
|
|
|
12435
13268
|
}
|
|
12436
13269
|
if (mode === "refuse") {
|
|
12437
13270
|
const holder = tx.rows().find((row) => row.fingerprint === fingerprintOf(credential) || row.id === id && row.credential);
|
|
12438
|
-
const accounts =
|
|
13271
|
+
const accounts = isRecord8(tx.state.accounts) ? tx.state.accounts : {};
|
|
12439
13272
|
const stateHolder = Object.entries(accounts).find(([, account]) => {
|
|
12440
|
-
if (!
|
|
13273
|
+
if (!isRecord8(account))
|
|
12441
13274
|
return false;
|
|
12442
13275
|
if (credential.type === "oauth")
|
|
12443
13276
|
return account.refresh === credential.refresh;
|
|
@@ -12740,7 +13573,7 @@ async function transitionRow(rt, operation, id, flag, options) {
|
|
|
12740
13573
|
await tx.commitState();
|
|
12741
13574
|
return result;
|
|
12742
13575
|
}
|
|
12743
|
-
const transition = flag.enabled ? { mark:
|
|
13576
|
+
const transition = flag.enabled ? { mark: randomUUID11(), enabled: true } : { mark: randomUUID11(), enabled: false, reason: flag.reason };
|
|
12744
13577
|
const stamp = plan.account[CREDENTIAL_STAMP_KEY];
|
|
12745
13578
|
tx.setStateAccount(id, {
|
|
12746
13579
|
...plan.account,
|
|
@@ -12770,7 +13603,7 @@ async function removeRow(rt, id, options = {}) {
|
|
|
12770
13603
|
throw refusal("remove", id, "invalid-input", "id must be non-empty");
|
|
12771
13604
|
const fence = options.attribution;
|
|
12772
13605
|
validateAttribution("remove", id, fence);
|
|
12773
|
-
if (options.staged !== undefined && (!
|
|
13606
|
+
if (options.staged !== undefined && (!isRecord8(options.staged) || typeof options.staged.reservation !== "string" || !options.staged.reservation))
|
|
12774
13607
|
throw refusal("remove", id, "invalid-input", "a staged removal needs a reservation");
|
|
12775
13608
|
const result = await readPool(ctx);
|
|
12776
13609
|
if (result.status !== "ready")
|
|
@@ -12785,7 +13618,7 @@ async function removeRow(rt, id, options = {}) {
|
|
|
12785
13618
|
return withTransaction(ctx, locks, progress, { operation: "remove", rowId: id }, async (tx) => {
|
|
12786
13619
|
const reservation = tx.reservation(id);
|
|
12787
13620
|
if (reservation !== undefined) {
|
|
12788
|
-
if (!
|
|
13621
|
+
if (!isRecord8(reservation) || !options.staged || reservation.reservation !== options.staged.reservation)
|
|
12789
13622
|
throw refusal("remove", id, "row-staged", `row ${id} is reserved for roster publication`);
|
|
12790
13623
|
} else if (options.staged)
|
|
12791
13624
|
throw refusal("remove", id, "attribution", `row ${id} is no longer reserved`);
|
|
@@ -12873,10 +13706,10 @@ function assertOrphanAttribution(rt, tx, id, fence) {
|
|
|
12873
13706
|
}
|
|
12874
13707
|
function hasStateAccount(state, id) {
|
|
12875
13708
|
const accounts = state.accounts;
|
|
12876
|
-
return
|
|
13709
|
+
return isRecord8(accounts) && Object.hasOwn(accounts, id);
|
|
12877
13710
|
}
|
|
12878
13711
|
function rosterIdOf(raw) {
|
|
12879
|
-
return
|
|
13712
|
+
return isRecord8(raw) && typeof raw.id === "string" ? raw.id : undefined;
|
|
12880
13713
|
}
|
|
12881
13714
|
function orderProblem(roster, ids) {
|
|
12882
13715
|
if (!Array.isArray(ids))
|
|
@@ -12951,7 +13784,7 @@ async function recordRowIdentity(rt, id, identity2, attribution, options = {}) {
|
|
|
12951
13784
|
return runOperation(rt.ctx, "recordIdentity", id, options.onFailure, async (locks, progress) => {
|
|
12952
13785
|
if (typeof identity2 !== "string" || identity2.length === 0)
|
|
12953
13786
|
throw refusal("recordIdentity", id, "invalid-input", "identity must be non-empty");
|
|
12954
|
-
const captured =
|
|
13787
|
+
const captured = isRecord8(attribution) ? attribution.credentialEpoch : undefined;
|
|
12955
13788
|
if (!isCredentialEpoch(captured))
|
|
12956
13789
|
throw refusal("recordIdentity", id, "invalid-input", "the credential epoch the identity lookup was issued for is required");
|
|
12957
13790
|
const { row: seen } = await readRow(rt, "recordIdentity", id);
|
|
@@ -12980,14 +13813,14 @@ async function recordRowIdentity(rt, id, identity2, attribution, options = {}) {
|
|
|
12980
13813
|
// ../../node_modules/@cortexkit/common-auth/dist/store/publication.js
|
|
12981
13814
|
function receiptsIn(config) {
|
|
12982
13815
|
const pool = config[POOL_KEY];
|
|
12983
|
-
return
|
|
13816
|
+
return isRecord8(pool) && isRecord8(pool.publications) ? pool.publications : {};
|
|
12984
13817
|
}
|
|
12985
13818
|
function receiptIn(config, operationId) {
|
|
12986
13819
|
const receipts = receiptsIn(config);
|
|
12987
13820
|
if (!Object.hasOwn(receipts, operationId))
|
|
12988
13821
|
return;
|
|
12989
13822
|
const raw = receipts[operationId];
|
|
12990
|
-
if (!
|
|
13823
|
+
if (!isRecord8(raw) || raw.operationId !== operationId || typeof raw.planDigest !== "string" || !/^[a-f0-9]{64}$/.test(raw.planDigest) || !["committed", "cleaned"].includes(String(raw.phase)) || !Array.isArray(raw.removed) || !Array.isArray(raw.finalized) || raw.removed.some((ref) => !isRecord8(ref) || typeof ref.id !== "string" || !isCredentialEpoch(ref.credentialEpoch)) || raw.finalized.some((ref) => !isRecord8(ref) || typeof ref.id !== "string" || !isCredentialEpoch(ref.credentialEpoch) || typeof ref.reservation !== "string" || !ref.reservation || typeof ref.enabled !== "boolean"))
|
|
12991
13824
|
throw refusal("publishRoster", operationId, "invalid-input", "the stored publication receipt is malformed");
|
|
12992
13825
|
return structuredClone(raw);
|
|
12993
13826
|
}
|
|
@@ -13001,11 +13834,11 @@ function validatePlan(rt, plan) {
|
|
|
13001
13834
|
const fail = () => {
|
|
13002
13835
|
throw refusal("publishRoster", plan?.operationId ?? "", "invalid-input", "the publication plan is invalid");
|
|
13003
13836
|
};
|
|
13004
|
-
if (!
|
|
13837
|
+
if (!isRecord8(plan) || typeof plan.operationId !== "string" || !plan.operationId || !Array.isArray(plan.remove) || !Array.isArray(plan.finalize) || !Array.isArray(plan.order))
|
|
13005
13838
|
fail();
|
|
13006
13839
|
const ids = new Set;
|
|
13007
13840
|
for (const ref of [...plan.remove, ...plan.finalize]) {
|
|
13008
|
-
if (!
|
|
13841
|
+
if (!isRecord8(ref) || typeof ref.id !== "string" || idProblem(ref.id) || ids.has(ref.id) || !ref.attribution)
|
|
13009
13842
|
fail();
|
|
13010
13843
|
ids.add(ref.id);
|
|
13011
13844
|
validateAttribution("publishRoster", ref.id, ref.attribution);
|
|
@@ -13037,7 +13870,7 @@ function saveReceipt(tx, receipt) {
|
|
|
13037
13870
|
function publicationSurvivors(tx, plan, rows) {
|
|
13038
13871
|
const rosterIds = new Set;
|
|
13039
13872
|
for (const raw of rosterOf(tx.config)) {
|
|
13040
|
-
if (!
|
|
13873
|
+
if (!isRecord8(raw) || typeof raw.id !== "string")
|
|
13041
13874
|
continue;
|
|
13042
13875
|
if (rosterIds.has(raw.id))
|
|
13043
13876
|
throw refusal("publishRoster", plan.operationId, "invalid-input", "publication needs a roster of unique named rows");
|
|
@@ -13076,14 +13909,14 @@ async function cleanup(tx, receipt) {
|
|
|
13076
13909
|
async function publishRoster(rt, plan, options = {}) {
|
|
13077
13910
|
assertNotInsideHook("publishRoster");
|
|
13078
13911
|
return runOperation(rt.ctx, "publishRoster", plan?.operationId ?? "", options.onFailure, async (locks, progress) => {
|
|
13079
|
-
if (!
|
|
13912
|
+
if (!isRecord8(plan) || typeof plan.operationId !== "string" || !plan.operationId)
|
|
13080
13913
|
throw refusal("publishRoster", plan?.operationId ?? "", "invalid-input", "the publication needs an operation id");
|
|
13081
13914
|
plan = structuredClone(plan);
|
|
13082
13915
|
const planDigest = canonicalDigest(plan);
|
|
13083
13916
|
const named = [
|
|
13084
13917
|
...Array.isArray(plan.remove) ? plan.remove : [],
|
|
13085
13918
|
...Array.isArray(plan.finalize) ? plan.finalize : []
|
|
13086
|
-
].filter((ref) =>
|
|
13919
|
+
].filter((ref) => isRecord8(ref) && typeof ref.id === "string");
|
|
13087
13920
|
for (let attempt = 0;; attempt++) {
|
|
13088
13921
|
const seen = await readPool(rt.ctx);
|
|
13089
13922
|
if (seen.status !== "ready")
|
|
@@ -13187,7 +14020,7 @@ async function publishRoster(rt, plan, options = {}) {
|
|
|
13187
14020
|
entry.disabledReason = ref.disabledReason;
|
|
13188
14021
|
tx.setEntry(ref.id, entry);
|
|
13189
14022
|
}
|
|
13190
|
-
const preserved = tx.roster().filter((raw) => !
|
|
14023
|
+
const preserved = tx.roster().filter((raw) => !isRecord8(raw) || typeof raw.id !== "string" || rows.find((row) => row.id === raw.id)?.invalid === "roster");
|
|
13191
14024
|
tx.config.accounts = [
|
|
13192
14025
|
...plan.order.map((id) => tx.rosterRow(id)),
|
|
13193
14026
|
...preserved
|
|
@@ -13317,8 +14150,8 @@ class PullScheduler {
|
|
|
13317
14150
|
}
|
|
13318
14151
|
// ../../node_modules/@cortexkit/common-auth/dist/logger/engine.js
|
|
13319
14152
|
import { appendFileSync as appendFileSync2, chmodSync, existsSync as existsSync3, renameSync as renameSync2, statSync as statSync4 } from "node:fs";
|
|
13320
|
-
import { open as
|
|
13321
|
-
import { dirname as
|
|
14153
|
+
import { open as open7 } from "node:fs/promises";
|
|
14154
|
+
import { dirname as dirname12, resolve as resolve6 } from "node:path";
|
|
13322
14155
|
var ORDER = {
|
|
13323
14156
|
error: 0,
|
|
13324
14157
|
warn: 1,
|
|
@@ -13357,7 +14190,7 @@ async function closeWindowsFile(sink) {
|
|
|
13357
14190
|
await privateOperation(file, "log-close", () => handle.close());
|
|
13358
14191
|
}
|
|
13359
14192
|
async function openWindowsFile(sink, file) {
|
|
13360
|
-
await ensurePrivateDirectory(
|
|
14193
|
+
await ensurePrivateDirectory(dirname12(file));
|
|
13361
14194
|
try {
|
|
13362
14195
|
await verifyPrivate(file, "file", true);
|
|
13363
14196
|
} catch (error) {
|
|
@@ -13371,7 +14204,7 @@ async function openWindowsFile(sink, file) {
|
|
|
13371
14204
|
await verifyPrivate(file, "file", true);
|
|
13372
14205
|
}
|
|
13373
14206
|
}
|
|
13374
|
-
sink.handle = await privateOperation(file, "log-open", () =>
|
|
14207
|
+
sink.handle = await privateOperation(file, "log-open", () => open7(file, "a"));
|
|
13375
14208
|
sink.file = file;
|
|
13376
14209
|
return sink.handle;
|
|
13377
14210
|
}
|
|
@@ -13853,7 +14686,7 @@ class PoolQuotaWriter {
|
|
|
13853
14686
|
}
|
|
13854
14687
|
|
|
13855
14688
|
// ../../node_modules/@cortexkit/common-auth/dist/store/refresh.js
|
|
13856
|
-
import { randomUUID as
|
|
14689
|
+
import { randomUUID as randomUUID12 } from "node:crypto";
|
|
13857
14690
|
function requireRefreshable(id, row) {
|
|
13858
14691
|
assertNotReserved("refresh", id, row?.staged);
|
|
13859
14692
|
if (!row)
|
|
@@ -13970,7 +14803,7 @@ async function refreshRow(rt, id, provider, options = {}) {
|
|
|
13970
14803
|
returnedIdentity: result.identity
|
|
13971
14804
|
} : undefined;
|
|
13972
14805
|
const transition = contradiction ? {
|
|
13973
|
-
mark:
|
|
14806
|
+
mark: randomUUID12(),
|
|
13974
14807
|
enabled: false,
|
|
13975
14808
|
reason: `${IDENTITY_CONTRADICTED_REASON_PREFIX}${JSON.stringify(contradiction)}`
|
|
13976
14809
|
} : undefined;
|
|
@@ -14103,7 +14936,7 @@ async function updatePoolSettings(rt, mutator, options = {}) {
|
|
|
14103
14936
|
const draft = structuredClone(current);
|
|
14104
14937
|
const returned = await runInsideHook("updateSettings", () => mutator(draft));
|
|
14105
14938
|
const next = returned === undefined ? draft : returned;
|
|
14106
|
-
if (!
|
|
14939
|
+
if (!isRecord8(next))
|
|
14107
14940
|
throw settingsRefusal("the settings mutator must produce an object");
|
|
14108
14941
|
const owned = POOL_OWNED_KEYS.filter((key) => Object.hasOwn(next, key));
|
|
14109
14942
|
if (owned.length > 0)
|
|
@@ -14250,7 +15083,7 @@ function entryTime(entry) {
|
|
|
14250
15083
|
function limitKey(scope, label) {
|
|
14251
15084
|
return JSON.stringify([scope, label]);
|
|
14252
15085
|
}
|
|
14253
|
-
function
|
|
15086
|
+
function isRecord9(value) {
|
|
14254
15087
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
14255
15088
|
}
|
|
14256
15089
|
function isFiniteNumber(value) {
|
|
@@ -14269,7 +15102,7 @@ function isString(value) {
|
|
|
14269
15102
|
return typeof value === "string";
|
|
14270
15103
|
}
|
|
14271
15104
|
function isQuotaEntry(value) {
|
|
14272
|
-
if (!
|
|
15105
|
+
if (!isRecord9(value) || !isName(value.scope) || !isName(value.label)) {
|
|
14273
15106
|
return false;
|
|
14274
15107
|
}
|
|
14275
15108
|
switch (value.kind) {
|
|
@@ -14284,26 +15117,26 @@ function isQuotaEntry(value) {
|
|
|
14284
15117
|
}
|
|
14285
15118
|
}
|
|
14286
15119
|
function isCreditBudgetEntry(value) {
|
|
14287
|
-
if (!
|
|
15120
|
+
if (!isRecord9(value) || !isFiniteNumber(value.checkedAt))
|
|
14288
15121
|
return false;
|
|
14289
15122
|
if (value.kind === "cleared")
|
|
14290
15123
|
return true;
|
|
14291
15124
|
return value.kind === "reading" && typeof value.reached === "boolean" && optional(value, "remainingPercent", isFiniteNumber) && optional(value, "usedPercent", isFiniteNumber) && optional(value, "resetsAt", isString) && optional(value, "limit", isFiniteNumber) && optional(value, "used", isFiniteNumber) && optional(value, "remaining", isFiniteNumber) && optional(value, "unit", isString);
|
|
14292
15125
|
}
|
|
14293
15126
|
function isQuotaCounter(value) {
|
|
14294
|
-
return
|
|
15127
|
+
return isRecord9(value) && isFiniteNumber(value.value) && Number.isInteger(value.value) && value.value >= 0 && isFiniteNumber(value.checkedAt);
|
|
14295
15128
|
}
|
|
14296
15129
|
function isQuotaCounters(value) {
|
|
14297
|
-
return
|
|
15130
|
+
return isRecord9(value) && Object.values(value).every(isQuotaCounter);
|
|
14298
15131
|
}
|
|
14299
15132
|
function isBoolean(value) {
|
|
14300
15133
|
return typeof value === "boolean";
|
|
14301
15134
|
}
|
|
14302
15135
|
function isQuotaCredits(value) {
|
|
14303
|
-
return
|
|
15136
|
+
return isRecord9(value) && typeof value.hasCredits === "boolean" && typeof value.unlimited === "boolean" && optional(value, "balance", isFiniteNumber) && optional(value, "overageLimitReached", isBoolean) && isFiniteNumber(value.checkedAt);
|
|
14304
15137
|
}
|
|
14305
15138
|
function readQuotaCounters(value) {
|
|
14306
|
-
if (!
|
|
15139
|
+
if (!isRecord9(value))
|
|
14307
15140
|
return;
|
|
14308
15141
|
const entries = Object.entries(value).filter(([, entry]) => isQuotaCounter(entry));
|
|
14309
15142
|
return entries.length === 0 ? undefined : Object.fromEntries(entries);
|
|
@@ -14311,7 +15144,7 @@ function readQuotaCounters(value) {
|
|
|
14311
15144
|
function decodeQuotaMap(value) {
|
|
14312
15145
|
if (isQuotaMap(value))
|
|
14313
15146
|
return value;
|
|
14314
|
-
if (!
|
|
15147
|
+
if (!isRecord9(value))
|
|
14315
15148
|
return;
|
|
14316
15149
|
const { counters: rawCounters, credits: rawCredits, ...rest } = value;
|
|
14317
15150
|
if (!isQuotaMap(rest))
|
|
@@ -14325,7 +15158,7 @@ function decodeQuotaMap(value) {
|
|
|
14325
15158
|
};
|
|
14326
15159
|
}
|
|
14327
15160
|
function isQuotaMap(value) {
|
|
14328
|
-
if (!
|
|
15161
|
+
if (!isRecord9(value) || !Array.isArray(value.limits))
|
|
14329
15162
|
return false;
|
|
14330
15163
|
const seen = new Set;
|
|
14331
15164
|
for (const entry of value.limits) {
|
|
@@ -14346,7 +15179,7 @@ class QuotaCodecError extends TypeError {
|
|
|
14346
15179
|
this.name = "QuotaCodecError";
|
|
14347
15180
|
}
|
|
14348
15181
|
}
|
|
14349
|
-
function
|
|
15182
|
+
function isRecord10(value) {
|
|
14350
15183
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
14351
15184
|
}
|
|
14352
15185
|
function isFiniteNumber2(value) {
|
|
@@ -14365,20 +15198,20 @@ function optionalString(record, key) {
|
|
|
14365
15198
|
return record[key] === undefined || typeof record[key] === "string";
|
|
14366
15199
|
}
|
|
14367
15200
|
function isObservedReading(value) {
|
|
14368
|
-
return
|
|
15201
|
+
return isRecord10(value) && isScope(value.scope) && isLabel(value.label) && isFiniteNumber2(value.usedPercent) && optionalString(value, "resetsAt") && (value.windowMinutes === undefined || isFiniteNumber2(value.windowMinutes) && value.windowMinutes > 0);
|
|
14369
15202
|
}
|
|
14370
15203
|
function isObservedPair(value) {
|
|
14371
|
-
return
|
|
15204
|
+
return isRecord10(value) && isScope(value.scope) && isLabel(value.label);
|
|
14372
15205
|
}
|
|
14373
15206
|
function isObservedBudget(value) {
|
|
14374
|
-
if (!
|
|
15207
|
+
if (!isRecord10(value))
|
|
14375
15208
|
return false;
|
|
14376
15209
|
if (value.kind === "cleared")
|
|
14377
15210
|
return true;
|
|
14378
15211
|
return value.kind === "reading" && typeof value.reached === "boolean" && optionalFinite(value, "remainingPercent") && optionalFinite(value, "usedPercent") && optionalString(value, "resetsAt") && optionalFinite(value, "limit") && optionalFinite(value, "used") && optionalFinite(value, "remaining") && optionalString(value, "unit");
|
|
14379
15212
|
}
|
|
14380
15213
|
function isQuotaObservation(value) {
|
|
14381
|
-
if (!
|
|
15214
|
+
if (!isRecord10(value) || !isFiniteNumber2(value.checkedAt))
|
|
14382
15215
|
return false;
|
|
14383
15216
|
const readings = value.readings ?? [];
|
|
14384
15217
|
const coverage = value.coverage ?? [];
|
|
@@ -14654,11 +15487,11 @@ function groupShortNames(groups) {
|
|
|
14654
15487
|
function groupedNarrowPieces(groups, windows) {
|
|
14655
15488
|
if (!groups || groups.length === 0)
|
|
14656
15489
|
return;
|
|
14657
|
-
const
|
|
14658
|
-
if (
|
|
15490
|
+
const reported2 = windows.filter(({ part }) => part.kind === "window");
|
|
15491
|
+
if (reported2.some(({ scope }) => scope === ALL_SCOPE))
|
|
14659
15492
|
return;
|
|
14660
15493
|
const candidates = groups.flatMap((group, listed) => {
|
|
14661
|
-
const inGroup =
|
|
15494
|
+
const inGroup = reported2.filter(({ scope }) => scope === group.scope);
|
|
14662
15495
|
const groupTightest = inGroup.reduce((least, window) => least === undefined || (window.part.remainingPercent ?? 0) < (least.part.remainingPercent ?? 0) ? window : least, undefined);
|
|
14663
15496
|
return groupTightest ? [{ group, listed, window: groupTightest }] : [];
|
|
14664
15497
|
});
|
|
@@ -14945,14 +15778,14 @@ var nativeQuotaCodec = {
|
|
|
14945
15778
|
};
|
|
14946
15779
|
|
|
14947
15780
|
// src/native-runtime.ts
|
|
14948
|
-
import { randomUUID as
|
|
15781
|
+
import { randomUUID as randomUUID13 } from "node:crypto";
|
|
14949
15782
|
import { constants as constants2 } from "node:fs";
|
|
14950
|
-
import { lstat as
|
|
14951
|
-
import { basename as
|
|
15783
|
+
import { lstat as lstat8, mkdir as mkdir10, open as open8, rename as rename11, rm as rm6 } from "node:fs/promises";
|
|
15784
|
+
import { basename as basename7, dirname as dirname13, isAbsolute as isAbsolute4, join as join15 } from "node:path";
|
|
14952
15785
|
import { types as utilTypes5 } from "node:util";
|
|
14953
15786
|
|
|
14954
15787
|
// src/pool-binding.ts
|
|
14955
|
-
import { createHash as
|
|
15788
|
+
import { createHash as createHash9 } from "node:crypto";
|
|
14956
15789
|
|
|
14957
15790
|
class NativePoolBindingError extends Error {
|
|
14958
15791
|
constructor() {
|
|
@@ -14996,7 +15829,7 @@ function nativeLocalPoolBindingMatches(binding, paths, row) {
|
|
|
14996
15829
|
function nativeLocalRefreshJobKey(binding) {
|
|
14997
15830
|
if (!isNativeLocalPoolBinding(binding))
|
|
14998
15831
|
throw new NativePoolBindingError;
|
|
14999
|
-
return
|
|
15832
|
+
return createHash9("sha256").update(JSON.stringify([
|
|
15000
15833
|
"anthropic-local-refresh",
|
|
15001
15834
|
binding.storageId,
|
|
15002
15835
|
binding.credentialEpoch,
|
|
@@ -15005,9 +15838,9 @@ function nativeLocalRefreshJobKey(binding) {
|
|
|
15005
15838
|
}
|
|
15006
15839
|
|
|
15007
15840
|
// src/token-fingerprint.ts
|
|
15008
|
-
import { createHash as
|
|
15841
|
+
import { createHash as createHash10 } from "node:crypto";
|
|
15009
15842
|
function tokenFingerprint(token) {
|
|
15010
|
-
return
|
|
15843
|
+
return createHash10("sha256").update(token).digest("hex").slice(0, 16);
|
|
15011
15844
|
}
|
|
15012
15845
|
|
|
15013
15846
|
// src/native-credential-validation.ts
|
|
@@ -15034,53 +15867,14 @@ function nativeLocalCredentialValidationMatches(validation, binding, material) {
|
|
|
15034
15867
|
return validation.binding.storageId === binding.storageId && validation.binding.rowId === binding.rowId && validation.binding.credentialEpoch === binding.credentialEpoch && validation.binding.identity === binding.identity && validation.credentialFingerprint === fingerprintOf({ type: "oauth", refresh: material.refresh }) && validation.version.accessFingerprint === tokenFingerprint(material.access) && validation.version.expires === material.expires && Object.hasOwn(validation.version, "lastRefreshedAt") === Object.hasOwn(material, "lastRefreshedAt") && validation.version.lastRefreshedAt === material.lastRefreshedAt;
|
|
15035
15868
|
}
|
|
15036
15869
|
|
|
15037
|
-
// src/native-lock-observer.ts
|
|
15038
|
-
import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
|
|
15039
|
-
var detachedLocks = new AsyncLocalStorage2;
|
|
15040
|
-
function withDetachedNativeLocks(work) {
|
|
15041
|
-
return detachedLocks.run(true, work);
|
|
15042
|
-
}
|
|
15043
|
-
function nativeLockObserver(observer) {
|
|
15044
|
-
if (!observer)
|
|
15045
|
-
return;
|
|
15046
|
-
return (event) => {
|
|
15047
|
-
try {
|
|
15048
|
-
const result = observer(detachedLocks.getStore() ? { ...event, detached: true } : event);
|
|
15049
|
-
if (result !== null && (typeof result === "object" || typeof result === "function") && "then" in result && typeof result.then === "function") {
|
|
15050
|
-
Promise.resolve(result).catch(() => {});
|
|
15051
|
-
}
|
|
15052
|
-
} catch {}
|
|
15053
|
-
};
|
|
15054
|
-
}
|
|
15055
|
-
async function withNativeLock(path2, options, run, acquire = withLock) {
|
|
15056
|
-
const observer = nativeLockObserver(options.onLockEvent);
|
|
15057
|
-
if (!observer)
|
|
15058
|
-
return acquire(path2, options, run);
|
|
15059
|
-
observer({ type: "acquiring", name: options.name, path: path2 });
|
|
15060
|
-
let acquired = false;
|
|
15061
|
-
try {
|
|
15062
|
-
return await acquire(path2, options, async (lease) => {
|
|
15063
|
-
acquired = true;
|
|
15064
|
-
observer({ type: "acquired", name: options.name, path: path2 });
|
|
15065
|
-
return run(lease);
|
|
15066
|
-
});
|
|
15067
|
-
} finally {
|
|
15068
|
-
if (acquired)
|
|
15069
|
-
observer({ type: "released", name: options.name, path: path2 });
|
|
15070
|
-
}
|
|
15071
|
-
}
|
|
15072
|
-
function observeNativeLocks(acquire, observer) {
|
|
15073
|
-
return (path2, options, run) => withNativeLock(path2, { ...options, onLockEvent: options.onLockEvent ?? observer }, run, acquire());
|
|
15074
|
-
}
|
|
15075
|
-
|
|
15076
15870
|
// src/native-vault-seed.ts
|
|
15077
|
-
import { lstat as
|
|
15871
|
+
import { lstat as lstat7, readFile as readFile9 } from "node:fs/promises";
|
|
15078
15872
|
|
|
15079
15873
|
// src/native-migration-source.ts
|
|
15080
|
-
import { createHash as
|
|
15874
|
+
import { createHash as createHash13 } from "node:crypto";
|
|
15081
15875
|
|
|
15082
15876
|
// src/native-host-auth.ts
|
|
15083
|
-
import { createHash as
|
|
15877
|
+
import { createHash as createHash11 } from "node:crypto";
|
|
15084
15878
|
class NativeHostAuthError extends Error {
|
|
15085
15879
|
code;
|
|
15086
15880
|
constructor(code) {
|
|
@@ -15206,7 +16000,7 @@ function inspectNativeHostAuthEntry(host, hostAuth) {
|
|
|
15206
16000
|
}
|
|
15207
16001
|
return Object.freeze({
|
|
15208
16002
|
kind,
|
|
15209
|
-
digest:
|
|
16003
|
+
digest: createHash11("sha256").update(canonical, "utf8").digest("hex")
|
|
15210
16004
|
});
|
|
15211
16005
|
} catch {
|
|
15212
16006
|
throw new NativeHostAuthError("invalid-source");
|
|
@@ -15214,7 +16008,7 @@ function inspectNativeHostAuthEntry(host, hostAuth) {
|
|
|
15214
16008
|
}
|
|
15215
16009
|
|
|
15216
16010
|
// src/native-migration-proof.ts
|
|
15217
|
-
import { createHash as
|
|
16011
|
+
import { createHash as createHash12 } from "node:crypto";
|
|
15218
16012
|
import { types } from "node:util";
|
|
15219
16013
|
|
|
15220
16014
|
class NativeMigrationProofError extends Error {
|
|
@@ -15288,7 +16082,7 @@ function nativeMigrationCanonicalJson(value) {
|
|
|
15288
16082
|
return JSON.stringify(captureNativeMigrationJson(value));
|
|
15289
16083
|
}
|
|
15290
16084
|
function nativeMigrationDigest(value) {
|
|
15291
|
-
return
|
|
16085
|
+
return createHash12("sha256").update(nativeMigrationCanonicalJson(value)).digest("hex");
|
|
15292
16086
|
}
|
|
15293
16087
|
function record3(value) {
|
|
15294
16088
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
@@ -15569,7 +16363,7 @@ function runtime(source2, accountIdentity, current) {
|
|
|
15569
16363
|
"permanent"
|
|
15570
16364
|
]);
|
|
15571
16365
|
safe.message = field === "lastRefreshError" ? "Imported refresh failure" : "Imported quota failure";
|
|
15572
|
-
if (field === "lastRefreshError" && current?.type === "oauth" && error.tokenHash ===
|
|
16366
|
+
if (field === "lastRefreshError" && current?.type === "oauth" && error.tokenHash === createHash13("sha256").update(current.refresh).digest("hex"))
|
|
15573
16367
|
safe.credentialFingerprint = fingerprintOf(current);
|
|
15574
16368
|
result[field] = safe;
|
|
15575
16369
|
}
|
|
@@ -15593,7 +16387,7 @@ function projectNativeMigrationSource(input) {
|
|
|
15593
16387
|
const hostEntry = inspectNativeHostAuthEntry(input.host, auth);
|
|
15594
16388
|
if (config.version !== undefined && config.version !== 1 || state.version !== undefined && state.version !== 1)
|
|
15595
16389
|
refuse2();
|
|
15596
|
-
const formerMain =
|
|
16390
|
+
const formerMain = createHash13("sha256").update(JSON.stringify([input.storageId, input.configDigest, "former-main"])).digest("hex");
|
|
15597
16391
|
const mainRouteId = config.mainAccountId === undefined ? `${formerMain.slice(0, 8)}-${formerMain.slice(8, 12)}-${formerMain.slice(12, 16)}-${formerMain.slice(16, 20)}-${formerMain.slice(20, 32)}` : id(config.mainAccountId);
|
|
15598
16392
|
const settings = {
|
|
15599
16393
|
mainAccountId: mainRouteId,
|
|
@@ -15867,14 +16661,14 @@ function record5(value) {
|
|
|
15867
16661
|
}
|
|
15868
16662
|
async function readNativeVaultLegacyJson(path2) {
|
|
15869
16663
|
try {
|
|
15870
|
-
return JSON.parse(await
|
|
16664
|
+
return JSON.parse(await readFile9(path2, "utf8"));
|
|
15871
16665
|
} catch {
|
|
15872
16666
|
return;
|
|
15873
16667
|
}
|
|
15874
16668
|
}
|
|
15875
16669
|
async function nativeVaultFileAbsent(path2) {
|
|
15876
16670
|
try {
|
|
15877
|
-
await
|
|
16671
|
+
await lstat7(path2);
|
|
15878
16672
|
return false;
|
|
15879
16673
|
} catch (error) {
|
|
15880
16674
|
if (error instanceof Error && "code" in error && error.code === "ENOENT")
|
|
@@ -16263,7 +17057,7 @@ function missing(error) {
|
|
|
16263
17057
|
return error instanceof Error && "code" in error && error.code === "ENOENT";
|
|
16264
17058
|
}
|
|
16265
17059
|
function checkPath(path2) {
|
|
16266
|
-
if (!
|
|
17060
|
+
if (!isAbsolute4(path2))
|
|
16267
17061
|
throw new NativeRuntimeError("unsafe-runtime");
|
|
16268
17062
|
}
|
|
16269
17063
|
async function readNativeRuntime(path2, storageId, ownership = {}) {
|
|
@@ -16273,10 +17067,10 @@ async function readNativeRuntime(path2, storageId, ownership = {}) {
|
|
|
16273
17067
|
const noFollow = constants2.O_NOFOLLOW ?? 0;
|
|
16274
17068
|
try {
|
|
16275
17069
|
for (let attempt = 0;attempt < 2; attempt++) {
|
|
16276
|
-
const info = await
|
|
17070
|
+
const info = await lstat8(path2);
|
|
16277
17071
|
if (!info.isFile() || !await isOwnerOnly(path2, () => (info.mode & 511) === 384 && (typeof process.geteuid !== "function" || info.uid === process.geteuid()), ownership))
|
|
16278
17072
|
throw new NativeRuntimeError("unsafe-runtime");
|
|
16279
|
-
const file = await
|
|
17073
|
+
const file = await open8(path2, constants2.O_RDONLY | noFollow);
|
|
16280
17074
|
try {
|
|
16281
17075
|
const opened = await file.stat();
|
|
16282
17076
|
if (!opened.isFile() || !await isOwnerOnly(path2, () => (opened.mode & 511) === 384 && (typeof process.geteuid !== "function" || opened.uid === process.geteuid()), ownership))
|
|
@@ -16395,7 +17189,7 @@ async function writeNativeRuntimeOutcome(path2, storageId, change, hooks, firstI
|
|
|
16395
17189
|
checkPath(path2);
|
|
16396
17190
|
const publication2 = capturePublicationOptions(hooks.publication);
|
|
16397
17191
|
try {
|
|
16398
|
-
await
|
|
17192
|
+
await mkdir10(dirname13(path2), { recursive: true, mode: 448 });
|
|
16399
17193
|
return await withLock2(path2, {
|
|
16400
17194
|
name: "native-runtime",
|
|
16401
17195
|
ttlMs: 1e4,
|
|
@@ -16409,11 +17203,11 @@ async function writeNativeRuntimeOutcome(path2, storageId, change, hooks, firstI
|
|
|
16409
17203
|
assertTransitions(current, next, firstIdentity);
|
|
16410
17204
|
const bytes = `${JSON.stringify(next, null, 2)}
|
|
16411
17205
|
`;
|
|
16412
|
-
const stage =
|
|
17206
|
+
const stage = join15(dirname13(path2), `${basename7(path2)}.native-runtime.${randomUUID13()}.partial`);
|
|
16413
17207
|
let ownsStage = false;
|
|
16414
17208
|
try {
|
|
16415
17209
|
const nativeCreated = await createWindowsOwnerOnly(stage, bytes);
|
|
16416
|
-
const file = await
|
|
17210
|
+
const file = await open8(stage, nativeCreated ? constants2.O_RDWR : "wx", 384);
|
|
16417
17211
|
ownsStage = true;
|
|
16418
17212
|
try {
|
|
16419
17213
|
if (!nativeCreated)
|
|
@@ -17710,7 +18504,7 @@ function insulaUsageTransport(options) {
|
|
|
17710
18504
|
})), 3000);
|
|
17711
18505
|
deadline.unref?.();
|
|
17712
18506
|
});
|
|
17713
|
-
const
|
|
18507
|
+
const open9 = (async () => {
|
|
17714
18508
|
const handshakeTimeoutMs = Math.min(options.handshakeTimeoutMs ?? 3000, 3000);
|
|
17715
18509
|
const connected = options.connector ? await options.connector({
|
|
17716
18510
|
connectionFile: options.connectionFile,
|
|
@@ -17732,7 +18526,7 @@ function insulaUsageTransport(options) {
|
|
|
17732
18526
|
subscription = connected.subscribe(route, { method: "usage.watch" }, onNotice);
|
|
17733
18527
|
})();
|
|
17734
18528
|
try {
|
|
17735
|
-
await Promise.race([
|
|
18529
|
+
await Promise.race([open9, timeout]);
|
|
17736
18530
|
} catch (error) {
|
|
17737
18531
|
stopped = true;
|
|
17738
18532
|
throw error;
|
|
@@ -18064,12 +18858,12 @@ var CUSTODY_PLACEHOLDER_PREFIX = "claustrum-tombstone:v1:";
|
|
|
18064
18858
|
|
|
18065
18859
|
// ../../node_modules/@cortexkit/common-auth/dist/claustrum/shutdown.js
|
|
18066
18860
|
function shutdownWarning(logger2, shutdown) {
|
|
18067
|
-
let
|
|
18861
|
+
let warned2 = false;
|
|
18068
18862
|
return (pendingOperations) => {
|
|
18069
|
-
if (
|
|
18863
|
+
if (warned2)
|
|
18070
18864
|
return;
|
|
18071
18865
|
if (!shutdown || shutdown.aborted)
|
|
18072
|
-
|
|
18866
|
+
warned2 = true;
|
|
18073
18867
|
logger2.warn("claustrum shutdown drain timed out", { pendingOperations });
|
|
18074
18868
|
};
|
|
18075
18869
|
}
|
|
@@ -18719,7 +19513,7 @@ function quotaFields(publication2, witness = "") {
|
|
|
18719
19513
|
}
|
|
18720
19514
|
|
|
18721
19515
|
// ../../node_modules/@cortexkit/common-auth/dist/claustrum/roster.js
|
|
18722
|
-
import { createHash as
|
|
19516
|
+
import { createHash as createHash14 } from "node:crypto";
|
|
18723
19517
|
import { stat as stat7 } from "node:fs/promises";
|
|
18724
19518
|
import { resolve as resolve8 } from "node:path";
|
|
18725
19519
|
|
|
@@ -18766,7 +19560,7 @@ function seedIndex(seed, row) {
|
|
|
18766
19560
|
}
|
|
18767
19561
|
var DEFAULT_ROUTE_PREFIX = "vault:";
|
|
18768
19562
|
function hash(value) {
|
|
18769
|
-
return
|
|
19563
|
+
return createHash14("sha256").update(value).digest("hex");
|
|
18770
19564
|
}
|
|
18771
19565
|
function defaultLabel(credential2) {
|
|
18772
19566
|
const parts = credential2.credentialId.split(":");
|
|
@@ -18917,15 +19711,15 @@ function vaultRoutingRows(roster) {
|
|
|
18917
19711
|
...row.quota !== undefined && { quota: row.quota }
|
|
18918
19712
|
}));
|
|
18919
19713
|
}
|
|
18920
|
-
function
|
|
19714
|
+
function isRecord11(value) {
|
|
18921
19715
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
18922
19716
|
}
|
|
18923
19717
|
function optionalString2(value) {
|
|
18924
19718
|
return value === undefined || typeof value === "string";
|
|
18925
19719
|
}
|
|
18926
19720
|
function decodeRow(value) {
|
|
18927
|
-
const quota2 =
|
|
18928
|
-
if (!
|
|
19721
|
+
const quota2 = isRecord11(value) ? decodeQuotaMap(value.quota) : undefined;
|
|
19722
|
+
if (!isRecord11(value) || typeof value.routeId !== "string" || typeof value.credentialId !== "string" || value.credentialType !== "oauth" && value.credentialType !== "api_key" || typeof value.state !== "string" || typeof value.label !== "string" || typeof value.enabled !== "boolean" || typeof value.addedAt !== "number" || !optionalString2(value.accountIdentity) || !optionalString2(value.email) || !optionalString2(value.orgName) || value.aliases !== undefined && (!Array.isArray(value.aliases) || !value.aliases.every((alias) => typeof alias === "string")) || value.quota !== undefined && quota2 === undefined || value.stale !== undefined && value.stale !== true || value.unclaimed !== undefined && value.unclaimed !== true)
|
|
18929
19723
|
return;
|
|
18930
19724
|
return {
|
|
18931
19725
|
...value,
|
|
@@ -18943,14 +19737,14 @@ function decodeRejected(value) {
|
|
|
18943
19737
|
return;
|
|
18944
19738
|
const records = [];
|
|
18945
19739
|
for (const entry2 of value) {
|
|
18946
|
-
if (!
|
|
19740
|
+
if (!isRecord11(entry2) || !optionalString2(entry2.credentialId) || typeof entry2.reason !== "string" || !SKIPPED_REASONS.has(entry2.reason))
|
|
18947
19741
|
return;
|
|
18948
19742
|
records.push(entry2);
|
|
18949
19743
|
}
|
|
18950
19744
|
return records;
|
|
18951
19745
|
}
|
|
18952
19746
|
function decodeRoster(value) {
|
|
18953
|
-
if (!
|
|
19747
|
+
if (!isRecord11(value) || value.version !== 1 || !optionalString2(value.view) || !Array.isArray(value.rows) || !Array.isArray(value.declined) || value.complete !== undefined && typeof value.complete !== "boolean" || value.rejected !== undefined && !decodeRejected(value.rejected))
|
|
18954
19748
|
throw new ClaustrumConsumerError("invalid-state", "Claustrum roster file is not valid");
|
|
18955
19749
|
const rows = [];
|
|
18956
19750
|
for (const entry2 of value.rows) {
|
|
@@ -18961,7 +19755,7 @@ function decodeRoster(value) {
|
|
|
18961
19755
|
}
|
|
18962
19756
|
const declined = [];
|
|
18963
19757
|
for (const entry2 of value.declined) {
|
|
18964
|
-
if (!
|
|
19758
|
+
if (!isRecord11(entry2) || typeof entry2.credentialId !== "string" || !optionalString2(entry2.accountIdentity))
|
|
18965
19759
|
throw new ClaustrumConsumerError("invalid-state", "Claustrum roster file is not valid");
|
|
18966
19760
|
declined.push(entry2);
|
|
18967
19761
|
}
|
|
@@ -20120,9 +20914,9 @@ class ClaustrumConsumer {
|
|
|
20120
20914
|
}
|
|
20121
20915
|
}
|
|
20122
20916
|
// ../../node_modules/@cortexkit/common-auth/dist/claustrum/hub.js
|
|
20123
|
-
import { createHash as
|
|
20917
|
+
import { createHash as createHash15 } from "node:crypto";
|
|
20124
20918
|
import { readdir as readdir3, stat as stat8 } from "node:fs/promises";
|
|
20125
|
-
import { join as
|
|
20919
|
+
import { dirname as dirname14, join as join16 } from "node:path";
|
|
20126
20920
|
var FILE_ID = /^[a-z0-9][a-z0-9._-]{0,63}$/;
|
|
20127
20921
|
var WINDOWS_DEVICE = /^(con|prn|aux|nul|com[0-9]|lpt[0-9])(\.|$)/;
|
|
20128
20922
|
var FINGERPRINT = /^[0-9a-f]{16}$/;
|
|
@@ -20168,7 +20962,7 @@ function rosterFingerprint(options, members) {
|
|
|
20168
20962
|
});
|
|
20169
20963
|
if (input === undefined)
|
|
20170
20964
|
throw new ClaustrumConsumerError("invalid-state", "Claustrum hub classifierInput must be plain JSON");
|
|
20171
|
-
return
|
|
20965
|
+
return createHash15("sha256").update(input).digest("hex").slice(0, 16);
|
|
20172
20966
|
}
|
|
20173
20967
|
function fileId(value, what) {
|
|
20174
20968
|
if (typeof value !== "string" || !FILE_ID.test(value) || WINDOWS_DEVICE.test(value))
|
|
@@ -20236,13 +21030,13 @@ class ClaustrumDiscoveryHub {
|
|
|
20236
21030
|
this.#options = options;
|
|
20237
21031
|
this.#logger = options.logger ?? createLogger("claustrum");
|
|
20238
21032
|
this.#warnShutdown = shutdownWarning(this.#logger, this.#shutdown.signal);
|
|
20239
|
-
this.#generationDirectory =
|
|
21033
|
+
this.#generationDirectory = join16(options.stateDir, "rosters", hostGeneration);
|
|
20240
21034
|
this.#key = rosterFingerprint(options, providers);
|
|
20241
|
-
const directory =
|
|
21035
|
+
const directory = join16(this.#generationDirectory, this.#key);
|
|
20242
21036
|
for (const provider of providers)
|
|
20243
21037
|
this.#members.set(provider, {
|
|
20244
21038
|
provider,
|
|
20245
|
-
path:
|
|
21039
|
+
path: join16(directory, `${provider}.json`),
|
|
20246
21040
|
closed: false
|
|
20247
21041
|
});
|
|
20248
21042
|
}
|
|
@@ -20590,9 +21384,13 @@ class ClaustrumDiscoveryHub {
|
|
|
20590
21384
|
run.generation = generation;
|
|
20591
21385
|
if (!this.#live(generation))
|
|
20592
21386
|
return;
|
|
20593
|
-
const
|
|
20594
|
-
|
|
20595
|
-
|
|
21387
|
+
const folders = await this.#ensureRosterDirectories().then(() => {
|
|
21388
|
+
return;
|
|
21389
|
+
}, (error) => error instanceof Error ? error : new Error(String(error)));
|
|
21390
|
+
const bases = new Map(await Promise.all([...this.#members.values()].map(async (entry2) => [
|
|
21391
|
+
entry2,
|
|
21392
|
+
await readVaultRoster(entry2.path).then((file) => file ? { file } : {}, (error) => error instanceof Error ? error : new Error(String(error)))
|
|
21393
|
+
])));
|
|
20596
21394
|
if (!this.#live(generation))
|
|
20597
21395
|
return;
|
|
20598
21396
|
let inventory;
|
|
@@ -20606,38 +21404,21 @@ class ClaustrumDiscoveryHub {
|
|
|
20606
21404
|
this.#markPending(entry2);
|
|
20607
21405
|
throw error;
|
|
20608
21406
|
}
|
|
21407
|
+
if (!this.#live(generation))
|
|
21408
|
+
return;
|
|
21409
|
+
const members = this.#open();
|
|
21410
|
+
const commits = await Promise.all(members.map((entry2) => entry2.hooks && !entry2.closed ? this.#commit(entry2, entry2.hooks, inventory, folders ?? bases.get(entry2), generation) : undefined));
|
|
21411
|
+
if (!this.#live(generation))
|
|
21412
|
+
return;
|
|
20609
21413
|
const errors = new Map;
|
|
20610
21414
|
let complete = true;
|
|
20611
|
-
for (const entry2 of
|
|
20612
|
-
if (!this.#live(generation))
|
|
20613
|
-
return;
|
|
21415
|
+
for (const [index, entry2] of members.entries()) {
|
|
20614
21416
|
const hooks = entry2.hooks;
|
|
20615
|
-
|
|
21417
|
+
const commit = commits[index];
|
|
21418
|
+
if (!hooks || !commit)
|
|
20616
21419
|
continue;
|
|
20617
|
-
|
|
20618
|
-
|
|
20619
|
-
credentials: inventory.credentials.filter((credential2) => credential2.member === entry2.provider),
|
|
20620
|
-
skipped: inventory.skipped.filter((record8) => record8.member === entry2.provider)
|
|
20621
|
-
};
|
|
20622
|
-
const base = bases.get(entry2);
|
|
20623
|
-
let roster;
|
|
20624
|
-
try {
|
|
20625
|
-
if (!base)
|
|
20626
|
-
throw closed("Claustrum hub member has no base view");
|
|
20627
|
-
if (base instanceof Error)
|
|
20628
|
-
throw base;
|
|
20629
|
-
const seed = base.file ? undefined : await this.#seed(entry2);
|
|
20630
|
-
roster = await refreshVaultRoster({
|
|
20631
|
-
path: entry2.path,
|
|
20632
|
-
custody: { discover: async () => share },
|
|
20633
|
-
isActive: () => this.#live(generation) && this.#active === true,
|
|
20634
|
-
signal: generation.controller.signal,
|
|
20635
|
-
projection: () => ({ ...hooks.projection(), ...seed && { seed } }),
|
|
20636
|
-
listedOver: { view: base.file?.view }
|
|
20637
|
-
});
|
|
20638
|
-
} catch (error) {
|
|
20639
|
-
if (!this.#live(generation))
|
|
20640
|
-
return;
|
|
21420
|
+
if ("error" in commit) {
|
|
21421
|
+
const { error } = commit;
|
|
20641
21422
|
complete = false;
|
|
20642
21423
|
this.#markPending(entry2);
|
|
20643
21424
|
if (isVaultRosterLockRefusal(entry2.path, error))
|
|
@@ -20648,6 +21429,7 @@ class ClaustrumDiscoveryHub {
|
|
|
20648
21429
|
errors.set(entry2.provider, error);
|
|
20649
21430
|
continue;
|
|
20650
21431
|
}
|
|
21432
|
+
const { roster } = commit;
|
|
20651
21433
|
if (!this.#live(generation))
|
|
20652
21434
|
return;
|
|
20653
21435
|
if (roster?.view !== inventory.view) {
|
|
@@ -20679,13 +21461,46 @@ class ClaustrumDiscoveryHub {
|
|
|
20679
21461
|
this.#discoveredAt = (this.#options.now ?? Date.now)();
|
|
20680
21462
|
return { errors };
|
|
20681
21463
|
}
|
|
21464
|
+
async#commit(entry2, hooks, inventory, base, generation) {
|
|
21465
|
+
const share = {
|
|
21466
|
+
...inventory,
|
|
21467
|
+
credentials: inventory.credentials.filter((credential2) => credential2.member === entry2.provider),
|
|
21468
|
+
skipped: inventory.skipped.filter((record8) => record8.member === entry2.provider)
|
|
21469
|
+
};
|
|
21470
|
+
try {
|
|
21471
|
+
if (!base)
|
|
21472
|
+
throw closed("Claustrum hub member has no base view");
|
|
21473
|
+
if (base instanceof Error)
|
|
21474
|
+
throw base;
|
|
21475
|
+
const seed = base.file ? undefined : await this.#seed(entry2);
|
|
21476
|
+
const roster = await refreshVaultRoster({
|
|
21477
|
+
path: entry2.path,
|
|
21478
|
+
custody: { discover: async () => share },
|
|
21479
|
+
isActive: () => this.#live(generation) && this.#active === true,
|
|
21480
|
+
signal: generation.controller.signal,
|
|
21481
|
+
projection: () => ({ ...hooks.projection(), ...seed && { seed } }),
|
|
21482
|
+
listedOver: { view: base.file?.view }
|
|
21483
|
+
});
|
|
21484
|
+
return { roster };
|
|
21485
|
+
} catch (error) {
|
|
21486
|
+
return { error };
|
|
21487
|
+
}
|
|
21488
|
+
}
|
|
21489
|
+
async#ensureRosterDirectories() {
|
|
21490
|
+
for (const directory of [
|
|
21491
|
+
dirname14(this.#generationDirectory),
|
|
21492
|
+
this.#generationDirectory,
|
|
21493
|
+
join16(this.#generationDirectory, this.#key)
|
|
21494
|
+
])
|
|
21495
|
+
await ensureClaustrumPrivateDirectory(directory, {}, "roster directory");
|
|
21496
|
+
}
|
|
20682
21497
|
async#seed(entry2) {
|
|
20683
21498
|
const name = `${entry2.provider}.json`;
|
|
20684
|
-
const candidates = [
|
|
21499
|
+
const candidates = [join16(this.#generationDirectory, name)];
|
|
20685
21500
|
try {
|
|
20686
21501
|
for (const key of await readdir3(this.#generationDirectory))
|
|
20687
21502
|
if (key !== this.#key && FINGERPRINT.test(key))
|
|
20688
|
-
candidates.push(
|
|
21503
|
+
candidates.push(join16(this.#generationDirectory, key, name));
|
|
20689
21504
|
} catch {}
|
|
20690
21505
|
let newest;
|
|
20691
21506
|
for (const path2 of candidates) {
|
|
@@ -20851,8 +21666,8 @@ class ClaustrumDiscoveryHub {
|
|
|
20851
21666
|
return this.#committed?.reach;
|
|
20852
21667
|
}
|
|
20853
21668
|
watchState() {
|
|
20854
|
-
const
|
|
20855
|
-
return
|
|
21669
|
+
const open9 = this.#watch;
|
|
21670
|
+
return open9 && this.#live(open9.generation) ? open9.watch.mode : "polling";
|
|
20856
21671
|
}
|
|
20857
21672
|
keptReceiptState() {
|
|
20858
21673
|
return this.#current?.custody?.keptReceiptState() ?? Object.freeze({ active: false, since: null });
|
|
@@ -21410,7 +22225,7 @@ function createNativeLocalRuntimeReaders(options) {
|
|
|
21410
22225
|
}
|
|
21411
22226
|
|
|
21412
22227
|
// src/native-refresh-coordinator.ts
|
|
21413
|
-
import { createHash as
|
|
22228
|
+
import { createHash as createHash16 } from "node:crypto";
|
|
21414
22229
|
|
|
21415
22230
|
// src/native-transient-account.ts
|
|
21416
22231
|
var TRANSIENT_ACCOUNT_MESSAGE = "Anthropic account update in progress; retry the request";
|
|
@@ -21512,7 +22327,7 @@ function pause(ms, signals) {
|
|
|
21512
22327
|
var NATIVE_REFRESH_MAX_ATTEMPTS = 3;
|
|
21513
22328
|
var NATIVE_REFRESH_JOIN_BUDGET_MS = 2000;
|
|
21514
22329
|
function nativeAccountProviderLock(paths, identity3) {
|
|
21515
|
-
const key =
|
|
22330
|
+
const key = createHash16("sha256").update(JSON.stringify([paths.storageId, identity3])).digest("hex");
|
|
21516
22331
|
return {
|
|
21517
22332
|
path: paths.state,
|
|
21518
22333
|
name: `native-account-provider-${key}`,
|
|
@@ -22309,12 +23124,12 @@ function createNativeRefreshCoordinator(options) {
|
|
|
22309
23124
|
}
|
|
22310
23125
|
|
|
22311
23126
|
// src/pool-authority.ts
|
|
22312
|
-
import { isAbsolute as
|
|
23127
|
+
import { isAbsolute as isAbsolute5, normalize, parse as parse3, sep } from "node:path";
|
|
22313
23128
|
|
|
22314
23129
|
// src/migration-source.ts
|
|
22315
|
-
import { createHash as
|
|
23130
|
+
import { createHash as createHash17 } from "node:crypto";
|
|
22316
23131
|
import { constants as constants3 } from "node:fs";
|
|
22317
|
-
import { lstat as
|
|
23132
|
+
import { lstat as lstat9, open as open9 } from "node:fs/promises";
|
|
22318
23133
|
class NativeMigrationSourceError extends Error {
|
|
22319
23134
|
role;
|
|
22320
23135
|
code;
|
|
@@ -22326,7 +23141,7 @@ class NativeMigrationSourceError extends Error {
|
|
|
22326
23141
|
}
|
|
22327
23142
|
}
|
|
22328
23143
|
var MAX_SOURCE_BYTES = 4 * 1024 * 1024;
|
|
22329
|
-
function
|
|
23144
|
+
function isRecord12(value) {
|
|
22330
23145
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
22331
23146
|
}
|
|
22332
23147
|
function freezeJson(root) {
|
|
@@ -22357,7 +23172,7 @@ async function readNativeMigrationSource(role, path2, hooks = {}) {
|
|
|
22357
23172
|
});
|
|
22358
23173
|
let initial;
|
|
22359
23174
|
try {
|
|
22360
|
-
initial = await
|
|
23175
|
+
initial = await lstat9(path2, { bigint: true });
|
|
22361
23176
|
} catch (error) {
|
|
22362
23177
|
if (error instanceof Error && "code" in error && error.code === "ENOENT")
|
|
22363
23178
|
return missing2;
|
|
@@ -22367,7 +23182,7 @@ async function readNativeMigrationSource(role, path2, hooks = {}) {
|
|
|
22367
23182
|
throw new NativeMigrationSourceError(role, "unsafe-source");
|
|
22368
23183
|
let handle;
|
|
22369
23184
|
try {
|
|
22370
|
-
handle = await
|
|
23185
|
+
handle = await open9(path2, constants3.O_RDONLY | (constants3.O_NOFOLLOW ?? 0) | (constants3.O_NONBLOCK ?? 0));
|
|
22371
23186
|
const before = await handle.stat({ bigint: true });
|
|
22372
23187
|
if (!before.isFile() || before.dev !== initial.dev || before.ino !== initial.ino) {
|
|
22373
23188
|
throw new NativeMigrationSourceError(role, "source-changed");
|
|
@@ -22395,7 +23210,7 @@ async function readNativeMigrationSource(role, path2, hooks = {}) {
|
|
|
22395
23210
|
chunks.push(chunk.subarray(0, read.bytesRead));
|
|
22396
23211
|
}
|
|
22397
23212
|
const after = await handle.stat({ bigint: true });
|
|
22398
|
-
const current = await
|
|
23213
|
+
const current = await lstat9(path2, { bigint: true });
|
|
22399
23214
|
if (before.uid !== after.uid || before.gid !== after.gid || before.mode !== after.mode || current.uid !== before.uid || current.gid !== before.gid || current.mode !== before.mode || before.dev !== after.dev || before.ino !== after.ino || before.mtimeNs !== after.mtimeNs || before.ctimeNs !== after.ctimeNs || before.size !== after.size || current.dev !== before.dev || current.ino !== before.ino || current.isSymbolicLink() || current.mtimeNs !== before.mtimeNs || current.ctimeNs !== before.ctimeNs || current.size !== before.size || BigInt(bytes) !== before.size) {
|
|
22400
23215
|
throw new NativeMigrationSourceError(role, "source-changed");
|
|
22401
23216
|
}
|
|
@@ -22406,12 +23221,12 @@ async function readNativeMigrationSource(role, path2, hooks = {}) {
|
|
|
22406
23221
|
} catch {
|
|
22407
23222
|
throw new NativeMigrationSourceError(role, "invalid-source");
|
|
22408
23223
|
}
|
|
22409
|
-
if (!
|
|
23224
|
+
if (!isRecord12(data))
|
|
22410
23225
|
throw new NativeMigrationSourceError(role, "invalid-source");
|
|
22411
23226
|
return sourceSnapshot({
|
|
22412
23227
|
role,
|
|
22413
23228
|
path: path2,
|
|
22414
|
-
digest:
|
|
23229
|
+
digest: createHash17("sha256").update(content).digest("hex"),
|
|
22415
23230
|
data: freezeJson(data),
|
|
22416
23231
|
metadata: Object.freeze({
|
|
22417
23232
|
uid: Number(before.uid),
|
|
@@ -22467,7 +23282,7 @@ class NativeAuthorityError extends Error {
|
|
|
22467
23282
|
this.name = "NativeAuthorityError";
|
|
22468
23283
|
}
|
|
22469
23284
|
}
|
|
22470
|
-
function
|
|
23285
|
+
function isRecord13(value) {
|
|
22471
23286
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
22472
23287
|
}
|
|
22473
23288
|
function captureJournalJson(value) {
|
|
@@ -22500,22 +23315,22 @@ function isHostEntry(value) {
|
|
|
22500
23315
|
return value === "absent" || isDigest(value);
|
|
22501
23316
|
}
|
|
22502
23317
|
function isCapturedPath(value) {
|
|
22503
|
-
return typeof value === "string" &&
|
|
23318
|
+
return typeof value === "string" && isAbsolute5(value) && !/\p{Cc}/u.test(value) && !value.endsWith(sep) && normalize(value) === value && (sep !== "\\" || parse3(value).root !== sep) && !value.split(sep).some((part) => part === "." || part === "..");
|
|
22504
23319
|
}
|
|
22505
23320
|
function isSources(value) {
|
|
22506
|
-
return
|
|
23321
|
+
return isRecord13(value) && hasKeys(value, ["config", "state", "hostAuth", "routing"]) && isFileDigest(value.config) && isFileDigest(value.state) && isHostEntry(value.hostAuth) && isFileDigest(value.routing);
|
|
22507
23322
|
}
|
|
22508
23323
|
function isRoutingPaths(value) {
|
|
22509
|
-
return
|
|
23324
|
+
return isRecord13(value) && hasKeys(value, ["source", "destination"]) && isCapturedPath(value.source) && isCapturedPath(value.destination);
|
|
22510
23325
|
}
|
|
22511
23326
|
function isText(value) {
|
|
22512
23327
|
return typeof value === "string" && value.length > 0;
|
|
22513
23328
|
}
|
|
22514
23329
|
function decodeRoster2(value) {
|
|
22515
|
-
if (!
|
|
23330
|
+
if (!isRecord13(value) || !hasKeys(value, ["version", "view", "complete", "rows", "declined"]) || value.version !== 1 || !isText(value.view) || value.complete !== true || !Array.isArray(value.rows) || !Array.isArray(value.declined))
|
|
22516
23331
|
throw new NativeAuthorityError("invalid-journal");
|
|
22517
23332
|
const rows = value.rows.map((row) => {
|
|
22518
|
-
if (!
|
|
23333
|
+
if (!isRecord13(row) || !hasKeys(row, [
|
|
22519
23334
|
"routeId",
|
|
22520
23335
|
"credentialId",
|
|
22521
23336
|
"credentialType",
|
|
@@ -22538,7 +23353,7 @@ function decodeRoster2(value) {
|
|
|
22538
23353
|
};
|
|
22539
23354
|
});
|
|
22540
23355
|
const declined = value.declined.map((entry2) => {
|
|
22541
|
-
if (!
|
|
23356
|
+
if (!isRecord13(entry2) || !isText(entry2.credentialId) || !(hasKeys(entry2, ["credentialId"]) || hasKeys(entry2, ["credentialId", "accountIdentity"]) && isText(entry2.accountIdentity)))
|
|
22542
23357
|
throw new NativeAuthorityError("invalid-journal");
|
|
22543
23358
|
return isText(entry2.accountIdentity) ? {
|
|
22544
23359
|
credentialId: entry2.credentialId,
|
|
@@ -22550,7 +23365,7 @@ function decodeRoster2(value) {
|
|
|
22550
23365
|
return { version: 1, view: value.view, complete: true, rows, declined };
|
|
22551
23366
|
}
|
|
22552
23367
|
function decodeDigestPair(value, keys4, valid) {
|
|
22553
|
-
if (!
|
|
23368
|
+
if (!isRecord13(value) || !hasKeys(value, [...keys4]) || !keys4.every((key) => valid(value[key])))
|
|
22554
23369
|
throw new NativeAuthorityError("invalid-journal");
|
|
22555
23370
|
return Object.fromEntries(keys4.map((key) => [key, value[key]]));
|
|
22556
23371
|
}
|
|
@@ -22558,7 +23373,7 @@ var ACTIVATION_PHASES = ["prepared", "published", "committed"];
|
|
|
22558
23373
|
function decodeActivation(value, phase) {
|
|
22559
23374
|
if (value === null)
|
|
22560
23375
|
return null;
|
|
22561
|
-
if (!
|
|
23376
|
+
if (!isRecord13(value))
|
|
22562
23377
|
throw new NativeAuthorityError("invalid-journal");
|
|
22563
23378
|
if (value.kind === "requested" && hasKeys(value, ["kind"]))
|
|
22564
23379
|
return { kind: "requested" };
|
|
@@ -22572,7 +23387,7 @@ function decodeActivation(value, phase) {
|
|
|
22572
23387
|
"settings",
|
|
22573
23388
|
"runtime",
|
|
22574
23389
|
"hostAuth"
|
|
22575
|
-
]) || !ACTIVATION_PHASES.some((item) => item === value.phase) || !
|
|
23390
|
+
]) || !ACTIVATION_PHASES.some((item) => item === value.phase) || !isRecord13(value.primary) || !hasKeys(value.primary, ["routeId", "credentialId", "accountIdentity"]) || !isText(value.primary.routeId) || !isText(value.primary.credentialId) || !isText(value.primary.accountIdentity) || !Array.isArray(value.removeIds) || !value.removeIds.every(isText))
|
|
22576
23391
|
throw new NativeAuthorityError("invalid-journal");
|
|
22577
23392
|
const primary = {
|
|
22578
23393
|
routeId: value.primary.routeId,
|
|
@@ -22599,7 +23414,7 @@ function decodeActivation(value, phase) {
|
|
|
22599
23414
|
}
|
|
22600
23415
|
function decodeJournal(input, storageId) {
|
|
22601
23416
|
const value = captureJournalJson(input);
|
|
22602
|
-
if (!
|
|
23417
|
+
if (!isRecord13(value) || value.storageId !== storageId)
|
|
22603
23418
|
throw new NativeAuthorityError("invalid-journal");
|
|
22604
23419
|
if (value.version === 5 && value.kind === "empty-init") {
|
|
22605
23420
|
if (!hasKeys(value, ["version", "kind", "storageId", "host", "phase"]) || value.host !== "opencode" || value.phase !== "committed")
|
|
@@ -22784,7 +23599,7 @@ async function beginNativeMigration(paths, input, hooks = {}, replaces) {
|
|
|
22784
23599
|
}
|
|
22785
23600
|
async function recordNativeMigrationExpectations(paths, expectations, hooks = {}) {
|
|
22786
23601
|
const captured = captureJournalJson(expectations);
|
|
22787
|
-
if (!
|
|
23602
|
+
if (!isRecord13(captured) || !hasKeys(captured, [
|
|
22788
23603
|
"expectedHostAuth",
|
|
22789
23604
|
"expectedRouting",
|
|
22790
23605
|
"preparedProof"
|
|
@@ -22859,7 +23674,7 @@ function journalLock(hooks) {
|
|
|
22859
23674
|
}
|
|
22860
23675
|
async function recordNativeCustodyActivation(paths, plan, hooks = {}) {
|
|
22861
23676
|
const captured = captureJournalJson(plan);
|
|
22862
|
-
if (!
|
|
23677
|
+
if (!isRecord13(captured) || captured.phase !== "prepared")
|
|
22863
23678
|
throw new NativeAuthorityError("journal-conflict");
|
|
22864
23679
|
const decoded = decodeActivation(captured, "retired");
|
|
22865
23680
|
if (decoded?.kind !== "activation")
|
|
@@ -23435,43 +24250,8 @@ class NativeRuntimeRegistry {
|
|
|
23435
24250
|
}
|
|
23436
24251
|
}
|
|
23437
24252
|
|
|
23438
|
-
// src/native-vault-paths.ts
|
|
23439
|
-
import { createHash as createHash16 } from "node:crypto";
|
|
23440
|
-
import { basename as basename5, dirname as dirname11, join as join14 } from "node:path";
|
|
23441
|
-
function sibling(path2, expected, name, suffix) {
|
|
23442
|
-
return basename5(path2) === expected ? join14(dirname11(path2), name) : path2.replace(/(?:\.json)?$/, `.${suffix}.json`);
|
|
23443
|
-
}
|
|
23444
|
-
function nativeVaultPaths(local) {
|
|
23445
|
-
const config = sibling(local.legacyConfig, "anthropic-auth.json", "anthropic-auth-vault-settings.json", "vault-settings");
|
|
23446
|
-
const state = sibling(local.legacyState, "anthropic-auth-state.json", "anthropic-auth-vault-store-state.json", "vault-store");
|
|
23447
|
-
const runtime2 = sibling(local.legacyState, "anthropic-auth-state.json", "anthropic-auth-vault-state.json", "vault-native");
|
|
23448
|
-
const roster = sibling(local.legacyState, "anthropic-auth-state.json", "anthropic-auth-vault-roster.json", "vault-roster");
|
|
23449
|
-
const routing = sibling(local.legacyState, "anthropic-auth-state.json", "anthropic-auth-vault-routing-state.json", "vault-routing");
|
|
23450
|
-
const destinations = [config, state, runtime2, roster, routing];
|
|
23451
|
-
const localFiles = [
|
|
23452
|
-
local.legacyConfig,
|
|
23453
|
-
local.legacyState,
|
|
23454
|
-
local.config,
|
|
23455
|
-
local.state,
|
|
23456
|
-
local.runtime,
|
|
23457
|
-
local.journal,
|
|
23458
|
-
local.roster
|
|
23459
|
-
];
|
|
23460
|
-
if (new Set([...localFiles, ...destinations]).size !== localFiles.length + destinations.length)
|
|
23461
|
-
throw new Error("Vault storage overlaps local account storage");
|
|
23462
|
-
return {
|
|
23463
|
-
legacySeedConfig: local.legacyConfig,
|
|
23464
|
-
config,
|
|
23465
|
-
state,
|
|
23466
|
-
runtime: runtime2,
|
|
23467
|
-
roster,
|
|
23468
|
-
routing,
|
|
23469
|
-
storageId: createHash16("sha256").update(JSON.stringify(["anthropic-vault", config, state])).digest("hex")
|
|
23470
|
-
};
|
|
23471
|
-
}
|
|
23472
|
-
|
|
23473
24253
|
// src/native-vault-runtime.ts
|
|
23474
|
-
import { randomUUID as
|
|
24254
|
+
import { randomUUID as randomUUID14 } from "node:crypto";
|
|
23475
24255
|
import { SubcClient as SubcClient2 } from "@cortexkit/subc-client";
|
|
23476
24256
|
|
|
23477
24257
|
// src/insula-quota.ts
|
|
@@ -24753,7 +25533,7 @@ function nativeDisplayProfile(profile2, publish, isCurrent) {
|
|
|
24753
25533
|
}
|
|
24754
25534
|
async function publishNativeVaultRosterSeed(paths, input, options = {}) {
|
|
24755
25535
|
const seed = buildNativeVaultRosterSeed(input);
|
|
24756
|
-
const
|
|
25536
|
+
const published2 = await mutateVaultRoster(paths.roster, async (current, lease) => {
|
|
24757
25537
|
if (current) {
|
|
24758
25538
|
validateNativeVaultRosterSeed(current, input);
|
|
24759
25539
|
await options.assertOwned?.();
|
|
@@ -24764,7 +25544,7 @@ async function publishNativeVaultRosterSeed(paths, input, options = {}) {
|
|
|
24764
25544
|
return { next: seed, result: seed };
|
|
24765
25545
|
}, { beforePublish: options.assertOwned });
|
|
24766
25546
|
retainNativeVaultRoster(paths.roster, await readVaultRoster(paths.roster));
|
|
24767
|
-
return
|
|
25547
|
+
return published2;
|
|
24768
25548
|
}
|
|
24769
25549
|
async function publishNativeVaultRuntimeSeed(paths, state, options = {}) {
|
|
24770
25550
|
const imported = decodeNativeRuntime(captureNativePlainData(state), paths.storageId);
|
|
@@ -24831,6 +25611,7 @@ function createNativeVaultRuntime(options) {
|
|
|
24831
25611
|
onLockEvent: options.onLockEvent
|
|
24832
25612
|
});
|
|
24833
25613
|
const observeLock = nativeLockObserver(options.onLockEvent);
|
|
25614
|
+
const relocation = nativeRelocationGuard(options.paths);
|
|
24834
25615
|
let rosterWatch;
|
|
24835
25616
|
let rosterWatching = false;
|
|
24836
25617
|
let rosterView;
|
|
@@ -25070,6 +25851,7 @@ function createNativeVaultRuntime(options) {
|
|
|
25070
25851
|
onLockEvent: options.onLockEvent,
|
|
25071
25852
|
onStep: async (point) => {
|
|
25072
25853
|
if (point === "before-config-write" || point === "before-state-write") {
|
|
25854
|
+
await relocation.assertNotRelocated();
|
|
25073
25855
|
await assertPrimary();
|
|
25074
25856
|
}
|
|
25075
25857
|
}
|
|
@@ -25171,7 +25953,7 @@ function createNativeVaultRuntime(options) {
|
|
|
25171
25953
|
path: paths.roster,
|
|
25172
25954
|
custody: options.discover ? { discover: options.discover } : custody,
|
|
25173
25955
|
signal: shutdown.signal,
|
|
25174
|
-
isActive: active,
|
|
25956
|
+
isActive: async () => await active() && !await relocation.isRelocated(),
|
|
25175
25957
|
projection: () => ({ reservedRouteIds })
|
|
25176
25958
|
}).then(async (roster) => {
|
|
25177
25959
|
retainNativeVaultRoster(paths.roster, roster);
|
|
@@ -25206,6 +25988,7 @@ function createNativeVaultRuntime(options) {
|
|
|
25206
25988
|
throw new NativeCustodyError("identity-changed");
|
|
25207
25989
|
if (!nativeAccountCanServe(current))
|
|
25208
25990
|
throw new NativeCustodyError("not-active");
|
|
25991
|
+
await relocation.assertNotRelocated();
|
|
25209
25992
|
check(combined);
|
|
25210
25993
|
issued.set(receipt, { routeId: row.routeId, logicalId });
|
|
25211
25994
|
const key = JSON.stringify([
|
|
@@ -25289,7 +26072,7 @@ function createNativeVaultRuntime(options) {
|
|
|
25289
26072
|
async getOrCreateAuthLineage(receipt) {
|
|
25290
26073
|
let lineage;
|
|
25291
26074
|
const kept = await mutateReceipt(receipt, (old) => {
|
|
25292
|
-
lineage = old.authLineageId ??
|
|
26075
|
+
lineage = old.authLineageId ?? randomUUID14();
|
|
25293
26076
|
return { ...old, authLineageId: lineage };
|
|
25294
26077
|
});
|
|
25295
26078
|
return kept ? lineage : undefined;
|
|
@@ -25402,7 +26185,8 @@ function createNativeVaultRuntime(options) {
|
|
|
25402
26185
|
const row = await rowFor(roster, routeId);
|
|
25403
26186
|
if (!row)
|
|
25404
26187
|
throw new NativeCustodyError("route-unavailable");
|
|
25405
|
-
const changed = await mutateVaultRoster(paths.roster, (current) => {
|
|
26188
|
+
const changed = await mutateVaultRoster(paths.roster, async (current) => {
|
|
26189
|
+
await relocation.assertNotRelocated();
|
|
25406
26190
|
const held = current?.rows.find((entry2) => entry2.routeId === row.routeId);
|
|
25407
26191
|
if (!current || !held)
|
|
25408
26192
|
throw new ClaustrumConsumerError("route-unavailable", "Claustrum route is not in the roster");
|
|
@@ -25680,14 +26464,14 @@ function leaseNativeVaultRuntime(use, close) {
|
|
|
25680
26464
|
}
|
|
25681
26465
|
|
|
25682
26466
|
// src/pool-paths.ts
|
|
25683
|
-
import { createHash as
|
|
26467
|
+
import { createHash as createHash19 } from "node:crypto";
|
|
25684
26468
|
import { realpath as realpath3 } from "node:fs/promises";
|
|
25685
|
-
import { basename as
|
|
26469
|
+
import { basename as basename9, dirname as dirname16, join as join18, resolve as resolve12 } from "node:path";
|
|
25686
26470
|
|
|
25687
26471
|
// src/sticky-routing.ts
|
|
25688
|
-
import { createHash as
|
|
25689
|
-
import { mkdir as
|
|
25690
|
-
import { basename as
|
|
26472
|
+
import { createHash as createHash18, randomUUID as randomUUID15 } from "node:crypto";
|
|
26473
|
+
import { mkdir as mkdir11, readFile as readFile10, rename as rename12, rm as rm7, stat as stat9, writeFile as writeFile4 } from "node:fs/promises";
|
|
26474
|
+
import { basename as basename8, dirname as dirname15, join as join17 } from "node:path";
|
|
25691
26475
|
var STICKY_ROUTING_MAIN_ACCOUNT_ID = "main";
|
|
25692
26476
|
var STICKY_ROUTING_SHORT_RESET_GRACE_MS = 15 * 60000;
|
|
25693
26477
|
var STICKY_ROUTING_ASSIGNMENT_TTL_MS = 7 * 24 * 60 * 60000;
|
|
@@ -25737,14 +26521,14 @@ function createStickyNoRouteResponse(input) {
|
|
|
25737
26521
|
}
|
|
25738
26522
|
});
|
|
25739
26523
|
}
|
|
25740
|
-
function
|
|
26524
|
+
function isRecord14(value) {
|
|
25741
26525
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
25742
26526
|
}
|
|
25743
26527
|
function finiteNumber(value) {
|
|
25744
26528
|
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
25745
26529
|
}
|
|
25746
26530
|
function normalizeAssignment(value) {
|
|
25747
|
-
if (!
|
|
26531
|
+
if (!isRecord14(value))
|
|
25748
26532
|
return;
|
|
25749
26533
|
if (typeof value.accountId !== "string" || !["fable", "opus", "general"].includes(String(value.family))) {
|
|
25750
26534
|
return;
|
|
@@ -25773,7 +26557,7 @@ function normalizeAssignment(value) {
|
|
|
25773
26557
|
};
|
|
25774
26558
|
}
|
|
25775
26559
|
function normalizeState(value) {
|
|
25776
|
-
if (!
|
|
26560
|
+
if (!isRecord14(value) || value.version !== 1 || !isRecord14(value.assignments)) {
|
|
25777
26561
|
return;
|
|
25778
26562
|
}
|
|
25779
26563
|
const assignments = {};
|
|
@@ -25791,7 +26575,7 @@ function normalizeState(value) {
|
|
|
25791
26575
|
}
|
|
25792
26576
|
function migrateStickyRoutingState(source2, rowIdMap) {
|
|
25793
26577
|
try {
|
|
25794
|
-
if (!
|
|
26578
|
+
if (!isRecord14(source2) || !isRecord14(source2.assignments))
|
|
25795
26579
|
throw new Error;
|
|
25796
26580
|
const entries = Object.entries(source2.assignments);
|
|
25797
26581
|
const state = normalizeState({
|
|
@@ -25809,7 +26593,7 @@ function migrateStickyRoutingState(source2, rowIdMap) {
|
|
|
25809
26593
|
const assignments = Object.create(null);
|
|
25810
26594
|
for (const [index, [key, original]] of entries.entries()) {
|
|
25811
26595
|
const assignment = state.assignments[String(index)];
|
|
25812
|
-
if (!
|
|
26596
|
+
if (!isRecord14(original) || !assignment)
|
|
25813
26597
|
throw new Error;
|
|
25814
26598
|
const fields2 = Object.keys(assignment).filter((field) => field !== "affinityModelId" || Object.hasOwn(original, "affinityModelId"));
|
|
25815
26599
|
if (Object.keys(original).length !== fields2.length || fields2.some((field) => !Object.hasOwn(original, field) || !Object.is(original[field], Reflect.get(assignment, field)))) {
|
|
@@ -25830,7 +26614,7 @@ function emptyState(now) {
|
|
|
25830
26614
|
return { version: 1, updatedAt: now, assignments: {} };
|
|
25831
26615
|
}
|
|
25832
26616
|
function sessionKey(sessionId) {
|
|
25833
|
-
return
|
|
26617
|
+
return createHash18("sha256").update(sessionId).digest("hex");
|
|
25834
26618
|
}
|
|
25835
26619
|
function stickyQuotaSnapshotIsFresh(quota2, storage, now = Date.now(), modelId) {
|
|
25836
26620
|
const maxAge = getQuotaCheckIntervalMs(storage);
|
|
@@ -25938,12 +26722,12 @@ function decideStickyQuotaFailure(input) {
|
|
|
25938
26722
|
return { action: "migrate", reason: blocking.reason };
|
|
25939
26723
|
}
|
|
25940
26724
|
function getStickyRoutingStatePath(accountStoragePath) {
|
|
25941
|
-
const name =
|
|
26725
|
+
const name = basename8(accountStoragePath);
|
|
25942
26726
|
const stem = name.endsWith(".json") ? name.slice(0, -5) : name;
|
|
25943
|
-
return
|
|
26727
|
+
return join17(dirname15(accountStoragePath), `${stem}-routing-state.json`);
|
|
25944
26728
|
}
|
|
25945
26729
|
function stickyRetryAfterWithJitter(sessionId, retryAfterSeconds) {
|
|
25946
|
-
const hash2 =
|
|
26730
|
+
const hash2 = createHash18("sha256").update(sessionId).digest().readUInt32BE(0);
|
|
25947
26731
|
return Math.max(1, Math.ceil(retryAfterSeconds)) + hash2 % 21;
|
|
25948
26732
|
}
|
|
25949
26733
|
var localRecoveries = new Map;
|
|
@@ -25966,7 +26750,7 @@ class StickySessionRouter {
|
|
|
25966
26750
|
}
|
|
25967
26751
|
async readState() {
|
|
25968
26752
|
try {
|
|
25969
|
-
const raw = await
|
|
26753
|
+
const raw = await readFile10(this.options.path, "utf8");
|
|
25970
26754
|
const normalized = normalizeState(JSON.parse(raw));
|
|
25971
26755
|
if (!normalized) {
|
|
25972
26756
|
throw new Error(`Invalid sticky routing state at ${this.options.path}`);
|
|
@@ -26015,7 +26799,7 @@ class StickySessionRouter {
|
|
|
26015
26799
|
const observer = nativeLockObserver(this.options.onLockEvent);
|
|
26016
26800
|
const event = { name: "write", path: this.options.path, detached };
|
|
26017
26801
|
observer?.({ ...event, type: "acquiring" });
|
|
26018
|
-
await
|
|
26802
|
+
await mkdir11(dirname15(this.options.path), { recursive: true, mode: 448 });
|
|
26019
26803
|
const deadline = performance.now() + STICKY_ROUTING_LOCK_WAIT_MS;
|
|
26020
26804
|
while (true) {
|
|
26021
26805
|
const lock = await acquireRefreshFileLock2({
|
|
@@ -26063,7 +26847,7 @@ class StickySessionRouter {
|
|
|
26063
26847
|
try {
|
|
26064
26848
|
let legacy;
|
|
26065
26849
|
try {
|
|
26066
|
-
legacy = normalizeState(JSON.parse(await
|
|
26850
|
+
legacy = normalizeState(JSON.parse(await readFile10(source2, "utf8")));
|
|
26067
26851
|
} catch (error) {
|
|
26068
26852
|
if (error.code === "ENOENT")
|
|
26069
26853
|
return;
|
|
@@ -26102,10 +26886,11 @@ class StickySessionRouter {
|
|
|
26102
26886
|
});
|
|
26103
26887
|
}
|
|
26104
26888
|
async writeState(state, beforeRename, prune = true) {
|
|
26889
|
+
await this.options.relocationGuard?.assertNotRelocated();
|
|
26105
26890
|
if (prune)
|
|
26106
26891
|
this.prune(state);
|
|
26107
26892
|
state.updatedAt = this.now();
|
|
26108
|
-
const tempPath = `${this.options.path}.${
|
|
26893
|
+
const tempPath = `${this.options.path}.${randomUUID15()}.tmp`;
|
|
26109
26894
|
try {
|
|
26110
26895
|
await writeFile4(tempPath, `${JSON.stringify(state)}
|
|
26111
26896
|
`, { mode: 384 });
|
|
@@ -26156,7 +26941,7 @@ class StickySessionRouter {
|
|
|
26156
26941
|
const source2 = await readNativeVaultLegacyJson(seed.legacyConfig);
|
|
26157
26942
|
const routes = nativeVaultLegacyRoutes(source2, roster);
|
|
26158
26943
|
const legacy = await readNativeVaultLegacyJson(getStickyRoutingStatePath(seed.legacyConfig));
|
|
26159
|
-
if (
|
|
26944
|
+
if (isRecord14(legacy) && legacy.version === 1 && isRecord14(legacy.assignments)) {
|
|
26160
26945
|
for (const [key, raw] of Object.entries(legacy.assignments)) {
|
|
26161
26946
|
if (!/^[0-9a-f]{64}$/.test(key) || Object.hasOwn(state.assignments, key))
|
|
26162
26947
|
continue;
|
|
@@ -26415,24 +27200,34 @@ async function canonicalPath(path2) {
|
|
|
26415
27200
|
throw error;
|
|
26416
27201
|
}
|
|
26417
27202
|
}
|
|
26418
|
-
const parent =
|
|
27203
|
+
const parent = dirname16(absolute);
|
|
26419
27204
|
if (parent === absolute)
|
|
26420
27205
|
return absolute;
|
|
26421
|
-
return
|
|
27206
|
+
return join18(await canonicalPath(parent), basename9(absolute));
|
|
26422
27207
|
}
|
|
26423
27208
|
function sibling2(path2, legacyName, name, suffix) {
|
|
26424
|
-
return
|
|
27209
|
+
return basename9(path2) === legacyName ? join18(dirname16(path2), name) : `${path2}.${suffix}.json`;
|
|
26425
27210
|
}
|
|
26426
|
-
async function resolveNativePoolPaths(legacyConfig = getAccountStoragePath(), legacyState = getAccountStatePath(legacyConfig)) {
|
|
27211
|
+
async function resolveNativePoolPaths(legacyConfig = getAccountStoragePath(), legacyState = getAccountStatePath(legacyConfig), layout = processStateLayout()) {
|
|
26427
27212
|
const [sourceConfig, sourceState] = await Promise.all([
|
|
26428
27213
|
canonicalPath(legacyConfig),
|
|
26429
27214
|
canonicalPath(legacyState)
|
|
26430
27215
|
]);
|
|
26431
27216
|
const config = await canonicalPath(sibling2(sourceConfig, "anthropic-auth.json", "anthropic-auth-pool.json", "pool"));
|
|
26432
|
-
const
|
|
26433
|
-
|
|
26434
|
-
|
|
26435
|
-
|
|
27217
|
+
const legacyLayoutState = await canonicalPath(sibling2(sourceState, "anthropic-auth-state.json", "anthropic-auth-pool-state.json", "pool"));
|
|
27218
|
+
let state = legacyLayoutState;
|
|
27219
|
+
let runtime2 = await canonicalPath(sibling2(sourceState, "anthropic-auth-state.json", "anthropic-auth-native-state.json", "native"));
|
|
27220
|
+
let journal = await canonicalPath(sibling2(sourceState, "anthropic-auth-state.json", "anthropic-auth-migration.json", "migration"));
|
|
27221
|
+
let roster = await canonicalPath(sibling2(sourceState, "anthropic-auth-state.json", "anthropic-auth-custody-roster.json", "roster"));
|
|
27222
|
+
if (layout.kind === "state-home") {
|
|
27223
|
+
const moved = stateHomeDatasetFiles(layout, sourceConfig, sourceState);
|
|
27224
|
+
[state, runtime2, journal, roster] = await Promise.all([
|
|
27225
|
+
canonicalPath(moved.localPoolState),
|
|
27226
|
+
canonicalPath(moved.localRuntime),
|
|
27227
|
+
canonicalPath(moved.journal),
|
|
27228
|
+
canonicalPath(moved.localRoster)
|
|
27229
|
+
]);
|
|
27230
|
+
}
|
|
26436
27231
|
const paths = [
|
|
26437
27232
|
sourceConfig,
|
|
26438
27233
|
sourceState,
|
|
@@ -26445,7 +27240,7 @@ async function resolveNativePoolPaths(legacyConfig = getAccountStoragePath(), le
|
|
|
26445
27240
|
if (new Set(paths).size !== paths.length) {
|
|
26446
27241
|
throw new Error("Anthropic account storage paths overlap; migration requires separate files");
|
|
26447
27242
|
}
|
|
26448
|
-
const storageId =
|
|
27243
|
+
const storageId = createHash19("sha256").update(JSON.stringify(["anthropic", config, legacyLayoutState])).digest("hex");
|
|
26449
27244
|
return {
|
|
26450
27245
|
legacyConfig: sourceConfig,
|
|
26451
27246
|
legacyState: sourceState,
|
|
@@ -26460,7 +27255,7 @@ async function resolveNativePoolPaths(legacyConfig = getAccountStoragePath(), le
|
|
|
26460
27255
|
|
|
26461
27256
|
// src/relay.ts
|
|
26462
27257
|
import { Buffer as Buffer3 } from "node:buffer";
|
|
26463
|
-
import { createHash as
|
|
27258
|
+
import { createHash as createHash20, randomBytes as randomBytes5 } from "node:crypto";
|
|
26464
27259
|
var WEBSOCKET_RELAY_URL = /^wss?:\/\//i;
|
|
26465
27260
|
function effectiveRelayTransport(stored, url) {
|
|
26466
27261
|
if (stored === "http" || stored === "websocket")
|
|
@@ -26611,7 +27406,7 @@ function generateRelayToken() {
|
|
|
26611
27406
|
return randomBytes5(32).toString("base64url");
|
|
26612
27407
|
}
|
|
26613
27408
|
function hashBody(body) {
|
|
26614
|
-
return `sha256:${
|
|
27409
|
+
return `sha256:${createHash20("sha256").update(body).digest("hex")}`;
|
|
26615
27410
|
}
|
|
26616
27411
|
function createStringPatch(previous, next) {
|
|
26617
27412
|
let start = 0;
|
|
@@ -28079,10 +28874,12 @@ function acquireNativeAccountRuntime(options) {
|
|
|
28079
28874
|
const vault = leaseNativeVaultRuntime(() => use().vault, close);
|
|
28080
28875
|
const quotaObservations = use().quotaObservations;
|
|
28081
28876
|
const onLockEvent = use().onLockEvent;
|
|
28877
|
+
const relocationGuard = use().relocationGuard;
|
|
28082
28878
|
const drainRoutingPublications = use().drainRoutingPublications;
|
|
28083
28879
|
const drainQuotaPublications = use().drainQuotaPublications;
|
|
28084
28880
|
return {
|
|
28085
28881
|
onLockEvent,
|
|
28882
|
+
relocationGuard,
|
|
28086
28883
|
vault,
|
|
28087
28884
|
quotaObservations,
|
|
28088
28885
|
drainQuotaPublications,
|
|
@@ -28135,6 +28932,7 @@ function createNativeAccountRuntime(options) {
|
|
|
28135
28932
|
const now = options.local?.now ?? options.vault?.now ?? Date.now;
|
|
28136
28933
|
const env = { ...options.vault?.env ?? process.env };
|
|
28137
28934
|
const vaultPaths = nativeVaultPaths(paths);
|
|
28935
|
+
const relocation = nativeRelocationGuard(paths);
|
|
28138
28936
|
const routingSeed = {
|
|
28139
28937
|
legacyConfig: paths.legacyConfig,
|
|
28140
28938
|
roster: vaultPaths.roster
|
|
@@ -28143,7 +28941,8 @@ function createNativeAccountRuntime(options) {
|
|
|
28143
28941
|
path: vaultPaths.routing,
|
|
28144
28942
|
vaultSeed: routingSeed,
|
|
28145
28943
|
onLockEvent,
|
|
28146
|
-
now
|
|
28944
|
+
now,
|
|
28945
|
+
relocationGuard: relocation
|
|
28147
28946
|
});
|
|
28148
28947
|
let settingsBootstrap;
|
|
28149
28948
|
const vaultStore = createNativePoolStore({
|
|
@@ -28152,8 +28951,10 @@ function createNativeAccountRuntime(options) {
|
|
|
28152
28951
|
now,
|
|
28153
28952
|
onLockEvent: options.local?.onLockEvent,
|
|
28154
28953
|
onStep: async (point) => {
|
|
28155
|
-
if (point === "before-config-write" || point === "before-state-write")
|
|
28954
|
+
if (point === "before-config-write" || point === "before-state-write") {
|
|
28955
|
+
await relocation.assertNotRelocated();
|
|
28156
28956
|
await requireMode("claustrum");
|
|
28957
|
+
}
|
|
28157
28958
|
}
|
|
28158
28959
|
});
|
|
28159
28960
|
const shutdown = new AbortController;
|
|
@@ -28356,7 +29157,7 @@ function createNativeAccountRuntime(options) {
|
|
|
28356
29157
|
const sameAccount = old?.kind === "local" && old.rowId === binding2.rowId && binding2.identity !== undefined && old.identity === binding2.identity;
|
|
28357
29158
|
const next = {
|
|
28358
29159
|
binding: binding2,
|
|
28359
|
-
...row.credential?.type === "oauth" ? { authLineageId:
|
|
29160
|
+
...row.credential?.type === "oauth" ? { authLineageId: randomUUID16() } : {}
|
|
28360
29161
|
};
|
|
28361
29162
|
if (sameAccount && previous) {
|
|
28362
29163
|
for (const key of [
|
|
@@ -28460,6 +29261,7 @@ function createNativeAccountRuntime(options) {
|
|
|
28460
29261
|
}
|
|
28461
29262
|
const runtime2 = {
|
|
28462
29263
|
onLockEvent,
|
|
29264
|
+
relocationGuard: relocation,
|
|
28463
29265
|
vault,
|
|
28464
29266
|
quotaObservations: vault.quotaObservations,
|
|
28465
29267
|
drainQuotaPublications: async () => {
|
|
@@ -28478,7 +29280,7 @@ function createNativeAccountRuntime(options) {
|
|
|
28478
29280
|
const settings = await store2.readSettings();
|
|
28479
29281
|
if (settings.status !== "ready")
|
|
28480
29282
|
throw new NativeRuntimeError("publication-refused");
|
|
28481
|
-
const
|
|
29283
|
+
const flags = relayFlags(settings.settings.relay);
|
|
28482
29284
|
const generation = relayGeneration(settings.settings.relay);
|
|
28483
29285
|
const read = await readNativeRuntime(paths2.runtime, paths2.storageId);
|
|
28484
29286
|
await requireMode(mode);
|
|
@@ -28486,9 +29288,9 @@ function createNativeAccountRuntime(options) {
|
|
|
28486
29288
|
if (generation !== state?.relayGeneration)
|
|
28487
29289
|
continue;
|
|
28488
29290
|
const token2 = state?.relay?.token;
|
|
28489
|
-
if (!
|
|
29291
|
+
if (!flags.enabled || !flags.url || !token2)
|
|
28490
29292
|
return null;
|
|
28491
|
-
return { ...
|
|
29293
|
+
return { ...flags, token: token2 };
|
|
28492
29294
|
}
|
|
28493
29295
|
throw new NativeRuntimeError("relay-inconsistent");
|
|
28494
29296
|
},
|
|
@@ -28518,7 +29320,7 @@ function createNativeAccountRuntime(options) {
|
|
|
28518
29320
|
throw new NativeRuntimeError("publication-refused");
|
|
28519
29321
|
const previous = relayFlags(read.settings.relay);
|
|
28520
29322
|
const previousGeneration = relayGeneration(read.settings.relay);
|
|
28521
|
-
const generation =
|
|
29323
|
+
const generation = randomUUID16();
|
|
28522
29324
|
const metadata2 = await readNativeRuntime(paths2.runtime, paths2.storageId);
|
|
28523
29325
|
const token2 = patch.token === undefined ? metadata2.status === "ready" ? metadata2.state.relay?.token : undefined : patch.token?.trim();
|
|
28524
29326
|
const next = relayFlags({
|
|
@@ -28528,12 +29330,12 @@ function createNativeAccountRuntime(options) {
|
|
|
28528
29330
|
});
|
|
28529
29331
|
if (next.enabled && (!next.url || !token2))
|
|
28530
29332
|
throw new NativeRuntimeError("publication-refused");
|
|
28531
|
-
async function writeFlags(
|
|
29333
|
+
async function writeFlags(flags, stamp) {
|
|
28532
29334
|
await store2.updateSettings(async (settings) => {
|
|
28533
29335
|
await requireMode(mode);
|
|
28534
29336
|
await lease.assertOwned();
|
|
28535
29337
|
settings.relay = {
|
|
28536
|
-
...
|
|
29338
|
+
...flags,
|
|
28537
29339
|
...stamp === undefined ? {} : { generation: stamp }
|
|
28538
29340
|
};
|
|
28539
29341
|
});
|
|
@@ -28744,7 +29546,7 @@ function createNativeAccountRuntime(options) {
|
|
|
28744
29546
|
const snapshot = await runtime2.read();
|
|
28745
29547
|
if (snapshot.mode !== "local")
|
|
28746
29548
|
throw new NativeCustodyError("route-unavailable");
|
|
28747
|
-
const id2 = input.routeId === "main" ? await physicalId("main").catch(() =>
|
|
29549
|
+
const id2 = input.routeId === "main" ? await physicalId("main").catch(() => randomUUID16()) : input.routeId;
|
|
28748
29550
|
if (input.credential.type === "api" && (input.routeId === "main" || id2 === snapshot.settings.mainAccountId))
|
|
28749
29551
|
throw new NativeCustodyError("route-unavailable");
|
|
28750
29552
|
const old = await poolRow(id2);
|
|
@@ -28783,7 +29585,7 @@ function createNativeAccountRuntime(options) {
|
|
|
28783
29585
|
return row;
|
|
28784
29586
|
},
|
|
28785
29587
|
addApi: (input) => runtime2.putAccount({
|
|
28786
|
-
routeId: input.routeId ??
|
|
29588
|
+
routeId: input.routeId ?? randomUUID16(),
|
|
28787
29589
|
label: input.label,
|
|
28788
29590
|
replace: input.replace,
|
|
28789
29591
|
credential: {
|
|
@@ -29000,7 +29802,7 @@ function createNativeAccountRuntime(options) {
|
|
|
29000
29802
|
return;
|
|
29001
29803
|
let lineage;
|
|
29002
29804
|
const kept = await metadataPublications.run(() => localMetadataWrite(fence, (old) => {
|
|
29003
|
-
lineage = old.authLineageId ??
|
|
29805
|
+
lineage = old.authLineageId ?? randomUUID16();
|
|
29004
29806
|
return {
|
|
29005
29807
|
...old,
|
|
29006
29808
|
authLineageId: lineage
|
|
@@ -29204,9 +30006,9 @@ function relayGeneration(input) {
|
|
|
29204
30006
|
return generation;
|
|
29205
30007
|
}
|
|
29206
30008
|
// src/native-host-auth-write.ts
|
|
29207
|
-
import { randomUUID as
|
|
29208
|
-
import { lstat as
|
|
29209
|
-
import { dirname as
|
|
30009
|
+
import { randomUUID as randomUUID17 } from "node:crypto";
|
|
30010
|
+
import { lstat as lstat10, open as open10, rename as rename13, unlink as unlink6 } from "node:fs/promises";
|
|
30011
|
+
import { dirname as dirname17, isAbsolute as isAbsolute6, join as join19 } from "node:path";
|
|
29210
30012
|
class NativeHostAuthWriteError extends Error {
|
|
29211
30013
|
code;
|
|
29212
30014
|
effect;
|
|
@@ -29243,7 +30045,7 @@ async function writeNativeHostAuth(input, hooks = {}) {
|
|
|
29243
30045
|
requireNoSupervisedAuthContentSnapshot(input.env);
|
|
29244
30046
|
const { beforeRecheck, beforeRename, afterRename, afterUnlink } = hooks;
|
|
29245
30047
|
const publication2 = capturePublicationOptions(hooks.publication);
|
|
29246
|
-
if (host !== "opencode" && host !== "pi" || typeof authPath !== "string" || !
|
|
30048
|
+
if (host !== "opencode" && host !== "pi" || typeof authPath !== "string" || !isAbsolute6(authPath) || /\p{Cc}/u.test(authPath) || !isEntryDigest(sourceDigest) || !isEntryDigest(expectedDigest) || typeof processFence !== "function")
|
|
29247
30049
|
throw new NativeHostAuthWriteError("invalid-source");
|
|
29248
30050
|
const snapshot = await readNativeMigrationSource("hostAuth", authPath);
|
|
29249
30051
|
if (snapshot.metadata && process.getuid && snapshot.metadata.uid !== process.getuid())
|
|
@@ -29267,11 +30069,11 @@ async function writeNativeHostAuth(input, hooks = {}) {
|
|
|
29267
30069
|
const removingFile = host === "pi" && Object.keys(next).length === 0;
|
|
29268
30070
|
const outcome = Object.freeze(host === "pi" ? { status: "removed", file: removingFile ? "unlinked" : "replaced" } : { status: snapshot.data === undefined ? "created" : "replaced" });
|
|
29269
30071
|
if (!removingFile) {
|
|
29270
|
-
stage =
|
|
30072
|
+
stage = join19(dirname17(authPath), `.native-host-auth-write.${randomUUID17()}.tmp`);
|
|
29271
30073
|
const bytes = `${JSON.stringify(next, null, 2)}
|
|
29272
30074
|
`;
|
|
29273
30075
|
const nativeCreated = await createWindowsOwnerOnly(stage, bytes);
|
|
29274
|
-
const handle = await
|
|
30076
|
+
const handle = await open10(stage, nativeCreated ? "r+" : "wx", 384);
|
|
29275
30077
|
try {
|
|
29276
30078
|
const identity3 = await handle.stat();
|
|
29277
30079
|
ownedStage = { dev: identity3.dev, ino: identity3.ino };
|
|
@@ -29317,7 +30119,7 @@ async function writeNativeHostAuth(input, hooks = {}) {
|
|
|
29317
30119
|
} finally {
|
|
29318
30120
|
if (stage && ownedStage) {
|
|
29319
30121
|
try {
|
|
29320
|
-
const current = await
|
|
30122
|
+
const current = await lstat10(stage);
|
|
29321
30123
|
if (current.dev === ownedStage.dev && current.ino === ownedStage.ino)
|
|
29322
30124
|
await unlink6(stage);
|
|
29323
30125
|
} catch {}
|
|
@@ -29326,9 +30128,9 @@ async function writeNativeHostAuth(input, hooks = {}) {
|
|
|
29326
30128
|
}
|
|
29327
30129
|
|
|
29328
30130
|
// src/native-migration.ts
|
|
29329
|
-
import { createHash as
|
|
29330
|
-
import { lstat as
|
|
29331
|
-
import { dirname as
|
|
30131
|
+
import { createHash as createHash21 } from "node:crypto";
|
|
30132
|
+
import { lstat as lstat11, mkdir as mkdir12, unlink as unlink7 } from "node:fs/promises";
|
|
30133
|
+
import { dirname as dirname18, isAbsolute as isAbsolute7 } from "node:path";
|
|
29332
30134
|
class NativeMigrationError extends Error {
|
|
29333
30135
|
code;
|
|
29334
30136
|
constructor(code) {
|
|
@@ -29377,7 +30179,7 @@ function owned(snapshot) {
|
|
|
29377
30179
|
}
|
|
29378
30180
|
async function absent(path2) {
|
|
29379
30181
|
try {
|
|
29380
|
-
await
|
|
30182
|
+
await lstat11(path2);
|
|
29381
30183
|
return false;
|
|
29382
30184
|
} catch (error) {
|
|
29383
30185
|
if (error instanceof Error && "code" in error && error.code === "ENOENT")
|
|
@@ -29417,11 +30219,11 @@ async function publishNativeEmptyInit(input, hooks = {}) {
|
|
|
29417
30219
|
refuse3();
|
|
29418
30220
|
if (!env.OPENCODE_ANTHROPIC_AUTH_ROUTING_STATE_FILE && !await absent(routingDestinationPath))
|
|
29419
30221
|
refuse3();
|
|
29420
|
-
const resolved = await resolveNativePoolPaths(paths.legacyConfig, paths.legacyState);
|
|
30222
|
+
const resolved = await resolveNativePoolPaths(paths.legacyConfig, paths.legacyState, processStateLayout());
|
|
29421
30223
|
for (const key of Object.keys(resolved))
|
|
29422
30224
|
if (paths[key] !== resolved[key])
|
|
29423
30225
|
refuse3();
|
|
29424
|
-
if (!
|
|
30226
|
+
if (!isAbsolute7(routingDestinationPath) || /\p{Cc}/u.test(routingDestinationPath))
|
|
29425
30227
|
refuse3();
|
|
29426
30228
|
const routing = await canonicalPath(routingDestinationPath);
|
|
29427
30229
|
const all = [
|
|
@@ -29461,7 +30263,7 @@ function releaseNativeMigrationPreflight(token2) {
|
|
|
29461
30263
|
async function capture2(input, checkPool = false) {
|
|
29462
30264
|
requireNoSupervisedAuthContentSnapshot(input.env);
|
|
29463
30265
|
await input.processFence();
|
|
29464
|
-
const resolved = await resolveNativePoolPaths(input.paths.legacyConfig, input.paths.legacyState);
|
|
30266
|
+
const resolved = await resolveNativePoolPaths(input.paths.legacyConfig, input.paths.legacyState, processStateLayout());
|
|
29465
30267
|
for (const key of Object.keys(resolved))
|
|
29466
30268
|
if (input.paths[key] !== resolved[key])
|
|
29467
30269
|
refuse3();
|
|
@@ -29470,7 +30272,7 @@ async function capture2(input, checkPool = false) {
|
|
|
29470
30272
|
input.routingSourcePath,
|
|
29471
30273
|
input.routingDestinationPath
|
|
29472
30274
|
])
|
|
29473
|
-
if (!
|
|
30275
|
+
if (!isAbsolute7(path2) || /\p{Cc}/u.test(path2))
|
|
29474
30276
|
refuse3();
|
|
29475
30277
|
const current = await readNativeMigrationJournal(input.paths);
|
|
29476
30278
|
const emptyInit = current?.kind === "empty-init";
|
|
@@ -29706,7 +30508,7 @@ function routingBytes(captured) {
|
|
|
29706
30508
|
`;
|
|
29707
30509
|
}
|
|
29708
30510
|
function bytesDigest(bytes) {
|
|
29709
|
-
return bytes === undefined ? null :
|
|
30511
|
+
return bytes === undefined ? null : createHash21("sha256").update(bytes).digest("hex");
|
|
29710
30512
|
}
|
|
29711
30513
|
function expectedAuth(input, snapshot) {
|
|
29712
30514
|
const entry2 = inspectNativeHostAuthEntry(input.host, snapshot.data);
|
|
@@ -30081,7 +30883,7 @@ async function runNativeMigration(input, hooks = {}) {
|
|
|
30081
30883
|
refuse3();
|
|
30082
30884
|
await step("before:host");
|
|
30083
30885
|
await recheck();
|
|
30084
|
-
await
|
|
30886
|
+
await mkdir12(dirname18(operation.hostAuthPath), {
|
|
30085
30887
|
recursive: true,
|
|
30086
30888
|
mode: 448
|
|
30087
30889
|
});
|
|
@@ -30157,7 +30959,7 @@ class NativeCustodyActivationError extends Error {
|
|
|
30157
30959
|
function refuse4(code) {
|
|
30158
30960
|
throw new NativeCustodyActivationError(code);
|
|
30159
30961
|
}
|
|
30160
|
-
function
|
|
30962
|
+
function isRecord15(value) {
|
|
30161
30963
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
30162
30964
|
}
|
|
30163
30965
|
function sameJson(left, right) {
|
|
@@ -30242,7 +31044,7 @@ var ACCOUNT_RUNTIME_FIELDS = [
|
|
|
30242
31044
|
"quotaErrorGeneration"
|
|
30243
31045
|
];
|
|
30244
31046
|
function vaultSettings(settings, primary) {
|
|
30245
|
-
const custody =
|
|
31047
|
+
const custody = isRecord15(settings.claustrum) ? settings.claustrum : {};
|
|
30246
31048
|
return {
|
|
30247
31049
|
...settings,
|
|
30248
31050
|
claustrum: {
|
|
@@ -30352,7 +31154,7 @@ async function preparePlan(options, journal, store) {
|
|
|
30352
31154
|
const main = pool.settings.mainAccountId;
|
|
30353
31155
|
if (typeof main !== "string" || !main)
|
|
30354
31156
|
refuse4("invalid-state");
|
|
30355
|
-
const custody =
|
|
31157
|
+
const custody = isRecord15(pool.settings.claustrum) ? pool.settings.claustrum : {};
|
|
30356
31158
|
const host = await readHostEntry(options.host, journal.hostAuthPath);
|
|
30357
31159
|
const hostAuth = {
|
|
30358
31160
|
source: host.digest,
|
|
@@ -30383,7 +31185,7 @@ async function preparePlan(options, journal, store) {
|
|
|
30383
31185
|
let roster;
|
|
30384
31186
|
let targetSettings;
|
|
30385
31187
|
if (custody.mode === "claustrum") {
|
|
30386
|
-
const pin =
|
|
31188
|
+
const pin = isRecord15(custody.primaryAccount) ? custody.primaryAccount : {};
|
|
30387
31189
|
if (oauth.length > 0 || pin.credentialId !== primary.credentialId || pin.accountId !== primary.accountIdentity)
|
|
30388
31190
|
refuse4("primary-mismatch");
|
|
30389
31191
|
if (!existing)
|
|
@@ -30434,7 +31236,7 @@ async function preparePlan(options, journal, store) {
|
|
|
30434
31236
|
} catch (error) {
|
|
30435
31237
|
if (error instanceof NativeCustodyActivationError)
|
|
30436
31238
|
throw error;
|
|
30437
|
-
return refuse4(
|
|
31239
|
+
return refuse4(isRecord15(error) && error.code === "unenrolled-local-row" ? "unenrolled-local-row" : "roster-conflict");
|
|
30438
31240
|
}
|
|
30439
31241
|
roster = existing ?? rosterProjection(seed);
|
|
30440
31242
|
targetSettings = vaultSettings(pool.settings, primary);
|
|
@@ -30586,7 +31388,7 @@ async function runNativeCustodyActivation(options, hooks = {}) {
|
|
|
30586
31388
|
if (settings.status !== "ready")
|
|
30587
31389
|
refuse4("invalid-state");
|
|
30588
31390
|
const custody = settings.settings.claustrum;
|
|
30589
|
-
if (
|
|
31391
|
+
if (isRecord15(custody) && custody.mode === "claustrum")
|
|
30590
31392
|
return { status: "already-vault", journal };
|
|
30591
31393
|
}
|
|
30592
31394
|
if (journal.activation?.kind === "activation" && journal.activation.phase === "committed")
|
|
@@ -32539,7 +33341,7 @@ function waitForRequest(pending, signal) {
|
|
|
32539
33341
|
});
|
|
32540
33342
|
}
|
|
32541
33343
|
// src/native-vault-connection.ts
|
|
32542
|
-
import { dirname as
|
|
33344
|
+
import { dirname as dirname20, join as join20, resolve as resolve14 } from "node:path";
|
|
32543
33345
|
// ../../node_modules/@cortexkit/common-auth/dist/opencode2/integration.js
|
|
32544
33346
|
var PLACEHOLDER_PREFIX = "common-auth-placeholder";
|
|
32545
33347
|
var PLACEHOLDER_LIFETIME_MS = 365 * 24 * 60 * 60 * 1000;
|
|
@@ -32550,15 +33352,15 @@ function placeholderSecret(integrationID) {
|
|
|
32550
33352
|
// ../../node_modules/@cortexkit/common-auth/dist/opencode2/install.js
|
|
32551
33353
|
var MAX_RETRY_HOLD_MS = 20 * 60 * 1000;
|
|
32552
33354
|
// ../../node_modules/@cortexkit/common-auth/dist/pi-slot/slot.js
|
|
32553
|
-
import { createHash as
|
|
33355
|
+
import { createHash as createHash22 } from "node:crypto";
|
|
32554
33356
|
import { constants as constants4 } from "node:fs";
|
|
32555
|
-
import { lstat as
|
|
32556
|
-
import { dirname as
|
|
33357
|
+
import { lstat as lstat12, mkdir as mkdir14, open as open11, unlink as unlink8 } from "node:fs/promises";
|
|
33358
|
+
import { dirname as dirname19, resolve as resolve13 } from "node:path";
|
|
32557
33359
|
import { setTimeout as sleep } from "node:timers/promises";
|
|
32558
33360
|
|
|
32559
33361
|
// ../../node_modules/@cortexkit/common-auth/dist/pi-slot/lock.js
|
|
32560
33362
|
import { rmdirSync, statSync as statSync5, utimesSync } from "node:fs";
|
|
32561
|
-
import { mkdir as
|
|
33363
|
+
import { mkdir as mkdir13, rmdir, stat as stat10, utimes } from "node:fs/promises";
|
|
32562
33364
|
var STALE = 30000;
|
|
32563
33365
|
var RENEWAL_STALE = 1e4;
|
|
32564
33366
|
var UPDATE = 3000;
|
|
@@ -32578,7 +33380,7 @@ process.once("exit", () => {
|
|
|
32578
33380
|
function sameDirectory(observed, identity3) {
|
|
32579
33381
|
return observed.dev === identity3.dev && observed.ino === identity3.ino;
|
|
32580
33382
|
}
|
|
32581
|
-
function
|
|
33383
|
+
function errorCode3(error) {
|
|
32582
33384
|
return typeof error === "object" && error !== null && "code" in error ? error.code : undefined;
|
|
32583
33385
|
}
|
|
32584
33386
|
function held() {
|
|
@@ -32588,15 +33390,15 @@ async function remove(path2) {
|
|
|
32588
33390
|
try {
|
|
32589
33391
|
await rmdir(path2);
|
|
32590
33392
|
} catch (error) {
|
|
32591
|
-
if (
|
|
33393
|
+
if (errorCode3(error) !== "ENOENT")
|
|
32592
33394
|
throw error;
|
|
32593
33395
|
}
|
|
32594
33396
|
}
|
|
32595
33397
|
async function acquire(path2, stale) {
|
|
32596
33398
|
try {
|
|
32597
|
-
await
|
|
33399
|
+
await mkdir13(path2);
|
|
32598
33400
|
} catch (error) {
|
|
32599
|
-
if (
|
|
33401
|
+
if (errorCode3(error) !== "EEXIST")
|
|
32600
33402
|
throw error;
|
|
32601
33403
|
if (stale <= 0)
|
|
32602
33404
|
throw held();
|
|
@@ -32604,7 +33406,7 @@ async function acquire(path2, stale) {
|
|
|
32604
33406
|
try {
|
|
32605
33407
|
mtime = (await stat10(path2)).mtime.getTime();
|
|
32606
33408
|
} catch (error2) {
|
|
32607
|
-
if (
|
|
33409
|
+
if (errorCode3(error2) === "ENOENT")
|
|
32608
33410
|
return acquire(path2, 0);
|
|
32609
33411
|
throw error2;
|
|
32610
33412
|
}
|
|
@@ -32657,7 +33459,7 @@ async function acquirePiLock(authPath, onCompromised, onRenew) {
|
|
|
32657
33459
|
function retry(error) {
|
|
32658
33460
|
if (released)
|
|
32659
33461
|
return;
|
|
32660
|
-
if (
|
|
33462
|
+
if (errorCode3(error) === "ENOENT" || lastUpdate + RENEWAL_STALE < Date.now())
|
|
32661
33463
|
compromise();
|
|
32662
33464
|
else
|
|
32663
33465
|
schedule2(1000);
|
|
@@ -32719,7 +33521,7 @@ async function acquirePiLock(authPath, onCompromised, onRenew) {
|
|
|
32719
33521
|
try {
|
|
32720
33522
|
observed = await stat10(path2);
|
|
32721
33523
|
} catch (error) {
|
|
32722
|
-
if (
|
|
33524
|
+
if (errorCode3(error) !== "ENOENT")
|
|
32723
33525
|
throw error;
|
|
32724
33526
|
compromise();
|
|
32725
33527
|
return;
|
|
@@ -32814,7 +33616,7 @@ function canonical(value) {
|
|
|
32814
33616
|
return JSON.stringify(value);
|
|
32815
33617
|
}
|
|
32816
33618
|
function digest2(value) {
|
|
32817
|
-
return
|
|
33619
|
+
return createHash22("sha256").update(canonical(value)).digest("hex");
|
|
32818
33620
|
}
|
|
32819
33621
|
function code(error) {
|
|
32820
33622
|
return object2(error) ? error.code : undefined;
|
|
@@ -32836,13 +33638,13 @@ async function safeRead(path2, privateFile = false, afterReadCheck) {
|
|
|
32836
33638
|
}
|
|
32837
33639
|
let file;
|
|
32838
33640
|
try {
|
|
32839
|
-
file = await
|
|
33641
|
+
file = await open11(path2, constants4.O_RDONLY | constants4.O_NOFOLLOW);
|
|
32840
33642
|
const stat11 = await file.stat();
|
|
32841
33643
|
if (!stat11.isFile() || privateFile && (stat11.mode & 511) !== 384) {
|
|
32842
33644
|
throw new PiSlotError("unsafe-path");
|
|
32843
33645
|
}
|
|
32844
33646
|
await afterReadCheck?.(path2);
|
|
32845
|
-
const current = await
|
|
33647
|
+
const current = await lstat12(path2);
|
|
32846
33648
|
if (!current.isFile() || current.dev !== stat11.dev || current.ino !== stat11.ino) {
|
|
32847
33649
|
throw new PiSlotError("unsafe-path");
|
|
32848
33650
|
}
|
|
@@ -32914,7 +33716,7 @@ function replaceEntry(auth, provider, next) {
|
|
|
32914
33716
|
async function syncDir(path2) {
|
|
32915
33717
|
if (windowsPrivateFiles)
|
|
32916
33718
|
return;
|
|
32917
|
-
const dir = await
|
|
33719
|
+
const dir = await open11(path2, "r");
|
|
32918
33720
|
try {
|
|
32919
33721
|
await dir.sync();
|
|
32920
33722
|
} finally {
|
|
@@ -32965,7 +33767,7 @@ function createPiSlot(options, onStep, hooks) {
|
|
|
32965
33767
|
}
|
|
32966
33768
|
}
|
|
32967
33769
|
async function locked(fn) {
|
|
32968
|
-
let
|
|
33770
|
+
let release2;
|
|
32969
33771
|
let assertFresh;
|
|
32970
33772
|
let compromised = false;
|
|
32971
33773
|
const assertLock = () => {
|
|
@@ -32975,17 +33777,17 @@ function createPiSlot(options, onStep, hooks) {
|
|
|
32975
33777
|
};
|
|
32976
33778
|
try {
|
|
32977
33779
|
if (windowsPrivateFiles)
|
|
32978
|
-
await ensurePrivateDirectory(
|
|
33780
|
+
await ensurePrivateDirectory(dirname19(authPath));
|
|
32979
33781
|
else
|
|
32980
|
-
await
|
|
33782
|
+
await mkdir14(dirname19(authPath), { recursive: true, mode: 448 });
|
|
32981
33783
|
const deadline = Date.now() + timeout;
|
|
32982
33784
|
let retry = 0;
|
|
32983
|
-
while (!
|
|
33785
|
+
while (!release2) {
|
|
32984
33786
|
try {
|
|
32985
33787
|
const lease = await acquirePiLock(authPath, () => {
|
|
32986
33788
|
compromised = true;
|
|
32987
33789
|
}, hooks?.onRenew);
|
|
32988
|
-
|
|
33790
|
+
release2 = lease.release;
|
|
32989
33791
|
assertFresh = lease.assertFresh;
|
|
32990
33792
|
} catch (error) {
|
|
32991
33793
|
if (code(error) !== "ELOCKED")
|
|
@@ -33005,7 +33807,7 @@ function createPiSlot(options, onStep, hooks) {
|
|
|
33005
33807
|
throw error;
|
|
33006
33808
|
throw new PiSlotError("io");
|
|
33007
33809
|
} finally {
|
|
33008
|
-
await
|
|
33810
|
+
await release2?.().catch(() => {});
|
|
33009
33811
|
assertLock();
|
|
33010
33812
|
}
|
|
33011
33813
|
}
|
|
@@ -33017,7 +33819,7 @@ function createPiSlot(options, onStep, hooks) {
|
|
|
33017
33819
|
async function deleteStash(assertLock) {
|
|
33018
33820
|
assertLock();
|
|
33019
33821
|
await unlink8(stashPath);
|
|
33020
|
-
await syncDir(
|
|
33822
|
+
await syncDir(dirname19(stashPath));
|
|
33021
33823
|
onStep?.("stash-deleted");
|
|
33022
33824
|
}
|
|
33023
33825
|
return {
|
|
@@ -33037,10 +33839,10 @@ function createPiSlot(options, onStep, hooks) {
|
|
|
33037
33839
|
throw new PiSlotError("conflict");
|
|
33038
33840
|
if (!stash) {
|
|
33039
33841
|
if (windowsPrivateFiles)
|
|
33040
|
-
await ensurePrivateDirectory(
|
|
33842
|
+
await ensurePrivateDirectory(dirname19(stashPath));
|
|
33041
33843
|
else {
|
|
33042
|
-
await
|
|
33043
|
-
const dir = await
|
|
33844
|
+
await mkdir14(dirname19(stashPath), { recursive: true, mode: 448 });
|
|
33845
|
+
const dir = await lstat12(dirname19(stashPath));
|
|
33044
33846
|
if (!dir.isDirectory() || (dir.mode & 511) !== 448)
|
|
33045
33847
|
throw new PiSlotError("unsafe-path");
|
|
33046
33848
|
}
|
|
@@ -33081,7 +33883,7 @@ function createPiSlot(options, onStep, hooks) {
|
|
|
33081
33883
|
function nativePiAuthSlotPaths(options) {
|
|
33082
33884
|
return {
|
|
33083
33885
|
authPath: resolve14(options.authPath),
|
|
33084
|
-
stashPath:
|
|
33886
|
+
stashPath: join20(dirname20(getHostClaustrumEnrollmentPaths("pi", options.env).tokenPath), "pi-auth-slot", "anthropic.json"),
|
|
33085
33887
|
provider: "anthropic",
|
|
33086
33888
|
placeholderKey: placeholderSecret("anthropic")
|
|
33087
33889
|
};
|
|
@@ -33150,11 +33952,11 @@ function createAnthropicOAuthFetch(options = {}) {
|
|
|
33150
33952
|
});
|
|
33151
33953
|
}
|
|
33152
33954
|
// src/prime.ts
|
|
33153
|
-
import { createHash as
|
|
33154
|
-
import { realpathSync as
|
|
33155
|
-
import { mkdir as
|
|
33955
|
+
import { createHash as createHash23 } from "node:crypto";
|
|
33956
|
+
import { realpathSync as realpathSync3 } from "node:fs";
|
|
33957
|
+
import { mkdir as mkdir15, readdir as readdir4, rm as rm8, stat as stat11, writeFile as writeFile5 } from "node:fs/promises";
|
|
33156
33958
|
import { tmpdir as tmpdir7 } from "node:os";
|
|
33157
|
-
import { join as
|
|
33959
|
+
import { join as join21, resolve as resolve15 } from "node:path";
|
|
33158
33960
|
var CLAUDE_PRIME_COMMAND_NAME = "claude-prime";
|
|
33159
33961
|
var PRIME_TICK_MS = 60000;
|
|
33160
33962
|
var PRIME_DUE_OFFSET_MS = 60000;
|
|
@@ -33342,34 +34144,34 @@ function buildPrimeRequestBody() {
|
|
|
33342
34144
|
return JSON.parse(JSON.stringify(PRIME_REQUEST_BODY));
|
|
33343
34145
|
}
|
|
33344
34146
|
function defaultMarkerDir() {
|
|
33345
|
-
return
|
|
34147
|
+
return join21(tmpdir7(), "opencode-anthropic-auth", "prime");
|
|
33346
34148
|
}
|
|
33347
34149
|
function primeStorageFingerprint(storagePath) {
|
|
33348
34150
|
const absolutePath = resolve15(storagePath);
|
|
33349
34151
|
let canonicalPath2;
|
|
33350
34152
|
try {
|
|
33351
|
-
canonicalPath2 =
|
|
34153
|
+
canonicalPath2 = realpathSync3(absolutePath);
|
|
33352
34154
|
} catch (error) {
|
|
33353
34155
|
if (error.code !== "ENOENT")
|
|
33354
34156
|
throw error;
|
|
33355
34157
|
canonicalPath2 = absolutePath;
|
|
33356
34158
|
}
|
|
33357
|
-
return
|
|
34159
|
+
return createHash23("sha256").update(canonicalPath2).digest("hex").slice(0, 12);
|
|
33358
34160
|
}
|
|
33359
34161
|
function primeMarkerNamespaceDir(markerDir, storagePath) {
|
|
33360
|
-
return
|
|
34162
|
+
return join21(markerDir, primeStorageFingerprint(storagePath));
|
|
33361
34163
|
}
|
|
33362
34164
|
function primeAccountMarkerDir(markerDir, storagePath, accountFingerprint) {
|
|
33363
34165
|
if (!/^[a-f0-9]{12,}$/i.test(accountFingerprint)) {
|
|
33364
34166
|
throw new Error("Prime account fingerprint must be a hexadecimal digest");
|
|
33365
34167
|
}
|
|
33366
|
-
return
|
|
34168
|
+
return join21(primeMarkerNamespaceDir(markerDir, storagePath), accountFingerprint.toLowerCase().slice(0, 12));
|
|
33367
34169
|
}
|
|
33368
34170
|
function primeMarkerPath(markerDir, accountId2, resetsAtEpochMs) {
|
|
33369
|
-
return
|
|
34171
|
+
return join21(markerDir, `${encodeURIComponent(accountId2)}-${resetsAtEpochMs}`);
|
|
33370
34172
|
}
|
|
33371
34173
|
function primeBootstrapMarkerPath(markerDir, accountId2) {
|
|
33372
|
-
return
|
|
34174
|
+
return join21(markerDir, `${encodeURIComponent(accountId2)}-bootstrap`);
|
|
33373
34175
|
}
|
|
33374
34176
|
function primeAccountLabel(id2, fallback) {
|
|
33375
34177
|
if (id2 === "main")
|
|
@@ -33664,7 +34466,7 @@ class PrimeManager {
|
|
|
33664
34466
|
}
|
|
33665
34467
|
async tryClaimPath(dir, markerPath) {
|
|
33666
34468
|
try {
|
|
33667
|
-
await
|
|
34469
|
+
await mkdir15(dir, { recursive: true });
|
|
33668
34470
|
} catch {}
|
|
33669
34471
|
try {
|
|
33670
34472
|
await writeFile5(markerPath, "", { encoding: "utf8", flag: "wx" });
|
|
@@ -33799,7 +34601,7 @@ class PrimeManager {
|
|
|
33799
34601
|
let swept = 0;
|
|
33800
34602
|
for (const entry2 of entries) {
|
|
33801
34603
|
try {
|
|
33802
|
-
const path2 =
|
|
34604
|
+
const path2 = join21(dir, entry2);
|
|
33803
34605
|
const s = await stat11(path2);
|
|
33804
34606
|
if (s.isDirectory()) {
|
|
33805
34607
|
swept += await this.sweepMarkerDirectory(path2, now);
|
|
@@ -33821,24 +34623,24 @@ class PrimeManager {
|
|
|
33821
34623
|
}
|
|
33822
34624
|
}
|
|
33823
34625
|
// src/quota-header-feed.ts
|
|
33824
|
-
import { randomUUID as
|
|
34626
|
+
import { randomUUID as randomUUID18 } from "node:crypto";
|
|
33825
34627
|
import {
|
|
33826
34628
|
chmod as chmod3,
|
|
33827
|
-
lstat as
|
|
33828
|
-
mkdir as
|
|
34629
|
+
lstat as lstat13,
|
|
34630
|
+
mkdir as mkdir16,
|
|
33829
34631
|
readdir as readdir5,
|
|
33830
|
-
readFile as
|
|
34632
|
+
readFile as readFile11,
|
|
33831
34633
|
rename as rename14,
|
|
33832
34634
|
rm as rm9,
|
|
33833
34635
|
stat as stat12,
|
|
33834
34636
|
writeFile as writeFile6
|
|
33835
34637
|
} from "node:fs/promises";
|
|
33836
34638
|
import { tmpdir as tmpdir8 } from "node:os";
|
|
33837
|
-
import { join as
|
|
34639
|
+
import { join as join22 } from "node:path";
|
|
33838
34640
|
var QUOTA_HEADER_FEED_SCHEMA_VERSION = 3;
|
|
33839
34641
|
var QUOTA_HEADER_FEED_LEASE_MS = 180000;
|
|
33840
34642
|
function getDefaultQuotaHeaderFeedDirectory() {
|
|
33841
|
-
return process.env.OPENCODE_ANTHROPIC_AUTH_QUOTA_FEED_DIR ??
|
|
34643
|
+
return process.env.OPENCODE_ANTHROPIC_AUTH_QUOTA_FEED_DIR ?? join22(tmpdir8(), "opencode-anthropic-auth", "quota-header-feed");
|
|
33842
34644
|
}
|
|
33843
34645
|
function configuredAnthropicOAuthAccountCount(input) {
|
|
33844
34646
|
const fallbackCount = input.storage?.accounts.filter(isOAuthAccount).length ?? 0;
|
|
@@ -33996,8 +34798,8 @@ class QuotaHeaderFeedRegistry {
|
|
|
33996
34798
|
writeChain = Promise.resolve();
|
|
33997
34799
|
constructor(options = {}) {
|
|
33998
34800
|
this.options = options;
|
|
33999
|
-
const instanceId = options.instanceId ?? `${process.pid}-${
|
|
34000
|
-
this.filePath =
|
|
34801
|
+
const instanceId = options.instanceId ?? `${process.pid}-${randomUUID18()}`;
|
|
34802
|
+
this.filePath = join22(options.directory ?? getDefaultQuotaHeaderFeedDirectory(), `${instanceId}.json`);
|
|
34001
34803
|
}
|
|
34002
34804
|
publish(entry2) {
|
|
34003
34805
|
const { accountKey, quota: quota2 } = entry2;
|
|
@@ -34026,17 +34828,17 @@ class QuotaHeaderFeedRegistry {
|
|
|
34026
34828
|
return Promise.reject(new Error("Invalid quota header feed account key"));
|
|
34027
34829
|
this.writeChain = this.writeChain.catch(() => {}).then(async () => {
|
|
34028
34830
|
const directory = this.options.directory ?? getDefaultQuotaHeaderFeedDirectory();
|
|
34029
|
-
await
|
|
34831
|
+
await mkdir16(directory, { recursive: true, mode: 448 });
|
|
34030
34832
|
await chmod3(directory, 448);
|
|
34031
34833
|
await this.reapStaleSiblingLeases(directory);
|
|
34032
34834
|
let entries = {};
|
|
34033
34835
|
try {
|
|
34034
|
-
const record9 = JSON.parse(await
|
|
34836
|
+
const record9 = JSON.parse(await readFile11(this.filePath, "utf8"));
|
|
34035
34837
|
if (record9.version === QUOTA_HEADER_FEED_SCHEMA_VERSION && record9.entries && typeof record9.entries === "object")
|
|
34036
34838
|
entries = record9.entries;
|
|
34037
34839
|
} catch {}
|
|
34038
34840
|
entries[accountKey] = cleanEntry;
|
|
34039
|
-
const tempPath = `${this.filePath}.${
|
|
34841
|
+
const tempPath = `${this.filePath}.${randomUUID18()}.tmp`;
|
|
34040
34842
|
try {
|
|
34041
34843
|
await writeFile6(tempPath, `${JSON.stringify({ version: QUOTA_HEADER_FEED_SCHEMA_VERSION, lease_horizon_ms: this.options.leaseMs ?? QUOTA_HEADER_FEED_LEASE_MS, entries })}
|
|
34042
34844
|
`, { mode: 384 });
|
|
@@ -34058,7 +34860,7 @@ class QuotaHeaderFeedRegistry {
|
|
|
34058
34860
|
return;
|
|
34059
34861
|
}
|
|
34060
34862
|
await Promise.all(names2.filter((name) => /^\d+-[0-9a-f-]+\.json$/i.test(name)).map(async (name) => {
|
|
34061
|
-
const path2 =
|
|
34863
|
+
const path2 = join22(directory, name);
|
|
34062
34864
|
if (path2 === this.filePath)
|
|
34063
34865
|
return;
|
|
34064
34866
|
try {
|
|
@@ -34066,7 +34868,7 @@ class QuotaHeaderFeedRegistry {
|
|
|
34066
34868
|
if (file.mtimeMs > now || now - file.mtimeMs < leaseMs)
|
|
34067
34869
|
return;
|
|
34068
34870
|
await this.options.beforeRemoveFile?.(path2);
|
|
34069
|
-
const current = await
|
|
34871
|
+
const current = await lstat13(path2);
|
|
34070
34872
|
if (current.ino !== file.ino || current.mtimeMs !== file.mtimeMs)
|
|
34071
34873
|
return;
|
|
34072
34874
|
await (this.options.removeFile ?? ((target2) => rm9(target2)))(path2);
|
|
@@ -34087,7 +34889,7 @@ class QuotaHeaderFeedRegistry {
|
|
|
34087
34889
|
const newest = new Map;
|
|
34088
34890
|
await Promise.all(names2.map(async (name) => {
|
|
34089
34891
|
try {
|
|
34090
|
-
const record9 = JSON.parse(await
|
|
34892
|
+
const record9 = JSON.parse(await readFile11(join22(directory, name), "utf8"));
|
|
34091
34893
|
if (record9.version !== QUOTA_HEADER_FEED_SCHEMA_VERSION || !record9.entries || typeof record9.entries !== "object")
|
|
34092
34894
|
return;
|
|
34093
34895
|
for (const [accountKey, candidate] of Object.entries(record9.entries)) {
|
|
@@ -34267,8 +35069,8 @@ function buildClaudeQuotaSummary(input) {
|
|
|
34267
35069
|
`).trimEnd();
|
|
34268
35070
|
}
|
|
34269
35071
|
// src/request-gzip.ts
|
|
34270
|
-
import { mkdir as
|
|
34271
|
-
import { basename as
|
|
35072
|
+
import { mkdir as mkdir17, readFile as readFile12, rename as rename15, rm as rm10, writeFile as writeFile7 } from "node:fs/promises";
|
|
35073
|
+
import { basename as basename10, dirname as dirname21, join as join23 } from "node:path";
|
|
34272
35074
|
import { promisify } from "node:util";
|
|
34273
35075
|
import { gzip } from "node:zlib";
|
|
34274
35076
|
var gzipAsync = promisify(gzip);
|
|
@@ -34369,7 +35171,7 @@ class RequestGzipLatch {
|
|
|
34369
35171
|
return false;
|
|
34370
35172
|
let text5;
|
|
34371
35173
|
try {
|
|
34372
|
-
text5 = await
|
|
35174
|
+
text5 = await readFile12(this.path, "utf8");
|
|
34373
35175
|
} catch {
|
|
34374
35176
|
return false;
|
|
34375
35177
|
}
|
|
@@ -34392,7 +35194,7 @@ class RequestGzipLatch {
|
|
|
34392
35194
|
return;
|
|
34393
35195
|
const temporary = `${this.path}.${process.pid}.tmp`;
|
|
34394
35196
|
try {
|
|
34395
|
-
await
|
|
35197
|
+
await mkdir17(dirname21(this.path), { recursive: true });
|
|
34396
35198
|
await writeFile7(temporary, `${JSON.stringify({ latchedAt: this.now(), status })}
|
|
34397
35199
|
`, { mode: 384 });
|
|
34398
35200
|
await rename15(temporary, this.path);
|
|
@@ -34412,9 +35214,9 @@ function getRequestGzipLatch(path2) {
|
|
|
34412
35214
|
return latch;
|
|
34413
35215
|
}
|
|
34414
35216
|
function getRequestGzipLatchPath(accountStoragePath) {
|
|
34415
|
-
const name =
|
|
35217
|
+
const name = basename10(accountStoragePath);
|
|
34416
35218
|
const stem = name.endsWith(".json") ? name.slice(0, -5) : name;
|
|
34417
|
-
return
|
|
35219
|
+
return join23(dirname21(accountStoragePath), `${stem}-request-gzip.json`);
|
|
34418
35220
|
}
|
|
34419
35221
|
async function decideRequestGzip(options) {
|
|
34420
35222
|
if (!CLAUDE_CODE_GZIPS_REQUEST_BODIES)
|
|
@@ -34559,7 +35361,7 @@ var REPORTED_BLOCK_TYPES = new Set([
|
|
|
34559
35361
|
"document"
|
|
34560
35362
|
]);
|
|
34561
35363
|
var EMPTY_TEXT_BLOCK_KEYS = new Set(["type", "text", "cache_control"]);
|
|
34562
|
-
function
|
|
35364
|
+
function isRecord16(value) {
|
|
34563
35365
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
34564
35366
|
}
|
|
34565
35367
|
function isProvablyEmptyContent(content) {
|
|
@@ -34567,14 +35369,14 @@ function isProvablyEmptyContent(content) {
|
|
|
34567
35369
|
return content.trim() === "";
|
|
34568
35370
|
if (!Array.isArray(content))
|
|
34569
35371
|
return false;
|
|
34570
|
-
return content.every((block) =>
|
|
35372
|
+
return content.every((block) => isRecord16(block) && block.type === "text" && typeof block.text === "string" && block.text.trim() === "" && Object.keys(block).every((key) => EMPTY_TEXT_BLOCK_KEYS.has(key)));
|
|
34571
35373
|
}
|
|
34572
35374
|
function describeContent(content) {
|
|
34573
35375
|
if (Array.isArray(content)) {
|
|
34574
35376
|
return {
|
|
34575
35377
|
contentShape: "array",
|
|
34576
35378
|
contentBlockCount: content.length,
|
|
34577
|
-
contentBlockTypes: content.map((block) =>
|
|
35379
|
+
contentBlockTypes: content.map((block) => isRecord16(block) && typeof block.type === "string" && REPORTED_BLOCK_TYPES.has(block.type) ? block.type : "other")
|
|
34578
35380
|
};
|
|
34579
35381
|
}
|
|
34580
35382
|
if (typeof content === "string")
|
|
@@ -34587,7 +35389,7 @@ function assertNoMeaningfulTrailingAssistant(messages) {
|
|
|
34587
35389
|
let end = messages.length;
|
|
34588
35390
|
while (end > 0) {
|
|
34589
35391
|
const last = messages[end - 1];
|
|
34590
|
-
if (!
|
|
35392
|
+
if (!isRecord16(last) || last.role !== "assistant")
|
|
34591
35393
|
break;
|
|
34592
35394
|
if (!isProvablyEmptyContent(last.content)) {
|
|
34593
35395
|
throw new TrailingAssistantHistoryError({
|
|
@@ -34730,11 +35532,11 @@ function executeLaneStartCommand(input) {
|
|
|
34730
35532
|
}
|
|
34731
35533
|
// src/thinking-binding.ts
|
|
34732
35534
|
var THINKING_BINDING_CONTROLS_BETA = "thinking-binding-controls-2026-08-01";
|
|
34733
|
-
function
|
|
35535
|
+
function isRecord17(value) {
|
|
34734
35536
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
34735
35537
|
}
|
|
34736
35538
|
function isReplayableThinkingBlock(block) {
|
|
34737
|
-
if (!
|
|
35539
|
+
if (!isRecord17(block))
|
|
34738
35540
|
return false;
|
|
34739
35541
|
if (block.type === "thinking") {
|
|
34740
35542
|
return typeof block.signature === "string" && block.signature.length > 0;
|
|
@@ -34752,7 +35554,7 @@ function hasReplayableThinkingBlocks(body) {
|
|
|
34752
35554
|
if (!Array.isArray(body.messages))
|
|
34753
35555
|
return false;
|
|
34754
35556
|
return body.messages.some((message) => {
|
|
34755
|
-
if (!
|
|
35557
|
+
if (!isRecord17(message) || message.role !== "assistant")
|
|
34756
35558
|
return false;
|
|
34757
35559
|
return Array.isArray(message.content) && message.content.some(isReplayableThinkingBlock);
|
|
34758
35560
|
});
|
|
@@ -34764,7 +35566,7 @@ function applyThinkingBindingControls(body, behavior = "account-default") {
|
|
|
34764
35566
|
return false;
|
|
34765
35567
|
if (!hasReplayableThinkingBlocks(body))
|
|
34766
35568
|
return false;
|
|
34767
|
-
if (!
|
|
35569
|
+
if (!isRecord17(body.thinking) || body.thinking.type !== "adaptive")
|
|
34768
35570
|
return false;
|
|
34769
35571
|
body.thinking.block_binding = {
|
|
34770
35572
|
prefix_mismatch_behavior: behavior
|
|
@@ -34772,9 +35574,9 @@ function applyThinkingBindingControls(body, behavior = "account-default") {
|
|
|
34772
35574
|
return true;
|
|
34773
35575
|
}
|
|
34774
35576
|
function hasThinkingBindingControls(body) {
|
|
34775
|
-
if (!
|
|
35577
|
+
if (!isRecord17(body.thinking))
|
|
34776
35578
|
return false;
|
|
34777
|
-
if (!
|
|
35579
|
+
if (!isRecord17(body.thinking.block_binding))
|
|
34778
35580
|
return false;
|
|
34779
35581
|
const behavior = body.thinking.block_binding.prefix_mismatch_behavior;
|
|
34780
35582
|
return behavior === "error" || behavior === "drop_block";
|
|
@@ -34783,7 +35585,7 @@ function hasThinkingBindingControls(body) {
|
|
|
34783
35585
|
var TURN_END_NOTE_MIN_VISIBLE_CHARACTERS = 350;
|
|
34784
35586
|
var TURN_END_NOTE_CONTENT = "Your reply above has already reached the user. The tool call after it was housekeeping and changed nothing they need to know. Do not repeat, summarize or rewrite that reply. If no new work remains, end the turn without restating anything.";
|
|
34785
35587
|
var DEFAULT_TOOLS = ["board", "ctx_reduce"];
|
|
34786
|
-
function
|
|
35588
|
+
function isRecord18(value) {
|
|
34787
35589
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
34788
35590
|
}
|
|
34789
35591
|
function supportsTurnEndNote(model) {
|
|
@@ -34804,24 +35606,24 @@ function applyTurnEndNotes(body, options = {}) {
|
|
|
34804
35606
|
let preceding = index - 1;
|
|
34805
35607
|
while (preceding >= 0) {
|
|
34806
35608
|
const control = messages[preceding];
|
|
34807
|
-
if (!
|
|
35609
|
+
if (!isRecord18(control) || control.role !== "system" || !Array.isArray(control.content) || control.content.length !== 0 || !isRecord18(control.output_config))
|
|
34808
35610
|
break;
|
|
34809
35611
|
preceding--;
|
|
34810
35612
|
}
|
|
34811
35613
|
const assistant = messages[preceding];
|
|
34812
|
-
if (!
|
|
35614
|
+
if (!isRecord18(assistant) || assistant.role !== "assistant" || !Array.isArray(assistant.content) || !isRecord18(results) || results.role !== "user" || !Array.isArray(results.content))
|
|
34813
35615
|
continue;
|
|
34814
|
-
const visible = options.visibleText ? options.visibleText(assistant) : assistant.content.filter((block) =>
|
|
35616
|
+
const visible = options.visibleText ? options.visibleText(assistant) : assistant.content.filter((block) => isRecord18(block) && block.type === "text" && typeof block.text === "string" && block.text.trim().length > 0).map((block) => block.text).join("");
|
|
34815
35617
|
if (visible.length < TURN_END_NOTE_MIN_VISIBLE_CHARACTERS)
|
|
34816
35618
|
continue;
|
|
34817
|
-
const calls = assistant.content.filter((block) =>
|
|
35619
|
+
const calls = assistant.content.filter((block) => isRecord18(block) && block.type === "tool_use");
|
|
34818
35620
|
if (!calls.length || !calls.every((call) => allowed.has(call.name)))
|
|
34819
35621
|
continue;
|
|
34820
|
-
const resultIds = new Set(results.content.filter((block) =>
|
|
35622
|
+
const resultIds = new Set(results.content.filter((block) => isRecord18(block) && block.type === "tool_result").map((block) => block.tool_use_id));
|
|
34821
35623
|
if (!calls.every((call) => typeof call.id === "string" && resultIds.has(call.id)))
|
|
34822
35624
|
continue;
|
|
34823
35625
|
const next = messages[index + 1];
|
|
34824
|
-
if (
|
|
35626
|
+
if (isRecord18(next) && next.role === "user")
|
|
34825
35627
|
continue;
|
|
34826
35628
|
rewritten.push({
|
|
34827
35629
|
role: "system",
|
|
@@ -34835,6 +35637,7 @@ function applyTurnEndNotes(body, options = {}) {
|
|
|
34835
35637
|
return inserted;
|
|
34836
35638
|
}
|
|
34837
35639
|
export {
|
|
35640
|
+
writerStamp,
|
|
34838
35641
|
writeNativeHostAuth,
|
|
34839
35642
|
writeDumpFile,
|
|
34840
35643
|
usesPerTurnControl,
|
|
@@ -34852,10 +35655,15 @@ export {
|
|
|
34852
35655
|
stickyRouteCandidateWeight,
|
|
34853
35656
|
stickyRetryAfterWithJitter,
|
|
34854
35657
|
stickyQuotaSnapshotIsFresh,
|
|
35658
|
+
stateSubfolderName,
|
|
35659
|
+
stateRefusalCause,
|
|
35660
|
+
stateHomeFilePaths,
|
|
35661
|
+
stateHomeDatasetFiles,
|
|
34855
35662
|
snapshotHasServableLocalOAuth,
|
|
34856
35663
|
signRequestBody,
|
|
34857
35664
|
shouldFallbackStatus,
|
|
34858
35665
|
shouldEmit,
|
|
35666
|
+
setupUsage,
|
|
34859
35667
|
setupEnrollment,
|
|
34860
35668
|
setLogLevel,
|
|
34861
35669
|
setFastModeEnabled,
|
|
@@ -34872,12 +35680,14 @@ export {
|
|
|
34872
35680
|
runPiCommandMenu,
|
|
34873
35681
|
runNativeMigration,
|
|
34874
35682
|
runNativeCustodyActivation,
|
|
35683
|
+
resolveStateHomeTarget,
|
|
34875
35684
|
resolveNativePoolPaths,
|
|
34876
35685
|
resolveLocalRoutingDestination,
|
|
34877
35686
|
resolveClaustrumConnectionPath,
|
|
34878
35687
|
resolveClaudeModelCapabilities,
|
|
34879
35688
|
resolveClaudeCodeIdentity,
|
|
34880
35689
|
resolveClaudeCodeAccountIdentity,
|
|
35690
|
+
resetNativeHolderRegistryForTests,
|
|
34881
35691
|
resetFastModeState,
|
|
34882
35692
|
resetDumpState,
|
|
34883
35693
|
resetClaustrumEnrollmentState2 as resetClaustrumEnrollmentState,
|
|
@@ -34891,14 +35701,18 @@ export {
|
|
|
34891
35701
|
remapModelId,
|
|
34892
35702
|
releaseNativeMigrationPreflight,
|
|
34893
35703
|
relayLog,
|
|
35704
|
+
registerNativePoolHolder,
|
|
34894
35705
|
refuseWritableAncestor2 as refuseWritableAncestor,
|
|
34895
35706
|
refreshClaudeOAuthToken,
|
|
34896
35707
|
refreshBackoffActive,
|
|
34897
35708
|
redactPayload,
|
|
35709
|
+
readStateLayoutMarker,
|
|
35710
|
+
readRelocationPointer,
|
|
34898
35711
|
readNativeMigrationJournal,
|
|
34899
35712
|
readNativeHostAuthKind,
|
|
34900
35713
|
readNativeEnrollmentMode,
|
|
34901
35714
|
readNativeAccountsForRequest,
|
|
35715
|
+
readConfigDirMarker,
|
|
34902
35716
|
readClaustrumEnrollmentToken2 as readClaustrumEnrollmentToken,
|
|
34903
35717
|
readClaustrumEnrollmentStatus2 as readClaustrumEnrollmentStatus,
|
|
34904
35718
|
quotaWindowParts,
|
|
@@ -34914,6 +35728,8 @@ export {
|
|
|
34914
35728
|
publishNativeVaultRuntimeSeed,
|
|
34915
35729
|
publishNativeVaultRosterSeed,
|
|
34916
35730
|
publishNativeEmptyInit,
|
|
35731
|
+
processStateLayout,
|
|
35732
|
+
processIncarnation,
|
|
34917
35733
|
primeStorageFingerprint,
|
|
34918
35734
|
primeMarkerPath,
|
|
34919
35735
|
primeMarkerNamespaceDir,
|
|
@@ -34940,6 +35756,7 @@ export {
|
|
|
34940
35756
|
parseAccountCommandAction,
|
|
34941
35757
|
orderClaudeCodeBody,
|
|
34942
35758
|
openNativePiAuthSlot,
|
|
35759
|
+
openCodeHolderKind,
|
|
34943
35760
|
oauthProfileMatchesIdentity,
|
|
34944
35761
|
oauthProfileIsFresh,
|
|
34945
35762
|
normalizeQuotaHeaders,
|
|
@@ -34948,6 +35765,8 @@ export {
|
|
|
34948
35765
|
normalizeAdaptiveEffort,
|
|
34949
35766
|
nativeSettingsRecord,
|
|
34950
35767
|
nativeRuntimeOptionIdentity,
|
|
35768
|
+
nativeRelocationRuntimePaths,
|
|
35769
|
+
nativeRelocationGuard,
|
|
34951
35770
|
nativePoolStoreLocks,
|
|
34952
35771
|
nativePoolHoldsAccountData,
|
|
34953
35772
|
nativePollQuotaGenerallyExhausted,
|
|
@@ -34956,6 +35775,7 @@ export {
|
|
|
34956
35775
|
nativeLocalQuotaLineage,
|
|
34957
35776
|
nativeLocalCredentialValidationMatches,
|
|
34958
35777
|
nativeJournalMayAdoptLaterHostLogin,
|
|
35778
|
+
nativeHolderDatasetFiles,
|
|
34959
35779
|
nativeCacheKeepAlways,
|
|
34960
35780
|
nativeAccountPolicy,
|
|
34961
35781
|
nativeAccountCanServe,
|
|
@@ -34994,6 +35814,7 @@ export {
|
|
|
34994
35814
|
isFastModeEnabled,
|
|
34995
35815
|
isDumpPersistentlyEnabled,
|
|
34996
35816
|
isDumpEnabled,
|
|
35817
|
+
isDestinationShapedDirectory,
|
|
34997
35818
|
isCustodyTombstoneValue,
|
|
34998
35819
|
isCustodyTombstoneOAuth,
|
|
34999
35820
|
isCostZeroingEnabled,
|
|
@@ -35015,6 +35836,8 @@ export {
|
|
|
35015
35836
|
isCache1hEnabled,
|
|
35016
35837
|
isApiKeyAccount,
|
|
35017
35838
|
inspectNativeHostAuthEntry,
|
|
35839
|
+
homeDefaultConfigDir,
|
|
35840
|
+
holderEntryIsLive,
|
|
35018
35841
|
hashRefreshToken,
|
|
35019
35842
|
hashBody,
|
|
35020
35843
|
hasThinkingBindingControls,
|
|
@@ -35035,6 +35858,7 @@ export {
|
|
|
35035
35858
|
getQuotaCheckIntervalMs,
|
|
35036
35859
|
getPersistedMainQuota,
|
|
35037
35860
|
getPersistedLogLevel,
|
|
35861
|
+
getOpenCodeConfigDir,
|
|
35038
35862
|
getNativeMenuModel,
|
|
35039
35863
|
getLogLevel,
|
|
35040
35864
|
getLogFilePath,
|
|
@@ -35069,6 +35893,7 @@ export {
|
|
|
35069
35893
|
formatLogLine,
|
|
35070
35894
|
formatEnrollmentStatus,
|
|
35071
35895
|
formatCreditAmounts,
|
|
35896
|
+
findRelocationTombstone,
|
|
35072
35897
|
findExistingClaustrumConnectionPath,
|
|
35073
35898
|
fetchOAuthQuotaSnapshot,
|
|
35074
35899
|
fetchOAuthAccountProfile,
|
|
@@ -35109,6 +35934,7 @@ export {
|
|
|
35109
35934
|
createStringPatch,
|
|
35110
35935
|
createStickyNoRouteResponse,
|
|
35111
35936
|
createSseFramer,
|
|
35937
|
+
createRelocationGuard,
|
|
35112
35938
|
createProviderErrorResponseScope,
|
|
35113
35939
|
createProviderErrorRedactor,
|
|
35114
35940
|
createProcessFence,
|
|
@@ -35125,6 +35951,7 @@ export {
|
|
|
35125
35951
|
countUserPrompts,
|
|
35126
35952
|
connectClaustrumEnrollmentClient2 as connectClaustrumEnrollmentClient,
|
|
35127
35953
|
configuredAnthropicOAuthAccountCount,
|
|
35954
|
+
configFolderIdentity,
|
|
35128
35955
|
computeXxhash64Hex,
|
|
35129
35956
|
computeCcVersionSuffix,
|
|
35130
35957
|
computeCCH,
|
|
@@ -35160,6 +35987,8 @@ export {
|
|
|
35160
35987
|
applyCustomHeaders,
|
|
35161
35988
|
applyClaudeCodeMetadata,
|
|
35162
35989
|
applyClaudeCodeHeaders,
|
|
35990
|
+
anthropicAuthStateRoot,
|
|
35991
|
+
anthropicAuthRelease,
|
|
35163
35992
|
acquireRefreshFileLock2 as acquireRefreshFileLock,
|
|
35164
35993
|
acquireNativeVaultRuntime,
|
|
35165
35994
|
acquireNativeAccountRuntime,
|
|
@@ -35176,14 +36005,19 @@ export {
|
|
|
35176
36005
|
THINKING_BINDING_CONTROLS_BETA,
|
|
35177
36006
|
TEXT_REPLACEMENTS,
|
|
35178
36007
|
StickySessionRouter,
|
|
36008
|
+
StateLayoutFileError,
|
|
35179
36009
|
SseFrameTooLargeError,
|
|
35180
36010
|
STICKY_ROUTING_SHORT_RESET_GRACE_MS,
|
|
35181
36011
|
STICKY_ROUTING_MAIN_ACCOUNT_ID,
|
|
35182
36012
|
STICKY_ROUTING_ASSIGNMENT_TTL_MS,
|
|
36013
|
+
STATE_LAYOUT_PHASES,
|
|
36014
|
+
STATE_HOME_FILE_NAMES,
|
|
35183
36015
|
SECRET_KEY_EXACT2 as SECRET_KEY_EXACT,
|
|
35184
36016
|
RequestGzipLatch,
|
|
36017
|
+
RelocatedError,
|
|
35185
36018
|
ROUTING_MODES,
|
|
35186
36019
|
REQUIRED_BETAS,
|
|
36020
|
+
RELOCATED_MESSAGE,
|
|
35187
36021
|
REFRESH_SCOPE,
|
|
35188
36022
|
QuotaRefreshDeferred,
|
|
35189
36023
|
QuotaManager,
|
|
@@ -35219,7 +36053,14 @@ export {
|
|
|
35219
36053
|
NativeCustodyActivationError,
|
|
35220
36054
|
NATIVE_VAULT_NO_ACCOUNT_MESSAGE,
|
|
35221
36055
|
LOGGING_LEVELS,
|
|
36056
|
+
LEGACY_STATE_LAYOUT,
|
|
35222
36057
|
KILLSWITCH_COMMAND_NAME,
|
|
36058
|
+
HolderRegistrationError,
|
|
36059
|
+
HOLDER_RETRY_INTERVAL_MS,
|
|
36060
|
+
HOLDER_REGISTRATION_ERROR_MESSAGES,
|
|
36061
|
+
HOLDER_LOCK_TIMEOUT_MS,
|
|
36062
|
+
HOLDER_LOCK_NAME,
|
|
36063
|
+
HOLDER_FILE_NAME,
|
|
35223
36064
|
GZIP_REQUEST_BODIES_ENV,
|
|
35224
36065
|
GZIP_LATCH_TTL_MS,
|
|
35225
36066
|
FAST_MODE_BETA,
|