@rubytech/create-maxy 1.0.772 → 1.0.773
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/admin/mcp/dist/index.js +43 -4
- package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/admin/skills/business-profile/SKILL.md +5 -6
- package/payload/platform/plugins/admin/skills/onboarding/SKILL.md +5 -6
- package/payload/server/{chunk-XHFMXKXI.js → chunk-2HBD6IRL.js} +63 -0
- package/payload/server/{chunk-57S5JC7G.js → chunk-PIMJJCOQ.js} +1 -1
- package/payload/server/{client-pool-5V5GX3UT.js → client-pool-U3A5YUO7.js} +1 -1
- package/payload/server/maxy-edge.js +2 -2
- package/payload/server/public/assets/{admin-CFttroHB.js → admin-C4CTVtBu.js} +2 -2
- package/payload/server/public/index.html +1 -1
- package/payload/server/server.js +24 -4
- package/payload/platform/plugins/memory/mcp/dist/lib/semantic-chunker.d.ts +0 -61
- package/payload/platform/plugins/memory/mcp/dist/lib/semantic-chunker.d.ts.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/semantic-chunker.js +0 -266
- package/payload/platform/plugins/memory/mcp/dist/lib/semantic-chunker.js.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/index.d.ts +0 -2
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/index.d.ts.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/index.js +0 -293
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/index.js.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/lib/crypto.d.ts +0 -10
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/lib/crypto.d.ts.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/lib/crypto.js +0 -88
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/lib/crypto.js.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/lib/loop-api.d.ts +0 -80
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/lib/loop-api.d.ts.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/lib/loop-api.js +0 -355
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/lib/loop-api.js.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/lib/neo4j.d.ts +0 -5
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/lib/neo4j.d.ts.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/lib/neo4j.js +0 -34
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/lib/neo4j.js.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/customer-preferences.d.ts +0 -10
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/customer-preferences.d.ts.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/customer-preferences.js +0 -24
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/customer-preferences.js.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/feedback-list.d.ts +0 -6
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/feedback-list.d.ts.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/feedback-list.js +0 -18
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/feedback-list.js.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/feedback.d.ts +0 -16
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/feedback.d.ts.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/feedback.js +0 -35
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/feedback.js.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/key-deregister.d.ts +0 -5
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/key-deregister.d.ts.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/key-deregister.js +0 -19
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/key-deregister.js.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/key-list.d.ts +0 -4
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/key-list.d.ts.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/key-list.js +0 -14
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/key-list.js.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/key-register.d.ts +0 -9
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/key-register.d.ts.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/key-register.js +0 -60
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/key-register.js.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-enquiry.d.ts +0 -13
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-enquiry.d.ts.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-enquiry.js +0 -41
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-enquiry.js.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-match-batch.d.ts +0 -9
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-match-batch.d.ts.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-match-batch.js +0 -16
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-match-batch.js.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-match-request.d.ts +0 -15
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-match-request.d.ts.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-match-request.js +0 -11
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-match-request.js.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-match.d.ts +0 -10
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-match.d.ts.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-match.js +0 -39
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-match.js.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/people-detail.d.ts +0 -9
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/people-detail.d.ts.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/people-detail.js +0 -125
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/people-detail.js.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/people-list.d.ts +0 -7
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/people-list.d.ts.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/people-list.js +0 -16
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/people-list.js.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/people-search.d.ts +0 -18
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/people-search.d.ts.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/people-search.js +0 -87
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/people-search.js.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/properties-list.d.ts +0 -7
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/properties-list.d.ts.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/properties-list.js +0 -19
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/properties-list.js.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-detail.d.ts +0 -10
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-detail.d.ts.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-detail.js +0 -82
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-detail.js.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-listed.d.ts +0 -12
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-listed.d.ts.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-listed.js +0 -32
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-listed.js.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-request.d.ts +0 -15
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-request.d.ts.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-request.js +0 -11
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-request.js.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-search.d.ts +0 -16
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-search.d.ts.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-search.js +0 -41
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-search.js.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/supplier.d.ts +0 -13
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/supplier.d.ts.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/supplier.js +0 -49
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/supplier.js.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/team-availability.d.ts +0 -7
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/team-availability.d.ts.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/team-availability.js +0 -19
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/team-availability.js.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/team-info.d.ts +0 -5
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/team-info.d.ts.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/team-info.js +0 -32
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/team-info.js.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-create.d.ts +0 -14
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-create.d.ts.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-create.js +0 -11
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-create.js.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-detail.d.ts +0 -9
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-detail.d.ts.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-detail.js +0 -85
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-detail.js.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-search.d.ts +0 -13
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-search.d.ts.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-search.js +0 -44
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-search.js.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-update.d.ts +0 -14
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-update.d.ts.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-update.js +0 -18
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-update.js.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewings-list.d.ts +0 -9
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewings-list.d.ts.map +0 -1
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewings-list.js +0 -25
- package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewings-list.js.map +0 -1
- package/payload/server/chunk-26QT2HEQ.js +0 -9483
- package/payload/server/chunk-2T4RRIJK.js +0 -9462
- package/payload/server/chunk-2W7O63CK.js +0 -3052
- package/payload/server/chunk-32ZHQJNX.js +0 -11395
- package/payload/server/chunk-3KDVGWPQ.js +0 -2920
- package/payload/server/chunk-3RBKKDHC.js +0 -783
- package/payload/server/chunk-3VVHVJK2.js +0 -11405
- package/payload/server/chunk-43JK6WNK.js +0 -3057
- package/payload/server/chunk-5YIXIF6C.js +0 -726
- package/payload/server/chunk-7ODDM7L4.js +0 -12370
- package/payload/server/chunk-A5K3CFMI.js +0 -12297
- package/payload/server/chunk-AIWWYOBH.js +0 -9439
- package/payload/server/chunk-B54KBAK4.js +0 -72
- package/payload/server/chunk-BIOIXN5A.js +0 -12165
- package/payload/server/chunk-D53LK5YC.js +0 -12171
- package/payload/server/chunk-EIQT6QDH.js +0 -9562
- package/payload/server/chunk-FM5JMRED.js +0 -12033
- package/payload/server/chunk-HPU24BXP.js +0 -12173
- package/payload/server/chunk-HU5FSQYA.js +0 -12186
- package/payload/server/chunk-IAIGB5WN.js +0 -11406
- package/payload/server/chunk-IO2WQEY4.js +0 -9562
- package/payload/server/chunk-JDT3MGUY.js +0 -12165
- package/payload/server/chunk-JLVVVQN7.js +0 -9447
- package/payload/server/chunk-K7GQ5RMN.js +0 -12172
- package/payload/server/chunk-LQ5GSMEW.js +0 -12036
- package/payload/server/chunk-MPWGVFU2.js +0 -12340
- package/payload/server/chunk-O2FWENOD.js +0 -11530
- package/payload/server/chunk-PE76FPYP.js +0 -12040
- package/payload/server/chunk-PQ6LDXZ4.js +0 -2997
- package/payload/server/chunk-Q6NDXCM6.js +0 -11448
- package/payload/server/chunk-QXAUMZXQ.js +0 -9512
- package/payload/server/chunk-S3M2NZMA.js +0 -3136
- package/payload/server/chunk-SGBNY4NP.js +0 -9540
- package/payload/server/chunk-SKXO42T6.js +0 -2934
- package/payload/server/chunk-SPTD7L7Z.js +0 -9474
- package/payload/server/chunk-TKYZ7AEB.js +0 -3142
- package/payload/server/chunk-TXPEEAV6.js +0 -2997
- package/payload/server/chunk-U3W5YIXU.js +0 -11450
- package/payload/server/chunk-U5JPRUYZ.js +0 -12298
- package/payload/server/chunk-UFLV7I6N.js +0 -11678
- package/payload/server/chunk-ULVR2RRY.js +0 -9439
- package/payload/server/chunk-VOD2IZ6J.js +0 -2934
- package/payload/server/chunk-VS7CRH4M.js +0 -9439
- package/payload/server/chunk-W6ZUNLLS.js +0 -9446
- package/payload/server/chunk-WW464F23.js +0 -9512
- package/payload/server/chunk-Y57ACANQ.js +0 -12292
- package/payload/server/chunk-ZK3VNR7Y.js +0 -9510
- package/payload/server/chunk-ZL2A4ROK.js +0 -11416
- package/payload/server/client-pool-67NUIL7H.js +0 -28
- package/payload/server/client-pool-CX2MFW75.js +0 -28
- package/payload/server/client-pool-DQBHSKAF.js +0 -28
- package/payload/server/client-pool-I5TCP7WI.js +0 -28
- package/payload/server/client-pool-ISMYJXCU.js +0 -28
- package/payload/server/client-pool-J4ZHJ6Z3.js +0 -28
- package/payload/server/client-pool-SGPHSYLK.js +0 -28
- package/payload/server/client-pool-TCKGDZLE.js +0 -28
- package/payload/server/client-pool-TULUIO6M.js +0 -28
- package/payload/server/upgrade-progress-server.js +0 -83
|
@@ -1,726 +0,0 @@
|
|
|
1
|
-
var __create = Object.create;
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
-
var __commonJS = (cb, mod) => function __require() {
|
|
8
|
-
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
19
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
20
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
21
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
22
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
23
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
24
|
-
mod
|
|
25
|
-
));
|
|
26
|
-
|
|
27
|
-
// app/lib/paths.ts
|
|
28
|
-
import { homedir } from "os";
|
|
29
|
-
import { resolve, join } from "path";
|
|
30
|
-
import { existsSync, readFileSync } from "fs";
|
|
31
|
-
var configDirName = ".maxy";
|
|
32
|
-
var platformRoot = process.env.MAXY_PLATFORM_ROOT;
|
|
33
|
-
if (platformRoot) {
|
|
34
|
-
const brandPath = join(platformRoot, "config", "brand.json");
|
|
35
|
-
if (existsSync(brandPath)) {
|
|
36
|
-
try {
|
|
37
|
-
const brand = JSON.parse(readFileSync(brandPath, "utf-8"));
|
|
38
|
-
if (brand.configDir) configDirName = brand.configDir;
|
|
39
|
-
} catch {
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
var MAXY_DIR = resolve(homedir(), configDirName);
|
|
44
|
-
var PLATFORM_ROOT = process.env.MAXY_PLATFORM_ROOT ?? resolve(process.cwd(), "..");
|
|
45
|
-
var USERS_FILE = resolve(PLATFORM_ROOT, "config", "users.json");
|
|
46
|
-
var LOG_DIR = resolve(MAXY_DIR, "logs");
|
|
47
|
-
var BIN_DIR = resolve(MAXY_DIR, "bin");
|
|
48
|
-
var REMOTE_PASSWORD_FILE = resolve(MAXY_DIR, ".remote-password");
|
|
49
|
-
var TELEGRAM_WEBHOOK_SECRET_FILE = resolve(MAXY_DIR, ".telegram-webhook-secret");
|
|
50
|
-
var TELEGRAM_ADMIN_WEBHOOK_SECRET_FILE = resolve(MAXY_DIR, ".telegram-admin-webhook-secret");
|
|
51
|
-
var CLAUDE_CREDENTIALS_FILE = resolve(homedir(), ".claude", ".credentials.json");
|
|
52
|
-
|
|
53
|
-
// app/lib/vnc-logger.ts
|
|
54
|
-
import { appendFileSync, mkdirSync } from "fs";
|
|
55
|
-
import { resolve as resolve2 } from "path";
|
|
56
|
-
var VNC_LOG_FILE = resolve2(LOG_DIR, "vnc-boot.log");
|
|
57
|
-
try {
|
|
58
|
-
mkdirSync(LOG_DIR, { recursive: true });
|
|
59
|
-
} catch (err) {
|
|
60
|
-
console.error(`[vnc-log-fail] mkdir ${LOG_DIR} failed: ${err.message}`);
|
|
61
|
-
}
|
|
62
|
-
function vncLog(phase, fields = {}) {
|
|
63
|
-
const ts = (/* @__PURE__ */ new Date()).toISOString();
|
|
64
|
-
const kv = Object.entries(fields).map(([k, v]) => `${k}=${JSON.stringify(v)}`).join(" ");
|
|
65
|
-
const line = kv.length > 0 ? `[${ts}] [${phase}] ${kv}
|
|
66
|
-
` : `[${ts}] [${phase}]
|
|
67
|
-
`;
|
|
68
|
-
try {
|
|
69
|
-
appendFileSync(VNC_LOG_FILE, line);
|
|
70
|
-
} catch (err) {
|
|
71
|
-
console.error(`[vnc-log-fail] ${err.message} \u2014 dropped: ${line.slice(0, 300).trim()}`);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
var corrCounter = 0;
|
|
75
|
-
function newCorrId() {
|
|
76
|
-
corrCounter = corrCounter + 1 & 4294967295;
|
|
77
|
-
const counterHex = corrCounter.toString(16).padStart(8, "0");
|
|
78
|
-
const randomHex = Math.floor(Math.random() * 16777215).toString(16).padStart(6, "0");
|
|
79
|
-
return `${counterHex}-${randomHex}`;
|
|
80
|
-
}
|
|
81
|
-
function sanitizeClientCorrId(raw) {
|
|
82
|
-
if (!raw) return null;
|
|
83
|
-
if (raw.length > 32) return null;
|
|
84
|
-
if (!/^[A-Za-z0-9_-]+$/.test(raw)) return null;
|
|
85
|
-
return raw;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// app/lib/password-strength.ts
|
|
89
|
-
function validatePasswordStrength(password) {
|
|
90
|
-
return [
|
|
91
|
-
{ key: "length", label: "At least 8 characters", met: password.length >= 8 },
|
|
92
|
-
{ key: "number", label: "Contains a number", met: /\d/.test(password) },
|
|
93
|
-
{ key: "special", label: "Contains a special character", met: /[^A-Za-z0-9]/.test(password) },
|
|
94
|
-
{ key: "whitespace", label: "No spaces", met: password.length > 0 && !/\s/.test(password) }
|
|
95
|
-
];
|
|
96
|
-
}
|
|
97
|
-
function isPasswordValid(password) {
|
|
98
|
-
return validatePasswordStrength(password).every((r) => r.met);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// app/lib/remote-auth.ts
|
|
102
|
-
import { scrypt, randomBytes, timingSafeEqual } from "crypto";
|
|
103
|
-
import { readFileSync as readFileSync2, writeFileSync, existsSync as existsSync2 } from "fs";
|
|
104
|
-
var SCRYPT_N = 16384;
|
|
105
|
-
var SCRYPT_R = 8;
|
|
106
|
-
var SCRYPT_P = 1;
|
|
107
|
-
var SCRYPT_KEYLEN = 64;
|
|
108
|
-
function scryptAsync(password, salt) {
|
|
109
|
-
return new Promise((resolve3, reject) => {
|
|
110
|
-
scrypt(password, salt, SCRYPT_KEYLEN, { N: SCRYPT_N, r: SCRYPT_R, p: SCRYPT_P }, (err, key) => {
|
|
111
|
-
if (err) reject(err);
|
|
112
|
-
else resolve3(key);
|
|
113
|
-
});
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
|
-
async function hashPassword(password) {
|
|
117
|
-
const salt = randomBytes(32);
|
|
118
|
-
const hash = await scryptAsync(password, salt);
|
|
119
|
-
return `${salt.toString("hex")}:${hash.toString("hex")}`;
|
|
120
|
-
}
|
|
121
|
-
async function verifyPassword(password, stored) {
|
|
122
|
-
const colonIndex = stored.indexOf(":");
|
|
123
|
-
if (colonIndex === -1) return false;
|
|
124
|
-
const saltHex = stored.slice(0, colonIndex);
|
|
125
|
-
const hashHex = stored.slice(colonIndex + 1);
|
|
126
|
-
if (!saltHex || !hashHex) return false;
|
|
127
|
-
try {
|
|
128
|
-
const salt = Buffer.from(saltHex, "hex");
|
|
129
|
-
const storedHash = Buffer.from(hashHex, "hex");
|
|
130
|
-
if (storedHash.length !== SCRYPT_KEYLEN) return false;
|
|
131
|
-
const computed = await scryptAsync(password, salt);
|
|
132
|
-
return timingSafeEqual(computed, storedHash);
|
|
133
|
-
} catch {
|
|
134
|
-
return false;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
function isRemoteAuthConfigured() {
|
|
138
|
-
if (!existsSync2(REMOTE_PASSWORD_FILE)) return false;
|
|
139
|
-
const content = readFileSync2(REMOTE_PASSWORD_FILE, "utf-8").trim();
|
|
140
|
-
return content.length > 0 && content.includes(":");
|
|
141
|
-
}
|
|
142
|
-
function readPasswordHash() {
|
|
143
|
-
try {
|
|
144
|
-
if (!existsSync2(REMOTE_PASSWORD_FILE)) return null;
|
|
145
|
-
const content = readFileSync2(REMOTE_PASSWORD_FILE, "utf-8").trim();
|
|
146
|
-
if (!content || !content.includes(":")) return null;
|
|
147
|
-
return content;
|
|
148
|
-
} catch {
|
|
149
|
-
return null;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
async function setRemotePassword(password) {
|
|
153
|
-
const hash = await hashPassword(password);
|
|
154
|
-
writeFileSync(REMOTE_PASSWORD_FILE, hash, "utf-8");
|
|
155
|
-
}
|
|
156
|
-
async function verifyRemotePassword(password) {
|
|
157
|
-
const stored = readPasswordHash();
|
|
158
|
-
if (!stored) return false;
|
|
159
|
-
return verifyPassword(password, stored);
|
|
160
|
-
}
|
|
161
|
-
var SESSION_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
162
|
-
var remoteSessions = /* @__PURE__ */ new Map();
|
|
163
|
-
function pruneExpiredSessions() {
|
|
164
|
-
const now = Date.now();
|
|
165
|
-
for (const [token, session] of remoteSessions) {
|
|
166
|
-
if (now - session.createdAt > SESSION_TTL_MS) {
|
|
167
|
-
remoteSessions.delete(token);
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
function createRemoteSession() {
|
|
172
|
-
const token = randomBytes(32).toString("hex");
|
|
173
|
-
remoteSessions.set(token, { createdAt: Date.now() });
|
|
174
|
-
return token;
|
|
175
|
-
}
|
|
176
|
-
function validateRemoteSession(token) {
|
|
177
|
-
if (!token) return false;
|
|
178
|
-
pruneExpiredSessions();
|
|
179
|
-
const session = remoteSessions.get(token);
|
|
180
|
-
if (!session) return false;
|
|
181
|
-
if (Date.now() - session.createdAt > SESSION_TTL_MS) {
|
|
182
|
-
remoteSessions.delete(token);
|
|
183
|
-
return false;
|
|
184
|
-
}
|
|
185
|
-
return true;
|
|
186
|
-
}
|
|
187
|
-
function invalidateRemoteSession(token) {
|
|
188
|
-
remoteSessions.delete(token);
|
|
189
|
-
}
|
|
190
|
-
var MAX_ATTEMPTS = 5;
|
|
191
|
-
var LOCKOUT_MS = 15 * 60 * 1e3;
|
|
192
|
-
var rateLimitMap = /* @__PURE__ */ new Map();
|
|
193
|
-
function checkRateLimit(ip) {
|
|
194
|
-
const rec = rateLimitMap.get(ip);
|
|
195
|
-
if (!rec) return null;
|
|
196
|
-
if (rec.lockedUntil > Date.now()) {
|
|
197
|
-
const remaining = Math.ceil((rec.lockedUntil - Date.now()) / 1e3);
|
|
198
|
-
return `Too many attempts. Try again in ${remaining}s`;
|
|
199
|
-
}
|
|
200
|
-
if (rec.lockedUntil > 0) {
|
|
201
|
-
rateLimitMap.delete(ip);
|
|
202
|
-
}
|
|
203
|
-
return null;
|
|
204
|
-
}
|
|
205
|
-
function recordFailedAttempt(ip) {
|
|
206
|
-
const rec = rateLimitMap.get(ip) ?? { count: 0, lockedUntil: 0 };
|
|
207
|
-
rec.count++;
|
|
208
|
-
if (rec.count >= MAX_ATTEMPTS) {
|
|
209
|
-
rec.lockedUntil = Date.now() + LOCKOUT_MS;
|
|
210
|
-
rec.count = 0;
|
|
211
|
-
}
|
|
212
|
-
rateLimitMap.set(ip, rec);
|
|
213
|
-
}
|
|
214
|
-
function clearRateLimit(ip) {
|
|
215
|
-
rateLimitMap.delete(ip);
|
|
216
|
-
}
|
|
217
|
-
setInterval(() => {
|
|
218
|
-
const now = Date.now();
|
|
219
|
-
for (const [ip, rec] of rateLimitMap) {
|
|
220
|
-
if (rec.lockedUntil > 0 && rec.lockedUntil <= now) {
|
|
221
|
-
rateLimitMap.delete(ip);
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
}, 15 * 60 * 1e3).unref();
|
|
225
|
-
function normalizeIp(ip) {
|
|
226
|
-
if (!ip) return void 0;
|
|
227
|
-
const trimmed = ip.trim();
|
|
228
|
-
if (trimmed.startsWith("::ffff:")) return trimmed.slice(7);
|
|
229
|
-
return trimmed;
|
|
230
|
-
}
|
|
231
|
-
function isLoopback(ip) {
|
|
232
|
-
return ip === "127.0.0.1" || ip.startsWith("127.") || ip === "::1";
|
|
233
|
-
}
|
|
234
|
-
function isPrivateIp(ip) {
|
|
235
|
-
const parts = ip.split(".");
|
|
236
|
-
if (parts.length !== 4) return false;
|
|
237
|
-
const a = parseInt(parts[0], 10);
|
|
238
|
-
const b = parseInt(parts[1], 10);
|
|
239
|
-
if (Number.isNaN(a) || Number.isNaN(b)) return false;
|
|
240
|
-
if (a === 10) return true;
|
|
241
|
-
if (a === 172 && b >= 16 && b <= 31) return true;
|
|
242
|
-
if (a === 192 && b === 168) return true;
|
|
243
|
-
if (a === 169 && b === 254) return true;
|
|
244
|
-
return false;
|
|
245
|
-
}
|
|
246
|
-
function resolveClientIp(remoteAddress, xForwardedFor) {
|
|
247
|
-
const remote = normalizeIp(remoteAddress);
|
|
248
|
-
if (!remote) return void 0;
|
|
249
|
-
if (isLoopback(remote) && xForwardedFor) {
|
|
250
|
-
const firstIp = normalizeIp(xForwardedFor.split(",")[0]?.trim());
|
|
251
|
-
if (firstIp) {
|
|
252
|
-
if (isLoopback(firstIp) || isPrivateIp(firstIp)) return "loopback";
|
|
253
|
-
return firstIp;
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
return remote;
|
|
257
|
-
}
|
|
258
|
-
function isExternalIp(ip) {
|
|
259
|
-
if (!ip) return false;
|
|
260
|
-
const normalized = normalizeIp(ip);
|
|
261
|
-
if (!normalized) return false;
|
|
262
|
-
if (isLoopback(normalized)) return false;
|
|
263
|
-
if (isPrivateIp(normalized)) return false;
|
|
264
|
-
return true;
|
|
265
|
-
}
|
|
266
|
-
function renderLoginPage(opts) {
|
|
267
|
-
const error = opts?.error ?? "";
|
|
268
|
-
const lockout = opts?.lockoutSeconds ?? 0;
|
|
269
|
-
const redirect = opts?.redirect ?? "/";
|
|
270
|
-
const mode = opts?.mode ?? "login";
|
|
271
|
-
const changeError = opts?.changeError ?? "";
|
|
272
|
-
const success = opts?.success ?? "";
|
|
273
|
-
const setupError = opts?.setupError ?? "";
|
|
274
|
-
const primaryColor = opts?.primaryColor ?? "#7C8C72";
|
|
275
|
-
const primaryHoverColor = opts?.primaryHoverColor ?? "#6A7A62";
|
|
276
|
-
const primarySubtle = opts?.primarySubtle ?? "rgba(124,140,114,0.08)";
|
|
277
|
-
const productName = opts?.productName ?? "Maxy";
|
|
278
|
-
const logoPath = opts?.logoPath ?? "/brand/maxy-monochrome.png";
|
|
279
|
-
const faviconPath = opts?.faviconPath ?? "/favicon.ico";
|
|
280
|
-
const displayFont = opts?.displayFont ?? "'Cormorant', Georgia, serif";
|
|
281
|
-
const bodyFont = opts?.bodyFont ?? "'DM Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif";
|
|
282
|
-
const logoContainsName = opts?.logoContainsName ?? false;
|
|
283
|
-
const errorHtml = error ? `<p class="msg msg--error">${escapeHtml(error)}</p>` : "";
|
|
284
|
-
const changeErrorHtml = changeError ? `<p class="msg msg--error">${escapeHtml(changeError)}</p>` : "";
|
|
285
|
-
const successHtml = success ? `<p class="msg msg--success">${escapeHtml(success)}</p>` : "";
|
|
286
|
-
const lockoutHtml = lockout > 0 ? `<p class="msg msg--error">Too many attempts. Try again in <span id="countdown">${lockout}</span>s</p>
|
|
287
|
-
<script>
|
|
288
|
-
(function() {
|
|
289
|
-
var s = ${lockout};
|
|
290
|
-
var el = document.getElementById('countdown');
|
|
291
|
-
var iv = setInterval(function() { s--; el.textContent = s; if (s <= 0) { clearInterval(iv); location.reload(); } }, 1000);
|
|
292
|
-
})();
|
|
293
|
-
</script>` : "";
|
|
294
|
-
const setupErrorHtml = setupError ? `<p class="msg msg--error">${escapeHtml(setupError)}</p>` : "";
|
|
295
|
-
const formDisabled = lockout > 0 ? "disabled" : "";
|
|
296
|
-
const loginDisplay = mode === "login" ? "block" : "none";
|
|
297
|
-
const changeDisplay = mode === "change" ? "block" : "none";
|
|
298
|
-
const setupDisplay = mode === "setup" ? "block" : "none";
|
|
299
|
-
const successDisplay = mode === "success" ? "block" : "none";
|
|
300
|
-
const subtitleText = mode === "setup" ? "Set your remote password" : "Remote access";
|
|
301
|
-
const displayFontName = displayFont.match(/^'([^']+)'/)?.[1] ?? "";
|
|
302
|
-
const bodyFontName = bodyFont.match(/^'([^']+)'/)?.[1] ?? "";
|
|
303
|
-
const googleFontsLink = displayFontName || bodyFontName ? [
|
|
304
|
-
'<link rel="preconnect" href="https://fonts.googleapis.com">',
|
|
305
|
-
'<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>',
|
|
306
|
-
'<link href="https://fonts.googleapis.com/css2?' + [
|
|
307
|
-
displayFontName ? `family=${displayFontName.replace(/ /g, "+")}:wght@300;400` : "",
|
|
308
|
-
bodyFontName ? `family=${bodyFontName.replace(/ /g, "+")}:wght@400;500` : ""
|
|
309
|
-
].filter(Boolean).join("&") + '&display=swap" rel="stylesheet">'
|
|
310
|
-
].join("\n ") : "";
|
|
311
|
-
return `<!DOCTYPE html>
|
|
312
|
-
<html lang="en">
|
|
313
|
-
<head>
|
|
314
|
-
<meta charset="utf-8">
|
|
315
|
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
316
|
-
<title>Sign in \u2014 ${escapeHtml(productName)}</title>
|
|
317
|
-
<link rel="icon" href="${escapeHtml(faviconPath)}">
|
|
318
|
-
${googleFontsLink}
|
|
319
|
-
<style>
|
|
320
|
-
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
321
|
-
body {
|
|
322
|
-
font-family: ${bodyFont};
|
|
323
|
-
background: #FAFAF8;
|
|
324
|
-
color: #1A1A1A;
|
|
325
|
-
min-height: 100vh;
|
|
326
|
-
display: flex;
|
|
327
|
-
align-items: center;
|
|
328
|
-
justify-content: center;
|
|
329
|
-
}
|
|
330
|
-
.page {
|
|
331
|
-
display: flex;
|
|
332
|
-
flex-direction: column;
|
|
333
|
-
align-items: center;
|
|
334
|
-
gap: 24px;
|
|
335
|
-
max-width: 420px;
|
|
336
|
-
width: 100%;
|
|
337
|
-
padding: 40px 20px;
|
|
338
|
-
}
|
|
339
|
-
.logo-img {
|
|
340
|
-
width: 110px;
|
|
341
|
-
height: 110px;
|
|
342
|
-
margin: -11px;
|
|
343
|
-
object-fit: contain;
|
|
344
|
-
}
|
|
345
|
-
.title {
|
|
346
|
-
font-family: ${displayFont};
|
|
347
|
-
font-weight: 300;
|
|
348
|
-
font-size: 28px;
|
|
349
|
-
color: #1A1A1A;
|
|
350
|
-
text-align: center;
|
|
351
|
-
letter-spacing: -0.01em;
|
|
352
|
-
line-height: 1.3;
|
|
353
|
-
}
|
|
354
|
-
.subtitle {
|
|
355
|
-
font-size: 15px;
|
|
356
|
-
color: #6B6B6B;
|
|
357
|
-
text-align: center;
|
|
358
|
-
margin-top: -8px;
|
|
359
|
-
}
|
|
360
|
-
.form-wrap {
|
|
361
|
-
width: 100%;
|
|
362
|
-
max-width: 300px;
|
|
363
|
-
}
|
|
364
|
-
.field { margin-bottom: 12px; }
|
|
365
|
-
.field-label {
|
|
366
|
-
display: block;
|
|
367
|
-
font-size: 13px;
|
|
368
|
-
font-weight: 500;
|
|
369
|
-
color: #6B6B6B;
|
|
370
|
-
margin-bottom: 6px;
|
|
371
|
-
}
|
|
372
|
-
.field-input {
|
|
373
|
-
width: 100%;
|
|
374
|
-
padding: 10px 12px;
|
|
375
|
-
border: 1px solid rgba(0,0,0,0.1);
|
|
376
|
-
border-radius: 8px;
|
|
377
|
-
font-size: 15px;
|
|
378
|
-
font-family: inherit;
|
|
379
|
-
outline: none;
|
|
380
|
-
background: #fff;
|
|
381
|
-
transition: border-color 0.15s, box-shadow 0.15s;
|
|
382
|
-
}
|
|
383
|
-
.field-input:focus {
|
|
384
|
-
border-color: ${primaryColor};
|
|
385
|
-
box-shadow: 0 0 0 3px ${primarySubtle};
|
|
386
|
-
}
|
|
387
|
-
.options {
|
|
388
|
-
display: flex;
|
|
389
|
-
align-items: center;
|
|
390
|
-
justify-content: space-between;
|
|
391
|
-
gap: 12px;
|
|
392
|
-
margin-top: 8px;
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
/* Checkbox \u2014 matches Maxy shared checkbox (asterisk-in-square) */
|
|
396
|
-
.check {
|
|
397
|
-
position: relative;
|
|
398
|
-
display: flex;
|
|
399
|
-
align-items: center;
|
|
400
|
-
gap: 8px;
|
|
401
|
-
cursor: pointer;
|
|
402
|
-
user-select: none;
|
|
403
|
-
}
|
|
404
|
-
.check input { position: absolute; opacity: 0; width: 0; height: 0; pointer-events: none; }
|
|
405
|
-
.check-box {
|
|
406
|
-
width: 14px;
|
|
407
|
-
height: 14px;
|
|
408
|
-
border: 1px solid rgba(0,0,0,0.1);
|
|
409
|
-
border-radius: 2px;
|
|
410
|
-
display: flex;
|
|
411
|
-
align-items: center;
|
|
412
|
-
justify-content: center;
|
|
413
|
-
font-size: 10px;
|
|
414
|
-
color: transparent;
|
|
415
|
-
transition: border-color 0.15s, color 0.15s;
|
|
416
|
-
flex-shrink: 0;
|
|
417
|
-
}
|
|
418
|
-
.check input:checked + .check-box {
|
|
419
|
-
border-color: ${primaryColor};
|
|
420
|
-
color: ${primaryColor};
|
|
421
|
-
}
|
|
422
|
-
.check-label {
|
|
423
|
-
font-size: 13px;
|
|
424
|
-
color: #6B6B6B;
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
/* Ghost button \u2014 matches Maxy ghost variant */
|
|
428
|
-
.ghost {
|
|
429
|
-
background: none;
|
|
430
|
-
border: none;
|
|
431
|
-
font-family: inherit;
|
|
432
|
-
font-size: 13px;
|
|
433
|
-
color: #6B6B6B;
|
|
434
|
-
cursor: pointer;
|
|
435
|
-
padding: 4px 0;
|
|
436
|
-
transition: color 0.15s;
|
|
437
|
-
}
|
|
438
|
-
.ghost:hover { color: #1A1A1A; }
|
|
439
|
-
|
|
440
|
-
/* Primary button */
|
|
441
|
-
.btn {
|
|
442
|
-
width: 100%;
|
|
443
|
-
padding: 12px;
|
|
444
|
-
margin-top: 16px;
|
|
445
|
-
background: ${primaryColor};
|
|
446
|
-
color: #fff;
|
|
447
|
-
border: none;
|
|
448
|
-
border-radius: 10px;
|
|
449
|
-
font-size: 15px;
|
|
450
|
-
font-weight: 500;
|
|
451
|
-
font-family: inherit;
|
|
452
|
-
cursor: pointer;
|
|
453
|
-
transition: background 0.15s;
|
|
454
|
-
}
|
|
455
|
-
.btn:hover:not(:disabled) { background: ${primaryHoverColor}; }
|
|
456
|
-
.btn:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
457
|
-
|
|
458
|
-
/* Messages */
|
|
459
|
-
.msg {
|
|
460
|
-
font-size: 13px;
|
|
461
|
-
text-align: center;
|
|
462
|
-
margin-top: 8px;
|
|
463
|
-
}
|
|
464
|
-
.msg--error { color: #c44; }
|
|
465
|
-
.msg--success { color: ${primaryColor}; }
|
|
466
|
-
|
|
467
|
-
/* Strength checklist (setup mode) */
|
|
468
|
-
.strength-checklist { margin: 8px 0; }
|
|
469
|
-
.strength-item {
|
|
470
|
-
font-size: 13px;
|
|
471
|
-
color: #6B6B6B;
|
|
472
|
-
padding: 2px 0;
|
|
473
|
-
transition: color 0.15s;
|
|
474
|
-
}
|
|
475
|
-
.strength-icon {
|
|
476
|
-
display: inline-block;
|
|
477
|
-
width: 16px;
|
|
478
|
-
text-align: center;
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
@media (max-width: 440px) {
|
|
482
|
-
.page { padding: 24px 16px; }
|
|
483
|
-
}
|
|
484
|
-
</style>
|
|
485
|
-
</head>
|
|
486
|
-
<body>
|
|
487
|
-
<div class="page">
|
|
488
|
-
<img src="${escapeHtml(logoPath)}" alt="${escapeHtml(productName)}" class="logo-img">
|
|
489
|
-
<h1 class="title"${logoContainsName ? ' style="display:none"' : ""}>${escapeHtml(productName)}</h1>
|
|
490
|
-
<p class="subtitle">${escapeHtml(subtitleText)}</p>
|
|
491
|
-
|
|
492
|
-
${successHtml}
|
|
493
|
-
|
|
494
|
-
<!-- Login -->
|
|
495
|
-
<div id="login-section" class="form-wrap" style="display:${loginDisplay}">
|
|
496
|
-
<form method="POST" action="/__remote-auth/login">
|
|
497
|
-
<input type="hidden" name="redirect" value="${escapeHtml(redirect)}">
|
|
498
|
-
<div class="field">
|
|
499
|
-
<label class="field-label" for="password">Password</label>
|
|
500
|
-
<input class="field-input" type="password" id="password" name="password" required autofocus ${formDisabled}>
|
|
501
|
-
</div>
|
|
502
|
-
<div class="options">
|
|
503
|
-
<label class="check">
|
|
504
|
-
<input type="checkbox" id="show-login-pw">
|
|
505
|
-
<span class="check-box">\u2731</span>
|
|
506
|
-
<span class="check-label">Show password</span>
|
|
507
|
-
</label>
|
|
508
|
-
<button type="button" class="ghost" onclick="toggleMode('change')">Change password</button>
|
|
509
|
-
</div>
|
|
510
|
-
<button type="submit" class="btn" ${formDisabled}>Sign in</button>
|
|
511
|
-
</form>
|
|
512
|
-
${errorHtml}
|
|
513
|
-
${lockoutHtml}
|
|
514
|
-
</div>
|
|
515
|
-
|
|
516
|
-
<!-- Change password -->
|
|
517
|
-
<div id="change-section" class="form-wrap" style="display:${changeDisplay}">
|
|
518
|
-
<form method="POST" action="/__remote-auth/change-password">
|
|
519
|
-
<input type="hidden" name="redirect" value="${escapeHtml(redirect)}">
|
|
520
|
-
<div class="field">
|
|
521
|
-
<label class="field-label" for="current_password">Current password</label>
|
|
522
|
-
<input class="field-input" type="password" id="current_password" name="current_password" required ${formDisabled}>
|
|
523
|
-
</div>
|
|
524
|
-
<div class="field">
|
|
525
|
-
<label class="field-label" for="new_password">New password</label>
|
|
526
|
-
<input class="field-input" type="password" id="new_password" name="new_password" required ${formDisabled}>
|
|
527
|
-
</div>
|
|
528
|
-
<div class="field">
|
|
529
|
-
<label class="field-label" for="confirm_password">Confirm new password</label>
|
|
530
|
-
<input class="field-input" type="password" id="confirm_password" name="confirm_password" required ${formDisabled}>
|
|
531
|
-
</div>
|
|
532
|
-
<div class="options">
|
|
533
|
-
<label class="check">
|
|
534
|
-
<input type="checkbox" id="show-change-pw">
|
|
535
|
-
<span class="check-box">\u2731</span>
|
|
536
|
-
<span class="check-label">Show passwords</span>
|
|
537
|
-
</label>
|
|
538
|
-
<button type="button" class="ghost" onclick="toggleMode('login')">Back to sign in</button>
|
|
539
|
-
</div>
|
|
540
|
-
<button type="submit" class="btn" ${formDisabled}>Change password</button>
|
|
541
|
-
</form>
|
|
542
|
-
${changeErrorHtml}
|
|
543
|
-
</div>
|
|
544
|
-
|
|
545
|
-
<!-- Setup (initial password) -->
|
|
546
|
-
<div id="setup-section" class="form-wrap" style="display:${setupDisplay}">
|
|
547
|
-
<form method="POST" action="/__remote-auth/set-initial-password">
|
|
548
|
-
<div class="field">
|
|
549
|
-
<label class="field-label" for="setup_password">Password</label>
|
|
550
|
-
<input class="field-input" type="password" id="setup_password" name="password" required autofocus>
|
|
551
|
-
</div>
|
|
552
|
-
<div class="field">
|
|
553
|
-
<label class="field-label" for="setup_confirm">Confirm password</label>
|
|
554
|
-
<input class="field-input" type="password" id="setup_confirm" name="confirm_password" required>
|
|
555
|
-
</div>
|
|
556
|
-
<div id="strength-checklist" class="strength-checklist">
|
|
557
|
-
<div class="strength-item" id="req-length"><span class="strength-icon">\u25CB</span> At least 8 characters</div>
|
|
558
|
-
<div class="strength-item" id="req-number"><span class="strength-icon">\u25CB</span> Contains a number</div>
|
|
559
|
-
<div class="strength-item" id="req-special"><span class="strength-icon">\u25CB</span> Contains a special character</div>
|
|
560
|
-
<div class="strength-item" id="req-spaces"><span class="strength-icon">\u25CB</span> No spaces</div>
|
|
561
|
-
</div>
|
|
562
|
-
<div class="options">
|
|
563
|
-
<label class="check">
|
|
564
|
-
<input type="checkbox" id="show-setup-pw">
|
|
565
|
-
<span class="check-box">\u2731</span>
|
|
566
|
-
<span class="check-label">Show passwords</span>
|
|
567
|
-
</label>
|
|
568
|
-
</div>
|
|
569
|
-
<button type="submit" class="btn" id="setup-submit" disabled>Set password</button>
|
|
570
|
-
</form>
|
|
571
|
-
${setupErrorHtml}
|
|
572
|
-
</div>
|
|
573
|
-
|
|
574
|
-
<!-- Success (after initial password set) -->
|
|
575
|
-
<div id="success-section" class="form-wrap" style="display:${successDisplay}">
|
|
576
|
-
<p class="msg msg--success" style="font-size:15px;margin-bottom:4px;">\u2713 Password set</p>
|
|
577
|
-
<p style="font-size:14px;color:#6B6B6B;text-align:center;">You can close this tab and return to the onboarding tab.</p>
|
|
578
|
-
<script>
|
|
579
|
-
(function() {
|
|
580
|
-
try {
|
|
581
|
-
var ch = new BroadcastChannel('platform-onboarding');
|
|
582
|
-
setTimeout(function() {
|
|
583
|
-
ch.postMessage({ type: 'remote-password-set' });
|
|
584
|
-
ch.close();
|
|
585
|
-
}, 2500);
|
|
586
|
-
} catch(e) {}
|
|
587
|
-
})();
|
|
588
|
-
</script>
|
|
589
|
-
</div>
|
|
590
|
-
</div>
|
|
591
|
-
|
|
592
|
-
<script>
|
|
593
|
-
/* Toggle between login and change-password modes */
|
|
594
|
-
function toggleMode(mode) {
|
|
595
|
-
document.getElementById('login-section').style.display = mode === 'login' ? 'block' : 'none';
|
|
596
|
-
document.getElementById('change-section').style.display = mode === 'change' ? 'block' : 'none';
|
|
597
|
-
/* Focus first input in the active section */
|
|
598
|
-
var id = mode === 'login' ? 'password' : 'current_password';
|
|
599
|
-
var el = document.getElementById(id);
|
|
600
|
-
if (el) el.focus();
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
/* Show/hide password toggles */
|
|
604
|
-
function bindShowHide(checkboxId, inputIds) {
|
|
605
|
-
var cb = document.getElementById(checkboxId);
|
|
606
|
-
if (!cb) return;
|
|
607
|
-
cb.addEventListener('change', function() {
|
|
608
|
-
var type = cb.checked ? 'text' : 'password';
|
|
609
|
-
inputIds.forEach(function(id) {
|
|
610
|
-
var el = document.getElementById(id);
|
|
611
|
-
if (el) el.type = type;
|
|
612
|
-
});
|
|
613
|
-
});
|
|
614
|
-
}
|
|
615
|
-
bindShowHide('show-login-pw', ['password']);
|
|
616
|
-
bindShowHide('show-change-pw', ['current_password', 'new_password', 'confirm_password']);
|
|
617
|
-
bindShowHide('show-setup-pw', ['setup_password', 'setup_confirm']);
|
|
618
|
-
|
|
619
|
-
/* Explicit Enter-to-submit for the login password field */
|
|
620
|
-
var loginPw = document.getElementById('password');
|
|
621
|
-
if (loginPw) {
|
|
622
|
-
loginPw.addEventListener('keydown', function(e) {
|
|
623
|
-
if (e.key === 'Enter') {
|
|
624
|
-
e.preventDefault();
|
|
625
|
-
this.closest('form').requestSubmit();
|
|
626
|
-
}
|
|
627
|
-
});
|
|
628
|
-
}
|
|
629
|
-
|
|
630
|
-
/* Live password strength validation (setup mode) */
|
|
631
|
-
(function() {
|
|
632
|
-
var pw = document.getElementById('setup_password');
|
|
633
|
-
var confirm = document.getElementById('setup_confirm');
|
|
634
|
-
var btn = document.getElementById('setup-submit');
|
|
635
|
-
if (!pw || !confirm || !btn) return;
|
|
636
|
-
|
|
637
|
-
var rules = [
|
|
638
|
-
{ id: 'req-length', test: function(p) { return p.length >= 8; } },
|
|
639
|
-
{ id: 'req-number', test: function(p) { return /\\d/.test(p); } },
|
|
640
|
-
{ id: 'req-special', test: function(p) { return /[^A-Za-z0-9]/.test(p); } },
|
|
641
|
-
{ id: 'req-spaces', test: function(p) { return p.length > 0 && !/\\s/.test(p); } }
|
|
642
|
-
];
|
|
643
|
-
|
|
644
|
-
function check() {
|
|
645
|
-
var p = pw.value;
|
|
646
|
-
var allMet = true;
|
|
647
|
-
rules.forEach(function(r) {
|
|
648
|
-
var el = document.getElementById(r.id);
|
|
649
|
-
var met = r.test(p);
|
|
650
|
-
if (!met) allMet = false;
|
|
651
|
-
el.querySelector('.strength-icon').textContent = met ? '\\u2713' : '\\u25CB';
|
|
652
|
-
el.style.color = met ? '${primaryColor}' : '#6B6B6B';
|
|
653
|
-
});
|
|
654
|
-
var match = p.length > 0 && p === confirm.value;
|
|
655
|
-
btn.disabled = !(allMet && match);
|
|
656
|
-
}
|
|
657
|
-
|
|
658
|
-
pw.addEventListener('input', check);
|
|
659
|
-
confirm.addEventListener('input', check);
|
|
660
|
-
})();
|
|
661
|
-
</script>
|
|
662
|
-
</body>
|
|
663
|
-
</html>`;
|
|
664
|
-
}
|
|
665
|
-
function escapeHtml(str) {
|
|
666
|
-
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
// app/lib/auth-gate.ts
|
|
670
|
-
function canAccessAdmin(input) {
|
|
671
|
-
if (input.isPublicHost(input.host)) {
|
|
672
|
-
return { allow: false, reason: "public-host" };
|
|
673
|
-
}
|
|
674
|
-
const clientIp = resolveClientIp(input.remoteAddress, input.xForwardedFor);
|
|
675
|
-
if (!isExternalIp(clientIp)) {
|
|
676
|
-
return { allow: true };
|
|
677
|
-
}
|
|
678
|
-
if (!isRemoteAuthConfigured()) {
|
|
679
|
-
return { allow: false, reason: "remote-unconfigured" };
|
|
680
|
-
}
|
|
681
|
-
const token = parseCookieValue(input.cookieHeader, "__remote_session");
|
|
682
|
-
if (token && validateRemoteSession(token)) {
|
|
683
|
-
return { allow: true };
|
|
684
|
-
}
|
|
685
|
-
return { allow: false, reason: "unauthorized" };
|
|
686
|
-
}
|
|
687
|
-
function parseCookieValue(cookieHeader, name) {
|
|
688
|
-
if (!cookieHeader) return null;
|
|
689
|
-
const match = cookieHeader.match(new RegExp(`(?:^|;\\s*)${name}=([^;]*)`));
|
|
690
|
-
if (!match) return null;
|
|
691
|
-
try {
|
|
692
|
-
return decodeURIComponent(match[1]);
|
|
693
|
-
} catch {
|
|
694
|
-
return null;
|
|
695
|
-
}
|
|
696
|
-
}
|
|
697
|
-
|
|
698
|
-
export {
|
|
699
|
-
__commonJS,
|
|
700
|
-
__toESM,
|
|
701
|
-
MAXY_DIR,
|
|
702
|
-
USERS_FILE,
|
|
703
|
-
LOG_DIR,
|
|
704
|
-
BIN_DIR,
|
|
705
|
-
TELEGRAM_WEBHOOK_SECRET_FILE,
|
|
706
|
-
TELEGRAM_ADMIN_WEBHOOK_SECRET_FILE,
|
|
707
|
-
CLAUDE_CREDENTIALS_FILE,
|
|
708
|
-
vncLog,
|
|
709
|
-
newCorrId,
|
|
710
|
-
sanitizeClientCorrId,
|
|
711
|
-
validatePasswordStrength,
|
|
712
|
-
isPasswordValid,
|
|
713
|
-
hashPassword,
|
|
714
|
-
verifyPassword,
|
|
715
|
-
isRemoteAuthConfigured,
|
|
716
|
-
setRemotePassword,
|
|
717
|
-
verifyRemotePassword,
|
|
718
|
-
createRemoteSession,
|
|
719
|
-
invalidateRemoteSession,
|
|
720
|
-
checkRateLimit,
|
|
721
|
-
recordFailedAttempt,
|
|
722
|
-
clearRateLimit,
|
|
723
|
-
resolveClientIp,
|
|
724
|
-
renderLoginPage,
|
|
725
|
-
canAccessAdmin
|
|
726
|
-
};
|