Skip to content

feat: provision 1Password service account token to new targets#27

Merged
smartwatermelon merged 4 commits intomainfrom
claude/phase4-op-service-account-token-20260413-1445
Apr 13, 2026
Merged

feat: provision 1Password service account token to new targets#27
smartwatermelon merged 4 commits intomainfrom
claude/phase4-op-service-account-token-20260413-1445

Conversation

@smartwatermelon
Copy link
Copy Markdown
Owner

Summary

Phase 4 of the 1Password service-account migration. Uses the existing external-keychain airdrop flow to provision op-service-account-claude-automation to new Mac Mini dev-server targets, so claude-wrapper can fetch GH_TOKEN from op://Automation/GitHub - CCCLI/Token on first boot.

Scope: dev-server only. No Caddy, no runtime rotation, no System-keychain hop. mac-server-setup will get a parallel PR covering those.

Changes

  • prep-airdrop.sh — read token from dev Keychain, stage in external keychain under SERVER_NAME_LOWER account; add KEYCHAIN_OP_SERVICE to manifest
  • scripts/server/first-boot.sh — import token from external keychain, install in admin login keychain under ADMIN_USERNAME (matches claude-wrapper's id -un lookup in lib/credentials.sh)
  • CLAUDE.md — clarify op (service account, non-interactive) vs opp (Personal vault, interactive)
  • docs/plans/2026-04-13-phase4-op-service-account-token.md — implementation plan

Account-name invariant

External keychain: -a "\${SERVER_NAME_LOWER}" (consistent with existing TimeMachine/WiFi).
Login keychain on target: -a "\${ADMIN_USERNAME}" (= `whoami` = `id -un`, what the wrapper looks up).

Test plan

  • `shellcheck -S info` clean on modified files
  • Local code-reviewer + adversarial-reviewer pass (pre-push hook)
  • After merge: one-time manual backfill on MIMOLETTE (it pre-dates this flow), then verify claude-wrapper picks up the token via `id -un` lookup
  • Next new-target provisioning: confirm prep-airdrop stages the token and first-boot installs it under ADMIN_USERNAME

🤖 Generated with Claude Code

Claude Code Bot and others added 4 commits April 13, 2026 14:50
… keychain

Read the op service account token from the dev machine's login Keychain
and store it in the external airdrop keychain under SERVER_NAME_LOWER.
First-boot extracts and installs it under ADMIN_USERNAME so claude-wrapper
can fetch it via id -un lookup.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…chain

Extract the op service account token from the external airdrop keychain
and install it in the admin user's login keychain. Uses ADMIN_USERNAME
on the write so claude-wrapper's id -un lookup matches on first run.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@claude
Copy link
Copy Markdown

claude bot commented Apr 13, 2026

PR Review -- feat: provision 1Password service account token to new targets

Summary

Phase 4 of the 1Password service-account migration. Piggybacks on the existing external-keychain airdrop flow to stage op-service-account-claude-automation so claude-wrapper can fetch GH_TOKEN on first boot.


Code Quality

prep-airdrop.sh (lines 662-688)

The provisioning block follows existing conventions cleanly. The || true in the subshell assignment correctly prevents set -e from aborting when the keychain entry is absent.

Minor: echo "Provisioning 1Password service account token..." fires unconditionally before the nil-check, so users always see it even when the token is absent. Moving it inside the success branch (or rephrasing to "Checking for...") would be cleaner, but this is purely cosmetic.

scripts/server/first-boot.sh (lines 473-488)

The new block mirrors the WiFi pattern exactly. The intentional account-name divergence -- find using ${KEYCHAIN_ACCOUNT} in the external keychain, delete/add using ${ADMIN_USERNAME} in the login keychain -- is correctly implemented and documented in the inline comment. This is the right behavior for claude-wrapper's id -un lookup.

The -A flag on security add-generic-password grants all-app access without prompting. This matches the TimeMachine and WiFi entries and is appropriate for a headless build server. Worth noting it is intentional if audited later.

CLAUDE.md

opp is listed as an interactive-auth command but is not a standard macOS or Homebrew tool -- it appears to be a local alias or wrapper. If a future contributor does not have opp configured, this command will silently fail. A note like # (alias for op with personal vault settings -- see dotfiles) would help.


Reliability

No regressions identified. The new first-boot.sh block is guarded with 2>/dev/null and the else-branch is informational-only (show_log), so a missing token is a soft failure, consistent with WiFi and TimeMachine handling.

KEYCHAIN_OP_SERVICE added to keychain_manifest.conf is protected by # shellcheck disable=SC2154 at its point of use in first-boot.sh -- correct, since it is loaded from a sourced file at runtime.


Security

No concerns. The token is stored in the macOS Keychain (not written to disk), unset promptly after use in both scripts, and the manifest file is chmod 600. The -A access flag is consistent with other entries.


Non-Blocking Observations (by maintenance impact)

  1. prep-airdrop.sh:669 -- Unconditional "Provisioning..." echo fires even when the token is absent; operators may see the message and then a warning. Easy fix: move the echo inside the success branch or rephrase to "Checking for...".
  2. CLAUDE.md -- opp needs provenance documentation so future contributors know where it comes from.

VERDICT: PASS

@smartwatermelon smartwatermelon merged commit d3c8500 into main Apr 13, 2026
1 check passed
@smartwatermelon smartwatermelon deleted the claude/phase4-op-service-account-token-20260413-1445 branch April 13, 2026 22:25
smartwatermelon pushed a commit that referenced this pull request Apr 13, 2026
- prep-airdrop.sh: only echo "Provisioning..." when token is present
  (previously printed before the nil-check, creating misleading output
  when the dev Keychain lacks the token) — closes #28
- first-boot.sh: clarify -u flag semantics for security set-keychain-settings
  — the no-timeout behavior comes from omitting -t, not from -u alone —
  closes #31
- CLAUDE.md: note that opp is a local shell function from dotfiles,
  not a standard macOS/Homebrew tool — closes #29

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
smartwatermelon added a commit that referenced this pull request Apr 13, 2026
- prep-airdrop.sh: only echo "Provisioning..." when token is present
  (previously printed before the nil-check, creating misleading output
  when the dev Keychain lacks the token) — closes #28
- first-boot.sh: clarify -u flag semantics for security set-keychain-settings
  — the no-timeout behavior comes from omitting -t, not from -u alone —
  closes #31
- CLAUDE.md: note that opp is a local shell function from dotfiles,
  not a standard macOS/Homebrew tool — closes #29

Co-authored-by: Claude Code Bot <claude-code@smartwatermelon.github>
Co-authored-by: Claude Opus 4.6 (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