- Rust 98.4%
- Makefile 1.1%
- Shell 0.5%
|
|
||
|---|---|---|
| .forgejo/workflows | ||
| crates | ||
| doc | ||
| .gitignore | ||
| buildenv.sh | ||
| Cargo.lock | ||
| Cargo.toml | ||
| Makefile | ||
| README.md | ||
hero_office
OnlyOffice document editor connector for the Hero stack, backed by per-context hero_fossil WebDAV storage.
hero_office hosts OnlyOffice Docs editor surfaces (documents, spreadsheets, presentations, PDFs, diagrams) and persists files through the tenant's hero_fossil instance. The UI is embedded into hero_os as a set of apps under the "Office" archipelago.
Workspace layout
| crate | role |
|---|---|
hero_office_server |
OpenRPC JSON-RPC daemon on rpc.sock — all business logic |
hero_office_sdk |
Generated typed client via openrpc_client! macro |
hero_office_admin |
HTTP UI on admin.sock — admin dashboard + OnlyOffice wrapper pages |
hero_office_examples |
Examples and integration tests |
Sockets
| socket | purpose |
|---|---|
$HERO_SOCKET_DIR/hero_office/rpc.sock |
server OpenRPC endpoint |
$HERO_SOCKET_DIR/hero_office/ui.sock |
UI HTTP endpoint (iframed) |
$HERO_SOCKET_DIR/<context>/hero_fossil_server.sock |
per-context fossil backend |
HERO_SOCKET_DIR defaults to $HOME/hero/var/sockets.
Runtime dependencies
hero_office stores all documents in hero_foundry — there is no local
storage. The dependency is implicit (a hardcoded socket path, no requires=
in service.toml), so nothing warns you when it's missing:
| dependency | why | failure mode when absent |
|---|---|---|
hero_foundry |
file storage — every document op PUTs/GETs over its UDS | RPC error -32001: hero_foundry list_contexts failed: connecting to …/hero_foundry/rpc.sock |
hero_proc |
process supervisor — lab service registers actions through it |
nothing starts |
hero_router |
browser entry point on :9988, routes /hero_office/* to UDS |
UI unreachable from a browser |
| OnlyOffice container | document editing (onlyoffice/documentserver:9.3.1) |
listing/upload work, editor pages don't |
Start order: hero_proc → hero_foundry → hero_office → hero_router.
hero_office connects to foundry per-request, so foundry can be (re)started
without restarting hero_office.
Lifecycle
The service (both actions — hero_office_server + hero_office_admin) is managed
through hero_proc. Use lab for the full build → install → run flow:
lab build hero_office --install # build all 3 binaries and install to ~/hero/bin
lab service hero_office --start # register + start both actions via hero_proc
lab service hero_office --stop # stop both actions
lab service hero_office --start --reset # force a clean restart
Known gap: lab's hardcoded
SERVICE_MAPcurrently lists onlyhero_office_serverfor this service, solab service hero_officedoes not start (or stop)hero_office_admin. Until lab is fixed, start the admin explicitly by binary name:lab service hero_office_admin --start(or run it directly:
~/hero/bin/hero_office_admin &).
Equivalently, the installed hero_office CLI binary starts/stops the service
directly (this is what lab service drives under the hood):
hero_office --start
hero_office --stop
Status and logs:
hero_proc list | grep hero_office
hero_proc logs hero_office_server # or hero_office_admin
Fresh machine setup
lab service hero_office --build --start on a clean box trips on a few
prerequisites, in this order:
# 1. git — lab clones by shelling out to the git CLI; without it you get the
# misleading "cannot find or clone repo …: I/O error (os error 2)"
apt install -y git
# 2. forge token — private lhumina_code repos need auth
# (lab reads ~/hero/cfg/hero_cfg.toml, key `forge_token`)
# 3. cargo auth for private git deps. The *admin* crate pulls hero_admin_lib →
# hero_theme from a private repo; without this the server builds but the
# admin binary silently never lands in ~/hero/bin.
git config --global url."https://USER:TOKEN@forge.ourworld.tf/".insteadOf "https://forge.ourworld.tf/"
export CARGO_NET_GIT_FETCH_WITH_CLI=true
# 4. dependencies first (see Runtime dependencies above)
lab service hero_proc --build --start
lab service hero_foundry --build --start
lab service hero_router --build --start # build, don't --download (see below)
# 5. hero_office itself
lab build hero_office --install
lab service hero_office --start
lab service hero_office_admin --start # admin — see Known gap above
# 6. verify
ls ~/hero/var/sockets/hero_office/ # want: rpc.sock + admin.sock
curl -s http://127.0.0.1:9988/hero_office/ui/ | head
Troubleshooting (deployment)
| symptom | cause | fix |
|---|---|---|
cannot find or clone repo …: I/O error: No such file or directory (os error 2) |
git not installed — lab spawns the git CLI |
apt install -y git |
hero_office_admin missing from ~/hero/bin after a "successful" build |
cargo couldn't fetch private deps (hero_admin_lib → hero_theme); only the server crate built |
cargo git auth (step 3 above), rebuild |
panic at startup: Path segments must not start with ':' … use {capture} |
stale checkout — binary built from pre-axum-0.8 route syntax | git pull to latest main, rebuild |
lab service X --download fails with MD5 mismatch |
lab publish bug: .md5 sidecar is computed before UPX packing, so every published musl asset fails verification (the binary itself is fine) |
use --build instead of --download until lab is fixed |
RPC error -32001: hero_foundry list_contexts failed: connecting to …/hero_foundry/rpc.sock |
hero_foundry not running | lab service hero_foundry --build --start; no hero_office restart needed |
| admin starts but UI unreachable in browser | hero_router not running, or wrong port | start hero_router; UI is at http://<host>:9988/hero_office/ui/ |
Env vars are read at start time (see below). They are forwarded to the actions only if set in the shell when you start — e.g. to land the UI on the
corecontext:DEFAULT_CONTEXT=core hero_office --start.
Environment variables
| variable | purpose |
|---|---|
ONLYOFFICE_JWT_SECRET |
shared JWT secret for signing editor configs (must match the OO container) |
OO_SERVER_URL |
public URL of the OnlyOffice Docs server (loaded by the user's browser) |
CONNECTOR_EXTERNAL_URL |
URL of this service as seen by the OnlyOffice container |
DEFAULT_CONTEXT |
fallback context shown on / (default: default) |
HERO_SOCKET_DIR |
socket directory (default: $HOME/hero/var/sockets) |
URL surface (admin.sock, proxied by hero_router under /hero_office/)
| route | method | purpose |
|---|---|---|
/health |
GET | JSON health check |
/admin/?context=<ctx> |
GET | operator dashboard |
/<ctx>/<type>/ |
GET | file browser filtered to one OnlyOffice type |
/<ctx>/edit/<filename> |
GET | OnlyOffice editor wrapper page |
/<ctx>/files/<filename> |
GET | byte proxy for the OO container |
/<ctx>/callback |
POST | OnlyOffice save callback |
Where <type> is one of word, cell, slide, pdf, diagram.
hero_os integration
The "Office" archipelago (hierarchical) contains five islands, each an iframe pointing at the corresponding filtered surface:
- Documents →
/hero_office/<ctx>/word/ - Spreadsheets →
/hero_office/<ctx>/cell/ - Presentations →
/hero_office/<ctx>/slide/ - PDF →
/hero_office/<ctx>/pdf/ - Diagrams →
/hero_office/<ctx>/diagram/
See hero_os/crates/hero_os_app/src/registry.rs and island_content.rs.