Commit Graph
38 Commits
Author SHA1 Message Date
VykosandClaude affaee1e66 fix(discovery): cache a successful but empty Tailscale lookup (#6228)
The host cache was gated on the list being non-empty, so "queried fine, no
eligible peers" looked exactly like a cold cache and every caller paid for
another `tailscale status --json` — a subprocess with a 5s timeout.

Gate on the timestamp instead. Failures still leave the timestamp unset, so a
missing binary, a non-zero exit or unparseable output stays retryable rather
than being cached for the full TTL.

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-02 12:05:01 +02:00
VykosandClaude Opus 4.8 ab2f412b27 fix(endpoint): scope secondary endpoint lookups by owner
* Scope secondary endpoint lookups by owner

* Reject unregistered image endpoint URLs for non-admins

* Adjust owner-scope tests for rebased routes

* Allow non-admins to compare endpoints they own

The compare owner-scope guard called _reject_raw_endpoint_url_for_non_admin
with endpoint_id=None, so it rejected every signed-in non-admin
/api/compare/start request — even for endpoints the caller owns — because
compare resolves endpoints by URL and carries no endpoint_id. That locked
non-admins out of compare entirely.

Resolve the owned ModelEndpoint first and pass its id, so a registered
endpoint the caller owns is allowed while only truly raw, unregistered URLs
are rejected (mirrors the gallery inpaint/harmonize checks in this PR).
Replace the source-only reject test with deterministic reject + allow
regressions that no longer depend on the dev DB contents.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Bind compare sessions to the resolved owner-scoped endpoint

/api/compare/start created the [CMP] helper sessions with the raw
caller-supplied endpoint URL and only used the owner-scoped lookup to
decide whether to copy an API key. That stopped key borrowing but still
let a non-admin inject an arbitrary raw endpoint URL into the compare
session path.

Now, when the supplied URL resolves to a registered endpoint visible to
the caller, the session binds to that row's own normalized base URL
(build_chat_url(normalize_base(ep.base_url))) plus its headers — the same
registered-endpoint shape session_routes uses. The raw URL survives only
when ep is None, which non-admins already hit a 403 on, leaving raw URLs
reachable solely for admins / single-user mode with no borrowed key.

Adds compare-specific behavior tests: another user's private endpoint is
rejected (nothing created), the session binds to the stored URL rather
than the raw input, and an admin raw URL is allowed but carries no
inherited key.

Addresses the review on #1511.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Validate both compare endpoints before creating any session

start_comparison resolved + created each [CMP] session inside one loop,
so a request pairing a valid owned endpoint A with an unregistered raw
endpoint B raised 403 only after A's session was already created — and
its Authorization header copied in. The rejected request left a partial
compare session with that header behind.

Split the flow into two phases: phase 1 resolves and owner-validates
both endpoints (running the raw-URL reject helper) and stashes the
session URL + headers; phase 2 creates the two sessions only once both
passed. A 403 on either endpoint now aborts with nothing created and no
header copied.

Adds a regression test: owned endpoint A + unregistered/raw endpoint B
-> 403 with no sessions created.

Addresses the follow-up review on #1511.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Resolve compare credentials by endpoint id, not URL alone

Two endpoints visible to a caller can share a base_url but hold different
api_keys. _owned_endpoint_by_url returned whichever row sorted first, so
/api/compare/start could copy the wrong key into the [CMP] session.

Add _owned_endpoint_by_id (same owner scoping) and optional endpoint_a_id/
endpoint_b_id form fields. The id pins the exact registered endpoint; URL
resolution remains only for legacy/admin raw-URL callers. An id the caller
can't see 404s instead of falling back to a same-URL row.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Loosen research-routes owner-scope assertion to the stable substring

The rebased _resolve_research_endpoint generalized its owner derivation to
honor an explicit owner arg first (owner = owner or getattr(sess, ...)), so
the exact-line assertion broke CI. Assert the stable session-derivation
substring instead of the full line.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 11:51:55 +01:00
Vykos ca22afb10c Scope auxiliary LLM endpoints by owner (#2996)
* fix(auth): scope auxiliary llm endpoints by owner

* fix(auth): scope auxiliary llm fallbacks by owner
2026-06-07 14:47:44 +02:00
Vykos 1fcb3f9283 fix(rag): forward owner through manager wrapper (#2991) 2026-06-07 12:56:57 +02:00
Vykos eade393332 fix(personal): require document privilege for rag upload (#2990) 2026-06-07 12:56:53 +02:00
Vykos 09cade728c fix(auth): gate api tokens from user routes (#2992) 2026-06-07 12:55:01 +02:00
Vykos be933a1202 Harden note reminder dispatch ownership (#2999) 2026-06-07 12:52:27 +02:00
Vykos f109c1e7d6 Scope gallery image endpoints by owner (#3001) 2026-06-07 12:51:21 +02:00
Vykos cae10e623f Tighten manage notes owner checks (#3002) 2026-06-07 12:50:10 +02:00
Vykos ac8e6b9e06 Harden gallery album assignment scope (#3004) 2026-06-07 12:49:03 +02:00
Vykos de33fba0e7 Scope document session links by owner (#3005) 2026-06-07 12:47:20 +02:00
Vykos 93b614a649 Enforce task chain owner scope (#3006) 2026-06-07 12:43:43 +02:00
Vykos 88043ef8d1 Scope model helper endpoint resolution (#3007) 2026-06-07 12:40:23 +02:00
Vykos e876f8f5fa Scope vision model resolution by owner (#3009) 2026-06-07 12:39:02 +02:00
Vykos ec413bbcb5 Harden DAV outbound URL validation (#2819) 2026-06-05 13:22:21 +02:00
Vykos 92bb41881c Constrain research handler JSON paths (#2846) 2026-06-05 13:20:02 +02:00
Vykos 91ccb9fabf Constrain signature uploads to PNG data (#2844) 2026-06-05 13:17:43 +02:00
Vykos 32f6566050 Constrain upload paths to upload root (#2825) 2026-06-05 13:15:23 +02:00
Vykos 15540ae4ea Constrain embedding model cache paths (#2849) 2026-06-05 10:46:48 +02:00
Vykos 0f1dedb7cb Constrain generated-image paths to image root (#2837) 2026-06-05 10:33:47 +02:00
Vykos daa52b35db Harden emoji SVG proxy responses (#2842) 2026-06-05 10:31:58 +02:00
Vykos 484e2dc9d9 Constrain gallery filenames to image root (#2828) 2026-06-05 10:29:11 +02:00
Vykos 88b230e8ae Sanitize calendar export filenames (#2840) 2026-06-05 10:18:09 +02:00
Vykos cf146b396d Isolate HTML popup openers (#2501) 2026-06-04 20:52:41 +02:00
Vykos 978d5a39bc Guard image and QR DOM attributes (#2500) 2026-06-04 20:51:23 +02:00
Vykos 8ee14ab2aa Harden chat streaming DOM sinks (#2498) 2026-06-04 20:49:37 +02:00
Vykos d10b1c14fd Harden email HTML URL sanitization (#2496) 2026-06-04 20:47:47 +02:00
Vykos fad9b9c701 Harden markdown raw HTML sanitization (#2497) 2026-06-04 20:46:10 +02:00
Vykos 266240f3e1 Whitelist research source links (#2499) 2026-06-04 20:41:35 +02:00
Vykos ff771033f2 fix(ai): scope tool model resolution by owner
* Stabilize full test collection

* Scope AI tool model resolution by owner
2026-06-04 00:37:28 +01:00
Vykos ea2f1f45c6 fix(search): align content URL guards
* Stabilize full test collection

* Align search content URL guards
2026-06-04 00:34:06 +01:00
Vykos 1ad8687bfd fix(uploads): bound direct upload reads
* Stabilize full test collection

* Add bounded reads for direct uploads
2026-06-04 00:32:50 +01:00
Vykos 0819741161 test: stabilize full test collection 2026-06-04 00:27:29 +01:00
Vykos 53ee79cdb6 Harden CalDAV credentials and URLs (#1310) 2026-06-03 02:50:02 +09:00
Vykos 94d54b5872 Harden session endpoint owner scope (#1308) 2026-06-03 02:40:22 +09:00
Vykos 2a8329aa44 Scope skills usage by owner (#1312) 2026-06-03 02:27:43 +09:00
Vykos 4007296c9f Scope email account workflows by owner (#1309) 2026-06-03 02:21:02 +09:00
Vykos d921ff9871 Keep Bitwarden unlock password off argv (#1311) 2026-06-03 02:13:51 +09:00