Require a token for writes and quarantine what nobody vouches for

Sixteen mutating routes now refuse a caller who cannot present the token the
server started with; queries stay open, because a question is not a write. The
environment variable is ELY_EYE_AUTH_TOKEN, following the repo's env_prefix
convention — the shorter name I reached for first returned 403 where the smoke
expected 401, and the server printed the reason.

Words from a stranger are quarantined on the way in: an HTTP upload is
third_party by definition, and a sentence carrying an instruction-shaped phrase
is quarantined whoever wrote it. A quarantined atom stays findable and stays out
of the compiled context until a second, live, unquarantined source agrees with
its rarest words. Corroboration is computed at read time because it is a
property of the corpus now, not of the moment a memory was written; it is
term-level, and the docstring says so.

forget now erases the source row and the compiled contexts beside the atoms, so
a forgotten memory leaves nothing that can still speak. The semantic cache key
carries a store revision, which fixes a real staleness: a context compiled
before new evidence arrived kept its old quarantine decision forever.

bench.audit --product still pointed at evals.py, which the p1-6 split moved into
backend/src/ely_eye/proofs/. It failed fast, but the anti-self-justification
rule had quietly stopped auditing the product; it now walks the package, and a
test pins that the package exists and holds no re-roll.

Gates: pytest 306 passed; ruff clean; mypy cold cache 24 errors in 9 files, the
recorded baseline, net zero; pyright 0 errors on the 23 backend files and the 2
bench files; go build/vet/test and gofmt clean; npm run build 221.39 kB with
eslint exit 0; bench/filesize_check clean; bench.audit --product clean over 31
harness files; scripts/mcp_write_smoke.sh PASS with the gate live across two
servers and the MCP child.
This commit is contained in:
ZacharyZhang-NY committed 2026-10-08 23:05:15 -04:00
1 parent 8b974e6626
commit 9145a23f18
32 files changed
+750 -58

No files matched your search

+23 -8
View File
@@ -1,7 +1,7 @@
import { Activity, Archive, Database, Gauge, RefreshCw, Server } from 'lucide-react';
import { useEffect, useState } from 'react';
import { getAdapters, getStatus } from './api';
import { getAdapters, getStatus, readToken, writeToken } from './api';
import { AdapterPanel } from './components/AdapterPanel';
import { CartridgePanel } from './components/CartridgePanel';
import { CompilerPanel } from './components/CompilerPanel';
@@ -17,6 +17,7 @@ export function App() {
const [status, setStatus] = useState<SystemStatus | null>(null);
const [adapters, setAdapters] = useState<AdapterStatus[]>([]);
const [error, setError] = useState<string | null>(null);
const [token, setToken] = useState(readToken);
async function refresh() {
const [nextStatus, nextAdapters] = await Promise.all([getStatus(), getAdapters()]);
@@ -63,13 +64,27 @@ export function App() {
<p className="eyebrow">Ely-Eye v4.0</p>
<h1>Local VLM Context OS</h1>
</div>
<button
className="icon-button"
title="Refresh status"
onClick={() => refreshQuietly()}
>
<RefreshCw size={18} />
</button>
<div className="topbar-actions">
<input
className="token-input"
type="password"
value={token}
placeholder="写入令牌"
aria-label="写入令牌"
title="服务器设置了 ELY_EYE_AUTH_TOKEN 时,写入需要它"
onChange={(event) => {
setToken(event.target.value);
writeToken(event.target.value);
}}
/>
<button
className="icon-button"
title="Refresh status"
onClick={() => refreshQuietly()}
>
<RefreshCw size={18} />
</button>
</div>
</header>
{error && <div className="error-line">{error}</div>}
+21 -1
View File
@@ -16,8 +16,28 @@ import type {
SystemStatus,
} from './types';
const TOKEN_KEY = 'ely_eye_token';
/** The write token lives in the browser, not in the bundle: a served page must not ship the owner's secret. */
export function readToken(): string {
return window.localStorage.getItem(TOKEN_KEY) ?? '';
}
export function writeToken(token: string): void {
if (token) {
window.localStorage.setItem(TOKEN_KEY, token);
} else {
window.localStorage.removeItem(TOKEN_KEY);
}
}
async function request<T>(url: string, init?: RequestInit): Promise<T> {
const response = await fetch(url, init);
const headers = new Headers(init?.headers);
const token = readToken();
if (token) {
headers.set('Authorization', `Bearer ${token}`);
}
const response = await fetch(url, { ...init, headers });
if (!response.ok) {
const payload = await response.json().catch(() => ({ detail: response.statusText }));
throw new Error(typeof payload.detail === 'string' ? payload.detail : JSON.stringify(payload.detail));