@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.
Files changed (84) hide show
  1. package/README.md +70 -0
  2. package/data/execution-surfaces.json +28 -0
  3. package/dist/auth.js +20 -0
  4. package/dist/commands/authorize.d.ts +1 -0
  5. package/dist/commands/authorize.js +99 -0
  6. package/dist/commands/chaos.d.ts +1 -0
  7. package/dist/commands/chaos.js +35 -0
  8. package/dist/commands/dev.d.ts +1 -0
  9. package/dist/commands/dev.js +27 -0
  10. package/dist/commands/doctor.d.ts +1 -0
  11. package/dist/commands/doctor.js +50 -0
  12. package/dist/commands/log.d.ts +3 -0
  13. package/dist/commands/log.js +119 -0
  14. package/dist/commands/logMonitor.d.ts +1 -0
  15. package/dist/commands/logMonitor.js +65 -0
  16. package/dist/commands/login-web.d.ts +1 -0
  17. package/dist/commands/login-web.js +80 -0
  18. package/dist/commands/policy-distribution.d.ts +10 -0
  19. package/dist/commands/policy-distribution.js +108 -0
  20. package/dist/commands/policy-runtime.d.ts +4 -0
  21. package/dist/commands/policy-runtime.js +61 -0
  22. package/dist/commands/policy.d.ts +1 -0
  23. package/dist/commands/policy.js +123 -0
  24. package/dist/commands/policyLifecycle.d.ts +13 -0
  25. package/dist/commands/policyLifecycle.js +601 -0
  26. package/dist/commands/receiptFetch.d.ts +1 -0
  27. package/dist/commands/receiptFetch.js +44 -0
  28. package/dist/commands/receiptProof.d.ts +1 -0
  29. package/dist/commands/receiptProof.js +43 -0
  30. package/dist/commands/replay.d.ts +2 -0
  31. package/dist/commands/replay.js +130 -0
  32. package/dist/commands/session.d.ts +6 -0
  33. package/dist/commands/session.js +280 -0
  34. package/dist/commands/simulate.d.ts +5 -0
  35. package/dist/commands/simulate.js +89 -0
  36. package/dist/commands/tg-authorize.d.ts +12 -0
  37. package/dist/commands/tg-authorize.js +191 -0
  38. package/dist/commands/tg-init.d.ts +1 -0
  39. package/dist/commands/tg-init.js +149 -0
  40. package/dist/commands/tg-setup.d.ts +1 -0
  41. package/dist/commands/tg-setup.js +43 -0
  42. package/dist/commands/tg-surfaces.d.ts +7 -0
  43. package/dist/commands/tg-surfaces.js +50 -0
  44. package/dist/commands/tg-verify.d.ts +1 -0
  45. package/dist/commands/tg-verify.js +118 -0
  46. package/dist/commands/transparency.d.ts +2 -0
  47. package/dist/commands/transparency.js +65 -0
  48. package/dist/commands/verify.d.ts +1 -0
  49. package/dist/commands/verify.js +127 -0
  50. package/dist/commands/verifyBundle.d.ts +1 -0
  51. package/dist/commands/verifyBundle.js +109 -0
  52. package/dist/commands/verifyReceiptCmd.d.ts +1 -0
  53. package/dist/commands/verifyReceiptCmd.js +49 -0
  54. package/dist/commands/witness.d.ts +1 -0
  55. package/dist/commands/witness.js +22 -0
  56. package/dist/cp/cliDeviceAuth.d.ts +24 -0
  57. package/dist/cp/cliDeviceAuth.js +68 -0
  58. package/dist/cp/client.d.ts +19 -0
  59. package/dist/cp/client.js +73 -0
  60. package/dist/cp/config.d.ts +8 -0
  61. package/dist/cp/config.js +113 -0
  62. package/dist/cp/credentials.d.ts +9 -0
  63. package/dist/cp/credentials.js +31 -0
  64. package/dist/cp/provisionCliKey.d.ts +12 -0
  65. package/dist/cp/provisionCliKey.js +43 -0
  66. package/dist/cp/types.d.ts +37 -0
  67. package/dist/cp/types.js +1 -0
  68. package/dist/stdin.js +9 -0
  69. package/dist/tg/args.d.ts +3 -0
  70. package/dist/tg/args.js +28 -0
  71. package/dist/tg/authorize-format.d.ts +21 -0
  72. package/dist/tg/authorize-format.js +87 -0
  73. package/dist/tg/errors.d.ts +6 -0
  74. package/dist/tg/errors.js +53 -0
  75. package/dist/tg/gateway.d.ts +2 -0
  76. package/dist/tg/gateway.js +19 -0
  77. package/dist/tg/help.d.ts +7 -0
  78. package/dist/tg/help.js +164 -0
  79. package/dist/tg/receipt.d.ts +1 -0
  80. package/dist/tg/receipt.js +13 -0
  81. package/dist/tg/shellQuote.d.ts +1 -0
  82. package/dist/tg/shellQuote.js +6 -0
  83. package/dist/tg.js +92 -0
  84. 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
+ }
@@ -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
+ }
@@ -0,0 +1,3 @@
1
+ export declare function hasFlag(args: readonly string[], name: string): boolean;
2
+ export declare function flagValue(args: readonly string[], name: string): string | undefined;
3
+ export declare function stripFlags(args: readonly string[]): string[];
@@ -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,2 @@
1
+ export declare function defaultGatewayUrl(environment?: string): string;
2
+ export declare function resolveGatewayUrl(args: readonly string[], environment?: string): string;
@@ -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;
@@ -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;
@@ -0,0 +1,6 @@
1
+ export function shellQuoteArg(value) {
2
+ const trimmed = value.trim();
3
+ if (/^[A-Za-z0-9._@/-]+$/.test(trimmed))
4
+ return trimmed;
5
+ return `'${trimmed.replace(/'/g, `'\\''`)}'`;
6
+ }
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
+ });