@vibecontrols/vibe-plugin-security-release-gate 2026.528.1
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/LICENSE +5 -0
- package/README.md +25 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +2 -0
- package/dist/provider.d.ts +13 -0
- package/package.json +83 -0
package/LICENSE
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# @vibecontrols/vibe-plugin-security-release-gate
|
|
2
|
+
|
|
3
|
+
OPA-backed release gate for the `promote.prod` lifecycle stage in [VibeControls](https://vibecontrols.com). Does **not** shell out — it calls the backend's `securityPolicyDecision(scanRunId)` GraphQL resolver, which in turn POSTs to the existing `opa-wspace:8181` ACA sidecar with the appropriate Rego bundle.
|
|
4
|
+
|
|
5
|
+
Registers as a `security.release` provider (name `opa-release-gate`) with the [`@vibecontrols/vibe-plugin-security`](https://www.npmjs.com/package/@vibecontrols/vibe-plugin-security) meta plugin.
|
|
6
|
+
|
|
7
|
+
## Decision input
|
|
8
|
+
|
|
9
|
+
The backend resolver loads:
|
|
10
|
+
|
|
11
|
+
- the scan run's `summary` (severity counts)
|
|
12
|
+
- open `SecurityFinding[]` (joined to active `SecurityException[]`)
|
|
13
|
+
- the workspace + per-vibe `SecurityPolicy` (level: `advisory` / `warn` / `block`)
|
|
14
|
+
- artifact metadata (signed? SBOM present? pinned by digest?)
|
|
15
|
+
|
|
16
|
+
It POSTs the document to `POST {OPA_URL}/v1/data/vibecontrols/security/release/allow` and caches the decision in Valkey for 5 minutes keyed by `(scanRunId, policyVersion)`.
|
|
17
|
+
|
|
18
|
+
## Provider output
|
|
19
|
+
|
|
20
|
+
- `NormalizedFinding[]` — one row per `deny[]` entry with `category: "policy"` and severity derived from the policy expression
|
|
21
|
+
- Evidence: a single `opa-decision` JSON document containing the input + decision (uploaded to S3 for the audit trail)
|
|
22
|
+
|
|
23
|
+
## License
|
|
24
|
+
|
|
25
|
+
Proprietary — Burdenoff Consultancy Services Pvt. Ltd.
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import{ProviderRegistry,TelemetryEmitter,createLifecycleHooks}from"@vibecontrols/plugin-sdk";import{createHash}from"crypto";import{promises as fs}from"fs";import*as path from"path";import{normalizeOpaDecision}from"@vibecontrols/vibe-plugin-security/normalizer";var POLICY_VERSION=2,POLICY_ID="vibecontrols.security.release";class ReleaseGateProvider{name="opa-release-gate";stage="promote.prod";toolVersion=`agent-local-policy@${POLICY_ID}/v${POLICY_VERSION}`;host;async init(host){this.host=host}async ensureToolInstalled(){}async run(input){let startedAt=Date.now(),cfg=input.config??{};input.onProgress?.({pct:10,message:"Loading upstream scan data"});let upstreamFindings=cfg.upstreamFindings??[],upstreamSummary=cfg.upstreamSummary??{critical:0,high:0,medium:0,low:0,info:0};input.onProgress?.({pct:40,message:"Evaluating release gate policy"});let decision=evaluatePolicy(upstreamFindings,upstreamSummary,cfg);input.onProgress?.({pct:70,message:"Building deny[] -> findings"});let opaResultDoc=JSON.stringify({result:{allow:decision.allow,deny:decision.denyReasons}}),findings=normalizeOpaDecision(opaResultDoc,this.name),evidencePath=path.join(input.workdir,"opa-decision.json"),evidenceJson=JSON.stringify(decision,null,2);await fs.writeFile(evidencePath,evidenceJson,"utf-8");let stat=await fs.stat(evidencePath),sha256=createHash("sha256").update(evidenceJson).digest("hex"),evidence=[{type:"opa-decision",localPath:evidencePath,sha256,sizeBytes:stat.size}];return input.onProgress?.({pct:100,message:"Release gate evaluated"}),{runId:input.runId,status:"succeeded",findings,evidence,durationMs:Date.now()-startedAt,summary:summarize(findings)}}async cancel(_runId){}metadata(){return{stage:this.stage,supportedProfiles:["backend","frontend","cli","sdk","mcp","mobile","container","iac"],toolVersion:this.toolVersion,description:"Agent-local release-gate policy for the promote.prod stage. No backend."}}}function evaluatePolicy(upstreamFindings,summary,cfg){let denyReasons=[],openCriticals=upstreamFindings.filter((f)=>f.severity==="critical"&&f.status==="open"),openHighs=upstreamFindings.filter((f)=>f.severity==="high"&&f.status==="open");if(openCriticals.length>0)denyReasons.push(`${openCriticals.length} critical finding(s) open: ${openCriticals.slice(0,3).map((f)=>f.ruleId).join(", ")}${openCriticals.length>3?"...":""}`);if(!cfg.upstreamScanRunId&&summary.critical===0&&summary.high===0&&summary.medium===0&&summary.low===0&&summary.info===0)denyReasons.push("No upstream scan recorded \u2014 build stage must run before promote.prod");if(cfg.requireSignedArtifact&&!cfg.signature?.verified)denyReasons.push("Required signature is missing or not verified");if(typeof cfg.maxHighOpen==="number"&&openHighs.length>cfg.maxHighOpen)denyReasons.push(`${openHighs.length} open high-severity finding(s) exceeds maxHighOpen=${cfg.maxHighOpen}`);return{allow:denyReasons.length===0,denyReasons,evaluatedAt:new Date().toISOString(),policyVersion:POLICY_VERSION,policyId:POLICY_ID,input:{summary,openCriticalCount:openCriticals.length,openHighCount:openHighs.length,upstreamScanRunId:cfg.upstreamScanRunId}}}function summarize(findings){let s={critical:0,high:0,medium:0,low:0,info:0};for(let f of findings)s[f.severity]++;return s}var PLUGIN_NAME="security-release-gate",PLUGIN_VERSION="2026.527.1",createPlugin=(_ctx)=>{let provider=new ReleaseGateProvider,telemetry=new TelemetryEmitter(PLUGIN_NAME,PLUGIN_VERSION),lifecycle=createLifecycleHooks({name:PLUGIN_NAME,telemetryEventName:"security.release-gate.ready",onInit:async(host)=>{await provider.init(host),new ProviderRegistry(host).registerProvider("security.release","opa-release-gate",provider),telemetry.emit("security.release-gate.registered",{provider:"opa-release-gate",toolVersion:provider.toolVersion})}});return{name:PLUGIN_NAME,version:PLUGIN_VERSION,description:"OPA Rego release-gate provider for the promote.prod stage.",tags:["backend","provider","integration"],capabilities:{storage:"rw",audit:!0,telemetry:!0,gateway:!0},onServerStart:lifecycle.onServerStart,onServerStop:lifecycle.onServerStop}},src_default=createPlugin;export{src_default as default,createPlugin,ReleaseGateProvider};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { HostServices } from "@vibecontrols/plugin-sdk/contract";
|
|
2
|
+
import type { SecurityProvider, SecurityProviderMetadata, SecurityScanInput, SecurityScanResult, SecurityStage } from "@vibecontrols/vibe-plugin-security/types";
|
|
3
|
+
export declare class ReleaseGateProvider implements SecurityProvider {
|
|
4
|
+
readonly name = "opa-release-gate";
|
|
5
|
+
readonly stage: SecurityStage;
|
|
6
|
+
readonly toolVersion = "agent-local-policy@vibecontrols.security.release/v2";
|
|
7
|
+
private host?;
|
|
8
|
+
init(host: HostServices): Promise<void>;
|
|
9
|
+
ensureToolInstalled(): Promise<void>;
|
|
10
|
+
run(input: SecurityScanInput): Promise<SecurityScanResult>;
|
|
11
|
+
cancel(_runId: string): Promise<void>;
|
|
12
|
+
metadata(): SecurityProviderMetadata;
|
|
13
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vibecontrols/vibe-plugin-security-release-gate",
|
|
3
|
+
"version": "2026.528.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
7
|
+
"description": "OPA-backed release-gate provider for the promote.prod lifecycle stage. Calls the backend policy decision resolver and maps deny[] to NormalizedFinding[]. Registers as a security.release provider with @vibecontrols/vibe-plugin-security.",
|
|
8
|
+
"engines": {
|
|
9
|
+
"bun": ">=1.3.14"
|
|
10
|
+
},
|
|
11
|
+
"author": {
|
|
12
|
+
"name": "Vignesh T.V",
|
|
13
|
+
"email": "vignesh@burdenoff.com",
|
|
14
|
+
"url": "https://github.com/tvvignesh"
|
|
15
|
+
},
|
|
16
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "bun build ./src/index.ts --outdir ./dist --target bun --minify-syntax --minify-whitespace --external elysia --external @vibecontrols/vibe-plugin-security --external @vibecontrols/plugin-sdk && tsc --emitDeclarationOnly --declaration --outDir ./dist",
|
|
19
|
+
"dev": "tsc --watch",
|
|
20
|
+
"lint": "eslint ./src ./tests",
|
|
21
|
+
"format": "bunx prettier . --write",
|
|
22
|
+
"format:check": "bunx prettier . --check",
|
|
23
|
+
"type:check": "tsc --noEmit",
|
|
24
|
+
"test": "bun test ./tests",
|
|
25
|
+
"clean": "rimraf dist",
|
|
26
|
+
"prebuild": "bun run clean",
|
|
27
|
+
"prepublishOnly": "bun run build",
|
|
28
|
+
"sanity": "bun run format:check && bun run lint && bun run type:check && bun run test && bun run build"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@vibecontrols/plugin-sdk": "2026.527.1",
|
|
32
|
+
"@vibecontrols/vibe-plugin-security": "2026.528.1"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@eslint/js": "^10.0.1",
|
|
36
|
+
"@types/node": "^22.0.0",
|
|
37
|
+
"bun-types": "^1.3.9",
|
|
38
|
+
"eslint": "^9.30.1",
|
|
39
|
+
"globals": "^17.3.0",
|
|
40
|
+
"prettier": "^3.6.2",
|
|
41
|
+
"rimraf": "^6.0.1",
|
|
42
|
+
"typescript": "^5.9.3",
|
|
43
|
+
"typescript-eslint": "^8.56.0"
|
|
44
|
+
},
|
|
45
|
+
"peerDependencies": {
|
|
46
|
+
"@vibecontrols/agent": ">=2026.428.0"
|
|
47
|
+
},
|
|
48
|
+
"peerDependenciesMeta": {
|
|
49
|
+
"@vibecontrols/agent": {
|
|
50
|
+
"optional": true
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"keywords": [
|
|
54
|
+
"vibecontrols",
|
|
55
|
+
"vibe",
|
|
56
|
+
"vibe-plugin",
|
|
57
|
+
"security",
|
|
58
|
+
"opa",
|
|
59
|
+
"rego",
|
|
60
|
+
"release-gate",
|
|
61
|
+
"promote-prod",
|
|
62
|
+
"policy",
|
|
63
|
+
"bun"
|
|
64
|
+
],
|
|
65
|
+
"repository": {
|
|
66
|
+
"type": "git",
|
|
67
|
+
"url": "git+https://github.com/algoshred/vibe-plugin-security-release-gate.git"
|
|
68
|
+
},
|
|
69
|
+
"bugs": {
|
|
70
|
+
"url": "https://github.com/algoshred/vibe-plugin-security-release-gate/issues"
|
|
71
|
+
},
|
|
72
|
+
"homepage": "https://vibecontrols.com",
|
|
73
|
+
"publishConfig": {
|
|
74
|
+
"access": "public",
|
|
75
|
+
"registry": "https://registry.npmjs.org/"
|
|
76
|
+
},
|
|
77
|
+
"files": [
|
|
78
|
+
"dist/**/*",
|
|
79
|
+
"!dist/**/*.map",
|
|
80
|
+
"README.md",
|
|
81
|
+
"LICENSE"
|
|
82
|
+
]
|
|
83
|
+
}
|