M0: compilable skeleton — Kigi 0.1.0 fork surgery
Hard fork of xai-org/grok-build (Apache-2.0) re-targeted as Kigi, an
unofficial Kimi Code CLI community build.
Rename & identity
- 72 xai-*/xai-grok-* crates -> kigi-* (explicit: xai-grok-pager-bin ->
kigi-bin [binary `kigi`], xai-grok-pager -> kigi-tui; rest mechanical);
ptyctl, ptyctl-cli, third_party/ unchanged; proto package
xai.grok.tools.v1 -> kigi.tools.v1
- Config home ~/.kigi (KIGI_SHARE_DIR override), env prefix GROK_* ->
KIGI_*, `kigi --version` carries the unofficial-community-build notice
- clap identity, help text, startup banner, prompt templates rebranded
(templates re-encrypted)
Deletions (PRD removal list #5/#6/#7/#9/#10)
- voice input (xai-grok-voice) and all TUI wiring
- telemetry: Mixpanel client, external OTel stream, Sentry, OTLP layers,
trace/GCS/S3 upload queues (kigi-file-utils halved), workspace upload
module & dc_log, heap-profile uploader, auth-diagnostics uploader,
session-analytics halves of feedback; local zero-egress observability
preserved in new kigi-log crate (unified log, --debug firehose,
subsystem file logs, opt-in instrumentation)
- announcements (crate, remote-settings fields, TUI surfaces)
- plugin marketplace (crate, sources/browse/CTA/extensions-modal tab);
direct plugin install/uninstall/update via kigi-agent git_install kept
- relay/gateway/assets endpoints and features (agent relay, headless
relay transport, gateway bridge, LeaderEnvUrls); leader IPC socket now
~/.kigi/leader.sock + KIGI_LEADER_SOCKET, no ws-url derivation
- functional types rehomed instead of deleted: PermissionMode ->
kigi-config-types, McpInitStrategy -> kigi-mcp, PrCreationSource ->
session signals, TerminalDiagnostics -> kigi-pager-render, agent_id ->
shell util
Endpoints
- kigi-env rewritten: single production KigiEndpoints {coding_api_base_url
https://api.kimi.com/coding/v1 (KIGI_CODE_BASE_URL), oauth_host
https://auth.kimi.com (KIGI_OAUTH_HOST), update_base_url (GitHub
Releases API), upgrade_page_url}; GrokBuildEnvironment enum deleted
Toolchain & workspace hygiene
- Rust 1.97.0 pinned; edition 2024; full cargo update; git2 hoisted to
workspace at 0.21 (Option->Result API migration), quick-xml 0.41
- Root Cargo.toml hand-maintained (PRD §8.1): version 0.1.0 inherited by
all members, members sorted, unused deps pruned
- cargo-deny advisories gate (deny.toml with documented transitive
exceptions); CI workflow (check/clippy/fmt/deny/test, macOS+Linux)
- cross-crate test seams re-gated behind `test-support` cargo feature;
insta snapshot baselines renamed to the kigi_tui prefix
- clippy --workspace --all-targets: zero warnings; fmt clean
Fixes surfaced by the port
- updater probe/installer divergence (bin/kigi vs bin/grok symlink set)
- idle model-metadata refresh dead under KIGI_CODE_BASE_URL override
(new is_effective_coding_endpoint_url, loopback+override aware)
- macOS symlinked-TMPDIR fixture canonicalization (foreign_sessions,
fast-worktree); RSS measurement tests serialized via serial_test
Docs & legal (Apache §4)
- NOTICE added (upstream attribution + change statement); THIRD-PARTY
notices sustained; kigi-tools ported-code notices extended; README,
CONTRIBUTING, SECURITY, AGENTS.md rewritten
Out of scope for M0 (tracked): Kimi auth/inference (M1), search/fetch,
command parity, config import (M2), Computer Hub excision & final
brand-token sweep (M2), distribution & self-update rewrite (M3).
This commit is contained in:
commit
d6c20fc13f
2612 files changed
+1353757
No files matched your search
@@ -0,0 +1,196 @@
|
||||
//! macOS MDM managed-preferences layer.
|
||||
//!
|
||||
//! Admins push a device profile with standard-base64 (padded) TOML under
|
||||
//! preference domain `ai.x.kigi` (`requirements_toml_base64`). Only admin-*forced*
|
||||
//! values are read, so a local user can't forge it via their own preference
|
||||
//! domain; trusted on every launch, independent of network/cache. `None` off macOS.
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
const MANAGED_PREFERENCES_DOMAIN: &str = "ai.x.kigi";
|
||||
#[cfg(target_os = "macos")]
|
||||
const REQUIREMENTS_KEY: &str = "requirements_toml_base64";
|
||||
|
||||
/// Synthetic source label for the MDM layer (no file on disk); diagnostics only.
|
||||
pub const MDM_REQUIREMENTS_SOURCE: &str = "ai.x.kigi:requirements_toml_base64";
|
||||
|
||||
/// The MDM-forced requirements TOML, or `None` when none is forced (or not macOS).
|
||||
pub(crate) fn managed_preferences_requirements() -> Option<toml::Value> {
|
||||
// Read once and cache for the process lifetime: the forced policy is fixed per
|
||||
// launch, so a mid-session profile change isn't picked up until restart — fine
|
||||
// for a short-lived CLI, and it avoids re-crossing the CoreFoundation boundary.
|
||||
static CACHED: std::sync::OnceLock<Option<toml::Value>> = std::sync::OnceLock::new();
|
||||
CACHED
|
||||
.get_or_init(|| managed_requirements_from(read_forced_requirements))
|
||||
.clone()
|
||||
}
|
||||
|
||||
/// Decode the forced requirements from a raw-string reader. Split from the FFI
|
||||
/// read (`read_forced_requirements`) so the forced → decode path is unit-testable
|
||||
/// without CoreFoundation (the CFPreferences read/downcast itself stays FFI).
|
||||
fn managed_requirements_from(read: impl FnOnce() -> Option<String>) -> Option<toml::Value> {
|
||||
decode_managed_toml(&read()?)
|
||||
}
|
||||
|
||||
/// Decode a base64 TOML payload into a non-empty table. The forced payload is
|
||||
/// used **verbatim** — `$VAR`/`${VAR}` are deliberately NOT expanded: this is
|
||||
/// the trusted, non-forgeable admin layer, and expanding from the local process
|
||||
/// environment would let the very user the forced check excludes influence the
|
||||
/// policy (which feeds yolo / permission / minimum-version enforcement). FFI-free,
|
||||
/// so unit-tested on every platform; invalid base64/UTF-8/TOML or an empty table
|
||||
/// yields `None`.
|
||||
fn decode_managed_toml(encoded: &str) -> Option<toml::Value> {
|
||||
use base64::Engine as _;
|
||||
|
||||
// Strip all whitespace: profile tooling line-wraps payloads and the STANDARD
|
||||
// engine rejects interior whitespace.
|
||||
let compact: String = encoded
|
||||
.chars()
|
||||
.filter(|c| !c.is_ascii_whitespace())
|
||||
.collect();
|
||||
let decoded = base64::engine::general_purpose::STANDARD
|
||||
.decode(compact.as_bytes())
|
||||
.map_err(|e| tracing::warn!("managed preference is not valid base64: {e}"))
|
||||
.ok()?;
|
||||
let toml_str = String::from_utf8(decoded)
|
||||
.map_err(|e| tracing::warn!("managed preference is not valid UTF-8: {e}"))
|
||||
.ok()?;
|
||||
let value = toml::from_str::<toml::Value>(&toml_str)
|
||||
.map_err(|e| {
|
||||
// Redact via the span-only detail: a TOML error's Display echoes the
|
||||
// offending source line, and an admin payload may carry secrets.
|
||||
tracing::warn!(
|
||||
"managed preference is not valid TOML: {}",
|
||||
crate::loader::toml_error_detail(&toml_str, &e)
|
||||
)
|
||||
})
|
||||
.ok()?;
|
||||
value
|
||||
.as_table()
|
||||
.is_some_and(|t| !t.is_empty())
|
||||
.then_some(value)
|
||||
}
|
||||
|
||||
/// The raw forced `requirements_toml_base64` MDM string via CoreFoundation, or
|
||||
/// `None`. macOS only.
|
||||
#[cfg(target_os = "macos")]
|
||||
fn read_forced_requirements() -> Option<String> {
|
||||
use core_foundation::base::{CFType, CFTypeRef, TCFType};
|
||||
use core_foundation::string::{CFString, CFStringRef};
|
||||
|
||||
// `CFPreferencesCopyAppValue` returns a +1 CFPropertyListRef (Copy rule).
|
||||
#[link(name = "CoreFoundation", kind = "framework")]
|
||||
unsafe extern "C" {
|
||||
fn CFPreferencesCopyAppValue(key: CFStringRef, application_id: CFStringRef) -> CFTypeRef;
|
||||
fn CFPreferencesAppValueIsForced(key: CFStringRef, application_id: CFStringRef) -> u8;
|
||||
}
|
||||
|
||||
let cf_key = CFString::new(REQUIREMENTS_KEY);
|
||||
let cf_app = CFString::new(MANAGED_PREFERENCES_DOMAIN);
|
||||
|
||||
// Trust only admin-forced values: otherwise the lookup falls through to the
|
||||
// per-user domain, which a local user can set (`defaults write ai.x.kigi`)
|
||||
// to forge an `is_system`-trusted layer.
|
||||
let forced = unsafe {
|
||||
CFPreferencesAppValueIsForced(cf_key.as_concrete_TypeRef(), cf_app.as_concrete_TypeRef())
|
||||
};
|
||||
if forced == 0 {
|
||||
return None;
|
||||
}
|
||||
|
||||
let value_ref = unsafe {
|
||||
CFPreferencesCopyAppValue(cf_key.as_concrete_TypeRef(), cf_app.as_concrete_TypeRef())
|
||||
};
|
||||
if value_ref.is_null() {
|
||||
return None;
|
||||
}
|
||||
// Type-check before reading as text: reading a non-CFString through CFString
|
||||
// APIs is UB. `wrap_under_create_rule` owns the +1, freeing it even if the
|
||||
// downcast fails.
|
||||
let value = unsafe { CFType::wrap_under_create_rule(value_ref) };
|
||||
value.downcast_into::<CFString>().map(|s| s.to_string())
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
fn read_forced_requirements() -> Option<String> {
|
||||
None
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use base64::Engine as _;
|
||||
|
||||
fn b64(s: &str) -> String {
|
||||
base64::engine::general_purpose::STANDARD.encode(s.as_bytes())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decodes_valid_base64_toml_table() {
|
||||
let v = decode_managed_toml(&b64("allowed_sandbox_modes = [\"read-only\"]\n"))
|
||||
.expect("valid payload decodes");
|
||||
assert_eq!(
|
||||
v.get("allowed_sandbox_modes")
|
||||
.and_then(|m| m.as_array())
|
||||
.map(|a| a.len()),
|
||||
Some(1)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decodes_line_wrapped_base64() {
|
||||
// Profile tooling line-wraps base64; interior newlines must be tolerated.
|
||||
let raw = b64("allowed_sandbox_modes = [\"read-only\"]\n");
|
||||
let wrapped = format!("{}\n{}", &raw[..4], &raw[4..]);
|
||||
assert!(decode_managed_toml(&wrapped).is_some());
|
||||
}
|
||||
|
||||
/// The forced payload is used verbatim: `$VAR`/`${VAR}` must NOT be expanded,
|
||||
/// so a local user can't influence the trusted admin layer through their env.
|
||||
#[test]
|
||||
fn forced_payload_is_not_env_expanded() {
|
||||
// SAFETY: process-global env mutation, restored before return.
|
||||
let prior = std::env::var("KIGI_MDM_NO_EXPAND_TEST").ok();
|
||||
unsafe { std::env::set_var("KIGI_MDM_NO_EXPAND_TEST", "attacker") };
|
||||
let decoded = decode_managed_toml(&b64("base_url = \"${KIGI_MDM_NO_EXPAND_TEST}/v1\"\n"));
|
||||
unsafe {
|
||||
match prior {
|
||||
Some(p) => std::env::set_var("KIGI_MDM_NO_EXPAND_TEST", p),
|
||||
None => std::env::remove_var("KIGI_MDM_NO_EXPAND_TEST"),
|
||||
}
|
||||
}
|
||||
assert_eq!(
|
||||
decoded
|
||||
.as_ref()
|
||||
.and_then(|v| v.get("base_url"))
|
||||
.and_then(|v| v.as_str()),
|
||||
Some("${KIGI_MDM_NO_EXPAND_TEST}/v1"),
|
||||
"forced payload must keep ${{VAR}} literal, not expand from the user env",
|
||||
);
|
||||
}
|
||||
|
||||
/// The forced gating around the FFI read: nothing forced → no layer; a forced
|
||||
/// valid payload → a layer; a forced but unparseable payload → no layer (never
|
||||
/// a partial/garbage layer). Exercises the seam without CoreFoundation.
|
||||
#[test]
|
||||
fn managed_requirements_gated_on_the_forced_read() {
|
||||
assert!(managed_requirements_from(|| None).is_none());
|
||||
assert!(
|
||||
managed_requirements_from(|| Some(b64("allowed_sandbox_modes = [\"read-only\"]\n")))
|
||||
.is_some()
|
||||
);
|
||||
assert!(managed_requirements_from(|| Some("not base64!!!".to_string())).is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rejects_garbage_and_empty() {
|
||||
// not valid base64
|
||||
assert!(decode_managed_toml("not base64!!!").is_none());
|
||||
// valid base64, but the bytes aren't valid UTF-8
|
||||
let bad_utf8 = base64::engine::general_purpose::STANDARD.encode([0xff, 0xfe]);
|
||||
assert!(decode_managed_toml(&bad_utf8).is_none());
|
||||
// valid base64 + valid UTF-8, but not parseable TOML
|
||||
assert!(decode_managed_toml(&b64("= not toml =")).is_none());
|
||||
// empty table → skipped (no managed preference effectively)
|
||||
assert!(decode_managed_toml(&b64("")).is_none());
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user