@mooncompany/uplink-chat 0.5.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.
Potentially problematic release.
This version of @mooncompany/uplink-chat might be problematic. Click here for more details.
- package/LICENSE +21 -0
- package/README.md +185 -0
- package/bin/uplink.js +279 -0
- package/middleware/error-handler.js +69 -0
- package/package.json +93 -0
- package/public/css/agents.36b98c0f.css +1469 -0
- package/public/css/agents.css +1469 -0
- package/public/css/app.a6a7f8f5.css +2731 -0
- package/public/css/app.css +2731 -0
- package/public/css/artifacts.css +444 -0
- package/public/css/commands.css +55 -0
- package/public/css/connection.css +131 -0
- package/public/css/dashboard.css +233 -0
- package/public/css/developer.css +328 -0
- package/public/css/files.css +123 -0
- package/public/css/markdown.css +156 -0
- package/public/css/message-actions.css +278 -0
- package/public/css/mobile.css +614 -0
- package/public/css/panels-unified.css +483 -0
- package/public/css/premium.css +415 -0
- package/public/css/realtime.css +189 -0
- package/public/css/satellites.css +401 -0
- package/public/css/shortcuts.css +185 -0
- package/public/css/split-view.4def0262.css +673 -0
- package/public/css/split-view.css +673 -0
- package/public/css/theme-generator.css +391 -0
- package/public/css/themes.css +387 -0
- package/public/css/timestamps.css +54 -0
- package/public/css/variables.css +78 -0
- package/public/dist/bundle.b55050c4.js +15757 -0
- package/public/favicon.svg +24 -0
- package/public/img/agents/ada.png +0 -0
- package/public/img/agents/clarice.png +0 -0
- package/public/img/agents/dennis-nedry.png +0 -0
- package/public/img/agents/elliot-alderson.png +0 -0
- package/public/img/agents/main.png +0 -0
- package/public/img/agents/scotty.png +0 -0
- package/public/img/agents/top-flight-security.png +0 -0
- package/public/index.html +1083 -0
- package/public/js/agents-data.js +234 -0
- package/public/js/agents-ui.js +72 -0
- package/public/js/agents.js +1525 -0
- package/public/js/app.js +79 -0
- package/public/js/appearance-settings.js +111 -0
- package/public/js/artifacts.js +432 -0
- package/public/js/audio-queue.js +168 -0
- package/public/js/bootstrap.js +54 -0
- package/public/js/chat.js +1211 -0
- package/public/js/commands.js +581 -0
- package/public/js/connection-api.js +121 -0
- package/public/js/connection.js +1231 -0
- package/public/js/context-tracker.js +271 -0
- package/public/js/core.js +172 -0
- package/public/js/dashboard.js +452 -0
- package/public/js/developer.js +432 -0
- package/public/js/encryption.js +124 -0
- package/public/js/errors.js +122 -0
- package/public/js/event-bus.js +77 -0
- package/public/js/fetch-utils.js +171 -0
- package/public/js/file-handler.js +229 -0
- package/public/js/files.js +352 -0
- package/public/js/gateway-chat.js +538 -0
- package/public/js/logger.js +112 -0
- package/public/js/markdown.js +190 -0
- package/public/js/message-actions.js +431 -0
- package/public/js/message-renderer.js +288 -0
- package/public/js/missed-messages.js +235 -0
- package/public/js/mobile-debug.js +95 -0
- package/public/js/notifications.js +367 -0
- package/public/js/offline-queue.js +178 -0
- package/public/js/onboarding.js +543 -0
- package/public/js/panels.js +156 -0
- package/public/js/premium.js +412 -0
- package/public/js/realtime-voice.js +844 -0
- package/public/js/satellite-sync.js +256 -0
- package/public/js/satellite-ui.js +175 -0
- package/public/js/satellites.js +1516 -0
- package/public/js/settings.js +1087 -0
- package/public/js/shortcuts.js +381 -0
- package/public/js/split-chat.js +1234 -0
- package/public/js/split-resize.js +211 -0
- package/public/js/splitview.js +340 -0
- package/public/js/storage.js +408 -0
- package/public/js/streaming-handler.js +324 -0
- package/public/js/stt-settings.js +316 -0
- package/public/js/theme-generator.js +661 -0
- package/public/js/themes.js +164 -0
- package/public/js/timestamps.js +198 -0
- package/public/js/tts-settings.js +575 -0
- package/public/js/ui.js +267 -0
- package/public/js/update-notifier.js +143 -0
- package/public/js/utils/constants.js +165 -0
- package/public/js/utils/sanitize.js +93 -0
- package/public/js/utils/sse-parser.js +195 -0
- package/public/js/voice.js +883 -0
- package/public/manifest.json +58 -0
- package/public/moon_texture.jpg +0 -0
- package/public/sw.js +221 -0
- package/public/three.min.js +6 -0
- package/server/channel.js +529 -0
- package/server/chat.js +270 -0
- package/server/config-store.js +362 -0
- package/server/config.js +159 -0
- package/server/context.js +131 -0
- package/server/gateway-commands.js +211 -0
- package/server/gateway-proxy.js +318 -0
- package/server/index.js +22 -0
- package/server/logger.js +89 -0
- package/server/middleware/auth.js +188 -0
- package/server/middleware.js +218 -0
- package/server/openclaw-discover.js +308 -0
- package/server/premium/index.js +156 -0
- package/server/premium/license.js +140 -0
- package/server/realtime/bridge.js +837 -0
- package/server/realtime/index.js +349 -0
- package/server/realtime/tts-stream.js +446 -0
- package/server/routes/agents.js +564 -0
- package/server/routes/artifacts.js +174 -0
- package/server/routes/chat.js +311 -0
- package/server/routes/config-settings.js +345 -0
- package/server/routes/config.js +603 -0
- package/server/routes/files.js +307 -0
- package/server/routes/index.js +18 -0
- package/server/routes/media.js +451 -0
- package/server/routes/missed-messages.js +107 -0
- package/server/routes/premium.js +75 -0
- package/server/routes/push.js +156 -0
- package/server/routes/satellite.js +406 -0
- package/server/routes/status.js +251 -0
- package/server/routes/stt.js +35 -0
- package/server/routes/voice.js +260 -0
- package/server/routes/webhooks.js +203 -0
- package/server/routes.js +206 -0
- package/server/runtime-config.js +336 -0
- package/server/share.js +305 -0
- package/server/stt/faster-whisper.js +72 -0
- package/server/stt/groq.js +51 -0
- package/server/stt/index.js +196 -0
- package/server/stt/openai.js +49 -0
- package/server/sync.js +244 -0
- package/server/tailscale-https.js +175 -0
- package/server/tts.js +646 -0
- package/server/update-checker.js +172 -0
- package/server/utils/filename.js +129 -0
- package/server/utils.js +147 -0
- package/server/watchdog.js +318 -0
- package/server/websocket/broadcast.js +359 -0
- package/server/websocket/connections.js +339 -0
- package/server/websocket/index.js +215 -0
- package/server/websocket/routing.js +277 -0
- package/server/websocket/sync.js +102 -0
- package/server.js +404 -0
- package/utils/detect-tool-usage.js +93 -0
- package/utils/errors.js +158 -0
- package/utils/html-escape.js +84 -0
- package/utils/id-sanitize.js +94 -0
- package/utils/response.js +130 -0
- package/utils/with-retry.js +105 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* License Validation Module
|
|
3
|
+
*
|
|
4
|
+
* Validates Uplink Premium license keys using HMAC-SHA256.
|
|
5
|
+
*
|
|
6
|
+
* Key format: UPL-XXXXX-XXXXX-XXXXX-XXXXX
|
|
7
|
+
*
|
|
8
|
+
* Structure:
|
|
9
|
+
* - First 10 base32 chars (6 bytes): random payload
|
|
10
|
+
* - Last 10 base32 chars (6 bytes): truncated HMAC-SHA256 tag
|
|
11
|
+
*
|
|
12
|
+
* The HMAC secret is derived from multiple components to avoid
|
|
13
|
+
* a single obvious string in the source code.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { createHmac } from 'crypto';
|
|
17
|
+
|
|
18
|
+
// Key derivation components — split across the file to avoid easy grep
|
|
19
|
+
// These combine to form the HMAC signing key
|
|
20
|
+
const _a = Buffer.from('7570-6c69-6e6b', 'hex'); // part 1
|
|
21
|
+
const _b = Buffer.from('2e70-7265-6d69-756d', 'hex'); // part 2
|
|
22
|
+
const _c = Buffer.from('2e6c-6963-656e-7365', 'hex'); // part 3
|
|
23
|
+
const _d = Buffer.from('2e76-3031', 'hex'); // part 4
|
|
24
|
+
|
|
25
|
+
function _dk() {
|
|
26
|
+
// Derive signing key from components + additional mixing
|
|
27
|
+
const base = Buffer.concat([_a, _b, _c, _d]);
|
|
28
|
+
return createHmac('sha256', 'uplink-key-derivation')
|
|
29
|
+
.update(base)
|
|
30
|
+
.digest();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Base32 alphabet (Crockford variant — no I/L/O/U to avoid confusion)
|
|
34
|
+
const B32 = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';
|
|
35
|
+
|
|
36
|
+
function base32Encode(buffer) {
|
|
37
|
+
let result = '';
|
|
38
|
+
let bits = 0;
|
|
39
|
+
let value = 0;
|
|
40
|
+
for (const byte of buffer) {
|
|
41
|
+
value = (value << 8) | byte;
|
|
42
|
+
bits += 8;
|
|
43
|
+
while (bits >= 5) {
|
|
44
|
+
bits -= 5;
|
|
45
|
+
result += B32[(value >>> bits) & 0x1f];
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (bits > 0) {
|
|
49
|
+
result += B32[(value << (5 - bits)) & 0x1f];
|
|
50
|
+
}
|
|
51
|
+
return result;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function base32Decode(str) {
|
|
55
|
+
const lookup = {};
|
|
56
|
+
for (let i = 0; i < B32.length; i++) {
|
|
57
|
+
lookup[B32[i]] = i;
|
|
58
|
+
}
|
|
59
|
+
// Also accept lowercase
|
|
60
|
+
for (let i = 0; i < B32.length; i++) {
|
|
61
|
+
lookup[B32[i].toLowerCase()] = i;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
let bits = 0;
|
|
65
|
+
let value = 0;
|
|
66
|
+
const bytes = [];
|
|
67
|
+
for (const char of str) {
|
|
68
|
+
const v = lookup[char];
|
|
69
|
+
if (v === undefined) return null;
|
|
70
|
+
value = (value << 5) | v;
|
|
71
|
+
bits += 5;
|
|
72
|
+
if (bits >= 8) {
|
|
73
|
+
bits -= 8;
|
|
74
|
+
bytes.push((value >>> bits) & 0xff);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return Buffer.from(bytes);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Validate a license key
|
|
82
|
+
* @param {string} key - License key (e.g. UPL-A1B2C-D3E4F-G5H6J-K7M8N)
|
|
83
|
+
* @returns {{ valid: boolean, error?: string }}
|
|
84
|
+
*/
|
|
85
|
+
export function validateLicense(key) {
|
|
86
|
+
if (!key || typeof key !== 'string') {
|
|
87
|
+
return { valid: false, error: 'No license key provided' };
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Normalize: remove prefix, dashes, whitespace, uppercase
|
|
91
|
+
const cleaned = key.trim().toUpperCase().replace(/^UPL-/, '').replace(/[-\s]/g, '');
|
|
92
|
+
|
|
93
|
+
// Should be exactly 20 base32 chars (10 payload + 10 tag)
|
|
94
|
+
if (cleaned.length !== 20) {
|
|
95
|
+
return { valid: false, error: 'Invalid key format' };
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Split into payload and tag
|
|
99
|
+
const payloadStr = cleaned.slice(0, 10);
|
|
100
|
+
const tagStr = cleaned.slice(10);
|
|
101
|
+
|
|
102
|
+
const payload = base32Decode(payloadStr);
|
|
103
|
+
const tag = base32Decode(tagStr);
|
|
104
|
+
|
|
105
|
+
if (!payload || !tag) {
|
|
106
|
+
return { valid: false, error: 'Invalid key format' };
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Canonicalize: re-encode decoded bytes and compare to input
|
|
110
|
+
// This prevents padding bit variants from being treated as different keys
|
|
111
|
+
if (base32Encode(payload).slice(0, 10) !== payloadStr ||
|
|
112
|
+
base32Encode(tag).slice(0, 10) !== tagStr) {
|
|
113
|
+
return { valid: false, error: 'Invalid key format' };
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Compute expected HMAC tag
|
|
117
|
+
const signingKey = _dk();
|
|
118
|
+
const expectedTag = createHmac('sha256', signingKey)
|
|
119
|
+
.update(payload)
|
|
120
|
+
.digest()
|
|
121
|
+
.slice(0, 6); // Truncate to 6 bytes (matches tag length)
|
|
122
|
+
|
|
123
|
+
// Constant-time comparison
|
|
124
|
+
if (expectedTag.length !== tag.length) {
|
|
125
|
+
return { valid: false, error: 'Invalid license key' };
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
let diff = 0;
|
|
129
|
+
for (let i = 0; i < expectedTag.length; i++) {
|
|
130
|
+
diff |= expectedTag[i] ^ tag[i];
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (diff !== 0) {
|
|
134
|
+
return { valid: false, error: 'Invalid license key' };
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return { valid: true };
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export default { validateLicense };
|