Commit Graph
5 Commits
Author SHA1 Message Date
mlsmayconandClaude Fable 5.1 0df2eb7b25 [management] Refuse pins onto a host another account's gateway already claims
A host can be claimed by a pin as well as by a proxy row, and the proxy-row
check cannot see that. Another account's labeled pin beneath a host makes
the host its cluster, so a self-addressed endpoint on it would never be
served; another account's self-addressed endpoint on a host makes the proxy
declaring it theirs, so a label beneath it would never be served either.
Both bootstrap paths now refuse those shapes before the insert.

Neither question touches the shared-cluster shape: labeled pins under one
cluster are asked about in neither direction, so any number of accounts
still pin beneath a shared cluster. Two self-addressed endpoints on one
hostname stay the domain unique index's conflict to refuse.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Sa3DsBDP3VciAi4PPG17L6
2026-09-12 17:02:05 +00:00
mlsmayconandClaude Fable 5.1 09cc91886f [management] Refuse to pin an agent network gateway onto another account's host
An agent network bootstrap stores the cluster it pins to as proxy_address,
and that value selects the proxy that serves the endpoint. An account-scoped
proxy only ever receives its own account's mappings, so a pin onto a host
another account's proxy declares can never be served — and the endpoint it
assigns is immutable, so the account is left with a dead gateway until it
deletes its settings and starts over. Nothing refused that pin: the domain
unique index arbitrates between pins only, and knows nothing about proxies.

Both bootstrap paths now ask, before the insert, whether a proxy owned by a
different account declares the host. Shared proxies are not foreign — a
shared cluster is what most accounts pin to, and any number of them may —
and a host no proxy has declared stays pinnable, since claiming the address
before the proxy's first connection is the documented order. Ownership is
decided on the proxy rows, not on heartbeat freshness, and on the folded
spelling, since proxies declare their address as the operator typed it.

Registration is deliberately not changed: refusing a proxy because another
account pinned its host would let a pin lock a tenant's proxy out once the
stale-proxy reaper has dropped its rows. Left as is, the worst a race or a
reaping window can produce is a dead pin for the account that made it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Sa3DsBDP3VciAi4PPG17L6
2026-09-12 16:50:49 +00:00
Maycon Santos 6aaeed744e [management] Check a provider's url and credential before saving it (#7301)
A bad upstream or key saved cleanly and surfaced minutes later as a failed
request or an empty model picker, with nothing pointing back at the record.

CreateProvider now spends the credential once against the vendor's model
listing. UpdateProvider does the same when the upstream, the key, the catalog
provider or the skip-TLS flag changed — only then, so renames and price edits
neither wait on a vendor nor fail because one is down. Both run before the store
write, so a rejected rotation leaves the working key where it was.

What cannot be checked still saves: no listing endpoint, no derivable Bedrock
control-plane host, a private upstream, a record skipping TLS verification.
Everything else blocks, outages included — 5xx, 429 and timeouts leave the
record unverified just as a refusal does. Refusals return 422 and carry no
status code or echoed URL.

Discovery now reads as a partial edit, so a retyped URL can be listed against
without also rotating the credential. Entries with their own listing host
(Bedrock) get their configured upstream resolved separately, since a successful
listing said nothing about it.
2026-09-02 21:46:47 +02:00
dmitri-netbird a144e8c144 [client, management] switch to go.uber.org/mock (#7253)
* switch to go.uber.org/mock/gomock

Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>

* updated go:generate commands + regenerated mocks

Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>

* update go:generate mockgen commands

Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>

* removed duplicate import

Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>

* fix go:generate

Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>

---------

Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>
2026-08-20 11:53:19 +02:00
Brad Ison ebfdf7d7b8 [management] Rework Agent Network endpoint identity and settings bootstrap (#7085)
Store the per-account gateway endpoint as {domain, proxy_address} with a
global unique index on the full hostname; dedicated = (domain ==
proxy_address). Bootstrap becomes an explicit POST carrying exactly one
of proxy_address (server allocates an adjective-noun label beneath it)
or endpoint (claimed verbatim, address-first); provider create loses its
bootstrap side effect. PUT is a full replace with every field required —
the immutable identity fields must be echoed unchanged and a mismatch is
rejected with 422. A guarded DELETE releases the endpoint: refused with
412 while providers exist or a proxy is actively serving the endpoint
hostname (matched case-insensitively); re-creating bootstraps fresh. A
self-addressed pin excludes its address from the account's cluster allow
list, and the live mapping update path now addresses the serving proxy
from the synthesized service. Existing rows are migrated on all three
store engines.
2026-08-10 19:06:55 +02:00