Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
94 commits
Select commit Hold shift + click to select a range
d1e2db5
zoo(feat): share intel between maps
guarzo Aug 8, 2026
6ebdb30
zoo(build): add devcontainer, docker tooling, and fork release workflow
guarzo Aug 8, 2026
675c349
zoo(feat): add the zoo map theme, palette, and icon set
guarzo Aug 8, 2026
f1ee7b5
zoo(feat): render solar system nodes and edges with the zoo theme
guarzo Aug 8, 2026
462016b
zoo(feat): add zoo tag, label, and connection context menus
guarzo Aug 8, 2026
c44e488
zoo(feat): add the custom system settings dialog
guarzo Aug 8, 2026
4d1d4e5
zoo(feat): track system ownership and owner ticker
guarzo Aug 8, 2026
4cf11ee
zoo(feat): add fleet readiness tracking
guarzo Aug 8, 2026
607455c
zoo(feat): add signature cleanup and zoo signature settings
guarzo Aug 8, 2026
5e0d982
zoo(feat): add the local pilot counter and presence grace period
guarzo Aug 8, 2026
b440b0b
zoo(feat): add connection loop type and chain mass tracking
guarzo Aug 8, 2026
032eec9
zoo(chore): wire zoo customizations into map server, router, and config
guarzo Aug 8, 2026
1b4a7e2
zoo(feat): add discord webhook and notification resources
guarzo Aug 8, 2026
499a4c1
zoo(feat): add the discord notification delivery pipeline
guarzo Aug 8, 2026
8114858
zoo(feat): add killmail ingest and corporation search
guarzo Aug 8, 2026
fad3f06
zoo(feat): add the discord notification settings UI
guarzo Aug 8, 2026
9b29e47
zoo(refactor): rework the access-list member API controller
guarzo Aug 8, 2026
7f819f1
zoo(chore): fork adjustments carried with the discord work
guarzo Aug 8, 2026
a010cb4
fix: corporation typeahead crash and silent ESI search failures (#103)
guarzo Aug 4, 2026
240a8f2
Clear the PR #101 follow-up backlog: warnings, cancel_ping, workflow …
guarzo Aug 4, 2026
c0a77e5
fix: stop Add buttons stretching and surface the corp-search reason (…
guarzo Aug 4, 2026
2321332
fix(json-api): correct JsonApiFormatter payload contract against real…
guarzo Aug 4, 2026
17530ad
fix: name the character the corporation search runs as (#106)
guarzo Aug 4, 2026
c156415
fix: corporation filter replaces tracked characters; unknown-involvem…
guarzo Aug 4, 2026
a9f1a52
fix: align the Add buttons with their inputs on the Notifications tab…
guarzo Aug 4, 2026
027e6ad
Fly.io migration groundwork: config, IPv6 kills transport, /health, f…
guarzo Aug 5, 2026
afb8b76
docs(plan): resolve the EVE SSO callback question — one redirect URL …
guarzo Aug 5, 2026
0518a96
fix: reach the route builder over IPv6 (#112)
guarzo Aug 5, 2026
272e505
fix: stop rotating the unsplashed-holes badge (#113)
guarzo Aug 5, 2026
7adea6c
fix(fly): name the app and run migrations off the direct URL (#114)
guarzo Aug 5, 2026
57679e2
ci: drop the VM release pipeline (#115)
guarzo Aug 5, 2026
c2042e7
bump
guarzo Aug 5, 2026
a644fa2
feat(discord): add notable items section to kill embeds (#116)
guarzo Aug 5, 2026
66cefb9
ci: run the test suite on guarzo/zoo pull requests (#117)
guarzo Aug 5, 2026
aabeead
test: pull in the upstream suite fixes (#639, #642) so zoo runs green…
guarzo Aug 5, 2026
9336deb
chore(deps-dev): bump postcss from 8.5.6 to 8.5.23 in /assets (#119)
dependabot[bot] Aug 5, 2026
a500f6e
fix(db): drop the duplicate maps_v1 scopes-default migration (#122)
guarzo Aug 5, 2026
708d601
perf(ci): split the test suite into parallel jobs and fix the caches …
guarzo Aug 5, 2026
6c133d6
perf(discord): fetch notable-items ESI data concurrently, keep partia…
guarzo Aug 5, 2026
9cde7ae
chore(fly): enable notable-item enrichment on the Fly deployment (#123)
guarzo Aug 6, 2026
05c9147
fix(discord): resolve missing corporation tickers from ESI for kill e…
guarzo Aug 6, 2026
1868b9f
polish: make a fully-failed ticker batch visible, document the timeou…
guarzo Aug 6, 2026
bc9ead3
feat(discord): add corp-ticker incident switch, log partial resolution
guarzo Aug 6, 2026
bd5dbae
review: bound per-element ESI timeout, quiet permanent partial misses
guarzo Aug 6, 2026
dc64037
docs: design spec for discord voice-participant kill mentions
guarzo Aug 7, 2026
6ff3c52
docs: fold codex review findings into voice-mentions spec
guarzo Aug 7, 2026
d0efd4c
docs: implementation plan for discord voice mentions (codex findings …
guarzo Aug 7, 2026
829c44c
feat(discord): config surface and nostrum dep for voice mentions
guarzo Aug 7, 2026
14438eb
fix(deps): restore original lock; add nostrum, bump cowlib 2.14.0->2.…
guarzo Aug 7, 2026
622136f
feat(discord): voice participants module with mention budget
guarzo Aug 7, 2026
b473c80
feat(discord): conditional nostrum gateway startup for voice mentions
guarzo Aug 7, 2026
680fc9b
feat(discord): prepend voice-participant mentions to system kill noti…
guarzo Aug 7, 2026
6da322d
polish: test-gate voice env keys, catch non-exception exits in voice …
guarzo Aug 7, 2026
6924b90
docs: record debug-level ruling for the all-filtered voice diagnostic
guarzo Aug 7, 2026
92a0f35
review: normalize blank bot tokens, warn on any partial voice config
guarzo Aug 7, 2026
5f2664a
Merge pull request #126 from guarzo/worktree-discord-route-alerts
guarzo Aug 8, 2026
f7e30e3
docs(spec): deploy approval gate replacing the Fly branch-watch integ…
guarzo Aug 8, 2026
6dd6a93
docs(spec): apply codex review findings to the deploy approval gate
guarzo Aug 8, 2026
0079b5b
docs(spec): collapse the deploy gate to a single job
guarzo Aug 8, 2026
d5a17ef
docs: implementation plan for the deploy approval gate
guarzo Aug 8, 2026
d827ac3
review: correct workflow_run semantics, merge-armed run, tag convergence
guarzo Aug 8, 2026
51c3265
ci: gated deploy workflow for guarzo/zoo
guarzo Aug 8, 2026
3a88d3b
docs: describe the gated deploy process
guarzo Aug 8, 2026
0c61de6
fix(deploy): apply final review fixes to zoo-deploy.yml and docs
guarzo Aug 8, 2026
b682fe7
ci: retire guarzo/release instead of keeping it as a deploy bookmark
guarzo Aug 8, 2026
26a6774
ci: read the Fly credential from FLY_DEPLOY_TOKEN, not FLY_API_TOKEN
guarzo Aug 8, 2026
7a233e1
fix(routes): stop one slow static lookup from killing the whole route…
guarzo Aug 8, 2026
251d14a
test: temporary failing test to validate the deploy gate on a red commit
guarzo Aug 8, 2026
2864472
test: remove the temporary deploy-gate check
guarzo Aug 8, 2026
7a09ca7
fix(ci): read the Fly release number from .Version, not .version
guarzo Aug 8, 2026
203d98d
zoo(docs): refresh ZOO-FORK.md and add parallel-session follow-up pro…
guarzo Aug 8, 2026
d342b54
fix(notifications): keep the route alerts checkbox ticked on toggle (…
guarzo Aug 8, 2026
60289bd
fix(maps): reject unknown and feature-disabled settings tabs server-s…
guarzo Aug 8, 2026
3397d55
feat(components): give button/1 primary/secondary/ghost/danger varian…
guarzo Aug 8, 2026
42c8faf
feat(notifications): pick the route-alert home system by name (#134)
guarzo Aug 8, 2026
e8edbad
feat(notifications): resolve Discord channel identity and detect coll…
guarzo Aug 8, 2026
813ae3b
fix(codegen): clear the maps_v1 scopes drift and gate codegen in CI (…
guarzo Aug 8, 2026
71634db
feat(notifications): restructure the Notifications tab around its two…
guarzo Aug 8, 2026
6382d68
zoo: fork hygiene — dead flag, label docs, duplicate-migration guard …
guarzo Aug 8, 2026
b782cbe
zoo(docs): refresh the prompt doc after the history rewrite, add two …
guarzo Aug 8, 2026
80317ee
zoo(ci): drop the deploy approval gate, correct the secret's scope (#…
guarzo Aug 8, 2026
0d6c89d
feat(notifications): rebuild the route-alert embed around Discord's o…
guarzo Aug 8, 2026
99748b4
feat(notifications): name the channel, pick the mention, split the ta…
guarzo Aug 8, 2026
5eb9c1a
chore(assets): install jest-environment-jsdom, clear the one lint err…
guarzo Aug 9, 2026
1d0ae92
fix(zoo): show scan age for unscanned signatures, stop hiding it past…
guarzo Aug 9, 2026
bf956cd
fix(discord): stop killmail notifications for removed systems and dup…
guarzo Aug 9, 2026
2118203
feat(notifications): rebuild the settings tab around what is true now…
guarzo Aug 9, 2026
2a55406
fix(tracker): restore location tracking on map re-entry, instrument t…
guarzo Aug 11, 2026
0cd1370
chore(metrics): enable PromEx so the tracking defect counters record …
guarzo Aug 11, 2026
70b3015
fix(tracker): carry the real untrack reason into the metrics
guarzo Aug 11, 2026
c029af9
fix(map): make the admin Untrack button write the row it claims to
guarzo Aug 11, 2026
c3dae39
test: catch instrumentation and cache config that silently does nothing
guarzo Aug 11, 2026
8040da4
fix(tracker): stop the untrack-reason sidecar from leaking or going s…
guarzo Aug 11, 2026
494a0e9
fix(tracking): bound the untrack reason where the metric label is born
guarzo Aug 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
129 changes: 109 additions & 20 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,30 +1,119 @@
FROM elixir:1.17-otp-27
FROM elixir:1.17-otp-26

RUN apt install -yq curl gnupg
# Install OS packages and Node.js (via nodesource),
# plus inotify-tools and yarn
ARG USERNAME=developer
ARG USER_UID=1000
ARG USER_GID=$USER_UID

ENV DEBIAN_FRONTEND=noninteractive

# Install OS packages, Node.js (via nodesource), yarn, and gh CLI
RUN apt-get update && apt-get install -y --no-install-recommends \
sudo \
curl \
make \
git \
bash \
build-essential \
ca-certificates \
jq \
vim \
net-tools \
procps \
netcat-traditional \
# Optionally add any other tools you need, e.g. vim, wget...
sudo \
curl \
make \
git \
git-lfs \
bash \
zsh \
build-essential \
ca-certificates \
gnupg \
jq \
ripgrep \
tree \
lsof \
htop \
less \
vim \
locales \
net-tools \
netcat-openbsd \
procps \
inotify-tools \
&& curl -sL https://deb.nodesource.com/setup_18.x | bash - \
&& apt-get install -y --no-install-recommends nodejs inotify-tools \
&& apt-get install -y --no-install-recommends nodejs \
&& npm install -g yarn \
&& curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg \
| dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg \
&& chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg \
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" \
> /etc/apt/sources.list.d/github-cli.list \
&& apt-get update \
&& apt-get install -y --no-install-recommends gh \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*

RUN apt --fix-broken install
# Generate UTF-8 locale (some Elixir libs are encoding-sensitive)
RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && locale-gen
ENV LANG=en_US.UTF-8
ENV LANGUAGE=en_US:en
ENV LC_ALL=en_US.UTF-8

# Create non-root user with passwordless sudo and zsh as login shell
RUN groupadd --gid $USER_GID $USERNAME \
&& useradd --uid $USER_UID --gid $USER_GID -m -s /bin/zsh $USERNAME \
&& echo "$USERNAME ALL=(root) NOPASSWD:ALL" > /etc/sudoers.d/$USERNAME \
&& chmod 0440 /etc/sudoers.d/$USERNAME

# Persistent shell history across container rebuilds
RUN mkdir -p /commandhistory && chown -R $USERNAME:$USERNAME /commandhistory

# Allow git operations on the bind-mounted workspace
RUN git config --system --add safe.directory /app

RUN mix local.hex --force
USER $USERNAME

RUN mix local.hex --force && mix local.rebar --force

# Install oh-my-zsh
RUN sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended

# Install zsh plugins (autosuggestions + syntax highlighting)
RUN git clone https://github.com/zsh-users/zsh-autosuggestions \
${ZSH_CUSTOM:-/home/$USERNAME/.oh-my-zsh/custom}/plugins/zsh-autosuggestions \
&& git clone https://github.com/zsh-users/zsh-syntax-highlighting \
${ZSH_CUSTOM:-/home/$USERNAME/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting

# .zshrc with oh-my-zsh, persistent history, project aliases, and dotfiles
RUN printf '%s\n' \
'export ZSH="$HOME/.oh-my-zsh"' \
'ZSH_THEME="robbyrussell"' \
'plugins=(git mix docker docker-compose zsh-autosuggestions zsh-syntax-highlighting)' \
'source $ZSH/oh-my-zsh.sh' \
'' \
'# Persistent history (mounted volume)' \
'HISTFILE=/commandhistory/.zsh_history' \
'HISTSIZE=10000' \
'SAVEHIST=10000' \
'setopt appendhistory' \
'setopt sharehistory' \
'setopt hist_ignore_dups' \
'' \
'# NOTE: personal dotfiles are intentionally NOT sourced here. Doing so' \
'# only ever worked for a developer who separately bind-mounts ~/.dotfiles' \
'# via a local (gitignored) compose override, so it was dead code for' \
'# everyone else. That wiring now lives with the mount that enables it.' \
'' \
'# Aliases' \
'alias ll="ls -la"' \
'alias la="ls -A"' \
'alias gs="git status"' \
'alias gd="git diff"' \
'' \
'# Elixir/Phoenix aliases' \
'alias mt="mix test"' \
'alias mc="mix compile"' \
'alias mf="mix format"' \
'alias ms="iex -S mix phx.server"' \
'alias deps="mix deps.get"' \
'' \
'# Ensure Claude Code and local binaries are on PATH' \
'export PATH="$HOME/.local/bin:$PATH"' \
'' \
'export EDITOR=vim' \
'cd /app 2>/dev/null || true' \
> /home/$USERNAME/.zshrc

WORKDIR /app

ENV DEBIAN_FRONTEND=dialog
9 changes: 9 additions & 0 deletions .devcontainer/devcontainer-lock.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"features": {
"ghcr.io/devcontainers/features/common-utils:2": {
"version": "2.5.9",
"resolved": "ghcr.io/devcontainers/features/common-utils@sha256:cb0c4d3c276f157eed17935747e364178d75fee17f55c4e129966f64633deb3a",
"integrity": "sha256:cb0c4d3c276f157eed17935747e364178d75fee17f55c4e129966f64633deb3a"
}
}
}
53 changes: 40 additions & 13 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -1,30 +1,57 @@
{
"name": "wanderer-dev",
"dockerComposeFile": ["./docker-compose.yml"],
"dockerComposeFile": [
"./docker-compose.yml",
"./docker-compose.override.yml"
],
"service": "wanderer",
"workspaceFolder": "/app",
"shutdownAction": "stopCompose",
"remoteUser": "developer",
"containerUser": "developer",

"initializeCommand": "test -f .devcontainer/docker-compose.override.yml || echo 'services: {}' > .devcontainer/docker-compose.override.yml",
"postCreateCommand": "bash .devcontainer/setup.sh",
"postStartCommand": "bash .devcontainer/post-start.sh",

"remoteEnv": {
"PATH": "${containerEnv:HOME}/.local/bin:${containerEnv:PATH}"
},
"customizations": {
"vscode": {
"extensions": [
"jakebecker.elixir-ls",
"JakeBecker.elixir-ls",
"phoenixframework.phoenix",
"pantajoe.vscode-elixir-credo",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode"
"esbenp.prettier-vscode",
"eamodio.gitlens",
"mikestead.dotenv",
"ms-azuretools.vscode-docker"
],
"settings": {
"editor.formatOnSave": true,
"search.exclude": {
"**/doc": true
"**/doc": true,
"**/_build": true,
"**/deps": true
},
"elixirLS.dialyzerEnabled": false
"elixirLS.dialyzerEnabled": false,
"terminal.integrated.defaultProfile.linux": "zsh",
"terminal.integrated.profiles.linux": {
"zsh": {
"path": "/bin/zsh"
}
}
}
}
},
"service": "wanderer",
"workspaceFolder": "/app",
"shutdownAction": "stopCompose",
"features": {
"ghcr.io/devcontainers/features/common-utils:2": {
"networkArgs": ["--add-host=host.docker.internal:host-gateway"]

"forwardPorts": [4444],
"portsAttributes": {
"4444": {
"label": "Wanderer (Phoenix)",
"onAutoForward": "notify"
}
},
"forwardPorts": [4444]
}
}
18 changes: 18 additions & 0 deletions .devcontainer/docker-compose.override.yml.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# docker-compose.override.yml.example
#
# Copy this file to docker-compose.override.yml for host-specific mounts.
# The override file is gitignored and will be auto-created (empty) by
# devcontainer.json's initializeCommand if missing.
#
# Uncomment any sections you want.
services:
wanderer:
volumes:
# Host SSH keys (Git over SSH, signing)
- ~/.ssh:/home/developer/.ssh:ro

# GitHub CLI auth
- ~/.config/gh:/home/developer/.config/gh:ro

# Claude Code config, commands, plugins, settings
- ~/.claude:/home/developer/.claude:cached
47 changes: 33 additions & 14 deletions .devcontainer/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,36 +1,55 @@
version: "0.1"

services:
db:
image: postgres:13-alpine
# Matches production (postgres:16-alpine). AshPostgres declares
# min_pg_version 15 in lib/wanderer_app/repo.ex, so 13 was below the
# supported floor. The volume is renamed from db-new because a PG13 data
# directory is not readable by a PG16 server — reusing the old name would
# make the container fail to start rather than upgrade. Recreate the
# databases with `mix ecto.setup`, which also runs priv/repo/seeds.exs to
# re-download the EVE SDE reference data (solar systems, jumps, ship types).
image: postgres:16-alpine
restart: always
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
ports:
- "5432:5432"
- "5436:5432"
volumes:
- db-new:/var/lib/postgresql/data
- db-pg16:/var/lib/postgresql/data

wanderer:
build:
context: .
dockerfile: Dockerfile
environment:
PORT: 4444
DB_HOST: db
WEB_APP_URL: "http://localhost:4444"
ERL_AFLAGS: "-kernel shell_history enabled"
build:
context: .
dockerfile: Dockerfile
ports:
- 4444:4444
extra_hosts:
- "host.docker.internal:host-gateway"
volumes:
- ..:/app:delegated
- ~/.gitconfig:/root/.gitconfig
- ~/.gitignore:/root/.gitignore
- ~/.ssh:/root/.ssh
- elixir-artifacts:/opt/elixir-artifacts
- command-history:/commandhistory
# deps/ and _build/ deliberately live in the repo via the /app bind
# rather than in named volumes nested at /app/deps and /app/_build.
#
# A named volume mounted inside the bind MASKS whatever the repo has at
# that path, and it only does so for the main working tree. Git worktrees
# (this repo keeps them under .claude/worktrees/) therefore came up with
# an empty deps/ and _build/ and had to recompile from scratch, which is
# what drove the ad-hoc `ln -sfn /app/deps deps` workarounds — those
# produce symlinks that resolve in the container but dangle on the host.
#
# Tradeoff accepted: host and container now share _build. BEAM artifacts
# are OTP-version-specific, so after changing the Erlang/Elixir version
# (including this container's OTP 27 -> 26 correction), run
# `rm -rf _build` once or mix will report modules compiled by a
# different version.
command: sleep infinity

volumes:
elixir-artifacts: {}
db-new: {}
db-pg16: {}
command-history: {}
38 changes: 38 additions & 0 deletions .devcontainer/post-start.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#!/bin/bash
# Post-start script - runs every time the container starts

set -e

echo "🔄 Running post-start tasks..."

CONTAINER_HOME="$(eval echo ~)"

# Display helpful information
echo ""
echo "📊 Environment Info:"
echo " Elixir version: $(elixir --version | tail -1 | awk '{print $2}' 2>/dev/null || echo 'not installed')"
echo " Node version: $(node --version 2>/dev/null || echo 'not installed')"
echo " Claude Code: $(claude --version 2>/dev/null || echo 'not installed')"
echo " Shell: $(basename "${SHELL}")"
echo " Working dir: $(pwd)"
echo ""

# Check database (Postgres)
DB_HOST=${DB_HOST:-db}
if command -v nc >/dev/null 2>&1; then
if nc -z "$DB_HOST" 5432 2>/dev/null; then
echo "💾 Postgres: ready (${DB_HOST}:5432)"
else
echo "⚠️ Postgres not yet ready at ${DB_HOST}:5432 — check docker compose logs db"
fi
fi

echo ""
echo "🎯 Ready to code!"
echo ""
echo "Useful commands:"
echo " make server # Start Phoenix dev server (port 4444)"
echo " mix test # Run tests"
echo " mix format # Format code"
echo " claude # Start Claude Code CLI"
echo ""
Loading
Loading