@character-foundry/character-foundry 0.4.1 → 0.4.2-dev.1765997746
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/charx.cjs +17 -38
- package/dist/charx.cjs.map +1 -1
- package/dist/charx.d.cts +27 -18
- package/dist/charx.d.ts +27 -18
- package/dist/charx.js +17 -38
- package/dist/charx.js.map +1 -1
- package/dist/exporter.cjs +36 -40
- package/dist/exporter.cjs.map +1 -1
- package/dist/exporter.d.cts +27 -18
- package/dist/exporter.d.ts +27 -18
- package/dist/exporter.js +36 -40
- package/dist/exporter.js.map +1 -1
- package/dist/federation.cjs +104 -36
- package/dist/federation.cjs.map +1 -1
- package/dist/federation.d.cts +62 -18
- package/dist/federation.d.ts +62 -18
- package/dist/federation.js +104 -36
- package/dist/federation.js.map +1 -1
- package/dist/index.cjs +36 -40
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +63 -42
- package/dist/index.d.ts +63 -42
- package/dist/index.js +36 -40
- package/dist/index.js.map +1 -1
- package/dist/loader.cjs +103 -17
- package/dist/loader.cjs.map +1 -1
- package/dist/loader.d.cts +56 -28
- package/dist/loader.d.ts +56 -28
- package/dist/loader.js +103 -17
- package/dist/loader.js.map +1 -1
- package/dist/lorebook.d.cts +51 -34
- package/dist/lorebook.d.ts +51 -34
- package/dist/normalizer.cjs +4 -4
- package/dist/normalizer.cjs.map +1 -1
- package/dist/normalizer.d.cts +90 -60
- package/dist/normalizer.d.ts +90 -60
- package/dist/normalizer.js +4 -4
- package/dist/normalizer.js.map +1 -1
- package/dist/png.cjs +4 -4
- package/dist/png.cjs.map +1 -1
- package/dist/png.d.cts +48 -32
- package/dist/png.d.ts +48 -32
- package/dist/png.js +4 -4
- package/dist/png.js.map +1 -1
- package/dist/schemas.cjs +9 -9
- package/dist/schemas.cjs.map +1 -1
- package/dist/schemas.d.cts +144 -96
- package/dist/schemas.d.ts +144 -96
- package/dist/schemas.js +9 -9
- package/dist/schemas.js.map +1 -1
- package/dist/voxta.cjs +23 -6
- package/dist/voxta.cjs.map +1 -1
- package/dist/voxta.d.cts +42 -28
- package/dist/voxta.d.ts +42 -28
- package/dist/voxta.js +23 -6
- package/dist/voxta.js.map +1 -1
- package/package.json +6 -6
package/dist/federation.cjs
CHANGED
|
@@ -50,6 +50,7 @@ __export(federation_exports, {
|
|
|
50
50
|
createAnnounceActivity: () => createAnnounceActivity,
|
|
51
51
|
createArchiveAdapter: () => createArchiveAdapter,
|
|
52
52
|
createBlockActivity: () => createBlockActivity,
|
|
53
|
+
createConsoleLogger: () => createConsoleLogger,
|
|
53
54
|
createCreateActivity: () => createCreateActivity,
|
|
54
55
|
createDeleteActivity: () => createDeleteActivity,
|
|
55
56
|
createFlagActivity: () => createFlagActivity,
|
|
@@ -64,6 +65,7 @@ __export(federation_exports, {
|
|
|
64
65
|
enableFederation: () => enableFederation,
|
|
65
66
|
generateActivityId: () => generateActivityId,
|
|
66
67
|
generateCardId: () => generateCardId,
|
|
68
|
+
getFederationLogger: () => getLogger,
|
|
67
69
|
handleActor: () => handleActor,
|
|
68
70
|
handleInbox: () => handleInbox,
|
|
69
71
|
handleNodeInfo: () => handleNodeInfo,
|
|
@@ -76,6 +78,8 @@ __export(federation_exports, {
|
|
|
76
78
|
parseForkActivity: () => parseForkActivity,
|
|
77
79
|
parseInstallActivity: () => parseInstallActivity,
|
|
78
80
|
parseSignatureHeader: () => parseSignatureHeader,
|
|
81
|
+
setFederationLogLevel: () => setLogLevel,
|
|
82
|
+
setFederationLogger: () => setLogger,
|
|
79
83
|
signRequest: () => signRequest,
|
|
80
84
|
stCharacterToCCv3: () => stCharacterToCCv3,
|
|
81
85
|
validateBlockActivityFields: () => validateBlockActivity,
|
|
@@ -133,6 +137,50 @@ function generateUUID() {
|
|
|
133
137
|
}
|
|
134
138
|
|
|
135
139
|
// ../federation/dist/index.js
|
|
140
|
+
var LEVELS = {
|
|
141
|
+
silent: 0,
|
|
142
|
+
error: 1,
|
|
143
|
+
warn: 2,
|
|
144
|
+
info: 3,
|
|
145
|
+
debug: 4
|
|
146
|
+
};
|
|
147
|
+
var noop = () => {
|
|
148
|
+
};
|
|
149
|
+
function createConsoleLogger(level = "warn") {
|
|
150
|
+
const severity = LEVELS[level] ?? LEVELS.warn;
|
|
151
|
+
const hasConsole = typeof console !== "undefined";
|
|
152
|
+
const c = hasConsole ? console : void 0;
|
|
153
|
+
const debugImpl = c?.debug ? c.debug.bind(c) : c?.log ? c.log.bind(c) : noop;
|
|
154
|
+
const infoImpl = c?.info ? c.info.bind(c) : c?.log ? c.log.bind(c) : noop;
|
|
155
|
+
const warnImpl = c?.warn ? c.warn.bind(c) : c?.log ? c.log.bind(c) : noop;
|
|
156
|
+
const errorImpl = c?.error ? c.error.bind(c) : c?.log ? c.log.bind(c) : noop;
|
|
157
|
+
return {
|
|
158
|
+
debug: severity >= LEVELS.debug ? debugImpl : noop,
|
|
159
|
+
info: severity >= LEVELS.info ? infoImpl : noop,
|
|
160
|
+
warn: severity >= LEVELS.warn ? warnImpl : noop,
|
|
161
|
+
error: severity >= LEVELS.error ? errorImpl : noop
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
var federationLogger = createConsoleLogger("warn");
|
|
165
|
+
function getLogger() {
|
|
166
|
+
return federationLogger;
|
|
167
|
+
}
|
|
168
|
+
function setLogger(logger) {
|
|
169
|
+
federationLogger = logger;
|
|
170
|
+
}
|
|
171
|
+
function setLogLevel(level) {
|
|
172
|
+
federationLogger = createConsoleLogger(level);
|
|
173
|
+
}
|
|
174
|
+
function configureLogger(options) {
|
|
175
|
+
if (!options) return;
|
|
176
|
+
if (options.logger) {
|
|
177
|
+
setLogger(options.logger);
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
if (options.logLevel) {
|
|
181
|
+
setLogLevel(options.logLevel);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
136
184
|
var ACTIVITY_CONTEXT = [
|
|
137
185
|
"https://www.w3.org/ns/activitystreams",
|
|
138
186
|
{
|
|
@@ -491,7 +539,7 @@ var SyncEngine = class {
|
|
|
491
539
|
try {
|
|
492
540
|
listener(event);
|
|
493
541
|
} catch (err) {
|
|
494
|
-
|
|
542
|
+
getLogger().error("[federation] Event listener error:", err);
|
|
495
543
|
}
|
|
496
544
|
}
|
|
497
545
|
}
|
|
@@ -1620,7 +1668,7 @@ var HttpPlatformAdapter = class extends BasePlatformAdapter {
|
|
|
1620
1668
|
const data = await response.json();
|
|
1621
1669
|
return this.config.transformers?.get ? this.config.transformers.get(data) : data;
|
|
1622
1670
|
} catch (err) {
|
|
1623
|
-
|
|
1671
|
+
getLogger().error(`[federation] Failed to get card ${localId}:`, err);
|
|
1624
1672
|
return null;
|
|
1625
1673
|
}
|
|
1626
1674
|
}
|
|
@@ -2172,27 +2220,14 @@ function parseSignatureHeader(header) {
|
|
|
2172
2220
|
return {
|
|
2173
2221
|
keyId: params.keyId,
|
|
2174
2222
|
algorithm: params.algorithm || "rsa-sha256",
|
|
2175
|
-
headers: (params.headers || "(request-target) host date").split(
|
|
2223
|
+
headers: (params.headers || "(request-target) host date").trim().split(/\s+/).filter(Boolean).map((h) => h.toLowerCase()),
|
|
2176
2224
|
signature: params.signature
|
|
2177
2225
|
};
|
|
2178
2226
|
}
|
|
2179
2227
|
function buildSigningString(method, path, headers, headerNames) {
|
|
2180
2228
|
const result = buildSigningStringStrict(method, path, headers, headerNames);
|
|
2181
2229
|
if (!result.success) {
|
|
2182
|
-
|
|
2183
|
-
const lines = [];
|
|
2184
|
-
for (const name of headerNames) {
|
|
2185
|
-
if (name === "(request-target)") {
|
|
2186
|
-
lines.push(`(request-target): ${method.toLowerCase()} ${path}`);
|
|
2187
|
-
} else if (name === "(created)" || name === "(expires)") {
|
|
2188
|
-
} else {
|
|
2189
|
-
const value = headers.get(name);
|
|
2190
|
-
if (value !== null) {
|
|
2191
|
-
lines.push(`${name.toLowerCase()}: ${value}`);
|
|
2192
|
-
}
|
|
2193
|
-
}
|
|
2194
|
-
}
|
|
2195
|
-
return lines.join("\n");
|
|
2230
|
+
throw new Error(result.error);
|
|
2196
2231
|
}
|
|
2197
2232
|
return result.signingString;
|
|
2198
2233
|
}
|
|
@@ -2201,16 +2236,17 @@ function buildSigningStringStrict(method, path, headers, headerNames) {
|
|
|
2201
2236
|
const missingHeaders = [];
|
|
2202
2237
|
const syntheticHeaders = /* @__PURE__ */ new Set(["(request-target)", "(created)", "(expires)"]);
|
|
2203
2238
|
for (const name of headerNames) {
|
|
2204
|
-
|
|
2239
|
+
const normalizedName = name.toLowerCase();
|
|
2240
|
+
if (normalizedName === "(request-target)") {
|
|
2205
2241
|
lines.push(`(request-target): ${method.toLowerCase()} ${path}`);
|
|
2206
|
-
} else if (
|
|
2207
|
-
} else if (
|
|
2242
|
+
} else if (normalizedName === "(created)") {
|
|
2243
|
+
} else if (normalizedName === "(expires)") {
|
|
2208
2244
|
} else {
|
|
2209
|
-
const value = headers.get(
|
|
2245
|
+
const value = headers.get(normalizedName);
|
|
2210
2246
|
if (value !== null) {
|
|
2211
|
-
lines.push(`${
|
|
2212
|
-
} else if (!syntheticHeaders.has(
|
|
2213
|
-
missingHeaders.push(
|
|
2247
|
+
lines.push(`${normalizedName}: ${value}`);
|
|
2248
|
+
} else if (!syntheticHeaders.has(normalizedName)) {
|
|
2249
|
+
missingHeaders.push(normalizedName);
|
|
2214
2250
|
}
|
|
2215
2251
|
}
|
|
2216
2252
|
}
|
|
@@ -2231,7 +2267,7 @@ async function verifyHttpSignature(parsed, publicKeyPem, method, path, headers,
|
|
|
2231
2267
|
if (options.strictHeaders) {
|
|
2232
2268
|
const strictResult = buildSigningStringStrict(method, path, headers, parsed.headers);
|
|
2233
2269
|
if (!strictResult.success) {
|
|
2234
|
-
|
|
2270
|
+
getLogger().warn(`[federation] Strict header verification failed: ${strictResult.error}`);
|
|
2235
2271
|
return false;
|
|
2236
2272
|
}
|
|
2237
2273
|
}
|
|
@@ -2251,7 +2287,7 @@ async function verifyHttpSignature(parsed, publicKeyPem, method, path, headers,
|
|
|
2251
2287
|
data
|
|
2252
2288
|
);
|
|
2253
2289
|
} catch (error) {
|
|
2254
|
-
|
|
2290
|
+
getLogger().error("[federation] Signature verification failed:", error);
|
|
2255
2291
|
return false;
|
|
2256
2292
|
}
|
|
2257
2293
|
}
|
|
@@ -2389,7 +2425,7 @@ async function importPublicKey(pem) {
|
|
|
2389
2425
|
["verify"]
|
|
2390
2426
|
);
|
|
2391
2427
|
} catch (error) {
|
|
2392
|
-
|
|
2428
|
+
getLogger().error("[federation] Failed to import public key:", error);
|
|
2393
2429
|
return null;
|
|
2394
2430
|
}
|
|
2395
2431
|
}
|
|
@@ -2405,7 +2441,7 @@ async function importPrivateKey(pem) {
|
|
|
2405
2441
|
["sign"]
|
|
2406
2442
|
);
|
|
2407
2443
|
} catch (error) {
|
|
2408
|
-
|
|
2444
|
+
getLogger().error("[federation] Failed to import private key:", error);
|
|
2409
2445
|
return null;
|
|
2410
2446
|
}
|
|
2411
2447
|
}
|
|
@@ -2434,9 +2470,31 @@ function extractHostFromActorId(actorId) {
|
|
|
2434
2470
|
return null;
|
|
2435
2471
|
}
|
|
2436
2472
|
}
|
|
2473
|
+
function timingSafeEqualString(a, b) {
|
|
2474
|
+
let mismatch = a.length === b.length ? 0 : 1;
|
|
2475
|
+
const maxLen = Math.max(a.length, b.length);
|
|
2476
|
+
for (let i = 0; i < maxLen; i++) {
|
|
2477
|
+
const aCode = a.charCodeAt(i) || 0;
|
|
2478
|
+
const bCode = b.charCodeAt(i) || 0;
|
|
2479
|
+
mismatch |= aCode ^ bCode;
|
|
2480
|
+
}
|
|
2481
|
+
return mismatch === 0;
|
|
2482
|
+
}
|
|
2437
2483
|
async function handleInbox(body, headers, options) {
|
|
2438
2484
|
assertFederationEnabled("handleInbox");
|
|
2439
2485
|
try {
|
|
2486
|
+
const normalizedHeaders = headers instanceof Headers ? headers : new Headers(headers);
|
|
2487
|
+
const networkKey = typeof options.networkKey === "string" ? options.networkKey : void 0;
|
|
2488
|
+
const networkKeyHeader = options.networkKeyHeader ?? "X-Foundry-Network-Key";
|
|
2489
|
+
if (networkKey && networkKey.length > 0) {
|
|
2490
|
+
const provided = normalizedHeaders.get(networkKeyHeader);
|
|
2491
|
+
if (!provided || !timingSafeEqualString(provided, networkKey)) {
|
|
2492
|
+
return {
|
|
2493
|
+
accepted: false,
|
|
2494
|
+
error: "Unauthorized: invalid or missing network key"
|
|
2495
|
+
};
|
|
2496
|
+
}
|
|
2497
|
+
}
|
|
2440
2498
|
if (options.moderationStore) {
|
|
2441
2499
|
const actorId = typeof body === "object" && body !== null && "actor" in body ? String(body.actor) : null;
|
|
2442
2500
|
if (actorId) {
|
|
@@ -2459,7 +2517,7 @@ async function handleInbox(body, headers, options) {
|
|
|
2459
2517
|
};
|
|
2460
2518
|
}
|
|
2461
2519
|
if (options.strictMode) {
|
|
2462
|
-
const signatureHeader =
|
|
2520
|
+
const signatureHeader = normalizedHeaders.get("signature");
|
|
2463
2521
|
if (!signatureHeader) {
|
|
2464
2522
|
return {
|
|
2465
2523
|
accepted: false,
|
|
@@ -2473,6 +2531,15 @@ async function handleInbox(body, headers, options) {
|
|
|
2473
2531
|
error: "Invalid Signature header format"
|
|
2474
2532
|
};
|
|
2475
2533
|
}
|
|
2534
|
+
if (networkKey && networkKey.length > 0) {
|
|
2535
|
+
const requiredSigned = networkKeyHeader.toLowerCase();
|
|
2536
|
+
if (!parsedSig.headers.includes(requiredSigned)) {
|
|
2537
|
+
return {
|
|
2538
|
+
accepted: false,
|
|
2539
|
+
error: `Strict mode: signature missing required header: ${requiredSigned}`
|
|
2540
|
+
};
|
|
2541
|
+
}
|
|
2542
|
+
}
|
|
2476
2543
|
const missingSignedHeaders = REQUIRED_SIGNED_HEADERS.filter(
|
|
2477
2544
|
(h) => !parsedSig.headers.includes(h)
|
|
2478
2545
|
);
|
|
@@ -2482,14 +2549,14 @@ async function handleInbox(body, headers, options) {
|
|
|
2482
2549
|
error: `Strict mode: signature missing required headers: ${missingSignedHeaders.join(", ")}`
|
|
2483
2550
|
};
|
|
2484
2551
|
}
|
|
2485
|
-
const dateHeader =
|
|
2552
|
+
const dateHeader = normalizedHeaders.get("date");
|
|
2486
2553
|
if (!dateHeader) {
|
|
2487
2554
|
return {
|
|
2488
2555
|
accepted: false,
|
|
2489
2556
|
error: "Strict mode: Date header required"
|
|
2490
2557
|
};
|
|
2491
2558
|
}
|
|
2492
|
-
const hostHeader =
|
|
2559
|
+
const hostHeader = normalizedHeaders.get("host");
|
|
2493
2560
|
if (!hostHeader) {
|
|
2494
2561
|
return {
|
|
2495
2562
|
accepted: false,
|
|
@@ -2532,7 +2599,7 @@ async function handleInbox(body, headers, options) {
|
|
|
2532
2599
|
error: `Invalid key ID or actor URL`
|
|
2533
2600
|
};
|
|
2534
2601
|
}
|
|
2535
|
-
const digestHeader =
|
|
2602
|
+
const digestHeader = normalizedHeaders.get("digest");
|
|
2536
2603
|
if (digestHeader) {
|
|
2537
2604
|
if (!options.rawBody) {
|
|
2538
2605
|
return {
|
|
@@ -2563,13 +2630,13 @@ async function handleInbox(body, headers, options) {
|
|
|
2563
2630
|
}
|
|
2564
2631
|
const method = options.method || "POST";
|
|
2565
2632
|
const path = options.path || "/inbox";
|
|
2566
|
-
const normalizedHeaders = headers instanceof Headers ? headers : new Headers(headers);
|
|
2567
2633
|
const isValid = await verifyHttpSignature(
|
|
2568
2634
|
parsedSig,
|
|
2569
2635
|
actor.publicKey.publicKeyPem,
|
|
2570
2636
|
method,
|
|
2571
2637
|
path,
|
|
2572
|
-
normalizedHeaders
|
|
2638
|
+
normalizedHeaders,
|
|
2639
|
+
{ strictHeaders: true }
|
|
2573
2640
|
);
|
|
2574
2641
|
if (!isValid) {
|
|
2575
2642
|
return {
|
|
@@ -3648,7 +3715,7 @@ var PolicyEngine = class {
|
|
|
3648
3715
|
if (!regex) {
|
|
3649
3716
|
const safetyWarning = checkRegexSafety(rule.pattern);
|
|
3650
3717
|
if (safetyWarning) {
|
|
3651
|
-
|
|
3718
|
+
getLogger().warn(`[moderation] Rule "${rule.name}": ${safetyWarning}`);
|
|
3652
3719
|
}
|
|
3653
3720
|
try {
|
|
3654
3721
|
regex = new RegExp(rule.pattern, "i");
|
|
@@ -3888,11 +3955,12 @@ function getEnvVar(name) {
|
|
|
3888
3955
|
return void 0;
|
|
3889
3956
|
}
|
|
3890
3957
|
function enableFederation(options) {
|
|
3958
|
+
configureLogger(options);
|
|
3891
3959
|
explicitlyEnabled = true;
|
|
3892
3960
|
envCheckSkipped = options?.skipEnvCheck ?? false;
|
|
3893
3961
|
const nodeEnv = getEnvVar("NODE_ENV");
|
|
3894
3962
|
if (nodeEnv === "development" || nodeEnv === "test") {
|
|
3895
|
-
|
|
3963
|
+
getLogger().warn(
|
|
3896
3964
|
"[character-foundry/federation] Federation enabled. WARNING: Verify HTTP signatures in production. Do NOT use in production with untrusted inputs without signature validation."
|
|
3897
3965
|
);
|
|
3898
3966
|
}
|