Files
nvrl 0245402ead typst: a block of it in markdown is typeset on the server
A ```typst (or ```typ) block is compiled by the typst crate into SVG and
shown as an image where it stands, so math, tables and figures can be
written in typst beside the markdown around them. It shows its source while
it is set, and the error typst gives, with the block's line, when it cannot
be.

Each block is a document of its own: its source is the only file in its
world and the fonts are typst-assets', inside the binary, so nothing is read
from disk or fetched — packages and images are refused. The page fits what
is on it, is transparent, and carries the theme's text colour. Answers are
cached by source, two blocks are laid out at a time off the async threads,
and comemo's memo is evicted after each compile.

A share page asks POST /api/share/{token}/typst, which takes the reader's
cookie and typesets only a block the shared document holds.

typst brings a palette crate whose AsRef impls on arrays made four
`kek.as_ref().into()` in the vault ambiguous; they deref instead.
2026-10-21 15:41:45 +02:00

98 lines
3.9 KiB
TOML

[package]
name = "narl-workspace"
version = "0.1.0"
edition = "2021"
# The Proton crates set the floor.
rust-version = "1.96"
description = "A private, terminal-themed workspace for the browser: diary, notes, boards and files"
[dependencies]
axum = { version = "0.8", features = ["multipart", "macros"] }
tokio = { version = "1", features = ["rt-multi-thread", "macros", "signal", "fs", "io-util"] }
tower = "0.5"
tokio-util = { version = "0.7", features = ["io"] }
tower-http = { version = "0.6", features = ["trace", "compression-gzip", "limit", "set-header"] }
sqlx = { version = "0.8", default-features = false, features = ["runtime-tokio", "sqlite", "migrate", "macros"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
dotenvy = "0.15"
uuid = { version = "1", features = ["v4"] }
rand = "0.8"
hmac = "0.12"
sha2 = "0.10"
base64 = "0.22"
subtle = "2"
mime_guess = "2"
rust-embed = { version = "8", features = ["interpolate-folder-path"] }
regex = "1"
anyhow = "1"
zip = { version = "2", default-features = false, features = ["deflate"] }
tempfile = "3.27.0"
# Only for `--features keyring`, on a host that has a Secret Service; the
# container deployment has no session bus and falls back to the session file.
keyring = { version = "3", features = ["sync-secret-service", "crypto-rust"], optional = true }
# Mail. rustls rather than native-tls: the container has no OpenSSL, and the
# Proton client already pulls rustls in.
lettre = { version = "0.11", default-features = false, features = ["smtp-transport", "pool", "builder", "hostname", "tokio1-rustls-tls"] }
# "did I write today?" and "is this due today?" are local-day questions, and DST
# rules out doing them with a fixed offset.
chrono = { version = "0.4", default-features = false, features = ["clock", "std"] }
chrono-tz = "0.10"
# The vault: files encrypted at rest under a key only a password unlocks.
# AES-256-GCM in the STREAM construction, so a file of any size is sealed and
# opened a chunk at a time; Argon2id between the password and the key.
aes-gcm = { version = "0.10", features = ["stream"] }
argon2 = "0.5"
zeroize = { version = "1", features = ["serde"] }
futures-util = { version = "0.3", default-features = false, features = ["std"] }
proton-drive-rs = "0.9.2"
proton-sdk = "0.9.2"
rpassword = "7"
hex = "0.4"
# SFTP mount: spaces and folders as a filesystem, authenticated by pubkey
# instead of the cookie session. `ring` rather than the default `aws-lc-rs`
# backend, because rustls (via lettre) already pulls `ring` in.
russh = { version = "0.63", default-features = false, features = ["ring", "rsa"] }
russh-sftp = "3"
# Only for generating the host key at first boot — ssh-key needs an rng that
# speaks rand_core 0.10, one major version past the `rand` used everywhere else.
rand10 = { package = "rand", version = "0.10" }
# Reading certificates, keys and keystores for the file view, in pure Rust —
# there is no OpenSSL to lean on. p12-keystore brings RC2 and 3DES for the
# keystores older tools still export; pkcs8 opens encrypted PKCS#8 keys.
x509-parser = "0.18"
p12-keystore = "0.4"
pkcs8 = { version = "0.11", features = ["encryption", "3des", "std"] }
sec1 = { version = "0.8", features = ["der"] }
sha1 = "0.10"
# ```typst blocks in markdown, typeset on the server into SVG. The fonts come
# from typst-assets, inside the binary, so nothing is fetched to render.
typst = "0.15"
typst-svg = "0.15"
typst-layout = "0.15"
typst-assets = { version = "0.15", features = ["fonts"] }
[dev-dependencies]
# A paused clock, so tests of timed loops do not wait in real time.
tokio = { version = "1", features = ["test-util"] }
[features]
default = []
# Keep the Proton session in the OS keyring instead of a 0600 file. Needs a
# Secret Service on D-Bus, so it is off for the container deployment.
keyring = ["dep:keyring"]
[profile.release]
opt-level = 3
lto = true
codegen-units = 1
strip = true