Commit graph

7 commits

Author SHA1 Message Date
Parfii-bot
39f95f7e04 fix(cortex-ui): strip whitespace from token; drop credentials:'include'
Live e2e test caught a paste-inserted whitespace in URL token param —
copy-paste from terminal had inserted %20%20%20 into middle of the
64-char hex token, which passed URL parsing but failed byte-level
auth::tokens_match on the daemon → 403.

Two fixes:

1. `sanitize_token()` strips ALL whitespace (spaces, tabs, newlines,
   zero-width) from token before use, applied on both URL-param and
   localStorage read paths. Defensive even against future Setup-form
   paste mishaps — Setup input itself could also be whitespace-dirty.

2. `credentials: 'include'` → `credentials: 'omit'`. Bearer auth rides
   on an explicit header; we don't need cookies. `include` triggers
   browser quirks (Safari especially) around credentialed cross-origin
   fetches that can strip or mismangle Authorization on redirects.

3. Error message now includes response body preview — `"403 Forbidden
   — {\"error\":{\"code\":\"forbidden\",\"message\":\"bearer token
   rejected\"}}"` — so the next failing setup surfaces root-cause.

Tests unchanged (10 passing). Rebuild hash: index-7ZqAoBoM.js.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 03:14:09 +08:00
Parfii-bot
6672ae48e7 feat(wave20): kei-cortex daemon + cortex-ui — local HTTP + TypeScript web UI
49 crates, 876 tests green (+17 kei-cortex + 10 cortex-ui TS, was 859).

## kei-cortex — local HTTP daemon (Rust)

Axum-based server on :9797 exposing read-only cortex state (ledger,
pet, memory) as JSON for browser UI consumption. Bearer token auth.
CORS for https://keisei.app. Binds 127.0.0.1 only.

### Endpoints

- GET  /healthz — unauthenticated liveness
- GET  /api/v1/cortex/summary — total_dnas + active_pets + recent_sessions
- GET  /api/v1/cortex/pet/:user_id — pet manifest
- POST /api/v1/cortex/pet/:user_id/interaction — log chat
- GET  /api/v1/cortex/ledger/recent?limit=N — recent agent runs
- GET  /api/v1/cortex/memory/search?user_id=X&pet_name=Y&q=... — recall

### Security

- Token at ~/.keisei/cortex.token (32-byte hex, chmod 600 atomic via
  OpenOptions mode 0o600)
- tower-http CorsLayer with configured allow_origin
- tokio::task::spawn_blocking for rusqlite reads
- All non-healthz routes protected by Bearer middleware

### Constructor Pattern

14 files, largest 137 LOC. All functions ≤30 LOC. Split: auth / config
/ error / state / routes + 5 handlers (health/summary/pet/ledger/memory).

17 tests: token roundtrip + chmod 600 (cfg unix) + 401/403/healthz +
summary shape + pet 404 + pet parse + interaction 201 + CORS preflight
+ ledger limit + empty ledger.

## cortex-ui — Svelte 5 + TypeScript + Vite

Static web app, build to dist/ (~500 KB incl sourcemaps, 64 KB minified
JS+CSS), deployable to https://keisei.app/cortex/. Connects to local
kei-cortex daemon via fetch.

### Features

- Setup wizard (first run): daemon URL + token paste, saved to
  localStorage (origin-scoped)
- Dashboard: summary cards + nav
- PetEditor: view pet.toml fields (identity/voice/edge/forbidden)
- LedgerStream: recent agent runs, auto-refresh 5s
- MemorySearch: query form + results list
- Hash-based routing (no server needed)
- Dark-mode via prefers-color-scheme
- URL-param override: ?daemon=URL&token=T for one-click setup

### Stack choice

Svelte 5 for minimal runtime (~2 KB). TypeScript strict inherits
_ts_packages/tsconfig.base.json. Vite for dev + build. vitest for unit
tests (10 passing: api header/error, config precedence/overrides).

## User flow

Non-dev:
1. Install keisei, run `kei-cortex serve`
2. Open https://keisei.app/cortex
3. Paste daemon URL + token from ~/.keisei/cortex.token
4. View dashboard, edit pet, search memory — all local data, zero cloud

Power user (self-host):
1. `cd _ts_packages/packages/cortex-ui && npm run build`
2. Serve dist/ from localhost OR deploy anywhere
3. Point to own daemon URL

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 01:50:21 +08:00
Parfii-bot
d09dc5b142 chore(v0.19.1): replace placeholder bun.lock with real lockfile + fix workspace path
bun is a monorepo tool — lockfile lives at workspace root
(_ts_packages/bun.lock), not per-subpackage. Placeholder at
_ts_packages/packages/mcp-server/bun.lock was the wrong path.

Changes:
  - Generated real _ts_packages/bun.lock (626 lines) via 'bun install'
    (bun 1.3.13, auto-migrated from package-lock.json)
  - .github/workflows/release.yml working-directory:
    _ts_packages/packages/mcp-server → _ts_packages (workspace root)
  - BUILD.md Lockfile section rewritten to document workspace-root
    location + coexistence with package-lock.json (L2 audit finding
    partially resolved — full consolidation deferred to v0.20)

release.yml build-mcp-binary job now has real lockfile to consume —
H4 'tag build fails on missing lockfile' gate still active but now
there's something actually committed to satisfy it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 17:16:57 +08:00
Parfii-bot
ca046e61c1 fix(v0.19.1): supply-chain hardening remainder — ci.yml SHA-pin + dependabot + bun.lock placeholder
Follow-up to c27b626 (release.yml pinning). Finishes H4 + H5.

ci.yml:
  - 11 third-party actions SHA-pinned with # vN.m.k comments
  - actions/checkout@34e114876b... (v4.3.1)
  - actions/setup-node@49933ea5288... (v4.4.0)
  - dtolnay/rust-toolchain@3c5f7ea28... (rust 1.94.1)
  - Swatinem/rust-cache@c19371144... (v2.9.1)

.github/dependabot.yml (NEW):
  - 3 ecosystems weekly: github-actions, npm, cargo
  - PR cap 5, labels [dependencies, <ecosystem>]
  - Auto-opens update PRs for SHA bumps — human reviews, not silent churn

_ts_packages/packages/mcp-server/bun.lock (NEW — placeholder):
  - 13-line comment explaining H4 gate
  - Instructs: 'cd _ts_packages/packages/mcp-server && bun install' before release
  - release.yml (since v0.19.1) uses --frozen-lockfile with NO fallback —
    missing real lockfile fails the build deliberately

BUILD.md:
  - New 'Lockfile' section (19 LOC) documenting the pre-release workflow

CHANGELOG.md:
  - [Unreleased] → Security: 3 bullets covering this + prior supply-chain commit

All SHAs E1 (verified via api.github.com or reused from release.yml).

NEXT STEP BEFORE TAGGING v0.19.1:
  Populate real bun.lock locally, commit, then tag. Workflow will fail
  on missing/stale lockfile — that's the point of H4 defense.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 17:12:15 +08:00
Parfii-bot
e67ade47c8 feat(v0.18): kei-mcp-server single-binary compile — 5-platform via bun
Phase 1 of exobrain architecture. Ships TS MCP server as a static
binary so users on machines without Node can run KeiSeiKit (USB /
flashdrive / air-gapped scenarios).

.github/workflows/release.yml (+62 LOC) — new build-mcp-binary job:
  - 5-target matrix: darwin arm64/x64, linux arm64/x64, windows x64
  - bun build --compile, linux arm64 continue-on-error (ARM runners
    less reliable)
  - Artifact kei-mcp-server-<os>-<arch>[.exe] + sha256
  - release job now needs [build-release, build-mcp-binary]

install/lib-rust.sh (+50 LOC) — have_prebuilt_mcp_server() +
  report_mcp_server_binary_status(); KEI_SKIP_MCP_BUILD=1 env
  flag skips bun/npm install when a prebuilt binary is present.
  File 165 LOC (<200 limit).

_ts_packages/packages/mcp-server/package.json — scripts.build:native
  + 5 per-target aliases (macos-arm, macos-x64, linux-x64,
  linux-arm, win-x64) for local dev.

_ts_packages/packages/mcp-server/BUILD.md (NEW, 52 LOC) — local
  compile guide per platform + Gatekeeper/code-sign notes +
  cites bun docs [VERIFIED: https://bun.sh/docs/bundler/executables].

README.md pre-built-binaries section gains 'MCP server binary'
subsection (download, chmod +x, xattr -d com.apple.quarantine for
macOS, UAC note for Windows).

CHANGELOG.md [Unreleased] bullet added.

Output size: ~90 MB per binary (bundled bun runtime). Acceptable
trade for zero-dep USB distribution.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 15:52:36 +08:00
Parfii-bot
24c584ee50 fix: remove genesis-scan from public kit (internal tool, Bundle-only)
Per user decision: publishing the sensitive IP pattern blocklist via public
scanner is leak of the blocklist itself (attack surface). genesis-scan
remains in PROJECT-E (private); user-global
~/.claude/hooks/genesis-leak-guard.sh (runtime hook) separate.

Deleted:
- _primitives/_rust/genesis-scan/ (whole crate, 5 files)
- hooks/git-pre-commit-genesis.sh (scanner companion)

Modified:
- workspace Cargo.toml -1 member (24→23)
- MANIFEST.toml — removed [primitive.genesis-scan] + core/full profile refs
- .github/workflows/ci.yml — removed genesis-scan job
- README.md — 7 count/description edits (24→23 rust, 10→9 hooks, 37→36 full)
- install.sh — 5 edits (--help + menus)
- mcp-server tool-registry.ts + test — scanner removed from MCP surface
- kei-sleep-queue.sh — removed scan_prompt() pre-submit hook
- 2 sleep-on-it skill phases — removed genesis-scan references

Tests: 160 Rust (was 167, -7 genesis-scan tests as expected), 24 assembler unchanged.
2026-04-22 14:11:22 +08:00
Parfii-bot
c21943e40b feat(ts-packages): 6 TS packages — MCP server + 5 external-API adapters
Total 1465 LOC + 616 test LOC, 78/78 tests pass.
- @keisei/mcp-server (25 tests) — Rust-CLI bridge via execa, stdio+HTTP, HMAC auth, kei() meta-tool
- @keisei/telegram-adapter (16 tests) — grammy Bot, 7 tools
- @keisei/recall-adapter (8 tests) — Zoom via Recall.ai, 5 tools
- @keisei/grok-adapter (6 tests) — xAI OpenAI-compatible, 2 tools
- @keisei/gmail-adapter (11 tests) — googleapis OAuth2, 6 tools (new — LBM gap)
- @keisei/youtube-adapter (12 tests) — YouTube Data API v3, 5 tools (new — LBM gap)

RULE 0.2 exception #4 (TS for MCP/API layer documented in _ts_packages/README.md).
RULE 0.8 — env vars only (TELEGRAM_BOT_TOKEN, XAI_API_KEY, GMAIL_*, YOUTUBE_API_KEY).
Strict TypeScript: strict + exactOptionalPropertyTypes + noUncheckedIndexedAccess.
Genesis-scan clean (0 hits).
2026-04-22 12:45:19 +08:00