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
3.9 KiB
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-valueProject.internal/applications.buildSummaryno 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.Querynow routes token acquisition through the sharedensureTokenpath instead of duplicating the auth-expiry check inline.- Request body marshalling is consolidated into an unexported
requestBodyReaderhelper (DRY; no change to the public surface). - The
Request.Debugfield 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.NewServerfixtures that emulated OnlyOffice protocol endpoints. Replaced them with:- pure-Go unit tests in
unit_test.go(no network); - real integration tests in
client_test.goguarded by//go:build integration. Run withgo test -tags=integration ./.... Tests skip cleanly whenONLYOFFICE_URL/USER/PASS(or aliases) are absent.
- pure-Go unit tests in
- New policy documented in
AGENTS.mdand.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 localExpirestimestamp still looks fresh.
Notes
- Plain
Authenticate()is unchanged and remains a convenience wrapper aroundAuthenticateContext(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). SelfUserIDcached lookup ofpeople/@self.Defaultsstruct +SetDefaults+GetEnvironmentDefaultsfor 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 commandscal-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.Clientstruct 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.