Crate modernization #
Target #
Crate is an ATProto-native file application. A trusted, permissioned PDS owns records, blobs, and access control. Rust defines the storage models and HTTP contract. The server derives OpenAPI from its actual typed handlers; TypeScript and Swift consume generated clients. Astro owns the web pages and a cohesive Preact island owns the interactive file browser. The migration must preserve the original page layout and visual styling, not redesign the application.
The browser may use a same-origin OAuth backend. Its tokens and sessions are private operational state, not user-profile records. The backend must not become the only source of file semantics: published Lexicons describe the stored data. There is no silent fallback from permissioned storage to public repositories.
Work ownership #
- Protocol:
packages/protocol, rootlexicons, generated TypeScript/Swift clients, and deterministic contract generation. - Server:
packages/server, Rust OAuth/PDS access, file operations, responses, and server container. - Web:
packages/web, Astro/Preact, client state, interactions, and web container. - Integration: root tooling, deployment, shared documentation, and verification.
Work is developed in separate Jujutsu workspaces. Commits represent one concept;
integration preserves their descriptions and orders prerequisites before callers.
Generated files are committed with their corresponding contract change.
Authored files stay below 400 lines; tests and machine-generated Lexicon, OpenAPI,
TypeScript, and Swift output are exempt. Generators own their output formatting.
Oxfmt formats supported files; Prettier's Astro plugin handles only .astro.
TypeScript 7 checks the root project-reference graph. Astro's language-server
checker uses an isolated legacy TypeScript API dependency for .astro files;
it does not select the application compiler or require built package types.
Acceptance checklist #
An unchecked item is incomplete, not waived. Check items only with evidence.
Protocol and server #
Web #
Tooling, deployment, and verification #
Verified on 2026-09-06: Tailwind restoration #
Tailwind CSS 4.3.3 and its Vite plugin replace the handwritten component styling. Eight page/component stylesheets were removed; the shared CSS-first theme keeps the existing palette, typography, and native control defaults. There is no PostCSS configuration or Autoprefixer dependency. Vite retains its own transitive PostCSS dependency, unrelated to the Tailwind integration.
The full repository check passes: 81 JavaScript, 41 Rust, and four Swift tests,
plus formatting, lint, root-reference typechecking, file sizes, and contract drift.
The production web build passes. Eleven browser checks pass in both development
and production previews, including dark controls and portal popover centering.
All 24 captured desktop/mobile, light/dark views are pixel-identical to the
pre-Tailwind revision 3ba1e2e8; 496 measured elements retain their geometry and
painted colors. Comparisons use synthetic accounts and do not access a real PDS.
Live sign-in and namespace setup remain deferred under the boundaries below.
Verified on 2026-09-05 #
bun install --frozen-lockfile and bun run check pass from the main checkout:
81 JavaScript tests, 41 Rust tests, deterministic Lexicon/OpenAPI/SDK drift checks,
and four Swift tests. TypeScript 7 checks source-only root references; Astro reports
zero errors and warnings, with two dependency deprecation hints in query tests.
The Swift generator emits upstream unused-public-import warnings in generated files.
Both production builds pass. Nine Chromium tests cover hydration, protected routes,
typed proxy errors, retryable login failures, original layout geometry, selection,
search, grid/list switching, inspector controls, and synthetic-account logout.
The opt-in live PDS lifecycle remains skipped, not counted as a passing test.
Both listeners bind 127.0.0.1; the proxied health endpoint responds successfully.
The running server's OpenAPI is semantically identical to the generated contract.
Bacon restarted successfully after a source change. The largest authored file is
254 lines. The linear implementation series contains 127 commits since the
login-only baseline; each changes no more than six files. This evidence update
follows them as a separate documentation commit.
Original-revision screenshots were compared with the restored UI using synthetic accounts and files at desktop and mobile widths, including dark mode. The original shell, login card, landing artwork, file toolbar/table/grid/inspector, and settings sidebar are restored. Real ATProto identity and controls remain; placeholder security/billing pages, clipped filenames, broken selection, and mobile overflow were not reinstated. Layout assertions run in the regular browser suite.
Both container images build successfully. All nine non-live browser checks pass against the final restored web image and the updated OAuth server image on an isolated loopback port. No real PDS requests are made by that suite. Earlier container lifecycle checks also verified that the API exposes the generated OpenAPI contract, runs as UID 10001, and creates its data directory with mode 700 and SQLite database with mode 600. The volume survives server replacement. Nginx refreshes a changed backend IP without restarting, and the server's default stop signal reaches its graceful handler (observed clean exit in 130 ms).
Host disk exhaustion blocked checkout updates while Podman reported overlay/writeback errors. Only task-owned rebuildable caches and a failed build container were removed; flushing the VM's filesystem cleared the stale error state without resetting or restarting the VM. The Rust image build now discards compiler output before committing its build layer. Nested environment files and browser artifacts are excluded from image contexts.
The user's live sign-in attempt reached the Spaces alpha provider, which rejected
consent with invalid_scope: it could not retrieve Space declarations. Public
authoritative DNS had no TXT record at _lexicon.crate.network. The local generated
declaration also lacked the alpha validator's required name and key metadata;
the Rust generator now includes both, with a regression test. Callback handling
now distinguishes bound provider rejection from malformed requests, consumes only
the matching pending login, and never reflects arbitrary provider descriptions.
All four generated documents and their publication envelopes also passed the
unmodified official alpha validator pinned to commit
7cefaccc5307db53d92cda364ff582a2efec0027; negative controls missing name or key
were rejected. This validates local syntax, not remote discovery.
The interrupted browser run performed no file operations. Its diagnostic artifact was removed. Manual sign-in observation now reports provider rejection promptly without leaving a locator that logs callback URLs on cancellation. Live mode also disables Playwright's separate failure-page snapshot capture; an intentionally failing synthetic-provider test verified that neither its page contents nor its callback-state marker appeared in the diagnostic artifact.
Approved tooling exception: Astro 7.3.1 retains esbuild 0.28.2 internally. The user approved this framework-only dependency on 2026-09-05. Crate has no direct esbuild dependency or build scripts using it.
Remaining acceptance boundaries:
- Public declaration discovery, successful OAuth, and live file interoperability
remain unverified. The user confirmed control of
crate.networkand explicitly deferred DNS changes. Schema publication is also deferred; no PDS records or DNS entries were published. A later authorized setup requires a schema-publisher DID and publicly resolvable generated Lexicons before another user-driven sign-in attempt can complete.
Astro auto-backgrounds inside detected coding-agent environments. For foreground
verification here, env -u CODEX_THREAD_ID bun run dev disables only that detection;
ordinary shells use the unchanged bun run dev command.
Verification boundaries #
Do not publish Lexicons, change DNS, deploy services, migrate real accounts, or modify existing PDS files implicitly. Use isolated test data and ask the user to sign in for authenticated browser verification. An unsupported PDS or SDK is a reported capability gap, not permission to weaken the storage model.