@trigguard/cli 0.1.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 +70 -0
- package/data/execution-surfaces.json +28 -0
- package/dist/auth.js +20 -0
- package/dist/commands/authorize.d.ts +1 -0
- package/dist/commands/authorize.js +99 -0
- package/dist/commands/chaos.d.ts +1 -0
- package/dist/commands/chaos.js +35 -0
- package/dist/commands/dev.d.ts +1 -0
- package/dist/commands/dev.js +27 -0
- package/dist/commands/doctor.d.ts +1 -0
- package/dist/commands/doctor.js +50 -0
- package/dist/commands/log.d.ts +3 -0
- package/dist/commands/log.js +119 -0
- package/dist/commands/logMonitor.d.ts +1 -0
- package/dist/commands/logMonitor.js +65 -0
- package/dist/commands/login-web.d.ts +1 -0
- package/dist/commands/login-web.js +80 -0
- package/dist/commands/policy-distribution.d.ts +10 -0
- package/dist/commands/policy-distribution.js +108 -0
- package/dist/commands/policy-runtime.d.ts +4 -0
- package/dist/commands/policy-runtime.js +61 -0
- package/dist/commands/policy.d.ts +1 -0
- package/dist/commands/policy.js +123 -0
- package/dist/commands/policyLifecycle.d.ts +13 -0
- package/dist/commands/policyLifecycle.js +601 -0
- package/dist/commands/receiptFetch.d.ts +1 -0
- package/dist/commands/receiptFetch.js +44 -0
- package/dist/commands/receiptProof.d.ts +1 -0
- package/dist/commands/receiptProof.js +43 -0
- package/dist/commands/replay.d.ts +2 -0
- package/dist/commands/replay.js +130 -0
- package/dist/commands/session.d.ts +6 -0
- package/dist/commands/session.js +280 -0
- package/dist/commands/simulate.d.ts +5 -0
- package/dist/commands/simulate.js +89 -0
- package/dist/commands/tg-authorize.d.ts +12 -0
- package/dist/commands/tg-authorize.js +191 -0
- package/dist/commands/tg-init.d.ts +1 -0
- package/dist/commands/tg-init.js +149 -0
- package/dist/commands/tg-setup.d.ts +1 -0
- package/dist/commands/tg-setup.js +43 -0
- package/dist/commands/tg-surfaces.d.ts +7 -0
- package/dist/commands/tg-surfaces.js +50 -0
- package/dist/commands/tg-verify.d.ts +1 -0
- package/dist/commands/tg-verify.js +118 -0
- package/dist/commands/transparency.d.ts +2 -0
- package/dist/commands/transparency.js +65 -0
- package/dist/commands/verify.d.ts +1 -0
- package/dist/commands/verify.js +127 -0
- package/dist/commands/verifyBundle.d.ts +1 -0
- package/dist/commands/verifyBundle.js +109 -0
- package/dist/commands/verifyReceiptCmd.d.ts +1 -0
- package/dist/commands/verifyReceiptCmd.js +49 -0
- package/dist/commands/witness.d.ts +1 -0
- package/dist/commands/witness.js +22 -0
- package/dist/cp/cliDeviceAuth.d.ts +24 -0
- package/dist/cp/cliDeviceAuth.js +68 -0
- package/dist/cp/client.d.ts +19 -0
- package/dist/cp/client.js +73 -0
- package/dist/cp/config.d.ts +8 -0
- package/dist/cp/config.js +113 -0
- package/dist/cp/credentials.d.ts +9 -0
- package/dist/cp/credentials.js +31 -0
- package/dist/cp/provisionCliKey.d.ts +12 -0
- package/dist/cp/provisionCliKey.js +43 -0
- package/dist/cp/types.d.ts +37 -0
- package/dist/cp/types.js +1 -0
- package/dist/stdin.js +9 -0
- package/dist/tg/args.d.ts +3 -0
- package/dist/tg/args.js +28 -0
- package/dist/tg/authorize-format.d.ts +21 -0
- package/dist/tg/authorize-format.js +87 -0
- package/dist/tg/errors.d.ts +6 -0
- package/dist/tg/errors.js +53 -0
- package/dist/tg/gateway.d.ts +2 -0
- package/dist/tg/gateway.js +19 -0
- package/dist/tg/help.d.ts +7 -0
- package/dist/tg/help.js +164 -0
- package/dist/tg/receipt.d.ts +1 -0
- package/dist/tg/receipt.js +13 -0
- package/dist/tg/shellQuote.d.ts +1 -0
- package/dist/tg/shellQuote.js +6 -0
- package/dist/tg.js +92 -0
- package/package.json +50 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { TrigGuardCliConfig } from "./types.js";
|
|
2
|
+
export declare function defaultMachineLabel(): string;
|
|
3
|
+
export declare function createCliApiKey(config: TrigGuardCliConfig, orgId: string, machineLabel?: string): Promise<{
|
|
4
|
+
rawKey: string;
|
|
5
|
+
keyId: string;
|
|
6
|
+
displayName: string;
|
|
7
|
+
}>;
|
|
8
|
+
export declare function ensureCliApiKey(config: TrigGuardCliConfig, orgId: string, existingRawKey?: string | null, machineLabel?: string, existingKeyId?: string | null): Promise<{
|
|
9
|
+
rawKey: string;
|
|
10
|
+
keyId: string;
|
|
11
|
+
displayName: string;
|
|
12
|
+
}>;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import os from "node:os";
|
|
2
|
+
import { controlPlaneFetch, ControlPlaneError } from "./client.js";
|
|
3
|
+
const CLI_KEY_SCOPES = ["execute:staging", "execute:production"];
|
|
4
|
+
export function defaultMachineLabel() {
|
|
5
|
+
return os.hostname().trim().slice(0, 120) || "cli";
|
|
6
|
+
}
|
|
7
|
+
export async function createCliApiKey(config, orgId, machineLabel = defaultMachineLabel()) {
|
|
8
|
+
const displayName = `TrigGuard CLI (${machineLabel})`;
|
|
9
|
+
const data = await controlPlaneFetch(config, "/apikeys", {
|
|
10
|
+
method: "POST",
|
|
11
|
+
headers: { "Content-Type": "application/json" },
|
|
12
|
+
body: JSON.stringify({
|
|
13
|
+
orgId,
|
|
14
|
+
displayName,
|
|
15
|
+
environment: "live",
|
|
16
|
+
scopes: CLI_KEY_SCOPES,
|
|
17
|
+
}),
|
|
18
|
+
});
|
|
19
|
+
const rawKey = typeof data.rawKey === "string" ? data.rawKey : "";
|
|
20
|
+
const keyId = typeof data.keyId === "string" ? data.keyId : "";
|
|
21
|
+
if (!rawKey.startsWith("tg_live_")) {
|
|
22
|
+
throw new Error("api_key_create_failed");
|
|
23
|
+
}
|
|
24
|
+
return { rawKey, keyId, displayName };
|
|
25
|
+
}
|
|
26
|
+
export async function ensureCliApiKey(config, orgId, existingRawKey, machineLabel = defaultMachineLabel(), existingKeyId) {
|
|
27
|
+
if (existingRawKey?.startsWith("tg_live_")) {
|
|
28
|
+
return {
|
|
29
|
+
rawKey: existingRawKey,
|
|
30
|
+
keyId: existingKeyId ?? config.apiKeyId ?? "",
|
|
31
|
+
displayName: config.apiKeyDisplayName ?? `TrigGuard CLI (${machineLabel})`,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
try {
|
|
35
|
+
return await createCliApiKey(config, orgId, machineLabel);
|
|
36
|
+
}
|
|
37
|
+
catch (e) {
|
|
38
|
+
if (e instanceof ControlPlaneError && e.code === "email_verification_required") {
|
|
39
|
+
throw new Error("Email verification required before API key creation. Verify email in console, then retry tg login.");
|
|
40
|
+
}
|
|
41
|
+
throw e;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export type TrigGuardEnvironment = "production" | "staging" | "preview" | "local";
|
|
2
|
+
export interface ControlPlaneUser {
|
|
3
|
+
readonly id: string;
|
|
4
|
+
readonly email: string;
|
|
5
|
+
readonly createdAt: string;
|
|
6
|
+
readonly emailVerifiedAt: string | null;
|
|
7
|
+
}
|
|
8
|
+
export interface ControlPlaneOrgSummary {
|
|
9
|
+
readonly orgId: string;
|
|
10
|
+
readonly name: string;
|
|
11
|
+
readonly plan: string;
|
|
12
|
+
readonly subscriptionStatus?: string;
|
|
13
|
+
}
|
|
14
|
+
export interface TrigGuardCliConfig {
|
|
15
|
+
readonly version: 1;
|
|
16
|
+
readonly controlPlaneUrl: string;
|
|
17
|
+
readonly environment: TrigGuardEnvironment;
|
|
18
|
+
readonly sessionToken?: string;
|
|
19
|
+
readonly activeOrgId?: string;
|
|
20
|
+
readonly user?: {
|
|
21
|
+
readonly id: string;
|
|
22
|
+
readonly email: string;
|
|
23
|
+
};
|
|
24
|
+
readonly apiKey?: string;
|
|
25
|
+
readonly apiKeyId?: string;
|
|
26
|
+
readonly apiKeyDisplayName?: string;
|
|
27
|
+
/** When true, env/file session overrides are suppressed until next login. */
|
|
28
|
+
readonly sessionRevoked?: boolean;
|
|
29
|
+
}
|
|
30
|
+
export interface SessionSnapshot {
|
|
31
|
+
readonly authenticated: boolean;
|
|
32
|
+
readonly user: ControlPlaneUser | null;
|
|
33
|
+
readonly orgs: readonly ControlPlaneOrgSummary[];
|
|
34
|
+
readonly activeOrg: ControlPlaneOrgSummary | null;
|
|
35
|
+
readonly controlPlaneUrl: string;
|
|
36
|
+
readonly environment: TrigGuardEnvironment;
|
|
37
|
+
}
|
package/dist/cp/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/stdin.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { stdin as input } from "node:process";
|
|
2
|
+
/** Read entire stdin (for --input -). */
|
|
3
|
+
export async function readStdin() {
|
|
4
|
+
const chunks = [];
|
|
5
|
+
for await (const chunk of input) {
|
|
6
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
7
|
+
}
|
|
8
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
9
|
+
}
|
package/dist/tg/args.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export function hasFlag(args, name) {
|
|
2
|
+
return args.includes(name);
|
|
3
|
+
}
|
|
4
|
+
export function flagValue(args, name) {
|
|
5
|
+
const i = args.indexOf(name);
|
|
6
|
+
if (i === -1)
|
|
7
|
+
return undefined;
|
|
8
|
+
const next = args[i + 1];
|
|
9
|
+
if (next === undefined || next.startsWith("-"))
|
|
10
|
+
return undefined;
|
|
11
|
+
return next;
|
|
12
|
+
}
|
|
13
|
+
export function stripFlags(args) {
|
|
14
|
+
const out = [];
|
|
15
|
+
for (let i = 0; i < args.length; i++) {
|
|
16
|
+
const a = args[i];
|
|
17
|
+
if (!a.startsWith("-")) {
|
|
18
|
+
out.push(a);
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
if (a === "--json")
|
|
22
|
+
continue;
|
|
23
|
+
const next = args[i + 1];
|
|
24
|
+
if (next !== undefined && !next.startsWith("-"))
|
|
25
|
+
i++;
|
|
26
|
+
}
|
|
27
|
+
return out;
|
|
28
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export interface AuthorizeDisplay {
|
|
2
|
+
readonly decision: string;
|
|
3
|
+
readonly reason: string;
|
|
4
|
+
readonly riskScore: number | null;
|
|
5
|
+
readonly executionId: string | null;
|
|
6
|
+
readonly receiptValid: boolean;
|
|
7
|
+
readonly policyId: string | null;
|
|
8
|
+
readonly policyBundleHash: string | null;
|
|
9
|
+
readonly surface: string | null;
|
|
10
|
+
readonly actorId: string | null;
|
|
11
|
+
readonly latencyMs: number | null;
|
|
12
|
+
readonly authority: string | null;
|
|
13
|
+
readonly protocol: string | null;
|
|
14
|
+
readonly signatureStatus: string;
|
|
15
|
+
readonly receiptStatus: string;
|
|
16
|
+
readonly verificationResult: string;
|
|
17
|
+
}
|
|
18
|
+
export declare function formatReason(display: Pick<AuthorizeDisplay, "decision" | "policyId">): string;
|
|
19
|
+
export declare function buildAuthorizeDisplay(body: Record<string, unknown>, receiptValid: boolean): AuthorizeDisplay;
|
|
20
|
+
export declare function printHumanAuthorize(display: AuthorizeDisplay): void;
|
|
21
|
+
export declare function printJsonAuthorize(payload: Record<string, unknown>): void;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
function formatRisk(score) {
|
|
2
|
+
if (score === null || Number.isNaN(score))
|
|
3
|
+
return "—";
|
|
4
|
+
const normalized = score <= 1 ? Math.round(score * 100) : Math.round(score);
|
|
5
|
+
return `${normalized}/100`;
|
|
6
|
+
}
|
|
7
|
+
export function formatReason(display) {
|
|
8
|
+
if (display.policyId) {
|
|
9
|
+
const id = display.policyId.startsWith("RULE_") ? display.policyId.slice(5) : display.policyId;
|
|
10
|
+
return `Policy ${id} violated`;
|
|
11
|
+
}
|
|
12
|
+
const decision = display.decision.toUpperCase();
|
|
13
|
+
if (decision === "PERMIT")
|
|
14
|
+
return "No policy violation";
|
|
15
|
+
if (decision === "DENY")
|
|
16
|
+
return "Execution blocked by policy";
|
|
17
|
+
if (decision === "SILENCE")
|
|
18
|
+
return "Execution withheld (SILENCE)";
|
|
19
|
+
return "Policy evaluation complete";
|
|
20
|
+
}
|
|
21
|
+
export function buildAuthorizeDisplay(body, receiptValid) {
|
|
22
|
+
const receipt = body.receipt && typeof body.receipt === "object" ? body.receipt : {};
|
|
23
|
+
const decision = String(body.decision ?? receipt.decision ?? "UNKNOWN").toUpperCase();
|
|
24
|
+
const executionId = typeof body.execution_id === "string"
|
|
25
|
+
? body.execution_id
|
|
26
|
+
: typeof receipt.executionId === "string"
|
|
27
|
+
? receipt.executionId
|
|
28
|
+
: null;
|
|
29
|
+
const riskRaw = body.risk_score ?? body.riskScore;
|
|
30
|
+
const riskScore = typeof riskRaw === "number"
|
|
31
|
+
? riskRaw
|
|
32
|
+
: typeof riskRaw === "string" && riskRaw.trim() !== ""
|
|
33
|
+
? Number(riskRaw)
|
|
34
|
+
: null;
|
|
35
|
+
const policyId = typeof receipt.policyId === "string" ? receipt.policyId : null;
|
|
36
|
+
const authoritySig = typeof receipt.authoritySignature === "string" ? receipt.authoritySignature : "";
|
|
37
|
+
const signed = authoritySig.length > 0 && authoritySig !== "unsigned";
|
|
38
|
+
const base = {
|
|
39
|
+
decision,
|
|
40
|
+
reason: "",
|
|
41
|
+
riskScore,
|
|
42
|
+
executionId,
|
|
43
|
+
receiptValid,
|
|
44
|
+
policyId,
|
|
45
|
+
policyBundleHash: typeof body.policy_bundle_hash === "string"
|
|
46
|
+
? body.policy_bundle_hash
|
|
47
|
+
: typeof receipt.policyBundleHash === "string"
|
|
48
|
+
? receipt.policyBundleHash
|
|
49
|
+
: null,
|
|
50
|
+
surface: typeof body.surface === "string" ? body.surface : null,
|
|
51
|
+
actorId: typeof body.agent_id === "string" ? body.agent_id : null,
|
|
52
|
+
latencyMs: typeof body.latency_ms === "number" ? body.latency_ms : null,
|
|
53
|
+
authority: typeof body.authority === "string" ? body.authority : null,
|
|
54
|
+
protocol: typeof body.protocol === "string" ? body.protocol : null,
|
|
55
|
+
signatureStatus: signed ? (receiptValid ? "valid (Ed25519)" : "present — verification failed") : "unsigned",
|
|
56
|
+
receiptStatus: signed ? "signed" : "unsigned",
|
|
57
|
+
verificationResult: receiptValid ? "passed" : "failed",
|
|
58
|
+
};
|
|
59
|
+
return { ...base, reason: formatReason(base) };
|
|
60
|
+
}
|
|
61
|
+
export function printHumanAuthorize(display) {
|
|
62
|
+
const lines = [
|
|
63
|
+
["Decision:", display.decision],
|
|
64
|
+
["Reason:", formatReason(display)],
|
|
65
|
+
["Risk Score:", formatRisk(display.riskScore)],
|
|
66
|
+
["Execution ID:", display.executionId ?? "—"],
|
|
67
|
+
["Receipt Status:", display.receiptStatus],
|
|
68
|
+
["Signature Status:", display.signatureStatus],
|
|
69
|
+
["Authority Source:", display.authority ?? "trigguard-cloud"],
|
|
70
|
+
["Protocol:", display.protocol ?? "trigguard/v1"],
|
|
71
|
+
["Verification:", display.verificationResult],
|
|
72
|
+
];
|
|
73
|
+
for (const [label, value] of lines) {
|
|
74
|
+
console.log(`${label.padEnd(18)} ${value}`);
|
|
75
|
+
}
|
|
76
|
+
if (display.policyBundleHash) {
|
|
77
|
+
console.log(`${"Policy Bundle:".padEnd(18)} ${display.policyBundleHash.slice(0, 20)}…`);
|
|
78
|
+
}
|
|
79
|
+
if (display.latencyMs !== null) {
|
|
80
|
+
console.log(`${"Latency:".padEnd(18)} ${display.latencyMs}ms`);
|
|
81
|
+
}
|
|
82
|
+
console.log("");
|
|
83
|
+
console.log("Next: tg verify --execution-id", display.executionId ?? "<execution-id>");
|
|
84
|
+
}
|
|
85
|
+
export function printJsonAuthorize(payload) {
|
|
86
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
87
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare function missingApiKeyMessage(): string;
|
|
2
|
+
export declare function formatGatewayError(status: number, body: unknown, opts?: {
|
|
3
|
+
apiKeyProvided?: boolean;
|
|
4
|
+
}): string;
|
|
5
|
+
export declare function formatFetchError(err: unknown, gatewayUrl: string): string;
|
|
6
|
+
export declare function missingSurfaceMessage(): string;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { missingConfiguredApiKeyMessage } from "../cp/credentials.js";
|
|
2
|
+
export function missingApiKeyMessage() {
|
|
3
|
+
return missingConfiguredApiKeyMessage();
|
|
4
|
+
}
|
|
5
|
+
export function formatGatewayError(status, body, opts) {
|
|
6
|
+
const obj = body && typeof body === "object" ? body : {};
|
|
7
|
+
const code = String(obj.error ?? obj.code ?? `http_${status}`);
|
|
8
|
+
if (code === "TG_API_KEY_MISSING" || (status === 401 && !opts?.apiKeyProvided)) {
|
|
9
|
+
return missingApiKeyMessage();
|
|
10
|
+
}
|
|
11
|
+
if (status === 401) {
|
|
12
|
+
return [
|
|
13
|
+
`API key rejected (HTTP 401, ${code}).`,
|
|
14
|
+
"Verify TRIGGUARD_API_KEY is valid, not revoked, and has the required scope.",
|
|
15
|
+
].join("\n");
|
|
16
|
+
}
|
|
17
|
+
if (code === "unknown_surface") {
|
|
18
|
+
return [
|
|
19
|
+
"Unknown execution surface.",
|
|
20
|
+
"Use a surface registered in protocol/execution-surfaces.json.",
|
|
21
|
+
`Surface sent: ${String(obj.surface ?? "(see request)")}`,
|
|
22
|
+
].join("\n");
|
|
23
|
+
}
|
|
24
|
+
if (code === "email_verification_required") {
|
|
25
|
+
return "Email verification required. Complete verification in the console, then retry.";
|
|
26
|
+
}
|
|
27
|
+
if (status === 403) {
|
|
28
|
+
return `Authorization denied by gateway (${code}). Check API key scope and plan entitlements.`;
|
|
29
|
+
}
|
|
30
|
+
if (status >= 500) {
|
|
31
|
+
return `Gateway unavailable (HTTP ${status}). Retry later or check TRIGGUARD_GATEWAY_URL.`;
|
|
32
|
+
}
|
|
33
|
+
return `Gateway request failed (HTTP ${status}, ${code}).`;
|
|
34
|
+
}
|
|
35
|
+
export function formatFetchError(err, gatewayUrl) {
|
|
36
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
37
|
+
if (/fetch failed|ECONNREFUSED|ENOTFOUND|ETIMEDOUT|abort/i.test(msg)) {
|
|
38
|
+
return [
|
|
39
|
+
`Cannot reach TrigGuard gateway at ${gatewayUrl}.`,
|
|
40
|
+
"Check TRIGGUARD_GATEWAY_URL and network connectivity.",
|
|
41
|
+
"Local dev default: http://127.0.0.1:8080",
|
|
42
|
+
].join("\n");
|
|
43
|
+
}
|
|
44
|
+
return msg;
|
|
45
|
+
}
|
|
46
|
+
export function missingSurfaceMessage() {
|
|
47
|
+
return [
|
|
48
|
+
"Missing required --surface.",
|
|
49
|
+
"Example:",
|
|
50
|
+
' tg authorize --surface deploy.release --actor ci --intent "deploy main"',
|
|
51
|
+
"Or pass JSON via --file payload.json or stdin.",
|
|
52
|
+
].join("\n");
|
|
53
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { loadConfig } from "../cp/config.js";
|
|
2
|
+
import { flagValue } from "./args.js";
|
|
3
|
+
export function defaultGatewayUrl(environment) {
|
|
4
|
+
const override = process.env.TRIGGUARD_GATEWAY_URL?.trim();
|
|
5
|
+
if (override)
|
|
6
|
+
return override.replace(/\/$/, "");
|
|
7
|
+
switch ((environment ?? "production").trim().toLowerCase()) {
|
|
8
|
+
case "local":
|
|
9
|
+
case "dev":
|
|
10
|
+
case "development":
|
|
11
|
+
return "http://127.0.0.1:8080";
|
|
12
|
+
default:
|
|
13
|
+
return "https://api.trigguardai.com";
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export function resolveGatewayUrl(args, environment) {
|
|
17
|
+
const env = flagValue(args, "--environment") ?? environment ?? loadConfig().environment;
|
|
18
|
+
return flagValue(args, "--gateway-url") ?? defaultGatewayUrl(env);
|
|
19
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare function printRootHelp(): void;
|
|
2
|
+
export declare function printAuthorizeHelp(): void;
|
|
3
|
+
export declare function printVerifyHelp(): void;
|
|
4
|
+
export declare function printInitHelp(): void;
|
|
5
|
+
export declare function printLoginHelp(): void;
|
|
6
|
+
export declare function printSetupHelp(): void;
|
|
7
|
+
export declare function printSurfacesHelp(): void;
|
package/dist/tg/help.js
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
export function printRootHelp() {
|
|
2
|
+
console.log(`tg — TrigGuard developer CLI
|
|
3
|
+
|
|
4
|
+
PRODUCT EXPERIENCE
|
|
5
|
+
TrigGuard governs execution: every action gets PERMIT, DENY, or SILENCE
|
|
6
|
+
plus a cryptographically signed receipt. Start with authorize.
|
|
7
|
+
|
|
8
|
+
COMMANDS
|
|
9
|
+
authorize Request governed execution authorization (gateway rail)
|
|
10
|
+
verify Verify a signed receipt (file or execution ID)
|
|
11
|
+
init Bootstrap TrigGuard integration files (non-destructive)
|
|
12
|
+
setup First-run login + surface discovery
|
|
13
|
+
surfaces List registered execution surfaces
|
|
14
|
+
login Sign in (browser device flow by default)
|
|
15
|
+
logout Clear local session
|
|
16
|
+
whoami Current user and workspace
|
|
17
|
+
status Auth, org, environment summary
|
|
18
|
+
|
|
19
|
+
QUICK START
|
|
20
|
+
npm install -g @trigguard/cli
|
|
21
|
+
tg login
|
|
22
|
+
tg authorize --surface deploy.release --actor demo --intent "test deploy"
|
|
23
|
+
|
|
24
|
+
tg setup First-run guided flow
|
|
25
|
+
tg surfaces list Valid execution surfaces
|
|
26
|
+
|
|
27
|
+
ENVIRONMENT
|
|
28
|
+
TRIGGUARD_API_KEY Override stored API key (CI/scripts)
|
|
29
|
+
TRIGGUARD_GATEWAY_URL Gateway base URL (default https://api.trigguardai.com)
|
|
30
|
+
TRIGGUARD_CONTROL_PLANE_URL Control plane URL (session commands)
|
|
31
|
+
|
|
32
|
+
DOCS
|
|
33
|
+
docs/developer/TRIGGUARD_CLI_ZERO_CONFIG_AUTH.md
|
|
34
|
+
docs/developer/TRIGGUARD_QUICKSTART.md
|
|
35
|
+
`);
|
|
36
|
+
}
|
|
37
|
+
export function printAuthorizeHelp() {
|
|
38
|
+
console.log(`tg authorize — governed execution authorization
|
|
39
|
+
|
|
40
|
+
WHAT IT DOES
|
|
41
|
+
Sends surface + actor + intent to the TrigGuard gateway (POST /execute).
|
|
42
|
+
Returns PERMIT, DENY, or SILENCE with a signed receipt.
|
|
43
|
+
|
|
44
|
+
WHY IT EXISTS
|
|
45
|
+
The fastest way to experience TrigGuard: one command shows policy + evidence.
|
|
46
|
+
|
|
47
|
+
USAGE
|
|
48
|
+
tg authorize --surface SURFACE --actor ACTOR [options]
|
|
49
|
+
tg authorize --file payload.json
|
|
50
|
+
cat payload.json | tg authorize
|
|
51
|
+
|
|
52
|
+
OPTIONS
|
|
53
|
+
--surface SURFACE Execution surface (required unless JSON/stdin)
|
|
54
|
+
--actor ACTOR Agent or service identity (default: tg-cli)
|
|
55
|
+
--intent TEXT Human-readable intent (stored in context)
|
|
56
|
+
--risk LEVEL low | medium | high | critical | 0-100
|
|
57
|
+
--environment ENV production | staging | preview | local
|
|
58
|
+
--payload JSON|FILE Additional context JSON
|
|
59
|
+
--file PATH Full request JSON (- for stdin)
|
|
60
|
+
--gateway-url URL Override gateway base URL
|
|
61
|
+
--json Machine-readable output (CI/CD)
|
|
62
|
+
|
|
63
|
+
OUTPUT (human)
|
|
64
|
+
Decision, reason, risk score, execution ID, receipt/signature status,
|
|
65
|
+
authority source, verification result.
|
|
66
|
+
|
|
67
|
+
EXIT CODES
|
|
68
|
+
0 PERMIT and receipt signature verified
|
|
69
|
+
1 DENY, SILENCE, invalid receipt, or request error
|
|
70
|
+
|
|
71
|
+
FAILURE MODES
|
|
72
|
+
Missing API key → run tg login
|
|
73
|
+
Unknown surface → tg surfaces list
|
|
74
|
+
Gateway unreachable → check TRIGGUARD_GATEWAY_URL
|
|
75
|
+
|
|
76
|
+
EXAMPLES
|
|
77
|
+
tg authorize --surface payment.execute --actor finance-agent \\
|
|
78
|
+
--intent "issue refund" --risk high
|
|
79
|
+
|
|
80
|
+
tg authorize --surface infrastructure.modify --actor deployment-bot \\
|
|
81
|
+
--intent "delete production cluster" --risk critical --json
|
|
82
|
+
|
|
83
|
+
See docs/developer/TRIGGUARD_CLI_AUTHORIZE_V1.md
|
|
84
|
+
`);
|
|
85
|
+
}
|
|
86
|
+
export function printVerifyHelp() {
|
|
87
|
+
console.log(`tg verify — verify a TrigGuard signed receipt
|
|
88
|
+
|
|
89
|
+
USAGE
|
|
90
|
+
tg verify receipt.json [--gateway-url URL] [--environment ENV] [--json]
|
|
91
|
+
tg verify --execution-id EXEC_ID [--gateway-url URL] [--environment ENV] [--json]
|
|
92
|
+
|
|
93
|
+
WHAT IT DOES
|
|
94
|
+
Cryptographically verifies receipt signature against gateway public keys.
|
|
95
|
+
Does not re-run policy — verifies evidence integrity only.
|
|
96
|
+
|
|
97
|
+
EXIT CODES
|
|
98
|
+
0 Signature valid
|
|
99
|
+
1 Invalid, unsigned, or fetch error
|
|
100
|
+
`);
|
|
101
|
+
}
|
|
102
|
+
export function printInitHelp() {
|
|
103
|
+
console.log(`tg init — bootstrap TrigGuard integration (non-destructive)
|
|
104
|
+
|
|
105
|
+
USAGE
|
|
106
|
+
tg init [--dir trigguard] [--force]
|
|
107
|
+
|
|
108
|
+
WHAT IT DOES
|
|
109
|
+
Inspects the repository, detects likely stack, and writes:
|
|
110
|
+
.env.example
|
|
111
|
+
trigguard.example.json
|
|
112
|
+
TRIGGUARD_INTEGRATION.md
|
|
113
|
+
stack-specific example snippets
|
|
114
|
+
|
|
115
|
+
DOES NOT
|
|
116
|
+
Edit application code, install packages, commit, or send telemetry.
|
|
117
|
+
|
|
118
|
+
OPTIONS
|
|
119
|
+
--dir PATH Output directory (default: trigguard)
|
|
120
|
+
--force Overwrite existing scaffold files
|
|
121
|
+
`);
|
|
122
|
+
}
|
|
123
|
+
export function printLoginHelp() {
|
|
124
|
+
console.log(`tg login — sign in and configure this machine
|
|
125
|
+
|
|
126
|
+
USAGE
|
|
127
|
+
tg login [--web] [--json]
|
|
128
|
+
tg login --email you@company.com --password '…'
|
|
129
|
+
|
|
130
|
+
DEFAULT (TTY)
|
|
131
|
+
Browser device flow — opens console, supports Google / GitHub / Microsoft.
|
|
132
|
+
Provisions a machine-scoped tg_live_* API key automatically.
|
|
133
|
+
|
|
134
|
+
PASSWORD FLOW
|
|
135
|
+
Use --email / --password for automation without a browser.
|
|
136
|
+
|
|
137
|
+
STORES (~/.trigguard/config.json, mode 0600)
|
|
138
|
+
session token, workspace, API key
|
|
139
|
+
|
|
140
|
+
See docs/developer/TRIGGUARD_CLI_ZERO_CONFIG_AUTH.md
|
|
141
|
+
`);
|
|
142
|
+
}
|
|
143
|
+
export function printSetupHelp() {
|
|
144
|
+
console.log(`tg setup — first-run guided onboarding
|
|
145
|
+
|
|
146
|
+
WORKFLOW
|
|
147
|
+
1. tg login (if needed)
|
|
148
|
+
2. List execution surfaces
|
|
149
|
+
3. Print first authorize example
|
|
150
|
+
|
|
151
|
+
GOAL
|
|
152
|
+
First PERMIT in under 10 minutes without reading docs.
|
|
153
|
+
`);
|
|
154
|
+
}
|
|
155
|
+
export function printSurfacesHelp() {
|
|
156
|
+
console.log(`tg surfaces list — read-only execution surface registry
|
|
157
|
+
|
|
158
|
+
USAGE
|
|
159
|
+
tg surfaces list [--json]
|
|
160
|
+
|
|
161
|
+
SOURCE
|
|
162
|
+
protocol/execution-surfaces.json (bundled in CLI)
|
|
163
|
+
`);
|
|
164
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function extractReceiptFromPayload(data: unknown): Record<string, unknown>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export function extractReceiptFromPayload(data) {
|
|
2
|
+
if (!data || typeof data !== "object") {
|
|
3
|
+
throw new Error("Invalid receipt file: expected JSON object");
|
|
4
|
+
}
|
|
5
|
+
const obj = data;
|
|
6
|
+
if (obj.receipt && typeof obj.receipt === "object") {
|
|
7
|
+
return obj.receipt;
|
|
8
|
+
}
|
|
9
|
+
if (typeof obj.receiptHash === "string" && typeof obj.authoritySignature === "string") {
|
|
10
|
+
return obj;
|
|
11
|
+
}
|
|
12
|
+
throw new Error("No receipt found in file (expected receipt.json or output of tg authorize --json)");
|
|
13
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function shellQuoteArg(value: string): string;
|
package/dist/tg.js
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { runTgAuthorize } from "./commands/tg-authorize.js";
|
|
3
|
+
import { runTgInit } from "./commands/tg-init.js";
|
|
4
|
+
import { runTgSetup } from "./commands/tg-setup.js";
|
|
5
|
+
import { runTgSurfaces } from "./commands/tg-surfaces.js";
|
|
6
|
+
import { runTgVerify } from "./commands/tg-verify.js";
|
|
7
|
+
import { runLogin, runLogout, runStatus, runWhoami } from "./commands/session.js";
|
|
8
|
+
import { printAuthorizeHelp, printInitHelp, printLoginHelp, printRootHelp, printSetupHelp, printSurfacesHelp, printVerifyHelp, } from "./tg/help.js";
|
|
9
|
+
async function main() {
|
|
10
|
+
const argv = process.argv.slice(2);
|
|
11
|
+
if (argv.length === 0 || argv[0] === "-h" || argv[0] === "--help") {
|
|
12
|
+
printRootHelp();
|
|
13
|
+
process.exit(0);
|
|
14
|
+
}
|
|
15
|
+
const cmd = argv[0];
|
|
16
|
+
const rest = argv.slice(1);
|
|
17
|
+
if (rest[0] === "-h" || rest[0] === "--help") {
|
|
18
|
+
if (cmd === "authorize")
|
|
19
|
+
printAuthorizeHelp();
|
|
20
|
+
else if (cmd === "verify")
|
|
21
|
+
printVerifyHelp();
|
|
22
|
+
else if (cmd === "init")
|
|
23
|
+
printInitHelp();
|
|
24
|
+
else if (cmd === "login")
|
|
25
|
+
printLoginHelp();
|
|
26
|
+
else if (cmd === "setup")
|
|
27
|
+
printSetupHelp();
|
|
28
|
+
else if (cmd === "surfaces")
|
|
29
|
+
printSurfacesHelp();
|
|
30
|
+
else
|
|
31
|
+
printRootHelp();
|
|
32
|
+
process.exit(0);
|
|
33
|
+
}
|
|
34
|
+
try {
|
|
35
|
+
if (cmd === "authorize") {
|
|
36
|
+
await runTgAuthorize(rest);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
if (cmd === "verify") {
|
|
40
|
+
await runTgVerify(rest);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
if (cmd === "init") {
|
|
44
|
+
await runTgInit(rest);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
if (cmd === "setup") {
|
|
48
|
+
await runTgSetup(rest);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if (cmd === "surfaces") {
|
|
52
|
+
if (rest[0] === "list") {
|
|
53
|
+
await runTgSurfaces(rest.slice(1));
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
await runTgSurfaces(rest);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (cmd === "login") {
|
|
60
|
+
await runLogin(rest);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
if (cmd === "logout") {
|
|
64
|
+
await runLogout(rest);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
if (cmd === "whoami") {
|
|
68
|
+
await runWhoami(rest);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
if (cmd === "status") {
|
|
72
|
+
await runStatus(rest);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
catch (e) {
|
|
77
|
+
if (e instanceof Error && e.message === "login_cancelled") {
|
|
78
|
+
console.error("Login cancelled.");
|
|
79
|
+
process.exit(130);
|
|
80
|
+
}
|
|
81
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
82
|
+
console.error(msg);
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
console.error(`Unknown command: ${cmd}`);
|
|
86
|
+
printRootHelp();
|
|
87
|
+
process.exit(1);
|
|
88
|
+
}
|
|
89
|
+
main().catch((e) => {
|
|
90
|
+
console.error(e instanceof Error ? e.message : e);
|
|
91
|
+
process.exit(1);
|
|
92
|
+
});
|