@rubytech/create-maxy 1.0.887 → 1.0.889
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/package.json +1 -1
- package/payload/platform/plugins/docs/references/plugins-guide.md +5 -5
- package/payload/platform/plugins/scheduling/PLUGIN.md +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/__tests__/time-resolve-description.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/__tests__/time-resolve-description.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/__tests__/time-resolve-description.test.js +16 -0
- package/payload/platform/plugins/scheduling/mcp/dist/__tests__/time-resolve-description.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/index.js +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/index.js.map +1 -1
- package/payload/platform/templates/account.json +0 -1
- package/payload/premium-plugins/real-agency/BUNDLE.md +1 -1
- package/payload/server/chunk-BGVO5GMU.js +11432 -0
- package/payload/server/chunk-S65GGO53.js +11629 -0
- package/payload/server/maxy-edge.js +1 -1
- package/payload/server/server.js +304 -75
package/payload/server/server.js
CHANGED
|
@@ -42,7 +42,6 @@ import {
|
|
|
42
42
|
load,
|
|
43
43
|
logPath,
|
|
44
44
|
pickComponentBytes,
|
|
45
|
-
readBundleSubPlugins,
|
|
46
45
|
reconcileEnabledPlugins,
|
|
47
46
|
recordFailedAttempt,
|
|
48
47
|
render,
|
|
@@ -53,7 +52,6 @@ import {
|
|
|
53
52
|
resolveBrowserTransport,
|
|
54
53
|
resolveClientIp,
|
|
55
54
|
resolveDefaultAgentSlug,
|
|
56
|
-
resolveEntitlement,
|
|
57
55
|
resolveUserAccounts,
|
|
58
56
|
safeJson,
|
|
59
57
|
sanitizeClientCorrId,
|
|
@@ -75,8 +73,9 @@ import {
|
|
|
75
73
|
verifyRemotePassword,
|
|
76
74
|
vncLog,
|
|
77
75
|
waitForExit,
|
|
76
|
+
walkPremiumBundles,
|
|
78
77
|
writeChromiumWrapper
|
|
79
|
-
} from "./chunk-
|
|
78
|
+
} from "./chunk-S65GGO53.js";
|
|
80
79
|
import {
|
|
81
80
|
CDP_PORT,
|
|
82
81
|
COMMERCIAL_MODE,
|
|
@@ -664,8 +663,8 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
664
663
|
};
|
|
665
664
|
|
|
666
665
|
// server/index.ts
|
|
667
|
-
import { readFileSync as
|
|
668
|
-
import { resolve as
|
|
666
|
+
import { readFileSync as readFileSync19, existsSync as existsSync25, watchFile } from "fs";
|
|
667
|
+
import { resolve as resolve22, join as join12, basename as basename4 } from "path";
|
|
669
668
|
import { homedir as homedir3 } from "os";
|
|
670
669
|
|
|
671
670
|
// app/lib/agent-slug-pattern.ts
|
|
@@ -1309,7 +1308,7 @@ var credsSaveQueue = Promise.resolve();
|
|
|
1309
1308
|
async function drainCredsSaveQueue(timeoutMs = 5e3) {
|
|
1310
1309
|
console.error(`${TAG3} draining credential save queue\u2026`);
|
|
1311
1310
|
const timer2 = new Promise(
|
|
1312
|
-
(
|
|
1311
|
+
(resolve23) => setTimeout(() => resolve23("timeout"), timeoutMs)
|
|
1313
1312
|
);
|
|
1314
1313
|
const result = await Promise.race([
|
|
1315
1314
|
credsSaveQueue.then(() => "drained"),
|
|
@@ -1437,11 +1436,11 @@ async function createWaSocket(opts) {
|
|
|
1437
1436
|
return sock;
|
|
1438
1437
|
}
|
|
1439
1438
|
async function waitForConnection(sock) {
|
|
1440
|
-
return new Promise((
|
|
1439
|
+
return new Promise((resolve23, reject) => {
|
|
1441
1440
|
const handler = (update) => {
|
|
1442
1441
|
if (update.connection === "open") {
|
|
1443
1442
|
sock.ev.off("connection.update", handler);
|
|
1444
|
-
|
|
1443
|
+
resolve23();
|
|
1445
1444
|
}
|
|
1446
1445
|
if (update.connection === "close") {
|
|
1447
1446
|
sock.ev.off("connection.update", handler);
|
|
@@ -1555,14 +1554,14 @@ ${inspected}`;
|
|
|
1555
1554
|
return inspect2(err, INSPECT_OPTS2);
|
|
1556
1555
|
}
|
|
1557
1556
|
function withTimeout(label, promise, timeoutMs) {
|
|
1558
|
-
return new Promise((
|
|
1557
|
+
return new Promise((resolve23, reject) => {
|
|
1559
1558
|
const timer2 = setTimeout(() => {
|
|
1560
1559
|
reject(new Error(`${label} timed out after ${timeoutMs}ms`));
|
|
1561
1560
|
}, timeoutMs);
|
|
1562
1561
|
promise.then(
|
|
1563
1562
|
(value) => {
|
|
1564
1563
|
clearTimeout(timer2);
|
|
1565
|
-
|
|
1564
|
+
resolve23(value);
|
|
1566
1565
|
},
|
|
1567
1566
|
(err) => {
|
|
1568
1567
|
clearTimeout(timer2);
|
|
@@ -2097,8 +2096,8 @@ async function persistWhatsAppMessage(input) {
|
|
|
2097
2096
|
const { givenName, familyName } = splitName(input.pushName);
|
|
2098
2097
|
const prev = sessionWriteLocks.get(input.cacheKey);
|
|
2099
2098
|
let release;
|
|
2100
|
-
const mine = new Promise((
|
|
2101
|
-
release =
|
|
2099
|
+
const mine = new Promise((resolve23) => {
|
|
2100
|
+
release = resolve23;
|
|
2102
2101
|
});
|
|
2103
2102
|
const chained = (prev ?? Promise.resolve()).then(() => mine);
|
|
2104
2103
|
sessionWriteLocks.set(input.cacheKey, chained);
|
|
@@ -3135,11 +3134,11 @@ async function connectWithReconnect(conn) {
|
|
|
3135
3134
|
console.error(
|
|
3136
3135
|
`${TAG13} reconnecting account=${conn.accountId} in ${delay}ms (attempt ${decision.nextAttempts}/${maxAttempts})`
|
|
3137
3136
|
);
|
|
3138
|
-
await new Promise((
|
|
3139
|
-
const timer2 = setTimeout(
|
|
3137
|
+
await new Promise((resolve23) => {
|
|
3138
|
+
const timer2 = setTimeout(resolve23, delay);
|
|
3140
3139
|
conn.abortController.signal.addEventListener("abort", () => {
|
|
3141
3140
|
clearTimeout(timer2);
|
|
3142
|
-
|
|
3141
|
+
resolve23();
|
|
3143
3142
|
}, { once: true });
|
|
3144
3143
|
});
|
|
3145
3144
|
}
|
|
@@ -3147,16 +3146,16 @@ async function connectWithReconnect(conn) {
|
|
|
3147
3146
|
}
|
|
3148
3147
|
}
|
|
3149
3148
|
function waitForDisconnectEvent(conn) {
|
|
3150
|
-
return new Promise((
|
|
3149
|
+
return new Promise((resolve23) => {
|
|
3151
3150
|
if (!conn.sock) {
|
|
3152
|
-
|
|
3151
|
+
resolve23();
|
|
3153
3152
|
return;
|
|
3154
3153
|
}
|
|
3155
3154
|
const sock = conn.sock;
|
|
3156
3155
|
const handler = (update) => {
|
|
3157
3156
|
if (update.connection === "close") {
|
|
3158
3157
|
sock.ev.off("connection.update", handler);
|
|
3159
|
-
|
|
3158
|
+
resolve23();
|
|
3160
3159
|
}
|
|
3161
3160
|
};
|
|
3162
3161
|
sock.ev.on("connection.update", handler);
|
|
@@ -3418,8 +3417,8 @@ async function handleInboundMessage(conn, msg) {
|
|
|
3418
3417
|
const conversationKey = isGroup ? remoteJid : senderPhone;
|
|
3419
3418
|
const debounceKey = `${conn.accountId}:${conversationKey}:${senderPhone}`;
|
|
3420
3419
|
let resolvePending;
|
|
3421
|
-
const sttPending = new Promise((
|
|
3422
|
-
resolvePending =
|
|
3420
|
+
const sttPending = new Promise((resolve23) => {
|
|
3421
|
+
resolvePending = resolve23;
|
|
3423
3422
|
});
|
|
3424
3423
|
if (conn.debouncer) conn.debouncer.registerPending(debounceKey, sttPending);
|
|
3425
3424
|
try {
|
|
@@ -3540,20 +3539,20 @@ async function probeApiKey() {
|
|
|
3540
3539
|
return result.status;
|
|
3541
3540
|
}
|
|
3542
3541
|
function checkPort(port2, timeoutMs = 500) {
|
|
3543
|
-
return new Promise((
|
|
3542
|
+
return new Promise((resolve23) => {
|
|
3544
3543
|
const socket = createConnection(port2, "127.0.0.1");
|
|
3545
3544
|
socket.setTimeout(timeoutMs);
|
|
3546
3545
|
socket.once("connect", () => {
|
|
3547
3546
|
socket.destroy();
|
|
3548
|
-
|
|
3547
|
+
resolve23(true);
|
|
3549
3548
|
});
|
|
3550
3549
|
socket.once("error", () => {
|
|
3551
3550
|
socket.destroy();
|
|
3552
|
-
|
|
3551
|
+
resolve23(false);
|
|
3553
3552
|
});
|
|
3554
3553
|
socket.once("timeout", () => {
|
|
3555
3554
|
socket.destroy();
|
|
3556
|
-
|
|
3555
|
+
resolve23(false);
|
|
3557
3556
|
});
|
|
3558
3557
|
});
|
|
3559
3558
|
}
|
|
@@ -5644,8 +5643,8 @@ async function startLogin(opts) {
|
|
|
5644
5643
|
resetActiveLogin(accountId);
|
|
5645
5644
|
let resolveQr = null;
|
|
5646
5645
|
let rejectQr = null;
|
|
5647
|
-
const qrPromise = new Promise((
|
|
5648
|
-
resolveQr =
|
|
5646
|
+
const qrPromise = new Promise((resolve23, reject) => {
|
|
5647
|
+
resolveQr = resolve23;
|
|
5649
5648
|
rejectQr = reject;
|
|
5650
5649
|
});
|
|
5651
5650
|
const qrTimer = setTimeout(
|
|
@@ -9557,8 +9556,8 @@ app23.get("/tunnels", requireAdminSession, async (c) => {
|
|
|
9557
9556
|
if (!correlationId) return err("session", "No active conversation for session \u2014 refresh chat.");
|
|
9558
9557
|
streamLogPath = streamLogPathFor(accountId, correlationId).streamLogPath;
|
|
9559
9558
|
const certPath = resolve13(homedir2(), brand.configDir, "cloudflared", "cert.pem");
|
|
9560
|
-
const { existsSync:
|
|
9561
|
-
if (!
|
|
9559
|
+
const { existsSync: existsSync26 } = await import("fs");
|
|
9560
|
+
if (!existsSync26(certPath)) {
|
|
9562
9561
|
return err("cert", `Cloudflare origin certificate is not on disk yet (${certPath}). Complete the Cloudflare login first by submitting the form once \u2014 the OAuth flow writes cert.pem.`);
|
|
9563
9562
|
}
|
|
9564
9563
|
const result = await runFormSpawn({
|
|
@@ -12935,8 +12934,232 @@ function startGraphHealthTimer() {
|
|
|
12935
12934
|
if (typeof timer.unref === "function") timer.unref();
|
|
12936
12935
|
}
|
|
12937
12936
|
|
|
12937
|
+
// ../lib/entitlement/src/index.ts
|
|
12938
|
+
import { createPublicKey, createHash as createHash3, verify as cryptoVerify } from "crypto";
|
|
12939
|
+
import { existsSync as existsSync24, readFileSync as readFileSync18, statSync as statSync8 } from "fs";
|
|
12940
|
+
import { resolve as resolve21 } from "path";
|
|
12941
|
+
|
|
12942
|
+
// ../lib/entitlement/src/canonicalize.ts
|
|
12943
|
+
function canonicalize(value) {
|
|
12944
|
+
if (value === null) return "null";
|
|
12945
|
+
if (typeof value === "boolean") return value ? "true" : "false";
|
|
12946
|
+
if (typeof value === "string") return JSON.stringify(value);
|
|
12947
|
+
if (typeof value === "number") {
|
|
12948
|
+
if (!Number.isFinite(value)) {
|
|
12949
|
+
throw new Error(`canonicalize: non-finite number rejected (${value})`);
|
|
12950
|
+
}
|
|
12951
|
+
if (Object.is(value, -0)) {
|
|
12952
|
+
throw new Error("canonicalize: negative zero rejected");
|
|
12953
|
+
}
|
|
12954
|
+
return JSON.stringify(value);
|
|
12955
|
+
}
|
|
12956
|
+
if (Array.isArray(value)) {
|
|
12957
|
+
return "[" + value.map(canonicalize).join(",") + "]";
|
|
12958
|
+
}
|
|
12959
|
+
if (typeof value === "object") {
|
|
12960
|
+
const keys = Object.keys(value).sort();
|
|
12961
|
+
const parts = [];
|
|
12962
|
+
for (const k of keys) {
|
|
12963
|
+
parts.push(JSON.stringify(k) + ":" + canonicalize(value[k]));
|
|
12964
|
+
}
|
|
12965
|
+
return "{" + parts.join(",") + "}";
|
|
12966
|
+
}
|
|
12967
|
+
throw new Error(`canonicalize: unsupported value type ${typeof value}`);
|
|
12968
|
+
}
|
|
12969
|
+
|
|
12970
|
+
// ../lib/entitlement/src/index.ts
|
|
12971
|
+
var PUBKEY_SHA256 = "8eee6bcb33545fd13b16d3199a5735ca5db5062834c7b49dfe4f23801d99db79";
|
|
12972
|
+
var GRACE_DAYS = 7;
|
|
12973
|
+
var GRACE_MS = GRACE_DAYS * 24 * 60 * 60 * 1e3;
|
|
12974
|
+
function pubkeyPath(brand) {
|
|
12975
|
+
return resolve21(brand.platformRoot, "lib", "entitlement", "rubytech-pubkey.pem");
|
|
12976
|
+
}
|
|
12977
|
+
var memo = null;
|
|
12978
|
+
function memoKey(mtimeMs, account) {
|
|
12979
|
+
const bucket = Math.floor(Date.now() / 6e4);
|
|
12980
|
+
return `${mtimeMs}:${bucket}:${account.accountId}:${account.customerEmail ?? ""}`;
|
|
12981
|
+
}
|
|
12982
|
+
var VALID_TIERS = /* @__PURE__ */ new Set(["solo", "family", "pro"]);
|
|
12983
|
+
function resolveEntitlement(brand, account) {
|
|
12984
|
+
if (brand.commercialMode !== true) {
|
|
12985
|
+
return logResolved(implicitTrust(account), null);
|
|
12986
|
+
}
|
|
12987
|
+
const entitlementPath = resolve21(brand.configDir, "entitlement.json");
|
|
12988
|
+
if (!existsSync24(entitlementPath)) {
|
|
12989
|
+
return logResolved(anonymousFallback("missing"), { reason: "missing" });
|
|
12990
|
+
}
|
|
12991
|
+
const stat6 = statSync8(entitlementPath);
|
|
12992
|
+
const key = memoKey(stat6.mtimeMs, account);
|
|
12993
|
+
if (memo && memo.key === key) {
|
|
12994
|
+
return memo.result;
|
|
12995
|
+
}
|
|
12996
|
+
const result = verifyAndResolve(brand, entitlementPath, account);
|
|
12997
|
+
memo = { key, result };
|
|
12998
|
+
return result;
|
|
12999
|
+
}
|
|
13000
|
+
function verifyAndResolve(brand, entitlementPath, account) {
|
|
13001
|
+
let pubkeyPem;
|
|
13002
|
+
try {
|
|
13003
|
+
pubkeyPem = readFileSync18(pubkeyPath(brand), "utf-8");
|
|
13004
|
+
} catch (err) {
|
|
13005
|
+
return logResolved(anonymousFallback("pubkey-missing"), {
|
|
13006
|
+
reason: "pubkey-missing"
|
|
13007
|
+
});
|
|
13008
|
+
}
|
|
13009
|
+
const pubkeyHash = createHash3("sha256").update(pubkeyPem).digest("hex");
|
|
13010
|
+
if (pubkeyHash !== PUBKEY_SHA256) {
|
|
13011
|
+
return logResolved(anonymousFallback("pubkey-tamper"), {
|
|
13012
|
+
reason: "pubkey-tamper"
|
|
13013
|
+
});
|
|
13014
|
+
}
|
|
13015
|
+
let envelope;
|
|
13016
|
+
try {
|
|
13017
|
+
envelope = JSON.parse(readFileSync18(entitlementPath, "utf-8"));
|
|
13018
|
+
} catch {
|
|
13019
|
+
return logResolved(anonymousFallback("malformed"), { reason: "malformed" });
|
|
13020
|
+
}
|
|
13021
|
+
if (typeof envelope !== "object" || envelope === null || typeof envelope.signature !== "string" || typeof envelope.payload !== "object" || envelope.payload === null) {
|
|
13022
|
+
return logResolved(anonymousFallback("malformed"), { reason: "malformed" });
|
|
13023
|
+
}
|
|
13024
|
+
const payload = envelope.payload;
|
|
13025
|
+
const signatureB64 = envelope.signature;
|
|
13026
|
+
let pubkey;
|
|
13027
|
+
try {
|
|
13028
|
+
pubkey = createPublicKey(pubkeyPem);
|
|
13029
|
+
} catch {
|
|
13030
|
+
return logResolved(anonymousFallback("pubkey-malformed"), {
|
|
13031
|
+
reason: "pubkey-malformed"
|
|
13032
|
+
});
|
|
13033
|
+
}
|
|
13034
|
+
let canonical;
|
|
13035
|
+
try {
|
|
13036
|
+
canonical = canonicalize(payload);
|
|
13037
|
+
} catch {
|
|
13038
|
+
return logResolved(anonymousFallback("payload-shape"), {
|
|
13039
|
+
reason: "payload-shape"
|
|
13040
|
+
});
|
|
13041
|
+
}
|
|
13042
|
+
let sigBuf;
|
|
13043
|
+
try {
|
|
13044
|
+
sigBuf = Buffer.from(signatureB64, "base64");
|
|
13045
|
+
} catch {
|
|
13046
|
+
return logResolved(anonymousFallback("signature-encoding"), {
|
|
13047
|
+
reason: "signature-encoding"
|
|
13048
|
+
});
|
|
13049
|
+
}
|
|
13050
|
+
const ok = cryptoVerify(null, Buffer.from(canonical, "utf-8"), pubkey, sigBuf);
|
|
13051
|
+
if (!ok) {
|
|
13052
|
+
return logResolved(anonymousFallback("signature"), { reason: "signature" });
|
|
13053
|
+
}
|
|
13054
|
+
if (typeof payload.accountId !== "string" || payload.accountId !== account.accountId) {
|
|
13055
|
+
return logResolved(anonymousFallback("binding-account"), {
|
|
13056
|
+
reason: "binding-account"
|
|
13057
|
+
});
|
|
13058
|
+
}
|
|
13059
|
+
const signedEmail = typeof payload.customerEmail === "string" ? payload.customerEmail : void 0;
|
|
13060
|
+
if (signedEmail !== void 0 || account.customerEmail !== void 0) {
|
|
13061
|
+
if (signedEmail !== account.customerEmail) {
|
|
13062
|
+
return logResolved(anonymousFallback("binding-email"), {
|
|
13063
|
+
reason: "binding-email"
|
|
13064
|
+
});
|
|
13065
|
+
}
|
|
13066
|
+
}
|
|
13067
|
+
const issuedRaw = payload.issued;
|
|
13068
|
+
const expiresRaw = payload.expires;
|
|
13069
|
+
if (typeof issuedRaw !== "string" || typeof expiresRaw !== "string") {
|
|
13070
|
+
return logResolved(anonymousFallback("temporal-shape"), {
|
|
13071
|
+
reason: "temporal-shape"
|
|
13072
|
+
});
|
|
13073
|
+
}
|
|
13074
|
+
const issued = Date.parse(issuedRaw);
|
|
13075
|
+
const expires = Date.parse(expiresRaw);
|
|
13076
|
+
const now = Date.now();
|
|
13077
|
+
if (Number.isNaN(issued) || Number.isNaN(expires)) {
|
|
13078
|
+
return logResolved(anonymousFallback("temporal-shape"), {
|
|
13079
|
+
reason: "temporal-shape"
|
|
13080
|
+
});
|
|
13081
|
+
}
|
|
13082
|
+
if (issued > now) {
|
|
13083
|
+
return logResolved(anonymousFallback("clock-skew"), {
|
|
13084
|
+
reason: "clock-skew"
|
|
13085
|
+
});
|
|
13086
|
+
}
|
|
13087
|
+
const tier = typeof payload.tier === "string" ? payload.tier : "";
|
|
13088
|
+
if (!VALID_TIERS.has(tier)) {
|
|
13089
|
+
return logResolved(anonymousFallback("tier-shape"), { reason: "tier-shape" });
|
|
13090
|
+
}
|
|
13091
|
+
const purchased = Array.isArray(payload.purchasedPlugins) ? payload.purchasedPlugins.filter((s) => typeof s === "string") : [];
|
|
13092
|
+
if (now <= expires) {
|
|
13093
|
+
return logResolved(
|
|
13094
|
+
{
|
|
13095
|
+
tier,
|
|
13096
|
+
purchasedPlugins: purchased,
|
|
13097
|
+
source: "signed",
|
|
13098
|
+
issued: issuedRaw,
|
|
13099
|
+
expires: expiresRaw
|
|
13100
|
+
},
|
|
13101
|
+
maybeTamperLine(account, tier)
|
|
13102
|
+
);
|
|
13103
|
+
}
|
|
13104
|
+
if (now <= expires + GRACE_MS) {
|
|
13105
|
+
return logResolved(
|
|
13106
|
+
{
|
|
13107
|
+
tier,
|
|
13108
|
+
purchasedPlugins: purchased,
|
|
13109
|
+
source: "signed-grace",
|
|
13110
|
+
issued: issuedRaw,
|
|
13111
|
+
expires: expiresRaw
|
|
13112
|
+
},
|
|
13113
|
+
maybeTamperLine(account, tier)
|
|
13114
|
+
);
|
|
13115
|
+
}
|
|
13116
|
+
return logResolved(anonymousFallback("expired"), { reason: "expired" });
|
|
13117
|
+
}
|
|
13118
|
+
function implicitTrust(account) {
|
|
13119
|
+
const tier = typeof account.tier === "string" ? account.tier : "";
|
|
13120
|
+
const purchased = Array.isArray(account.purchasedPlugins) ? account.purchasedPlugins : [];
|
|
13121
|
+
return {
|
|
13122
|
+
tier,
|
|
13123
|
+
purchasedPlugins: purchased,
|
|
13124
|
+
source: "implicit-trust",
|
|
13125
|
+
issued: null,
|
|
13126
|
+
expires: null
|
|
13127
|
+
};
|
|
13128
|
+
}
|
|
13129
|
+
function anonymousFallback(_reason) {
|
|
13130
|
+
return {
|
|
13131
|
+
tier: "solo",
|
|
13132
|
+
purchasedPlugins: [],
|
|
13133
|
+
source: "anonymous-fallback",
|
|
13134
|
+
issued: null,
|
|
13135
|
+
expires: null
|
|
13136
|
+
};
|
|
13137
|
+
}
|
|
13138
|
+
function maybeTamperLine(account, signedTier) {
|
|
13139
|
+
if (typeof account.tier === "string" && account.tier !== signedTier) {
|
|
13140
|
+
return { reason: "tampered", diskTier: account.tier, signedTier };
|
|
13141
|
+
}
|
|
13142
|
+
return null;
|
|
13143
|
+
}
|
|
13144
|
+
function logResolved(result, detail) {
|
|
13145
|
+
console.error(
|
|
13146
|
+
`[entitlement] resolved: tier=${result.tier} plugins=${result.purchasedPlugins.length} source=${result.source} issued=${result.issued ?? "-"} expires=${result.expires ?? "-"}`
|
|
13147
|
+
);
|
|
13148
|
+
if (detail && "diskTier" in detail) {
|
|
13149
|
+
console.error(
|
|
13150
|
+
`[entitlement] tampered: tier-on-disk=${detail.diskTier} signed=${detail.signedTier} action=using-signed`
|
|
13151
|
+
);
|
|
13152
|
+
} else if (detail && result.source === "anonymous-fallback") {
|
|
13153
|
+
const action = detail.reason === "expired" || detail.reason === "missing" ? "lock" : "degrade";
|
|
13154
|
+
console.error(
|
|
13155
|
+
`[entitlement] verify-failed: reason=${detail.reason} action=${action}`
|
|
13156
|
+
);
|
|
13157
|
+
}
|
|
13158
|
+
return result;
|
|
13159
|
+
}
|
|
13160
|
+
|
|
12938
13161
|
// server/index.ts
|
|
12939
|
-
import { existsSync as existsSyncBoot } from "fs";
|
|
13162
|
+
import { existsSync as existsSyncBoot, readFileSync as readFileSyncBoot, writeFileSync as writeFileSyncBoot } from "fs";
|
|
12940
13163
|
import { resolve as resolveBoot } from "path";
|
|
12941
13164
|
function requestIsTlsTerminated(c) {
|
|
12942
13165
|
const remote = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
@@ -12954,12 +13177,12 @@ function clientFrom(c) {
|
|
|
12954
13177
|
var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT || "";
|
|
12955
13178
|
var BRAND_JSON_PATH = PLATFORM_ROOT7 ? join12(PLATFORM_ROOT7, "config", "brand.json") : "";
|
|
12956
13179
|
var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", domain: "getmaxy.com" };
|
|
12957
|
-
if (BRAND_JSON_PATH && !
|
|
13180
|
+
if (BRAND_JSON_PATH && !existsSync25(BRAND_JSON_PATH)) {
|
|
12958
13181
|
console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
|
|
12959
13182
|
}
|
|
12960
|
-
if (BRAND_JSON_PATH &&
|
|
13183
|
+
if (BRAND_JSON_PATH && existsSync25(BRAND_JSON_PATH)) {
|
|
12961
13184
|
try {
|
|
12962
|
-
const parsed = JSON.parse(
|
|
13185
|
+
const parsed = JSON.parse(readFileSync19(BRAND_JSON_PATH, "utf-8"));
|
|
12963
13186
|
BRAND = { ...BRAND, ...parsed };
|
|
12964
13187
|
} catch (err) {
|
|
12965
13188
|
console.error(`[brand] Failed to parse brand.json: ${err.message}`);
|
|
@@ -12981,8 +13204,8 @@ var brandLoginOpts = {
|
|
|
12981
13204
|
var ALIAS_DOMAINS_PATH2 = join12(homedir3(), BRAND.configDir, "alias-domains.json");
|
|
12982
13205
|
function loadAliasDomains() {
|
|
12983
13206
|
try {
|
|
12984
|
-
if (!
|
|
12985
|
-
const parsed = JSON.parse(
|
|
13207
|
+
if (!existsSync25(ALIAS_DOMAINS_PATH2)) return null;
|
|
13208
|
+
const parsed = JSON.parse(readFileSync19(ALIAS_DOMAINS_PATH2, "utf-8"));
|
|
12986
13209
|
if (!Array.isArray(parsed)) {
|
|
12987
13210
|
console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
|
|
12988
13211
|
return null;
|
|
@@ -13356,20 +13579,20 @@ app39.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
13356
13579
|
console.error(`[agent-assets] no-account slug=${slug} file=${filename}`);
|
|
13357
13580
|
return c.text("Not found", 404);
|
|
13358
13581
|
}
|
|
13359
|
-
const filePath =
|
|
13360
|
-
const expectedDir =
|
|
13582
|
+
const filePath = resolve22(account.accountDir, "agents", slug, "assets", filename);
|
|
13583
|
+
const expectedDir = resolve22(account.accountDir, "agents", slug, "assets");
|
|
13361
13584
|
if (!filePath.startsWith(expectedDir + "/")) {
|
|
13362
13585
|
console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
|
|
13363
13586
|
return c.text("Forbidden", 403);
|
|
13364
13587
|
}
|
|
13365
|
-
if (!
|
|
13588
|
+
if (!existsSync25(filePath)) {
|
|
13366
13589
|
console.error(`[agent-assets] serve slug=${slug} file=${filename} status=404`);
|
|
13367
13590
|
return c.text("Not found", 404);
|
|
13368
13591
|
}
|
|
13369
13592
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
13370
13593
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
13371
13594
|
console.log(`[agent-assets] serve slug=${slug} file=${filename} status=200`);
|
|
13372
|
-
const body =
|
|
13595
|
+
const body = readFileSync19(filePath);
|
|
13373
13596
|
return c.body(body, 200, {
|
|
13374
13597
|
"Content-Type": contentType,
|
|
13375
13598
|
"Cache-Control": "public, max-age=3600"
|
|
@@ -13386,20 +13609,20 @@ app39.get("/generated/:filename", (c) => {
|
|
|
13386
13609
|
console.error(`[generated] serve file=${filename} status=404`);
|
|
13387
13610
|
return c.text("Not found", 404);
|
|
13388
13611
|
}
|
|
13389
|
-
const filePath =
|
|
13390
|
-
const expectedDir =
|
|
13612
|
+
const filePath = resolve22(account.accountDir, "generated", filename);
|
|
13613
|
+
const expectedDir = resolve22(account.accountDir, "generated");
|
|
13391
13614
|
if (!filePath.startsWith(expectedDir + "/")) {
|
|
13392
13615
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
13393
13616
|
return c.text("Forbidden", 403);
|
|
13394
13617
|
}
|
|
13395
|
-
if (!
|
|
13618
|
+
if (!existsSync25(filePath)) {
|
|
13396
13619
|
console.error(`[generated] serve file=${filename} status=404`);
|
|
13397
13620
|
return c.text("Not found", 404);
|
|
13398
13621
|
}
|
|
13399
13622
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
13400
13623
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
13401
13624
|
console.log(`[generated] serve file=${filename} status=200`);
|
|
13402
|
-
const body =
|
|
13625
|
+
const body = readFileSync19(filePath);
|
|
13403
13626
|
return c.body(body, 200, {
|
|
13404
13627
|
"Content-Type": contentType,
|
|
13405
13628
|
"Cache-Control": "public, max-age=86400"
|
|
@@ -13409,9 +13632,9 @@ app39.route("/sites", sites_default);
|
|
|
13409
13632
|
var htmlCache = /* @__PURE__ */ new Map();
|
|
13410
13633
|
var brandLogoPath = "/brand/maxy-monochrome.png";
|
|
13411
13634
|
var brandIconPath = "/brand/maxy-monochrome.png";
|
|
13412
|
-
if (BRAND_JSON_PATH &&
|
|
13635
|
+
if (BRAND_JSON_PATH && existsSync25(BRAND_JSON_PATH)) {
|
|
13413
13636
|
try {
|
|
13414
|
-
const fullBrand = JSON.parse(
|
|
13637
|
+
const fullBrand = JSON.parse(readFileSync19(BRAND_JSON_PATH, "utf-8"));
|
|
13415
13638
|
if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
|
|
13416
13639
|
brandIconPath = fullBrand.assets?.icon ? `/brand/${fullBrand.assets.icon}` : brandLogoPath;
|
|
13417
13640
|
} catch {
|
|
@@ -13429,8 +13652,8 @@ function readInstalledVersion() {
|
|
|
13429
13652
|
try {
|
|
13430
13653
|
if (!PLATFORM_ROOT7) return "unknown";
|
|
13431
13654
|
const versionFile = join12(PLATFORM_ROOT7, "config", `.${BRAND.hostname}-version`);
|
|
13432
|
-
if (!
|
|
13433
|
-
const content =
|
|
13655
|
+
if (!existsSync25(versionFile)) return "unknown";
|
|
13656
|
+
const content = readFileSync19(versionFile, "utf-8").trim();
|
|
13434
13657
|
return content || "unknown";
|
|
13435
13658
|
} catch {
|
|
13436
13659
|
return "unknown";
|
|
@@ -13471,7 +13694,7 @@ var clientErrorReporterScript = `<script>
|
|
|
13471
13694
|
function cachedHtml(file) {
|
|
13472
13695
|
let html = htmlCache.get(file);
|
|
13473
13696
|
if (!html) {
|
|
13474
|
-
html =
|
|
13697
|
+
html = readFileSync19(resolve22(process.cwd(), "public", file), "utf-8");
|
|
13475
13698
|
const productNameEsc = escapeHtml(BRAND.productName);
|
|
13476
13699
|
html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
|
|
13477
13700
|
html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
|
|
@@ -13490,13 +13713,13 @@ function loadBrandingCache(agentSlug) {
|
|
|
13490
13713
|
const configDir2 = join12(homedir3(), BRAND.configDir);
|
|
13491
13714
|
try {
|
|
13492
13715
|
const accountJsonPath = join12(configDir2, "account.json");
|
|
13493
|
-
if (!
|
|
13494
|
-
const account = JSON.parse(
|
|
13716
|
+
if (!existsSync25(accountJsonPath)) return null;
|
|
13717
|
+
const account = JSON.parse(readFileSync19(accountJsonPath, "utf-8"));
|
|
13495
13718
|
const accountId = account.accountId;
|
|
13496
13719
|
if (!accountId) return null;
|
|
13497
13720
|
const cachePath = join12(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
|
|
13498
|
-
if (!
|
|
13499
|
-
return JSON.parse(
|
|
13721
|
+
if (!existsSync25(cachePath)) return null;
|
|
13722
|
+
return JSON.parse(readFileSync19(cachePath, "utf-8"));
|
|
13500
13723
|
} catch {
|
|
13501
13724
|
return null;
|
|
13502
13725
|
}
|
|
@@ -13505,8 +13728,8 @@ function resolveDefaultSlug() {
|
|
|
13505
13728
|
try {
|
|
13506
13729
|
const configDir2 = join12(homedir3(), BRAND.configDir);
|
|
13507
13730
|
const accountJsonPath = join12(configDir2, "account.json");
|
|
13508
|
-
if (!
|
|
13509
|
-
const account = JSON.parse(
|
|
13731
|
+
if (!existsSync25(accountJsonPath)) return null;
|
|
13732
|
+
const account = JSON.parse(readFileSync19(accountJsonPath, "utf-8"));
|
|
13510
13733
|
return account.defaultAgent || null;
|
|
13511
13734
|
} catch {
|
|
13512
13735
|
return null;
|
|
@@ -13579,7 +13802,7 @@ app39.use("/vnc-popout.html", logViewerFetch);
|
|
|
13579
13802
|
app39.get("/vnc-popout.html", (c) => {
|
|
13580
13803
|
let html = htmlCache.get("vnc-popout.html");
|
|
13581
13804
|
if (!html) {
|
|
13582
|
-
html =
|
|
13805
|
+
html = readFileSync19(resolve22(process.cwd(), "public", "vnc-popout.html"), "utf-8");
|
|
13583
13806
|
const name = escapeHtml(BRAND.productName);
|
|
13584
13807
|
html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
|
|
13585
13808
|
html = html.replace("</head>", ` ${brandScript}
|
|
@@ -13685,8 +13908,8 @@ try {
|
|
|
13685
13908
|
(async () => {
|
|
13686
13909
|
try {
|
|
13687
13910
|
let userId = "";
|
|
13688
|
-
if (
|
|
13689
|
-
const users = JSON.parse(
|
|
13911
|
+
if (existsSync25(USERS_FILE)) {
|
|
13912
|
+
const users = JSON.parse(readFileSync19(USERS_FILE, "utf-8").trim() || "[]");
|
|
13690
13913
|
userId = users[0]?.userId ?? "";
|
|
13691
13914
|
}
|
|
13692
13915
|
await backfillNullUserIdConversations(userId);
|
|
@@ -13703,8 +13926,8 @@ try {
|
|
|
13703
13926
|
})();
|
|
13704
13927
|
(async () => {
|
|
13705
13928
|
try {
|
|
13706
|
-
if (!
|
|
13707
|
-
const usersRaw =
|
|
13929
|
+
if (!existsSync25(USERS_FILE)) return;
|
|
13930
|
+
const usersRaw = readFileSync19(USERS_FILE, "utf-8").trim();
|
|
13708
13931
|
if (!usersRaw) return;
|
|
13709
13932
|
const users = JSON.parse(usersRaw);
|
|
13710
13933
|
const userId = users[0]?.userId;
|
|
@@ -13742,25 +13965,31 @@ var configDirForWhatsApp = basename4(MAXY_DIR) || ".maxy";
|
|
|
13742
13965
|
var bootAccount = resolveAccount();
|
|
13743
13966
|
var bootAccountConfig = bootAccount?.config;
|
|
13744
13967
|
var bootPublicAgent = bootAccount ? resolvePublicAgent(bootAccount.accountDir, { accountId: bootAccount.accountId })?.slug ?? null : null;
|
|
13968
|
+
if (bootAccount) {
|
|
13969
|
+
const accountJsonPath = resolveBoot(bootAccount.accountDir, "account.json");
|
|
13970
|
+
if (existsSyncBoot(accountJsonPath)) {
|
|
13971
|
+
try {
|
|
13972
|
+
const parsed = JSON.parse(readFileSyncBoot(accountJsonPath, "utf-8"));
|
|
13973
|
+
if ("purchasedPlugins" in parsed) {
|
|
13974
|
+
delete parsed.purchasedPlugins;
|
|
13975
|
+
writeFileSyncBoot(accountJsonPath, JSON.stringify(parsed, null, 2) + "\n");
|
|
13976
|
+
console.log(`[account-scrub] removed-purchasedPlugins=true accountId=${bootAccount.accountId}`);
|
|
13977
|
+
}
|
|
13978
|
+
} catch (err) {
|
|
13979
|
+
console.error(`[account-scrub] read/write failed accountId=${bootAccount.accountId} \u2014 ${err instanceof Error ? err.message : String(err)}`);
|
|
13980
|
+
}
|
|
13981
|
+
}
|
|
13982
|
+
}
|
|
13745
13983
|
var bootEntitlement = bootAccountConfig ? resolveEntitlement(
|
|
13746
13984
|
{ configDir: MAXY_DIR, platformRoot: PLATFORM_ROOT, commercialMode: COMMERCIAL_MODE },
|
|
13747
13985
|
{
|
|
13748
13986
|
accountId: typeof bootAccountConfig.accountId === "string" ? bootAccountConfig.accountId : "",
|
|
13749
13987
|
customerEmail: typeof bootAccountConfig.customerEmail === "string" ? bootAccountConfig.customerEmail : void 0,
|
|
13750
|
-
tier: typeof bootAccountConfig.tier === "string" ? bootAccountConfig.tier : void 0
|
|
13751
|
-
purchasedPlugins: Array.isArray(bootAccountConfig.purchasedPlugins) ? bootAccountConfig.purchasedPlugins : void 0
|
|
13988
|
+
tier: typeof bootAccountConfig.tier === "string" ? bootAccountConfig.tier : void 0
|
|
13752
13989
|
}
|
|
13753
13990
|
) : null;
|
|
13754
|
-
autoDeliverPremiumPlugins(
|
|
13755
|
-
|
|
13756
|
-
bootAccount?.accountDir,
|
|
13757
|
-
bootAccount?.config
|
|
13758
|
-
);
|
|
13759
|
-
reconcileEnabledPlugins(
|
|
13760
|
-
bootAccount?.accountDir,
|
|
13761
|
-
bootAccount?.config,
|
|
13762
|
-
bootEntitlement?.purchasedPlugins ?? void 0
|
|
13763
|
-
);
|
|
13991
|
+
autoDeliverPremiumPlugins();
|
|
13992
|
+
reconcileEnabledPlugins(bootAccount?.accountDir, bootAccount?.config);
|
|
13764
13993
|
(async () => {
|
|
13765
13994
|
if (!bootAccount) return;
|
|
13766
13995
|
try {
|
|
@@ -13806,11 +14035,11 @@ for (const dir of bootEnabled) {
|
|
|
13806
14035
|
bootDelivered.push(dir);
|
|
13807
14036
|
}
|
|
13808
14037
|
var bootEnabledNotDelivered = [];
|
|
13809
|
-
|
|
14038
|
+
var bootBundles = walkPremiumBundles();
|
|
14039
|
+
if (bootBundles.length > 0) {
|
|
13810
14040
|
const enabledSet = new Set(bootEnabled);
|
|
13811
|
-
for (const
|
|
13812
|
-
|
|
13813
|
-
for (const sub of readBundleSubPlugins(bundlePath)) {
|
|
14041
|
+
for (const { subs } of bootBundles) {
|
|
14042
|
+
for (const sub of subs) {
|
|
13814
14043
|
if (!enabledSet.has(sub)) bootEnabledNotDelivered.push(sub);
|
|
13815
14044
|
}
|
|
13816
14045
|
}
|
|
@@ -13824,7 +14053,7 @@ if (bootAccountConfig?.whatsapp) {
|
|
|
13824
14053
|
}
|
|
13825
14054
|
init({
|
|
13826
14055
|
configDir: configDirForWhatsApp,
|
|
13827
|
-
platformRoot:
|
|
14056
|
+
platformRoot: resolve22(process.env.MAXY_PLATFORM_ROOT ?? join12(__dirname, "..")),
|
|
13828
14057
|
accountConfig: bootAccountConfig,
|
|
13829
14058
|
onMessage: async (msg) => {
|
|
13830
14059
|
try {
|