Soft-delete (Immediately false) failed on some project files with
"You don't have enough permission to create" when moving to Trash.
Co-authored-by: Cursor <cursoragent@cursor.com>
fileops/delete returns 200 on produktor.io OO without removing files;
route DeleteFiles through DeleteDavItems so put-md --replace and oo rm work.
Co-authored-by: Cursor <cursoragent@cursor.com>
UploadToFolderReplacing deletes same-stem files before upload (--replace,
default true). OO may still display title+fileExst as double extension.
Co-authored-by: Cursor <cursoragent@cursor.com>
The docker:// runner mounts the checkout at /github/workspace; using
${{ github.workspace }} (host path) made gitleaks fail with ENOENT.
Co-authored-by: Cursor <cursoragent@cursor.com>
Merges GitHub main content (mail-send SendMail, files ops/WebDAV,
contact-indexes CRM, history whitelist) onto Gitea main so Gitea (source
of truth) contains every commit from both sides.
- BuildContactEmailIndex: one-pass email→contact id map over all persons
(O(N) instead of per-address FindPersonByEmail O(N×M))
- BuildPersonOpportunityIndex: person→lowest-id opportunity for history notes
(OO has no person-level history; verified live)
- HistoryEntity{Opportunity,Case} whitelist constants
- IsCompany/ContactID/NumericIDLess/SortIDs helpers with unit tests
- Client.SendMail: PUT /api/2.0/mail/messages/send.json, omits empty cc/bcc
- oo mails send subcommand with --id/--to/--subject/--body/--cc/--bcc
- guard: sending by --id without --body errors (send.json does not copy
subject/body from the draft; prevents empty emails)
- unit test: empty cc/bcc omitted, correct path
resolveAPIURL now rewrites absolute viewUrl hosts to the configured portal
base so downloads stay on the internal network and keep the Authorization
header (a cross-host HTTP->HTTPS redirect would otherwise strip it, failing
large-file reads).
This exposes the canonical attachment download path via oo mails so downstream tools like 2dph can migrate off local OnlyOffice mail adapters without taking a direct module dependency first.
This gives go-onlyoffice a cookie-backed attachment download path so 2dph can reuse the canonical OnlyOffice client instead of keeping a local mail adapter.
The Gitea act_runner runs action JS in node:16-bullseye; setup-go@v5 crashes
with 'ReferenceError: ReadableStream is not defined'. Gitea discovers
.github/workflows too, so:
- setup-go@v5 -> @v4 (node16-safe, fine on GitHub)
- gate GoReleaser (release.yml) + release-please jobs to
github.server_url == https://github.com so the GitHub CD never runs on the
Gitea mirror (GoReleaser/release-please are GitHub-release-centric)
The catalog feature (approved ASR-0014) was lost during the GitHub history
rewrite: the merge commit on main is empty and the code only survived on the
old gitea-history branches (no merge base with main). Port catalog/* and the
oo catalog CLI verbatim; drop the library-only applications package whose
Sync() created the 'Write application'/'Apply application'/'Send CV' CRM
task spam (23k+ tasks deleted 2026-08-18).
Expose CRM invoice list/get/create/delete and catalog items via oo,
plus contact address/about helpers and opportunity bid/stage update.
Needed for Medex VM billing and other draft invoices.
Add List/Add/Remove project contacts and CLI:
contacts list|add|remove|link-git|link-authors.
Contacts tab (CRM) is separate from ProjectTeam portal users.
Add --mbox-headers for Thunderbird folder files; strip GmbH/& Co. KG in
CompanyGroupingKey; FindCompany falls back to full scan; apply companies
before persons. Tightens role-mailbox noise filters.
Add filesystem inventory (VCF, contact folders, project trees) into a
reviewable YAML catalog, match against live OnlyOffice, and upsert only
rows with approve:true. Includes FindPersonByEmail for email-keyed persons.
GITHUB_TOKEN cannot trigger push:tags workflows, so Release never ran
after release-please. Dispatch release.yml explicitly when a release is
created. Add workflow_dispatch to Tests for on-demand main verification.
workflow_dispatch raced release-please: checkout of refs/tags/vX failed
because the tag was not fetched yet. Clone main first, retry-fetch the
tag, then check it out.
* fix(oo): assign owner and deadline on task create
CRM and project task create omitted responsibleId/responsibles, so the
portal attached a removed stub profile and CRM create without a deadline
failed or looked empty in the UI. Default both to the authenticated user
and now+14d; add crm-tasks reassign-self for backfill.
* fix(oo): collect all bad CRM tasks before reassign-self apply
Offset-0 apply stopped early when the first page was already fixed.
Stop inventing CRM companies from node_modules/tools README trees.
Only sync dossier-like folders (source-NNN-…) and invent Company from
the slug token after the numeric id.
Unify project/user flex column layout into layoutFlexTable with per-subject
policy in model. Add office-tui-table skill and AGENTS notes; fix CI go mod
tidy drift and test matrix Go version to match go.mod 1.25.
Co-authored-by: Cursor <cursoragent@cursor.com>
Add Users list/detail with ACL toggles and library people update/status APIs.
Fix project table layout and ANSI-safe cell rendering, and decode array
responses from people/status so saves no longer fail on JSON unmarshal.
Co-authored-by: Cursor <cursoragent@cursor.com>
Polish the office TUI with proportional pane layout, drag resize, live
filtering, HTML mail preview, paginated mail lists, overflow scrollbars,
flattened navigation, and project save/status fixes; add UpdateProjectStatus.
Co-authored-by: Cursor <cursoragent@cursor.com>
Add spreadsheet-style list, split detail pane with forms and document preview,
and Alt+1/2/3 to show/hide panes with even width distribution.
Co-authored-by: Cursor <cursoragent@cursor.com>
Add viewports to all three columns with cursor sync scrolling. Support
Shift+Tab reverse pane focus. Replace flat menu with hierarchical NavTree
(list loads only on leaf nodes; dynamic project subnodes with Tasks/Files).
Enter or a opens per-item action menu (view, delete, download) wired to
the OnlyOffice API.
Co-authored-by: Cursor <cursoragent@cursor.com>
Remove synthetic map-based entity and fetch mapper unit tests; cover all
menu subjects and preview pipelines via integration tests against the real
Workspace API. Handle draft mail without subjects in list mapping.
Co-authored-by: Cursor <cursoragent@cursor.com>
Release Please creates GitHub releases without pushing tag events that
reliably trigger GoReleaser; workflow_dispatch publishes binaries for a
given tag on demand.
Co-authored-by: Cursor <cursoragent@cursor.com>
Introduce the office Bubble Tea browser (module tree, multi-select lists,
markdown preview) alongside oo, with cmd/internal/bootstrap for shared auth,
unit tests across preview/model/ui/fetch, CI build for both binaries, and
GoReleaser archives for office.
Co-authored-by: Cursor <cursoragent@cursor.com>
Manage the OnlyOffice Mail addon via oo mails using existing ONLYOFFICE_* creds,
with automatic page fetching past the 25-message API cap and fromName/fromAddress columns.
Co-authored-by: Cursor <cursoragent@cursor.com>
Treat names like "Affirm" and "Affirm — Fraud Engineering" as the same
company for dedupe, deal matching, members, and applications sync lookup.
Co-authored-by: Cursor <cursoragent@cursor.com>
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
Adds two helpers tailored for cron-driven or watcher-style clients:
- AuthenticateContext(ctx) — cancellable variant of Authenticate(). Bypasses
the non-context Query() path and POSTs /api/2.0/authentication.json directly,
so a stalled auth call never outlives the caller's deadline.
- InvalidateToken() — zeroes the cached *Token. Next request (or Authenticate*)
forces a fresh auth. Intended for mid-sync 401 recovery when the server has
revoked/rotated the session while local Expires still looks fresh.
Plain Authenticate() is unchanged; it remains a convenience wrapper.
Unit tests cover cache-hit, forced refresh, and context-cancellation paths.
Refs eSlider/inventar-sync#3, ASR-0008.
Made-with: Cursor
Four new executable examples mirror the oo-cli subcommands at library level so
downstream Go consumers can see the typed API without reading the CLI wiring.
README table updated to list all examples.
Made-with: Cursor