feat(gateway): hivectl gateway user management + fix htpasswdFile assertion

Add `hivectl gateway {create-user,delete-user,list-users}` subcommands for
managing htpasswd files used by gateway Basic auth. Pure Rust bcrypt
(cost 12, $2y$ prefix nginx accepts). No external htpasswd binary required.

Also fix the NixOS module assertion: `cfg.auth ? htpasswdFile` is always
true in the module system (declared options always exist as keys); switch
to `nullOr path; default = null` + `!= null` check so the assertion
actually fires with a useful error when enable=true but no file is set.
Guard bind-mount and nginx config against null to prevent eval errors.

Update docs/gateway.md to show hivectl commands instead of raw htpasswd.
This commit is contained in:
atlas 2026-06-01 23:00:38 +02:00
commit 4bff450343
61 changed files with 1084 additions and 547 deletions

View file

@ -32,7 +32,10 @@ pub struct Args {
pub fn run(client: &Client, args: Args) -> Result<()> {
let repo = client.repo();
let diff = client.get_text(&format!("/repos/{repo}/pulls/{}.diff", args.number), "text/plain")?;
let diff = client.get_text(
&format!("/repos/{repo}/pulls/{}.diff", args.number),
"text/plain",
)?;
let out = if args.full {
diff
} else {
@ -218,7 +221,9 @@ mod tests {
assert!(is_autogenerated("flake.lock"));
assert!(is_autogenerated("a/flake.lock"));
assert!(is_autogenerated("hive-c0re/Cargo.lock"));
assert!(is_autogenerated("frontend/packages/dashboard/package-lock.json"));
assert!(is_autogenerated(
"frontend/packages/dashboard/package-lock.json"
));
assert!(!is_autogenerated("src/main.rs"));
assert!(!is_autogenerated("Cargo.toml"));
// Suffix-only files we deliberately don't match — keep
@ -346,10 +351,7 @@ index 1111..2222 100644
#[test]
fn parse_diff_git_path_picks_b_side() {
assert_eq!(
parse_diff_git_path("a/foo b/foo"),
Some("foo".to_owned())
);
assert_eq!(parse_diff_git_path("a/foo b/foo"), Some("foo".to_owned()));
assert_eq!(
parse_diff_git_path("a/old.txt b/new.txt"),
Some("new.txt".to_owned())