Repository navigation
A fact's evidence is read only inside its own base - #1261
Merged
WaylandYang merged 1 commit intoOct 16, 2026
Merged
Conversation
…base no longer reads another base's quotes Signed-off-by: Bogdan Szabo <[email protected]>
WaylandYang
approved these changes
Oct 16, 2026
WaylandYang
left a comment
Contributor
There was a problem hiding this comment.
Thank you, this is the right fix in the right place. fact_evidence now takes the base and answers NotFound for a fact outside it, the same rule entity_detail follows, and passing the base through premise_steps and steps_for means proofs can't be used to read another base's quotes either. Checking only the fact is enough because the fact_evidence_stays_inside_its_kb trigger already keeps a fact's evidence in the fact's base. The store test fails without the check and runs in CI against Postgres. This has to land before #1263, which opens this route to kb_ids-limited tokens. Merging.
This was referenced Oct 16, 2026
gedaiu
added a commit
to re-cinq/lore
that referenced
this pull request
Oct 16, 2026
…y external_id) (#2789) Bumps Utopia from `re.6` to `0.1.0-re.7` (digest `sha256:9fa04033…`). It puts the reads Lore's Utopia side needs on the running Utopia, so the trace reader can be built and measured against real data (dual-write experiment, #2787) while upstream reviews them. `re.7` = `re.6` + current upstream `dev` (which now has deeplethe/utopia#1261, the cross-base evidence fix, and #1270, members of a class lacking a relation) + our open PRs: - #1263, #1264, #1265, #1266: a personal token reads the graph of the bases it reaches (entities, history, evidence, overview, neighbourhood, ontology, instances, extractions, export; export audited with the token) - #1268: a push that names its `external_id` keeps that id's document; content clashes answer `duplicate`; tombstone-then-push renames - #1272: reads return a statement's role-word qualifiers (e.g. a test's line range) - #1273: search takes a token and returns scores, ranks, source, `external_id` and pages - #1274: a write token creates `api` sources - #1280: read a pushed document back by its `external_id` Left out on purpose: the list-by-`external_id` change (held until #1280 merges), because it adds a migration whose number upstream has not assigned yet. **No new migration in `re.7`** (still 0113). Checked before pushing: on the merged `re-dev` (`8c477cd`), `cargo fmt --check`, `clippy -D warnings` and `cargo test --workspace` on a freshly migrated database (1612 passed, 6 ignored, 0 failed). The image booted on a fresh database: health 200, migrations at 113, and a bogus token on the new entities route answers 401 (route present, token checked). After merge: `terraform apply -target='kubernetes_deployment_v1.utopia[0]'` from main. Generated with [Claude Code](https://claude.com/claude-code)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1260.
What happened
graph::fact_evidence(pool, fact_id)loaded a fact's evidence by id alone. The route checked the base in the path and nothing else, so a role in base A was enough to read the quotes of a fact in base B through/kbs/A/facts/<B's fact>/evidence. Proof steps (reasoning::steps_for) called it the same way.What changed
graph::fact_evidence(pool, kb_id, fact_id)first checks that the fact is inkb_idand answersNotFoundotherwise, asentity_detaildoes for an entity outside its base. A fact of the right base with no evidence still returns an empty list. The route passes the base from its path;proofandblocked_proofalready had the base and now hand it down throughpremise_stepstosteps_for. The cost is one primary-key lookup per evidence read.Tests
evidence_stays_inside_its_base(utopia-store): evidence of a fact in base B, asked from A, isNotFound; asked from B it returns the row. It fails without the check.Run in
rust:1-slim-bookwormagainst Postgres withUTOPIA_TEST_REQUIRE_DB=1:cargo fmt --all --checkandcargo clippy --workspace --all-targets -- -D warningsare clean;cargo test -p utopia-store --test store evidence9 passed,proof3 passed,blocked1 passed;cargo test -p utopia-server evidence12 passed.