]> quire.kejadlen.dev Git - quire.git/log
quire.git
23 hours agoAdd quire config
Alpha Chen [Mon, 27 Apr 2026 03:04:59 +0000 (20:04 -0700)]
Add quire config

23 hours agoAdd docs/config.md for the Fennel config schemas
Alpha Chen [Mon, 27 Apr 2026 02:53:07 +0000 (19:53 -0700)]
Add docs/config.md for the Fennel config schemas

Assisted-by: Claude Opus 4.7 via Claude Code
25 hours agoTighten post-receive hook based on review
Alpha Chen [Sun, 26 Apr 2026 22:26:33 +0000 (15:26 -0700)]
Tighten post-receive hook based on review

Move the push out of the hook into Repo::push_to_mirror so the actual
push logic is unit-testable independent of GIT_DIR/stdin orchestration.
Reject mirror URLs that embed credentials at deserialization, since a
typo would leak the token via tracing or Sentry. Make terminal-stdin
invocation an error rather than a silent no-op — running the hook
manually is a misuse, not a state.

Documents the env-var token exposure (visible in /proc/<pid>/environ)
as a known limitation in the helper's docstring; revisit when the CI
runner lands. Updates README to describe the PAT approach instead of
the per-repo deploy key the original design called for.

Assisted-by: Claude Opus 4.7 via Claude Code
25 hours agoImplement post-receive hook to push main to mirror
Alpha Chen [Sun, 26 Apr 2026 21:48:52 +0000 (14:48 -0700)]
Implement post-receive hook to push main to mirror

Post-receive reads GIT_DIR to resolve the repo, loads per-repo config
for the mirror URL and global config for the GitHub PAT, then pushes
main to the mirror. No mirror configured = no-op. Token is passed via
GIT_CONFIG env vars, never written to disk.

Also adds Quire::repo_from_path for resolving hooks that receive GIT_DIR,
and makes Repo::git public for use in command handlers.

Assisted-by: GLM-5.1 via pi
25 hours agoAlign docs with code after accuracy audit
Alpha Chen [Sun, 26 Apr 2026 21:52:47 +0000 (21:52 +0000)]
Align docs with code after accuracy audit

The audit found docs claiming `quire new` (CLI is `quire repo new`),
git 2.36+ (Dockerfile builds 2.54), and a stale fennel.md describing
a once-per-process Fennel that the code constructs per-call. README's
"Design phase" status also undersold actual progress.

Assisted-by: Claude Opus 4.7 via Claude Code
25 hours agoPolish docs and fix per-repo config drift in PLAN.md
Alpha Chen [Sun, 26 Apr 2026 21:02:25 +0000 (14:02 -0700)]
Polish docs and fix per-repo config drift in PLAN.md

PLAN.md placed per-repo config in the bare repo's quire/ directory, but
the code reads HEAD:.quire/config.fnl. Other edits are clarity polish
from a technical-writing pass.

Assisted-by: Claude Opus 4.7 via Claude Code
25 hours agoAdd Sentry for error tracking
Alpha Chen [Sun, 26 Apr 2026 20:45:19 +0000 (13:45 -0700)]
Add Sentry for error tracking

Optional sentry config in global config.fnl with SecretString DSN.
Best-effort init in main — logs a warning and continues if config is
missing, DSN resolution fails, or Sentry is not configured. Uses rustls
to avoid native OpenSSL dependency.

Config schema: {:sentry {:dsn \"https://key@sentry.io/123\"}}

Assisted-by: GLM-5.1 via pi
25 hours agoExtract Repo::git helper for running commands in bare repos
Alpha Chen [Sun, 26 Apr 2026 19:09:18 +0000 (12:09 -0700)]
Extract Repo::git helper for running commands in bare repos

Returns a Command with current_dir set so callers can chain .status(),
.output(), or anything else without repeating the setup.

Assisted-by: GLM-5.1 via pi
25 hours agoPropagate FennelError directly instead of flattening to String
Alpha Chen [Sun, 26 Apr 2026 19:07:25 +0000 (19:07 +0000)]
Propagate FennelError directly instead of flattening to String

Error::Fennel now wraps FennelError via #[from], preserving miette
source labels and line information. Removes four .map_err closures.

Assisted-by: GLM-5.1 via pi
25 hours agoCheck HEAD existence with rev-parse instead of parsing stderr
Alpha Chen [Sun, 26 Apr 2026 19:06:15 +0000 (19:06 +0000)]
Check HEAD existence with rev-parse instead of parsing stderr

Two-command approach: git rev-parse --verify HEAD uses exit codes
reliably, then git show only runs when HEAD exists so any failure means
the file is absent. No more fragility from matching stderr text.

Assisted-by: GLM-5.1 via pi
25 hours agoUse more accurate error variants in Repo::config()
Alpha Chen [Sun, 26 Apr 2026 19:05:12 +0000 (12:05 -0700)]
Use more accurate error variants in Repo::config()

Unexpected git failures now surface as Error::Git rather than
Error::NotFound, and UTF-8 decoding failures use Error::Io with
InvalidData rather than Error::NotFound.

Assisted-by: GLM-5.1 via pi
25 hours agoLoad per-repo config from bare repos via git show
Alpha Chen [Sun, 26 Apr 2026 14:48:17 +0000 (14:48 +0000)]
Load per-repo config from bare repos via git show

Repo::config() reads HEAD:.quire/config.fnl from bare repos, returning
a default RepoConfig when HEAD is missing (fresh repo), the file is
absent, or the :mirror key is omitted. Malformed Fennel surfaces as a
miette error with source labels pointing at the right line.

This is the foundation for per-repo mirror URLs — the config lives in
the repo's content, not in server-side operator state.

Assisted-by: GLM-5.1 via pi
36 hours agoRe-declare GIT_VERSION inside the build stage so it expands
Alpha Chen [Sun, 26 Apr 2026 03:22:30 +0000 (03:22 +0000)]
Re-declare GIT_VERSION inside the build stage so it expands

A pre-FROM ARG is a global build arg and is not in scope inside any
build stage. With it unset in the stage, ${GIT_VERSION} in the curl
URL expanded to an empty string, so we fetched
github.com/git/git/archive/refs/tags/v.tar.gz, got a 404, and the
piped tar exited 2. BuildKit reports the entire RUN command in its
error, which made it look like make was the failing step.

Verified locally: with `ARG GIT_VERSION` re-declared inside the
stage, the variable expands to 2.54.0 as intended.

36 hours agoAdd global config loader with base_dir refactor
Alpha Chen [Sun, 26 Apr 2026 03:54:34 +0000 (20:54 -0700)]
Add global config loader with base_dir refactor

Quire now stores a single base_dir (/var/quire) instead of
separate repos_dir and config_path fields. GlobalConfig parses
the Fennel config file and exposes github.token as a SecretString.
Missing config produces a typed ConfigNotFound error.

Assisted-by: GLM-5.1 via pi
36 hours agoAbsorb Config into Quire
Alpha Chen [Sun, 26 Apr 2026 03:51:47 +0000 (03:51 +0000)]
Absorb Config into Quire

Config was a thin wrapper around repos_dir. Quire now owns all
configuration directly and gains a config_path field, in
preparation for the global config loader.

Assisted-by: GLM-5.1 via pi
36 hours agoScope SecretString cache to the file variant
Alpha Chen [Sun, 26 Apr 2026 03:22:17 +0000 (20:22 -0700)]
Scope SecretString cache to the file variant

The OnceLock was vestigial on Plain secrets. Bundles two
related fixes: strip_suffix preserves all but one trailing
newline (Docker convention), and from_plain/from_file are
now public.

Assisted-by: Claude Opus 4.7 via Claude Code
47 hours agoInstall perl in git-builder stage so make can build git
Claude [Sun, 26 Apr 2026 01:56:08 +0000 (01:56 +0000)]
Install perl in git-builder stage so make can build git

debian:trixie-slim ships without perl, but git's Makefile invokes
/usr/bin/perl during the build to generate sources (command-list,
GIT-VERSION-FILE, perl/Makefile via ExtUtils::MakeMaker, etc.).
Without it, `make` aborts almost immediately with exit 2, which is
what run 24932667835's Build job hit.

The git INSTALL doc lists Perl 5.26+ as a required build dep.

47 hours agoDrop unused tooling from CI test job
Claude [Sun, 26 Apr 2026 01:50:39 +0000 (01:50 +0000)]
Drop unused tooling from CI test job

grcov, cargo-mutants, llvm-tools, and astral-sh/setup-uv were left over
from the coverage and mutation steps disabled in b33250f. Installing
them on every run added several minutes and a transient failure surface
without exercising anything. The leading comment now records what to
restore when those steps come back.

47 hours agoAdd SecretString type with lazy file resolver
Alpha Chen [Sun, 26 Apr 2026 01:30:11 +0000 (01:30 +0000)]
Add SecretString type with lazy file resolver

Untagged serde enum accepts a plain string or a file path table
({:file "/run/secrets/name"}). File contents are resolved lazily
on first call to reveal() and cached via OnceLock. Debug impl
redacts the value. Missing files produce a typed SecretResolve error.

Assisted-by: GLM-5.1 via pi
2 days agoFix line extraction for names containing colons
Alpha Chen [Sun, 26 Apr 2026 00:40:20 +0000 (00:40 +0000)]
Fix line extraction for names containing colons

extract_line_offset split on : from the left, so names like
HEAD:.quire/config.fnl broke the parser. Use regex-lite to match
the first :LINE:COLUMN: run instead, which is unambiguous.

Assisted-by: GLM-5.1 via pi
2 days agoEmbed Fennel compiler and implement load_string round-trip
Alpha Chen [Sat, 25 Apr 2026 19:12:55 +0000 (19:12 +0000)]
Embed Fennel compiler and implement load_string round-trip

Vendor fennel.lua 1.5.1 and wrap it behind a Fennel struct that owns
a Lua VM. Uses mlua with lua54 + serde features so fennel.eval results
deserialize directly into typed Rust structs. Uses unsafe_new because
Fennel needs the debug standard library internally.

Assisted-by: GLM-5.1 via pi
2 days agoAdd design note for Fennel embedding
Alpha Chen [Sat, 25 Apr 2026 16:20:26 +0000 (09:20 -0700)]
Add design note for Fennel embedding

Assisted-by: Claude Opus 4.7 via Claude Code
2 days agoInstall Rust via rustup instead of system packages
Alpha Chen [Sat, 25 Apr 2026 15:37:55 +0000 (08:37 -0700)]
Install Rust via rustup instead of system packages

Debian packages lag behind upstream. rustup gives a current toolchain
with minimal profile plus clippy and rustfmt.

Assisted-by: GLM-5.1 via pi
2 days agoSet RANGER_DEFAULT_BACKLOG in ramekin Dockerfile
Alpha Chen [Sat, 25 Apr 2026 14:52:38 +0000 (14:52 +0000)]
Set RANGER_DEFAULT_BACKLOG in ramekin Dockerfile

Assisted-by: GLM-5.1 via pi
2 days agoExtract Repo struct wrapping a resolved path
Alpha Chen [Sat, 25 Apr 2026 14:38:19 +0000 (14:38 +0000)]
Extract Repo struct wrapping a resolved path

Gives commands a typed handle instead of a bare PathBuf, with room to
add methods later.

Assisted-by: GLM-5.1 via pi
2 days agoAdd ramekin Dockerfile with Rust toolchain
Alpha Chen [Sat, 25 Apr 2026 14:15:36 +0000 (14:15 +0000)]
Add ramekin Dockerfile with Rust toolchain

Installs the packages needed to run justfile targets (fmt, clippy,
test, coverage) inside the ramekin container.

Assisted-by: GLM-5.1 via pi
2 days agoExtract Quire struct to replace Repo and Config threading
Alpha Chen [Sat, 25 Apr 2026 14:10:21 +0000 (07:10 -0700)]
Extract Quire struct to replace Repo and Config threading

Repo was a thin validated-name wrapper that required callers to pass
repos_dir alongside it at every call site. Quire holds the config and
provides repo() -> PathBuf and repos() -> Iterator, collapsing two
arguments into one at every command handler.

Assisted-by: GLM-5.1 via pi
2 days agoStrengthen pre-commit requirement in AGENTS.md
Alpha Chen [Sat, 25 Apr 2026 14:05:04 +0000 (14:05 +0000)]
Strengthen pre-commit requirement in AGENTS.md

Assisted-by: GLM-5.1 via pi
2 days agoInline repo submodules and add Repo::exists
Alpha Chen [Sat, 25 Apr 2026 14:00:32 +0000 (07:00 -0700)]
Inline repo submodules and add Repo::exists

Collapsed commands/repo/{new,list,rm}.rs into a single repo.rs. Added
Repo::exists() so callers don't need to construct paths just to check.

Assisted-by: GLM-5.1 via pi
2 days agoExtract Repo struct to unify path validation
Alpha Chen [Sat, 25 Apr 2026 13:56:41 +0000 (06:56 -0700)]
Extract Repo struct to unify path validation

All repo name validation now goes through Repo::from_name(). The exec
command strips the SSH leading slash before calling it, keeping the
Repo type focused on name rules only. Removed the duplicate
validate_repo_path function from exec.rs.

Assisted-by: GLM-5.1 via pi
2 days agoAdd repo management subcommands (new, list, rm)
Alpha Chen [Sat, 25 Apr 2026 13:47:49 +0000 (06:47 -0700)]
Add repo management subcommands (new, list, rm)

New `quire repo` subcommand group with new/list/rm. Name validation
rejects traversal, deep nesting, missing .git suffix, and reserved
segments (.git). The exec allowlist dispatches `quire repo` to the
binary. Post-receive hook is configured system-wide via gitconfig
instead of per-repo.

Assisted-by: GLM-5.1 via pi
2 days agoSwitch base images from bookworm to trixie
Alpha Chen [Sat, 25 Apr 2026 13:45:27 +0000 (13:45 +0000)]
Switch base images from bookworm to trixie

Trixie ships newer packages overall. Git still needs building from
source (trixie has 2.47, we need 2.54+) but trixie is a better
foundation going forward.

Assisted-by: GLM-5.1 via pi
2 days agoRestrict hook subcommand to HookName enum
Alpha Chen [Sat, 25 Apr 2026 13:36:03 +0000 (06:36 -0700)]
Restrict hook subcommand to HookName enum

Only post-receive is allowed for now; clap rejects anything else at
parse time. Easy to extend with more variants later.

Assisted-by: GLM-5.1 via pi
2 days agoBuild git 2.54 from source and add hook subcommand
Alpha Chen [Sat, 25 Apr 2026 04:44:53 +0000 (04:44 +0000)]
Build git 2.54 from source and add hook subcommand

Debian bookworm ships git 2.39 but we need 2.54+ for
hook.<name>.command config support, which lets quire register
hooks via git config instead of writing shim scripts to disk.

The hook subcommand is a no-op that logs invocations — enough to
verify the dispatch path works end-to-end.

Assisted-by: GLM-5.1 via pi
2 days agoNote ranger as task manager in AGENTS.md
Alpha Chen [Sat, 25 Apr 2026 04:37:53 +0000 (04:37 +0000)]
Note ranger as task manager in AGENTS.md

Assisted-by: GLM-5.1 via pi
2 days agoRun container as host uid/gid
Alpha Chen [Sat, 25 Apr 2026 02:41:05 +0000 (19:41 -0700)]
Run container as host uid/gid

Bind-mounted repos under /var/quire are owned by the host's git user;
baking a quire user with a different uid into the image triggered
git's safe.directory "dubious ownership" check. Setting the user at
docker run time keeps ownership aligned end-to-end.

Assisted-by: Claude Opus 4.7 via Claude Code
3 days agoStub HTTP server in quire serve
Alpha Chen [Fri, 24 Apr 2026 17:28:39 +0000 (17:28 +0000)]
Stub HTTP server in quire serve

Prevents the Docker container from restarting in a loop by binding
an HTTP listener on port 3000 with /health and / endpoints.

Assisted-by: GLM-5.1 via pi
3 days agoFix typo in docker/login-action pinned SHA
Alpha Chen [Fri, 24 Apr 2026 15:29:24 +0000 (15:29 +0000)]
Fix typo in docker/login-action pinned SHA

The SHA for v4.1.0 had a transposed digit (7398 → 7399) which
caused GitHub Actions to fail resolving the action reference.

Assisted-by: GLM-5.1 via pi
3 days agoTrim AGENTS.md to just pre-commit rule only
Alpha Chen [Fri, 24 Apr 2026 15:18:21 +0000 (15:18 +0000)]
Trim AGENTS.md to just pre-commit rule only

Clippy and miette conventions are already enforced by tooling.
Use "just all" instead of "cargo test" since the justfile is
the canonical check runner.

Assisted-by: GLM-5.1 via pi
3 days agoAdd project AGENTS.md and remove unused miette import
Alpha Chen [Fri, 24 Apr 2026 14:35:34 +0000 (14:35 +0000)]
Add project AGENTS.md and remove unused miette import

Assisted-by: GLM-5.1 via pi
3 days agoSimplify Config to Default and use miette bail/ensure macros
Alpha Chen [Fri, 24 Apr 2026 13:38:10 +0000 (13:38 +0000)]
Simplify Config to Default and use miette bail/ensure macros

Config::load() with env var parsing was premature. Default impl is
enough for now. Switch exec.rs from if/return Err(miette!) to
ensure! and bail! for idiomatic miette usage.

Assisted-by: GLM-5.1 via pi
3 days agoExtract Config struct for shared app configuration
Alpha Chen [Fri, 24 Apr 2026 13:31:19 +0000 (06:31 -0700)]
Extract Config struct for shared app configuration

Multiple commands need the repos directory path. A Config struct
centralizes the default and lets QUIRE_REPOS_DIR override it.

Assisted-by: GLM-5.1 via pi
3 days agoSwitch from color-eyre to miette for error reporting
Alpha Chen [Fri, 24 Apr 2026 13:27:33 +0000 (06:27 -0700)]
Switch from color-eyre to miette for error reporting

Miette provides better diagnostic output and integrates with thiserror
via the Diagnostic derive. Library errors now derive both Error and
Diagnostic. Binary uses miette::Result with into_diagnostic() for
third-party errors.

Assisted-by: GLM-5.1 via pi
3 days agoImplement quire exec dispatch with git command allowlist
Alpha Chen [Fri, 24 Apr 2026 04:05:42 +0000 (04:05 +0000)]
Implement quire exec dispatch with git command allowlist

Parses SSH_ORIGINAL_COMMAND, validates git commands against an
allowlist (receive-pack, upload-pack, upload-archive), sanitizes
repo paths, and execs the git subprocess. Removes the separate
quire-dispatch shell script — the binary handles dispatch directly.
Updates host reference configs to use quire exec in ForceCommand.

Assisted-by: GLM-5.1 via pi
3 days agoComment out coverage and mutation testing in CI
Alpha Chen [Fri, 24 Apr 2026 04:00:24 +0000 (04:00 +0000)]
Comment out coverage and mutation testing in CI

Disabled during early exploratory work — not enough library code
to meaningfully measure yet.

Assisted-by: GLM-5.1 via pi
3 days agoReplace binary release with Docker image build and push
Alpha Chen [Fri, 24 Apr 2026 00:01:59 +0000 (00:01 +0000)]
Replace binary release with Docker image build and push

Multi-stage Dockerfile builds the Rust binary then copies it into a
slim runtime image with git and ca-certificates. CI workflow follows
the ketchup pattern: single ci.yml with test, zizmor, and build jobs.
Build pushes to GHCR on green main, tags with YYYYMMDD-<short-sha>,
and creates a GitHub release. Removes the old release workflow and
dotslash config.

Assisted-by: GLM-5.1 via pi
3 days agoAdd host-side reference configs for SSH dispatch
Alpha Chen [Thu, 23 Apr 2026 23:57:07 +0000 (23:57 +0000)]
Add host-side reference configs for SSH dispatch

sshd_config Match block, quire-dispatch script with repo path
validation and git-command allowlist, and a README covering setup
steps. These are reference configs versioned with the repo — the
dispatch script will be replaced by quire exec in step 2.

Assisted-by: GLM-5.1 via pi
3 days agoAdd Dockerfile for step 1 host-mediated dispatch
Alpha Chen [Thu, 23 Apr 2026 23:51:20 +0000 (16:51 -0700)]
Add Dockerfile for step 1 host-mediated dispatch

Minimal image: debian bookworm, git, quire user, bare test repo
at /var/quire/repos/foo.git. Entrypoint passes through to docker
exec invocations. No sshd, no quire binary yet.

Assisted-by: GLM-5.1 via pi
3 days agoAdd project README and design plan
Alpha Chen [Thu, 23 Apr 2026 21:14:45 +0000 (14:14 -0700)]
Add project README and design plan

Assisted-by: GLM-5.1 via pi
3 days agoScaffold Rust binary project with clap, CI, and tooling
Alpha Chen [Thu, 23 Apr 2026 21:14:45 +0000 (14:14 -0700)]
Scaffold Rust binary project with clap, CI, and tooling

Restructure from a minimal lib+main into a proper binary project
layout: library target with error types, separate binary target
under src/bin/quire/ with clap subcommands (serve, exec), CalVer
versioning via build.rs, integration tests, justfile, clippy config,
mutation testing config, and GitHub Actions CI/release workflows.

Assisted-by: GLM-5.1 via pi
3 days agoInitialize quire project with Cargo skeleton
Alpha Chen [Thu, 23 Apr 2026 16:16:47 +0000 (09:16 -0700)]
Initialize quire project with Cargo skeleton

Assisted-by: GLM-5.1 via pi