@codacy/verity-cli 0.25.0-experimental.e3da48a → 0.25.0-experimental.ed0c319
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/bin/verity.js +172 -63
- package/data/skills/verity-analyze/SKILL.md +7 -1
- package/data/skills/verity-setup/SKILL.md +49 -17
- package/package.json +1 -1
package/bin/verity.js
CHANGED
|
@@ -10325,9 +10325,7 @@ var {
|
|
|
10325
10325
|
} = import_index.default;
|
|
10326
10326
|
|
|
10327
10327
|
// src/commands/auth.ts
|
|
10328
|
-
var import_promises3 = require("node:fs/promises");
|
|
10329
10328
|
var import_node_child_process4 = require("node:child_process");
|
|
10330
|
-
var import_node_path3 = require("node:path");
|
|
10331
10329
|
|
|
10332
10330
|
// src/lib/auth.ts
|
|
10333
10331
|
var import_promises = require("node:fs/promises");
|
|
@@ -10748,6 +10746,10 @@ function analyzeRequest(options) {
|
|
|
10748
10746
|
});
|
|
10749
10747
|
}
|
|
10750
10748
|
|
|
10749
|
+
// src/lib/register.ts
|
|
10750
|
+
var import_promises3 = require("node:fs/promises");
|
|
10751
|
+
var import_node_path3 = require("node:path");
|
|
10752
|
+
|
|
10751
10753
|
// src/lib/provider-auth.ts
|
|
10752
10754
|
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
10753
10755
|
var form = (fields) => new URLSearchParams(fields).toString();
|
|
@@ -11003,8 +11005,8 @@ function filterReviewable(files) {
|
|
|
11003
11005
|
const ext = (0, import_node_path2.extname)(f).slice(1);
|
|
11004
11006
|
if (ANALYZABLE_EXTENSIONS.has(ext)) return false;
|
|
11005
11007
|
if (REVIEWABLE_EXTENSIONS.has(ext)) return true;
|
|
11006
|
-
const
|
|
11007
|
-
if (REVIEWABLE_FILENAMES.has(
|
|
11008
|
+
const basename3 = f.split("/").pop() ?? "";
|
|
11009
|
+
if (REVIEWABLE_FILENAMES.has(basename3)) return true;
|
|
11008
11010
|
if (REVIEWABLE_PATH_PATTERNS.some((p) => p.test(f))) return true;
|
|
11009
11011
|
return false;
|
|
11010
11012
|
});
|
|
@@ -11066,6 +11068,66 @@ function listTrackedFiles() {
|
|
|
11066
11068
|
return Array.from(set);
|
|
11067
11069
|
}
|
|
11068
11070
|
|
|
11071
|
+
// src/lib/register.ts
|
|
11072
|
+
async function registerProject(opts) {
|
|
11073
|
+
const parsed = parseRemote(opts.remote);
|
|
11074
|
+
if (!parsed) {
|
|
11075
|
+
return { ok: false, error: `Could not parse git remote: ${opts.remote}` };
|
|
11076
|
+
}
|
|
11077
|
+
if (parsed.provider !== "github") {
|
|
11078
|
+
return { ok: false, error: `Provider '${parsed.provider}' is not supported yet \u2014 GitHub only for now.` };
|
|
11079
|
+
}
|
|
11080
|
+
const providerAuth = await githubDeviceFlow();
|
|
11081
|
+
if (!providerAuth.ok) {
|
|
11082
|
+
return { ok: false, error: providerAuth.error };
|
|
11083
|
+
}
|
|
11084
|
+
const providerToken = providerAuth.data;
|
|
11085
|
+
const result = await apiRequest({
|
|
11086
|
+
method: "POST",
|
|
11087
|
+
path: "/auth/register",
|
|
11088
|
+
serviceUrl: opts.serviceUrl,
|
|
11089
|
+
body: { project_name: opts.projectName, git_remote_url: opts.remote },
|
|
11090
|
+
extraHeaders: { "X-Provider-Token": providerToken },
|
|
11091
|
+
verbose: opts.verbose
|
|
11092
|
+
});
|
|
11093
|
+
if (!result.ok) {
|
|
11094
|
+
return { ok: false, error: result.error };
|
|
11095
|
+
}
|
|
11096
|
+
const { project_id, token, service_url, user } = result.data;
|
|
11097
|
+
try {
|
|
11098
|
+
await (0, import_promises3.mkdir)(VERITY_DIR, { recursive: true });
|
|
11099
|
+
await (0, import_promises3.writeFile)(
|
|
11100
|
+
CREDENTIALS_FILE,
|
|
11101
|
+
`token: ${token}
|
|
11102
|
+
service_url: ${service_url}
|
|
11103
|
+
provider_token: ${providerToken}
|
|
11104
|
+
`,
|
|
11105
|
+
{ mode: 384 }
|
|
11106
|
+
);
|
|
11107
|
+
await (0, import_promises3.chmod)(CREDENTIALS_FILE, 384).catch(() => {
|
|
11108
|
+
});
|
|
11109
|
+
} catch (err) {
|
|
11110
|
+
return {
|
|
11111
|
+
ok: false,
|
|
11112
|
+
error: `Registered with the Verity service, but could not save credentials to ${CREDENTIALS_FILE}: ${err.message}. Check filesystem permissions and re-run "verity auth register".`
|
|
11113
|
+
};
|
|
11114
|
+
}
|
|
11115
|
+
try {
|
|
11116
|
+
await (0, import_promises3.mkdir)((0, import_node_path3.dirname)(GLOBAL_CREDENTIALS_FILE), { recursive: true });
|
|
11117
|
+
await (0, import_promises3.appendFile)(
|
|
11118
|
+
GLOBAL_CREDENTIALS_FILE,
|
|
11119
|
+
`${opts.remote} token: ${token}
|
|
11120
|
+
${opts.remote} provider_token: ${providerToken}
|
|
11121
|
+
`,
|
|
11122
|
+
{ mode: 384 }
|
|
11123
|
+
);
|
|
11124
|
+
await (0, import_promises3.chmod)(GLOBAL_CREDENTIALS_FILE, 384).catch(() => {
|
|
11125
|
+
});
|
|
11126
|
+
} catch {
|
|
11127
|
+
}
|
|
11128
|
+
return { ok: true, data: { projectId: project_id, serviceUrl: service_url, email: user?.email } };
|
|
11129
|
+
}
|
|
11130
|
+
|
|
11069
11131
|
// src/commands/auth.ts
|
|
11070
11132
|
function registerAuthCommands(program2) {
|
|
11071
11133
|
const auth = program2.command("auth").description("Manage project authentication");
|
|
@@ -11081,60 +11143,20 @@ function registerAuthCommands(program2) {
|
|
|
11081
11143
|
process.exit(1);
|
|
11082
11144
|
}
|
|
11083
11145
|
}
|
|
11084
|
-
const
|
|
11085
|
-
|
|
11086
|
-
|
|
11087
|
-
process.exit(1);
|
|
11088
|
-
}
|
|
11089
|
-
if (parsed.provider !== "github") {
|
|
11090
|
-
printError(`Provider '${parsed.provider}' is not supported yet \u2014 GitHub only for now.`);
|
|
11091
|
-
process.exit(1);
|
|
11092
|
-
}
|
|
11093
|
-
const providerAuth = await githubDeviceFlow();
|
|
11094
|
-
if (!providerAuth.ok) {
|
|
11095
|
-
printError(providerAuth.error);
|
|
11096
|
-
process.exit(1);
|
|
11097
|
-
}
|
|
11098
|
-
const providerToken = providerAuth.data;
|
|
11099
|
-
const result = await apiRequest({
|
|
11100
|
-
method: "POST",
|
|
11101
|
-
path: "/auth/register",
|
|
11146
|
+
const result = await registerProject({
|
|
11147
|
+
projectName: opts.project,
|
|
11148
|
+
remote,
|
|
11102
11149
|
serviceUrl,
|
|
11103
|
-
body: { project_name: opts.project, git_remote_url: remote },
|
|
11104
|
-
extraHeaders: { "X-Provider-Token": providerToken },
|
|
11105
11150
|
verbose: globals.verbose
|
|
11106
11151
|
});
|
|
11107
11152
|
if (!result.ok) {
|
|
11108
11153
|
printError(result.error);
|
|
11109
11154
|
process.exit(1);
|
|
11110
11155
|
}
|
|
11111
|
-
const {
|
|
11112
|
-
|
|
11113
|
-
|
|
11114
|
-
|
|
11115
|
-
`token: ${token}
|
|
11116
|
-
service_url: ${service_url}
|
|
11117
|
-
provider_token: ${providerToken}
|
|
11118
|
-
`,
|
|
11119
|
-
{ mode: 384 }
|
|
11120
|
-
);
|
|
11121
|
-
await (0, import_promises3.chmod)(CREDENTIALS_FILE, 384).catch(() => {
|
|
11122
|
-
});
|
|
11123
|
-
try {
|
|
11124
|
-
await (0, import_promises3.mkdir)((0, import_node_path3.dirname)(GLOBAL_CREDENTIALS_FILE), { recursive: true });
|
|
11125
|
-
await (0, import_promises3.appendFile)(
|
|
11126
|
-
GLOBAL_CREDENTIALS_FILE,
|
|
11127
|
-
`${remote} token: ${token}
|
|
11128
|
-
${remote} provider_token: ${providerToken}
|
|
11129
|
-
`
|
|
11130
|
-
);
|
|
11131
|
-
await (0, import_promises3.chmod)(GLOBAL_CREDENTIALS_FILE, 384).catch(() => {
|
|
11132
|
-
});
|
|
11133
|
-
} catch {
|
|
11134
|
-
}
|
|
11135
|
-
printInfo(`Project registered: ${project_id}`);
|
|
11136
|
-
if (user?.email) printInfo(`Authenticated as: ${user.email}`);
|
|
11137
|
-
printJson({ project_id, service_url });
|
|
11156
|
+
const { projectId, serviceUrl: resolvedUrl, email } = result.data;
|
|
11157
|
+
printInfo(`Project registered: ${projectId}`);
|
|
11158
|
+
if (email) printInfo(`Authenticated as: ${email}`);
|
|
11159
|
+
printJson({ project_id: projectId, service_url: resolvedUrl });
|
|
11138
11160
|
});
|
|
11139
11161
|
auth.command("verify").description("Verify the current token is valid").action(async () => {
|
|
11140
11162
|
const globals = program2.opts();
|
|
@@ -14733,6 +14755,27 @@ function passAndExit(reason) {
|
|
|
14733
14755
|
printJsonCompact({ gate_decision: "PASS", systemMessage: `Verity: ${reason}` });
|
|
14734
14756
|
process.exit(0);
|
|
14735
14757
|
}
|
|
14758
|
+
var EMPTY_STATIC = {
|
|
14759
|
+
tool: "@codacy/analysis-cli",
|
|
14760
|
+
findings: [],
|
|
14761
|
+
summary: { total_findings: 0, by_severity: {}, tools_run: [] }
|
|
14762
|
+
};
|
|
14763
|
+
function runLocalStatic(analyzable, securityFiles, baseline, skipStatic) {
|
|
14764
|
+
if (skipStatic || !isCodacyAvailable()) return EMPTY_STATIC;
|
|
14765
|
+
let scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles]));
|
|
14766
|
+
if (baseline) scannable = scannable.filter((f) => changedSinceBaseline(f, baseline));
|
|
14767
|
+
if (scannable.length === 0) return EMPTY_STATIC;
|
|
14768
|
+
return runCodacyAnalysis(scannable);
|
|
14769
|
+
}
|
|
14770
|
+
function localOnlyAndExit(staticResults) {
|
|
14771
|
+
printJsonCompact({
|
|
14772
|
+
gate_decision: "PASS",
|
|
14773
|
+
systemMessage: "Verity: not authenticated \u2014 ran a local static-only check (no deep review, no upload). Run `verity init` to authenticate and enable the full quality gate.",
|
|
14774
|
+
unauthenticated: true,
|
|
14775
|
+
static_results: staticResults
|
|
14776
|
+
});
|
|
14777
|
+
process.exit(0);
|
|
14778
|
+
}
|
|
14736
14779
|
function registerAnalyzeCommand(program2) {
|
|
14737
14780
|
program2.command("analyze").description("Run Verity analysis on changed files (stop hook)").option("--debounce <seconds>", "Skip if last analysis was within N seconds", "30").option("--max-iterations <n>", "Force PASS after N FAIL cycles", "2").option("--max-files <n>", "Max files to send for review", "20").option("--max-file-size <bytes>", "Skip files larger than N bytes", "51200").option("--max-total-size <bytes>", "Stop collecting files at N total bytes", "194560").option("--skip-static", "Skip codacy-analysis").option("--mode <mode>", "Force analysis mode (standard|plan|debug|skip)").option("--json", "Output raw JSON response").action(async (opts) => {
|
|
14738
14781
|
const globals = program2.opts();
|
|
@@ -14783,12 +14826,9 @@ async function runAnalyze(opts, globals) {
|
|
|
14783
14826
|
passAndExit("Reflection-prompt turn \u2014 skipping analysis");
|
|
14784
14827
|
}
|
|
14785
14828
|
const tokenResult = await resolveToken(globals.token);
|
|
14786
|
-
if (!tokenResult.ok) {
|
|
14787
|
-
passAndExit("Not configured yet \u2014 run /verity-setup in Claude Code to enable quality gates.");
|
|
14788
|
-
}
|
|
14789
14829
|
const urlResult = await resolveServiceUrl(globals.serviceUrl);
|
|
14790
|
-
if (!urlResult.ok) {
|
|
14791
|
-
|
|
14830
|
+
if (!tokenResult.ok || !urlResult.ok) {
|
|
14831
|
+
localOnlyAndExit(runLocalStatic(analyzable, securityFiles, baseline, !!opts.skipStatic));
|
|
14792
14832
|
}
|
|
14793
14833
|
const sessionIdForMemory = sessionId || process.env.CLAUDE_SESSION_ID || "";
|
|
14794
14834
|
let contextFilePaths = [];
|
|
@@ -15362,13 +15402,14 @@ async function runReview(opts, globals) {
|
|
|
15362
15402
|
}
|
|
15363
15403
|
const codeDelta = collectCodeDelta(allFiles);
|
|
15364
15404
|
const tokenResult = await resolveToken(globals.token);
|
|
15365
|
-
if (!tokenResult.ok) {
|
|
15366
|
-
printError("Not configured yet \u2014 run /verity-setup in Claude Code to enable quality gates.");
|
|
15367
|
-
process.exit(0);
|
|
15368
|
-
}
|
|
15369
15405
|
const urlResult = await resolveServiceUrl(globals.serviceUrl);
|
|
15370
|
-
if (!urlResult.ok) {
|
|
15371
|
-
|
|
15406
|
+
if (!tokenResult.ok || !urlResult.ok) {
|
|
15407
|
+
printJsonCompact({
|
|
15408
|
+
gate_decision: "PASS",
|
|
15409
|
+
systemMessage: "Verity: not authenticated \u2014 showing local static results only (no deep review, no upload). Run `verity init` to authenticate and unlock the full review.",
|
|
15410
|
+
unauthenticated: true,
|
|
15411
|
+
static_results: staticResults
|
|
15412
|
+
});
|
|
15372
15413
|
process.exit(0);
|
|
15373
15414
|
}
|
|
15374
15415
|
let specs;
|
|
@@ -15757,6 +15798,7 @@ var import_node_fs24 = require("node:fs");
|
|
|
15757
15798
|
var import_promises12 = require("node:fs/promises");
|
|
15758
15799
|
var import_node_path17 = require("node:path");
|
|
15759
15800
|
var import_node_child_process9 = require("node:child_process");
|
|
15801
|
+
var readline = __toESM(require("node:readline/promises"));
|
|
15760
15802
|
|
|
15761
15803
|
// src/commands/migrate.ts
|
|
15762
15804
|
var import_node_fs23 = require("node:fs");
|
|
@@ -16036,6 +16078,66 @@ function registerMigrateCommand(program2) {
|
|
|
16036
16078
|
}
|
|
16037
16079
|
|
|
16038
16080
|
// src/commands/init.ts
|
|
16081
|
+
async function promptYes(question) {
|
|
16082
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) return false;
|
|
16083
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
16084
|
+
try {
|
|
16085
|
+
const answer = (await rl.question(question)).trim().toLowerCase();
|
|
16086
|
+
return answer === "" || answer === "y" || answer === "yes";
|
|
16087
|
+
} finally {
|
|
16088
|
+
rl.close();
|
|
16089
|
+
}
|
|
16090
|
+
}
|
|
16091
|
+
async function runOptionalAuth() {
|
|
16092
|
+
const existing = await resolveToken();
|
|
16093
|
+
if (existing.ok) {
|
|
16094
|
+
printInfo("Already authenticated \u2014 results will upload to the Verity service. \u2713");
|
|
16095
|
+
return;
|
|
16096
|
+
}
|
|
16097
|
+
let remote = "";
|
|
16098
|
+
try {
|
|
16099
|
+
remote = (0, import_node_child_process9.execSync)("git remote get-url origin", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
16100
|
+
} catch {
|
|
16101
|
+
}
|
|
16102
|
+
const localOnlyNote = () => {
|
|
16103
|
+
printInfo("Verity runs in local-only mode: the gate still runs and shows static findings, but nothing uploads.");
|
|
16104
|
+
printInfo(' Authenticate anytime: run "verity init" again, or "verity auth register".');
|
|
16105
|
+
};
|
|
16106
|
+
if (process.stdin.isTTY && process.stdout.isTTY) {
|
|
16107
|
+
console.log("");
|
|
16108
|
+
console.log(" Signing in is optional. What it does:");
|
|
16109
|
+
console.log(" - Confirms you have write access to this repository. The GitHub token");
|
|
16110
|
+
console.log(" is used once to verify that, then discarded \u2014 Verity never stores it.");
|
|
16111
|
+
console.log(" - It does NOT give Verity access to your code. Code checked by the gate");
|
|
16112
|
+
console.log(" is analyzed in memory and discarded \u2014 we never store your code.");
|
|
16113
|
+
console.log(" - It is required to store and access run history for this repo");
|
|
16114
|
+
console.log(" (past results, trends, and shareable reports).");
|
|
16115
|
+
console.log(" - Skip and Verity still works fully locally: the gate runs and shows");
|
|
16116
|
+
console.log(" findings, but nothing is uploaded.");
|
|
16117
|
+
console.log("");
|
|
16118
|
+
}
|
|
16119
|
+
const wantsAuth = await promptYes("Authenticate with GitHub now to upload results to Verity? [Y/skip] ");
|
|
16120
|
+
if (!wantsAuth) {
|
|
16121
|
+
printInfo("Skipped authentication.");
|
|
16122
|
+
localOnlyNote();
|
|
16123
|
+
return;
|
|
16124
|
+
}
|
|
16125
|
+
if (!remote) {
|
|
16126
|
+
printWarn("No git remote found \u2014 cannot authenticate yet.");
|
|
16127
|
+
localOnlyNote();
|
|
16128
|
+
return;
|
|
16129
|
+
}
|
|
16130
|
+
const projectName = parseRemote(remote)?.repo ?? (0, import_node_path17.basename)(process.cwd());
|
|
16131
|
+
printInfo("Authenticating with GitHub\u2026");
|
|
16132
|
+
const result = await registerProject({ projectName, remote, serviceUrl: DEFAULT_SERVICE_URL });
|
|
16133
|
+
if (result.ok) {
|
|
16134
|
+
printInfo(`Project registered: ${result.data.projectId} \u2713`);
|
|
16135
|
+
if (result.data.email) printInfo(` Authenticated as: ${result.data.email}`);
|
|
16136
|
+
} else {
|
|
16137
|
+
printWarn(`Authentication did not complete: ${result.error}`);
|
|
16138
|
+
localOnlyNote();
|
|
16139
|
+
}
|
|
16140
|
+
}
|
|
16039
16141
|
function resolveDataDir() {
|
|
16040
16142
|
const candidates = [
|
|
16041
16143
|
(0, import_node_path17.join)(__dirname, "..", "data"),
|
|
@@ -16179,6 +16281,12 @@ function registerInitCommand(program2) {
|
|
|
16179
16281
|
const globalVerityDir = (0, import_node_path17.join)(process.env.HOME ?? "", ".verity");
|
|
16180
16282
|
await (0, import_promises12.mkdir)(globalVerityDir, { recursive: true });
|
|
16181
16283
|
console.log("");
|
|
16284
|
+
try {
|
|
16285
|
+
await runOptionalAuth();
|
|
16286
|
+
} catch (err) {
|
|
16287
|
+
printWarn(`Authentication step skipped: ${err.message}`);
|
|
16288
|
+
}
|
|
16289
|
+
console.log("");
|
|
16182
16290
|
printInfo("Verity initialized!");
|
|
16183
16291
|
console.log("");
|
|
16184
16292
|
console.log(" Installed:");
|
|
@@ -16194,6 +16302,7 @@ function registerInitCommand(program2) {
|
|
|
16194
16302
|
console.log(" .verity/memory/ \u2014 knowledge base (8 domains, commit to git)");
|
|
16195
16303
|
console.log("");
|
|
16196
16304
|
console.log(" Next step: open this project in Claude Code and run /verity-setup");
|
|
16305
|
+
console.log(' (Not authenticated? Verity runs in local-only mode until you run "verity auth register".)');
|
|
16197
16306
|
console.log("");
|
|
16198
16307
|
});
|
|
16199
16308
|
}
|
|
@@ -16925,7 +17034,7 @@ function registerTelemetryCommands(program2) {
|
|
|
16925
17034
|
}
|
|
16926
17035
|
|
|
16927
17036
|
// src/cli.ts
|
|
16928
|
-
program.name("verity").description("CLI for Verity quality gate service").version("0.25.0-experimental.
|
|
17037
|
+
program.name("verity").description("CLI for Verity quality gate service").version("0.25.0-experimental.ed0c319").option("--token <token>", "Override authentication token").option("--service-url <url>", "Override service URL").option("--verbose", "Log HTTP requests/responses to stderr");
|
|
16929
17038
|
registerAuthCommands(program);
|
|
16930
17039
|
registerHooksCommands(program);
|
|
16931
17040
|
registerIntentCommands(program);
|
|
@@ -15,7 +15,13 @@ You are running an on-demand Verity analysis. This is like a "second opinion"
|
|
|
15
15
|
|
|
16
16
|
1. Verify `.verity/standard.yaml` exists. If not: "Run `/verity-setup` first."
|
|
17
17
|
2. Verify `verity` CLI is available: `which verity`. If not: "Re-run the Verity installer: `curl -fsSL https://raw.githubusercontent.com/codacy/verity/main/install.sh | bash`"
|
|
18
|
-
3. Run `verity auth verify` to check token is valid.
|
|
18
|
+
3. Run `verity auth verify` to check the token is valid.
|
|
19
|
+
- **Valid**: proceed with the full deep review.
|
|
20
|
+
- **Fails / not authenticated**: don't stop. Tell the user Verity is in
|
|
21
|
+
**local-only mode**, so the review will run static analysis and show findings
|
|
22
|
+
but won't perform the deep (LLM) review or upload anything. To unlock the deep
|
|
23
|
+
review they can authenticate with `verity init` (or `verity auth register`).
|
|
24
|
+
Continue — `verity review` degrades to a local static-only report on its own.
|
|
19
25
|
|
|
20
26
|
---
|
|
21
27
|
|
|
@@ -310,32 +310,60 @@ Expected: single-digit findings per file, not hundreds. If you see 50+ issues fr
|
|
|
310
310
|
|
|
311
311
|
---
|
|
312
312
|
|
|
313
|
-
## Step 6:
|
|
314
|
-
|
|
315
|
-
|
|
313
|
+
## Step 6: Verify authentication
|
|
314
|
+
|
|
315
|
+
Login now happens in `verity init` (an optional, skippable step), **not** here.
|
|
316
|
+
This step only checks whether the user authenticated during init, and branches
|
|
317
|
+
the rest of setup accordingly.
|
|
318
|
+
|
|
319
|
+
**If the user asks what signing in does or why it matters, tell them:**
|
|
320
|
+
- It confirms they have **write access to this repository** — the GitHub token is
|
|
321
|
+
used **once** to verify that, then discarded. Verity never stores it.
|
|
322
|
+
- It does **not** give Verity access to their code. Code checked by the gate is
|
|
323
|
+
analyzed **in memory and discarded** — Verity never stores their code.
|
|
324
|
+
- It is **required to store and access run history** for the repo (past results,
|
|
325
|
+
trends, and shareable reports).
|
|
326
|
+
- Skipping keeps Verity fully **local-only**: the gate still runs and shows
|
|
327
|
+
findings, but nothing is uploaded.
|
|
316
328
|
|
|
317
329
|
```bash
|
|
318
|
-
verity auth
|
|
330
|
+
verity auth verify
|
|
319
331
|
```
|
|
320
332
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
333
|
+
- **Token valid** (prints the project name): The user authenticated during
|
|
334
|
+
`verity init`. Continue to Step 7 — the Standard, config, and knowledge base
|
|
335
|
+
will upload.
|
|
336
|
+
- **Not authenticated / no token**: The user skipped login in `verity init` (or
|
|
337
|
+
lacks write access). Verity runs in **local-only mode** — the gate still runs on
|
|
338
|
+
every stop and surfaces static findings, but nothing uploads and no
|
|
339
|
+
history/org/repo data is stored. **Skip Steps 7 and 7b** (they require a token)
|
|
340
|
+
and continue to Step 8. Tell the user they can authenticate anytime to unlock
|
|
341
|
+
deep review, history, and shareable reports by running:
|
|
342
|
+
|
|
343
|
+
```bash
|
|
344
|
+
verity init # re-runs init; offers the auth prompt again
|
|
345
|
+
# or, directly:
|
|
346
|
+
verity auth register --project "PROJECT_NAME" --remote "GIT_REMOTE_URL"
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
Registration is **provider-gated** (GitHub today): the CLI runs a GitHub OAuth
|
|
350
|
+
**device flow** ("open https://github.com/login/device and enter code
|
|
351
|
+
WXYZ-1234"), proving the user has **write access** to the repo before the
|
|
352
|
+
service issues a token.
|
|
353
|
+
|
|
354
|
+
When authenticated, `.verity/credentials` contains `token`, `service_url`, and
|
|
355
|
+
`provider_token` — all subsequent `verity` upload commands work.
|
|
334
356
|
|
|
335
357
|
---
|
|
336
358
|
|
|
337
359
|
## Step 7: Upload Standard and config
|
|
338
360
|
|
|
361
|
+
> **Skip this entire step if the user is not authenticated** (Step 6 reported
|
|
362
|
+
> local-only mode). These commands require a token and will fail without one. The
|
|
363
|
+
> `.verity/standard.yaml` and `.codacy/codacy.config.json` you generated locally
|
|
364
|
+
> still drive the gate; they'll upload the next time the user authenticates and
|
|
365
|
+
> re-runs setup.
|
|
366
|
+
|
|
339
367
|
### Upload the Standard
|
|
340
368
|
|
|
341
369
|
The `verity` CLI handles YAML→JSON conversion automatically:
|
|
@@ -366,6 +394,10 @@ This derives a small set of descriptive memory nodes from what you already analy
|
|
|
366
394
|
|
|
367
395
|
## Step 7b: Enable telemetry (only if the user opted in at Step 3b)
|
|
368
396
|
|
|
397
|
+
> **Skip this step if the user is not authenticated** (local-only mode) — telemetry
|
|
398
|
+
> export requires the token. Note that `/usage` stays empty until they authenticate
|
|
399
|
+
> and run `verity telemetry install`.
|
|
400
|
+
|
|
369
401
|
If — and only if — the user said **Yes** in Step 3b, enable the Claude Code telemetry export
|
|
370
402
|
now (the token from Step 6 must already exist):
|
|
371
403
|
|