The PDS's best-effort push to /internal/ingest-commit didn't
include the poster's handle. The AppView's indexer then stored
'\'' (empty) and the timeline UI fell back to '@did:plc:<snip>…'
synthetic identifiers — which is fine for Bluesky (PLC directory
resolves the rest), but local-PDS users have 'did🔑' DIDs that
no resolver can look up, so the synthetic handle stuck forever
and the profile endpoint could never resolve 'handle → did'.
Plumb the handle through:
- appview_push.rs: IngestCommitBody gains an optional 'handle'
field; push_create / push_follow_create take Option<&str>
- routes/helpers.rs: new 'lookup_handle(state, did)' helper that
hits the 'users' table (in practice always finds the row for an
authenticated route; logs a warning otherwise)
- routes/repo.rs (createRecord) and routes/feed.rs (feed.like.create):
resolve 'did → handle' from the users table before the spawned
ingest push, pass it through
The AppView-side companion commit stores the handle on the new
row and adds a Jetstream identity-event backfill, so by the
time this PR is merged timelines render real '@handle' again.
Three fixes for the integration test plan:
1. Layer order in tauri.conf.json: `body_limit_fallback` must
wrap `upload_blob_body_limit` so the JSON override is in
effect when the 413 fires. Swapped.
2. Type annotation on the `from_fn` middleware:
`.layer::<_, std::convert::Infallible>(...)`. The function
never errors, so the second type param is Infallible.
3. Register the standard `app.bsky.feed.like` and
`app.bsky.feed.repost` lexicons so the like/repost
endpoints (which create records of those collections) pass
the lex validator. We only ship what the PDS actually lets
users create server-side; anything else passes `validate: false`.
The 'unprocessable entity' style message and 'unknown lexicon'
errors that came up during manual testing are now gone.
Also dropped the stuck migration-2 row from `_sqlx_migrations`
on the dev DB so the new lex schemas apply.
- fetchBlob cache keyed by (did, cid), not just cid.
Security: future per-DID access control on getBlob would
otherwise leak the first responder's bytes to subsequent
viewers.
- EmbedImage: pass did to releaseBlob, release previous cid
on cid change (no leaked URLs).
- ComposeBox: releaseBlob called with both did and cid.
- pds-server: rename test
get_blob_after_upload_with_different_did ->
get_blob_returns_404_for_cross_did_cid_lookup. The
docstring was misleading — the test only verifies the
(did,cid) PK on the PDS row, not auth. The renamed name
matches what the test actually checks.
- vitest: update releaseBlob call sites to the new
(did, cid) signature.