feat(e13-s4/s5): add --from-text (local) and --ai (opt-in, secret-free, interactive) parse - #62
Merged
Conversation
…ged for LF Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Completes E13 — Smart
addOnboarding with the paste-text paths.add --from-text <text>/--from-text -— local heuristic parse viainternal/blobparse. Zero network. The default paste path.add --from-text ... --ai— opt-in escalation (internal/aiparse). Strips secrets locally, sends only the desensitized text to an Anthropic-compatible Messages endpoint using the active profile's credentials (--ai-profile <name>to override), receives strict core JSON, re-injects the secret locally. Off by default; explicit per run.Security model (load-bearing — this is the only networked path in claudecm)
Defense in depth, because reliably redacting arbitrary prose is not a solved problem:
blobparsecaptures secrets by shape (sk-, JWT,gh*/xox*/pat/token, GoogleAIza, 40-hex, high-entropy ≥32) and by field name (secret/password/token/api_key/auth/authorization/credential/private_key/access_key/client_secret), taking the whole value to end-of-line.aiparse.EnsureSecretFreere-scans the request body (shape + name) and refuses to send if any secret-shaped/secret-named token survives.--airequires an interactive TTY; it prints the credential-lending profile and the exact desensitized payload and asks for confirmation before sending. Non-interactive / piped--airefuses before any network call.api_keyonly ever goes in thex-api-keyheader;base_urluserinfo is stripped from the endpoint; no credential or response body is echoed in errors/logs/dry-run.DisallowUnknownFields); a returnedapi_keymust match a locally captured placeholder or it is rejected. Non-anthropic lender / missing creds / malformed response all refuse.Review trail (two adversarial passes, both found real leaks)
6c74b86): non-shape secret-named fields (CLIENT_SECRET=…) were reaching the LLM; borrowedbase_urluserinfo leaked into the request URL.bfdd9aa): secret-named unquoted values with spaces (AUTH=Bearer <token>) only redacted the first token;Authorizationfield name wasn't recognized; added the mandatory-interactive gate so the heuristic tail is backstopped by human review.Independently verified (oracle not derived from production regexes; real binary):
CLIENT_SECRET/PASSWORD/DATABASE_TOKEN/private_key/Bearer/Authorizationvalues all redact to placeholders; endpoint strips userinfo; non-interactive--airefuses (exit 1, no network);--from-textlocal path is zero-network.go test ./...+go vet ./...clean.ADR-0003 narrowly amends ADR-0001 Decision 8's no-network stance only for this opt-in, interactive-only, secret-free
--aiparse. Status marked Accepted (CEO-delegated); the network direction is flagged for your ratification. Every other E13 path is zero-network.🤖 Generated with Claude Code