@codyswann/lisa 2.142.3 → 2.143.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/package.json +1 -1
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-agy/plugin.json +1 -1
- package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-agy/plugin.json +1 -1
- package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-agy/plugin.json +1 -1
- package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-agy/plugin.json +1 -1
- package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-agy/plugin.json +1 -1
- package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-agy/plugin.json +1 -1
- package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/scripts/wiki-safety.mjs +199 -0
- package/plugins/lisa-wiki-agy/plugin.json +1 -1
- package/plugins/lisa-wiki-agy/scripts/wiki-safety.mjs +199 -0
- package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-copilot/scripts/wiki-safety.mjs +199 -0
- package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-cursor/scripts/wiki-safety.mjs +199 -0
- package/plugins/src/wiki/scripts/wiki-safety.mjs +199 -0
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Deterministic wiki source safety helpers.
|
|
4
|
+
*
|
|
5
|
+
* This module intentionally uses only Node built-ins and pure string scanning so
|
|
6
|
+
* downstream wiki connectors can run the same redaction pass before persisting
|
|
7
|
+
* reader-safe source notes.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const PLACEHOLDERS = {
|
|
11
|
+
ssn: "[REDACTED:SSN]",
|
|
12
|
+
credit_card: "[REDACTED:CREDIT_CARD]",
|
|
13
|
+
private_key: "[REDACTED:PRIVATE_KEY]",
|
|
14
|
+
password: "[REDACTED:PASSWORD]",
|
|
15
|
+
api_key: "[REDACTED:API_KEY]",
|
|
16
|
+
oauth_token: "[REDACTED:OAUTH_TOKEN]",
|
|
17
|
+
bank_account: "[REDACTED:BANK_ACCOUNT]",
|
|
18
|
+
routing_number: "[REDACTED:ROUTING_NUMBER]",
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const PATTERNS = [
|
|
22
|
+
{
|
|
23
|
+
entityType: "private_key",
|
|
24
|
+
confidence: "high",
|
|
25
|
+
re: /-----BEGIN (?:RSA |EC |OPENSSH |DSA |PGP )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA |EC |OPENSSH |DSA |PGP )?PRIVATE KEY-----/g,
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
entityType: "ssn",
|
|
29
|
+
confidence: "high",
|
|
30
|
+
re: /\b(?!000|666|9\d\d)\d{3}-(?!00)\d{2}-(?!0000)\d{4}\b/g,
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
entityType: "password",
|
|
34
|
+
confidence: "high",
|
|
35
|
+
re: /\b(?:password|passwd|pwd)\s*[:=]\s*(['"]?)([^\s'",;]{8,})\1/gi,
|
|
36
|
+
valueGroup: 2,
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
entityType: "api_key",
|
|
40
|
+
confidence: "medium",
|
|
41
|
+
re: /\b(?:api[_-]?key|access[_-]?key|secret[_-]?key|client[_-]?secret)\s*[:=]\s*(['"]?)([A-Za-z0-9._-]{20,})\1/gi,
|
|
42
|
+
valueGroup: 2,
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
entityType: "oauth_token",
|
|
46
|
+
confidence: "high",
|
|
47
|
+
re: /\b(?:oauth[_-]?token|refresh[_-]?token|access[_-]?token|bearer)\s*[:= ]\s*(['"]?)([A-Za-z0-9._-]{24,})\1/gi,
|
|
48
|
+
valueGroup: 2,
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
entityType: "routing_number",
|
|
52
|
+
confidence: "medium",
|
|
53
|
+
re: /\b(?:routing|routing_number|aba)\s*(?:number|no\.?)?\s*[:#=]?\s*(\d{9})\b/gi,
|
|
54
|
+
valueGroup: 1,
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
entityType: "bank_account",
|
|
58
|
+
confidence: "medium",
|
|
59
|
+
re: /\b(?:bank\s+)?(?:account|acct)\s*(?:number|no\.?)?\s*[:#=]?\s*(\d{6,17})\b/gi,
|
|
60
|
+
valueGroup: 1,
|
|
61
|
+
},
|
|
62
|
+
];
|
|
63
|
+
|
|
64
|
+
function luhnValid(candidate) {
|
|
65
|
+
const digits = candidate.replace(/\D/g, "");
|
|
66
|
+
if (digits.length < 13 || digits.length > 19) return false;
|
|
67
|
+
let sum = 0;
|
|
68
|
+
let doubleDigit = false;
|
|
69
|
+
for (let i = digits.length - 1; i >= 0; i -= 1) {
|
|
70
|
+
let n = Number(digits[i]);
|
|
71
|
+
if (doubleDigit) {
|
|
72
|
+
n *= 2;
|
|
73
|
+
if (n > 9) n -= 9;
|
|
74
|
+
}
|
|
75
|
+
sum += n;
|
|
76
|
+
doubleDigit = !doubleDigit;
|
|
77
|
+
}
|
|
78
|
+
return sum % 10 === 0;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function applyFinding(text, match, pattern) {
|
|
82
|
+
const raw = match[0];
|
|
83
|
+
const value = pattern.valueGroup ? match[pattern.valueGroup] : raw;
|
|
84
|
+
const valueOffset = pattern.valueGroup ? raw.indexOf(value) : 0;
|
|
85
|
+
const start = match.index + valueOffset;
|
|
86
|
+
const end = start + value.length;
|
|
87
|
+
return {
|
|
88
|
+
sanitized:
|
|
89
|
+
text.slice(0, start) + PLACEHOLDERS[pattern.entityType] + text.slice(end),
|
|
90
|
+
finding: {
|
|
91
|
+
entityType: pattern.entityType,
|
|
92
|
+
confidence: pattern.confidence,
|
|
93
|
+
range: { start, end },
|
|
94
|
+
},
|
|
95
|
+
delta: PLACEHOLDERS[pattern.entityType].length - value.length,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function collectCreditCardFindings(text) {
|
|
100
|
+
const findings = [];
|
|
101
|
+
const re = /\b(?:\d[ -]?){13,19}\b/g;
|
|
102
|
+
let match;
|
|
103
|
+
while ((match = re.exec(text)) !== null) {
|
|
104
|
+
const value = match[0].trim();
|
|
105
|
+
if (!luhnValid(value)) continue;
|
|
106
|
+
findings.push({
|
|
107
|
+
entityType: "credit_card",
|
|
108
|
+
confidence: "high",
|
|
109
|
+
range: { start: match.index, end: match.index + match[0].length },
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
return findings;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function summarizeFindings(sourceMetadata, findings) {
|
|
116
|
+
const sourceId =
|
|
117
|
+
sourceMetadata.sourceId ??
|
|
118
|
+
sourceMetadata.id ??
|
|
119
|
+
sourceMetadata.path ??
|
|
120
|
+
sourceMetadata.url ??
|
|
121
|
+
"unknown";
|
|
122
|
+
const byType = new Map();
|
|
123
|
+
for (const finding of findings) {
|
|
124
|
+
const current = byType.get(finding.entityType) ?? {
|
|
125
|
+
sourceId,
|
|
126
|
+
entityType: finding.entityType,
|
|
127
|
+
confidence: finding.confidence,
|
|
128
|
+
count: 0,
|
|
129
|
+
ranges: [],
|
|
130
|
+
};
|
|
131
|
+
current.count += 1;
|
|
132
|
+
current.ranges.push(finding.range);
|
|
133
|
+
byType.set(finding.entityType, current);
|
|
134
|
+
}
|
|
135
|
+
return [...byType.values()].sort((a, b) =>
|
|
136
|
+
a.entityType.localeCompare(b.entityType)
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function collectFindings(rawText) {
|
|
141
|
+
const text = String(rawText ?? "");
|
|
142
|
+
const findings = [];
|
|
143
|
+
|
|
144
|
+
for (const pattern of PATTERNS) {
|
|
145
|
+
pattern.re.lastIndex = 0;
|
|
146
|
+
let match;
|
|
147
|
+
while ((match = pattern.re.exec(text)) !== null) {
|
|
148
|
+
findings.push(applyFinding(text, match, pattern).finding);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
findings.push(...collectCreditCardFindings(text));
|
|
152
|
+
findings.sort((a, b) => a.range.start - b.range.start);
|
|
153
|
+
return findings;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export function scanWikiSourceText(rawText, sourceMetadata = {}) {
|
|
157
|
+
const findings = collectFindings(rawText);
|
|
158
|
+
|
|
159
|
+
return {
|
|
160
|
+
sourceId:
|
|
161
|
+
sourceMetadata.sourceId ??
|
|
162
|
+
sourceMetadata.id ??
|
|
163
|
+
sourceMetadata.path ??
|
|
164
|
+
sourceMetadata.url ??
|
|
165
|
+
"unknown",
|
|
166
|
+
reviewRequired: findings.length > 0,
|
|
167
|
+
findings: summarizeFindings(sourceMetadata, findings),
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export function sanitizeWikiSourceText(rawText, sourceMetadata = {}) {
|
|
172
|
+
let sanitized = String(rawText ?? "");
|
|
173
|
+
const rawFindings = collectFindings(rawText);
|
|
174
|
+
for (const finding of [...rawFindings].sort(
|
|
175
|
+
(a, b) => b.range.start - a.range.start
|
|
176
|
+
)) {
|
|
177
|
+
sanitized =
|
|
178
|
+
sanitized.slice(0, finding.range.start) +
|
|
179
|
+
PLACEHOLDERS[finding.entityType] +
|
|
180
|
+
sanitized.slice(finding.range.end);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return {
|
|
184
|
+
text: sanitized,
|
|
185
|
+
reviewRequired: rawFindings.length > 0,
|
|
186
|
+
findings: summarizeFindings(sourceMetadata, rawFindings),
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export function serializeWikiSafetyFindings(result) {
|
|
191
|
+
return JSON.stringify(
|
|
192
|
+
{
|
|
193
|
+
reviewRequired: Boolean(result?.reviewRequired),
|
|
194
|
+
findings: Array.isArray(result?.findings) ? result.findings : [],
|
|
195
|
+
},
|
|
196
|
+
null,
|
|
197
|
+
2
|
|
198
|
+
);
|
|
199
|
+
}
|