feat(paperclip): disable sign-up; document the Claude connection #967

Merged
k.renner merged 3 commits from feat/paperclip-signup-off into master 2026-09-25 11:57:09 +00:00
Member

Follow-up to #966.

  • PAPERCLIP_AUTH_DISABLE_SIGN_UP=true: the first admin is claimed.
  • Spec: Claude auth is a Paperclip-managed subscription connection created once via the local sign-in, run as the node user (gosu node), since exec sessions start as root and root-owned 0600 credentials are unreadable to the server. The server-env CLAUDE_CODE_OAUTH_TOKEN was never used (upstream stripAiAuthBindings blanks it; no pasted setup-token path without a Daytona sandbox) and is dropped from the spec.

Owner follow-up (not in git): remove the unused CLAUDE_CODE_OAUTH_TOKEN field from OpenBao homelab/apps/paperclip.

🤖 Generated with Claude Code

Follow-up to #966. - `PAPERCLIP_AUTH_DISABLE_SIGN_UP=true`: the first admin is claimed. - Spec: Claude auth is a Paperclip-managed subscription connection created once via the local sign-in, run as the `node` user (`gosu node`), since exec sessions start as root and root-owned 0600 credentials are unreadable to the server. The server-env `CLAUDE_CODE_OAUTH_TOKEN` was never used (upstream `stripAiAuthBindings` blanks it; no pasted setup-token path without a Daytona sandbox) and is dropped from the spec. Owner follow-up (not in git): remove the unused `CLAUDE_CODE_OAUTH_TOKEN` field from OpenBao `homelab/apps/paperclip`. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
claude-bot added 1 commit 2026-09-25 11:48:44 +00:00
feat(paperclip): disable sign-up; document the Claude connection
ci/woodpecker/pr/ci-scripts-test Pipeline was successful
ci/woodpecker/pr/ci-manifests-test Pipeline was successful
ci/woodpecker/pr/pr-review Pipeline was canceled
30931d3f50
The first admin is claimed, so PAPERCLIP_AUTH_DISABLE_SIGN_UP flips to
true.

Spec: Claude auth is a Paperclip-managed subscription connection created
once via the local sign-in. The server-env CLAUDE_CODE_OAUTH_TOKEN was
never used (stripAiAuthBindings blanks it for managed runs; upstream
accepts no pasted setup-token), so it is dropped from the spec. The
login must run as the node user: exec sessions start as root and
root-owned 0600 credentials are unreadable to the server.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
claude-bot added 1 commit 2026-09-25 11:51:47 +00:00
fix(paperclip): agents call the API on loopback, not through the gate
ci/woodpecker/pr/ci-scripts-test Pipeline was successful
ci/woodpecker/pr/ci-manifests-test Pipeline was successful
ci/woodpecker/pr/pr-review Pipeline was canceled
161d0561e7
Upstream derives the agents' PAPERCLIP_API_URL from the public URL, so
agent API calls went out through Traefik to the paperclip-gate outpost.
With intercept_header_auth the outpost treats the agent's Authorization
header as an Authentik credential and returns 401; agents could not
create tasks, post cards or update status.

Agents run in the server pod (option B), so PAPERCLIP_API_URL is set to
http://localhost:3100 (upstream keeps an explicit value and passes it to
every run). Loopback passes the private-hostname guard and agent JWTs
still authenticate each call; the gate stays fully enforced for browser
traffic instead of carving out /api/.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
claude-bot added 1 commit 2026-09-25 11:52:51 +00:00
fix(paperclip): agents use the Service name for the API
ci/woodpecker/pr/ci-scripts-test Pipeline was successful
ci/woodpecker/pr/ci-manifests-test Pipeline was successful
ci/woodpecker/pr/pr-review Pipeline was successful
56e30bf065
The cluster-internal name keeps working when runs move to sandbox pods
(option C), where loopback would not reach the server. The name is
added to PAPERCLIP_ALLOWED_HOSTNAMES because the private-hostname guard
otherwise returns 403 for it. Same-namespace traffic is already allowed
by the baseline CNP in both directions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
review-bot left a comment
Member

🤖 Automated review — model CLI default (complexity: unknown), commit 56e30bf065cc1ea73a53c7c0d0a3b1c4ca9fd12a.

Advisory review by the review-bot pipeline. It never approves; a human merges. Push new commits to get a fresh review.


Summary

Follow-up to #966: flips PAPERCLIP_AUTH_DISABLE_SIGN_UP to "true" now that the first
admin is claimed, adds PAPERCLIP_API_URL/PAPERCLIP_ALLOWED_HOSTNAMES so agents reach
the API through the in-cluster Service instead of the public URL (which the Authentik
gate would otherwise reject bearer tokens for), and updates the design spec to match —
including correcting it to say Claude auth is a Paperclip-managed local-login connection
rather than the previously-planned shared CLAUDE_CODE_OAUTH_TOKEN. No blocking issues
found; this is a small, well-scoped docs+manifest change consistent with the plan in
docs/superpowers/plans/2026-09-25-paperclip.md (Task 9, Step 7.3) and the network
policy already in place.

🟡 Suggestions

  • kubernetes/apps/paperclip/paperclip.yaml:57-58 — Flipping
    PAPERCLIP_AUTH_DISABLE_SIGN_UP to "true" is a one-way door: once merged and
    reconciled, nobody can sign up again, so if the admin claim mentioned in the PR
    description ("the first admin is claimed") turns out not to have actually completed
    successfully, recovery requires a second PR (or a manual kubectl set env) to flip it
    back. Worth a final confirmation that /bootstrap/claim was actually exercised on the
    live instance before merging, since nothing in this diff can verify that from the repo
    side.
  • Spec doc, ai-local-logins/<id> and the specific behavior of stripAiAuthBindings,
    intercept_header_auth, and the private-hostname guard's handling of
    PAPERCLIP_ALLOWED_HOSTNAMES (docs/superpowers/specs/2026-09-25-paperclip-design.md:19,82-86)
    are asserted as upstream facts but aren't verifiable from this checkout (no vendored
    Paperclip source). The implementation plan's Task 1 calls for reading the actual
    upstream source (gh api .../server/src/...) to settle exactly these questions, so
    presumably that was done — just flagging that this review couldn't independently
    confirm the upstream behavior claims, only that they're internally consistent with the
    rest of the spec and with the env vars actually set in the manifest.

Tests

No test suite applies to this docs+manifest change; the repo's CI has a dedicated
kubernetes/**-triggered pipeline (.woodpecker/ci-manifests-test.yml) that runs
kubectl kustomize across the tree and would catch structural breakage (bad resource
refs, invalid YAML) in paperclip.yaml. Semantic correctness of the new env vars
(whether PAPERCLIP_ALLOWED_HOSTNAMES actually makes the private-hostname guard accept
the Service FQDN, whether flipping sign-up off doesn't lock out the claimed admin) can
only be confirmed by watching the live reconcile and testing a real agent run, per
"Verification" in the spec and Task 9 Step 7.2 in the plan — this is inherent to
infra-as-docs PRs like this one, not a gap introduced here.

Recommendation

Looks reasonable — no blocking issues; comments above are optional.

🤖 **Automated review** — model `CLI default` (complexity: unknown), commit `56e30bf065cc1ea73a53c7c0d0a3b1c4ca9fd12a`. > Advisory review by the `review-bot` pipeline. It never approves; a human merges. Push new commits to get a fresh review. --- ## Summary Follow-up to #966: flips `PAPERCLIP_AUTH_DISABLE_SIGN_UP` to `"true"` now that the first admin is claimed, adds `PAPERCLIP_API_URL`/`PAPERCLIP_ALLOWED_HOSTNAMES` so agents reach the API through the in-cluster Service instead of the public URL (which the Authentik gate would otherwise reject bearer tokens for), and updates the design spec to match — including correcting it to say Claude auth is a Paperclip-managed local-login connection rather than the previously-planned shared `CLAUDE_CODE_OAUTH_TOKEN`. No blocking issues found; this is a small, well-scoped docs+manifest change consistent with the plan in `docs/superpowers/plans/2026-09-25-paperclip.md` (Task 9, Step 7.3) and the network policy already in place. ## 🟡 Suggestions - **`kubernetes/apps/paperclip/paperclip.yaml:57-58`** — Flipping `PAPERCLIP_AUTH_DISABLE_SIGN_UP` to `"true"` is a one-way door: once merged and reconciled, nobody can sign up again, so if the admin claim mentioned in the PR description ("the first admin is claimed") turns out not to have actually completed successfully, recovery requires a second PR (or a manual `kubectl set env`) to flip it back. Worth a final confirmation that `/bootstrap/claim` was actually exercised on the live instance before merging, since nothing in this diff can verify that from the repo side. - Spec doc, `ai-local-logins/<id>` and the specific behavior of `stripAiAuthBindings`, `intercept_header_auth`, and the private-hostname guard's handling of `PAPERCLIP_ALLOWED_HOSTNAMES` (`docs/superpowers/specs/2026-09-25-paperclip-design.md:19,82-86`) are asserted as upstream facts but aren't verifiable from this checkout (no vendored Paperclip source). The implementation plan's Task 1 calls for reading the actual upstream source (`gh api .../server/src/...`) to settle exactly these questions, so presumably that was done — just flagging that this review couldn't independently confirm the upstream behavior claims, only that they're internally consistent with the rest of the spec and with the env vars actually set in the manifest. ## Tests No test suite applies to this docs+manifest change; the repo's CI has a dedicated `kubernetes/**`-triggered pipeline (`.woodpecker/ci-manifests-test.yml`) that runs `kubectl kustomize` across the tree and would catch structural breakage (bad resource refs, invalid YAML) in `paperclip.yaml`. Semantic correctness of the new env vars (whether `PAPERCLIP_ALLOWED_HOSTNAMES` actually makes the private-hostname guard accept the Service FQDN, whether flipping sign-up off doesn't lock out the claimed admin) can only be confirmed by watching the live reconcile and testing a real agent run, per "Verification" in the spec and Task 9 Step 7.2 in the plan — this is inherent to infra-as-docs PRs like this one, not a gap introduced here. ## Recommendation Looks reasonable — no blocking issues; comments above are optional. <!-- pr-review:sha=56e30bf065cc1ea73a53c7c0d0a3b1c4ca9fd12a -->
k.renner merged commit e82303c314 into master 2026-09-25 11:57:09 +00:00
Sign in to join this conversation.