Commit 77fd4d9
authored
fix(web): workspace-scope dashboard endpoints + zero test coverage + hardening (#346)
The web dashboard (src/web/mod.rs, dashboard.html) had no test coverage
and three of its four data-fetching paths (list_entities, search, graph)
ignored workspace_hash entirely -- the same information-disclosure class
already fixed for context()/recall_when()/prepare in #338. In a federated
(multi-workspace) vault, the dashboard showed every workspace's memories,
including cross-workspace entity-graph edges, in one unfiltered view.
Fixes:
- db::list_entities/get_entity_graph gain workspace_hash: Option<&str>,
same exact-match scoping recall()/context() use since v1.2.0. None
preserves prior unscoped behavior (backward compatible).
- New db::count_entities(): a real COUNT(*) with the same filters, no
LIMIT/OFFSET -- fixes the dashboard's list_entities/search 'total'
field, which was actually 'items in this page' (items.len()), making
client-side pagination (has-more-pages?) impossible to implement
correctly. list_entities now reports a true total; search's total
remains page-count (documented why: FTS5 relevance ranking has no
cheap unlimited-count backing query without doubling recall cost).
- get_entity_graph drops edges whose target falls outside the scoped
node set, rather than emitting a dangling edge to a node the caller
never receives (which would also leak the target id's existence
across workspaces).
- web/mod.rs: list_entities/search/graph endpoints accept an optional
?workspace= query param, threaded through to the new db.rs params.
journal/get_recent_journal is NOT scoped -- the journal table has no
workspace_hash column; fixing that needs a schema migration and is
documented as a follow-up rather than folded into this pass.
- Injection audit: verified every dashboard.html render site that
interpolates untrusted entity content (key, category, layer,
body_json via JSON.stringify, timeline event fields) already goes
through the esc() HTML-escaping helper -- no missing site found, no
code change needed here, confirmed by inspection given the sibling
<memory-prep> injection fix in #337.
- Cosmetic: dashboard <title>/<h1> said 'Mneme', not updated in the
#341 Perseus Vault rebrand -- fixed.
- Hardening: vis-network@9.1.6 CDN <script> tag gains a real SRI
integrity hash (computed from the fetched artifact, sha384) +
crossorigin="anonymous", closing a supply-chain gap for any
deployment that binds --web-bind beyond 127.0.0.1.
Tests: 12 new tests in src/web/mod.rs (zero before this change) using
Axum's tower::ServiceExt::oneshot -- auth middleware (mirrors the
existing gRPC transport auth test pattern), list_entities/search/graph
workspace scoping (with and without ?workspace=), true-total pagination,
entity_detail 404, stats/journal smoke tests. Full suite: 167 passed,
0 failed, 2 ignored (was 155/0/2 before this change), stable across 3
repeated runs.
Manually verified end-to-end against the compiled binary's live --web
server: seeded two workspaces via real MCP mimir_remember calls,
confirmed unscoped /api/entities shows both (backward compat), scoped
?workspace= isolates correctly for entities/search/graph, cross-
workspace graph edges are dropped, dashboard title/h1/SRI hash render
as expected in the served HTML.
Version bump 2.12.0 -> 2.13.0.1 parent a788cc9 commit 77fd4d9
5 files changed
Lines changed: 519 additions & 18 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | | - | |
| 3 | + | |
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3347 | 3347 | | |
3348 | 3348 | | |
3349 | 3349 | | |
| 3350 | + | |
| 3351 | + | |
| 3352 | + | |
| 3353 | + | |
3350 | 3354 | | |
3351 | 3355 | | |
3352 | 3356 | | |
3353 | 3357 | | |
3354 | 3358 | | |
3355 | 3359 | | |
| 3360 | + | |
3356 | 3361 | | |
3357 | 3362 | | |
3358 | 3363 | | |
| |||
3378 | 3383 | | |
3379 | 3384 | | |
3380 | 3385 | | |
| 3386 | + | |
| 3387 | + | |
| 3388 | + | |
| 3389 | + | |
| 3390 | + | |
| 3391 | + | |
3381 | 3392 | | |
3382 | 3393 | | |
3383 | 3394 | | |
| |||
3401 | 3412 | | |
3402 | 3413 | | |
3403 | 3414 | | |
| 3415 | + | |
| 3416 | + | |
| 3417 | + | |
| 3418 | + | |
| 3419 | + | |
| 3420 | + | |
| 3421 | + | |
| 3422 | + | |
| 3423 | + | |
| 3424 | + | |
| 3425 | + | |
| 3426 | + | |
| 3427 | + | |
| 3428 | + | |
| 3429 | + | |
| 3430 | + | |
| 3431 | + | |
| 3432 | + | |
| 3433 | + | |
| 3434 | + | |
| 3435 | + | |
| 3436 | + | |
| 3437 | + | |
| 3438 | + | |
| 3439 | + | |
| 3440 | + | |
| 3441 | + | |
| 3442 | + | |
| 3443 | + | |
| 3444 | + | |
| 3445 | + | |
| 3446 | + | |
| 3447 | + | |
| 3448 | + | |
| 3449 | + | |
| 3450 | + | |
| 3451 | + | |
| 3452 | + | |
3404 | 3453 | | |
| 3454 | + | |
| 3455 | + | |
| 3456 | + | |
| 3457 | + | |
| 3458 | + | |
| 3459 | + | |
| 3460 | + | |
| 3461 | + | |
3405 | 3462 | | |
3406 | 3463 | | |
3407 | 3464 | | |
| |||
3434 | 3491 | | |
3435 | 3492 | | |
3436 | 3493 | | |
| 3494 | + | |
| 3495 | + | |
| 3496 | + | |
| 3497 | + | |
| 3498 | + | |
3437 | 3499 | | |
3438 | 3500 | | |
| 3501 | + | |
3439 | 3502 | | |
3440 | 3503 | | |
3441 | | - | |
3442 | | - | |
3443 | | - | |
| 3504 | + | |
| 3505 | + | |
| 3506 | + | |
| 3507 | + | |
| 3508 | + | |
| 3509 | + | |
| 3510 | + | |
| 3511 | + | |
| 3512 | + | |
| 3513 | + | |
| 3514 | + | |
| 3515 | + | |
3444 | 3516 | | |
3445 | 3517 | | |
3446 | 3518 | | |
3447 | 3519 | | |
3448 | 3520 | | |
3449 | 3521 | | |
3450 | | - | |
| 3522 | + | |
| 3523 | + | |
| 3524 | + | |
| 3525 | + | |
| 3526 | + | |
| 3527 | + | |
| 3528 | + | |
| 3529 | + | |
3451 | 3530 | | |
3452 | 3531 | | |
3453 | 3532 | | |
3454 | 3533 | | |
3455 | 3534 | | |
3456 | | - | |
3457 | | - | |
| 3535 | + | |
3458 | 3536 | | |
3459 | 3537 | | |
3460 | 3538 | | |
3461 | | - | |
3462 | | - | |
| 3539 | + | |
| 3540 | + | |
3463 | 3541 | | |
3464 | 3542 | | |
3465 | | - | |
| 3543 | + | |
3466 | 3544 | | |
3467 | 3545 | | |
3468 | 3546 | | |
3469 | 3547 | | |
3470 | 3548 | | |
3471 | 3549 | | |
3472 | 3550 | | |
| 3551 | + | |
| 3552 | + | |
| 3553 | + | |
| 3554 | + | |
| 3555 | + | |
| 3556 | + | |
| 3557 | + | |
3473 | 3558 | | |
3474 | 3559 | | |
3475 | 3560 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
6 | | - | |
| 6 | + | |
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
| |||
132 | 132 | | |
133 | 133 | | |
134 | 134 | | |
135 | | - | |
| 135 | + | |
136 | 136 | | |
137 | 137 | | |
138 | 138 | | |
| |||
167 | 167 | | |
168 | 168 | | |
169 | 169 | | |
170 | | - | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
171 | 173 | | |
172 | 174 | | |
173 | 175 | | |
| |||
0 commit comments