cerber-core 1.1.1 → 1.1.3
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/.cerber-example/{BIBLE.md → CERBER.md} +132 -132
- package/.cerber-example/CERBER_LAW.md +200 -200
- package/README.md +3 -85
- package/dev/templates/BACKEND_SCHEMA.ts.tpl +4 -2
- package/dev/templates/cerber-guardian.mjs.tpl +106 -2
- package/examples/team-integration/README.md +347 -347
- package/package.json +1 -1
- package/solo/templates/BACKEND_SCHEMA.ts.tpl +4 -2
- package/solo/templates/cerber-guardian.mjs.tpl +106 -2
- package/team/README.md +327 -327
- package/team/config/team-contract.json +27 -27
- package/team/templates/BACKEND_SCHEMA.ts.tpl +4 -2
- package/team/templates/BIBLE_TEMPLATE.md +52 -52
- package/team/templates/cerber-guardian.mjs.tpl +106 -2
package/README.md
CHANGED
|
@@ -50,7 +50,7 @@ ROI: Break-even on Day 1
|
|
|
50
50
|
**For CTOs & Engineering Managers:**
|
|
51
51
|
- **Reduce production incidents** - 95% bugs caught pre-production (vs 60-70% manual reviews)
|
|
52
52
|
- **Cut debugging costs** - 4.5 hours saved per developer per session
|
|
53
|
-
- **Speed up onboarding** -
|
|
53
|
+
- **Speed up onboarding** - CERBER.md = instant project understanding for new hires
|
|
54
54
|
- **Enforce architecture** - Prevent technical debt before it enters codebase
|
|
55
55
|
|
|
56
56
|
**Cost Comparison:**
|
|
@@ -91,7 +91,7 @@ Cerber guards → enforces your decisions
|
|
|
91
91
|
|
|
92
92
|
**Cerber Core solution:**
|
|
93
93
|
```
|
|
94
|
-
✅ Architect defines rules once (
|
|
94
|
+
✅ Architect defines rules once (CERBER.md contract)
|
|
95
95
|
✅ Cerber enforces automatically forever
|
|
96
96
|
✅ Every commit validates against your roadmap (<1 second)
|
|
97
97
|
✅ Architecture stays intact as team scales
|
|
@@ -141,7 +141,7 @@ export const BACKEND_SCHEMA = {
|
|
|
141
141
|
- **Focus Mode** - Generate 500 LOC context (vs 10K LOC) ⭐
|
|
142
142
|
- Module boundaries enforcement
|
|
143
143
|
- Connection contracts between modules
|
|
144
|
-
-
|
|
144
|
+
- CERBER.md project mapping
|
|
145
145
|
|
|
146
146
|
---
|
|
147
147
|
|
|
@@ -1143,88 +1143,6 @@ git commit # Guardian validates
|
|
|
1143
1143
|
|
|
1144
1144
|
---
|
|
1145
1145
|
|
|
1146
|
-
## 📖 BIBLE.md - Your Project's Single Source of Truth
|
|
1147
|
-
|
|
1148
|
-
**BIBLE.md** is your project's master map - the ONE place where everything is documented.
|
|
1149
|
-
|
|
1150
|
-
### Why BIBLE.md?
|
|
1151
|
-
|
|
1152
|
-
With AI coding, teams can diverge quickly. Everyone works fast, but in different directions. BIBLE.md keeps everyone aligned:
|
|
1153
|
-
|
|
1154
|
-
- **All modules documented** - What exists, who owns it, what it does
|
|
1155
|
-
- **All connections mapped** - How modules talk to each other
|
|
1156
|
-
- **Team responsibilities clear** - Who works on what
|
|
1157
|
-
- **Architecture decisions recorded** - Why things are built this way
|
|
1158
|
-
|
|
1159
|
-
### How It Works
|
|
1160
|
-
|
|
1161
|
-
```bash
|
|
1162
|
-
# 1. Copy template
|
|
1163
|
-
cp node_modules/cerber-core/team/templates/BIBLE_TEMPLATE.md .cerber/BIBLE.md
|
|
1164
|
-
|
|
1165
|
-
# 2. Describe your architecture
|
|
1166
|
-
nano .cerber/BIBLE.md
|
|
1167
|
-
|
|
1168
|
-
# 3. Keep it updated when adding modules
|
|
1169
|
-
# 4. Reference in code reviews
|
|
1170
|
-
```
|
|
1171
|
-
|
|
1172
|
-
### What's Inside BIBLE.md?
|
|
1173
|
-
|
|
1174
|
-
```markdown
|
|
1175
|
-
# PROJECT BIBLE - Master Map
|
|
1176
|
-
|
|
1177
|
-
## Architecture Overview
|
|
1178
|
-
[Visual diagram of your system]
|
|
1179
|
-
|
|
1180
|
-
## Modules Index
|
|
1181
|
-
1. **auth-service** - Authentication & JWT
|
|
1182
|
-
- Owner: Alice
|
|
1183
|
-
- Files: `src/modules/auth/`
|
|
1184
|
-
|
|
1185
|
-
2. **payment-service** - Stripe integration
|
|
1186
|
-
- Owner: Bob
|
|
1187
|
-
- Files: `src/modules/payment/`
|
|
1188
|
-
|
|
1189
|
-
## Connections Map
|
|
1190
|
-
- `auth-service` → `user-service`: validateToken()
|
|
1191
|
-
- `payment-service` → `notification-service`: sendReceipt()
|
|
1192
|
-
|
|
1193
|
-
## Team Responsibilities
|
|
1194
|
-
- Alice: auth, user management
|
|
1195
|
-
- Bob: payments, billing
|
|
1196
|
-
```
|
|
1197
|
-
|
|
1198
|
-
### Integration with Cerber
|
|
1199
|
-
|
|
1200
|
-
Cerber automatically reads BIBLE.md from `.cerber/BIBLE.md` when running health checks:
|
|
1201
|
-
|
|
1202
|
-
```typescript
|
|
1203
|
-
// server.ts
|
|
1204
|
-
import { createHealthEndpoint } from 'cerber-core';
|
|
1205
|
-
|
|
1206
|
-
const healthChecks = {
|
|
1207
|
-
// Cerber automatically validates against .cerber/BIBLE.md
|
|
1208
|
-
architecture: async () => {
|
|
1209
|
-
// Checks if actual modules match BIBLE structure
|
|
1210
|
-
return await validateArchitectureAgainstBible();
|
|
1211
|
-
}
|
|
1212
|
-
};
|
|
1213
|
-
|
|
1214
|
-
app.get('/api/health', createHealthEndpoint(healthChecks));
|
|
1215
|
-
```
|
|
1216
|
-
|
|
1217
|
-
**What Cerber checks:**
|
|
1218
|
-
- **Guardian** validates modules match BIBLE structure (pre-commit)
|
|
1219
|
-
- **Focus Mode** uses BIBLE to isolate context (500 LOC vs 10K LOC)
|
|
1220
|
-
- **Module checks** ensure boundaries defined in BIBLE are respected
|
|
1221
|
-
- **Morning checks** verify BIBLE is up-to-date with codebase
|
|
1222
|
-
- **Runtime health** checks architecture drift from BIBLE
|
|
1223
|
-
|
|
1224
|
-
**Result:** Your team stays aligned even when coding at AI speed! 🚀
|
|
1225
|
-
|
|
1226
|
-
---
|
|
1227
|
-
|
|
1228
1146
|
## 🏆 Why Cerber Core?
|
|
1229
1147
|
|
|
1230
1148
|
### Unique Innovations
|
|
@@ -20,12 +20,14 @@ export const BACKEND_SCHEMA = {
|
|
|
20
20
|
forbiddenPatterns: [
|
|
21
21
|
// Uncomment and customize based on your tech stack:
|
|
22
22
|
// {
|
|
23
|
-
// pattern:
|
|
23
|
+
// pattern: "password\\s*=\\s*['\"][^'\"]+['\"]",
|
|
24
|
+
// flags: "i",
|
|
24
25
|
// name: "Hardcoded passwords",
|
|
25
26
|
// severity: "error"
|
|
26
27
|
// },
|
|
27
28
|
// {
|
|
28
|
-
// pattern:
|
|
29
|
+
// pattern: "api[_-]?key\\s*=\\s*['\"][^'\"]+['\"]",
|
|
30
|
+
// flags: "i",
|
|
29
31
|
// name: "Hardcoded API keys",
|
|
30
32
|
// severity: "error"
|
|
31
33
|
// }
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import { execSync } from 'child_process';
|
|
6
6
|
import fs from 'fs';
|
|
7
|
+
import { join } from 'path';
|
|
7
8
|
|
|
8
9
|
const SCHEMA_FILE = '{{SCHEMA_FILE}}';
|
|
9
10
|
const APPROVALS_TAG = '{{APPROVALS_TAG}}';
|
|
@@ -13,10 +14,23 @@ async function main() {
|
|
|
13
14
|
|
|
14
15
|
if (!fs.existsSync(SCHEMA_FILE)) {
|
|
15
16
|
console.error(`❌ Schema file not found: ${SCHEMA_FILE}`);
|
|
16
|
-
console.error('
|
|
17
|
+
console.error('Create your schema file to enable validation.');
|
|
18
|
+
console.error(`Example: npx cerber init --print-schema-template > ${SCHEMA_FILE}`);
|
|
17
19
|
process.exit(1);
|
|
18
20
|
}
|
|
19
21
|
|
|
22
|
+
// Import schema
|
|
23
|
+
let schema;
|
|
24
|
+
try {
|
|
25
|
+
const schemaPath = join(process.cwd(), SCHEMA_FILE);
|
|
26
|
+
const schemaModule = await import(`file://${schemaPath}`);
|
|
27
|
+
schema = schemaModule.BACKEND_SCHEMA || schemaModule.default || schemaModule;
|
|
28
|
+
} catch (err) {
|
|
29
|
+
console.error(`❌ Failed to load schema from ${SCHEMA_FILE}:`, err.message);
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Get staged files
|
|
20
34
|
let stagedFiles;
|
|
21
35
|
try {
|
|
22
36
|
stagedFiles = execSync('git diff --cached --name-only', { encoding: 'utf-8' })
|
|
@@ -34,7 +48,97 @@ async function main() {
|
|
|
34
48
|
}
|
|
35
49
|
|
|
36
50
|
console.log(`Checking ${stagedFiles.length} file(s)...`);
|
|
37
|
-
|
|
51
|
+
|
|
52
|
+
const violations = [];
|
|
53
|
+
|
|
54
|
+
// Validate each staged file
|
|
55
|
+
for (const file of stagedFiles) {
|
|
56
|
+
if (!fs.existsSync(file)) continue;
|
|
57
|
+
|
|
58
|
+
const content = fs.readFileSync(file, 'utf-8');
|
|
59
|
+
|
|
60
|
+
// Check forbidden patterns
|
|
61
|
+
if (schema.forbiddenPatterns && Array.isArray(schema.forbiddenPatterns)) {
|
|
62
|
+
for (const rule of schema.forbiddenPatterns) {
|
|
63
|
+
if (!rule.pattern) continue;
|
|
64
|
+
|
|
65
|
+
const pattern = typeof rule.pattern === 'string'
|
|
66
|
+
? new RegExp(rule.pattern, rule.flags || 'i')
|
|
67
|
+
: rule.pattern;
|
|
68
|
+
|
|
69
|
+
// Check if file is in exceptions
|
|
70
|
+
if (rule.exceptions && rule.exceptions.some(ex => file.includes(ex))) {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (pattern.test(content)) {
|
|
75
|
+
// Check for architect approval
|
|
76
|
+
const hasApproval = content.includes(APPROVALS_TAG);
|
|
77
|
+
|
|
78
|
+
if (!hasApproval) {
|
|
79
|
+
violations.push({
|
|
80
|
+
file,
|
|
81
|
+
rule: rule.name || 'Unnamed rule',
|
|
82
|
+
severity: rule.severity || 'error'
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Check required imports (rules)
|
|
90
|
+
if (schema.rules && Array.isArray(schema.rules)) {
|
|
91
|
+
for (const rule of schema.rules) {
|
|
92
|
+
if (!rule.pattern || !rule.requiredImports) continue;
|
|
93
|
+
|
|
94
|
+
const filePattern = typeof rule.pattern === 'string' ? new RegExp(rule.pattern) : rule.pattern;
|
|
95
|
+
|
|
96
|
+
if (!filePattern.test(file)) continue;
|
|
97
|
+
|
|
98
|
+
// Check if file is in exceptions
|
|
99
|
+
if (rule.exceptions && rule.exceptions.some(ex => file.includes(ex))) {
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Check each required import
|
|
104
|
+
for (const requiredImport of rule.requiredImports) {
|
|
105
|
+
const importPattern = new RegExp(`import.*${requiredImport}`, 'i');
|
|
106
|
+
|
|
107
|
+
if (!importPattern.test(content)) {
|
|
108
|
+
// Check for architect approval
|
|
109
|
+
const hasApproval = content.includes(APPROVALS_TAG);
|
|
110
|
+
|
|
111
|
+
if (!hasApproval) {
|
|
112
|
+
violations.push({
|
|
113
|
+
file,
|
|
114
|
+
rule: `${rule.name || 'Unnamed rule'}: missing import '${requiredImport}'`,
|
|
115
|
+
severity: rule.severity || 'error'
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Report violations
|
|
125
|
+
if (violations.length > 0) {
|
|
126
|
+
console.error('\n❌ Architecture violations detected:\n');
|
|
127
|
+
|
|
128
|
+
for (const v of violations) {
|
|
129
|
+
const icon = v.severity === 'error' ? '🔴' : '⚠️';
|
|
130
|
+
console.error(`${icon} [${v.severity.toUpperCase()}] ${v.file}`);
|
|
131
|
+
console.error(` ${v.rule}`);
|
|
132
|
+
console.error(` Add ${APPROVALS_TAG} comment to override\n`);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const errorCount = violations.filter(v => v.severity === 'error').length;
|
|
136
|
+
if (errorCount > 0) {
|
|
137
|
+
console.error(`\n❌ Commit blocked: ${errorCount} error(s) found`);
|
|
138
|
+
process.exit(1);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
38
142
|
console.log('✅ All checks passed');
|
|
39
143
|
}
|
|
40
144
|
|