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:
1 parent
8b974e6626
commit
9145a23f18
32 files changed
+750
-58
No files matched your search
@@ -81,9 +81,10 @@ class Database:
|
||||
embedding_refs_json, layout_json, relations_json, trust_json,
|
||||
token_equivalent, metadata_json, holder_id, origin, scenario,
|
||||
event_time, event_time_end, event_time_precision, event_time_source,
|
||||
valid_from, valid_to, supersedes_json, visibility_json, retention_until
|
||||
valid_from, valid_to, supersedes_json, visibility_json, retention_until,
|
||||
quarantined
|
||||
)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
ON CONFLICT(atom_id) DO UPDATE SET
|
||||
modality=excluded.modality,
|
||||
source=excluded.source,
|
||||
@@ -107,7 +108,8 @@ class Database:
|
||||
valid_to=excluded.valid_to,
|
||||
supersedes_json=excluded.supersedes_json,
|
||||
visibility_json=excluded.visibility_json,
|
||||
retention_until=excluded.retention_until
|
||||
retention_until=excluded.retention_until,
|
||||
quarantined=excluded.quarantined
|
||||
""",
|
||||
[atom_params(atom) for atom in atoms],
|
||||
)
|
||||
@@ -118,6 +120,7 @@ class Database:
|
||||
)
|
||||
# New text changes which words are common, so every remembered count is void.
|
||||
connection.execute("DELETE FROM term_df")
|
||||
self._bump_revision(connection)
|
||||
|
||||
def list_atoms(self, limit: int | None = None) -> list[EvidenceAtom]:
|
||||
with self.connect() as connection:
|
||||
@@ -188,6 +191,7 @@ class Database:
|
||||
"WHERE valid_to IS NULL AND atom_id IN (SELECT value FROM json_each(?))",
|
||||
(closed_at.isoformat(), to_json(atom_ids)),
|
||||
)
|
||||
self._bump_revision(connection)
|
||||
return int(cursor.rowcount)
|
||||
|
||||
def delete_atoms(self, atom_ids: list[str]) -> int:
|
||||
@@ -201,6 +205,13 @@ class Database:
|
||||
"DELETE FROM atoms WHERE atom_id IN (SELECT value FROM json_each(?))", (to_json(atom_ids),)
|
||||
)
|
||||
connection.execute("DELETE FROM term_df")
|
||||
self._bump_revision(connection)
|
||||
return int(cursor.rowcount)
|
||||
|
||||
def delete_source(self, source_id: str) -> int:
|
||||
"""Erase where a memory came from, so a forget leaves no provenance row behind."""
|
||||
with self.connect() as connection:
|
||||
cursor = connection.execute("DELETE FROM sources WHERE source_id = ?", (source_id,))
|
||||
return int(cursor.rowcount)
|
||||
|
||||
def delete_edges_touching(self, atom_ids: list[str]) -> int:
|
||||
@@ -231,6 +242,17 @@ class Database:
|
||||
with self.connect() as connection:
|
||||
return int(connection.execute("SELECT COUNT(*) FROM atoms").fetchone()[0])
|
||||
|
||||
def revision(self) -> int:
|
||||
"""What a compiled context was compiled against; see store_meta."""
|
||||
with self.connect() as connection:
|
||||
row = connection.execute("SELECT value FROM store_meta WHERE key = 'revision'").fetchone()
|
||||
return int(row["value"]) if row is not None else 0
|
||||
|
||||
def _bump_revision(self, connection: sqlite3.Connection) -> None:
|
||||
"""A write changes what a compiled context may contain, so the semantic cache must notice."""
|
||||
connection.execute("INSERT OR IGNORE INTO store_meta(key, value) VALUES ('revision', '0')")
|
||||
connection.execute("UPDATE store_meta SET value = CAST(value AS INTEGER) + 1 WHERE key = 'revision'")
|
||||
|
||||
def token_equivalent_sum(self) -> int:
|
||||
with self.connect() as connection:
|
||||
value = connection.execute("SELECT COALESCE(SUM(token_equivalent), 0) FROM atoms").fetchone()[0]
|
||||
|
||||
Reference in new issue
Block a user