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 4s
Tests / Test (Go stable) (pull_request) Successful in 1m19s
Tests / Test (Go 1.25) (pull_request) Successful in 1m24s
Keep the public tree project-generic. Business/one-off tools, deployment and business docs move to the private oo-workspace repo. Moved to oo-workspace: - cmd/ooscan, cmd/pdfamount, cmd/kontoblatt, cmd/kontolink - internal/xlspipe (cutover-portugal workbook) -> oow workbook build (drops the --template/--title flags from oo docs put-xlsx) - deploy/docker-compose.rclone-webdav.yml + docs/rclone-webdav.md - docs/crm-associations.md Removed GitHub-era leftovers: - .github/workflows/release-please.yml, release-please-config.json, .release-please-manifest.json (tags are created on Gitea per SemVer) Naming: the FileStore subsystem is now filestore_*.go (was file_*.go) to match files_*.go (project Documents). Docs/AGENTS/README updated.
8.4 KiB
8.4 KiB
AGENTS — go-onlyoffice
Canonical Go client for OnlyOffice Workspace (Projects + Calendar + CRM) and the oo command.
Topology
- Library — flat package
onlyofficeat repo root. Split by domain file, not by subpackage, so every call site readsc.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/CopyDavItemswith 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.goadds a process-wide token bucket (OO_RATE_LIMIT/OO_BURST) and a shared 429 cooldown gate, installed viapacedTransportinNewClient;Retry-Afteris parsed into*TransientErrorand honoured. Seedocs/rate-limiting.md.mails.go— OnlyOffice Workspace Mail.invoices.go— CRM invoices, PDF regen/cleanup, status. Association rules live with the privateoo-workspacetooling.- 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,ErrReadOnlyon 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—FileClientwith read/write/search order and transient fallback. Usec.Files()(facade),c.FileStore("rest"|"dav"|"pg"|"sql")orc.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/aspackage main. Cobra wrapper that loads.envviagodotenvat startup. Subject-based command tree mirroringtea:main.go— entry point (docstring lists the command tree).common.go—rootCmd,newOO,printTable/printObject,--output table|jsonflag.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 ininit().dav.goexposes the Documents module by id (oo dav ls|move|copy|mkdir|rename-file|rename-folder|download|fileops);search.gorunsoo search QUERY(name/content,--backend oo|own);index.gofills the own full-text index (oo index folder|files, seedocs/unified-file-client.md).- CLI-only deps (
spf13/cobra,joho/godotenv) stay out of the library.
- TUI —
cmd/office/aspackage main. Bubble Tea three-pane browser (module tree, selectable list, markdown preview). Reusescmd/internal/bootstrapfor env/auth and the rootonlyofficelibrary for all API calls. UI logic incmd/office/ui/; preview/formatting incmd/office/preview/; list loaders incmd/office/fetch/.- List table (
DataTable) —cmd/office/ui/table*.go. Column layout policies live incmd/office/model/table_layout.go(TableFlexLayoutFor); cell rendering uses the bubbles/table inline pattern intable_render.go(renderTableCell,padANSIWidth). See.cursor/skills/office-tui-table/SKILL.mdbefore changing center-pane tables.
- List table (
- Shared bootstrap —
cmd/internal/bootstrap/.LoadEnv()+NewClient(ctx)extracted fromoo; both binaries import it. - Bulk Documents tools live in the private
oo-workspacerepo (ooscan,pdfamount,kontoblatt,kontolink), not in this public tree. They use the public client and itsDoRetrypacing. - Personal ops tooling (disk inventory, dossier→CRM sync, SearXNG) lives in a private companion repo
eSlider/oo-workspace(theoowCLI), 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/deleteObjectover hand-rolledjson.Unmarshal(responseField(...))blocks — they exist for DRY, use them. - Domain split is by file, not by subpackage. Don't introduce
internal/orpkg/*subpackages inside the library — it flattens the*Clientcall surface for a reason. - CLI commands follow subject → verb structure (
oo <subject> <verb>), neveroo <verb>-<subject>. Add new commands to the existing subject file if one fits; create a newcmd/oo/<subject>.gofor a genuinely new domain. The subject→verb tree incmd/oo/main.goand the README table are documentation — update them with the code. - Documents for agents: prefer Markdown in git; OnlyOffice UI is weak for
.md/.txt. Useoo docs put-md(md→docx) andoo docs put-txt(txt→docx, preserves line breaks). All upload paths default to upsert bystem|ext(--replace, default true);--no-replacefails on conflict;--allow-duplicateopts into raw OO append.oo projects files dedupe PROJECT_IDreports/removes duplicate stem|ext copies (--apply,--cross; includes project root folder). - Every table output goes through
printTable(headers, rows); every single-object throughprintObject(v). Do notfmt.Printlnrows ad-hoc or the--output jsonflag breaks for that command. - No secrets in the repo; use
.env(gitignored). Commit.env.exampleonly. - 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, seecatalog/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 integrationtag in*_integration_test.go) — hit a live OnlyOffice instance. Credentials come fromONLYOFFICE_URL,ONLYOFFICE_USER,ONLYOFFICE_PASS(aliases_HOST/_NAME/_PASSWORDalso accepted). Tests skip cleanly when credentials are missing sogo test ./...remains green in CI. - Run integration with:
go test -tags=integration ./.... - New endpoints must ship with an integration test before merge.
Related
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 frompkg/onlyofficeto this module.