beddel 0.1.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/README.md +297 -0
- package/dist/agents/agentRegistry.d.ts +68 -0
- package/dist/agents/agentRegistry.d.ts.map +1 -0
- package/dist/agents/agentRegistry.js +222 -0
- package/dist/agents/agentRegistry.js.map +1 -0
- package/dist/agents/formatter-agent.d.ts +10 -0
- package/dist/agents/formatter-agent.d.ts.map +1 -0
- package/dist/agents/formatter-agent.js +49 -0
- package/dist/agents/formatter-agent.js.map +1 -0
- package/dist/agents/genkit-agent.d.ts +12 -0
- package/dist/agents/genkit-agent.d.ts.map +1 -0
- package/dist/agents/genkit-agent.js +119 -0
- package/dist/agents/genkit-agent.js.map +1 -0
- package/dist/agents/i18n-messages.d.ts +17 -0
- package/dist/agents/i18n-messages.d.ts.map +1 -0
- package/dist/agents/i18n-messages.js +92 -0
- package/dist/agents/i18n-messages.js.map +1 -0
- package/dist/agents/index.d.ts +10 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/index.js +26 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/agents/pipeline.d.ts +15 -0
- package/dist/agents/pipeline.d.ts.map +1 -0
- package/dist/agents/pipeline.js +45 -0
- package/dist/agents/pipeline.js.map +1 -0
- package/dist/agents/schema-factory.d.ts +40 -0
- package/dist/agents/schema-factory.d.ts.map +1 -0
- package/dist/agents/schema-factory.js +121 -0
- package/dist/agents/schema-factory.js.map +1 -0
- package/dist/agents/translation-validators.d.ts +26 -0
- package/dist/agents/translation-validators.d.ts.map +1 -0
- package/dist/agents/translation-validators.js +77 -0
- package/dist/agents/translation-validators.js.map +1 -0
- package/dist/agents/translator-agents.d.ts +184 -0
- package/dist/agents/translator-agents.d.ts.map +1 -0
- package/dist/agents/translator-agents.js +613 -0
- package/dist/agents/translator-agents.js.map +1 -0
- package/dist/agents/types/translation.types.d.ts +100 -0
- package/dist/agents/types/translation.types.d.ts.map +1 -0
- package/dist/agents/types/translation.types.js +3 -0
- package/dist/agents/types/translation.types.js.map +1 -0
- package/dist/agents/validator-agent.d.ts +42 -0
- package/dist/agents/validator-agent.d.ts.map +1 -0
- package/dist/agents/validator-agent.js +122 -0
- package/dist/agents/validator-agent.js.map +1 -0
- package/dist/audit/auditTrail.d.ts +55 -0
- package/dist/audit/auditTrail.d.ts.map +1 -0
- package/dist/audit/auditTrail.js +93 -0
- package/dist/audit/auditTrail.js.map +1 -0
- package/dist/compliance/gdprEngine.d.ts +44 -0
- package/dist/compliance/gdprEngine.d.ts.map +1 -0
- package/dist/compliance/gdprEngine.js +178 -0
- package/dist/compliance/gdprEngine.js.map +1 -0
- package/dist/compliance/lgpdEngine.d.ts +51 -0
- package/dist/compliance/lgpdEngine.d.ts.map +1 -0
- package/dist/compliance/lgpdEngine.js +221 -0
- package/dist/compliance/lgpdEngine.js.map +1 -0
- package/dist/config.d.ts +78 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +77 -0
- package/dist/config.js.map +1 -0
- package/dist/errors.d.ts +17 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +40 -0
- package/dist/errors.js.map +1 -0
- package/dist/firebase/tenantManager.d.ts +84 -0
- package/dist/firebase/tenantManager.d.ts.map +1 -0
- package/dist/firebase/tenantManager.js +378 -0
- package/dist/firebase/tenantManager.js.map +1 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +118 -0
- package/dist/index.js.map +1 -0
- package/dist/integration/secure-yaml-runtime.d.ts +68 -0
- package/dist/integration/secure-yaml-runtime.d.ts.map +1 -0
- package/dist/integration/secure-yaml-runtime.js +245 -0
- package/dist/integration/secure-yaml-runtime.js.map +1 -0
- package/dist/parser/secure-yaml-parser.d.ts +62 -0
- package/dist/parser/secure-yaml-parser.d.ts.map +1 -0
- package/dist/parser/secure-yaml-parser.js +234 -0
- package/dist/parser/secure-yaml-parser.js.map +1 -0
- package/dist/performance/autoscaling.d.ts +100 -0
- package/dist/performance/autoscaling.d.ts.map +1 -0
- package/dist/performance/autoscaling.js +339 -0
- package/dist/performance/autoscaling.js.map +1 -0
- package/dist/performance/benchmark.d.ts +104 -0
- package/dist/performance/benchmark.d.ts.map +1 -0
- package/dist/performance/benchmark.js +514 -0
- package/dist/performance/benchmark.js.map +1 -0
- package/dist/performance/index.d.ts +14 -0
- package/dist/performance/index.d.ts.map +1 -0
- package/dist/performance/index.js +35 -0
- package/dist/performance/index.js.map +1 -0
- package/dist/performance/monitor.d.ts +126 -0
- package/dist/performance/monitor.d.ts.map +1 -0
- package/dist/performance/monitor.js +324 -0
- package/dist/performance/monitor.js.map +1 -0
- package/dist/performance/streaming.d.ts +82 -0
- package/dist/performance/streaming.d.ts.map +1 -0
- package/dist/performance/streaming.js +287 -0
- package/dist/performance/streaming.js.map +1 -0
- package/dist/runtime/audit.d.ts +240 -0
- package/dist/runtime/audit.d.ts.map +1 -0
- package/dist/runtime/audit.js +641 -0
- package/dist/runtime/audit.js.map +1 -0
- package/dist/runtime/declarativeAgentRuntime.d.ts +123 -0
- package/dist/runtime/declarativeAgentRuntime.d.ts.map +1 -0
- package/dist/runtime/declarativeAgentRuntime.js +576 -0
- package/dist/runtime/declarativeAgentRuntime.js.map +1 -0
- package/dist/runtime/isolatedRuntime.d.ts +119 -0
- package/dist/runtime/isolatedRuntime.d.ts.map +1 -0
- package/dist/runtime/isolatedRuntime.js +425 -0
- package/dist/runtime/isolatedRuntime.js.map +1 -0
- package/dist/runtime/schemaCompiler.d.ts +35 -0
- package/dist/runtime/schemaCompiler.d.ts.map +1 -0
- package/dist/runtime/schemaCompiler.js +151 -0
- package/dist/runtime/schemaCompiler.js.map +1 -0
- package/dist/runtime/simpleRuntime.d.ts +57 -0
- package/dist/runtime/simpleRuntime.d.ts.map +1 -0
- package/dist/runtime/simpleRuntime.js +187 -0
- package/dist/runtime/simpleRuntime.js.map +1 -0
- package/dist/security/dashboard.d.ts +89 -0
- package/dist/security/dashboard.d.ts.map +1 -0
- package/dist/security/dashboard.js +300 -0
- package/dist/security/dashboard.js.map +1 -0
- package/dist/security/hardening.d.ts +130 -0
- package/dist/security/hardening.d.ts.map +1 -0
- package/dist/security/hardening.js +414 -0
- package/dist/security/hardening.js.map +1 -0
- package/dist/security/index.d.ts +128 -0
- package/dist/security/index.d.ts.map +1 -0
- package/dist/security/index.js +353 -0
- package/dist/security/index.js.map +1 -0
- package/dist/security/monitor.d.ts +88 -0
- package/dist/security/monitor.d.ts.map +1 -0
- package/dist/security/monitor.js +356 -0
- package/dist/security/monitor.js.map +1 -0
- package/dist/security/scanner.d.ts +104 -0
- package/dist/security/scanner.d.ts.map +1 -0
- package/dist/security/scanner.js +298 -0
- package/dist/security/scanner.js.map +1 -0
- package/dist/security/score.d.ts +150 -0
- package/dist/security/score.d.ts.map +1 -0
- package/dist/security/score.js +983 -0
- package/dist/security/score.js.map +1 -0
- package/dist/security/test-security.d.ts +22 -0
- package/dist/security/test-security.d.ts.map +1 -0
- package/dist/security/test-security.js +154 -0
- package/dist/security/test-security.js.map +1 -0
- package/dist/security/threatDetector.d.ts +39 -0
- package/dist/security/threatDetector.d.ts.map +1 -0
- package/dist/security/threatDetector.js +354 -0
- package/dist/security/threatDetector.js.map +1 -0
- package/dist/security/validation.d.ts +69 -0
- package/dist/security/validation.d.ts.map +1 -0
- package/dist/security/validation.js +286 -0
- package/dist/security/validation.js.map +1 -0
- package/dist/server/api/clientsRoute.d.ts +9 -0
- package/dist/server/api/clientsRoute.d.ts.map +1 -0
- package/dist/server/api/clientsRoute.js +71 -0
- package/dist/server/api/clientsRoute.js.map +1 -0
- package/dist/server/api/endpointsRoute.d.ts +8 -0
- package/dist/server/api/endpointsRoute.d.ts.map +1 -0
- package/dist/server/api/endpointsRoute.js +76 -0
- package/dist/server/api/endpointsRoute.js.map +1 -0
- package/dist/server/api/graphql.d.ts +9 -0
- package/dist/server/api/graphql.d.ts.map +1 -0
- package/dist/server/api/graphql.js +180 -0
- package/dist/server/api/graphql.js.map +1 -0
- package/dist/server/errors.d.ts +19 -0
- package/dist/server/errors.d.ts.map +1 -0
- package/dist/server/errors.js +42 -0
- package/dist/server/errors.js.map +1 -0
- package/dist/server/index.d.ts +7 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +24 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/kvStore.d.ts +27 -0
- package/dist/server/kvStore.d.ts.map +1 -0
- package/dist/server/kvStore.js +128 -0
- package/dist/server/kvStore.js.map +1 -0
- package/dist/server/runtimeSecurity.d.ts +28 -0
- package/dist/server/runtimeSecurity.d.ts.map +1 -0
- package/dist/server/runtimeSecurity.js +85 -0
- package/dist/server/runtimeSecurity.js.map +1 -0
- package/dist/server/types.d.ts +53 -0
- package/dist/server/types.d.ts.map +1 -0
- package/dist/server/types.js +8 -0
- package/dist/server/types.js.map +1 -0
- package/dist/types/executionContext.d.ts +16 -0
- package/dist/types/executionContext.d.ts.map +1 -0
- package/dist/types/executionContext.js +3 -0
- package/dist/types/executionContext.js.map +1 -0
- package/package.json +77 -0
- package/src/agents/agentRegistry.ts +272 -0
- package/src/agents/image-agent.yaml +86 -0
- package/src/agents/joker-agent.yaml +47 -0
- package/src/agents/translator-agent.yaml +80 -0
- package/src/audit/auditTrail.ts +134 -0
- package/src/compliance/gdprEngine.ts +209 -0
- package/src/compliance/lgpdEngine.ts +268 -0
- package/src/config.ts +179 -0
- package/src/errors.ts +35 -0
- package/src/firebase/tenantManager.ts +443 -0
- package/src/index.ts +125 -0
- package/src/integration/secure-yaml-runtime.ts +341 -0
- package/src/parser/secure-yaml-parser.ts +273 -0
- package/src/performance/autoscaling.ts +495 -0
- package/src/performance/benchmark.ts +644 -0
- package/src/performance/index.ts +34 -0
- package/src/performance/monitor.ts +469 -0
- package/src/performance/streaming.ts +317 -0
- package/src/runtime/audit.ts +907 -0
- package/src/runtime/declarativeAgentRuntime.ts +836 -0
- package/src/runtime/isolatedRuntime.ts +572 -0
- package/src/runtime/schemaCompiler.ts +228 -0
- package/src/runtime/simpleRuntime.ts +201 -0
- package/src/security/dashboard.ts +462 -0
- package/src/security/hardening.ts +560 -0
- package/src/security/index.ts +439 -0
- package/src/security/monitor.ts +490 -0
- package/src/security/scanner.ts +368 -0
- package/src/security/score.ts +1138 -0
- package/src/security/threatDetector.ts +481 -0
- package/src/security/validation.ts +365 -0
- package/src/server/api/clientsRoute.ts +92 -0
- package/src/server/api/endpointsRoute.ts +97 -0
- package/src/server/api/graphql.ts +249 -0
- package/src/server/errors.ts +38 -0
- package/src/server/index.ts +6 -0
- package/src/server/kvStore.ts +152 -0
- package/src/server/runtimeSecurity.ts +102 -0
- package/src/server/types.ts +60 -0
- package/src/types/executionContext.ts +16 -0
- package/tools/seed.ts +365 -0
- package/tools/test-endpoints.ts +174 -0
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Security validation utilities for YAML parsing
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export interface SecurityValidationOptions {
|
|
6
|
+
maxKeyLength: number;
|
|
7
|
+
maxValueLength: number;
|
|
8
|
+
maxTotalSize: number;
|
|
9
|
+
validateKeyNames: boolean;
|
|
10
|
+
restrictSpecialChars: boolean;
|
|
11
|
+
maxNestingDepth: number;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface ValidationResult {
|
|
15
|
+
valid: boolean;
|
|
16
|
+
errors: ValidationError[];
|
|
17
|
+
warnings: ValidationWarning[];
|
|
18
|
+
stats: ValidationStats;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface ValidationError {
|
|
22
|
+
type: string;
|
|
23
|
+
message: string;
|
|
24
|
+
path: string;
|
|
25
|
+
severity: 'low' | 'medium' | 'high' | 'critical';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface ValidationWarning {
|
|
29
|
+
type: string;
|
|
30
|
+
message: string;
|
|
31
|
+
path: string;
|
|
32
|
+
recommendation: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface ValidationStats {
|
|
36
|
+
totalKeys: number;
|
|
37
|
+
maxDepth: number;
|
|
38
|
+
maxValueLength: number;
|
|
39
|
+
longestKey: string;
|
|
40
|
+
dataTypes: Record<string, number>;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const DEFAULT_VALIDATION_OPTIONS: SecurityValidationOptions = {
|
|
44
|
+
maxKeyLength: 1000,
|
|
45
|
+
maxValueLength: 10485760, // 10MB
|
|
46
|
+
maxTotalSize: 104857600, // 100MB
|
|
47
|
+
validateKeyNames: true,
|
|
48
|
+
restrictSpecialChars: true,
|
|
49
|
+
maxNestingDepth: 1000
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
// Pattern para caracteres especiais perigosos
|
|
53
|
+
const DANGEROUS_CHARS_PATTERN = /[\x00-\x08\x0B-\x0C\x0E-\x1F\x7F]/;
|
|
54
|
+
const KEY_NAME_PATTERN = /^[a-zA-Z_][a-zA-Z0-9_\-]*$/;
|
|
55
|
+
|
|
56
|
+
export class SecurityValidator {
|
|
57
|
+
private readonly options: SecurityValidationOptions;
|
|
58
|
+
|
|
59
|
+
constructor(options: Partial<SecurityValidationOptions> = {}) {
|
|
60
|
+
this.options = { ...DEFAULT_VALIDATION_OPTIONS, ...options };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Valida um objeto ou valor YAML para segurança
|
|
65
|
+
*/
|
|
66
|
+
validateObject(obj: any, path: string = 'root'): ValidationResult {
|
|
67
|
+
const errors: ValidationError[] = [];
|
|
68
|
+
const warnings: ValidationWarning[] = [];
|
|
69
|
+
const stats: ValidationStats = {
|
|
70
|
+
totalKeys: 0,
|
|
71
|
+
maxDepth: 0,
|
|
72
|
+
maxValueLength: 0,
|
|
73
|
+
longestKey: '',
|
|
74
|
+
dataTypes: {}
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const visit = (current: any, currentPath: string, depth: number = 0) => {
|
|
78
|
+
// Verifica profundidade máxima
|
|
79
|
+
if (depth > this.options.maxNestingDepth) {
|
|
80
|
+
errors.push({
|
|
81
|
+
type: 'depth_exceeded',
|
|
82
|
+
message: `Profundidade máxima de ${this.options.maxNestingDepth} excedida`,
|
|
83
|
+
path: currentPath,
|
|
84
|
+
severity: 'high'
|
|
85
|
+
});
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
stats.maxDepth = Math.max(stats.maxDepth, depth);
|
|
90
|
+
|
|
91
|
+
// Processa diferentes tipos de dados
|
|
92
|
+
if (current === null || current === undefined) {
|
|
93
|
+
stats.dataTypes.null = (stats.dataTypes.null || 0) + 1;
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (typeof current === 'boolean') {
|
|
98
|
+
stats.dataTypes.boolean = (stats.dataTypes.boolean || 0) + 1;
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (typeof current === 'number') {
|
|
103
|
+
stats.dataTypes.number = (stats.dataTypes.number || 0) + 1;
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (typeof current === 'string') {
|
|
108
|
+
stats.dataTypes.string = (stats.dataTypes.string || 0) + 1;
|
|
109
|
+
this.validateStringContent(current, currentPath, errors, warnings, stats);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (Array.isArray(current)) {
|
|
114
|
+
stats.dataTypes.array = (stats.dataTypes.array || 0) + 1;
|
|
115
|
+
current.forEach((item, index) => {
|
|
116
|
+
visit(item, `${currentPath}[${index}]`, depth + 1);
|
|
117
|
+
});
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (typeof current === 'object') {
|
|
122
|
+
stats.dataTypes.object = (stats.dataTypes.object || 0) + 1;
|
|
123
|
+
stats.totalKeys += Object.keys(current).length;
|
|
124
|
+
|
|
125
|
+
for (const [key, value] of Object.entries(current)) {
|
|
126
|
+
this.validateKey(key, errors, warnings, stats);
|
|
127
|
+
visit(value, `${currentPath}.${key}`, depth + 1);
|
|
128
|
+
}
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Tipo não permitido
|
|
133
|
+
errors.push({
|
|
134
|
+
type: 'forbidden_type',
|
|
135
|
+
message: `Tipo de dado não permitido: ${typeof current}`,
|
|
136
|
+
path: currentPath,
|
|
137
|
+
severity: 'high'
|
|
138
|
+
});
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
visit(obj, path, 0);
|
|
142
|
+
|
|
143
|
+
// Adiciona warnings baseados nas estatísticas
|
|
144
|
+
if (stats.totalKeys > 10000) {
|
|
145
|
+
warnings.push({
|
|
146
|
+
type: 'large_object',
|
|
147
|
+
message: `Objeto com ${stats.totalKeys} chaves pode afetar performance`,
|
|
148
|
+
path,
|
|
149
|
+
recommendation: 'Considerar limitar número de chaves para objetos grandes'
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (stats.maxDepth > 100) {
|
|
154
|
+
warnings.push({
|
|
155
|
+
type: 'deep_nesting',
|
|
156
|
+
message: `Profundidade de ${stats.maxDepth} pode ser difícil de manter`,
|
|
157
|
+
path,
|
|
158
|
+
recommendation: 'Considerar reduzir níveis de aninhamento'
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return {
|
|
163
|
+
valid: errors.length === 0,
|
|
164
|
+
errors,
|
|
165
|
+
warnings,
|
|
166
|
+
stats
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Valida o conteúdo de strings para caracteres perigosos
|
|
172
|
+
*/
|
|
173
|
+
private validateStringContent(
|
|
174
|
+
str: string,
|
|
175
|
+
path: string,
|
|
176
|
+
errors: ValidationError[],
|
|
177
|
+
warnings: ValidationWarning[],
|
|
178
|
+
stats: ValidationStats
|
|
179
|
+
): void {
|
|
180
|
+
stats.maxValueLength = Math.max(stats.maxValueLength, str.length);
|
|
181
|
+
|
|
182
|
+
// Verifica caracteres de controle perigosos
|
|
183
|
+
if (DANGEROUS_CHARS_PATTERN.test(str)) {
|
|
184
|
+
errors.push({
|
|
185
|
+
type: 'dangerous_chars',
|
|
186
|
+
message: 'String contém caracteres de controle perigosos',
|
|
187
|
+
path,
|
|
188
|
+
severity: 'high'
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Verifica tentativas de injection
|
|
193
|
+
if (this.options.restrictSpecialChars) {
|
|
194
|
+
// Verifica padrões comuns de injection
|
|
195
|
+
const dangerousPatterns = [
|
|
196
|
+
/<script[^>]*>/i,
|
|
197
|
+
/javascript:/i,
|
|
198
|
+
/on\w+\s*=/i,
|
|
199
|
+
/eval\s*\(/i,
|
|
200
|
+
/expression\s*\(/i,
|
|
201
|
+
/data:text\/html/i
|
|
202
|
+
];
|
|
203
|
+
|
|
204
|
+
for (const pattern of dangerousPatterns) {
|
|
205
|
+
if (pattern.test(str)) {
|
|
206
|
+
warnings.push({
|
|
207
|
+
type: 'potential_injection',
|
|
208
|
+
message: `Possível tentativa de code injection detectada`,
|
|
209
|
+
path,
|
|
210
|
+
recommendation: `Revisar conteúdo e filtrar elementos perigosos`
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Verifica tentativas de credential leakage
|
|
217
|
+
const credentialPatterns = [
|
|
218
|
+
/password\s*[:=]\s*["']?[\w\-]+["']?/i,
|
|
219
|
+
/api[_-]?key\s*[:=]\s*["']?[\w\-]+["']?/i,
|
|
220
|
+
/secret\s*[:=]\s*["']?[\w\-]+["']?/i,
|
|
221
|
+
/token\s*[:=]\s*["']?[\w\-]+["']?/i
|
|
222
|
+
];
|
|
223
|
+
|
|
224
|
+
for (const pattern of credentialPatterns) {
|
|
225
|
+
if (pattern.test(str)) {
|
|
226
|
+
warnings.push({
|
|
227
|
+
type: 'possible_credential',
|
|
228
|
+
message: `Possível exposição de credenciais detectada`,
|
|
229
|
+
path,
|
|
230
|
+
recommendation: `Remover ou mascarar informações sensíveis`
|
|
231
|
+
});
|
|
232
|
+
break;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Valida nomes de chaves para garantir segurança
|
|
239
|
+
*/
|
|
240
|
+
private validateKey(
|
|
241
|
+
key: string,
|
|
242
|
+
errors: ValidationError[],
|
|
243
|
+
warnings: ValidationWarning[],
|
|
244
|
+
stats: ValidationStats
|
|
245
|
+
): void {
|
|
246
|
+
if (key.length > stats.longestKey.length) {
|
|
247
|
+
stats.longestKey = key;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Verifica tamanho da chave
|
|
251
|
+
if (key.length > this.options.maxKeyLength) {
|
|
252
|
+
errors.push({
|
|
253
|
+
type: 'key_too_long',
|
|
254
|
+
message: `Chave excede limite de ${this.options.maxKeyLength} caracteres`,
|
|
255
|
+
path: `[key: "${key}"]`,
|
|
256
|
+
severity: 'medium'
|
|
257
|
+
});
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Valida formato do nome da chave
|
|
262
|
+
if (this.options.validateKeyNames && !KEY_NAME_PATTERN.test(key)) {
|
|
263
|
+
warnings.push({
|
|
264
|
+
type: 'invalid_key_name',
|
|
265
|
+
message: `Nome de chave "${key}" não segue convenções recomendadas`,
|
|
266
|
+
path: `[key: "${key}"]`,
|
|
267
|
+
recommendation: 'Usar nomes de chave alfanuméricos começando com letra ou underscore'
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// Verifica caracteres especiais na chave
|
|
272
|
+
if (this.options.restrictSpecialChars && /[<>:"'&|]/.test(key)) {
|
|
273
|
+
warnings.push({
|
|
274
|
+
type: 'dangerous_key_chars',
|
|
275
|
+
message: `Chave "${key}" contém caracteres potencialmente perigosos`,
|
|
276
|
+
path: `[key: "${key}"]`,
|
|
277
|
+
recommendation: 'Evitar caracteres especiais em nomes de chave'
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Gera um relatório de validação formatado
|
|
284
|
+
*/
|
|
285
|
+
generateReport(result: ValidationResult): string {
|
|
286
|
+
const lines: string[] = [];
|
|
287
|
+
|
|
288
|
+
if (result.valid) {
|
|
289
|
+
lines.push('✅ VALIDAÇÃO DE SEGURANÇA: PASS');
|
|
290
|
+
} else {
|
|
291
|
+
lines.push('❌ VALIDAÇÃO DE SEGURANÇA: FAIL');
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
lines.push('');
|
|
295
|
+
|
|
296
|
+
if (result.errors.length > 0) {
|
|
297
|
+
lines.push(`🔴 ERROS (${result.errors.length}):`);
|
|
298
|
+
result.errors.forEach(error => {
|
|
299
|
+
lines.push(` ${error.path}: ${error.message} [${error.severity.toUpperCase()}]`);
|
|
300
|
+
});
|
|
301
|
+
lines.push('');
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
if (result.warnings.length > 0) {
|
|
305
|
+
lines.push(`🟡 AVISOS (${result.warnings.length}):`);
|
|
306
|
+
result.warnings.forEach(warning => {
|
|
307
|
+
lines.push(` ${warning.path}: ${warning.message}`);
|
|
308
|
+
lines.push(` 💡 ${warning.recommendation}`);
|
|
309
|
+
});
|
|
310
|
+
lines.push('');
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
lines.push('📊 ESTATÍSTICAS:');
|
|
314
|
+
lines.push(` - Chaves totais: ${result.stats.totalKeys}`);
|
|
315
|
+
lines.push(` - Profundidade máxima: ${result.stats.maxDepth}`);
|
|
316
|
+
lines.push(` - Valor mais longo: ${result.stats.maxValueLength} caracteres`);
|
|
317
|
+
lines.push(` - Chave mais longa: "${result.stats.longestKey}" (${result.stats.longestKey.length} chars)`);
|
|
318
|
+
|
|
319
|
+
lines.push('');
|
|
320
|
+
lines.push('📈 TIPOS DE DADOS:');
|
|
321
|
+
Object.entries(result.stats.dataTypes).forEach(([type, count]) => {
|
|
322
|
+
lines.push(` - ${type}: ${count}`);
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
return lines.join('\n');
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Cria um resumo rápido da validação
|
|
330
|
+
*/
|
|
331
|
+
getQuickResult(result: ValidationResult): { ok: boolean; score: number } {
|
|
332
|
+
let score = 100;
|
|
333
|
+
|
|
334
|
+
// Penalidades por erros
|
|
335
|
+
result.errors.forEach(error => {
|
|
336
|
+
switch (error.severity) {
|
|
337
|
+
case 'low': score -= 10; break;
|
|
338
|
+
case 'medium': score -= 25; break;
|
|
339
|
+
case 'high': score -= 50; break;
|
|
340
|
+
case 'critical': score -= 100; break;
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
// Penalidades por warnings
|
|
345
|
+
result.warnings.forEach(() => {
|
|
346
|
+
score -= 5;
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
return {
|
|
350
|
+
ok: result.valid,
|
|
351
|
+
score: Math.max(0, score)
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Função auxiliar para validação rápida
|
|
358
|
+
*/
|
|
359
|
+
function isSecureYamlObject(obj: any, options: Partial<SecurityValidationOptions> = {}): boolean {
|
|
360
|
+
const validator = new SecurityValidator(options);
|
|
361
|
+
const result = validator.validateObject(obj);
|
|
362
|
+
return result.valid;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
export { isSecureYamlObject };
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Next.js route handlers for managing clients via Upstash KV.
|
|
3
|
+
* Exported from the Beddel package so the application code stays thin.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { saveClient, deleteClient, getClient } from "../kvStore";
|
|
7
|
+
import type { Client } from "../types";
|
|
8
|
+
|
|
9
|
+
export const dynamic = "force-dynamic";
|
|
10
|
+
|
|
11
|
+
export async function POST(request: Request) {
|
|
12
|
+
try {
|
|
13
|
+
const body = await request.json();
|
|
14
|
+
const { name, email, rateLimit, apiKeys } = body;
|
|
15
|
+
|
|
16
|
+
const client: Client = {
|
|
17
|
+
id: `client_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
|
|
18
|
+
name,
|
|
19
|
+
email,
|
|
20
|
+
rateLimit: rateLimit || 60,
|
|
21
|
+
apiKeys: apiKeys || [],
|
|
22
|
+
createdAt: new Date().toISOString(),
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
await saveClient(client);
|
|
26
|
+
|
|
27
|
+
return Response.json({ success: true, client });
|
|
28
|
+
} catch (error) {
|
|
29
|
+
console.error("[beddel] Error creating client:", error);
|
|
30
|
+
return Response.json(
|
|
31
|
+
{ success: false, error: "Failed to create client" },
|
|
32
|
+
{ status: 500 }
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export async function PUT(request: Request) {
|
|
38
|
+
try {
|
|
39
|
+
const body = await request.json();
|
|
40
|
+
const { id, name, email, rateLimit, apiKeys } = body;
|
|
41
|
+
|
|
42
|
+
const existing = await getClient(id);
|
|
43
|
+
if (!existing) {
|
|
44
|
+
return Response.json(
|
|
45
|
+
{ success: false, error: "Client not found" },
|
|
46
|
+
{ status: 404 }
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const client: Client = {
|
|
51
|
+
...existing,
|
|
52
|
+
name,
|
|
53
|
+
email,
|
|
54
|
+
rateLimit: rateLimit || 60,
|
|
55
|
+
apiKeys: apiKeys || [],
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
await saveClient(client);
|
|
59
|
+
|
|
60
|
+
return Response.json({ success: true, client });
|
|
61
|
+
} catch (error) {
|
|
62
|
+
console.error("[beddel] Error updating client:", error);
|
|
63
|
+
return Response.json(
|
|
64
|
+
{ success: false, error: "Failed to update client" },
|
|
65
|
+
{ status: 500 }
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export async function DELETE(request: Request) {
|
|
71
|
+
try {
|
|
72
|
+
const { searchParams } = new URL(request.url);
|
|
73
|
+
const id = searchParams.get("id");
|
|
74
|
+
|
|
75
|
+
if (!id) {
|
|
76
|
+
return Response.json(
|
|
77
|
+
{ success: false, error: "Missing client ID" },
|
|
78
|
+
{ status: 400 }
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
await deleteClient(id);
|
|
83
|
+
|
|
84
|
+
return Response.json({ success: true });
|
|
85
|
+
} catch (error) {
|
|
86
|
+
console.error("[beddel] Error deleting client:", error);
|
|
87
|
+
return Response.json(
|
|
88
|
+
{ success: false, error: "Failed to delete client" },
|
|
89
|
+
{ status: 500 }
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Next.js route handlers for managing endpoint definitions.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { saveEndpoint, deleteEndpoint, getEndpoint } from "../kvStore";
|
|
6
|
+
import type { Endpoint } from "../types";
|
|
7
|
+
|
|
8
|
+
export const dynamic = "force-dynamic";
|
|
9
|
+
|
|
10
|
+
export async function POST(request: Request) {
|
|
11
|
+
try {
|
|
12
|
+
const body = await request.json();
|
|
13
|
+
const { name, description, code, visibility, requiredProps } = body;
|
|
14
|
+
|
|
15
|
+
const endpoint: Endpoint = {
|
|
16
|
+
id: `endpoint_${Date.now()}_${Math.random()
|
|
17
|
+
.toString(36)
|
|
18
|
+
.substr(2, 9)}`,
|
|
19
|
+
name,
|
|
20
|
+
description,
|
|
21
|
+
code,
|
|
22
|
+
visibility,
|
|
23
|
+
requiredProps: requiredProps || [],
|
|
24
|
+
createdAt: new Date().toISOString(),
|
|
25
|
+
updatedAt: new Date().toISOString(),
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
await saveEndpoint(endpoint);
|
|
29
|
+
|
|
30
|
+
return Response.json({ success: true, endpoint });
|
|
31
|
+
} catch (error) {
|
|
32
|
+
console.error("[beddel] Error creating endpoint:", error);
|
|
33
|
+
return Response.json(
|
|
34
|
+
{ success: false, error: "Failed to create endpoint" },
|
|
35
|
+
{ status: 500 }
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export async function PUT(request: Request) {
|
|
41
|
+
try {
|
|
42
|
+
const body = await request.json();
|
|
43
|
+
const { id, name, description, code, visibility, requiredProps } = body;
|
|
44
|
+
|
|
45
|
+
const existing = await getEndpoint(id);
|
|
46
|
+
if (!existing) {
|
|
47
|
+
return Response.json(
|
|
48
|
+
{ success: false, error: "Endpoint not found" },
|
|
49
|
+
{ status: 404 }
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const endpoint: Endpoint = {
|
|
54
|
+
...existing,
|
|
55
|
+
name,
|
|
56
|
+
description,
|
|
57
|
+
code,
|
|
58
|
+
visibility,
|
|
59
|
+
requiredProps: requiredProps || [],
|
|
60
|
+
updatedAt: new Date().toISOString(),
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
await saveEndpoint(endpoint);
|
|
64
|
+
|
|
65
|
+
return Response.json({ success: true, endpoint });
|
|
66
|
+
} catch (error) {
|
|
67
|
+
console.error("[beddel] Error updating endpoint:", error);
|
|
68
|
+
return Response.json(
|
|
69
|
+
{ success: false, error: "Failed to update endpoint" },
|
|
70
|
+
{ status: 500 }
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export async function DELETE(request: Request) {
|
|
76
|
+
try {
|
|
77
|
+
const { searchParams } = new URL(request.url);
|
|
78
|
+
const id = searchParams.get("id");
|
|
79
|
+
|
|
80
|
+
if (!id) {
|
|
81
|
+
return Response.json(
|
|
82
|
+
{ success: false, error: "Missing endpoint ID" },
|
|
83
|
+
{ status: 400 }
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
await deleteEndpoint(id);
|
|
88
|
+
|
|
89
|
+
return Response.json({ success: true });
|
|
90
|
+
} catch (error) {
|
|
91
|
+
console.error("[beddel] Error deleting endpoint:", error);
|
|
92
|
+
return Response.json(
|
|
93
|
+
{ success: false, error: "Failed to delete endpoint" },
|
|
94
|
+
{ status: 500 }
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
}
|