Add UploadAttachment, a unary RPC that accepts a file in bounded chunks
and streams it to a temp file instead of holding the whole blob in one
request body and in memory. A call carrying a spec starts an upload and
returns an opaque upload_id; later calls carry that id with
write_offset,
data, and finish_write, following the Cloud Storage WriteObject shape.
Retrying the last chunk after a lost response is idempotent, uploads are
bound to their owner, and they expire after 30 minutes of inactivity.
CreateAttachment and the chunked finalize now share one processing
pipeline for motion-photo detection, EXIF stripping, and storage. The
motion-photo detector works over an io.ReaderAt so large JPEGs are never
loaded whole, and the request body cap is a single per-procedure lookup.
The web editor uploads through the new RPC in 2 MiB chunks with bounded
concurrency under the server's per-user limit.
The gnostic OpenAPI generator hardcodes `format: enum`, `format: bytes`,
and `format: field-mask` on string properties. These are OpenAPI-only
markers; MCP clients treat tool schemas as JSON Schema 2020-12 and warn
or fail on them (zod-based parsers log "unknown format" for every tool
on every load, ajv strict mode rejects the definitions).
Normalize schemas as they leave the resolver and when parameter schemas
are cloned: drop `format: enum` (the `enum` keyword is already present),
rewrite `format: bytes` to `contentEncoding: base64`, and drop
`format: field-mask`. The generated openapi.yaml is unchanged.
A catalog test now walks every curated tool's input and output schema
and fails on any format outside the registered allowlist.
Fixes#6262
- Generate UUID v4 values in the client with validated custom UID
support.\n- Show immutable UIDs where Space titles need
disambiguation.\n- Standardize Space surfaces on the Lucide Astroid
icon.
- Share one visible-tab connection across a browser and harden retries.\n- Preframe hub events, disconnect slow clients, and reset idle heartbeats.\n- Add cross-tab, concurrency, race, and fanout benchmark coverage.
Exercise real server startup on backend test runs and gate releases on fresh-install, previous-stable upgrade, and entrypoint smoke checks across supported databases.
- Resolve Gateway procedures from matched HTTP bindings before authorization.\n- Disable anonymous RSS on private instances.\n- Limit share-token access to the shared memo and its attachments.
Rename GetMemoByShare to GetSharedMemo and move REST resolution to /api/v1/shares/{share_token}/memo.\n\nBREAKING CHANGE: remove GET /api/v1/shares/{share_id} and the GetMemoByShare RPC.
Use the original UID format consistently across API, username, and store validation so UUID-based callers continue to work. Regenerate API documentation and add regression coverage for UUID memo IDs.
- Cache fingerprinted frontend assets for one month.
- Load media, rich renderers, dialogs, and editors only when needed.
- Simplify seeded demo content and cover deferred-loading behavior.
Validate new user-provided IDs using the AIP-122 format while retaining legacy UID compatibility. Correct resource annotations and canonical names returned by user stats.
Settings drops the all-in-one bordered card for a de-carded layout in
the property-rail design language: a sticky table-of-contents rail at
md+ (Settings wordmark, uppercase group labels, quiet anchor rows) and
a horizontally swipeable chip strip below md, replacing the mobile
section dropdown. Nav items are real anchors with aria-current, and
switching sections scrolls back to the top.
Access Tokens becomes a first-class section with an explainer panel:
what a PAT is and a copyable curl example (real instance origin,
memos_pat_ prefix) beside token-safety guidelines in a two-column band,
with a Learn more docs link and the tokens table beneath. Successful
PAT authentication now records the token's lastUsedAt asynchronously
inside resolveBearer, with a clone-before-mutate cache guard and
monotonic writes in the store, surfaced in a Last used column.
Also localizes the create dialog's 90 Days label, lets the My Account
row wrap instead of clipping on narrow screens, and drops the dead
select-section key from all locales.
- Load IdPs and supported instance-setting groups as runtime overlays from /etc/secrets.
- Reject API mutations of deployment-managed resources and serialize authentication safety checks across database drivers.
- Preserve upgrade compatibility, demo SSO policy, stable IdP ordering, and driver-specific transaction retries.
Rework ListUsers to match the ListMemos pagination contract: opaque
PageToken, normalizePageSize, DB-level limit+1 look-ahead, and a
next_page_token. Adds Offset to store.FindUser with an OFFSET clause in
all three dialects, and an `id DESC` ORDER BY tiebreaker so offset pages
stay stable when created_ts ties.
Also align pagination across list endpoints:
- Bump DefaultPageSize 10 -> 50 to match the documented default; use
normalizePageSize in ListAttachments.
- Remove the never-implemented total_size field from all six list
responses (ListUsers, ListAttachments, ListMemoComments,
ListMemoReactions, ListUserSettings, ListPersonalAccessTokens) and
regenerate.
- useListUsers now pages through next_page_token so the admin members
view still loads every user past the default page size.
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.
Add AttachmentService_CreateAttachment to the curated MCP allowlist so
agents can upload files (inline base64 content) alongside memos, closing
the gap where the MCP server could list/get/delete attachments but not
create them.
Closes#6057