mirror of
https://github.com/0xWheatyz/handler.git
synced 2026-08-30 07:26:25 +00:00
71a7550f48
Git servers (forge_hosts) become full credential owners: - an encrypted forge token (Fernet, HANDLER_SECRET_KEY) stored per server and never returned by the API (has_token flag only); used automatically by every project on that host and addressable as db:host:<hostname> — the reserved db: credential scheme is now live - a per-server ed25519 SSH deploy key: generated server-side, public half shown in the dashboard to paste into the forge, private half encrypted at rest and materialized 0600 only in the control container (GIT_SSH_COMMAND / core.sshCommand) Project registration gets a git-server mode: pick a registered server, type owner/name, and the API derives the remote (ssh when the server has a deploy key, https otherwise), computes root_dir under PROJECTS_ROOT, and enqueues a new 'sync' command the worker executes (clone, or ff-only pull). Spawn always pulls first, so runs start from the remote's latest state; POST /projects/:p/sync and 'handler sync' re-pull on demand. Schedules: recurring agent spawns (prefix, prompt, interval, role). The worker fires due schedules as ordinary queued spawn commands with timestamped agent names, so runs are fresh stateless agents and appear in the Activity audit trail; missed intervals collapse into one catch-up run. Dashboard: Git Servers pane shows the SSH public key (copy button) and takes a write-only token; Repositories gains the server-first add form and a Pull now button; new Schedules pane. Rebuilt static export. Also restores the missing frontend/lib (api client + format helpers) the components import. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XY1tEhQZXHZ5wci7dLc7rM
65 lines
3.2 KiB
Bash
65 lines
3.2 KiB
Bash
# Handler configuration — copy to .env and fill in. Never commit real secrets.
|
|
|
|
# Database. SQLite fallback (single-node) or Postgres (centralized, default for real deploys).
|
|
# SQLite: sqlite:////absolute/path/to/handler.db
|
|
# Postgres: postgresql+psycopg://user:pass@host:5432/handler
|
|
DATABASE_URL=sqlite:////var/lib/handler/handler.db
|
|
|
|
# Single global bearer token gating every API route. Required for the API to start.
|
|
AUTH_TOKEN=change-me-to-a-long-random-string
|
|
|
|
# Optional higher-trust token gating PUT /shared/context/:key.
|
|
# Falls back to AUTH_TOKEN if unset.
|
|
# SHARED_CONTEXT_WRITE_TOKEN=
|
|
|
|
# Optional admin token gating the web control surface: enqueuing control commands
|
|
# (spawn/kill/resume/approve/reject/forge-init/poll-ci), project CRUD, forge-host CRUD,
|
|
# and credential-pointer edits. Falls back to AUTH_TOKEN if unset. Give operators this
|
|
# token in the dashboard to unlock management actions.
|
|
# ADMIN_TOKEN=
|
|
|
|
# Optional generic webhook target for the Notification hook (ntfy, Pushover, Slack, ...).
|
|
# Fully bring-your-own; the Notification hook is a no-op when unset.
|
|
# WEBHOOK_URL=https://ntfy.sh/my-topic
|
|
|
|
# Symmetric key for the encrypted secret store: git-server tokens and SSH private keys
|
|
# are Fernet-encrypted with it before they reach the database. Set the SAME value on the
|
|
# API (encrypts on write) and the control container (decrypts at clone/spawn). Generate:
|
|
# python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
|
|
# Unset => storing tokens/SSH keys on git servers is refused with a clear error.
|
|
# HANDLER_SECRET_KEY=
|
|
|
|
# Base directory under which per-project roots and agent worktrees live (isolation).
|
|
PROJECTS_ROOT=/var/lib/handler/projects
|
|
|
|
# Binary overrides (defaults shown). Point at fakes in tests/CI.
|
|
# CLAUDE_BIN=claude
|
|
# MISE_BIN=mise
|
|
# TMUX_BIN=tmux
|
|
# FORGE_BIN=forge
|
|
# GIT_BIN=git
|
|
|
|
# Phase 2 (forge integration). Pin the forge version your base image installs; spawn
|
|
# verifies the injected forge matches and warns on drift. Leave unset to skip the check.
|
|
# FORGE_VERSION=1.2.3
|
|
|
|
# Branches a direct `git push` may not reach without a standing approval (comma-separated).
|
|
# Closes the "merge locally, push to main" path around the forge-merge approval gate.
|
|
# PROTECTED_BRANCHES=main,master
|
|
|
|
# Phase 3 (web UI). Serve the bundled UI from "/" and "/static". Set false for a
|
|
# headless, API-only deployment. Applied at process start (restart to change).
|
|
# UI_ENABLED=true
|
|
|
|
# Extra origins allowed to call the API cross-origin (comma-separated). Only needed if
|
|
# you host the UI on a DIFFERENT origin than the API; the shipped UI is same-origin and
|
|
# needs none. Empty => no CORS middleware.
|
|
# CORS_ORIGINS=https://handler.example.ts.net
|
|
|
|
# Per-project credentials are NOT set here — they live on each project's `credential_ref`
|
|
# as a POINTER (env:VAR / file:/path / cmd:...), resolved and injected only at spawn.
|
|
# The database never stores the raw token. Example, when registering a project:
|
|
# credential_ref = "env:LEEWORKS_TOKEN" (then export LEEWORKS_TOKEN where the control
|
|
# layer runs; it's injected as FORGE_TOKEN +
|
|
# the host-specific var, e.g. GITHUB_TOKEN)
|