@kinkai.cloud/vibecheck 0.3.0 → 0.3.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/README.md +2 -2
- package/dist/cli.js +51 -14
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ export PATH="$PWD/.tools/vibecheck/bin:$PATH"
|
|
|
16
16
|
```
|
|
17
17
|
|
|
18
18
|
3. Gere seus relatórios com o runner de testes habitual. Configure os caminhos existentes em `coverage`, `junit` e `sarif` no JSON. Não adicione um relatório que seu projeto não gera. Formatos de cobertura: `lcov`, `cobertura`, `jacoco`.
|
|
19
|
-
4. Analise localmente: `npx vibecheck analyze`. Para publicar, configure `VIBECHECK_PROJECT_TOKEN` como variável de ambiente ou segredo do CI e execute `npx vibecheck analyze --publish`.
|
|
19
|
+
4. Analise localmente: `npx vibecheck analyze`. Para publicar, configure `VIBECHECK_PROJECT_TOKEN` como variável de ambiente, em um arquivo `.env` na raiz do repositório, ou como segredo do CI, e execute `npx vibecheck analyze --publish`. O CLI carrega `.env` localmente quando a variável ainda não está definida no ambiente; nunca publica o arquivo.
|
|
20
20
|
|
|
21
21
|
O CLI não roda testes arbitrários. Código-fonte completo e valores de segredos permanecem locais. Relatórios sanitizados ficam em `.vibecheck/analysis.json` e `.vibecheck/analysis.sarif`. Adicione `.tools/` e `.vibecheck/` ao `.gitignore`.
|
|
22
22
|
|
|
@@ -33,7 +33,7 @@ No painel: **Achados** para correções, **Mapa** para arquivos, **Dependências
|
|
|
33
33
|
1. Create a project at https://vibecheck.kinkai.cloud/projects. Copy its configuration and generate a project token in Settings.
|
|
34
34
|
2. Install the CLI and engines using the commands above on Linux x64 or WSL, with Python 3 and venv. Versions are pinned; OSV/Gitleaks binaries are checksum verified. npm does not install engines automatically.
|
|
35
35
|
3. Generate reports using your usual test runner. Configure existing coverage (`lcov`, `cobertura`, `jacoco`), JUnit and SARIF paths. The CLI does not run arbitrary tests.
|
|
36
|
-
4. Run `npx vibecheck analyze`. To upload sanitized results, set `VIBECHECK_PROJECT_TOKEN` in your environment or CI secret store, then run `npx vibecheck analyze --publish`.
|
|
36
|
+
4. Run `npx vibecheck analyze`. To upload sanitized results, set `VIBECHECK_PROJECT_TOKEN` in your environment, in a `.env` file at the repository root, or in your CI secret store, then run `npx vibecheck analyze --publish`. The CLI loads `.env` locally only when the variable is not already set; it never uploads that file.
|
|
37
37
|
|
|
38
38
|
Publish the reference branch first. Without a comparable merge-base analysis, the gate is inconclusive. Exit codes: 0 pass, 1 fail, 2 inconclusive, 3 operational error. Default policy blocks new high/critical risks and secrets, and requires 80% coverage of new executable lines. Missing required evidence never means pass.
|
|
39
39
|
|
package/dist/cli.js
CHANGED
|
@@ -6,7 +6,7 @@ var __export = (target, all2) => {
|
|
|
6
6
|
};
|
|
7
7
|
|
|
8
8
|
// src/analyze.ts
|
|
9
|
-
import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync2, existsSync, lstatSync as lstatSync2 } from "fs";
|
|
9
|
+
import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync2, existsSync, lstatSync as lstatSync2, readFileSync as readFileSync3 } from "fs";
|
|
10
10
|
import { resolve as resolve2, join as join3 } from "path";
|
|
11
11
|
|
|
12
12
|
// ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/external.js
|
|
@@ -17693,6 +17693,20 @@ var configSchema = external_exports.object({
|
|
|
17693
17693
|
junit: external_exports.array(external_exports.string()).default([]),
|
|
17694
17694
|
sarif: external_exports.array(external_exports.string()).default([])
|
|
17695
17695
|
}).strict();
|
|
17696
|
+
function loadLocalEnv(root) {
|
|
17697
|
+
const file2 = join3(root, ".env");
|
|
17698
|
+
if (!existsSync(file2) || lstatSync2(file2).isSymbolicLink() || !lstatSync2(file2).isFile())
|
|
17699
|
+
return;
|
|
17700
|
+
for (const line of readFileSync3(file2, "utf8").split(/\r?\n/)) {
|
|
17701
|
+
const match = line.match(/^\s*(?:export\s+)?([A-Z_][A-Z0-9_]*)\s*=\s*(.*?)\s*$/);
|
|
17702
|
+
const key = match?.[1];
|
|
17703
|
+
if (!match || !key || process.env[key] !== void 0) continue;
|
|
17704
|
+
let value = match[2];
|
|
17705
|
+
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'"))
|
|
17706
|
+
value = value.slice(1, -1);
|
|
17707
|
+
process.env[key] = value;
|
|
17708
|
+
}
|
|
17709
|
+
}
|
|
17696
17710
|
async function analyzeCommand(argv) {
|
|
17697
17711
|
if (argv.includes("--help")) {
|
|
17698
17712
|
console.warn(
|
|
@@ -17705,14 +17719,37 @@ async function analyzeCommand(argv) {
|
|
|
17705
17719
|
return i < 0 ? void 0 : argv[i + 1];
|
|
17706
17720
|
};
|
|
17707
17721
|
const root = resolve2(value("--dir") ?? process.cwd()), configPath = value("--config") ?? "vibecheck.config.json";
|
|
17708
|
-
|
|
17722
|
+
loadLocalEnv(root);
|
|
17723
|
+
const token = process.env["VIBECHECK_PROJECT_TOKEN"], base = process.env["VIBECHECK_URL"] ?? "https://vibecheck.kinkai.cloud";
|
|
17724
|
+
let config2;
|
|
17725
|
+
if (existsSync(join3(root, configPath))) {
|
|
17726
|
+
config2 = configSchema.parse(JSON.parse(localFile(root, configPath)));
|
|
17727
|
+
} else if (argv.includes("--publish") && token) {
|
|
17728
|
+
const response = await fetch(new URL("/api/projects", base), {
|
|
17729
|
+
headers: { authorization: "Bearer " + token },
|
|
17730
|
+
signal: AbortSignal.timeout(3e4)
|
|
17731
|
+
});
|
|
17732
|
+
if (!response.ok) throw new Error("Project token rejected while discovering project");
|
|
17733
|
+
const project = external_exports.object({ id: external_exports.string().uuid(), reference: external_exports.string() }).parse(await response.json());
|
|
17734
|
+
config2 = {
|
|
17735
|
+
version: 2,
|
|
17736
|
+
projectId: project.id,
|
|
17737
|
+
reference: project.reference,
|
|
17738
|
+
baseline: void 0,
|
|
17739
|
+
coverage: [],
|
|
17740
|
+
junit: [],
|
|
17741
|
+
sarif: []
|
|
17742
|
+
};
|
|
17743
|
+
console.warn(
|
|
17744
|
+
"No vibecheck.config.json found; using project settings discovered from the token."
|
|
17745
|
+
);
|
|
17746
|
+
} else {
|
|
17709
17747
|
throw new Error(
|
|
17710
|
-
"Create vibecheck.config.json
|
|
17748
|
+
"Create vibecheck.config.json, or set VIBECHECK_PROJECT_TOKEN and use --publish to discover the project automatically."
|
|
17711
17749
|
);
|
|
17712
|
-
|
|
17750
|
+
}
|
|
17713
17751
|
let baseline = config2.baseline ? analysisReportSchema.parse(JSON.parse(localFile(root, config2.baseline))) : null;
|
|
17714
17752
|
let report = await analyze({ root, ...config2, baseline });
|
|
17715
|
-
const token = process.env["VIBECHECK_PROJECT_TOKEN"], base = process.env["VIBECHECK_URL"] ?? "https://vibecheck.kinkai.cloud";
|
|
17716
17753
|
const url2 = new URL(base);
|
|
17717
17754
|
if (url2.protocol !== "https:" && !["localhost", "127.0.0.1"].includes(url2.hostname))
|
|
17718
17755
|
throw new Error("Use HTTPS for project uploads");
|
|
@@ -18644,12 +18681,12 @@ var sequencedScanEventSchema = external_exports.intersection(
|
|
|
18644
18681
|
);
|
|
18645
18682
|
|
|
18646
18683
|
// src/consent.ts
|
|
18647
|
-
import { chmodSync as chmodSync2, mkdirSync as mkdirSync4, readFileSync as
|
|
18684
|
+
import { chmodSync as chmodSync2, mkdirSync as mkdirSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "fs";
|
|
18648
18685
|
import { createInterface } from "readline/promises";
|
|
18649
18686
|
import { join as join5, resolve as resolve3 } from "path";
|
|
18650
18687
|
|
|
18651
18688
|
// src/token.ts
|
|
18652
|
-
import { chmodSync, mkdirSync as mkdirSync3, readFileSync as
|
|
18689
|
+
import { chmodSync, mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "fs";
|
|
18653
18690
|
import { homedir } from "os";
|
|
18654
18691
|
import { join as join4 } from "path";
|
|
18655
18692
|
function dirConfig() {
|
|
@@ -18665,7 +18702,7 @@ function lerToken() {
|
|
|
18665
18702
|
return { token: env, host: hostEnv ?? "" };
|
|
18666
18703
|
}
|
|
18667
18704
|
try {
|
|
18668
|
-
const bruto =
|
|
18705
|
+
const bruto = readFileSync4(caminhoToken(), "utf8").trim();
|
|
18669
18706
|
const [token, host] = bruto.split("\n");
|
|
18670
18707
|
if (token === void 0 || token.length === 0) return null;
|
|
18671
18708
|
return { token, host: host ?? "" };
|
|
@@ -18694,7 +18731,7 @@ function repoKey(dir) {
|
|
|
18694
18731
|
}
|
|
18695
18732
|
function listarConsentimentos(deps = {}) {
|
|
18696
18733
|
try {
|
|
18697
|
-
const bruto = JSON.parse(
|
|
18734
|
+
const bruto = JSON.parse(readFileSync5(caminho(deps), "utf8"));
|
|
18698
18735
|
if (!Array.isArray(bruto)) return [];
|
|
18699
18736
|
return bruto.filter(
|
|
18700
18737
|
(e) => e !== null && typeof e === "object" && typeof e.repo === "string" && typeof e.acceptedAt === "string"
|
|
@@ -19077,7 +19114,7 @@ async function loginDevice(ci, options = {}) {
|
|
|
19077
19114
|
|
|
19078
19115
|
// src/repo.ts
|
|
19079
19116
|
import { execFileSync } from "child_process";
|
|
19080
|
-
import { lstatSync as lstatSync3, readdirSync as readdirSync2, readFileSync as
|
|
19117
|
+
import { lstatSync as lstatSync3, readdirSync as readdirSync2, readFileSync as readFileSync6 } from "fs";
|
|
19081
19118
|
import { join as join8, relative as relative2 } from "path";
|
|
19082
19119
|
var MAX_FILES = 800;
|
|
19083
19120
|
var MAX_BYTES2 = 64e3;
|
|
@@ -19140,7 +19177,7 @@ function readCodeContext(dir) {
|
|
|
19140
19177
|
try {
|
|
19141
19178
|
const st = lstatSync3(join8(dir, path));
|
|
19142
19179
|
if (st.size > (path.endsWith(".sql") ? MAX_SQL_BYTES : MAX_BYTES2)) continue;
|
|
19143
|
-
files.push({ path, content:
|
|
19180
|
+
files.push({ path, content: readFileSync6(join8(dir, path), "utf8") });
|
|
19144
19181
|
} catch {
|
|
19145
19182
|
}
|
|
19146
19183
|
}
|
|
@@ -19194,7 +19231,7 @@ function toSarif(report, version2) {
|
|
|
19194
19231
|
}
|
|
19195
19232
|
|
|
19196
19233
|
// src/walker.ts
|
|
19197
|
-
import { lstatSync as lstatSync4, readdirSync as readdirSync3, readFileSync as
|
|
19234
|
+
import { lstatSync as lstatSync4, readdirSync as readdirSync3, readFileSync as readFileSync7 } from "fs";
|
|
19198
19235
|
import { join as join9, relative as relative3 } from "path";
|
|
19199
19236
|
var IGNORAR = /* @__PURE__ */ new Set([
|
|
19200
19237
|
"node_modules",
|
|
@@ -19339,7 +19376,7 @@ function lerArquivo(raiz, cheio) {
|
|
|
19339
19376
|
const rel = posixRel(raiz, cheio);
|
|
19340
19377
|
let conteudo = "";
|
|
19341
19378
|
try {
|
|
19342
|
-
conteudo =
|
|
19379
|
+
conteudo = readFileSync7(cheio, "utf8").slice(0, MAX_BYTES_ARQUIVO);
|
|
19343
19380
|
} catch {
|
|
19344
19381
|
return null;
|
|
19345
19382
|
}
|
|
@@ -19461,7 +19498,7 @@ function isAdvancedScan(grafo) {
|
|
|
19461
19498
|
}
|
|
19462
19499
|
|
|
19463
19500
|
// src/cli.ts
|
|
19464
|
-
var VERSION = "0.3.
|
|
19501
|
+
var VERSION = "0.3.1";
|
|
19465
19502
|
var AJUDA = `vibecheck \u2014 security check for AI-built apps
|
|
19466
19503
|
|
|
19467
19504
|
npx @kinkai.cloud/vibecheck [options]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kinkai.cloud/vibecheck",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
"zod": "^4",
|
|
26
26
|
"@vibecheck/checks": "0.0.0",
|
|
27
27
|
"@vibecheck/graph": "0.0.0",
|
|
28
|
-
"@vibecheck/
|
|
29
|
-
"@vibecheck/
|
|
28
|
+
"@vibecheck/analysis": "0.0.0",
|
|
29
|
+
"@vibecheck/schema": "0.0.0"
|
|
30
30
|
},
|
|
31
31
|
"exports": {
|
|
32
32
|
"./login": "./src/login.ts",
|