@securityreviewai/securityreview-kit 0.1.51 → 0.1.52

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 (78) hide show
  1. package/README.md +105 -0
  2. package/bin/securityreview-kit.js +5 -0
  3. package/package.json +30 -24
  4. package/src/cli.js +109 -0
  5. package/src/commands/init.js +851 -0
  6. package/src/commands/status.js +99 -0
  7. package/src/commands/switch-project.js +207 -0
  8. package/src/generators/mcp/claude.js +85 -0
  9. package/src/generators/mcp/claude.test.js +64 -0
  10. package/src/generators/mcp/codex.js +70 -0
  11. package/src/generators/mcp/codex.test.js +43 -0
  12. package/src/generators/mcp/cursor.js +29 -0
  13. package/src/generators/mcp/cursor.test.js +50 -0
  14. package/src/generators/mcp/gemini.js +28 -0
  15. package/src/generators/mcp/vscode.js +29 -0
  16. package/src/generators/mcp/windsurf.js +27 -0
  17. package/src/generators/rules/antigravity.js +22 -0
  18. package/src/generators/rules/claude.js +87 -0
  19. package/src/generators/rules/claude.test.js +60 -0
  20. package/src/generators/rules/codex.js +141 -0
  21. package/src/generators/rules/codex.test.js +59 -0
  22. package/src/generators/rules/content.js +110 -0
  23. package/{templates/shared → src/generators/rules}/content.md +6 -9
  24. package/src/generators/rules/cursor.js +128 -0
  25. package/src/generators/rules/gemini.js +13 -0
  26. package/src/generators/rules/guardrails-init-profile.md +56 -0
  27. package/src/generators/rules/guardrails-profiler/SKILL.md +130 -0
  28. package/src/generators/rules/guardrails-profiler/references/signal-registry.json +514 -0
  29. package/{templates/shared/guardrails-selection.md → src/generators/rules/guardrails-selection/SKILL.md} +12 -10
  30. package/src/generators/rules/guardrails-selection/references/category-threat-map.md +232 -0
  31. package/src/generators/rules/guardrails_rule.md +94 -0
  32. package/src/generators/rules/hooks.json +11 -0
  33. package/{templates/shared/threat-modelling.md → src/generators/rules/skill.md} +11 -14
  34. package/src/generators/rules/srai-profile.md +32 -0
  35. package/{templates/shared → src/generators/rules}/vibereview-sync/SKILL.md +12 -15
  36. package/src/generators/rules/vscode.js +101 -0
  37. package/src/generators/rules/vscode.test.js +54 -0
  38. package/src/generators/rules/windsurf.js +13 -0
  39. package/src/utils/constants.js +95 -0
  40. package/src/utils/cursor-agent-path.js +67 -0
  41. package/src/utils/cursor-cli-permissions.js +28 -0
  42. package/src/utils/detect.js +27 -0
  43. package/src/utils/fs-helpers.js +82 -0
  44. package/src/utils/guardrails-profiler-bundle.js +84 -0
  45. package/src/utils/ide-cli-install.js +138 -0
  46. package/src/utils/profiler-agent.js +446 -0
  47. package/src/utils/profiler-agent.test.js +81 -0
  48. package/src/utils/srai.js +252 -0
  49. package/dist/api.js +0 -44
  50. package/dist/commands/guardrails.js +0 -13
  51. package/dist/commands/init.js +0 -88
  52. package/dist/commands/profile.js +0 -14
  53. package/dist/commands/status.js +0 -27
  54. package/dist/commands/sync.js +0 -6
  55. package/dist/config.js +0 -18
  56. package/dist/fs.js +0 -43
  57. package/dist/index.js +0 -44
  58. package/dist/profile.js +0 -113
  59. package/dist/scaffold/claude-code.js +0 -43
  60. package/dist/scaffold/codex.js +0 -41
  61. package/dist/scaffold/cursor.js +0 -45
  62. package/dist/scaffold/gemini.js +0 -10
  63. package/dist/scaffold/index.js +0 -22
  64. package/dist/scaffold/mcp.js +0 -15
  65. package/dist/scaffold/rules.js +0 -191
  66. package/dist/scaffold/vibreview.js +0 -30
  67. package/dist/scaffold/vscode.js +0 -28
  68. package/dist/scaffold/windsurf.js +0 -10
  69. package/dist/sync/index.js +0 -34
  70. package/dist/sync/payload.js +0 -23
  71. package/dist/sync/state.js +0 -12
  72. package/dist/types.js +0 -1
  73. package/templates/claude/CLAUDE.md +0 -13
  74. package/templates/claude/agents/guardrail_profiler.md +0 -12
  75. package/templates/claude/agents/threat_modeler.md +0 -5
  76. package/templates/claude/skills/vibreview/SKILL.md +0 -21
  77. package/templates/claude/skills/vibreview/guardrail_patterns.md +0 -12
  78. package/templates/cursor/rules/vibreview-security.mdc +0 -8
@@ -0,0 +1,514 @@
1
+ {
2
+ "_doc": "Maps filesystem signals to guardrail pack IDs. Each entry defines what to look for and which pack to activate.",
3
+
4
+ "universal": {
5
+ "_doc": "Always included regardless of detection",
6
+ "packs": ["owasp-asvs"]
7
+ },
8
+
9
+ "mobile_universal": {
10
+ "_doc": "Included when any mobile platform is detected",
11
+ "trigger_packs": ["flutter", "react-native", "swift", "objective-c", "kotlin"],
12
+ "packs": ["owasp-masvs"]
13
+ },
14
+
15
+ "languages": {
16
+ "typescript": {
17
+ "manifest_files": ["tsconfig.json", "tsconfig.base.json"],
18
+ "file_extensions": [".ts", ".tsx"],
19
+ "pack": "typescript"
20
+ },
21
+ "nodejs": {
22
+ "manifest_files": ["package.json"],
23
+ "file_extensions": [".js", ".mjs", ".cjs"],
24
+ "pack": "nodejs"
25
+ },
26
+ "python": {
27
+ "manifest_files": ["requirements.txt", "pyproject.toml", "setup.py", "setup.cfg", "Pipfile", "poetry.lock"],
28
+ "file_extensions": [".py"],
29
+ "pack": null,
30
+ "_note": "Python has no standalone pack; frameworks (django, flask, fastapi) cover it"
31
+ },
32
+ "go": {
33
+ "manifest_files": ["go.mod", "go.sum"],
34
+ "file_extensions": [".go"],
35
+ "pack": "go"
36
+ },
37
+ "java": {
38
+ "manifest_files": ["pom.xml", "build.gradle", "build.gradle.kts", "settings.gradle", "settings.gradle.kts"],
39
+ "file_extensions": [".java"],
40
+ "pack": null,
41
+ "_note": "Java framework packs (spring-boot, java-ee) are more specific"
42
+ },
43
+ "kotlin": {
44
+ "manifest_files": ["build.gradle.kts"],
45
+ "file_extensions": [".kt", ".kts"],
46
+ "dependency_signals": { "build.gradle.kts": ["kotlin"] },
47
+ "pack": "kotlin"
48
+ },
49
+ "php": {
50
+ "manifest_files": ["composer.json", "composer.lock"],
51
+ "file_extensions": [".php"],
52
+ "pack": "php"
53
+ },
54
+ "ruby": {
55
+ "manifest_files": ["Gemfile", "Gemfile.lock"],
56
+ "file_extensions": [".rb"],
57
+ "pack": null,
58
+ "_note": "Ruby framework pack (ruby-on-rails) is more specific"
59
+ },
60
+ "rust": {
61
+ "manifest_files": ["Cargo.toml", "Cargo.lock"],
62
+ "file_extensions": [".rs"],
63
+ "pack": "rust"
64
+ },
65
+ "c": {
66
+ "file_extensions": [".c", ".h"],
67
+ "manifest_files": ["CMakeLists.txt", "Makefile"],
68
+ "pack": "c"
69
+ },
70
+ "cpp": {
71
+ "file_extensions": [".cpp", ".cxx", ".cc", ".hpp", ".hxx"],
72
+ "manifest_files": ["CMakeLists.txt"],
73
+ "pack": "cpp"
74
+ },
75
+ "swift": {
76
+ "manifest_files": ["Package.swift"],
77
+ "file_extensions": [".swift"],
78
+ "config_files": ["*.xcodeproj", "*.xcworkspace"],
79
+ "pack": "swift"
80
+ },
81
+ "objective-c": {
82
+ "file_extensions": [".m", ".mm"],
83
+ "pack": "objective-c"
84
+ },
85
+ "groovy": {
86
+ "file_extensions": [".groovy"],
87
+ "pack": "groovy"
88
+ },
89
+ "csharp": {
90
+ "manifest_files": ["*.csproj", "*.sln"],
91
+ "file_extensions": [".cs"],
92
+ "pack": null,
93
+ "_note": "C# framework pack (dotnet-aspnet-core) is more specific"
94
+ }
95
+ },
96
+
97
+ "frameworks": {
98
+ "express": {
99
+ "ecosystem": "nodejs",
100
+ "dependency_signals": { "package.json": ["express"] },
101
+ "pack": "express"
102
+ },
103
+ "fastify": {
104
+ "ecosystem": "nodejs",
105
+ "dependency_signals": { "package.json": ["fastify"] },
106
+ "pack": "fastify"
107
+ },
108
+ "honojs": {
109
+ "ecosystem": "nodejs",
110
+ "dependency_signals": { "package.json": ["hono"] },
111
+ "pack": "honojs"
112
+ },
113
+ "nestjs": {
114
+ "ecosystem": "nodejs",
115
+ "dependency_signals": { "package.json": ["@nestjs/core"] },
116
+ "config_files": ["nest-cli.json"],
117
+ "pack": "nestjs"
118
+ },
119
+ "nextjs": {
120
+ "ecosystem": "nodejs",
121
+ "dependency_signals": { "package.json": ["next"] },
122
+ "config_files": ["next.config.js", "next.config.mjs", "next.config.ts"],
123
+ "pack": "nextjs"
124
+ },
125
+ "react": {
126
+ "ecosystem": "nodejs",
127
+ "dependency_signals": { "package.json": ["react", "react-dom"] },
128
+ "pack": "react"
129
+ },
130
+ "angular": {
131
+ "ecosystem": "nodejs",
132
+ "dependency_signals": { "package.json": ["@angular/core"] },
133
+ "config_files": ["angular.json"],
134
+ "pack": "angular"
135
+ },
136
+ "vuejs": {
137
+ "ecosystem": "nodejs",
138
+ "dependency_signals": { "package.json": ["vue"] },
139
+ "config_files": ["vue.config.js", "vite.config.ts", "nuxt.config.ts"],
140
+ "pack": "vuejs"
141
+ },
142
+ "electron": {
143
+ "ecosystem": "nodejs",
144
+ "dependency_signals": { "package.json": ["electron"] },
145
+ "pack": "electron"
146
+ },
147
+ "react-native": {
148
+ "ecosystem": "nodejs",
149
+ "dependency_signals": { "package.json": ["react-native"] },
150
+ "pack": "react-native"
151
+ },
152
+ "django": {
153
+ "ecosystem": "python",
154
+ "dependency_signals": {
155
+ "requirements.txt": ["django", "Django"],
156
+ "pyproject.toml": ["django", "Django"],
157
+ "Pipfile": ["django", "Django"]
158
+ },
159
+ "config_files": ["manage.py"],
160
+ "directory_signals": ["*/settings.py", "*/wsgi.py"],
161
+ "pack": "django"
162
+ },
163
+ "flask": {
164
+ "ecosystem": "python",
165
+ "dependency_signals": {
166
+ "requirements.txt": ["flask", "Flask"],
167
+ "pyproject.toml": ["flask", "Flask"]
168
+ },
169
+ "pack": "flask"
170
+ },
171
+ "fastapi": {
172
+ "ecosystem": "python",
173
+ "dependency_signals": {
174
+ "requirements.txt": ["fastapi"],
175
+ "pyproject.toml": ["fastapi"]
176
+ },
177
+ "pack": "fastapi"
178
+ },
179
+ "java-spring-boot": {
180
+ "ecosystem": "java",
181
+ "dependency_signals": {
182
+ "pom.xml": ["spring-boot-starter"],
183
+ "build.gradle": ["org.springframework.boot"]
184
+ },
185
+ "pack": "java-spring-boot"
186
+ },
187
+ "spring-security": {
188
+ "ecosystem": "java",
189
+ "dependency_signals": {
190
+ "pom.xml": ["spring-boot-starter-security", "spring-security"],
191
+ "build.gradle": ["spring-boot-starter-security", "spring-security"]
192
+ },
193
+ "pack": "spring-security"
194
+ },
195
+ "java-ee": {
196
+ "ecosystem": "java",
197
+ "dependency_signals": {
198
+ "pom.xml": ["javax.servlet", "jakarta.servlet", "javax.enterprise", "jakarta.enterprise"],
199
+ "build.gradle": ["javax.servlet", "jakarta.servlet"]
200
+ },
201
+ "config_files": ["web.xml"],
202
+ "pack": "java-ee"
203
+ },
204
+ "ruby-on-rails": {
205
+ "ecosystem": "ruby",
206
+ "dependency_signals": { "Gemfile": ["rails"] },
207
+ "config_files": ["config/routes.rb", "config/application.rb"],
208
+ "pack": "ruby-on-rails"
209
+ },
210
+ "laravel": {
211
+ "ecosystem": "php",
212
+ "dependency_signals": { "composer.json": ["laravel/framework"] },
213
+ "config_files": ["artisan"],
214
+ "directory_signals": ["app/Http/Controllers"],
215
+ "pack": "laravel"
216
+ },
217
+ "symfony": {
218
+ "ecosystem": "php",
219
+ "dependency_signals": { "composer.json": ["symfony/framework-bundle"] },
220
+ "config_files": ["config/bundles.php", "symfony.lock"],
221
+ "pack": "symfony"
222
+ },
223
+ "dotnet-aspnet-core": {
224
+ "ecosystem": "csharp",
225
+ "dependency_signals": { "*.csproj": ["Microsoft.AspNetCore"] },
226
+ "config_files": ["Program.cs", "Startup.cs", "appsettings.json"],
227
+ "pack": "dotnet-aspnet-core"
228
+ },
229
+ "flutter": {
230
+ "ecosystem": "dart",
231
+ "manifest_files": ["pubspec.yaml"],
232
+ "dependency_signals": { "pubspec.yaml": ["flutter"] },
233
+ "pack": "flutter"
234
+ },
235
+ "apollo-graphql": {
236
+ "ecosystem": "nodejs",
237
+ "dependency_signals": { "package.json": ["@apollo/server", "apollo-server", "apollo-server-express"] },
238
+ "pack": "apollo-graphql"
239
+ }
240
+ },
241
+
242
+ "auth_identity": {
243
+ "jwt": {
244
+ "dependency_signals": {
245
+ "package.json": ["jsonwebtoken", "jose", "@auth/core"],
246
+ "requirements.txt": ["pyjwt", "python-jose"],
247
+ "pyproject.toml": ["pyjwt", "python-jose"],
248
+ "Gemfile": ["jwt"],
249
+ "pom.xml": ["jjwt", "nimbus-jose-jwt"]
250
+ },
251
+ "pack": "jwt"
252
+ },
253
+ "oauth-oidc": {
254
+ "dependency_signals": {
255
+ "package.json": ["openid-client", "passport-oauth2", "oauth4webapi"],
256
+ "requirements.txt": ["authlib", "oauthlib"],
257
+ "pyproject.toml": ["authlib", "oauthlib"]
258
+ },
259
+ "pack": "oauth-oidc"
260
+ },
261
+ "auth0": {
262
+ "dependency_signals": {
263
+ "package.json": ["@auth0/nextjs-auth0", "auth0", "express-openid-connect"],
264
+ "requirements.txt": ["auth0-python"],
265
+ "pyproject.toml": ["auth0-python"]
266
+ },
267
+ "pack": "auth0"
268
+ },
269
+ "okta": {
270
+ "dependency_signals": {
271
+ "package.json": ["@okta/okta-sdk-nodejs", "@okta/oidc-middleware"],
272
+ "pom.xml": ["okta-spring-boot-starter"]
273
+ },
274
+ "pack": "okta"
275
+ },
276
+ "keycloak": {
277
+ "dependency_signals": {
278
+ "package.json": ["keycloak-connect", "keycloak-js"],
279
+ "pom.xml": ["keycloak-spring-boot-starter"]
280
+ },
281
+ "config_files": ["keycloak.json"],
282
+ "pack": "keycloak"
283
+ }
284
+ },
285
+
286
+ "ai_agent": {
287
+ "langchain": {
288
+ "dependency_signals": {
289
+ "requirements.txt": ["langchain"],
290
+ "pyproject.toml": ["langchain"],
291
+ "package.json": ["langchain"]
292
+ },
293
+ "pack": "langchain"
294
+ },
295
+ "langgraph": {
296
+ "dependency_signals": {
297
+ "requirements.txt": ["langgraph"],
298
+ "pyproject.toml": ["langgraph"]
299
+ },
300
+ "pack": "langgraph"
301
+ },
302
+ "llamaindex": {
303
+ "dependency_signals": {
304
+ "requirements.txt": ["llama-index", "llama_index"],
305
+ "pyproject.toml": ["llama-index", "llama_index"]
306
+ },
307
+ "pack": "llamaindex"
308
+ },
309
+ "crewai": {
310
+ "dependency_signals": {
311
+ "requirements.txt": ["crewai"],
312
+ "pyproject.toml": ["crewai"]
313
+ },
314
+ "pack": "crewai"
315
+ },
316
+ "mastra": {
317
+ "dependency_signals": {
318
+ "package.json": ["@mastra/core", "mastra"]
319
+ },
320
+ "pack": "mastra"
321
+ },
322
+ "ai-sdk": {
323
+ "dependency_signals": {
324
+ "package.json": ["ai", "@ai-sdk/openai", "@ai-sdk/anthropic"]
325
+ },
326
+ "pack": "ai-sdk"
327
+ },
328
+ "claude-agent-sdk": {
329
+ "dependency_signals": {
330
+ "package.json": ["@anthropic-ai/sdk"],
331
+ "requirements.txt": ["anthropic"],
332
+ "pyproject.toml": ["anthropic"]
333
+ },
334
+ "pack": "claude-agent-sdk"
335
+ },
336
+ "openai-agents-sdk": {
337
+ "dependency_signals": {
338
+ "package.json": ["openai"],
339
+ "requirements.txt": ["openai"],
340
+ "pyproject.toml": ["openai"]
341
+ },
342
+ "pack": "openai-agents-sdk"
343
+ },
344
+ "mcp": {
345
+ "dependency_signals": {
346
+ "package.json": ["@modelcontextprotocol/sdk"],
347
+ "requirements.txt": ["mcp"],
348
+ "pyproject.toml": ["mcp"]
349
+ },
350
+ "pack": "mcp"
351
+ }
352
+ },
353
+
354
+ "infrastructure": {
355
+ "docker": {
356
+ "config_files": ["Dockerfile", "docker-compose.yml", "docker-compose.yaml", ".dockerignore"],
357
+ "pack": "docker"
358
+ },
359
+ "kubernetes": {
360
+ "config_files": ["helmfile.yaml", "Chart.yaml", "kustomization.yaml"],
361
+ "directory_signals": ["k8s/", "kubernetes/", "helm/"],
362
+ "content_signals": { "*.yaml": ["apiVersion", "kind: Deployment", "kind: Service", "kind: Pod"] },
363
+ "pack": "kubernetes"
364
+ },
365
+ "terraform-aws": {
366
+ "file_extensions": [".tf"],
367
+ "content_signals": { "*.tf": ["provider \"aws\"", "aws_"] },
368
+ "pack": "terraform-aws"
369
+ },
370
+ "terraform-azure": {
371
+ "file_extensions": [".tf"],
372
+ "content_signals": { "*.tf": ["provider \"azurerm\"", "azurerm_"] },
373
+ "pack": "terraform-azure"
374
+ },
375
+ "terraform-gcp": {
376
+ "file_extensions": [".tf"],
377
+ "content_signals": { "*.tf": ["provider \"google\"", "google_"] },
378
+ "pack": "terraform-gcp"
379
+ },
380
+ "cloudformation": {
381
+ "content_signals": { "*.yaml": ["AWSTemplateFormatVersion"], "*.json": ["AWSTemplateFormatVersion"] },
382
+ "config_files": ["template.yaml", "template.json", "samconfig.toml"],
383
+ "pack": "cloudformation"
384
+ },
385
+ "nginx": {
386
+ "config_files": ["nginx.conf"],
387
+ "directory_signals": ["nginx/"],
388
+ "pack": "nginx"
389
+ }
390
+ },
391
+
392
+ "ci_cd": {
393
+ "github-actions": {
394
+ "directory_signals": [".github/workflows/"],
395
+ "pack": "github-actions"
396
+ },
397
+ "jenkins-pipeline": {
398
+ "config_files": ["Jenkinsfile"],
399
+ "pack": "jenkins-pipeline"
400
+ },
401
+ "argocd": {
402
+ "config_files": ["argocd-cm.yaml"],
403
+ "content_signals": { "*.yaml": ["argoproj.io"] },
404
+ "pack": "argocd"
405
+ }
406
+ },
407
+
408
+ "cloud_compute": {
409
+ "aws-lambda": {
410
+ "config_files": ["serverless.yml", "serverless.yaml", "serverless.ts", "sam.yaml", "samconfig.toml"],
411
+ "content_signals": {
412
+ "serverless.yml": ["provider:", "aws"],
413
+ "template.yaml": ["AWS::Serverless::Function", "AWS::Lambda::Function"]
414
+ },
415
+ "pack": "aws-lambda"
416
+ },
417
+ "azure-functions": {
418
+ "config_files": ["host.json", "local.settings.json"],
419
+ "directory_signals": ["function_app.py"],
420
+ "pack": "azure-functions"
421
+ },
422
+ "gcp-cloud-run": {
423
+ "config_files": ["app.yaml", "cloudbuild.yaml"],
424
+ "content_signals": { "*.yaml": ["gcr.io", "run.googleapis.com"] },
425
+ "pack": "gcp-cloud-run"
426
+ }
427
+ },
428
+
429
+ "databases": {
430
+ "mongodb": {
431
+ "dependency_signals": {
432
+ "package.json": ["mongoose", "mongodb"],
433
+ "requirements.txt": ["pymongo", "motor", "mongoengine"],
434
+ "pyproject.toml": ["pymongo", "motor"],
435
+ "Gemfile": ["mongoid"]
436
+ },
437
+ "pack": "mongodb"
438
+ },
439
+ "postgresql": {
440
+ "dependency_signals": {
441
+ "package.json": ["pg", "knex", "prisma", "typeorm", "sequelize"],
442
+ "requirements.txt": ["psycopg2", "asyncpg", "sqlalchemy"],
443
+ "pyproject.toml": ["psycopg2", "asyncpg", "sqlalchemy"],
444
+ "Gemfile": ["pg"],
445
+ "pom.xml": ["postgresql"]
446
+ },
447
+ "pack": "postgresql"
448
+ },
449
+ "mysql-mariadb": {
450
+ "dependency_signals": {
451
+ "package.json": ["mysql2", "mysql"],
452
+ "requirements.txt": ["mysqlclient", "pymysql", "aiomysql"],
453
+ "pyproject.toml": ["mysqlclient", "pymysql"],
454
+ "pom.xml": ["mysql-connector-java"]
455
+ },
456
+ "pack": "mysql-mariadb"
457
+ },
458
+ "redis": {
459
+ "dependency_signals": {
460
+ "package.json": ["redis", "ioredis"],
461
+ "requirements.txt": ["redis", "aioredis"],
462
+ "pyproject.toml": ["redis"],
463
+ "Gemfile": ["redis"]
464
+ },
465
+ "pack": "redis"
466
+ }
467
+ },
468
+
469
+ "messaging": {
470
+ "kafka": {
471
+ "dependency_signals": {
472
+ "package.json": ["kafkajs"],
473
+ "requirements.txt": ["confluent-kafka", "aiokafka"],
474
+ "pyproject.toml": ["confluent-kafka"],
475
+ "pom.xml": ["kafka-clients", "spring-kafka"]
476
+ },
477
+ "pack": "kafka"
478
+ },
479
+ "rabbitmq": {
480
+ "dependency_signals": {
481
+ "package.json": ["amqplib"],
482
+ "requirements.txt": ["pika", "aio-pika"],
483
+ "pyproject.toml": ["pika"],
484
+ "pom.xml": ["spring-boot-starter-amqp"]
485
+ },
486
+ "pack": "rabbitmq"
487
+ }
488
+ },
489
+
490
+ "api_protocols": {
491
+ "grpc": {
492
+ "dependency_signals": {
493
+ "package.json": ["@grpc/grpc-js"],
494
+ "requirements.txt": ["grpcio"],
495
+ "pyproject.toml": ["grpcio"],
496
+ "pom.xml": ["grpc-netty"]
497
+ },
498
+ "file_extensions": [".proto"],
499
+ "pack": "grpc"
500
+ },
501
+ "websockets": {
502
+ "dependency_signals": {
503
+ "package.json": ["ws", "socket.io"],
504
+ "requirements.txt": ["websockets"],
505
+ "pyproject.toml": ["websockets"]
506
+ },
507
+ "pack": "websockets"
508
+ },
509
+ "openapi-rest-api": {
510
+ "config_files": ["openapi.yaml", "openapi.json", "swagger.yaml", "swagger.json"],
511
+ "pack": "openapi-rest-api"
512
+ }
513
+ }
514
+ }
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: guardrails-selection
3
- description: Analyze the developer request, infer the security categories and likely threats involved, shortlist the most relevant project guardrails, then preserve the exact returned guardrail records before implementation. Use for every security-relevant code task before code is written and preserve the shortlist for the final VibeReview sync.
3
+ description: Analyze the developer request, infer the security categories and likely threats involved, shortlist the most relevant project guardrails, then hydrate the exact guardrails with get_guardrail_by_id before implementation. Use for every security-relevant code task before code is written and preserve the shortlist for the final VibeReview sync.
4
4
  ---
5
5
 
6
6
  # Guardrails Selection
@@ -9,15 +9,13 @@ Configured SRAI project name: `<SRAI_PROJECT_NAME>`
9
9
 
10
10
  Use this skill whenever code will be created or modified and the task has any security surface.
11
11
 
12
- This skill is a hard pre-write gate. Do not write, edit, patch, or generate implementation code until this skill has produced the active guardrail shortlist and the PWNISMS skill has used that shortlist for threat modelling.
13
-
14
12
  This skill exists to stop the IDE from treating the full `get_guardrails` result as an unstructured blob. The workflow is:
15
13
 
16
14
  1. Understand the request deeply.
17
15
  2. Infer which security categories are in play.
18
16
  3. Predict the threats that might occur for this exact task.
19
17
  4. Shortlist only the guardrails that mitigate those threats.
20
- 5. Preserve the exact shortlisted guardrails returned by the project guardrail bundle.
18
+ 5. Fetch the exact shortlisted guardrails with `get_guardrail_by_id`.
21
19
  6. Carry that same shortlist forward into implementation and the final VibeReview markdown sync.
22
20
 
23
21
  Do not skip the analysis step. Do not rely on title-matching alone. Do not dump every guardrail into the final answer.
@@ -96,7 +94,7 @@ The shortlist should be threat-led, not catalog-led.
96
94
  1. Call `find_project_by_name` with `name="<SRAI_PROJECT_NAME>"` to obtain `project_id`.
97
95
  2. Call `get_guardrails` with `project_id`.
98
96
 
99
- Treat `get_guardrails` as the broad project catalog. Do not treat the whole catalog as the final set of instructions. The returned entries are already the authoritative guardrail records for this project; shortlist from those exact records and preserve their ids, titles, rule types, categories, and instructions.
97
+ Treat `get_guardrails` as the broad catalog. Do not treat it as the final set of instructions.
100
98
 
101
99
  Assume each returned guardrail includes the fields needed for selection, including a stable identifier for follow-up retrieval, plus:
102
100
 
@@ -126,11 +124,15 @@ Examples:
126
124
  - If the task introduces parsing, uploads, template expansion, or object hydration, prioritize input validation, file handling, deserialization, and denial-of-service guardrails.
127
125
  - If the task moves security decisions into the browser or mobile client, prioritize client-side trust, token storage, server-side revalidation, and privilege-boundary guardrails.
128
126
 
129
- ### Step 3: Preserve exact shortlisted guardrails
127
+ ### Step 3: Hydrate exact shortlisted guardrails
128
+
129
+ For every shortlisted existing guardrail, call `get_guardrail_by_id` to retrieve the exact guardrail that will govern implementation.
130
130
 
131
- For every shortlisted existing guardrail, preserve the exact guardrail record returned by `get_guardrails`.
131
+ - Use `get_guardrail_by_id` for the shortlisted ids only.
132
+ - If the tool supports batching, batch the shortlisted ids.
133
+ - If the tool only supports one id at a time, call it once per shortlisted id.
132
134
 
133
- Implementation must be driven by that exact shortlist, not by vague memory from the broad catalog listing. Do not re-query guardrails after implementation starts unless the shortlist is missing or the task scope materially changes.
135
+ Implementation must be driven by the hydrated shortlist from `get_guardrail_by_id`, not by vague memory from the broad catalog listing.
134
136
 
135
137
  ### Step 4: Track the active shortlist in context
136
138
 
@@ -149,7 +151,7 @@ This shortlist is the source of truth for the rest of the session.
149
151
 
150
152
  ## Implementation Rules
151
153
 
152
- Once the exact shortlist is preserved:
154
+ Once the shortlist is hydrated:
153
155
 
154
156
  - Every applicable `must` guardrail is mandatory.
155
157
  - Every applicable `must_not` guardrail is a hard prohibition.
@@ -160,7 +162,7 @@ When deciding whether a guardrail applies, prefer security-preserving inclusion
160
162
 
161
163
  ## VibeReview Sync Contract
162
164
 
163
- The final sync step must reuse the shortlist from this skill. It must not call `get_guardrails` again unless the task scope materially changed.
165
+ The final sync step must reuse the shortlist from this skill. It must not call `get_guardrails` or `get_guardrail_by_id` again.
164
166
 
165
167
  Before `sync_ai_ide_markdown` is called, ensure the main agent context clearly contains:
166
168