- GetAllTaskFiles: retrieve all files attached to a task
- CreateTaskFile: upload file with base64 encoding
- DownloadTaskFile: download file with base64 decoding
- RemoveTaskFile: delete a task file
- TaskScope.GetFiles and UploadFile for fluent API
- Automatic base64 encoding/decoding for file content
- Comprehensive test coverage
- GetAllTaskLinks: retrieve all links for a task
- CreateTaskLink: create link between two tasks
- RemoveTaskLink: delete a task link
- TaskScope.GetLinks and LinkTo for fluent API
- Link types include "blocks", "is blocked by", etc.
- Comprehensive test coverage
- MoveToNextColumn: moves task to next column in workflow
- MoveToPreviousColumn: moves task to previous column
- Gets columns sorted by position, finds current, moves to adjacent
- Returns ErrAlreadyInLastColumn when at workflow end
- Returns ErrAlreadyInFirstColumn when at workflow start
- Handles column gaps (non-sequential positions)
- Comprehensive test coverage for all edge cases
- SearchTasksGlobally: cross-project search using errgroup
- Gets all projects, then searches each in parallel
- Results aggregated from all accessible projects
- Context cancellation propagates to all goroutines
- Single project failure cancels remaining searches
- Added golang.org/x/sync/errgroup dependency
- Comprehensive test coverage
- GetAllComments: retrieve all comments for a task
- GetComment: retrieve single comment by ID
- CreateComment: create comment and return the created comment
- UpdateComment: update comment content
- RemoveComment: delete a comment
- TaskScope.GetComments and AddComment for fluent API
- Returns ErrCommentNotFound when appropriate
- Comprehensive test coverage
- GetTags: retrieve task tags as map[int]string
- SetTags: replace all tags on a task
- ClearTags: remove all tags
- AddTag: read-modify-write, idempotent (no-op if tag exists)
- RemoveTag: read-modify-write, idempotent (no-op if tag doesn't exist)
- HasTag: check if task has a specific tag
WARNING: Tag operations are NOT atomic. Concurrent modifications may
cause data loss due to the read-modify-write pattern required by
Kanboard's setTaskTags API.
Comprehensive test coverage including idempotency tests.
- TaskScope struct for task-scoped operations
- Client.Task(taskID) returns a TaskScope
- Methods: Get, Close, Open, MoveToColumn, MoveToProject, Update
- MoveToColumn fetches task to get project_id and swimlane_id
- All methods delegate to direct Client methods
- Comprehensive test coverage
- BoardScope struct for project-scoped operations
- Client.Board(projectID) returns a BoardScope
- Methods: GetColumns, GetCategories, GetTasks, SearchTasks, CreateTask
- All methods delegate to direct Client methods
- CreateTask automatically sets project ID from scope
- Comprehensive test coverage
- SearchTasks: search tasks using Kanboard query syntax
- MoveTaskPosition: move task to specific position in column/swimlane
- MoveTaskToProject: move task to different project
- Comprehensive test coverage for all methods
- GetTask: retrieve single task by ID
- GetAllTasks: retrieve all tasks for a project with status filter
- CreateTask: create new task and return the created task
- UpdateTask: partial updates via pointer fields
- CloseTask/OpenTask: status operations with proper error handling
- Returns ErrTaskNotFound, ErrTaskClosed, ErrTaskOpen as appropriate
- Comprehensive test coverage for all methods and edge cases
- GetAllCategories returns all categories for a project
- GetCategory returns a single category by ID
- Returns ErrCategoryNotFound for non-existent categories
- Added ErrCategoryNotFound to IsNotFound helper
- Comprehensive test coverage
- GetColumns returns all columns for a project, sorted by position
- GetColumn returns a single column by ID
- Returns ErrColumnNotFound for non-existent columns
- Comprehensive test coverage including edge cases
Add direct client methods for project/board operations:
- GetAllProjects(ctx) - list all accessible projects
- GetProjectByID(ctx, projectID) - get project by ID
- GetProjectByName(ctx, name) - get project by name
All methods:
- Use context for cancellation support
- Return ErrProjectNotFound when project doesn't exist
- Properly wrap errors with context
Closes: kanboard-api-apl
Add custom Timestamp type that wraps time.Time for Kanboard's
Unix timestamp format:
UnmarshalJSON supports:
- Unix timestamps as integers
- Empty strings and "0" strings as zero time
- Null values as zero time
- Numeric strings (e.g., "1609459200")
MarshalJSON returns:
- 0 for zero time
- Unix timestamp for non-zero time
Includes comprehensive tests for round-trip marshaling
and struct embedding scenarios.
Closes: kanboard-api-25y
Add full client configuration with fluent builder pattern:
- WithTimeout(duration) - configurable request timeout
- WithLogger(slog.Logger) - optional debug logging
- DefaultTimeout constant (30 seconds)
- Default HTTP client with timeout on construction
All fluent methods return same client instance for chaining.
Client is thread-safe for concurrent use.
Closes: kanboard-api-uls
Add comprehensive tests for HTTP Basic Auth support:
- API token authentication (jsonrpc + token)
- Username/password authentication
- Verify no auth header when unconfigured
- Fluent configuration method chaining
- Auth overwrite behavior
The auth implementation was completed in the previous commit
as a dependency for JSON-RPC client.
Closes: kanboard-api-k33
Add core JSON-RPC 2.0 protocol implementation for Kanboard API:
- JSONRPCRequest/Response/Error structs with proper JSON tags
- Generic call() method for sending requests and parsing responses
- Thread-safe request ID generation using atomic.Int64
- Automatic /jsonrpc.php path appending to baseURL
- Support for subdirectory installations
- HTTP Basic Auth support (API token and username/password)
- Error handling for unauthorized/forbidden responses
Includes comprehensive tests with httptest mock server.
Closes: kanboard-api-2g1