KeiSeiKit-1.0/_primitives
Parfii-bot 23b818a682 fix(auth): SecretString redacted Serialize + PKCE verifier wired
Two findings from KeiSeiKit2.0 pr-review (~/Projects/KeiSeiKit2.0/skills/pr-review)
applied to commit range 897d010..HEAD.

1. BLOCKER — SecretString silently leaked plaintext via Serialize.

   File: _primitives/_rust/kei-runtime-core/src/secrets.rs
   Was: derive(Serialize) + serde(transparent) -> serde_json::to_string(&secret)
        emitted the raw plaintext in any parent struct with #[derive(Serialize)].
        Debug was redacted but Serialize was not. Defeated the type's purpose.
   Now: manual Serialize impl always emits literal "<redacted>". Deserialize
        derive kept (callers need to read secrets from config/env).
        Test serialize_emits_redacted_literal asserts JSON output is "\"<redacted>\"".

2. WARNING — PKCE code_verifier dropped before token exchange.

   build_auth_url generated code_challenge = SHA256(verifier) but verify() never
   threaded the verifier to the token endpoint. Token exchange submitted no
   code_verifier, defeating the PKCE protection.

   Files:
   - _primitives/_rust/kei-runtime-core/src/traits/auth.rs:
     AuthChallenge::OAuthCode now carries code_verifier: Option<String>.
     Caller stores verifier alongside state in their session-store, exactly as
     they already store state for CSRF check.
   - _primitives/_rust/kei-auth-google/src/provider.rs:
     verify() destructures code_verifier and passes to client.exchange_code(...).
   - _primitives/_rust/kei-auth-apple/src/provider.rs:
     same change.

   Tests added (wiremock body assertions):
   - google_smoke / apple_smoke: assert exchange request body contains
     code_verifier=<value> when challenge carried Some(verifier).
   - existing tests updated to construct OAuthCode { ..., code_verifier: None }.

Test split (Constructor Pattern 200 LOC):
   - apple_smoke.rs grew over 200 LOC after PKCE test addition. Split into
     apple_smoke.rs (provider tests) + apple_client_smoke.rs (client tests).
   - same for google_smoke.rs / google_client_smoke.rs.

Test results: 31 passed; 0 failed across kei-auth, kei-auth-apple, kei-auth-google,
kei-runtime-core unit + integration tests. cargo check --workspace clean.

Breaking change: any caller that constructs AuthChallenge::OAuthCode outside this
workspace must add code_verifier field (None for legacy no-PKCE; Some for PKCE).
Compile-time surfaced gap, not runtime regression.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 23:49:10 +08:00
..
_rust fix(auth): SecretString redacted Serialize + PKCE verifier wired 2026-05-02 23:49:10 +08:00
templates feat(live-graph): WebSocket activity stream — orchestrator-centric live view 2026-05-02 13:30:24 +08:00
design-scrape.sh KeiSeiKit-public — clean state 2026-05-01 12:09:03 +08:00
figma-tokens.sh KeiSeiKit-public — clean state 2026-05-01 12:09:03 +08:00
frontend-inspect.sh KeiSeiKit-public — clean state 2026-05-01 12:09:03 +08:00
harden-base.sh KeiSeiKit-public — clean state 2026-05-01 12:09:03 +08:00
kei-ci-lint.sh KeiSeiKit-public — clean state 2026-05-01 12:09:03 +08:00
kei-docs-scaffold.sh KeiSeiKit-public — clean state 2026-05-01 12:09:03 +08:00
kei-doctor.sh KeiSeiKit-public — clean state 2026-05-01 12:09:03 +08:00
kei-sleep-queue.sh KeiSeiKit-public — clean state 2026-05-01 12:09:03 +08:00
kei-sleep-setup.sh KeiSeiKit-public — clean state 2026-05-01 12:09:03 +08:00
kei-sleep-sync.sh feat(sleep-sync): mirror time-metrics + ledger snapshots, surface in Phase B report 2026-05-02 04:02:28 +08:00
live-preview.sh KeiSeiKit-public — clean state 2026-05-01 12:09:03 +08:00
log-ship.sh KeiSeiKit-public — clean state 2026-05-01 12:09:03 +08:00
MANIFEST.toml KeiSeiKit-public — clean state 2026-05-01 12:09:03 +08:00
metrics-scrape.sh KeiSeiKit-public — clean state 2026-05-01 12:09:03 +08:00
provision-hetzner.sh KeiSeiKit-public — clean state 2026-05-01 12:09:03 +08:00
provision-vultr.sh KeiSeiKit-public — clean state 2026-05-01 12:09:03 +08:00
README.md KeiSeiKit-public — clean state 2026-05-01 12:09:03 +08:00
screenshot-decode.sh KeiSeiKit-public — clean state 2026-05-01 12:09:03 +08:00
tomd.sh KeiSeiKit-public — clean state 2026-05-01 12:09:03 +08:00

_primitives — first-class building blocks

_primitives/ holds standalone utilities that agents, hooks, and skills (including /compose-solution) depend on. Unlike _blocks/ (behavioral markdown) or _manifests/ (agent TOML), primitives are executable shell programs installed at $HOME/.claude/agents/_primitives/ by install.sh.

Current primitives

Primitive Purpose Invocation
tomd.sh Universal non-native-format → markdown converter (PDF, DOCX, XLSX, PPTX, CSV, images, code). ~/.claude/agents/_primitives/tomd.sh <file>

tomd.sh is a first-class primitive. Universal non-native-format → markdown converter with configurable cache directory (KEISEI_TOMD_CACHE) and KeiSeiKit-style error tags ([tomd]).

Hook integration

hooks/tomd-preread.sh is a PreToolUse(Read) hook that auto-redirects Claude to the converted markdown when a Read targets .docx / .doc / .xlsx / .pptx / .csv. Cached under $KEISEI_TOMD_CACHE (default /tmp/keisei-tomd-cache).

/compose-solution discovery

Phase 3 prior-art sweep greps _primitives/ alongside _blocks/, _manifests/, skills/, _bridges/, hooks/. If a user task involves file-format parsing, the meta-composer surfaces tomd automatically — reuse over rewrite (RULE "No Patching").