Files
go-onlyoffice/AGENTS.md
T
eSlider 55356558a1
Release / GoReleaser (push) Skipped
Tests / Secret scan (gitleaks) (push) Skipped
Tests / Test (Go 1.25) (push) Skipped
Tests / Test (Go stable) (push) Skipped
Tests / Secret scan (gitleaks) (pull_request) Successful in 5s
Tests / Test (Go stable) (pull_request) Successful in 1m9s
Tests / Test (Go 1.25) (pull_request) Successful in 1m11s
feat(dav): oo dav upload (local file) + ensure-path (mkdir -p) in Documents (#80)
2026-09-25 15:07:57 +01:00

8.4 KiB

AGENTS — go-onlyoffice

Canonical Go client for OnlyOffice Workspace (Projects + Calendar + CRM) and the oo command.

Topology

  • Library — flat package onlyoffice at repo root. Split by domain file, not by subpackage, so every call site reads c.XxxYyy() against a single *Client. Files:
    • client.go — Client, Credentials, Defaults, env helpers, NewClient.
    • request.go — Request, Query, Time, Token, MetaResponse, Permissions.
    • auth.go — Authenticate, AuthenticateContext, InvalidateToken, Auth, token lifecycle.
    • http.go — transport + DRY response decoders (ResponseArray/ResponseObject/postFormObject/putFormObject/deleteObject).
    • projects.go, tasks.go, users.go, calendar.go, crm.go, files.go, files_webdav.go, files_stem.go, retry.go, mails.go, invoices.go — typed / untyped domain methods. files.go — CRM opportunity upload plus project/task Documents (UpdateFile, UploadToFolderReplacing). files_webdav.go — Documents module by id (ListDavFolder, MoveDavItems/CopyDavItems with per-operation error surfacing, ListFileOps). retry.go — DoRetry: deterministic exponential backoff (no jitter) on 429/502/503/504; every bulk tool routes API calls through it, and the HTTP transport + auth (retryRaw, AuthenticateContext) retry transient answers centrally. ratelimit.go adds a process-wide token bucket (OO_RATE_LIMIT/OO_BURST) and a shared 429 cooldown gate, installed via pacedTransport in NewClient; Retry-After is parsed into *TransientError and honoured. See docs/rate-limiting.md. mails.go — OnlyOffice Workspace Mail. invoices.go — CRM invoices, PDF regen/cleanup, status. Association rules live with the private oo-workspace tooling.
    • Unified file client (epic #34) — filestore_core.go, filestore_rest.go, filestore_dav.go, filestore_pg.go, filestore_es.go, filestore_es_text.go, filestore_text_index.go, filestore_facade.go. filestore_core.go — model (Entry, Kind) + FileStore/Searcher; filestore_rest.go/filestore_dav.go — REST/WebDAV adapters; filestore_pg.go — read-only SQL store (PostgreSQL/MySQL, ErrReadOnly on writes); filestore_es.go — OnlyOffice Elasticsearch searcher; filestore_es_text.go/filestore_text_index.go — own PDF/scan index (oo_docs_text, PDF attachments via pdfdetach); filestore_facade.go — FileClient with read/write/search order and transient fallback. Use c.Files() (facade), c.FileStore("rest"|"dav"|"pg"|"sql") or c.SQLFileStore(); contract and how to add a backend: docs/unified-file-client.md.
    • Pure stdlib + google/go-querystring; no UI, no dotenv.
  • CLI — cmd/oo/ as package main. Cobra wrapper that loads .env via godotenv at startup. Subject-based command tree mirroring tea:
    • main.go — entry point (docstring lists the command tree).
    • common.go — rootCmd, newOO, printTable/printObject, --output table|json flag.
    • calendar.go, projects.go, projects_files.go, tasks.go, tasks_files.go, users.go, contacts.go, opportunities.go, cases.go, crm.go, crm_tasks.go, catalog.go, docs.go, dav.go, search.go, index.go, mails.go, invoices.go — one file per subject (or per subject facet), each registers in init(). dav.go exposes the Documents module by id (oo dav ls|move|copy|mkdir|ensure-path|upload|rename-file|rename-folder|download|fileops); search.go runs oo search QUERY (name/content, --backend oo|own); index.go fills the own full-text index (oo index folder|files, see docs/unified-file-client.md).
    • CLI-only deps (spf13/cobra, joho/godotenv) stay out of the library.
  • TUI — cmd/office/ as package main. Bubble Tea three-pane browser (module tree, selectable list, markdown preview). Reuses cmd/internal/bootstrap for env/auth and the root onlyoffice library for all API calls. UI logic in cmd/office/ui/; preview/formatting in cmd/office/preview/; list loaders in cmd/office/fetch/.
    • List table (DataTable) — cmd/office/ui/table*.go. Column layout policies live in cmd/office/model/table_layout.go (TableFlexLayoutFor); cell rendering uses the bubbles/table inline pattern in table_render.go (renderTableCell, padANSIWidth). See .cursor/skills/office-tui-table/SKILL.md before changing center-pane tables.
  • Shared bootstrap — cmd/internal/bootstrap/. LoadEnv() + NewClient(ctx) extracted from oo; both binaries import it.
  • Bulk Documents tools live in the private oo-workspace repo (ooscan, pdfamount, kontoblatt, kontolink), not in this public tree. They use the public client and its DoRetry pacing.
  • Personal ops tooling (disk inventory, dossier→CRM sync, SearXNG) lives in a private companion repo eSlider/oo-workspace (the oow CLI), not in this public tree.

Rules

  • Library must never call godotenv.Load() — the CLI does that.
  • New endpoints go into the library first; CLI commands are thin wrappers.
  • Prefer ResponseObject / postFormObject / putFormObject / deleteObject over hand-rolled json.Unmarshal(responseField(...)) blocks — they exist for DRY, use them.
  • Domain split is by file, not by subpackage. Don't introduce internal/ or pkg/* subpackages inside the library — it flattens the *Client call surface for a reason.
  • CLI commands follow subject → verb structure (oo <subject> <verb>), never oo <verb>-<subject>. Add new commands to the existing subject file if one fits; create a new cmd/oo/<subject>.go for a genuinely new domain. The subject→verb tree in cmd/oo/main.go and the README table are documentation — update them with the code.
  • Documents for agents: prefer Markdown in git; OnlyOffice UI is weak for .md/.txt. Use oo docs put-md (md→docx) and oo docs put-txt (txt→docx, preserves line breaks). All upload paths default to upsert by stem|ext (--replace, default true); --no-replace fails on conflict; --allow-duplicate opts into raw OO append. oo projects files dedupe PROJECT_ID reports/removes duplicate stem|ext copies (--apply, --cross; includes project root folder).
  • Every table output goes through printTable(headers, rows); every single-object through printObject(v). Do not fmt.Println rows ad-hoc or the --output json flag breaks for that command.
  • No secrets in the repo; use .env (gitignored). Commit .env.example only.
  • No host/client specifics in the tree. Endpoints, IPs/ports, client mail domains, project remotes/names and personal names stay out of source and fixtures — they come from env/config (MINIO_*, OO_CATALOG_CONFIG, see catalog/classify.example.yaml). This repo is mirrored to GitHub as a public showroom, so the tree must stay project-generic.
  • Follow SemVer on tags; this repo is tagged at GitHub under git@github.com:eSlider/go-onlyoffice.git.

Testing policy (2026-04-24)

No synthetic OnlyOffice mockups. Protocol-level behaviour must be verified against a real OnlyOffice instance. httptest.NewServer is only acceptable for testing the caller's logic that the library can't reach (for example, the user's own HTTP handler). Anywhere we would otherwise write mux.HandleFunc("/api/2.0/...") to emulate OnlyOffice, we write an integration test instead.

  • Unit tests (*_test.go, no build tag) — pure Go: parsers, encoders, struct conversions. No network. No fake servers that emulate the vendor.
  • Integration tests (//go:build integration tag in *_integration_test.go) — hit a live OnlyOffice instance. Credentials come from ONLYOFFICE_URL, ONLYOFFICE_USER, ONLYOFFICE_PASS (aliases _HOST/_NAME/_PASSWORD also accepted). Tests skip cleanly when credentials are missing so go test ./... remains green in CI.
  • Run integration with: go test -tags=integration ./....
  • New endpoints must ship with an integration test before merge.
  • docs/README.md — reference index (file client, ES, SQL, rclone).
  • eSlider/inventar — ASR/ADR (see ASR-0008 Go library module conventions).
  • eSlider/inventar-sync — OnlyOffice → Gitea issue sync, consumes this library.
  • vidarr — legacy consumer being migrated from pkg/onlyoffice to this module.