@patricio0312rev/skillset 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.
Files changed (115) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/LICENSE +21 -0
  3. package/README.md +176 -0
  4. package/bin/cli.js +37 -0
  5. package/package.json +55 -0
  6. package/src/commands/init.js +301 -0
  7. package/src/index.js +168 -0
  8. package/src/lib/config.js +200 -0
  9. package/src/lib/generator.js +166 -0
  10. package/src/utils/display.js +95 -0
  11. package/src/utils/readme.js +196 -0
  12. package/src/utils/tool-specific.js +233 -0
  13. package/templates/ai-engineering/agent-orchestration-planner/ SKILL.md +266 -0
  14. package/templates/ai-engineering/cost-latency-optimizer/ SKILL.md +270 -0
  15. package/templates/ai-engineering/doc-to-vector-dataset-generator/ SKILL.md +239 -0
  16. package/templates/ai-engineering/evaluation-harness/ SKILL.md +219 -0
  17. package/templates/ai-engineering/guardrails-safety-filter-builder/ SKILL.md +226 -0
  18. package/templates/ai-engineering/llm-debugger/ SKILL.md +283 -0
  19. package/templates/ai-engineering/prompt-regression-tester/ SKILL.md +216 -0
  20. package/templates/ai-engineering/prompt-template-builder/ SKILL.md +393 -0
  21. package/templates/ai-engineering/rag-pipeline-builder/ SKILL.md +244 -0
  22. package/templates/ai-engineering/tool-function-schema-designer/ SKILL.md +219 -0
  23. package/templates/architecture/adr-writer/ SKILL.md +250 -0
  24. package/templates/architecture/api-versioning-deprecation-planner/ SKILL.md +331 -0
  25. package/templates/architecture/domain-model-boundaries-mapper/ SKILL.md +300 -0
  26. package/templates/architecture/migration-planner/ SKILL.md +376 -0
  27. package/templates/architecture/performance-budget-setter/ SKILL.md +318 -0
  28. package/templates/architecture/reliability-strategy-builder/ SKILL.md +286 -0
  29. package/templates/architecture/rfc-generator/ SKILL.md +362 -0
  30. package/templates/architecture/scalability-playbook/ SKILL.md +279 -0
  31. package/templates/architecture/system-design-generator/ SKILL.md +339 -0
  32. package/templates/architecture/tech-debt-prioritizer/ SKILL.md +329 -0
  33. package/templates/backend/api-contract-normalizer/ SKILL.md +487 -0
  34. package/templates/backend/api-endpoint-generator/ SKILL.md +415 -0
  35. package/templates/backend/auth-module-builder/ SKILL.md +99 -0
  36. package/templates/backend/background-jobs-designer/ SKILL.md +166 -0
  37. package/templates/backend/caching-strategist/ SKILL.md +190 -0
  38. package/templates/backend/error-handling-standardizer/ SKILL.md +174 -0
  39. package/templates/backend/rate-limiting-abuse-protection/ SKILL.md +147 -0
  40. package/templates/backend/rbac-permissions-builder/ SKILL.md +158 -0
  41. package/templates/backend/service-layer-extractor/ SKILL.md +269 -0
  42. package/templates/backend/webhook-receiver-hardener/ SKILL.md +211 -0
  43. package/templates/ci-cd/artifact-sbom-publisher/ SKILL.md +236 -0
  44. package/templates/ci-cd/caching-strategy-optimizer/ SKILL.md +195 -0
  45. package/templates/ci-cd/deployment-checklist-generator/ SKILL.md +381 -0
  46. package/templates/ci-cd/github-actions-pipeline-creator/ SKILL.md +348 -0
  47. package/templates/ci-cd/monorepo-ci-optimizer/ SKILL.md +298 -0
  48. package/templates/ci-cd/preview-environments-builder/ SKILL.md +187 -0
  49. package/templates/ci-cd/quality-gates-enforcer/ SKILL.md +342 -0
  50. package/templates/ci-cd/release-automation-builder/ SKILL.md +281 -0
  51. package/templates/ci-cd/rollback-workflow-builder/ SKILL.md +372 -0
  52. package/templates/ci-cd/secrets-env-manager/ SKILL.md +242 -0
  53. package/templates/db-management/backup-restore-runbook-generator/ SKILL.md +505 -0
  54. package/templates/db-management/data-integrity-auditor/ SKILL.md +505 -0
  55. package/templates/db-management/data-retention-archiving-planner/ SKILL.md +430 -0
  56. package/templates/db-management/data-seeding-fixtures-builder/ SKILL.md +375 -0
  57. package/templates/db-management/db-performance-watchlist/ SKILL.md +425 -0
  58. package/templates/db-management/etl-sync-job-builder/ SKILL.md +457 -0
  59. package/templates/db-management/multi-tenant-safety-checker/ SKILL.md +398 -0
  60. package/templates/db-management/prisma-migration-assistant/ SKILL.md +379 -0
  61. package/templates/db-management/schema-consistency-checker/ SKILL.md +440 -0
  62. package/templates/db-management/sql-query-optimizer/ SKILL.md +324 -0
  63. package/templates/foundation/changelog-writer/ SKILL.md +431 -0
  64. package/templates/foundation/code-formatter-installer/ SKILL.md +320 -0
  65. package/templates/foundation/codebase-summarizer/ SKILL.md +360 -0
  66. package/templates/foundation/dependency-doctor/ SKILL.md +163 -0
  67. package/templates/foundation/dev-environment-bootstrapper/ SKILL.md +259 -0
  68. package/templates/foundation/dev-onboarding-builder/ SKILL.md +556 -0
  69. package/templates/foundation/docs-starter-kit/ SKILL.md +574 -0
  70. package/templates/foundation/explaining-code/SKILL.md +13 -0
  71. package/templates/foundation/git-hygiene-enforcer/ SKILL.md +455 -0
  72. package/templates/foundation/project-scaffolder/ SKILL.md +65 -0
  73. package/templates/foundation/project-scaffolder/references/templates.md +126 -0
  74. package/templates/foundation/repo-structure-linter/ SKILL.md +0 -0
  75. package/templates/foundation/repo-structure-linter/references/conventions.md +98 -0
  76. package/templates/frontend/animation-micro-interaction-pack/ SKILL.md +41 -0
  77. package/templates/frontend/component-scaffold-generator/ SKILL.md +562 -0
  78. package/templates/frontend/design-to-component-translator/ SKILL.md +547 -0
  79. package/templates/frontend/form-wizard-builder/ SKILL.md +553 -0
  80. package/templates/frontend/frontend-refactor-planner/ SKILL.md +37 -0
  81. package/templates/frontend/i18n-frontend-implementer/ SKILL.md +44 -0
  82. package/templates/frontend/modal-drawer-system/ SKILL.md +377 -0
  83. package/templates/frontend/page-layout-builder/ SKILL.md +630 -0
  84. package/templates/frontend/state-ux-flow-builder/ SKILL.md +23 -0
  85. package/templates/frontend/table-builder/ SKILL.md +350 -0
  86. package/templates/performance/alerting-dashboard-builder/ SKILL.md +162 -0
  87. package/templates/performance/backend-latency-profiler-helper/ SKILL.md +108 -0
  88. package/templates/performance/caching-cdn-strategy-planner/ SKILL.md +150 -0
  89. package/templates/performance/capacity-planning-helper/ SKILL.md +242 -0
  90. package/templates/performance/core-web-vitals-tuner/ SKILL.md +126 -0
  91. package/templates/performance/incident-runbook-generator/ SKILL.md +162 -0
  92. package/templates/performance/load-test-scenario-builder/ SKILL.md +256 -0
  93. package/templates/performance/observability-setup/ SKILL.md +232 -0
  94. package/templates/performance/postmortem-writer/ SKILL.md +203 -0
  95. package/templates/performance/structured-logging-standardizer/ SKILL.md +122 -0
  96. package/templates/security/auth-security-reviewer/ SKILL.md +428 -0
  97. package/templates/security/dependency-vulnerability-triage/ SKILL.md +495 -0
  98. package/templates/security/input-validation-sanitization-auditor/ SKILL.md +76 -0
  99. package/templates/security/pii-redaction-logging-policy-builder/ SKILL.md +65 -0
  100. package/templates/security/rbac-policy-tester/ SKILL.md +80 -0
  101. package/templates/security/secrets-scanner/ SKILL.md +462 -0
  102. package/templates/security/secure-headers-csp-builder/ SKILL.md +404 -0
  103. package/templates/security/security-incident-playbook-generator/ SKILL.md +76 -0
  104. package/templates/security/security-pr-checklist-skill/ SKILL.md +62 -0
  105. package/templates/security/threat-model-generator/ SKILL.md +394 -0
  106. package/templates/testing/contract-testing-builder/ SKILL.md +492 -0
  107. package/templates/testing/coverage-strategist/ SKILL.md +436 -0
  108. package/templates/testing/e2e-test-builder/ SKILL.md +382 -0
  109. package/templates/testing/flaky-test-detective/ SKILL.md +416 -0
  110. package/templates/testing/integration-test-builder/ SKILL.md +525 -0
  111. package/templates/testing/mocking-assistant/ SKILL.md +383 -0
  112. package/templates/testing/snapshot-test-refactorer/ SKILL.md +375 -0
  113. package/templates/testing/test-data-factory-builder/ SKILL.md +449 -0
  114. package/templates/testing/test-reporting-triage-skill/ SKILL.md +469 -0
  115. package/templates/testing/unit-test-generator/ SKILL.md +548 -0
@@ -0,0 +1,269 @@
1
+ ---
2
+ name: service-layer-extractor
3
+ description: Refactors route handlers into service layer with clean boundaries, dependency injection, testability, and separation of concerns. Provides service interfaces, folder structure, testing strategy, and migration plan. Use when refactoring "fat controllers", "business logic", "service layer", or "architecture cleanup".
4
+ ---
5
+
6
+ # Service Layer Extractor
7
+
8
+ Extract business logic from controllers into a testable service layer.
9
+
10
+ ## Architecture Layers
11
+
12
+ ```
13
+ routes/ → Define endpoints, parse requests
14
+ controllers/ → Validate input, call services, format responses
15
+ services/ → Business logic, orchestration
16
+ repositories/ → Database queries
17
+ models/ → Data structures
18
+ ```
19
+
20
+ ## Before: Fat Controller
21
+
22
+ ```typescript
23
+ // ❌ Business logic mixed with HTTP concerns
24
+ router.post("/users", async (req, res) => {
25
+ try {
26
+ // Validation
27
+ if (!req.body.email) {
28
+ return res.status(400).json({ error: "Email required" });
29
+ }
30
+
31
+ // Check duplicate
32
+ const existing = await db.query("SELECT * FROM users WHERE email = $1", [
33
+ req.body.email,
34
+ ]);
35
+ if (existing.rows.length > 0) {
36
+ return res.status(409).json({ error: "Email already exists" });
37
+ }
38
+
39
+ // Hash password
40
+ const hashedPassword = await bcrypt.hash(req.body.password, 10);
41
+
42
+ // Create user
43
+ const result = await db.query(
44
+ "INSERT INTO users (email, password, name) VALUES ($1, $2, $3) RETURNING *",
45
+ [req.body.email, hashedPassword, req.body.name]
46
+ );
47
+
48
+ // Send welcome email
49
+ await sendEmail(req.body.email, "Welcome!", "Thanks for joining");
50
+
51
+ res.status(201).json(result.rows[0]);
52
+ } catch (err) {
53
+ res.status(500).json({ error: err.message });
54
+ }
55
+ });
56
+ ```
57
+
58
+ ## After: Service Layer
59
+
60
+ ```typescript
61
+ // ✅ Separated concerns
62
+
63
+ // services/user.service.ts
64
+ export class UserService {
65
+ constructor(
66
+ private userRepository: UserRepository,
67
+ private emailService: EmailService
68
+ ) {}
69
+
70
+ async createUser(dto: CreateUserDto): Promise<User> {
71
+ // Business logic only
72
+ const existing = await this.userRepository.findByEmail(dto.email);
73
+ if (existing) {
74
+ throw new ConflictError("Email already exists");
75
+ }
76
+
77
+ const hashedPassword = await bcrypt.hash(dto.password, 10);
78
+
79
+ const user = await this.userRepository.create({
80
+ ...dto,
81
+ password: hashedPassword,
82
+ });
83
+
84
+ await this.emailService.sendWelcome(user.email);
85
+
86
+ return user;
87
+ }
88
+ }
89
+
90
+ // controllers/user.controller.ts
91
+ export class UserController {
92
+ constructor(private userService: UserService) {}
93
+
94
+ create = asyncHandler(async (req, res) => {
95
+ const user = await this.userService.createUser(req.body);
96
+ res.status(201).json({ success: true, data: user });
97
+ });
98
+ }
99
+
100
+ // repositories/user.repository.ts
101
+ export class UserRepository {
102
+ async create(data: CreateUserData): Promise<User> {
103
+ const result = await db.query(
104
+ "INSERT INTO users (email, password, name) VALUES ($1, $2, $3) RETURNING *",
105
+ [data.email, data.password, data.name]
106
+ );
107
+ return result.rows[0];
108
+ }
109
+
110
+ async findByEmail(email: string): Promise<User | null> {
111
+ const result = await db.query("SELECT * FROM users WHERE email = $1", [
112
+ email,
113
+ ]);
114
+ return result.rows[0] || null;
115
+ }
116
+ }
117
+ ```
118
+
119
+ ## Dependency Injection
120
+
121
+ ```typescript
122
+ // container.ts (using tsyringe or manual)
123
+ import { UserService } from "./services/user.service";
124
+ import { UserRepository } from "./repositories/user.repository";
125
+ import { EmailService } from "./services/email.service";
126
+
127
+ export class Container {
128
+ private static instances = new Map();
129
+
130
+ static get<T>(constructor: new (...args: any[]) => T): T {
131
+ if (!this.instances.has(constructor)) {
132
+ // Create dependencies
133
+ const deps = this.resolveDependencies(constructor);
134
+ this.instances.set(constructor, new constructor(...deps));
135
+ }
136
+ return this.instances.get(constructor);
137
+ }
138
+
139
+ private static resolveDependencies(constructor: any): any[] {
140
+ // Resolve constructor dependencies
141
+ return [];
142
+ }
143
+ }
144
+
145
+ // Usage
146
+ const userService = Container.get(UserService);
147
+ ```
148
+
149
+ ## Testing Services
150
+
151
+ ```typescript
152
+ // user.service.test.ts
153
+ describe("UserService", () => {
154
+ let service: UserService;
155
+ let mockRepository: jest.Mocked<UserRepository>;
156
+ let mockEmailService: jest.Mocked<EmailService>;
157
+
158
+ beforeEach(() => {
159
+ mockRepository = {
160
+ create: jest.fn(),
161
+ findByEmail: jest.fn(),
162
+ } as any;
163
+
164
+ mockEmailService = {
165
+ sendWelcome: jest.fn(),
166
+ } as any;
167
+
168
+ service = new UserService(mockRepository, mockEmailService);
169
+ });
170
+
171
+ it("creates user successfully", async () => {
172
+ mockRepository.findByEmail.mockResolvedValue(null);
173
+ mockRepository.create.mockResolvedValue({
174
+ id: "1",
175
+ email: "test@example.com",
176
+ });
177
+
178
+ const user = await service.createUser({
179
+ email: "test@example.com",
180
+ password: "password123",
181
+ name: "Test User",
182
+ });
183
+
184
+ expect(user.id).toBe("1");
185
+ expect(mockEmailService.sendWelcome).toHaveBeenCalled();
186
+ });
187
+
188
+ it("throws error if email exists", async () => {
189
+ mockRepository.findByEmail.mockResolvedValue({ id: "1" } as User);
190
+
191
+ await expect(
192
+ service.createUser({
193
+ email: "existing@example.com",
194
+ password: "pass",
195
+ name: "Test",
196
+ })
197
+ ).rejects.toThrow(ConflictError);
198
+ });
199
+ });
200
+ ```
201
+
202
+ ## Folder Structure
203
+
204
+ ```
205
+ src/
206
+ ├── routes/
207
+ │ └── users.routes.ts
208
+ ├── controllers/
209
+ │ └── user.controller.ts
210
+ ├── services/
211
+ │ ├── user.service.ts
212
+ │ ├── email.service.ts
213
+ │ └── payment.service.ts
214
+ ├── repositories/
215
+ │ └── user.repository.ts
216
+ ├── models/
217
+ │ └── user.model.ts
218
+ ├── types/
219
+ │ └── user.types.ts
220
+ └── middleware/
221
+ └── validate.ts
222
+ ```
223
+
224
+ ## Migration Strategy
225
+
226
+ ```markdown
227
+ ## Phase 1: Create Service Layer (Week 1-2)
228
+
229
+ - [ ] Create service classes
230
+ - [ ] Move business logic to services
231
+ - [ ] Keep controllers thin
232
+ - [ ] No breaking changes
233
+
234
+ ## Phase 2: Add Tests (Week 3-4)
235
+
236
+ - [ ] Write service unit tests
237
+ - [ ] Mock dependencies
238
+ - [ ] Achieve 80%+ coverage
239
+
240
+ ## Phase 3: Extract Repositories (Week 5-6)
241
+
242
+ - [ ] Create repository layer
243
+ - [ ] Move DB queries from services
244
+ - [ ] Services depend on repositories
245
+
246
+ ## Phase 4: Dependency Injection (Week 7-8)
247
+
248
+ - [ ] Set up DI container
249
+ - [ ] Remove manual instantiation
250
+ - [ ] Wire up dependencies
251
+ ```
252
+
253
+ ## Benefits
254
+
255
+ - **Testability**: Services testable without HTTP
256
+ - **Reusability**: Logic reused across endpoints
257
+ - **Separation**: Clear boundaries between layers
258
+ - **Maintainability**: Easier to locate and modify logic
259
+
260
+ ## Output Checklist
261
+
262
+ - [ ] Service classes created
263
+ - [ ] Business logic extracted from controllers
264
+ - [ ] Repository layer for data access
265
+ - [ ] Dependency injection setup
266
+ - [ ] Unit tests for services
267
+ - [ ] Folder structure reorganized
268
+ - [ ] Migration plan documented
269
+ - [ ] Team trained on new patterns
@@ -0,0 +1,211 @@
1
+ ---
2
+ name: webhook-receiver-hardener
3
+ description: Secures webhook receivers with signature verification, retry handling, deduplication, idempotency keys, and error responses. Provides verification code, dedupe storage strategy, runbook for incidents. Use when implementing "webhooks", "webhook security", "event receivers", or "third-party integrations".
4
+ ---
5
+
6
+ # Webhook Receiver Hardener
7
+
8
+ Build secure, reliable webhook endpoints that handle failures gracefully.
9
+
10
+ ## Core Security
11
+
12
+ **Signature Verification**: HMAC validation before processing
13
+ **Deduplication**: Track processed webhook IDs
14
+ **Idempotency**: Safe to process same webhook multiple times
15
+ **Retries**: Handle provider retry attempts
16
+ **Rate Limiting**: Prevent abuse
17
+
18
+ ## Signature Verification
19
+
20
+ ```typescript
21
+ import crypto from "crypto";
22
+
23
+ export const verifyWebhookSignature = (
24
+ payload: string,
25
+ signature: string,
26
+ secret: string
27
+ ): boolean => {
28
+ const hmac = crypto
29
+ .createHmac("sha256", secret)
30
+ .update(payload)
31
+ .digest("hex");
32
+
33
+ return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(hmac));
34
+ };
35
+
36
+ // Stripe example
37
+ router.post(
38
+ "/webhooks/stripe",
39
+ express.raw({ type: "application/json" }),
40
+ async (req, res) => {
41
+ const sig = req.headers["stripe-signature"];
42
+
43
+ try {
44
+ const event = stripe.webhooks.constructEvent(
45
+ req.body,
46
+ sig,
47
+ process.env.STRIPE_WEBHOOK_SECRET
48
+ );
49
+ await processStripeEvent(event);
50
+ res.json({ received: true });
51
+ } catch (err) {
52
+ return res.status(400).send(`Webhook Error: ${err.message}`);
53
+ }
54
+ }
55
+ );
56
+ ```
57
+
58
+ ## Deduplication
59
+
60
+ ```typescript
61
+ // Redis-based dedupe
62
+ const WEBHOOK_TTL = 60 * 60 * 24; // 24 hours
63
+
64
+ export const isDuplicate = async (webhookId: string): Promise<boolean> => {
65
+ const key = `webhook:${webhookId}`;
66
+ const exists = await redis.exists(key);
67
+
68
+ if (exists) return true;
69
+
70
+ await redis.setex(key, WEBHOOK_TTL, "1");
71
+ return false;
72
+ };
73
+
74
+ // Usage
75
+ if (await isDuplicate(webhook.id)) {
76
+ return res.status(200).json({ received: true }); // Already processed
77
+ }
78
+ ```
79
+
80
+ ## Idempotent Processing
81
+
82
+ ```typescript
83
+ export const processWebhook = async (webhook: Webhook) => {
84
+ // Use database transaction with unique constraint
85
+ try {
86
+ await db.transaction(async (trx) => {
87
+ // Insert webhook record (unique constraint on webhook_id)
88
+ await trx("processed_webhooks").insert({
89
+ webhook_id: webhook.id,
90
+ processed_at: new Date(),
91
+ });
92
+
93
+ // Do actual processing
94
+ await performWebhookAction(webhook, trx);
95
+ });
96
+ } catch (err) {
97
+ if (err.code === "23505") {
98
+ // Unique violation
99
+ console.log("Webhook already processed");
100
+ return; // Idempotent - already processed
101
+ }
102
+ throw err;
103
+ }
104
+ };
105
+ ```
106
+
107
+ ## Retry Handling
108
+
109
+ ```typescript
110
+ // Acknowledge immediately, process async
111
+ router.post("/webhooks/provider", async (req, res) => {
112
+ // Verify signature
113
+ if (!verifySignature(req.body, req.headers["signature"])) {
114
+ return res.status(401).send("Invalid signature");
115
+ }
116
+
117
+ // Return 200 immediately
118
+ res.status(200).json({ received: true });
119
+
120
+ // Process async
121
+ processWebhookAsync(req.body).catch((err) => {
122
+ console.error("Webhook processing failed:", err);
123
+ // Will be retried by provider
124
+ });
125
+ });
126
+
127
+ // Exponential backoff for provider retries
128
+ // Attempt 1: immediate
129
+ // Attempt 2: +5 minutes
130
+ // Attempt 3: +15 minutes
131
+ // Attempt 4: +1 hour
132
+ // Attempt 5: +6 hours
133
+ ```
134
+
135
+ ## Error Responses
136
+
137
+ ```typescript
138
+ // Return appropriate status codes
139
+ const webhookHandler = async (req, res) => {
140
+ // 400: Malformed payload (won't retry)
141
+ if (!isValidPayload(req.body)) {
142
+ return res.status(400).json({ error: "Invalid payload" });
143
+ }
144
+
145
+ // 401: Invalid signature (won't retry)
146
+ if (!verifySignature(req.body, req.headers["signature"])) {
147
+ return res.status(401).json({ error: "Invalid signature" });
148
+ }
149
+
150
+ // 200: Already processed (idempotent)
151
+ if (await isDuplicate(req.body.id)) {
152
+ return res.status(200).json({ received: true });
153
+ }
154
+
155
+ // 500: Processing error (will retry)
156
+ try {
157
+ await processWebhook(req.body);
158
+ return res.status(200).json({ received: true });
159
+ } catch (err) {
160
+ console.error("Processing error:", err);
161
+ return res.status(500).json({ error: "Processing failed" });
162
+ }
163
+ };
164
+ ```
165
+
166
+ ## Monitoring & Runbook
167
+
168
+ ```markdown
169
+ ## Webhook Incidents
170
+
171
+ ### High Error Rate
172
+
173
+ 1. Check provider status page
174
+ 2. Review recent code deploys
175
+ 3. Check signature secret rotation
176
+ 4. Verify database connectivity
177
+
178
+ ### Missing Webhooks
179
+
180
+ 1. Check provider sending (their dashboard)
181
+ 2. Verify endpoint is accessible
182
+ 3. Check rate limiting rules
183
+ 4. Review dedupe cache TTL
184
+
185
+ ### Duplicate Processing
186
+
187
+ 1. Check dedupe cache connectivity
188
+ 2. Verify unique constraints
189
+ 3. Review idempotency logic
190
+ ```
191
+
192
+ ## Best Practices
193
+
194
+ - Verify signature BEFORE any processing
195
+ - Return 200 quickly, process async
196
+ - Dedupe with Redis + database constraints
197
+ - Log all webhook attempts
198
+ - Monitor processing latency
199
+ - Set up alerts for failures
200
+ - Document expected payload schemas
201
+
202
+ ## Output Checklist
203
+
204
+ - [ ] Signature verification
205
+ - [ ] Deduplication mechanism
206
+ - [ ] Idempotent processing
207
+ - [ ] Async processing pattern
208
+ - [ ] Proper status codes
209
+ - [ ] Error logging
210
+ - [ ] Monitoring/alerts
211
+ - [ ] Incident runbook
@@ -0,0 +1,236 @@
1
+ ---
2
+ name: artifact-sbom-publisher
3
+ description: Produces build artifacts with Software Bill of Materials (SBOM) and supply chain metadata for security and compliance. Use for "artifact publishing", "SBOM generation", "supply chain security", or "build provenance".
4
+ ---
5
+
6
+ # Artifact & SBOM Publisher
7
+
8
+ Generate and publish artifacts with supply chain security metadata.
9
+
10
+ ## Build Artifacts
11
+
12
+ ```yaml
13
+ build:
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+
18
+ - uses: actions/setup-node@v4
19
+ with:
20
+ node-version: "20"
21
+
22
+ - run: npm ci
23
+ - run: npm run build
24
+
25
+ - name: Upload artifacts
26
+ uses: actions/upload-artifact@v4
27
+ with:
28
+ name: dist-${{ github.sha }}
29
+ path: |
30
+ dist/
31
+ !dist/**/*.map
32
+ retention-days: 30
33
+ if-no-files-found: error
34
+ ```
35
+
36
+ ## SBOM Generation (CycloneDX)
37
+
38
+ ```yaml
39
+ sbom:
40
+ runs-on: ubuntu-latest
41
+ steps:
42
+ - uses: actions/checkout@v4
43
+
44
+ - name: Generate SBOM
45
+ uses: CycloneDX/gh-node-module-generatebom@master
46
+ with:
47
+ path: ./
48
+ output: ./sbom.json
49
+
50
+ - name: Upload SBOM
51
+ uses: actions/upload-artifact@v4
52
+ with:
53
+ name: sbom-${{ github.sha }}
54
+ path: sbom.json
55
+ ```
56
+
57
+ ## SBOM with Syft
58
+
59
+ ```yaml
60
+ - name: Generate SBOM with Syft
61
+ run: |
62
+ curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
63
+ syft . -o spdx-json > sbom-spdx.json
64
+ syft . -o cyclonedx-json > sbom-cyclonedx.json
65
+
66
+ - name: Upload SBOMs
67
+ uses: actions/upload-artifact@v4
68
+ with:
69
+ name: sboms
70
+ path: |
71
+ sbom-spdx.json
72
+ sbom-cyclonedx.json
73
+ ```
74
+
75
+ ## Docker Image SBOM
76
+
77
+ ```yaml
78
+ - name: Build image
79
+ uses: docker/build-push-action@v5
80
+ with:
81
+ context: .
82
+ push: true
83
+ tags: myapp:${{ github.sha }}
84
+ sbom: true
85
+ provenance: true
86
+
87
+ - name: Generate SBOM for image
88
+ run: |
89
+ syft myapp:${{ github.sha }} -o spdx-json > image-sbom.json
90
+
91
+ - name: Scan SBOM for vulnerabilities
92
+ uses: anchore/scan-action@v3
93
+ with:
94
+ sbom: image-sbom.json
95
+ fail-build: true
96
+ severity-cutoff: high
97
+ ```
98
+
99
+ ## Build Provenance (SLSA)
100
+
101
+ ```yaml
102
+ provenance:
103
+ runs-on: ubuntu-latest
104
+ permissions:
105
+ actions: read
106
+ id-token: write
107
+ contents: write
108
+ steps:
109
+ - uses: actions/checkout@v4
110
+
111
+ - name: Build
112
+ run: npm run build
113
+
114
+ - name: Generate provenance
115
+ uses: actions/attest-build-provenance@v1
116
+ with:
117
+ subject-path: "dist/**"
118
+ ```
119
+
120
+ ## Artifact Metadata
121
+
122
+ ```yaml
123
+ - name: Create artifact metadata
124
+ run: |
125
+ cat > artifact-metadata.json << EOF
126
+ {
127
+ "version": "${{ github.ref_name }}",
128
+ "commit": "${{ github.sha }}",
129
+ "branch": "${{ github.ref }}",
130
+ "build_time": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
131
+ "builder": "GitHub Actions",
132
+ "workflow": "${{ github.workflow }}",
133
+ "run_id": "${{ github.run_id }}",
134
+ "actor": "${{ github.actor }}"
135
+ }
136
+ EOF
137
+
138
+ - name: Upload metadata
139
+ uses: actions/upload-artifact@v4
140
+ with:
141
+ name: metadata
142
+ path: artifact-metadata.json
143
+ ```
144
+
145
+ ## Package & Release
146
+
147
+ ```yaml
148
+ release:
149
+ runs-on: ubuntu-latest
150
+ needs: [build, sbom]
151
+ if: github.event_name == 'release'
152
+ steps:
153
+ - name: Download artifacts
154
+ uses: actions/download-artifact@v4
155
+ with:
156
+ path: artifacts/
157
+
158
+ - name: Create release package
159
+ run: |
160
+ cd artifacts
161
+ tar -czf ../release.tar.gz dist-* sbom-* metadata/
162
+
163
+ - name: Upload to release
164
+ uses: actions/upload-release-asset@v1
165
+ env:
166
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
167
+ with:
168
+ upload_url: ${{ github.event.release.upload_url }}
169
+ asset_path: ./release.tar.gz
170
+ asset_name: release-${{ github.ref_name }}.tar.gz
171
+ asset_content_type: application/gzip
172
+ ```
173
+
174
+ ## Vulnerability Scanning
175
+
176
+ ```yaml
177
+ - name: Scan SBOM for vulnerabilities
178
+ uses: aquasecurity/trivy-action@master
179
+ with:
180
+ scan-type: "sbom"
181
+ format: "sarif"
182
+ output: "trivy-results.sarif"
183
+ sbom-sources: "sbom.json"
184
+
185
+ - name: Upload scan results
186
+ uses: github/codeql-action/upload-sarif@v3
187
+ with:
188
+ sarif_file: "trivy-results.sarif"
189
+ ```
190
+
191
+ ## Artifact Attestation
192
+
193
+ ```yaml
194
+ - name: Attest artifact
195
+ uses: actions/attest@v1
196
+ with:
197
+ subject-path: "dist/myapp.tar.gz"
198
+ predicate-type: "https://slsa.dev/provenance/v1"
199
+ predicate: |
200
+ {
201
+ "buildType": "https://github.com/actions/workflow",
202
+ "builder": {
203
+ "id": "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
204
+ },
205
+ "metadata": {
206
+ "buildInvocationId": "${{ github.run_id }}",
207
+ "completeness": {
208
+ "parameters": true,
209
+ "environment": false,
210
+ "materials": true
211
+ }
212
+ }
213
+ }
214
+ ```
215
+
216
+ ## Best Practices
217
+
218
+ 1. **Generate SBOMs**: For all releases
219
+ 2. **Multiple formats**: SPDX and CycloneDX
220
+ 3. **Scan vulnerabilities**: Before release
221
+ 4. **Sign artifacts**: For verification
222
+ 5. **Include provenance**: SLSA attestation
223
+ 6. **Retention policy**: Keep artifacts 30 days
224
+ 7. **Metadata**: Version, commit, timestamp
225
+ 8. **Automate**: Part of every build
226
+
227
+ ## Output Checklist
228
+
229
+ - [ ] Build artifacts uploaded
230
+ - [ ] SBOM generated (SPDX or CycloneDX)
231
+ - [ ] Vulnerability scanning configured
232
+ - [ ] Build provenance generated
233
+ - [ ] Artifact metadata included
234
+ - [ ] Release packaging automated
235
+ - [ ] Attestation/signing (optional)
236
+ - [ ] Retention policy set