opencodekit 0.20.7 → 0.20.8
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/dist/index.js +1 -1
- package/dist/template/.opencode/AGENTS.md +48 -0
- package/dist/template/.opencode/agent/build.md +3 -2
- package/dist/template/.opencode/agent/explore.md +14 -14
- package/dist/template/.opencode/agent/general.md +1 -1
- package/dist/template/.opencode/agent/plan.md +1 -1
- package/dist/template/.opencode/agent/review.md +1 -1
- package/dist/template/.opencode/agent/vision.md +0 -9
- package/dist/template/.opencode/memory.db +0 -0
- package/dist/template/.opencode/memory.db-shm +0 -0
- package/dist/template/.opencode/memory.db-wal +0 -0
- package/dist/template/.opencode/opencode.json +0 -5
- package/dist/template/.opencode/package.json +1 -1
- package/dist/template/.opencode/pnpm-lock.yaml +791 -9
- package/dist/template/.opencode/skill/api-and-interface-design/SKILL.md +162 -0
- package/dist/template/.opencode/skill/beads/SKILL.md +10 -9
- package/dist/template/.opencode/skill/beads/references/MULTI_AGENT.md +10 -10
- package/dist/template/.opencode/skill/ci-cd-and-automation/SKILL.md +202 -0
- package/dist/template/.opencode/skill/code-search-patterns/SKILL.md +253 -0
- package/dist/template/.opencode/skill/code-simplification/SKILL.md +211 -0
- package/dist/template/.opencode/skill/condition-based-waiting/SKILL.md +12 -0
- package/dist/template/.opencode/skill/defense-in-depth/SKILL.md +16 -6
- package/dist/template/.opencode/skill/deprecation-and-migration/SKILL.md +189 -0
- package/dist/template/.opencode/skill/development-lifecycle/SKILL.md +12 -48
- package/dist/template/.opencode/skill/documentation-and-adrs/SKILL.md +220 -0
- package/dist/template/.opencode/skill/incremental-implementation/SKILL.md +191 -0
- package/dist/template/.opencode/skill/performance-optimization/SKILL.md +236 -0
- package/dist/template/.opencode/skill/receiving-code-review/SKILL.md +11 -0
- package/dist/template/.opencode/skill/security-and-hardening/SKILL.md +296 -0
- package/dist/template/.opencode/skill/structured-edit/SKILL.md +10 -0
- package/dist/template/.opencode/skill/swarm-coordination/SKILL.md +66 -1
- package/package.json +1 -1
- package/dist/template/.opencode/skill/beads-bridge/SKILL.md +0 -321
- package/dist/template/.opencode/skill/code-navigation/SKILL.md +0 -130
- package/dist/template/.opencode/skill/mqdh/SKILL.md +0 -171
- package/dist/template/.opencode/skill/obsidian/SKILL.md +0 -192
- package/dist/template/.opencode/skill/obsidian/mcp.json +0 -22
- package/dist/template/.opencode/skill/pencil/SKILL.md +0 -72
- package/dist/template/.opencode/skill/ralph/SKILL.md +0 -296
- package/dist/template/.opencode/skill/tilth-cli/SKILL.md +0 -207
- package/dist/template/.opencode/skill/tool-priority/SKILL.md +0 -299
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: security-and-hardening
|
|
3
|
+
description: Use when auditing for security vulnerabilities, implementing auth/authz, handling secrets, or hardening against OWASP Top 10 — covers input validation, authentication, dependency auditing, and secure defaults
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
tags: [security, code-quality]
|
|
6
|
+
dependencies: []
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Security & Hardening
|
|
10
|
+
|
|
11
|
+
> **Replaces** "we'll add security later" with security-by-default patterns applied from the start
|
|
12
|
+
|
|
13
|
+
## When to Use
|
|
14
|
+
|
|
15
|
+
- Implementing authentication or authorization
|
|
16
|
+
- Handling user input that touches databases, file systems, or external services
|
|
17
|
+
- Reviewing code for security vulnerabilities
|
|
18
|
+
- Running dependency audits or responding to CVE alerts
|
|
19
|
+
- Deploying to production for the first time
|
|
20
|
+
|
|
21
|
+
## When NOT to Use
|
|
22
|
+
|
|
23
|
+
- Local-only developer tools with no network exposure
|
|
24
|
+
- Throwaway prototypes that will never see user data
|
|
25
|
+
- Performance optimization (that's a different skill)
|
|
26
|
+
|
|
27
|
+
## Overview
|
|
28
|
+
|
|
29
|
+
Security is a constraint, not a feature. It should be present by default and requires explicit justification to relax.
|
|
30
|
+
|
|
31
|
+
**Core principle:** Validate all input. Authenticate all access. Encrypt all secrets. Audit all dependencies. Trust nothing from outside your process boundary.
|
|
32
|
+
|
|
33
|
+
## Security Boundaries
|
|
34
|
+
|
|
35
|
+
### Always
|
|
36
|
+
|
|
37
|
+
- Validate and sanitize all user input at the boundary
|
|
38
|
+
- Use parameterized queries (never string interpolation for SQL)
|
|
39
|
+
- Hash passwords with bcrypt/scrypt/argon2 (never MD5/SHA for passwords)
|
|
40
|
+
- Use HTTPS for all external communication
|
|
41
|
+
- Store secrets in environment variables, never in code
|
|
42
|
+
- Set secure defaults (CORS restrictive, CSP strict, cookies httpOnly+secure)
|
|
43
|
+
|
|
44
|
+
### Ask First
|
|
45
|
+
|
|
46
|
+
- Changing authentication mechanism or session handling
|
|
47
|
+
- Adding new API endpoints that accept user data
|
|
48
|
+
- Modifying CORS policy or CSP headers
|
|
49
|
+
- Adding new third-party dependencies with network access
|
|
50
|
+
- Storing new types of PII or sensitive data
|
|
51
|
+
|
|
52
|
+
### Never
|
|
53
|
+
|
|
54
|
+
- Commit secrets, API keys, or credentials to git
|
|
55
|
+
- Disable CSRF protection
|
|
56
|
+
- Use `eval()` or `Function()` with user input
|
|
57
|
+
- Trust client-side validation as the only validation
|
|
58
|
+
- Log sensitive data (passwords, tokens, PII)
|
|
59
|
+
|
|
60
|
+
## OWASP Top 10 Patterns
|
|
61
|
+
|
|
62
|
+
### 1. Injection (SQL, NoSQL, Command)
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
// ❌ SQL Injection
|
|
66
|
+
const user = await db.query(`SELECT * FROM users WHERE id = '${userId}'`);
|
|
67
|
+
|
|
68
|
+
// ✅ Parameterized query
|
|
69
|
+
const user = await db.query("SELECT * FROM users WHERE id = $1", [userId]);
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
// ❌ Command injection
|
|
74
|
+
exec(`convert ${filename} output.png`);
|
|
75
|
+
|
|
76
|
+
// ✅ Safe argument passing
|
|
77
|
+
execFile("convert", [filename, "output.png"]);
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### 2. Broken Authentication
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
// ✅ Password hashing
|
|
84
|
+
import bcrypt from "bcrypt";
|
|
85
|
+
const hash = await bcrypt.hash(password, 12); // cost factor 12
|
|
86
|
+
const valid = await bcrypt.compare(input, hash);
|
|
87
|
+
|
|
88
|
+
// ✅ Session management
|
|
89
|
+
const session = {
|
|
90
|
+
httpOnly: true, // No JS access
|
|
91
|
+
secure: true, // HTTPS only
|
|
92
|
+
sameSite: "lax", // CSRF protection
|
|
93
|
+
maxAge: 3600, // 1 hour expiry
|
|
94
|
+
};
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### 3. Sensitive Data Exposure
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
// ❌ Logging sensitive data
|
|
101
|
+
console.log("User login:", { email, password });
|
|
102
|
+
|
|
103
|
+
// ✅ Redact sensitive fields
|
|
104
|
+
console.log("User login:", { email, password: "[REDACTED]" });
|
|
105
|
+
|
|
106
|
+
// ✅ API response excludes internal fields
|
|
107
|
+
function toPublicUser(user: DbUser): PublicUser {
|
|
108
|
+
const { passwordHash, internalId, ...publicFields } = user;
|
|
109
|
+
return publicFields;
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### 4. Broken Access Control
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
// ❌ No authorization check
|
|
117
|
+
app.get("/api/users/:id", async (req, res) => {
|
|
118
|
+
const user = await getUser(req.params.id);
|
|
119
|
+
res.json(user); // Any authenticated user can access any profile
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
// ✅ Authorization check
|
|
123
|
+
app.get("/api/users/:id", async (req, res) => {
|
|
124
|
+
const user = await getUser(req.params.id);
|
|
125
|
+
if (user.id !== req.auth.userId && !req.auth.isAdmin) {
|
|
126
|
+
return res.status(403).json({ error: "Forbidden" });
|
|
127
|
+
}
|
|
128
|
+
res.json(user);
|
|
129
|
+
});
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### 5. Security Misconfiguration
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
// ✅ Secure headers (use helmet for Express)
|
|
136
|
+
import helmet from "helmet";
|
|
137
|
+
app.use(helmet());
|
|
138
|
+
|
|
139
|
+
// ✅ CORS — restrictive by default
|
|
140
|
+
app.use(
|
|
141
|
+
cors({
|
|
142
|
+
origin: ["https://myapp.com"], // Not '*'
|
|
143
|
+
methods: ["GET", "POST"],
|
|
144
|
+
credentials: true,
|
|
145
|
+
}),
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
// ✅ CSP
|
|
149
|
+
app.use(
|
|
150
|
+
helmet.contentSecurityPolicy({
|
|
151
|
+
directives: {
|
|
152
|
+
defaultSrc: ["'self'"],
|
|
153
|
+
scriptSrc: ["'self'"], // No 'unsafe-inline'
|
|
154
|
+
styleSrc: ["'self'", "'unsafe-inline'"], // Only if needed
|
|
155
|
+
},
|
|
156
|
+
}),
|
|
157
|
+
);
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Input Validation Patterns
|
|
161
|
+
|
|
162
|
+
```typescript
|
|
163
|
+
import { z } from "zod";
|
|
164
|
+
|
|
165
|
+
// ✅ Validate at the boundary
|
|
166
|
+
const createUserSchema = z.object({
|
|
167
|
+
name: z.string().min(1).max(100).trim(),
|
|
168
|
+
email: z.string().email().max(254),
|
|
169
|
+
age: z.number().int().min(0).max(150).optional(),
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
// ✅ Reject unknown fields
|
|
173
|
+
const input = createUserSchema.strict().parse(req.body);
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
| Input Type | Validation |
|
|
177
|
+
| ----------- | -------------------------------------------- |
|
|
178
|
+
| String | Min/max length, regex pattern, trim |
|
|
179
|
+
| Number | Min/max range, integer check |
|
|
180
|
+
| Email | Format validation, max 254 chars |
|
|
181
|
+
| URL | Protocol whitelist (https only) |
|
|
182
|
+
| File upload | Type whitelist, max size, content validation |
|
|
183
|
+
| Array | Max length, item validation |
|
|
184
|
+
|
|
185
|
+
## Dependency Audit
|
|
186
|
+
|
|
187
|
+
### npm Audit Triage
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
# Run audit
|
|
191
|
+
npm audit
|
|
192
|
+
|
|
193
|
+
# Decision tree per vulnerability:
|
|
194
|
+
# 1. Is it in production dependencies? (devDeps are lower priority)
|
|
195
|
+
# 2. Is the vulnerability reachable in our usage?
|
|
196
|
+
# 3. Is a patch available? → Update
|
|
197
|
+
# 4. No patch? → Find alternative or add compensating control
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
| Severity | Action | Timeline |
|
|
201
|
+
| -------- | --------------------- | ---------------------- |
|
|
202
|
+
| Critical | Fix immediately | Same day |
|
|
203
|
+
| High | Fix in current sprint | Within 1 week |
|
|
204
|
+
| Medium | Plan fix | Within 1 month |
|
|
205
|
+
| Low | Track and monitor | Next convenient update |
|
|
206
|
+
|
|
207
|
+
### Supply Chain Security
|
|
208
|
+
|
|
209
|
+
- [ ] Use lockfile (`package-lock.json` / `pnpm-lock.yaml`) — commit it
|
|
210
|
+
- [ ] Pin major versions in production dependencies
|
|
211
|
+
- [ ] Review new dependencies before adding (check maintainers, download count, last update)
|
|
212
|
+
- [ ] Enable Dependabot or Renovate for automated updates
|
|
213
|
+
- [ ] Use `npm audit` or `pnpm audit` in CI pipeline
|
|
214
|
+
|
|
215
|
+
## Secrets Management
|
|
216
|
+
|
|
217
|
+
| Rule | Implementation |
|
|
218
|
+
| ------------------------- | ------------------------------------------------ |
|
|
219
|
+
| Never in code | Use `.env` files (gitignored) or secret managers |
|
|
220
|
+
| Never in logs | Redact before logging |
|
|
221
|
+
| Never in URLs | Use headers or body for tokens |
|
|
222
|
+
| Rotate on exposure | Immediate rotation + audit trail |
|
|
223
|
+
| Different per environment | Staging keys ≠ production keys |
|
|
224
|
+
| Least privilege | Each secret grants minimum required access |
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
# ✅ .gitignore
|
|
228
|
+
.env
|
|
229
|
+
.env.local
|
|
230
|
+
.env.*.local
|
|
231
|
+
*.key
|
|
232
|
+
*.pem
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
## Rate Limiting
|
|
236
|
+
|
|
237
|
+
```typescript
|
|
238
|
+
// ✅ Basic rate limiting
|
|
239
|
+
import rateLimit from "express-rate-limit";
|
|
240
|
+
|
|
241
|
+
const limiter = rateLimit({
|
|
242
|
+
windowMs: 15 * 60 * 1000, // 15 minutes
|
|
243
|
+
max: 100, // 100 requests per window
|
|
244
|
+
standardHeaders: true,
|
|
245
|
+
legacyHeaders: false,
|
|
246
|
+
message: { error: "Too many requests, try again later" },
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
app.use("/api/", limiter);
|
|
250
|
+
|
|
251
|
+
// ✅ Stricter limit for auth endpoints
|
|
252
|
+
const authLimiter = rateLimit({
|
|
253
|
+
windowMs: 15 * 60 * 1000,
|
|
254
|
+
max: 5, // 5 login attempts per 15 minutes
|
|
255
|
+
});
|
|
256
|
+
app.use("/api/auth/", authLimiter);
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
## Common Rationalizations
|
|
260
|
+
|
|
261
|
+
| Excuse | Rebuttal |
|
|
262
|
+
| ---------------------------------- | ----------------------------------------------------------------------------- |
|
|
263
|
+
| "It's an internal app" | Internal apps get compromised too. Validate all input regardless. |
|
|
264
|
+
| "We'll add security before launch" | Security retrofit is 10x harder than building it in. Start now. |
|
|
265
|
+
| "Nobody will find this endpoint" | Security through obscurity isn't security. Assume everything is discoverable. |
|
|
266
|
+
| "The framework handles it" | Frameworks have defaults, not guarantees. Verify your specific configuration. |
|
|
267
|
+
| "This is just a prototype" | Prototypes become production. Build secure habits from day one. |
|
|
268
|
+
| "The audit has too many warnings" | Triage by severity. Critical/High first, Low can wait. |
|
|
269
|
+
|
|
270
|
+
## Red Flags — STOP
|
|
271
|
+
|
|
272
|
+
- String concatenation in SQL queries
|
|
273
|
+
- Passwords stored in plaintext or MD5/SHA
|
|
274
|
+
- API keys or secrets in source code
|
|
275
|
+
- CORS set to `*` in production
|
|
276
|
+
- No rate limiting on authentication endpoints
|
|
277
|
+
- User input passed directly to `exec()`, `eval()`, or file system operations
|
|
278
|
+
- Dependencies with known critical CVEs
|
|
279
|
+
- No input validation at API boundaries
|
|
280
|
+
|
|
281
|
+
## Verification
|
|
282
|
+
|
|
283
|
+
- [ ] All user input validated with schemas at API boundaries
|
|
284
|
+
- [ ] SQL queries use parameterized statements
|
|
285
|
+
- [ ] Passwords hashed with bcrypt/scrypt/argon2 (cost ≥ 12)
|
|
286
|
+
- [ ] No secrets in source code or logs
|
|
287
|
+
- [ ] CORS, CSP, and security headers configured
|
|
288
|
+
- [ ] `npm audit` shows no critical/high vulnerabilities
|
|
289
|
+
- [ ] Rate limiting on authentication and sensitive endpoints
|
|
290
|
+
- [ ] Authorization checks on all protected resources
|
|
291
|
+
|
|
292
|
+
## See Also
|
|
293
|
+
|
|
294
|
+
- **defense-in-depth** — Validation at every layer, not just the boundary
|
|
295
|
+
- **api-and-interface-design** — Error responses that don't leak internals
|
|
296
|
+
- **ci-cd-and-automation** — Running security checks in CI pipeline
|
|
@@ -18,6 +18,16 @@ dependencies: []
|
|
|
18
18
|
- One-line edits where a direct edit is safe and unambiguous
|
|
19
19
|
- Large refactors better served by full rewrites or file splits
|
|
20
20
|
|
|
21
|
+
## Common Rationalizations
|
|
22
|
+
|
|
23
|
+
| Rationalization | Rebuttal |
|
|
24
|
+
| ------------------------------------------------- | ------------------------------------------------------------------------------------------- |
|
|
25
|
+
| "I remember what the file looks like" | You remember what it looked like 5 edits ago. Read it fresh |
|
|
26
|
+
| "The edit is simple, I don't need to verify" | Simple edits fail most often — whitespace, encoding, duplicate matches |
|
|
27
|
+
| "LSP lookup is an extra step I can skip" | LSP takes 1 call. Retrying a failed edit takes 3-5 calls |
|
|
28
|
+
| "I'll just use a larger context block to be safe" | Larger blocks = more chances for invisible character mismatches. Use minimal unique context |
|
|
29
|
+
| "The file hasn't changed since I last read it" | Other edits, formatters, and git operations can modify files between your reads |
|
|
30
|
+
|
|
21
31
|
## Overview
|
|
22
32
|
|
|
23
33
|
The `str_replace` edit tool is the #1 source of failures in LLM coding. Models reproduce content with subtle differences (whitespace, encoding, line endings) causing "string not found" errors.
|
|
@@ -8,7 +8,7 @@ description: >
|
|
|
8
8
|
version: "2.1.0"
|
|
9
9
|
license: MIT
|
|
10
10
|
tags: [agent-coordination, workflow]
|
|
11
|
-
dependencies: [beads
|
|
11
|
+
dependencies: [beads]
|
|
12
12
|
---
|
|
13
13
|
|
|
14
14
|
# Swarm Coordination - Kimi K2.5 PARL Multi-Agent Execution
|
|
@@ -137,6 +137,71 @@ SHUTDOWN:
|
|
|
137
137
|
- `monitor`: Progress tracking + visualization (actions: progress_update, render_block, status, clear)
|
|
138
138
|
- `sync`: Beads ↔ OpenCode todos (actions: push, pull, create_shared, get_shared, update_shared, list_shared)
|
|
139
139
|
|
|
140
|
+
## Beads Integration
|
|
141
|
+
|
|
142
|
+
### Session Start: Load Beads into Todos
|
|
143
|
+
|
|
144
|
+
Make Beads tasks visible to subagents:
|
|
145
|
+
|
|
146
|
+
```typescript
|
|
147
|
+
// Push Beads to OpenCode todos
|
|
148
|
+
const result = await swarm({
|
|
149
|
+
operation: "sync",
|
|
150
|
+
action: "push",
|
|
151
|
+
filter: "open", // or "in_progress", "all"
|
|
152
|
+
});
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Session End: Sync Back to Beads
|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
// Pull completed todos back to Beads
|
|
159
|
+
await swarm({ operation: "sync", action: "pull" });
|
|
160
|
+
|
|
161
|
+
// Clear swarm state
|
|
162
|
+
await swarm({
|
|
163
|
+
operation: "monitor",
|
|
164
|
+
action: "clear",
|
|
165
|
+
team_name: "api-refactor-swarm",
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
// Sync and commit
|
|
169
|
+
await bash("br sync --flush-only");
|
|
170
|
+
await bash("git add .beads/ && git commit -m 'close swarm'");
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Cross-Session Handoff
|
|
174
|
+
|
|
175
|
+
For work spanning multiple sessions, use shared task lists:
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
// Create shared list
|
|
179
|
+
const list = await swarm({
|
|
180
|
+
operation: "sync",
|
|
181
|
+
action: "create_shared",
|
|
182
|
+
name: "api-refactor-swarm",
|
|
183
|
+
tasks: JSON.stringify([
|
|
184
|
+
{ id: "task-1", content: "Refactor auth", status: "pending", priority: "high" },
|
|
185
|
+
]),
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
// Resume in new session
|
|
189
|
+
const shared = await swarm({
|
|
190
|
+
operation: "sync",
|
|
191
|
+
action: "get_shared",
|
|
192
|
+
list_id: "api-refactor-swarm",
|
|
193
|
+
});
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Data Locations
|
|
197
|
+
|
|
198
|
+
| Data Type | Location | Persistence |
|
|
199
|
+
| ----------------- | ----------------------------------------------- | ------------- |
|
|
200
|
+
| Beads tasks | `.beads/issues/*.md` | Git-backed |
|
|
201
|
+
| Swarm progress | `.beads/swarm-progress.jsonl` | Session |
|
|
202
|
+
| Shared task lists | `~/.local/share/opencode/storage/shared-tasks/` | Cross-session |
|
|
203
|
+
| OpenCode todos | `~/.local/share/opencode/storage/todo/` | Session |
|
|
204
|
+
|
|
140
205
|
## Rules
|
|
141
206
|
|
|
142
207
|
1. **Leader spawns, workers execute** - Clear role separation
|