gog-safe 0.1.0

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/dist/run.js ADDED
@@ -0,0 +1,282 @@
1
+ import { appendAuditLog } from "./audit.js";
2
+ import { buildForcedArgs, decideCommandAllowance, findForbiddenOverride, } from "./command-control.js";
3
+ import { parseArgv, resolveValidatorsForCommand } from "./matching.js";
4
+ import { loadEffectivePolicy } from "./policy.js";
5
+ import { runCommand } from "./process.js";
6
+ import { runValidator } from "./validators.js";
7
+ function buildBaseOutput(command, version, allowed) {
8
+ return {
9
+ ok: false,
10
+ allowed,
11
+ command,
12
+ safety: {
13
+ action: "block",
14
+ reasons: [],
15
+ },
16
+ data: null,
17
+ meta: {
18
+ policy_version: version,
19
+ },
20
+ };
21
+ }
22
+ function asErrorMessage(error) {
23
+ if (error instanceof Error) {
24
+ return error.message;
25
+ }
26
+ return String(error);
27
+ }
28
+ function isObject(value) {
29
+ return typeof value === "object" && value !== null && !Array.isArray(value);
30
+ }
31
+ async function finalizeWithAudit(outcome, auditFile, requireAuditSuccess, metadata) {
32
+ try {
33
+ await appendAuditLog(auditFile, {
34
+ timestamp: new Date().toISOString(),
35
+ command: outcome.output.command,
36
+ allowed: outcome.output.allowed,
37
+ ok: outcome.output.ok,
38
+ action: outcome.output.safety.action,
39
+ reasons: [...outcome.output.safety.reasons],
40
+ metadata,
41
+ });
42
+ return outcome;
43
+ }
44
+ catch (error) {
45
+ const updated = {
46
+ ...outcome,
47
+ output: {
48
+ ...outcome.output,
49
+ safety: {
50
+ ...outcome.output.safety,
51
+ reasons: [...outcome.output.safety.reasons, "audit_log_write_failed"],
52
+ },
53
+ },
54
+ stderrWarnings: [
55
+ ...outcome.stderrWarnings,
56
+ `audit log write failed: ${asErrorMessage(error)}`,
57
+ ],
58
+ };
59
+ if (!requireAuditSuccess) {
60
+ return updated;
61
+ }
62
+ return {
63
+ ...updated,
64
+ exitCode: 2,
65
+ output: {
66
+ ...updated.output,
67
+ ok: false,
68
+ safety: {
69
+ ...updated.output.safety,
70
+ action: "block",
71
+ },
72
+ },
73
+ };
74
+ }
75
+ }
76
+ export async function executeRun(policyPath, userArgv) {
77
+ let loaded;
78
+ try {
79
+ loaded = await loadEffectivePolicy(policyPath);
80
+ }
81
+ catch (error) {
82
+ return {
83
+ exitCode: 3,
84
+ output: {
85
+ ok: false,
86
+ allowed: false,
87
+ command: `gog ${userArgv.join(" ")}`.trim(),
88
+ safety: {
89
+ action: "block",
90
+ reasons: [`policy_error:${asErrorMessage(error)}`],
91
+ },
92
+ data: null,
93
+ meta: {
94
+ policy_version: 1,
95
+ },
96
+ },
97
+ stderrWarnings: [],
98
+ };
99
+ }
100
+ const { effective } = loaded;
101
+ const command = `${effective.gog.binary} ${userArgv.join(" ")}`.trim();
102
+ const analyzed = parseArgv(userArgv);
103
+ const decision = decideCommandAllowance(analyzed.positionals, effective.commands.allow, effective.commands.deny);
104
+ let base = buildBaseOutput(command, effective.version, decision.allowed);
105
+ if (!decision.allowed) {
106
+ base.safety.reasons = decision.reasons;
107
+ const outcome = {
108
+ exitCode: 2,
109
+ output: base,
110
+ stderrWarnings: [],
111
+ };
112
+ return await finalizeWithAudit(outcome, effective.logging.audit_file, effective.logging.require_audit_success, {
113
+ phase: "allow_deny",
114
+ policyPath: loaded.policyPath,
115
+ homeConfigPath: loaded.homeConfigPath,
116
+ projectConfigPath: loaded.projectConfigPath,
117
+ });
118
+ }
119
+ const forbidden = findForbiddenOverride(userArgv);
120
+ if (forbidden) {
121
+ base.safety.reasons = [`forbidden_option_override:${forbidden}`];
122
+ const outcome = {
123
+ exitCode: 2,
124
+ output: base,
125
+ stderrWarnings: [],
126
+ };
127
+ return await finalizeWithAudit(outcome, effective.logging.audit_file, effective.logging.require_audit_success, {
128
+ phase: "override_guard",
129
+ forbidden,
130
+ });
131
+ }
132
+ const gogArgs = buildForcedArgs(userArgv, {
133
+ enforceJson: effective.execution.enforce_json,
134
+ enforceNoInput: effective.execution.enforce_no_input,
135
+ account: effective.gog.account,
136
+ client: effective.gog.client,
137
+ });
138
+ const commandResult = await runCommand(effective.gog.binary, gogArgs, effective.execution.timeout_ms);
139
+ if (commandResult.timedOut) {
140
+ base.safety.reasons = ["gog_timeout"];
141
+ const outcome = {
142
+ exitCode: 3,
143
+ output: base,
144
+ stderrWarnings: commandResult.stderr ? [commandResult.stderr.trim()] : [],
145
+ };
146
+ return await finalizeWithAudit(outcome, effective.logging.audit_file, effective.logging.require_audit_success, {
147
+ phase: "gog_execution",
148
+ timedOut: true,
149
+ });
150
+ }
151
+ if (commandResult.spawnError) {
152
+ base.safety.reasons = ["gog_spawn_error"];
153
+ const outcome = {
154
+ exitCode: 3,
155
+ output: base,
156
+ stderrWarnings: [asErrorMessage(commandResult.spawnError)],
157
+ };
158
+ return await finalizeWithAudit(outcome, effective.logging.audit_file, effective.logging.require_audit_success, {
159
+ phase: "gog_execution",
160
+ spawnError: asErrorMessage(commandResult.spawnError),
161
+ });
162
+ }
163
+ if (commandResult.exitCode !== 0) {
164
+ base.safety.reasons = [`gog_exit_${commandResult.exitCode ?? "unknown"}`];
165
+ const outcome = {
166
+ exitCode: 3,
167
+ output: {
168
+ ...base,
169
+ data: {
170
+ stderr: commandResult.stderr.trim(),
171
+ stdout: commandResult.stdout.trim(),
172
+ },
173
+ },
174
+ stderrWarnings: commandResult.stderr ? [commandResult.stderr.trim()] : [],
175
+ };
176
+ return await finalizeWithAudit(outcome, effective.logging.audit_file, effective.logging.require_audit_success, {
177
+ phase: "gog_execution",
178
+ exitCode: commandResult.exitCode,
179
+ });
180
+ }
181
+ let parsedOutput;
182
+ try {
183
+ parsedOutput = JSON.parse(commandResult.stdout);
184
+ }
185
+ catch {
186
+ base.safety.reasons = ["gog_output_invalid_json"];
187
+ const outcome = {
188
+ exitCode: 3,
189
+ output: {
190
+ ...base,
191
+ data: {
192
+ stdout: commandResult.stdout,
193
+ },
194
+ },
195
+ stderrWarnings: [],
196
+ };
197
+ return await finalizeWithAudit(outcome, effective.logging.audit_file, effective.logging.require_audit_success, {
198
+ phase: "gog_output_parse",
199
+ });
200
+ }
201
+ if (!isObject(parsedOutput)) {
202
+ base.safety.reasons = ["gog_output_invalid_schema"];
203
+ const outcome = {
204
+ exitCode: 3,
205
+ output: {
206
+ ...base,
207
+ data: parsedOutput,
208
+ },
209
+ stderrWarnings: [],
210
+ };
211
+ return await finalizeWithAudit(outcome, effective.logging.audit_file, effective.logging.require_audit_success, {
212
+ phase: "gog_output_schema",
213
+ });
214
+ }
215
+ const validatorNames = resolveValidatorsForCommand(effective.validation.rules, analyzed);
216
+ const validatorReasons = [];
217
+ for (const validatorName of validatorNames) {
218
+ const validatorConfig = effective.validation.validators[validatorName];
219
+ if (!validatorConfig) {
220
+ const outcome = {
221
+ exitCode: 2,
222
+ output: {
223
+ ...base,
224
+ safety: {
225
+ action: "block",
226
+ reasons: [`validator_missing:${validatorName}`],
227
+ },
228
+ data: parsedOutput,
229
+ },
230
+ stderrWarnings: [],
231
+ };
232
+ return await finalizeWithAudit(outcome, effective.logging.audit_file, effective.logging.require_audit_success, {
233
+ phase: "validator",
234
+ validatorName,
235
+ });
236
+ }
237
+ const validatorDecision = await runValidator(validatorName, validatorConfig, {
238
+ command,
239
+ argv: userArgv,
240
+ output: parsedOutput,
241
+ policy_version: effective.version,
242
+ });
243
+ validatorReasons.push(`validator:${validatorName}:${validatorDecision.reason}`);
244
+ if (validatorDecision.decision === "block") {
245
+ const outcome = {
246
+ exitCode: 2,
247
+ output: {
248
+ ...base,
249
+ safety: {
250
+ action: "block",
251
+ reasons: [...validatorReasons],
252
+ },
253
+ data: parsedOutput,
254
+ },
255
+ stderrWarnings: [],
256
+ };
257
+ return await finalizeWithAudit(outcome, effective.logging.audit_file, effective.logging.require_audit_success, {
258
+ phase: "validator",
259
+ validatorName,
260
+ decision: "block",
261
+ });
262
+ }
263
+ }
264
+ const outcome = {
265
+ exitCode: 0,
266
+ output: {
267
+ ...base,
268
+ ok: true,
269
+ safety: {
270
+ action: "allow",
271
+ reasons: validatorReasons,
272
+ },
273
+ data: parsedOutput,
274
+ },
275
+ stderrWarnings: [],
276
+ };
277
+ return await finalizeWithAudit(outcome, effective.logging.audit_file, effective.logging.require_audit_success, {
278
+ phase: "completed",
279
+ validators: validatorNames,
280
+ });
281
+ }
282
+ //# sourceMappingURL=run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,SAAS,EAAE,2BAA2B,EAAE,MAAM,eAAe,CAAC;AACvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAQ/C,SAAS,eAAe,CAAC,OAAe,EAAE,OAAe,EAAE,OAAgB;IACzE,OAAO;QACL,EAAE,EAAE,KAAK;QACT,OAAO;QACP,OAAO;QACP,MAAM,EAAE;YACN,MAAM,EAAE,OAAO;YACf,OAAO,EAAE,EAAE;SACZ;QACD,IAAI,EAAE,IAAI;QACV,IAAI,EAAE;YACJ,cAAc,EAAE,OAAO;SACxB;KACF,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CAAC,KAAc;IACpC,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC3B,OAAO,KAAK,CAAC,OAAO,CAAC;IACvB,CAAC;IACD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED,KAAK,UAAU,iBAAiB,CAC9B,OAAmB,EACnB,SAAiB,EACjB,mBAA4B,EAC5B,QAAiC;IAEjC,IAAI,CAAC;QACH,MAAM,cAAc,CAAC,SAAS,EAAE;YAC9B,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,OAAO;YAC/B,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,OAAO;YAC/B,EAAE,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE;YACrB,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM;YACpC,OAAO,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;YAC3C,QAAQ;SACT,CAAC,CAAC;QACH,OAAO,OAAO,CAAC;IACjB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG;YACd,GAAG,OAAO;YACV,MAAM,EAAE;gBACN,GAAG,OAAO,CAAC,MAAM;gBACjB,MAAM,EAAE;oBACN,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM;oBACxB,OAAO,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,wBAAwB,CAAC;iBACtE;aACF;YACD,cAAc,EAAE;gBACd,GAAG,OAAO,CAAC,cAAc;gBACzB,2BAA2B,cAAc,CAAC,KAAK,CAAC,EAAE;aACnD;SACF,CAAC;QAEF,IAAI,CAAC,mBAAmB,EAAE,CAAC;YACzB,OAAO,OAAO,CAAC;QACjB,CAAC;QAED,OAAO;YACL,GAAG,OAAO;YACV,QAAQ,EAAE,CAAC;YACX,MAAM,EAAE;gBACN,GAAG,OAAO,CAAC,MAAM;gBACjB,EAAE,EAAE,KAAK;gBACT,MAAM,EAAE;oBACN,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM;oBACxB,MAAM,EAAE,OAAO;iBAChB;aACF;SACF,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,UAAkB,EAAE,QAAkB;IACrE,IAAI,MAAM,CAAC;IACX,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,mBAAmB,CAAC,UAAU,CAAC,CAAC;IACjD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,QAAQ,EAAE,CAAC;YACX,MAAM,EAAE;gBACN,EAAE,EAAE,KAAK;gBACT,OAAO,EAAE,KAAK;gBACd,OAAO,EAAE,OAAO,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE;gBAC3C,MAAM,EAAE;oBACN,MAAM,EAAE,OAAO;oBACf,OAAO,EAAE,CAAC,gBAAgB,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC;iBACnD;gBACD,IAAI,EAAE,IAAI;gBACV,IAAI,EAAE;oBACJ,cAAc,EAAE,CAAC;iBAClB;aACF;YACD,cAAc,EAAE,EAAE;SACnB,CAAC;IACJ,CAAC;IAED,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,CAAC;IAC7B,MAAM,OAAO,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,MAAM,IAAI,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;IACvE,MAAM,QAAQ,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;IACrC,MAAM,QAAQ,GAAG,sBAAsB,CACrC,QAAQ,CAAC,WAAW,EACpB,SAAS,CAAC,QAAQ,CAAC,KAAK,EACxB,SAAS,CAAC,QAAQ,CAAC,IAAI,CACxB,CAAC;IAEF,IAAI,IAAI,GAAG,eAAe,CAAC,OAAO,EAAE,SAAS,CAAC,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;IAEzE,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;QACtB,IAAI,CAAC,MAAM,CAAC,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC;QACvC,MAAM,OAAO,GAAG;YACd,QAAQ,EAAE,CAAC;YACX,MAAM,EAAE,IAAI;YACZ,cAAc,EAAE,EAAE;SACnB,CAAC;QACF,OAAO,MAAM,iBAAiB,CAAC,OAAO,EAAE,SAAS,CAAC,OAAO,CAAC,UAAU,EAAE,SAAS,CAAC,OAAO,CAAC,qBAAqB,EAAE;YAC7G,KAAK,EAAE,YAAY;YACnB,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,cAAc,EAAE,MAAM,CAAC,cAAc;YACrC,iBAAiB,EAAE,MAAM,CAAC,iBAAiB;SAC5C,CAAC,CAAC;IACL,CAAC;IAED,MAAM,SAAS,GAAG,qBAAqB,CAAC,QAAQ,CAAC,CAAC;IAClD,IAAI,SAAS,EAAE,CAAC;QACd,IAAI,CAAC,MAAM,CAAC,OAAO,GAAG,CAAC,6BAA6B,SAAS,EAAE,CAAC,CAAC;QACjE,MAAM,OAAO,GAAG;YACd,QAAQ,EAAE,CAAC;YACX,MAAM,EAAE,IAAI;YACZ,cAAc,EAAE,EAAE;SACnB,CAAC;QACF,OAAO,MAAM,iBAAiB,CAAC,OAAO,EAAE,SAAS,CAAC,OAAO,CAAC,UAAU,EAAE,SAAS,CAAC,OAAO,CAAC,qBAAqB,EAAE;YAC7G,KAAK,EAAE,gBAAgB;YACvB,SAAS;SACV,CAAC,CAAC;IACL,CAAC;IAED,MAAM,OAAO,GAAG,eAAe,CAAC,QAAQ,EAAE;QACxC,WAAW,EAAE,SAAS,CAAC,SAAS,CAAC,YAAY;QAC7C,cAAc,EAAE,SAAS,CAAC,SAAS,CAAC,gBAAgB;QACpD,OAAO,EAAE,SAAS,CAAC,GAAG,CAAC,OAAO;QAC9B,MAAM,EAAE,SAAS,CAAC,GAAG,CAAC,MAAM;KAC7B,CAAC,CAAC;IAEH,MAAM,aAAa,GAAG,MAAM,UAAU,CACpC,SAAS,CAAC,GAAG,CAAC,MAAM,EACpB,OAAO,EACP,SAAS,CAAC,SAAS,CAAC,UAAU,CAC/B,CAAC;IAEF,IAAI,aAAa,CAAC,QAAQ,EAAE,CAAC;QAC3B,IAAI,CAAC,MAAM,CAAC,OAAO,GAAG,CAAC,aAAa,CAAC,CAAC;QACtC,MAAM,OAAO,GAAG;YACd,QAAQ,EAAE,CAAC;YACX,MAAM,EAAE,IAAI;YACZ,cAAc,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE;SAC1E,CAAC;QACF,OAAO,MAAM,iBAAiB,CAAC,OAAO,EAAE,SAAS,CAAC,OAAO,CAAC,UAAU,EAAE,SAAS,CAAC,OAAO,CAAC,qBAAqB,EAAE;YAC7G,KAAK,EAAE,eAAe;YACtB,QAAQ,EAAE,IAAI;SACf,CAAC,CAAC;IACL,CAAC;IAED,IAAI,aAAa,CAAC,UAAU,EAAE,CAAC;QAC7B,IAAI,CAAC,MAAM,CAAC,OAAO,GAAG,CAAC,iBAAiB,CAAC,CAAC;QAC1C,MAAM,OAAO,GAAG;YACd,QAAQ,EAAE,CAAC;YACX,MAAM,EAAE,IAAI;YACZ,cAAc,EAAE,CAAC,cAAc,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;SAC3D,CAAC;QACF,OAAO,MAAM,iBAAiB,CAAC,OAAO,EAAE,SAAS,CAAC,OAAO,CAAC,UAAU,EAAE,SAAS,CAAC,OAAO,CAAC,qBAAqB,EAAE;YAC7G,KAAK,EAAE,eAAe;YACtB,UAAU,EAAE,cAAc,CAAC,aAAa,CAAC,UAAU,CAAC;SACrD,CAAC,CAAC;IACL,CAAC;IAED,IAAI,aAAa,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;QACjC,IAAI,CAAC,MAAM,CAAC,OAAO,GAAG,CAAC,YAAY,aAAa,CAAC,QAAQ,IAAI,SAAS,EAAE,CAAC,CAAC;QAC1E,MAAM,OAAO,GAAG;YACd,QAAQ,EAAE,CAAC;YACX,MAAM,EAAE;gBACN,GAAG,IAAI;gBACP,IAAI,EAAE;oBACJ,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,IAAI,EAAE;oBACnC,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,IAAI,EAAE;iBACpC;aACF;YACD,cAAc,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE;SAC1E,CAAC;QACF,OAAO,MAAM,iBAAiB,CAAC,OAAO,EAAE,SAAS,CAAC,OAAO,CAAC,UAAU,EAAE,SAAS,CAAC,OAAO,CAAC,qBAAqB,EAAE;YAC7G,KAAK,EAAE,eAAe;YACtB,QAAQ,EAAE,aAAa,CAAC,QAAQ;SACjC,CAAC,CAAC;IACL,CAAC;IAED,IAAI,YAAqB,CAAC;IAC1B,IAAI,CAAC;QACH,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IAClD,CAAC;IAAC,MAAM,CAAC;QACP,IAAI,CAAC,MAAM,CAAC,OAAO,GAAG,CAAC,yBAAyB,CAAC,CAAC;QAClD,MAAM,OAAO,GAAG;YACd,QAAQ,EAAE,CAAC;YACX,MAAM,EAAE;gBACN,GAAG,IAAI;gBACP,IAAI,EAAE;oBACJ,MAAM,EAAE,aAAa,CAAC,MAAM;iBAC7B;aACF;YACD,cAAc,EAAE,EAAE;SACnB,CAAC;QACF,OAAO,MAAM,iBAAiB,CAAC,OAAO,EAAE,SAAS,CAAC,OAAO,CAAC,UAAU,EAAE,SAAS,CAAC,OAAO,CAAC,qBAAqB,EAAE;YAC7G,KAAK,EAAE,kBAAkB;SAC1B,CAAC,CAAC;IACL,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;QAC5B,IAAI,CAAC,MAAM,CAAC,OAAO,GAAG,CAAC,2BAA2B,CAAC,CAAC;QACpD,MAAM,OAAO,GAAG;YACd,QAAQ,EAAE,CAAC;YACX,MAAM,EAAE;gBACN,GAAG,IAAI;gBACP,IAAI,EAAE,YAAY;aACnB;YACD,cAAc,EAAE,EAAE;SACnB,CAAC;QACF,OAAO,MAAM,iBAAiB,CAAC,OAAO,EAAE,SAAS,CAAC,OAAO,CAAC,UAAU,EAAE,SAAS,CAAC,OAAO,CAAC,qBAAqB,EAAE;YAC7G,KAAK,EAAE,mBAAmB;SAC3B,CAAC,CAAC;IACL,CAAC;IAED,MAAM,cAAc,GAAG,2BAA2B,CAAC,SAAS,CAAC,UAAU,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACzF,MAAM,gBAAgB,GAAa,EAAE,CAAC;IAEtC,KAAK,MAAM,aAAa,IAAI,cAAc,EAAE,CAAC;QAC3C,MAAM,eAAe,GAAG,SAAS,CAAC,UAAU,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;QACvE,IAAI,CAAC,eAAe,EAAE,CAAC;YACrB,MAAM,OAAO,GAAG;gBACd,QAAQ,EAAE,CAAC;gBACX,MAAM,EAAE;oBACN,GAAG,IAAI;oBACP,MAAM,EAAE;wBACN,MAAM,EAAE,OAAgB;wBACxB,OAAO,EAAE,CAAC,qBAAqB,aAAa,EAAE,CAAC;qBAChD;oBACD,IAAI,EAAE,YAAY;iBACnB;gBACD,cAAc,EAAE,EAAE;aACnB,CAAC;YAEF,OAAO,MAAM,iBAAiB,CAC5B,OAAO,EACP,SAAS,CAAC,OAAO,CAAC,UAAU,EAC5B,SAAS,CAAC,OAAO,CAAC,qBAAqB,EACvC;gBACE,KAAK,EAAE,WAAW;gBAClB,aAAa;aACd,CACF,CAAC;QACJ,CAAC;QAED,MAAM,iBAAiB,GAAG,MAAM,YAAY,CAAC,aAAa,EAAE,eAAe,EAAE;YAC3E,OAAO;YACP,IAAI,EAAE,QAAQ;YACd,MAAM,EAAE,YAAY;YACpB,cAAc,EAAE,SAAS,CAAC,OAAO;SAClC,CAAC,CAAC;QAEH,gBAAgB,CAAC,IAAI,CAAC,aAAa,aAAa,IAAI,iBAAiB,CAAC,MAAM,EAAE,CAAC,CAAC;QAEhF,IAAI,iBAAiB,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;YAC3C,MAAM,OAAO,GAAG;gBACd,QAAQ,EAAE,CAAC;gBACX,MAAM,EAAE;oBACN,GAAG,IAAI;oBACP,MAAM,EAAE;wBACN,MAAM,EAAE,OAAgB;wBACxB,OAAO,EAAE,CAAC,GAAG,gBAAgB,CAAC;qBAC/B;oBACD,IAAI,EAAE,YAAY;iBACnB;gBACD,cAAc,EAAE,EAAE;aACnB,CAAC;YAEF,OAAO,MAAM,iBAAiB,CAC5B,OAAO,EACP,SAAS,CAAC,OAAO,CAAC,UAAU,EAC5B,SAAS,CAAC,OAAO,CAAC,qBAAqB,EACvC;gBACE,KAAK,EAAE,WAAW;gBAClB,aAAa;gBACb,QAAQ,EAAE,OAAO;aAClB,CACF,CAAC;QACJ,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG;QACd,QAAQ,EAAE,CAAC;QACX,MAAM,EAAE;YACN,GAAG,IAAI;YACP,EAAE,EAAE,IAAI;YACR,MAAM,EAAE;gBACN,MAAM,EAAE,OAAgB;gBACxB,OAAO,EAAE,gBAAgB;aAC1B;YACD,IAAI,EAAE,YAAY;SACnB;QACD,cAAc,EAAE,EAAE;KACnB,CAAC;IAEF,OAAO,MAAM,iBAAiB,CAC5B,OAAO,EACP,SAAS,CAAC,OAAO,CAAC,UAAU,EAC5B,SAAS,CAAC,OAAO,CAAC,qBAAqB,EACvC;QACE,KAAK,EAAE,WAAW;QAClB,UAAU,EAAE,cAAc;KAC3B,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,88 @@
1
+ export type SafetyAction = "allow" | "block";
2
+ export interface SafetySummary {
3
+ action: SafetyAction;
4
+ reasons: string[];
5
+ }
6
+ export interface RunOutput {
7
+ ok: boolean;
8
+ allowed: boolean;
9
+ command: string;
10
+ safety: SafetySummary;
11
+ data: unknown;
12
+ meta: {
13
+ policy_version: number;
14
+ };
15
+ }
16
+ export interface GogConfig {
17
+ binary: string;
18
+ account: string;
19
+ client: string;
20
+ }
21
+ export interface ExecutionConfig {
22
+ enforce_json: boolean;
23
+ enforce_no_input: boolean;
24
+ timeout_ms: number;
25
+ }
26
+ export interface CommandsConfig {
27
+ allow: string[];
28
+ deny: string[];
29
+ }
30
+ export interface ValidationRule {
31
+ match: string;
32
+ validators: string[];
33
+ }
34
+ export interface RegexValidatorConfig {
35
+ type: "regex";
36
+ config: {
37
+ patterns: string[];
38
+ };
39
+ }
40
+ export interface ExternalCommandValidatorConfig {
41
+ type: "external_command";
42
+ command: string;
43
+ args: string[];
44
+ timeout_ms: number;
45
+ }
46
+ export type ValidatorConfig = RegexValidatorConfig | ExternalCommandValidatorConfig;
47
+ export interface ValidationConfig {
48
+ rules: ValidationRule[];
49
+ validators: Record<string, ValidatorConfig>;
50
+ }
51
+ export interface LoggingConfig {
52
+ level: string;
53
+ audit_file: string;
54
+ require_audit_success: boolean;
55
+ }
56
+ export interface EffectivePolicy {
57
+ version: number;
58
+ gog: GogConfig;
59
+ execution: ExecutionConfig;
60
+ commands: CommandsConfig;
61
+ validation: ValidationConfig;
62
+ logging: LoggingConfig;
63
+ }
64
+ export interface PartialConfig {
65
+ version?: unknown;
66
+ gog?: Partial<GogConfig>;
67
+ execution?: Partial<ExecutionConfig>;
68
+ commands?: Partial<CommandsConfig>;
69
+ validation?: {
70
+ rules?: ValidationRule[];
71
+ validators?: Record<string, ValidatorConfig>;
72
+ };
73
+ logging?: Partial<LoggingConfig>;
74
+ }
75
+ export interface ArgvAnalysis {
76
+ positionals: string[];
77
+ options: Set<string>;
78
+ }
79
+ export interface ValidatorDecision {
80
+ decision: SafetyAction;
81
+ reason: string;
82
+ }
83
+ export interface LoadedConfigSet {
84
+ policyPath: string;
85
+ homeConfigPath?: string;
86
+ projectConfigPath?: string;
87
+ effective: EffectivePolicy;
88
+ }
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,7 @@
1
+ import type { ValidatorConfig, ValidatorDecision } from "./types.js";
2
+ export declare function runValidator(validatorName: string, config: ValidatorConfig, context: {
3
+ command: string;
4
+ argv: string[];
5
+ output: unknown;
6
+ policy_version: number;
7
+ }): Promise<ValidatorDecision>;
@@ -0,0 +1,92 @@
1
+ import { runCommandWithJsonInput } from "./process.js";
2
+ function isObject(value) {
3
+ return typeof value === "object" && value !== null && !Array.isArray(value);
4
+ }
5
+ async function runRegexValidator(config, output) {
6
+ const serialized = JSON.stringify(output);
7
+ for (const pattern of config.config.patterns) {
8
+ try {
9
+ const re = new RegExp(pattern);
10
+ if (re.test(serialized)) {
11
+ return {
12
+ decision: "block",
13
+ reason: `regex_matched:${pattern}`,
14
+ };
15
+ }
16
+ }
17
+ catch {
18
+ return {
19
+ decision: "block",
20
+ reason: `regex_invalid:${pattern}`,
21
+ };
22
+ }
23
+ }
24
+ return {
25
+ decision: "allow",
26
+ reason: "regex_no_match",
27
+ };
28
+ }
29
+ async function runExternalValidator(config, payload) {
30
+ const result = await runCommandWithJsonInput(config.command, config.args, payload, config.timeout_ms);
31
+ if (result.timedOut) {
32
+ return {
33
+ decision: "block",
34
+ reason: "external_validator_timeout",
35
+ };
36
+ }
37
+ if (result.spawnError || result.writeError) {
38
+ return {
39
+ decision: "block",
40
+ reason: "external_validator_spawn_error",
41
+ };
42
+ }
43
+ if (result.exitCode !== 0) {
44
+ return {
45
+ decision: "block",
46
+ reason: `external_validator_exit_${result.exitCode}`,
47
+ };
48
+ }
49
+ let parsed;
50
+ try {
51
+ parsed = JSON.parse(result.stdout);
52
+ }
53
+ catch {
54
+ return {
55
+ decision: "block",
56
+ reason: "external_validator_non_json_output",
57
+ };
58
+ }
59
+ if (!isObject(parsed)) {
60
+ return {
61
+ decision: "block",
62
+ reason: "external_validator_invalid_contract",
63
+ };
64
+ }
65
+ const decision = parsed.decision;
66
+ const reason = parsed.reason;
67
+ if ((decision !== "allow" && decision !== "block")
68
+ || typeof reason !== "string"
69
+ || reason.trim().length === 0) {
70
+ return {
71
+ decision: "block",
72
+ reason: "external_validator_invalid_contract",
73
+ };
74
+ }
75
+ return {
76
+ decision,
77
+ reason,
78
+ };
79
+ }
80
+ export async function runValidator(validatorName, config, context) {
81
+ if (config.type === "regex") {
82
+ return await runRegexValidator(config, context.output);
83
+ }
84
+ if (config.type === "external_command") {
85
+ return await runExternalValidator(config, context);
86
+ }
87
+ return {
88
+ decision: "block",
89
+ reason: `unsupported_validator_type:${validatorName}`,
90
+ };
91
+ }
92
+ //# sourceMappingURL=validators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validators.js","sourceRoot":"","sources":["../src/validators.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "gog-safe",
3
+ "version": "0.1.0",
4
+ "private": false,
5
+ "description": "Policy-enforced wrapper for gog",
6
+ "type": "module",
7
+ "bin": {
8
+ "gog-safe": "dist/index.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc -p tsconfig.json",
12
+ "dev": "tsx src/index.ts",
13
+ "test": "vitest run",
14
+ "typecheck": "tsc --noEmit"
15
+ },
16
+ "engines": {
17
+ "node": ">=24"
18
+ },
19
+ "dependencies": {
20
+ "yaml": "^2.8.1"
21
+ },
22
+ "devDependencies": {
23
+ "@types/node": "^24.3.0",
24
+ "tsx": "^4.20.6",
25
+ "typescript": "^5.9.2",
26
+ "vitest": "^2.1.9"
27
+ },
28
+ "keywords": [],
29
+ "author": "catnose <hello@catnose.me> (https://catnose.me)",
30
+ "license": "MIT",
31
+ "files": [
32
+ "dist",
33
+ "README.md",
34
+ "LICENSE"
35
+ ]
36
+ }