Two fixes discovered by real end-to-end smoke test against Aliyun docmind:
1. fileUrlObject must be a ReadStream, not a Buffer. The SDK serializes
Buffers as JSON {type:'Buffer',data:[...]} which the API can't read;
a Stream is uploaded as multipart form data. Switched readFile → createReadStream.
2. QueryDocParserStatus returns data.status (not top-level completed/status).
The markdown output URL is in data.outputFormatResult[].outputFileUrl,
not in a separate GetDocParserResult call. Rewrote polling to check
data.status === 'success', then download markdown from the OSS URL.
Also added image download: markdown contains  references;
the client now downloads those images and rewrites paths to local filenames.
Smoke test verified: prime_sieve.pdf → 15s → markdown with image refs downloaded.
AliyunDocmindClient is now production-ready given an AccessKey.
vite dev only proxied /api and /auth, so /admin/login hit the SPA root
layout, re-ran loadSession, got 401, and redirected back to /admin/login
with an ever-nesting returnTo. Proxy /admin/login to the backend (which
owns it before the SPA fallback) and guard redirectToLogin against
re-entering /admin/login.
Replace the only emoji-as-icon (the back-arrow on project detail) with
the Icon component (new arrow-left glyph).
Add scripts/dev-bootstrap.ts for seeding a local Silo (stub probes) so
npm run dev can start on a fresh dev DB.