Files
go-onlyoffice/CHANGELOG.md
T
eSlider e2d481e7b8 refactor: DRY auth path, fix Sprintf/RE2 bugs; real integration tests only
Why
---
- Sprintf(*p.Title) fed the title as a format string — % in titles broke
  the String() method; also panicked on nil Title.
- internal/applications.buildSummary used RE2-unsupported `(?= ...)`
  lookahead inside regexp.MustCompile, panicking the first time the
  applications-sync path was exercised on Go 1.23+.
- Query() duplicated the auth-expiry check inline while ensureToken()
  already handled it — two code paths drifted.
- Request.Debug split Query() into two branches that both unmarshalled
  into the same target value. Dead code.
- httptest fixtures that emulated OnlyOffice endpoints were lying to us:
  they passed locally yet never caught a single real protocol regression.

What
----
- Project.String(): nil-safe, no Sprintf format-string interpretation.
- buildSummary regex: RE2-safe non-capturing trailing delimiter
  `(?:\n## |$)` replaces the lookahead.
- Query() routes through ensureToken(); body marshalling factored into
  an unexported requestBodyReader(). Debug flag retained for backwards
  compatibility, documented as a no-op, to be removed at next major.
- Dropped Debug: true stray flags in GetTasks/UpdateProjectTask.
- Deleted httptest-based OnlyOffice mocks. unit_test.go is now pure Go
  (parsers, helpers, env aliases, ctx cancellation against an unroutable
  address). client_test.go is `//go:build integration` and runs against
  a real OnlyOffice, skipping cleanly without ONLYOFFICE_URL/USER/PASS.
- AGENTS.md + .cursor/rules/no-synthetic-mocks.mdc document the new
  testing policy.

Verified
--------
- `go test ./...` green (15 unit tests across package + internal).
- `go test -tags=integration ./...` green against live
  office.produktor.io (5 integration tests: auth, projects, lifecycle,
  calendar+CRM read, task list).
- inventar-sync smoke dry-run against live OO project 33 + Gitea found
  30 tasks, 0 mutations.

Made-with: Cursor
2026-04-24 12:36:40 +01:00

3.9 KiB

Changelog

All notable changes to this project are documented here. The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[Unreleased]

[0.3.2] - 2026-04-24

Fixed

  • Project.String() no longer interprets the title as a format string (fmt.Sprintf(*p.Title)) and is now nil-safe on a zero-value Project.
  • internal/applications.buildSummary no longer panics at regex compile time on Go 1.23+ — the previous (?= ...) lookahead is replaced with an RE2-safe non-capturing trailing delimiter.

Changed

  • Client.Query now routes token acquisition through the shared ensureToken path instead of duplicating the auth-expiry check inline.
  • Request body marshalling is consolidated into an unexported requestBodyReader helper (DRY; no change to the public surface).
  • The Request.Debug field is preserved for backwards compatibility but no longer changes behaviour — both branches used to unmarshal into the same target value. We'll remove the field in a future major release.

Tests

  • Deleted httptest.NewServer fixtures that emulated OnlyOffice protocol endpoints. Replaced them with:
    • pure-Go unit tests in unit_test.go (no network);
    • real integration tests in client_test.go guarded by //go:build integration. Run with go test -tags=integration ./.... Tests skip cleanly when ONLYOFFICE_URL/USER/PASS (or aliases) are absent.
  • New policy documented in AGENTS.md and .cursor/rules/no-synthetic-mocks.mdc.

[0.3.1] - 2026-04-24

Added

  • AuthenticateContext(ctx) — context-aware auth that honours cancellation and deadlines. Preferred entry point for long-running syncs (cron, watchers).
  • InvalidateToken() — clears the cached token to force re-auth on the next request. Use this to recover from a mid-sync 401 when the server has revoked the session while the local Expires timestamp still looks fresh.

Notes

  • Plain Authenticate() is unchanged and remains a convenience wrapper around AuthenticateContext(context.Background()).
  • No breaking changes; a patch release.

[0.3.0] - 2026-04-24

Added

  • Calendar helpers: ListCalendars, ListEvents, AddEvent, DeleteEvent.
  • CRM helpers: contacts (ListContacts, GetContact, FindCompany, FindPerson, CreateCompany, CreatePerson, AddContactInfo, DeleteContact), deals (ListOpportunities, GetOpportunity, CreateOpportunity, AddOpportunityMember, ListDealStages, DeleteOpportunity), cases (ListCases, CreateCase, AddCaseMember, DeleteCase), CRM tasks (ListCRMTasks, CreateCRMTask, DeleteCRMTask, ListTaskCategories), and history notes (AddHistoryNote).
  • Project task extras: GetProjectByID, ListTasks, ListAllTasks, GetTaskByID, AddTask, AddSubtask, UpdateTaskStatus, DeleteTask.
  • File upload: UploadOpportunityFile (multipart).
  • SelfUserID cached lookup of people/@self.
  • Defaults struct + SetDefaults + GetEnvironmentDefaults for optional calendar/project fallbacks.
  • Alias env vars accepted by GetEnvironmentCredentials: ONLYOFFICE_HOST / ONLYOFFICE_NAME / ONLYOFFICE_PASSWORD.
  • Public Authenticate() that primes the token eagerly.
  • Bundled CLI: cmd/oo-cli (Cobra) with commands cal-list, cal-events, cal-add, cal-delete, task-list, task-add, subtask-add, task-update, crm-contacts, crm-add-contact, crm-deals, crm-add-deal, crm-cases, applications-sync.
  • httptest-based unit tests for form / multipart / CRM helpers.

Changed

  • The onlyoffice.Client struct gained unexported fields (defaults, selfID, noteCatID); the public API is unchanged and remains backwards compatible.

[0.2.0] - earlier

  • Badges, docs expansion (Gitea sync use case, Gantt/PM workflows).

[0.1.0] - earlier

  • Initial release: OnlyOffice Project Management API client.