@scheduler-systems/gal-run 0.0.377 → 0.0.378
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/index.cjs +148 -6
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -3970,7 +3970,7 @@ var cliVersion, defaultApiUrl, BUILD_CONSTANTS, constants_default;
|
|
|
3970
3970
|
var init_constants = __esm({
|
|
3971
3971
|
"src/constants.ts"() {
|
|
3972
3972
|
"use strict";
|
|
3973
|
-
cliVersion = true ? "0.0.
|
|
3973
|
+
cliVersion = true ? "0.0.378" : "0.0.0-dev";
|
|
3974
3974
|
defaultApiUrl = true ? "https://api.gal.run" : "http://localhost:3000";
|
|
3975
3975
|
BUILD_CONSTANTS = Object.freeze([cliVersion, defaultApiUrl]);
|
|
3976
3976
|
constants_default = BUILD_CONSTANTS;
|
|
@@ -4880,7 +4880,7 @@ function detectEnvironment() {
|
|
|
4880
4880
|
return "dev";
|
|
4881
4881
|
}
|
|
4882
4882
|
try {
|
|
4883
|
-
const version2 = true ? "0.0.
|
|
4883
|
+
const version2 = true ? "0.0.378" : void 0;
|
|
4884
4884
|
if (version2 && version2.includes("-local")) {
|
|
4885
4885
|
return "dev";
|
|
4886
4886
|
}
|
|
@@ -5249,7 +5249,7 @@ function getId() {
|
|
|
5249
5249
|
}
|
|
5250
5250
|
function getCliVersion() {
|
|
5251
5251
|
try {
|
|
5252
|
-
return true ? "0.0.
|
|
5252
|
+
return true ? "0.0.378" : "0.0.0-dev";
|
|
5253
5253
|
} catch {
|
|
5254
5254
|
return "0.0.0-dev";
|
|
5255
5255
|
}
|
|
@@ -54040,6 +54040,84 @@ function generateGenericHook(platform5, patterns) {
|
|
|
54040
54040
|
}
|
|
54041
54041
|
};
|
|
54042
54042
|
}
|
|
54043
|
+
function generateSdlcPrePushHook(apiUrl, orgName) {
|
|
54044
|
+
return `#!/bin/sh
|
|
54045
|
+
# GAL SDLC Phase-Gate Pre-Push Hook
|
|
54046
|
+
# Installed by: gal enforce install --sdlc
|
|
54047
|
+
# Blocks pushes when the SDLC phase gate for the branch is not met.
|
|
54048
|
+
# Fail-open: if the API is unreachable the push is allowed.
|
|
54049
|
+
# To skip: git push --no-verify
|
|
54050
|
+
|
|
54051
|
+
BRANCH=$(git rev-parse --abbrev-ref HEAD)
|
|
54052
|
+
|
|
54053
|
+
# Skip check for main/master \u2014 phase gates apply to feature branches
|
|
54054
|
+
case "$BRANCH" in
|
|
54055
|
+
main|master) exit 0 ;;
|
|
54056
|
+
esac
|
|
54057
|
+
|
|
54058
|
+
API_URL="${apiUrl}"
|
|
54059
|
+
ORG_NAME="${orgName}"
|
|
54060
|
+
|
|
54061
|
+
RESPONSE=$(curl -sf -w "\\n%{http_code}" \\
|
|
54062
|
+
"\${API_URL}/organizations/\${ORG_NAME}/enforcement/sdlc/gate?branch=\${BRANCH}" \\
|
|
54063
|
+
2>/dev/null) || {
|
|
54064
|
+
# API unreachable \u2014 fail open
|
|
54065
|
+
exit 0
|
|
54066
|
+
}
|
|
54067
|
+
|
|
54068
|
+
HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
|
|
54069
|
+
BODY=$(echo "$RESPONSE" | sed '$ d')
|
|
54070
|
+
|
|
54071
|
+
if [ "$HTTP_CODE" != "200" ]; then
|
|
54072
|
+
# Non-200 \u2014 fail open
|
|
54073
|
+
exit 0
|
|
54074
|
+
fi
|
|
54075
|
+
|
|
54076
|
+
ALLOWED=$(echo "$BODY" | grep -o '"allowed"\\s*:\\s*\\(true\\|false\\)' | grep -o '\\(true\\|false\\)')
|
|
54077
|
+
|
|
54078
|
+
if [ "$ALLOWED" = "false" ]; then
|
|
54079
|
+
MESSAGE=$(echo "$BODY" | grep -o '"message"\\s*:\\s*"[^"]*"' | head -1 | sed 's/"message"\\s*:\\s*"//;s/"$//')
|
|
54080
|
+
echo ""
|
|
54081
|
+
echo "\\033[31m[GAL] SDLC phase gate blocked this push.\\033[0m"
|
|
54082
|
+
echo "\\033[33m Branch: $BRANCH\\033[0m"
|
|
54083
|
+
if [ -n "$MESSAGE" ]; then
|
|
54084
|
+
echo "\\033[33m Reason: $MESSAGE\\033[0m"
|
|
54085
|
+
fi
|
|
54086
|
+
echo "\\033[33m Complete the required SDLC phase before pushing.\\033[0m"
|
|
54087
|
+
echo ""
|
|
54088
|
+
exit 1
|
|
54089
|
+
fi
|
|
54090
|
+
|
|
54091
|
+
exit 0
|
|
54092
|
+
`;
|
|
54093
|
+
}
|
|
54094
|
+
function generateSdlcAgentHook(apiUrl) {
|
|
54095
|
+
const hook = {
|
|
54096
|
+
type: "pre_tool_call",
|
|
54097
|
+
description: "GAL SDLC phase-gate enforcement \u2014 blocks tool calls when the required SDLC phase is not met.",
|
|
54098
|
+
api_url: apiUrl,
|
|
54099
|
+
matchers: [
|
|
54100
|
+
{
|
|
54101
|
+
tool_name: "Bash",
|
|
54102
|
+
command_pattern: "git\\s+push",
|
|
54103
|
+
action: "check_sdlc_gate"
|
|
54104
|
+
},
|
|
54105
|
+
{
|
|
54106
|
+
tool_name: "Edit",
|
|
54107
|
+
file_pattern: "^\\.github/workflows/.*\\.yml$",
|
|
54108
|
+
action: "check_sdlc_gate"
|
|
54109
|
+
}
|
|
54110
|
+
],
|
|
54111
|
+
check_sdlc_gate: {
|
|
54112
|
+
method: "GET",
|
|
54113
|
+
url: `${apiUrl}/enforcement/sdlc/gate`,
|
|
54114
|
+
query_params: { branch: "{{current_branch}}" },
|
|
54115
|
+
block_when: { allowed: false },
|
|
54116
|
+
fail_open: true
|
|
54117
|
+
}
|
|
54118
|
+
};
|
|
54119
|
+
return JSON.stringify(hook, null, 2);
|
|
54120
|
+
}
|
|
54043
54121
|
var init_hook_generator = __esm({
|
|
54044
54122
|
"src/enforcement/hook-generator.ts"() {
|
|
54045
54123
|
"use strict";
|
|
@@ -56667,7 +56745,7 @@ function getEnforcementHookPaths(basePath, platform5) {
|
|
|
56667
56745
|
}
|
|
56668
56746
|
function createEnforceCommand() {
|
|
56669
56747
|
const enforce = new Command("enforce").description("Install and manage organization security policies locally");
|
|
56670
|
-
enforce.command("install").description("Install organization-approved safety hooks from GAL").option("-o, --org <orgName>", "Organization name").option("-p, --platform <platform>", "Specific platform (claude, cursor, gemini, codex, windsurf)").option("--all", "Install hooks for all detected platforms").option("--path <path>", "Base path (default: current directory)").option("--force", "Overwrite existing hooks").option("--dry-run", "Show what would be installed without making changes").action(async (options) => {
|
|
56748
|
+
enforce.command("install").description("Install organization-approved safety hooks from GAL").option("-o, --org <orgName>", "Organization name").option("-p, --platform <platform>", "Specific platform (claude, cursor, gemini, codex, windsurf)").option("--all", "Install hooks for all detected platforms").option("--path <path>", "Base path (default: current directory)").option("--force", "Overwrite existing hooks").option("--dry-run", "Show what would be installed without making changes").option("--sdlc", "Install SDLC phase-gate hooks (git pre-push + Claude Code agent hook)").action(async (options) => {
|
|
56671
56749
|
const spinner = ora();
|
|
56672
56750
|
try {
|
|
56673
56751
|
const config2 = ConfigManager.load();
|
|
@@ -56737,6 +56815,29 @@ Installing hooks for: ${platforms.join(", ")}`));
|
|
|
56737
56815
|
const msg = err instanceof Error ? err.message : String(err);
|
|
56738
56816
|
spinner.warn(`Git pre-commit hook: ${msg}`);
|
|
56739
56817
|
}
|
|
56818
|
+
if (options.sdlc) {
|
|
56819
|
+
const sdlcApiUrl = config2.apiUrl || defaultApiUrl7;
|
|
56820
|
+
spinner.start("Installing SDLC git pre-push hook...");
|
|
56821
|
+
try {
|
|
56822
|
+
if (!options.dryRun) {
|
|
56823
|
+
await installSdlcPrePushHook(basePath, sdlcApiUrl, orgName, options.force);
|
|
56824
|
+
}
|
|
56825
|
+
spinner.succeed(`Installed SDLC git pre-push hook \u2192 ${source_default.dim(".git/hooks/pre-push")}`);
|
|
56826
|
+
} catch (err) {
|
|
56827
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
56828
|
+
spinner.warn(`SDLC git pre-push hook: ${msg}`);
|
|
56829
|
+
}
|
|
56830
|
+
spinner.start("Installing SDLC Claude Code agent hook...");
|
|
56831
|
+
try {
|
|
56832
|
+
if (!options.dryRun) {
|
|
56833
|
+
await installSdlcAgentHook(basePath, sdlcApiUrl, options.force);
|
|
56834
|
+
}
|
|
56835
|
+
spinner.succeed(`Installed SDLC agent hook \u2192 ${source_default.dim(".claude/hooks/sdlc-phase-gate.json")}`);
|
|
56836
|
+
} catch (err) {
|
|
56837
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
56838
|
+
spinner.warn(`SDLC agent hook: ${msg}`);
|
|
56839
|
+
}
|
|
56840
|
+
}
|
|
56740
56841
|
console.log(source_default.green("\nEnforcement hooks installed successfully!"));
|
|
56741
56842
|
console.log(source_default.dim("AI agents will now enforce your organization's security policies."));
|
|
56742
56843
|
console.log(source_default.dim("Git commits will be validated against approved policy via pre-commit hook."));
|
|
@@ -57673,7 +57774,46 @@ async function removeGitPrecommitHook(basePath) {
|
|
|
57673
57774
|
}
|
|
57674
57775
|
await (0, import_promises4.writeFile)(hookPath, filtered.join("\n"), "utf-8");
|
|
57675
57776
|
}
|
|
57676
|
-
|
|
57777
|
+
async function installSdlcPrePushHook(basePath, apiUrl, orgName, force) {
|
|
57778
|
+
const gitDir = (0, import_node_path3.join)(basePath, ".git");
|
|
57779
|
+
if (!(0, import_node_fs2.existsSync)(gitDir)) {
|
|
57780
|
+
throw new Error("Not a git repository");
|
|
57781
|
+
}
|
|
57782
|
+
const hooksDir = (0, import_node_path3.join)(gitDir, "hooks");
|
|
57783
|
+
const hookPath = (0, import_node_path3.join)(hooksDir, "pre-push");
|
|
57784
|
+
if ((0, import_node_fs2.existsSync)(hookPath)) {
|
|
57785
|
+
const existing = await (0, import_promises4.readFile)(hookPath, "utf-8");
|
|
57786
|
+
if (existing.includes(GAL_SDLC_PREPUSH_MARKER)) {
|
|
57787
|
+
if (!force) {
|
|
57788
|
+
throw new Error("SDLC pre-push hook already installed. Use --force to overwrite.");
|
|
57789
|
+
}
|
|
57790
|
+
}
|
|
57791
|
+
}
|
|
57792
|
+
await (0, import_promises4.mkdir)(hooksDir, { recursive: true });
|
|
57793
|
+
const hookContent = generateSdlcPrePushHook(apiUrl, orgName);
|
|
57794
|
+
if ((0, import_node_fs2.existsSync)(hookPath)) {
|
|
57795
|
+
const existing = await (0, import_promises4.readFile)(hookPath, "utf-8");
|
|
57796
|
+
if (!existing.includes(GAL_SDLC_PREPUSH_MARKER)) {
|
|
57797
|
+
const appended = existing.trimEnd() + "\n\n" + hookContent.replace("#!/bin/sh\n", "");
|
|
57798
|
+
await (0, import_promises4.writeFile)(hookPath, appended, "utf-8");
|
|
57799
|
+
await (0, import_promises4.chmod)(hookPath, 493);
|
|
57800
|
+
return;
|
|
57801
|
+
}
|
|
57802
|
+
}
|
|
57803
|
+
await (0, import_promises4.writeFile)(hookPath, hookContent, "utf-8");
|
|
57804
|
+
await (0, import_promises4.chmod)(hookPath, 493);
|
|
57805
|
+
}
|
|
57806
|
+
async function installSdlcAgentHook(basePath, apiUrl, force) {
|
|
57807
|
+
const claudeHooksDir = (0, import_node_path3.join)(basePath, ".claude", "hooks");
|
|
57808
|
+
const hookPath = (0, import_node_path3.join)(claudeHooksDir, "sdlc-phase-gate.json");
|
|
57809
|
+
if ((0, import_node_fs2.existsSync)(hookPath) && !force) {
|
|
57810
|
+
throw new Error("SDLC agent hook already installed. Use --force to overwrite.");
|
|
57811
|
+
}
|
|
57812
|
+
await (0, import_promises4.mkdir)(claudeHooksDir, { recursive: true });
|
|
57813
|
+
const hookContent = generateSdlcAgentHook(apiUrl);
|
|
57814
|
+
await (0, import_promises4.writeFile)(hookPath, hookContent, "utf-8");
|
|
57815
|
+
}
|
|
57816
|
+
var import_promises4, import_node_fs2, import_node_path3, import_node_crypto, defaultApiUrl7, PLATFORM_DIRS3, SCAN_PLATFORM_DIRS, ENFORCEMENT_HOOK_SUPPORT, GAL_PRECOMMIT_MARKER, GAL_PRECOMMIT_CONTENT, GAL_SDLC_PREPUSH_MARKER;
|
|
57677
57817
|
var init_enforce = __esm({
|
|
57678
57818
|
"src/commands/enforce.ts"() {
|
|
57679
57819
|
"use strict";
|
|
@@ -57685,6 +57825,7 @@ var init_enforce = __esm({
|
|
|
57685
57825
|
import_node_path3 = require("node:path");
|
|
57686
57826
|
import_node_crypto = require("node:crypto");
|
|
57687
57827
|
init_enforcement();
|
|
57828
|
+
init_hook_generator();
|
|
57688
57829
|
init_config_manager();
|
|
57689
57830
|
init_constants();
|
|
57690
57831
|
init_CoreServiceProvider();
|
|
@@ -57742,6 +57883,7 @@ fi
|
|
|
57742
57883
|
|
|
57743
57884
|
exit $EXIT_CODE
|
|
57744
57885
|
`;
|
|
57886
|
+
GAL_SDLC_PREPUSH_MARKER = "# GAL SDLC Phase-Gate Pre-Push Hook";
|
|
57745
57887
|
}
|
|
57746
57888
|
});
|
|
57747
57889
|
|
|
@@ -70762,7 +70904,7 @@ var init_index = __esm({
|
|
|
70762
70904
|
});
|
|
70763
70905
|
|
|
70764
70906
|
// src/bootstrap.ts
|
|
70765
|
-
var cliVersion10 = true ? "0.0.
|
|
70907
|
+
var cliVersion10 = true ? "0.0.378" : "0.0.0-dev";
|
|
70766
70908
|
var args = process.argv.slice(2);
|
|
70767
70909
|
var requestedGlobalHelp = args.length === 1 && (args[0] === "--help" || args[0] === "-h");
|
|
70768
70910
|
var requestedVersion = args.length === 1 && (args[0] === "--version" || args[0] === "-V");
|
package/package.json
CHANGED