Run the instance in private mode when instance_url is not configured: the API rejects anonymous requests except the auth-bootstrap set (sign-in, token refresh, instance profile/settings, SSO providers, share-link access) plus first-run user creation, and the web UI redirects anonymous visitors to /auth instead of /explore. Setting instance_url keeps the current public behavior. Access tokens and personal access tokens are never gated.
Enforcement lives in a shared Authorizer used by both the Connect interceptor and the gRPC-gateway middleware; the file server applies the same rule to public-memo attachments and avatars. Also merges the duplicated Authenticate/AuthenticateToUser token dispatch behind resolveBearer, dedups the AuthContext unauthenticated state, extracts the redirect decision into a pure shouldGatePrivateInstance helper, and prints the access mode at startup.
Generate webhook signing secrets server-side and let users reveal them on
demand, replacing the create-dialog secret controls that surfaced internal
mask state (Status / Generate & Copy / Clear / Pending) to users.
- Add owner-gated GetUserWebhookSigningSecret RPC — the only path that
returns the secret; list/create/update responses still omit it.
- Generate the secret server-side on create (webhook.GenerateSigningSecret),
so validity no longer depends on the client.
- Rename UserWebhook.has_signing_secret -> signing_secret_set for parity
with the existing api_key_set field.
- Create dialog drops the secret section to a one-line note; the generated
secret is shown once right after create and revealable from Edit later.
Adds an opt-in toggle to skip TLS certificate verification when connecting
to the S3 endpoint, for self-hosted S3-compatible backends (e.g. rustfs,
MinIO) that use self-signed certificates. Exposed in both the store/API
protos and the storage settings UI, mirroring the existing use_path_style
toggle. When enabled, the AWS client uses an HTTP transport with
InsecureSkipVerify; default behavior is unchanged.
This governs backend-initiated S3 calls (uploads, deletes, thumbnails, and
image/document streaming). Video/audio playback redirects the browser to a
presigned URL, so that path still requires the browser to trust the cert.
Closes#6039
Replace the custom now() function with an idiomatic `now` timestamp variable (host-injected, frozen once per compile) and retype created_ts/updated_ts/create_time to CEL timestamp. Filters now use standard timestamp/duration arithmetic, e.g. `created_ts >= now - duration("24h")` and `timestamp("2025-01-01T00:00:00Z")`.
Add standard CEL surface that compiles to SQL across SQLite/MySQL/Postgres: timestamp accessors (getFullYear/getMonth/getDate/getDayOfWeek/..., with 0-based month and weekday normalized), ext.Sets() (sets.contains/intersects/equivalent over tags), tags.exists_one(), size() on string fields, and division/modulo folding. A frozen clock is injectable for deterministic tests.
BREAKING CHANGE: now() is removed (use the `now` variable) and time fields are timestamps, so bare-epoch comparisons need timestamp(<epoch>). Existing saved shortcuts using the old syntax must be updated.
Let users write three more CEL constructs in the filter field, each compiled to
SQL across SQLite/MySQL/Postgres:
- Scalar startsWith()/endsWith() on content/filename/mime_type (case-insensitive)
- matches() regex: PG ~, MySQL/SQLite REGEXP (Go-backed SQLite fn), validated at
compile time via cel.ValidateRegexLiterals()
- all() comprehension over tags via per-element subqueries, non-empty required
Also: contains() now escapes LIKE metacharacters (%, _, \); cross-dialect render
tests plus behavioral tests; cel-go bumped to v0.28.1; new operators surfaced in
the frontend shortcut guide.
Follow-up to #6013. The signing path silently fell back to using the raw
secret string as the HMAC key when a whsec_-prefixed secret had invalid
base64, producing signatures no receiver could verify with no server-side
signal.
- Extract resolveSigningKey helper that errors on invalid whsec_ base64
- Post returns that error (logged by the async dispatcher); ValidateSigningSecret
rejects it at write time so a bad secret is never stored
- Fix stale comment referencing a nonexistent Authorization header
- Add Go tests: key derivation, secret validation, end-to-end signature
round-trip, and the invariant that the secret never leaks into API responses