@bike4mind/cli 0.18.4 → 0.20.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 +17 -3
- package/README.md +204 -35
- package/bin/bike4mind-cli.mjs +137 -24
- package/bin/hearth-hook.mjs +292 -0
- package/dist/AgentHistoryStore-C8uUKjjC.mjs +35512 -0
- package/dist/ApiClient-B_CQrUiF.mjs +277 -0
- package/dist/{ConfigStore-Cq20962p.mjs → ConfigStore-DD3DcC3-.mjs} +6256 -3911
- package/dist/{ImageStore-BVmEG1xc.mjs → ImageStore-kVo-oHoS.mjs} +2 -2
- package/dist/PluginStore-DwvOJ-G3.mjs +206 -0
- package/dist/ProxyManager-Bqr7Lmsd.mjs +3 -0
- package/dist/{ProxyManager-CV94yZUW.mjs → ProxyManager-C5H0pUyK.mjs} +2 -2
- package/dist/{SandboxOrchestrator-BS6gALNq.mjs → SandboxOrchestrator-BFPVpmB5.mjs} +1 -1
- package/dist/{SandboxOrchestrator-BoINxbX4.mjs → SandboxOrchestrator-C8uleDn2.mjs} +7 -7
- package/dist/ShellSessionManager-6o8KZzl1-vrbPAUTq.mjs +252 -0
- package/dist/{ViolationLogStore-B-plqJfn.mjs → ViolationLogStore-byEhxa2A.mjs} +1 -1
- package/dist/WorkItemsClient-Cow6nXx7.mjs +382 -0
- package/dist/{bashExecute-B1N1lMOS-TZVDbcQ4.mjs → bashExecute-CrdPpBqk-DCATrE-D.mjs} +116 -16
- package/dist/buildAgent-mVuXU_H4.mjs +824 -0
- package/dist/commands/acpCommand.mjs +798 -0
- package/dist/commands/apiCommand.mjs +14 -16
- package/dist/commands/doctorCommand.mjs +5 -5
- package/dist/commands/envCommand.mjs +1 -1
- package/dist/commands/headlessCommand.mjs +272 -76
- package/dist/commands/mcpCommand.mjs +14 -1
- package/dist/commands/pluginCommand.mjs +232 -0
- package/dist/commands/updateCommand.mjs +10 -9
- package/dist/{grepSearch-DJs-cubo-Bm0Y8oS3.mjs → grepSearch-BaYUfIYs-C-fxWc9G.mjs} +3 -3
- package/dist/index.mjs +3281 -2322
- package/dist/{package-CBaK53NX.mjs → package-BqKSCbso.mjs} +1 -1
- package/dist/serve-CuF0I5en.mjs +772 -0
- package/dist/store-BG3e54c8.mjs +3 -0
- package/dist/{store-DV5s-qni.mjs → store-CvjTpQPs.mjs} +70 -3
- package/dist/{terminalSetup-BbJt04ZG.mjs → terminalSetup-DjXAwpDy.mjs} +2 -3
- package/dist/{treeSitterEngine-BRbQ9b7I.mjs → treeSitterEngine-QBE3YkmG.mjs} +51 -1
- package/dist/{updateChecker-C8xsNY2L.mjs → updateChecker-CQW8bxo6.mjs} +10 -10
- package/package.json +48 -43
- package/dist/BackgroundAgentManager-DOesheMD.mjs +0 -27171
- package/dist/ProxyManager-ByuAHFMq.mjs +0 -3
- package/dist/store-DgzCTRkN.mjs +0 -3
- package/dist/utils-Cdktpk_k.mjs +0 -158
- package/dist/utils-DEizxshI.mjs +0 -3
package/dist/store-DgzCTRkN.mjs
DELETED
package/dist/utils-Cdktpk_k.mjs
DELETED
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { createHash, timingSafeEqual } from "crypto";
|
|
3
|
-
import speakeasy from "speakeasy";
|
|
4
|
-
import QRCode from "qrcode";
|
|
5
|
-
//#region ../../b4m-core/auth/dist/mfaService/utils.mjs
|
|
6
|
-
const originalEmitWarning = process.emitWarning;
|
|
7
|
-
process.emitWarning = (warning, name) => {
|
|
8
|
-
if (name === "DeprecationWarning" && warning?.toString().includes("Buffer")) return;
|
|
9
|
-
return originalEmitWarning.call(process, warning, name);
|
|
10
|
-
};
|
|
11
|
-
process.emitWarning = originalEmitWarning;
|
|
12
|
-
/**
|
|
13
|
-
* Generate TOTP setup data including secret and QR code
|
|
14
|
-
* Using the same implementation as polaris
|
|
15
|
-
*/
|
|
16
|
-
async function generateTOTPSetup(userEmail, appName = process.env.APP_NAME || "") {
|
|
17
|
-
const secret = speakeasy.generateSecret({ name: appName ? `${appName} (${userEmail})` : userEmail });
|
|
18
|
-
const qrCodeUrl = await QRCode.toDataURL(secret.otpauth_url);
|
|
19
|
-
return {
|
|
20
|
-
secret: secret.base32,
|
|
21
|
-
qrCodeUrl,
|
|
22
|
-
manualEntryKey: secret.base32
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Verify a TOTP token against a secret
|
|
27
|
-
* Using industry-standard window to handle minor clock drift
|
|
28
|
-
*/
|
|
29
|
-
function verifyTOTPToken(secret, token, window = 1) {
|
|
30
|
-
return speakeasy.totp.verify({
|
|
31
|
-
secret,
|
|
32
|
-
encoding: "base32",
|
|
33
|
-
token,
|
|
34
|
-
window
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Hash a backup code for at-rest storage.
|
|
39
|
-
* Codes are high-entropy random strings (speakeasy base32, ~50 bits), so a
|
|
40
|
-
* fast SHA-256 is appropriate — no dictionary attack risk, and the migration
|
|
41
|
-
* backfill over thousands of users stays instantaneous.
|
|
42
|
-
*/
|
|
43
|
-
function hashBackupCode(code) {
|
|
44
|
-
return createHash("sha256").update(code.trim().toUpperCase()).digest("hex");
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Generate cryptographically secure backup codes for MFA.
|
|
48
|
-
* Returns plaintext codes for display to the user; callers are responsible for
|
|
49
|
-
* hashing them (via hashBackupCode) before storing in the database.
|
|
50
|
-
*/
|
|
51
|
-
function generateBackupCodes(count = 10) {
|
|
52
|
-
return Array.from({ length: count }, () => {
|
|
53
|
-
return speakeasy.generateSecret({ length: 20 }).base32.substring(0, 10).toUpperCase();
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Verify a backup code against stored hashes.
|
|
58
|
-
* Hashes the provided code and compares against stored SHA-256 hashes using
|
|
59
|
-
* constant-time comparison to prevent timing attacks.
|
|
60
|
-
*/
|
|
61
|
-
function verifyBackupCode(userBackupCodes, providedCode) {
|
|
62
|
-
if (!userBackupCodes || !providedCode) return { isValid: false };
|
|
63
|
-
const providedHash = hashBackupCode(providedCode);
|
|
64
|
-
const providedBuf = Buffer.from(providedHash, "utf8");
|
|
65
|
-
let matchIdx = -1;
|
|
66
|
-
for (let i = 0; i < userBackupCodes.length; i++) {
|
|
67
|
-
const storedBuf = Buffer.from(userBackupCodes[i], "utf8");
|
|
68
|
-
if (storedBuf.length === providedBuf.length && timingSafeEqual(storedBuf, providedBuf)) {
|
|
69
|
-
matchIdx = i;
|
|
70
|
-
break;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
if (matchIdx !== -1) return {
|
|
74
|
-
isValid: true,
|
|
75
|
-
usedBackupCode: userBackupCodes[matchIdx]
|
|
76
|
-
};
|
|
77
|
-
return { isValid: false };
|
|
78
|
-
}
|
|
79
|
-
/**
|
|
80
|
-
* Check if a user requires MFA based on enforcement settings
|
|
81
|
-
* In lumina5, when MFA is enforced, it applies to ALL users (unlike polaris)
|
|
82
|
-
*/
|
|
83
|
-
function userRequiresMFA(user, enforceMFASetting) {
|
|
84
|
-
return enforceMFASetting;
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* Check if a user has MFA configured
|
|
88
|
-
*/
|
|
89
|
-
function userHasMFAConfigured(user) {
|
|
90
|
-
return !!(user.mfa && user.mfa.totpEnabled);
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Server-side attempt tracking to prevent bypass via refresh/cancel
|
|
94
|
-
* Constants for lockout policy
|
|
95
|
-
*/
|
|
96
|
-
const MAX_FAILED_ATTEMPTS = 3;
|
|
97
|
-
const LOCKOUT_DURATION_MS = 900 * 1e3;
|
|
98
|
-
const ATTEMPT_RESET_WINDOW_MS = 3600 * 1e3;
|
|
99
|
-
/**
|
|
100
|
-
* Check if user is currently locked out from MFA attempts
|
|
101
|
-
*/
|
|
102
|
-
function isUserLockedOut(user) {
|
|
103
|
-
if (!user.mfa?.lockedUntil) return false;
|
|
104
|
-
return /* @__PURE__ */ new Date() < new Date(user.mfa.lockedUntil);
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* Get remaining lockout time in minutes
|
|
108
|
-
*/
|
|
109
|
-
function getLockoutTimeRemaining(user) {
|
|
110
|
-
if (!user.mfa?.lockedUntil) return 0;
|
|
111
|
-
const remaining = new Date(user.mfa.lockedUntil).getTime() - Date.now();
|
|
112
|
-
return Math.max(0, Math.ceil(remaining / (60 * 1e3)));
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* Reset failed attempts if enough time has passed since last failure
|
|
116
|
-
*/
|
|
117
|
-
function shouldResetFailedAttempts(user) {
|
|
118
|
-
if (!user.mfa?.lastFailedAttempt) return false;
|
|
119
|
-
return Date.now() - new Date(user.mfa.lastFailedAttempt).getTime() > ATTEMPT_RESET_WINDOW_MS;
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* Record a failed MFA attempt and return updated MFA object
|
|
123
|
-
*/
|
|
124
|
-
function recordFailedAttempt(user) {
|
|
125
|
-
const newAttempts = (shouldResetFailedAttempts(user) ? 0 : user.mfa?.failedAttempts || 0) + 1;
|
|
126
|
-
const now = /* @__PURE__ */ new Date();
|
|
127
|
-
const updatedMFA = { ...user.mfa };
|
|
128
|
-
updatedMFA.failedAttempts = newAttempts;
|
|
129
|
-
updatedMFA.lastFailedAttempt = now;
|
|
130
|
-
if (newAttempts >= MAX_FAILED_ATTEMPTS) updatedMFA.lockedUntil = new Date(Date.now() + LOCKOUT_DURATION_MS);
|
|
131
|
-
return updatedMFA;
|
|
132
|
-
}
|
|
133
|
-
/**
|
|
134
|
-
* Clear failed attempts on successful verification
|
|
135
|
-
*/
|
|
136
|
-
function clearFailedAttempts(user) {
|
|
137
|
-
if (!user.mfa) return null;
|
|
138
|
-
const updatedMFA = { ...user.mfa };
|
|
139
|
-
updatedMFA.failedAttempts = 0;
|
|
140
|
-
updatedMFA.lastFailedAttempt = void 0;
|
|
141
|
-
updatedMFA.lockedUntil = void 0;
|
|
142
|
-
return updatedMFA;
|
|
143
|
-
}
|
|
144
|
-
/**
|
|
145
|
-
* Check if a user is eligible to set up MFA
|
|
146
|
-
*/
|
|
147
|
-
function userEligibleForMFA(user) {
|
|
148
|
-
return true;
|
|
149
|
-
}
|
|
150
|
-
/**
|
|
151
|
-
* Check if a user can disable MFA based on enforcement settings
|
|
152
|
-
* In lumina5, when MFA is enforced, NO user can disable it
|
|
153
|
-
*/
|
|
154
|
-
function userCanDisableMFA(user, enforceMFASetting) {
|
|
155
|
-
return !enforceMFASetting;
|
|
156
|
-
}
|
|
157
|
-
//#endregion
|
|
158
|
-
export { hashBackupCode as a, shouldResetFailedAttempts as c, userHasMFAConfigured as d, userRequiresMFA as f, getLockoutTimeRemaining as i, userCanDisableMFA as l, verifyTOTPToken as m, generateBackupCodes as n, isUserLockedOut as o, verifyBackupCode as p, generateTOTPSetup as r, recordFailedAttempt as s, clearFailedAttempts as t, userEligibleForMFA as u };
|
package/dist/utils-DEizxshI.mjs
DELETED