From eb2a0a532c4f684689b31c244a030e660a97c846 Mon Sep 17 00:00:00 2001 From: Vuong Hoang Date: Fri, 16 Oct 2026 11:09:13 -0700 Subject: [PATCH] feat(nh3-dev): /srv/nemi/books book drop (fiction/ nonfiction/ rejected/) for albok unit 8 --- playbooks/nh3-dev-nemi-books.yaml | 39 +++++++++++++++++++++++++++++++ servers/nh3-dev/README.md | 11 +++++++++ 2 files changed, 50 insertions(+) create mode 100644 playbooks/nh3-dev-nemi-books.yaml diff --git a/playbooks/nh3-dev-nemi-books.yaml b/playbooks/nh3-dev-nemi-books.yaml new file mode 100644 index 0000000..747d8fa --- /dev/null +++ b/playbooks/nh3-dev-nemi-books.yaml @@ -0,0 +1,39 @@ +# nh3-dev: /srv/nemi/books, the book drop Nemi validates into ~/library// (albok unit 8; albok-dev 2026-10-16 after +# Prime: "build the books drop folder in nemi ... a rejection folder feels appropriate"). Same shape as /srv/nemi/inbox +# (playbooks/nh3-dev-nemi-inbox.yaml, which created group nemi-drop and /srv/nemi): Nemi moves each valid epub from +# fiction/ or nonfiction/ into ~/library//, and anything it refuses into rejected/ beside a reason file. +# scripts/elway infra-ops@10.100.10.50 --playbook playbooks/nh3-dev-nemi-books.yaml +# Writers: group nemi-drop (lkraven, infra-ops). Nemi runs as lkraven from the user manager, whose groups predate +# nemi-drop, so lkraven gets in through the u:lkraven ACL entries, NOT the group (see servers/nh3-dev/README.md). +steps: + - name: Prerequisites from the inbox playbook (group nemi-drop, /srv/nemi with u:lkraven:rx) + shell: | + getent group nemi-drop >/dev/null && test -d /srv/nemi && getfacl -p /srv/nemi | grep -q '^user:lkraven:r-x' + changed_when: "false" + - name: /srv/nemi/books and fiction/ nonfiction/ rejected/ (lkraven:nemi-drop 2770, same ACL as the inbox) + sudo: true + shell: | + for d in /srv/nemi/books /srv/nemi/books/fiction /srv/nemi/books/nonfiction /srv/nemi/books/rejected; do + install -d -o lkraven -g nemi-drop -m 2770 "$d" + setfacl -m u:lkraven:rwx,g:nemi-drop:rwx "$d" + setfacl -d -m u::rwX,u:lkraven:rwX,g::rwX,g:nemi-drop:rwX,o::--- "$d" + done + getfacl -p /srv/nemi/books + creates: /srv/nemi/books/rejected +verify: + - name: Nemi's own context (lkraven's systemd user manager, groups fixed at boot) can list every books dir + shell: runuser -u lkraven -- env XDG_RUNTIME_DIR=/run/user/1000 systemd-run --user --wait --pipe -q ls -ld /srv/nemi/books /srv/nemi/books/fiction /srv/nemi/books/nonfiction /srv/nemi/books/rejected + sudo: true + changed_when: "false" + - name: A file dropped by infra-ops into fiction/ is readable by lkraven, movable to rejected/, and removable + sudo: true + shell: | + set -e + f=/srv/nemi/books/fiction/.acl-probe-$$ + r=/srv/nemi/books/rejected/.acl-probe-$$ + runuser -u infra-ops -g nemi-drop -- sh -c "umask 077; echo probe > $f" + runuser -u lkraven -- cat "$f" >/dev/null + runuser -u lkraven -- mv "$f" "$r" + runuser -u lkraven -- rm -f "$r" + test ! -e "$f" && test ! -e "$r" && echo "infra-ops drop -> lkraven read+move+remove: ok" + changed_when: "false" diff --git a/servers/nh3-dev/README.md b/servers/nh3-dev/README.md index a7796de..3b26edc 100644 --- a/servers/nh3-dev/README.md +++ b/servers/nh3-dev/README.md @@ -240,6 +240,17 @@ carries `u:lkraven:rx`. for lkraven, NOT through the group. Do not "simplify" them away until lkraven's user manager has restarted. `playbooks/nh3-dev-nemi-inbox.yaml` verifies both paths. +## `/srv/nemi/books`: the book drop (2026-10-16) + +albok unit 8 (albok-dev, after Prime asked for a books drop folder with a rejection folder). Drop an epub into `fiction/` or +`nonfiction/`. Nemi validates it and moves it into `~lkraven/library//`, writing its yaml and MANIFEST line, then walks it +the same hour. If it refuses the file, it moves it into `rejected/` beside a reason file. Files are examined only after +2 minutes unchanged, and temporary names (dotfiles, `.part`, `.crdownload`, `.tmp`, `~`, `.syncthing.*`) are ignored. +Same shape as the inbox: all four dirs are `lkraven:nemi-drop 2770` with the default ACL. Same filesystem as `~/library` +(`/dev/sda1`), so Nemi's move is a rename. There is no network share: drops are local writes or `scp`/`sftp` as lkraven, as +for the inbox. `playbooks/nh3-dev-nemi-books.yaml` provisions it and verifies an infra-ops drop is readable, movable +to `rejected/` and removable by lkraven. + ## `/srv/nemi/vault`: Prime's notes for Nemi (2026-10-15) A fresh clone of gitea `vh/VuongKB` (Prime's notes, which he syncs with git; his working copy is `/home/lkraven/kb`, never