Skip to content

docs(agent): service unit templates + operations guide (#116 Phase 3) - #130

Merged
arimxyer merged 1 commit into
mainfrom
feat/phase3-service-units-116
Jul 1, 2026
Merged

docs(agent): service unit templates + operations guide (#116 Phase 3)#130
arimxyer merged 1 commit into
mainfrom
feat/phase3-service-units-116

Conversation

@arimxyer

@arimxyer arimxyer commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

Phase 3 of #116: the optional platform-service layer, shipped as documented templates (not auto-registered), plus a full operations guide for the agent.

Plumbing/docs PR (auto-merge tier) — no Go changes.

What is here

  • packaging/systemd/pass-cli-agent.service — systemd --user unit. Sets LimitMEMLOCK=infinity so 2d's mlockall actually locks memory (a Go runtime exceeds the 8 MB default), binds to the graphical session so it stops at logout, and restarts only on failure (not on a clean auto-lock exit).
  • packaging/launchd/com.reyamira.pass-cli.agent.plist — macOS LaunchAgent template.
  • docs/05-operations/agent.md — run-on-demand usage, the security model (values-only protocol, SO_PEERCRED, PR_SET_DUMPABLE/mlockall, honest ceiling), socket location, snapshot freshness, and the service templates. Linked from the operations index.

Notes

  • Both service paths require keychain unlock (pass-cli keychain enable) — a service has no terminal to prompt for the master password. Documented prominently.
  • Windows service waits on the 2f named-pipe transport.

🤖 Generated with Claude Code

Ships the optional platform-service layer as documented templates (not
auto-registered), per the plan:
- packaging/systemd/pass-cli-agent.service: systemd --user unit with
  LimitMEMLOCK=infinity (so 2d's mlockall is effective) and logout teardown.
- packaging/launchd/com.reyamira.pass-cli.agent.plist: macOS LaunchAgent.
- docs/05-operations/agent.md: run-on-demand usage, the security model
  (values-only, peer-cred, memory hardening, honest ceiling), socket location,
  snapshot freshness, and the service templates. Both service paths require
  keychain unlock (a service is non-interactive).

No Go changes. Windows service waits on the 2f named-pipe transport.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014kVLjbUL4F4CkoA7RbMYy8
@arimxyer
arimxyer merged commit 2c59eff into main Jul 1, 2026
10 of 11 checks passed
@arimxyer
arimxyer deleted the feat/phase3-service-units-116 branch July 1, 2026 10:29
arimxyer added a commit that referenced this pull request Jul 1, 2026
agent.md (added in #130) never had Hugo front matter; the markdown validation
only flags files touched by a PR, so this surfaced when #134 edited it. Add
title/weight/toc matching the sibling operations docs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014kVLjbUL4F4CkoA7RbMYy8
arimxyer added a commit that referenced this pull request Jul 1, 2026
…134)

* feat(agent): add 'agent start' (daemonize) and 'agent serve' (foreground)

Replaces the clunky 'pass-cli agent &' with a proper lifecycle:
- 'agent start' backgrounds the agent and returns once it is unlocked and
  listening. It spawns a detached 'agent serve' (setsid — survives closing the
  terminal), keeping stdin+stderr on the terminal for the one-time unlock prompt
  (keychain is silent), and polls for the socket before returning.
- 'agent serve' is an explicit foreground alias for bare 'pass-cli agent'.
- --idle/--max-ttl are now persistent flags so all three forms accept them, and
  'start' forwards them to the spawned serve. POSIX only; Windows returns a clear
  'not supported' (unix-socket transport).

Real bug fixed along the way: the detached child must NOT inherit the caller's
stdout, or it holds the pipe open forever and hangs any caller that captures it
(e.g. out=$(pass-cli agent start)) — verified it hung, then fixed by pointing the
child's stdout at /dev/null (stderr stays on the terminal for the prompt/errors).

Test: TestIntegration_Agent_StartDaemonizes drives 'agent start' with the password
on an OS pipe and a file-backed stderr (a bytes.Buffer stderr would reproduce the
same Wait-on-copy-goroutine hang the feature had to fix), then resolves through the
detached agent. All 7 agent integration tests pass; unit + lint green on
linux/darwin/windows.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014kVLjbUL4F4CkoA7RbMYy8

* docs: add front matter to agent.md (markdown validation)

agent.md (added in #130) never had Hugo front matter; the markdown validation
only flags files touched by a PR, so this surfaced when #134 edited it. Add
title/weight/toc matching the sibling operations docs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014kVLjbUL4F4CkoA7RbMYy8

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant