sequelizer 0.1.4 → 0.1.6
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.
- checksums.yaml +4 -4
- data/.claude/settings.local.json +64 -0
- data/.devcontainer/.p10k.zsh +1713 -0
- data/.devcontainer/.zshrc +29 -0
- data/.devcontainer/Dockerfile +137 -0
- data/.devcontainer/copy-claude-credentials.sh +32 -0
- data/.devcontainer/devcontainer.json +102 -0
- data/.devcontainer/init-firewall.sh +123 -0
- data/.devcontainer/setup-credentials.sh +95 -0
- data/.github/workflows/test.yml +1 -1
- data/.gitignore +6 -1
- data/.overcommit.yml +73 -0
- data/.rubocop.yml +167 -0
- data/CHANGELOG.md +24 -0
- data/CLAUDE.md +219 -0
- data/Gemfile +6 -2
- data/Gemfile.lock +158 -0
- data/Guardfile +1 -1
- data/Rakefile +28 -3
- data/lib/sequel/extensions/cold_col.rb +436 -0
- data/lib/sequel/extensions/db_opts.rb +65 -4
- data/lib/sequel/extensions/make_readyable.rb +148 -30
- data/lib/sequel/extensions/more_sql.rb +76 -0
- data/lib/sequel/extensions/settable.rb +64 -0
- data/lib/sequel/extensions/sql_recorder.rb +85 -0
- data/lib/sequel/extensions/unionize.rb +169 -0
- data/lib/sequel/extensions/usable.rb +30 -1
- data/lib/sequelizer/cli.rb +61 -18
- data/lib/sequelizer/connection_maker.rb +54 -72
- data/lib/sequelizer/env_config.rb +6 -6
- data/lib/sequelizer/gemfile_modifier.rb +23 -21
- data/lib/sequelizer/monkey_patches/database_in_after_connect.rb +7 -5
- data/lib/sequelizer/options.rb +97 -18
- data/lib/sequelizer/options_hash.rb +2 -0
- data/lib/sequelizer/version.rb +3 -1
- data/lib/sequelizer/yaml_config.rb +9 -3
- data/lib/sequelizer.rb +65 -9
- data/sequelizer.gemspec +12 -7
- data/test/lib/sequel/extensions/test_cold_col.rb +251 -0
- data/test/lib/sequel/extensions/test_db_opts.rb +10 -8
- data/test/lib/sequel/extensions/test_make_readyable.rb +199 -28
- data/test/lib/sequel/extensions/test_more_sql.rb +132 -0
- data/test/lib/sequel/extensions/test_settable.rb +109 -0
- data/test/lib/sequel/extensions/test_sql_recorder.rb +231 -0
- data/test/lib/sequel/extensions/test_unionize.rb +76 -0
- data/test/lib/sequel/extensions/test_usable.rb +5 -2
- data/test/lib/sequelizer/test_connection_maker.rb +21 -17
- data/test/lib/sequelizer/test_env_config.rb +5 -2
- data/test/lib/sequelizer/test_gemfile_modifier.rb +7 -6
- data/test/lib/sequelizer/test_options.rb +14 -9
- data/test/lib/sequelizer/test_yaml_config.rb +13 -12
- data/test/test_helper.rb +36 -8
- metadata +107 -28
- data/lib/sequel/extensions/sqls.rb +0 -31
@@ -0,0 +1,29 @@
|
|
1
|
+
# Enable Powerlevel10k instant prompt. Should stay close to the top of ~/.zshrc.
|
2
|
+
# Initialization code that may require console input (password prompts, [y/n]
|
3
|
+
# confirmations, etc.) must go above this block; everything else may go below.
|
4
|
+
if [[ -r "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" ]]; then
|
5
|
+
source "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh"
|
6
|
+
fi
|
7
|
+
|
8
|
+
# Suppress Powerlevel10k instant prompt warning
|
9
|
+
typeset -g POWERLEVEL9K_INSTANT_PROMPT=quiet
|
10
|
+
|
11
|
+
export LANG='en_US.UTF-8'
|
12
|
+
export LANGUAGE='en_US:en'
|
13
|
+
export LC_ALL='en_US.UTF-8'
|
14
|
+
export TERM=xterm
|
15
|
+
|
16
|
+
##### Zsh/Oh-my-Zsh Configuration
|
17
|
+
export ZSH="/home/rubydev/.oh-my-zsh"
|
18
|
+
|
19
|
+
ZSH_THEME="powerlevel10k/powerlevel10k"
|
20
|
+
plugins=(git history-substring-search)
|
21
|
+
|
22
|
+
|
23
|
+
ZSH_THEME="powerlevel10k/powerlevel10k"
|
24
|
+
bindkey "\$terminfo[kcuu1]" history-substring-search-up
|
25
|
+
bindkey "\$terminfo[kcud1]" history-substring-search-down
|
26
|
+
source $ZSH/oh-my-zsh.sh
|
27
|
+
|
28
|
+
# To customize prompt, run `p10k configure` or edit ~/.p10k.zsh.
|
29
|
+
[[ ! -f ~/.p10k.zsh ]] || source ~/.p10k.zsh
|
@@ -0,0 +1,137 @@
|
|
1
|
+
# Start with Ruby 3.2 slim for a smaller image
|
2
|
+
FROM ruby:3.2-slim
|
3
|
+
|
4
|
+
# Set timezone argument (can be overridden in devcontainer.json)
|
5
|
+
ARG TZ=America/Los_Angeles
|
6
|
+
ENV TZ=$TZ
|
7
|
+
|
8
|
+
# Set host home directory for copying credentials
|
9
|
+
ARG HOST_HOME
|
10
|
+
|
11
|
+
# Set DEVCONTAINER environment variable to help with orientation
|
12
|
+
ENV DEVCONTAINER=true
|
13
|
+
|
14
|
+
# Create a non-root user (following Claude Code pattern)
|
15
|
+
ARG USERNAME=rubydev
|
16
|
+
ARG USER_UID=1001
|
17
|
+
ARG USER_GID=$USER_UID
|
18
|
+
|
19
|
+
# Install system dependencies first, then set up GitHub CLI repository
|
20
|
+
# (need wget/curl for GitHub CLI setup)
|
21
|
+
RUN apt-get update && apt-get install -y \
|
22
|
+
# Essential build tools for Ruby gems
|
23
|
+
build-essential \
|
24
|
+
libpq-dev \
|
25
|
+
libvips \
|
26
|
+
pkg-config \
|
27
|
+
# Network and system tools (needed for GitHub CLI setup)
|
28
|
+
curl \
|
29
|
+
wget \
|
30
|
+
git \
|
31
|
+
openssh-client \
|
32
|
+
# Firewall tools (for init-firewall.sh script)
|
33
|
+
iptables \
|
34
|
+
ipset \
|
35
|
+
# Additional utilities from Claude Code setup
|
36
|
+
sudo \
|
37
|
+
zsh \
|
38
|
+
fzf \
|
39
|
+
jq \
|
40
|
+
ca-certificates \
|
41
|
+
locales \
|
42
|
+
locales-all \
|
43
|
+
# Node.js for potential frontend needs
|
44
|
+
nodejs \
|
45
|
+
npm \
|
46
|
+
&& rm -rf /var/lib/apt/lists/*
|
47
|
+
|
48
|
+
# Set up GitHub CLI repository (now that wget is installed)
|
49
|
+
RUN mkdir -p -m 755 /etc/apt/keyrings && \
|
50
|
+
wget -qO- https://cli.github.com/packages/githubcli-archive-keyring.gpg > /etc/apt/keyrings/githubcli-archive-keyring.gpg && \
|
51
|
+
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" > /etc/apt/sources.list.d/github-cli.list
|
52
|
+
|
53
|
+
# Install GitHub CLI from the repository we just added
|
54
|
+
RUN apt-get update && apt-get install -y gh && rm -rf /var/lib/apt/lists/*
|
55
|
+
|
56
|
+
# Create the non-root user
|
57
|
+
RUN groupadd --gid $USER_GID $USERNAME \
|
58
|
+
&& useradd --uid $USER_UID --gid $USER_GID -m $USERNAME \
|
59
|
+
&& echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \
|
60
|
+
&& chmod 0440 /etc/sudoers.d/$USERNAME
|
61
|
+
|
62
|
+
# Install git-delta (from Claude Code setup)
|
63
|
+
RUN ARCH=$(dpkg --print-architecture) && \
|
64
|
+
wget "https://github.com/dandavison/delta/releases/download/0.18.2/git-delta_0.18.2_${ARCH}.deb" && \
|
65
|
+
dpkg -i "git-delta_0.18.2_${ARCH}.deb" && \
|
66
|
+
rm "git-delta_0.18.2_${ARCH}.deb"
|
67
|
+
|
68
|
+
# Install Claude Code CLI (as root first, then fix permissions)
|
69
|
+
RUN npm install -g @anthropic-ai/claude-code
|
70
|
+
|
71
|
+
# Set up command history persistence (from Claude Code setup)
|
72
|
+
RUN SNIPPET="export PROMPT_COMMAND='history -a' && export HISTFILE=/commandhistory/.bash_history" \
|
73
|
+
&& mkdir /commandhistory \
|
74
|
+
&& touch /commandhistory/.bash_history \
|
75
|
+
&& chown -R $USERNAME /commandhistory
|
76
|
+
|
77
|
+
# Create workspace and config directories
|
78
|
+
RUN mkdir -p /workspace /home/$USERNAME/.claude /home/$USERNAME/.bundle /home/$USERNAME/.ssh \
|
79
|
+
&& chown -R $USERNAME:$USERNAME /workspace /home/$USERNAME/.claude /home/$USERNAME/.bundle /home/$USERNAME/.ssh \
|
80
|
+
&& chmod 700 /home/$USERNAME/.ssh
|
81
|
+
|
82
|
+
# Set working directory
|
83
|
+
WORKDIR /workspace
|
84
|
+
|
85
|
+
# Switch to non-root user before gem installation
|
86
|
+
USER $USERNAME
|
87
|
+
|
88
|
+
RUN gem install overcommit:0.67.1
|
89
|
+
|
90
|
+
# Set up ZSH with powerline10k theme (from Claude Code setup)
|
91
|
+
RUN sh -c "$(wget -O- https://github.com/deluan/zsh-in-docker/releases/download/v1.1.5/zsh-in-docker.sh)" -- \
|
92
|
+
-t https://github.com/romkatv/powerlevel10k \
|
93
|
+
-a 'ZSH_THEME="powerlevel10k/powerlevel10k"' \
|
94
|
+
-p git \
|
95
|
+
-p ssh-agent \
|
96
|
+
-p 'history-substring-search' \
|
97
|
+
-a 'bindkey "\$terminfo[kcuu1]" history-substring-search-up' \
|
98
|
+
-a 'bindkey "\$terminfo[kcud1]" history-substring-search-down'
|
99
|
+
|
100
|
+
# Copy Gemfile and Gemfile.lock for better Docker layer caching
|
101
|
+
COPY Gemfile Gemfile.lock *.gemspec ./
|
102
|
+
COPY lib/sequelizer/version.rb ./lib/sequelizer/version.rb
|
103
|
+
|
104
|
+
# Configure bundler and install gems
|
105
|
+
RUN bundle config set --local path "/home/${USERNAME}/.bundle" \
|
106
|
+
&& bundle config set --local bin "/home/${USERNAME}/.bundle/bin" \
|
107
|
+
&& bundle install
|
108
|
+
|
109
|
+
# Set the default shell to zsh
|
110
|
+
ENV SHELL=/bin/zsh
|
111
|
+
|
112
|
+
COPY .devcontainer/.zshrc /home/$USERNAME/.zshrc
|
113
|
+
COPY .devcontainer/.p10k.zsh /home/$USERNAME/.p10k.zsh
|
114
|
+
|
115
|
+
# Add bundle bin to PATH
|
116
|
+
ENV PATH="/home/$USERNAME/.bundle/bin:$PATH"
|
117
|
+
|
118
|
+
# Set Ruby environment variables
|
119
|
+
ENV BUNDLE_PATH="/home/$USERNAME/.bundle"
|
120
|
+
ENV BUNDLE_BIN="/home/$USERNAME/.bundle/bin"
|
121
|
+
|
122
|
+
USER root
|
123
|
+
|
124
|
+
# Copy the credential setup scripts
|
125
|
+
COPY .devcontainer/copy-claude-credentials.sh /usr/local/bin/
|
126
|
+
COPY .devcontainer/setup-credentials.sh /usr/local/bin/
|
127
|
+
RUN chmod +x /usr/local/bin/copy-claude-credentials.sh \
|
128
|
+
&& chmod +x /usr/local/bin/setup-credentials.sh
|
129
|
+
|
130
|
+
# Copy the firewall initialization script
|
131
|
+
COPY .devcontainer/init-firewall.sh /usr/local/bin/init-firewall.sh
|
132
|
+
RUN chmod +x /usr/local/bin/init-firewall.sh
|
133
|
+
|
134
|
+
USER $USERNAME
|
135
|
+
|
136
|
+
# Default command
|
137
|
+
CMD ["/bin/zsh"]
|
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
set -euo pipefail
|
3
|
+
|
4
|
+
echo "Copying Claude credentials and GitHub config from host..."
|
5
|
+
|
6
|
+
# Create .claude directory if it doesn't exist
|
7
|
+
mkdir -p ~/.claude
|
8
|
+
|
9
|
+
# Copy credentials from temporary mounts to proper locations
|
10
|
+
if [ -d "/tmp/host-claude" ]; then
|
11
|
+
cp -r /tmp/host-claude/* ~/.claude/ 2>/dev/null || true
|
12
|
+
fi
|
13
|
+
|
14
|
+
if [ -d "/tmp/host-claude-config" ]; then
|
15
|
+
cp -r /tmp/host-claude-config/* ~/.config/claude/ 2>/dev/null || true
|
16
|
+
fi
|
17
|
+
|
18
|
+
if [ -f "/tmp/host-claude.json" ]; then
|
19
|
+
cp /tmp/host-claude.json ~/.claude.json
|
20
|
+
fi
|
21
|
+
|
22
|
+
# Create writable GitHub config directory and copy from readonly mount
|
23
|
+
mkdir -p ~/.config/gh
|
24
|
+
if [ -d "/tmp/host-gh" ]; then
|
25
|
+
cp -r /tmp/host-gh/* ~/.config/gh/ 2>/dev/null || true
|
26
|
+
fi
|
27
|
+
|
28
|
+
# Set proper permissions
|
29
|
+
chmod 700 ~/.claude
|
30
|
+
chmod 700 ~/.config/gh 2>/dev/null || true
|
31
|
+
|
32
|
+
echo "Done copying Claude credentials and GitHub config"
|
@@ -0,0 +1,102 @@
|
|
1
|
+
{
|
2
|
+
"name": "Ruby + Claude Code Development Environment",
|
3
|
+
"build": {
|
4
|
+
"dockerfile": "Dockerfile",
|
5
|
+
"context": "..",
|
6
|
+
"args": {
|
7
|
+
"TZ": "${localEnv:TZ:America/Los_Angeles}",
|
8
|
+
"HOST_HOME": "${localEnv:HOME}"
|
9
|
+
}
|
10
|
+
},
|
11
|
+
"runArgs": [
|
12
|
+
"--cap-add=NET_ADMIN",
|
13
|
+
"--cap-add=NET_RAW"
|
14
|
+
],
|
15
|
+
"mounts": [
|
16
|
+
"type=bind,source=${localEnv:HOME}/.claude,target=/tmp/host-claude,readonly",
|
17
|
+
"type=bind,source=${localEnv:HOME}/.config/claude,target=/tmp/host-claude-config,readonly",
|
18
|
+
"type=bind,source=${localEnv:HOME}/.claude.json,target=/tmp/host-claude.json,readonly",
|
19
|
+
"type=bind,source=${localEnv:HOME}/.gitconfig,target=/home/rubydev/.gitconfig,readonly",
|
20
|
+
"type=bind,source=${localEnv:HOME}/.ssh,target=/home/rubydev/.ssh,readonly",
|
21
|
+
"type=bind,source=${localEnv:HOME}/.config/gh,target=/tmp/host-gh,readonly",
|
22
|
+
"source=ruby-command-history,target=/commandhistory,type=volume"
|
23
|
+
],
|
24
|
+
"postCreateCommand": "/usr/local/bin/setup-credentials.sh && /usr/local/bin/copy-claude-credentials.sh",
|
25
|
+
"customizations": {
|
26
|
+
"vscode": {
|
27
|
+
"extensions": [
|
28
|
+
"rebornix.Ruby",
|
29
|
+
"castwide.solargraph",
|
30
|
+
"koichisasada.vscode-rdbg",
|
31
|
+
"eamodio.gitlens",
|
32
|
+
"esbenp.prettier-vscode",
|
33
|
+
"ms-vscode.vscode-json",
|
34
|
+
"yzhang.markdown-all-in-one",
|
35
|
+
"Shopify.ruby-lsp",
|
36
|
+
"vscodevim.vim"
|
37
|
+
],
|
38
|
+
"settings": {
|
39
|
+
"editor.formatOnSave": true,
|
40
|
+
"editor.tabSize": 2,
|
41
|
+
"editor.insertSpaces": true,
|
42
|
+
"editor.renderWhitespace": "all",
|
43
|
+
"editor.wordWrap": "on",
|
44
|
+
"editor.smartSelect.selectSubwords": false,
|
45
|
+
"files.trimTrailingWhitespace": true,
|
46
|
+
"files.insertFinalNewline": true,
|
47
|
+
"terminal.integrated.defaultProfile.linux": "zsh",
|
48
|
+
"terminal.integrated.scrollback": 100000,
|
49
|
+
"terminal.integrated.profiles.linux": {
|
50
|
+
"bash": {
|
51
|
+
"path": "bash",
|
52
|
+
"icon": "terminal-bash"
|
53
|
+
},
|
54
|
+
"zsh": {
|
55
|
+
"path": "zsh"
|
56
|
+
}
|
57
|
+
},
|
58
|
+
"vim.easymotion": true,
|
59
|
+
"vim.showMarksInGutter": true,
|
60
|
+
"ruby.intellisense": "rubyLocate",
|
61
|
+
"ruby.format": "rubocop",
|
62
|
+
"solargraph.diagnostics": true,
|
63
|
+
"solargraph.completion": true,
|
64
|
+
"solargraph.hover": true,
|
65
|
+
"solargraph.symbols": true,
|
66
|
+
"[ruby]": {
|
67
|
+
"rubyLsp.formatter": "rubocop",
|
68
|
+
"editor.defaultFormatter": "Shopify.ruby-lsp",
|
69
|
+
"editor.defaultColorDecorators": "never",
|
70
|
+
"editor.formatOnSave": true
|
71
|
+
},
|
72
|
+
"[markdown]": {
|
73
|
+
"editor.defaultFormatter": "yzhang.markdown-all-in-one",
|
74
|
+
"editor.suggest.showWords": false,
|
75
|
+
"editor.inlineSuggest.enabled": false
|
76
|
+
},
|
77
|
+
"[tsv]": {
|
78
|
+
"files.trimTrailingWhitespace": false,
|
79
|
+
"editor.formatOnSave": false
|
80
|
+
},
|
81
|
+
"[csv]": {
|
82
|
+
"files.trimTrailingWhitespace": false,
|
83
|
+
"editor.formatOnSave": false
|
84
|
+
},
|
85
|
+
"git.autofetch": true,
|
86
|
+
"git.openRepositoryInParentFolders": "never"
|
87
|
+
}
|
88
|
+
}
|
89
|
+
},
|
90
|
+
"remoteUser": "rubydev",
|
91
|
+
"remoteEnv": {
|
92
|
+
"GH_TOKEN": "${localEnv:GH_TOKEN}",
|
93
|
+
"GITHUB_TOKEN": "${localEnv:GITHUB_TOKEN}"
|
94
|
+
},
|
95
|
+
"containerEnv": {
|
96
|
+
"BUNDLE_PATH": "/home/rubydev/.bundle",
|
97
|
+
"BUNDLE_BIN": "/home/rubydev/.bundle/bin",
|
98
|
+
"SHELL": "/bin/zsh"
|
99
|
+
},
|
100
|
+
"workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=cached",
|
101
|
+
"workspaceFolder": "/workspace"
|
102
|
+
}
|
@@ -0,0 +1,123 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
set -euo pipefail # Exit on error, undefined vars, and pipeline failures
|
3
|
+
IFS=$'\n\t' # Stricter word splitting
|
4
|
+
|
5
|
+
echo "Initializing firewall rules..."
|
6
|
+
|
7
|
+
# Flush existing rules and delete existing ipsets
|
8
|
+
iptables -F
|
9
|
+
iptables -X
|
10
|
+
iptables -t nat -F
|
11
|
+
iptables -t nat -X
|
12
|
+
iptables -t mangle -F
|
13
|
+
iptables -t mangle -X
|
14
|
+
ipset destroy allowed-domains 2>/dev/null || true
|
15
|
+
|
16
|
+
# First allow DNS and localhost before any restrictions
|
17
|
+
# Allow outbound DNS
|
18
|
+
iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
|
19
|
+
# Allow inbound DNS responses
|
20
|
+
iptables -A INPUT -p udp --sport 53 -j ACCEPT
|
21
|
+
# Allow outbound SSH
|
22
|
+
iptables -A OUTPUT -p tcp --dport 22 -j ACCEPT
|
23
|
+
# Allow inbound SSH responses
|
24
|
+
iptables -A INPUT -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT
|
25
|
+
# Allow localhost
|
26
|
+
iptables -A INPUT -i lo -j ACCEPT
|
27
|
+
iptables -A OUTPUT -o lo -j ACCEPT
|
28
|
+
|
29
|
+
# Create ipset with CIDR support
|
30
|
+
ipset create allowed-domains hash:net
|
31
|
+
|
32
|
+
# Fetch GitHub meta information and aggregate + add their IP ranges
|
33
|
+
echo "Fetching GitHub IP ranges..."
|
34
|
+
gh_ranges=$(curl -s https://api.github.com/meta | jq -r '.git[],.web[],.api[],.pages[]' | sort -u)
|
35
|
+
for range in $gh_ranges; do
|
36
|
+
echo "Adding GitHub range: $range"
|
37
|
+
ipset add allowed-domains "$range"
|
38
|
+
done
|
39
|
+
|
40
|
+
# Define allowed domains for Claude Code functionality
|
41
|
+
declare -a domains=(
|
42
|
+
"api.anthropic.com"
|
43
|
+
"claude.ai"
|
44
|
+
"github.com"
|
45
|
+
"raw.githubusercontent.com"
|
46
|
+
"registry.npmjs.org"
|
47
|
+
"rubygems.org"
|
48
|
+
"index.rubygems.org"
|
49
|
+
"api.rubygems.org"
|
50
|
+
"bundler.rubygems.org"
|
51
|
+
"fastly.com"
|
52
|
+
"cloudflare.com"
|
53
|
+
"amazonaws.com"
|
54
|
+
"docker.io"
|
55
|
+
"docker.com"
|
56
|
+
"gcr.io"
|
57
|
+
"quay.io"
|
58
|
+
)
|
59
|
+
|
60
|
+
# Resolve domains to IP addresses and add to ipset
|
61
|
+
for domain in "${domains[@]}"; do
|
62
|
+
echo "Resolving $domain..."
|
63
|
+
ips=$(dig +short "$domain" A | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$')
|
64
|
+
|
65
|
+
while read -r ip; do
|
66
|
+
if [[ ! "$ip" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
|
67
|
+
echo "ERROR: Invalid IP from DNS for $domain: $ip"
|
68
|
+
exit 1
|
69
|
+
fi
|
70
|
+
echo "Adding $ip for $domain"
|
71
|
+
ipset add allowed-domains "$ip"
|
72
|
+
done < <(echo "$ips")
|
73
|
+
done
|
74
|
+
|
75
|
+
# Get host IP from default route
|
76
|
+
HOST_IP=$(ip route | grep default | cut -d" " -f3)
|
77
|
+
if [ -z "$HOST_IP" ]; then
|
78
|
+
echo "ERROR: Failed to detect host IP"
|
79
|
+
exit 1
|
80
|
+
fi
|
81
|
+
|
82
|
+
HOST_NETWORK=$(echo "$HOST_IP" | sed "s/\.[0-9]*$/.0\/24/")
|
83
|
+
echo "Host network detected as: $HOST_NETWORK"
|
84
|
+
|
85
|
+
# Set up remaining iptables rules
|
86
|
+
iptables -A INPUT -s "$HOST_NETWORK" -j ACCEPT
|
87
|
+
iptables -A OUTPUT -d "$HOST_NETWORK" -j ACCEPT
|
88
|
+
|
89
|
+
# Set default policies to DROP first
|
90
|
+
iptables -P INPUT DROP
|
91
|
+
iptables -P FORWARD DROP
|
92
|
+
iptables -P OUTPUT DROP
|
93
|
+
|
94
|
+
# First allow established connections for already approved traffic
|
95
|
+
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
|
96
|
+
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
|
97
|
+
|
98
|
+
# Allow outbound connections to allowed IPs
|
99
|
+
iptables -A OUTPUT -m set --match-set allowed-domains dst -j ACCEPT
|
100
|
+
|
101
|
+
# Allow outbound HTTPS (443) and HTTP (80) to allowed domains
|
102
|
+
iptables -A OUTPUT -p tcp --dport 443 -m set --match-set allowed-domains dst -j ACCEPT
|
103
|
+
iptables -A OUTPUT -p tcp --dport 80 -m set --match-set allowed-domains dst -j ACCEPT
|
104
|
+
|
105
|
+
echo "Firewall rules configured successfully"
|
106
|
+
|
107
|
+
# Verify firewall configuration
|
108
|
+
echo "Verifying firewall configuration..."
|
109
|
+
if ! curl --connect-timeout 5 https://api.github.com/zen >/dev/null 2>&1; then
|
110
|
+
echo "ERROR: Firewall verification failed - unable to reach https://api.github.com"
|
111
|
+
exit 1
|
112
|
+
else
|
113
|
+
echo "Firewall verification passed - able to reach https://api.github.com as expected"
|
114
|
+
fi
|
115
|
+
|
116
|
+
# Test Claude API connectivity
|
117
|
+
if ! curl --connect-timeout 5 https://api.anthropic.com >/dev/null 2>&1; then
|
118
|
+
echo "WARNING: Unable to reach https://api.anthropic.com - Claude Code may not work properly"
|
119
|
+
else
|
120
|
+
echo "Claude API connectivity verified"
|
121
|
+
fi
|
122
|
+
|
123
|
+
echo "Firewall initialization completed successfully"
|
@@ -0,0 +1,95 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
set -e
|
3
|
+
|
4
|
+
echo "Setting up Claude Code credentials..."
|
5
|
+
|
6
|
+
# Check if we have read-only mounted credentials
|
7
|
+
if [ -d "/tmp/host-claude" ]; then
|
8
|
+
echo "Found mounted credentials at /tmp/host-claude"
|
9
|
+
|
10
|
+
# Create the .claude directory in the user's home
|
11
|
+
mkdir -p ~/.claude
|
12
|
+
|
13
|
+
# Copy credentials file specifically
|
14
|
+
if [ -f "/tmp/host-claude/.credentials.json" ]; then
|
15
|
+
cp "/tmp/host-claude/.credentials.json" ~/.claude/
|
16
|
+
chmod 600 ~/.claude/.credentials.json
|
17
|
+
echo "✓ Claude credentials copied and secured"
|
18
|
+
else
|
19
|
+
echo "⚠ No .credentials.json found in mounted directory"
|
20
|
+
fi
|
21
|
+
|
22
|
+
# Copy other configuration files if they exist
|
23
|
+
for file in /tmp/host-claude/*.json; do
|
24
|
+
if [ -f "$file" ] && [ "$(basename "$file")" != ".credentials.json" ]; then
|
25
|
+
cp "$file" ~/.claude/
|
26
|
+
fi
|
27
|
+
done
|
28
|
+
|
29
|
+
# Set proper permissions for security
|
30
|
+
chmod 700 ~/.claude
|
31
|
+
find ~/.claude -type f -not -name ".credentials.json" -exec chmod 644 {} \;
|
32
|
+
|
33
|
+
echo "✓ Claude configuration files copied"
|
34
|
+
|
35
|
+
# Verify credential files exist
|
36
|
+
if [ -f ~/.claude/.credentials.json ]; then
|
37
|
+
echo "✓ Credentials file found and accessible"
|
38
|
+
else
|
39
|
+
echo "⚠ Warning: No credentials file found in ~/.claude"
|
40
|
+
echo "Available files:"
|
41
|
+
ls -la ~/.claude/ || echo "Directory is empty"
|
42
|
+
fi
|
43
|
+
else
|
44
|
+
echo "⚠ No Claude credentials found at /tmp/host-claude"
|
45
|
+
echo "You may need to authenticate Claude Code manually after container startup"
|
46
|
+
echo "Run: claude auth login"
|
47
|
+
fi
|
48
|
+
|
49
|
+
# Install Ruby gems
|
50
|
+
echo "Installing Ruby gems..."
|
51
|
+
if [ -f "Gemfile" ]; then
|
52
|
+
bundle install
|
53
|
+
echo "✓ Ruby gems installed successfully"
|
54
|
+
else
|
55
|
+
echo "⚠ No Gemfile found, skipping gem installation"
|
56
|
+
fi
|
57
|
+
|
58
|
+
# Initialize firewall if script exists and we have required capabilities
|
59
|
+
if [ -f "/usr/local/bin/init-firewall.sh" ]; then
|
60
|
+
echo "Initializing firewall..."
|
61
|
+
if sudo /usr/local/bin/init-firewall.sh; then
|
62
|
+
echo "✓ Firewall initialized successfully"
|
63
|
+
else
|
64
|
+
echo "⚠ Firewall initialization failed - continuing without network restrictions"
|
65
|
+
echo "Note: Container may need NET_ADMIN and NET_RAW capabilities for firewall"
|
66
|
+
fi
|
67
|
+
else
|
68
|
+
echo "⚠ Firewall script not found, skipping network security setup"
|
69
|
+
fi
|
70
|
+
|
71
|
+
# Verify Claude Code installation
|
72
|
+
echo "Verifying Claude Code installation..."
|
73
|
+
if command -v claude >/dev/null 2>&1; then
|
74
|
+
echo "✓ Claude Code CLI found at: $(which claude)"
|
75
|
+
|
76
|
+
# Test basic Claude Code functionality (non-interactive)
|
77
|
+
if claude --version >/dev/null 2>&1; then
|
78
|
+
echo "✓ Claude Code is working correctly"
|
79
|
+
else
|
80
|
+
echo "⚠ Claude Code binary found but may not be properly configured"
|
81
|
+
fi
|
82
|
+
else
|
83
|
+
echo "⚠ Claude Code CLI not found in PATH"
|
84
|
+
echo "You may need to install it manually with: npm install -g @anthropic-ai/claude-code"
|
85
|
+
fi
|
86
|
+
|
87
|
+
echo ""
|
88
|
+
echo "🎉 Setup complete!"
|
89
|
+
echo ""
|
90
|
+
echo "Next steps:"
|
91
|
+
echo "1. If credentials weren't found, authenticate with: claude auth login"
|
92
|
+
echo "2. Test Claude Code with: claude --help"
|
93
|
+
echo "3. Start coding with AI assistance: claude"
|
94
|
+
echo ""
|
95
|
+
|
data/.github/workflows/test.yml
CHANGED
data/.gitignore
CHANGED
@@ -3,7 +3,6 @@
|
|
3
3
|
.bundle
|
4
4
|
.config
|
5
5
|
.yardoc
|
6
|
-
Gemfile.lock
|
7
6
|
InstalledFiles
|
8
7
|
_yardoc
|
9
8
|
coverage
|
@@ -33,3 +32,9 @@ Session.vim
|
|
33
32
|
tags
|
34
33
|
|
35
34
|
# End of https://www.gitignore.io/api/vim
|
35
|
+
|
36
|
+
# DevContainer build artifacts
|
37
|
+
.devcontainer/.tmp
|
38
|
+
.worktrees/
|
39
|
+
.claude/settings.local.json
|
40
|
+
.specstory/
|
data/.overcommit.yml
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
# Overcommit configuration for Sequelizer
|
2
|
+
# See https://github.com/sds/overcommit for documentation
|
3
|
+
|
4
|
+
PreCommit:
|
5
|
+
# Run RuboCop to check for style violations and auto-fix when possible
|
6
|
+
RuboCop:
|
7
|
+
enabled: true
|
8
|
+
command: ['bundle', 'exec', 'rubocop']
|
9
|
+
flags: ['--autocorrect']
|
10
|
+
include:
|
11
|
+
- '**/*.rb'
|
12
|
+
- '**/*.rake'
|
13
|
+
- '**/Rakefile'
|
14
|
+
- '**/Gemfile'
|
15
|
+
- '**/*.gemspec'
|
16
|
+
|
17
|
+
# Run tests to ensure nothing is broken
|
18
|
+
RakeTarget:
|
19
|
+
enabled: true
|
20
|
+
targets: ['test']
|
21
|
+
description: 'Run test suite'
|
22
|
+
|
23
|
+
# Check for potential security issues (if bundler-audit is available)
|
24
|
+
BundleAudit:
|
25
|
+
enabled: false # Disabled by default, enable if you add bundler-audit gem
|
26
|
+
|
27
|
+
# Check for trailing whitespace
|
28
|
+
TrailingWhitespace:
|
29
|
+
enabled: true
|
30
|
+
exclude:
|
31
|
+
- '**/db/structure.sql' # Database dumps may have trailing whitespace
|
32
|
+
- '**/*.md' # Markdown may intentionally have trailing spaces
|
33
|
+
|
34
|
+
# Check for merge conflict markers
|
35
|
+
MergeConflicts:
|
36
|
+
enabled: true
|
37
|
+
|
38
|
+
# Check YAML syntax
|
39
|
+
YamlSyntax:
|
40
|
+
enabled: true
|
41
|
+
|
42
|
+
# Check JSON syntax
|
43
|
+
JsonSyntax:
|
44
|
+
enabled: true
|
45
|
+
|
46
|
+
# Check for hard tabs (prefer spaces)
|
47
|
+
HardTabs:
|
48
|
+
enabled: true
|
49
|
+
exclude:
|
50
|
+
- '**/Makefile*'
|
51
|
+
- '**/*.mk'
|
52
|
+
|
53
|
+
CommitMsg:
|
54
|
+
# Ensure commit messages are properly formatted
|
55
|
+
TextWidth:
|
56
|
+
enabled: true
|
57
|
+
max_subject_width: 60
|
58
|
+
max_body_width: 72
|
59
|
+
|
60
|
+
PostCheckout:
|
61
|
+
# Bundle install when Gemfile changes
|
62
|
+
BundleCheck:
|
63
|
+
enabled: true
|
64
|
+
|
65
|
+
PostMerge:
|
66
|
+
# Bundle install after merging changes to Gemfile
|
67
|
+
BundleCheck:
|
68
|
+
enabled: true
|
69
|
+
|
70
|
+
PostRewrite:
|
71
|
+
# Bundle install after rebasing with Gemfile changes
|
72
|
+
BundleCheck:
|
73
|
+
enabled: true
|