Add project documentation and beads configuration
- Added CLAUDE.md with project overview and architecture details - Added PRD.md with product requirements - Added AGENTS.md for agent workflow documentation - Initialized beads issue tracking system - Added .gitattributes for Git configuration
This commit is contained in:
parent
62e299192d
commit
9f613b1901
12 changed files with 933 additions and 1 deletions
44
.beads/.gitignore
vendored
Normal file
44
.beads/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
# SQLite databases
|
||||
*.db
|
||||
*.db?*
|
||||
*.db-journal
|
||||
*.db-wal
|
||||
*.db-shm
|
||||
|
||||
# Daemon runtime files
|
||||
daemon.lock
|
||||
daemon.log
|
||||
daemon.pid
|
||||
bd.sock
|
||||
sync-state.json
|
||||
last-touched
|
||||
|
||||
# Local version tracking (prevents upgrade notification spam after git ops)
|
||||
.local_version
|
||||
|
||||
# Legacy database files
|
||||
db.sqlite
|
||||
bd.db
|
||||
|
||||
# Worktree redirect file (contains relative path to main repo's .beads/)
|
||||
# Must not be committed as paths would be wrong in other clones
|
||||
redirect
|
||||
|
||||
# Merge artifacts (temporary files from 3-way merge)
|
||||
beads.base.jsonl
|
||||
beads.base.meta.json
|
||||
beads.left.jsonl
|
||||
beads.left.meta.json
|
||||
beads.right.jsonl
|
||||
beads.right.meta.json
|
||||
|
||||
# Sync state (local-only, per-machine)
|
||||
# These files are machine-specific and should not be shared across clones
|
||||
.sync.lock
|
||||
sync_base.jsonl
|
||||
|
||||
# NOTE: Do NOT add negation patterns (e.g., !issues.jsonl) here.
|
||||
# They would override fork protection in .git/info/exclude, allowing
|
||||
# contributors to accidentally commit upstream issue databases.
|
||||
# The JSONL files (issues.jsonl, interactions.jsonl) and config files
|
||||
# are tracked by git by default since no pattern above ignores them.
|
||||
89
.beads/PRIME.md
Normal file
89
.beads/PRIME.md
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
# Beads Workflow Context
|
||||
|
||||
> **Context Recovery**: Run `bd prime` after compaction, clear, or new session
|
||||
> Hooks auto-call this in Claude Code when .beads/ detected
|
||||
|
||||
# 🚨 TWO-PHASE WORKFLOW 🚨
|
||||
|
||||
**This project uses a split workflow:**
|
||||
|
||||
| Phase | Command | Actions |
|
||||
|-------|---------|---------|
|
||||
| **1. Implement** | `/start-issue <id>` | Set status → Plan → Implement |
|
||||
| **2. Finalize** | `/finish-issue` | Commit → Close → Push |
|
||||
|
||||
## What this means for you:
|
||||
|
||||
### ✅ ALLOWED during implementation:
|
||||
- Set ticket to `in_progress`
|
||||
- Read, analyze, plan
|
||||
- Write and modify code
|
||||
- Run tests, build, verify
|
||||
|
||||
### ❌ FORBIDDEN during implementation:
|
||||
- `git add` / `git commit` / `git push`
|
||||
- `bd close`
|
||||
- `bd sync` (syncs commits)
|
||||
|
||||
### When implementation is complete:
|
||||
|
||||
**DO NOT** run the old "Session Close Protocol". Instead say:
|
||||
|
||||
> "✅ Implementation complete. Files changed: [list files]. Run `/finish-issue` when ready to commit and close."
|
||||
|
||||
Then **STOP** and wait for the user.
|
||||
|
||||
---
|
||||
|
||||
## Core Rules
|
||||
- Track strategic work in beads (multi-session, dependencies, discovered work)
|
||||
- Use `bd create` for issues, TodoWrite for simple single-session execution
|
||||
- When in doubt, prefer bd—persistence you don't need beats lost context
|
||||
- Session management: check `bd ready` for available work
|
||||
|
||||
## Essential Commands
|
||||
|
||||
### Finding Work
|
||||
- `bd ready` - Show issues ready to work (no blockers)
|
||||
- `bd list --status=open` - All open issues
|
||||
- `bd list --status=in_progress` - Your active work
|
||||
- `bd show <id>` - Detailed issue view with dependencies
|
||||
|
||||
### Creating & Updating
|
||||
- `bd create --title="..." --type=task|bug|feature --priority=2` - New issue
|
||||
- Priority: 0-4 or P0-P4 (0=critical, 2=medium, 4=backlog). NOT "high"/"medium"/"low"
|
||||
- `bd update <id> --status=in_progress` - Claim work
|
||||
- `bd update <id> --assignee=username` - Assign to someone
|
||||
- `bd update <id> --title/--description/--notes/--design` - Update fields inline
|
||||
- `bd close <id>` - Mark complete (⚠️ only in /finish-issue!)
|
||||
- **WARNING**: Do NOT use `bd edit` - it opens $EDITOR which blocks agents
|
||||
|
||||
### Dependencies & Blocking
|
||||
- `bd dep add <issue> <depends-on>` - Add dependency
|
||||
- `bd blocked` - Show all blocked issues
|
||||
- `bd show <id>` - See what's blocking/blocked by this issue
|
||||
|
||||
### Project Health
|
||||
- `bd stats` - Project statistics
|
||||
- `bd doctor` - Check for issues
|
||||
|
||||
## Workflow Summary
|
||||
|
||||
```
|
||||
/start-issue <id>
|
||||
│
|
||||
├── bd update <id> --status=in_progress
|
||||
├── [Plan mode]
|
||||
├── [Implement]
|
||||
└── STOP → "Implementation complete"
|
||||
|
||||
... user reviews ...
|
||||
|
||||
/finish-issue
|
||||
│
|
||||
├── bd close <id>
|
||||
├── git add -A
|
||||
├── git commit -m "..."
|
||||
├── bd sync
|
||||
└── Done!
|
||||
```
|
||||
81
.beads/README.md
Normal file
81
.beads/README.md
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
# Beads - AI-Native Issue Tracking
|
||||
|
||||
Welcome to Beads! This repository uses **Beads** for issue tracking - a modern, AI-native tool designed to live directly in your codebase alongside your code.
|
||||
|
||||
## What is Beads?
|
||||
|
||||
Beads is issue tracking that lives in your repo, making it perfect for AI coding agents and developers who want their issues close to their code. No web UI required - everything works through the CLI and integrates seamlessly with git.
|
||||
|
||||
**Learn more:** [github.com/steveyegge/beads](https://github.com/steveyegge/beads)
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Essential Commands
|
||||
|
||||
```bash
|
||||
# Create new issues
|
||||
bd create "Add user authentication"
|
||||
|
||||
# View all issues
|
||||
bd list
|
||||
|
||||
# View issue details
|
||||
bd show <issue-id>
|
||||
|
||||
# Update issue status
|
||||
bd update <issue-id> --status in_progress
|
||||
bd update <issue-id> --status done
|
||||
|
||||
# Sync with git remote
|
||||
bd sync
|
||||
```
|
||||
|
||||
### Working with Issues
|
||||
|
||||
Issues in Beads are:
|
||||
- **Git-native**: Stored in `.beads/issues.jsonl` and synced like code
|
||||
- **AI-friendly**: CLI-first design works perfectly with AI coding agents
|
||||
- **Branch-aware**: Issues can follow your branch workflow
|
||||
- **Always in sync**: Auto-syncs with your commits
|
||||
|
||||
## Why Beads?
|
||||
|
||||
✨ **AI-Native Design**
|
||||
- Built specifically for AI-assisted development workflows
|
||||
- CLI-first interface works seamlessly with AI coding agents
|
||||
- No context switching to web UIs
|
||||
|
||||
🚀 **Developer Focused**
|
||||
- Issues live in your repo, right next to your code
|
||||
- Works offline, syncs when you push
|
||||
- Fast, lightweight, and stays out of your way
|
||||
|
||||
🔧 **Git Integration**
|
||||
- Automatic sync with git commits
|
||||
- Branch-aware issue tracking
|
||||
- Intelligent JSONL merge resolution
|
||||
|
||||
## Get Started with Beads
|
||||
|
||||
Try Beads in your own projects:
|
||||
|
||||
```bash
|
||||
# Install Beads
|
||||
curl -sSL https://raw.githubusercontent.com/steveyegge/beads/main/scripts/install.sh | bash
|
||||
|
||||
# Initialize in your repo
|
||||
bd init
|
||||
|
||||
# Create your first issue
|
||||
bd create "Try out Beads"
|
||||
```
|
||||
|
||||
## Learn More
|
||||
|
||||
- **Documentation**: [github.com/steveyegge/beads/docs](https://github.com/steveyegge/beads/tree/main/docs)
|
||||
- **Quick Start Guide**: Run `bd quickstart`
|
||||
- **Examples**: [github.com/steveyegge/beads/examples](https://github.com/steveyegge/beads/tree/main/examples)
|
||||
|
||||
---
|
||||
|
||||
*Beads: Issue tracking that moves at the speed of thought* ⚡
|
||||
62
.beads/config.yaml
Normal file
62
.beads/config.yaml
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
# Beads Configuration File
|
||||
# This file configures default behavior for all bd commands in this repository
|
||||
# All settings can also be set via environment variables (BD_* prefix)
|
||||
# or overridden with command-line flags
|
||||
|
||||
# Issue prefix for this repository (used by bd init)
|
||||
# If not set, bd init will auto-detect from directory name
|
||||
# Example: issue-prefix: "myproject" creates issues like "myproject-1", "myproject-2", etc.
|
||||
# issue-prefix: ""
|
||||
|
||||
# Use no-db mode: load from JSONL, no SQLite, write back after each command
|
||||
# When true, bd will use .beads/issues.jsonl as the source of truth
|
||||
# instead of SQLite database
|
||||
# no-db: false
|
||||
|
||||
# Disable daemon for RPC communication (forces direct database access)
|
||||
# no-daemon: false
|
||||
|
||||
# Disable auto-flush of database to JSONL after mutations
|
||||
# no-auto-flush: false
|
||||
|
||||
# Disable auto-import from JSONL when it's newer than database
|
||||
# no-auto-import: false
|
||||
|
||||
# Enable JSON output by default
|
||||
# json: false
|
||||
|
||||
# Default actor for audit trails (overridden by BD_ACTOR or --actor)
|
||||
# actor: ""
|
||||
|
||||
# Path to database (overridden by BEADS_DB or --db)
|
||||
# db: ""
|
||||
|
||||
# Auto-start daemon if not running (can also use BEADS_AUTO_START_DAEMON)
|
||||
# auto-start-daemon: true
|
||||
|
||||
# Debounce interval for auto-flush (can also use BEADS_FLUSH_DEBOUNCE)
|
||||
# flush-debounce: "5s"
|
||||
|
||||
# Git branch for beads commits (bd sync will commit to this branch)
|
||||
# IMPORTANT: Set this for team projects so all clones use the same sync branch.
|
||||
# This setting persists across clones (unlike database config which is gitignored).
|
||||
# Can also use BEADS_SYNC_BRANCH env var for local override.
|
||||
# If not set, bd sync will require you to run 'bd config set sync.branch <branch>'.
|
||||
# sync-branch: "beads-sync"
|
||||
|
||||
# Multi-repo configuration (experimental - bd-307)
|
||||
# Allows hydrating from multiple repositories and routing writes to the correct JSONL
|
||||
# repos:
|
||||
# primary: "." # Primary repo (where this database lives)
|
||||
# additional: # Additional repos to hydrate from (read-only)
|
||||
# - ~/beads-planning # Personal planning repo
|
||||
# - ~/work-planning # Work planning repo
|
||||
|
||||
# Integration settings (access with 'bd config get/set')
|
||||
# These are stored in the database, not in this file:
|
||||
# - jira.url
|
||||
# - jira.project
|
||||
# - linear.url
|
||||
# - linear.api-key
|
||||
# - github.org
|
||||
# - github.repo
|
||||
6
.beads/export-state/6feeba40f0df6736.json
Normal file
6
.beads/export-state/6feeba40f0df6736.json
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"worktree_root": "/home/oli/Dev/bookstack-api",
|
||||
"last_export_commit": "a6adae98dd1697df76e68e562a4f84e7a38aa52d",
|
||||
"last_export_time": "2026-01-30T09:36:58.353806809+01:00",
|
||||
"jsonl_hash": "274bd67ea9399c10b88ec481bf082fe529a2d0cff39af1f6cbe89339a2f57f75"
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
{"id":"bookstack-api-8op","title":"Implement Client and Config structs","description":"Create the main Client struct and Config for client initialization with token-based authentication.\n\n## Requirements\nFrom PRD Section 5 (API \u0026 Interface-Spezifikation):\n\n```go\ntype Config struct {\n BaseURL string // e.g. \"https://docs.jakoubek.net\"\n TokenID string // API Token ID\n TokenSecret string // API Token Secret\n HTTPClient *http.Client // optional, for tests/mocking\n}\n\ntype Client struct {\n Books *BooksService\n Pages *PagesService\n Chapters *ChaptersService\n Shelves *ShelvesService\n Search *SearchService\n}\n\nfunc NewClient(cfg Config) *Client\n```\n\n## Authentication\nHeader format: `Authorization: Token \u003ctoken_id\u003e:\u003ctoken_secret\u003e`\n\n## Acceptance Criteria\n- [ ] Config struct with BaseURL, TokenID, TokenSecret, optional HTTPClient\n- [ ] Client struct with service fields (initially nil)\n- [ ] NewClient() constructor validates required fields\n- [ ] Default http.Client used when not provided\n- [ ] Unit tests for NewClient()","status":"open","priority":0,"issue_type":"task","owner":"mail@oliverjakoubek.de","created_at":"2026-01-28T09:39:06.037277135+01:00","created_by":"Oliver Jakoubek","updated_at":"2026-01-28T09:39:06.037277135+01:00"}
|
||||
{"id":"bookstack-api-9at","title":"Implement Pages Delete","description":"Implement delete operation for Pages.\n\n## Requirements\nFrom PRD Section 5:\n\n| Method | Endpoint | Description |\n|--------|----------|-------------|\n| Delete | DELETE /api/pages/{id} | Delete page |\n\n## API Method\n```go\nfunc (s *PagesService) Delete(ctx context.Context, id int) error\n```\n\n## Technical Details\n- Returns no content on success\n- 404 if page not found\n- May require appropriate permissions\n\n## Acceptance Criteria\n- [ ] Delete() removes page by ID\n- [ ] Returns nil on success\n- [ ] Proper error handling (404 -\u003e ErrNotFound, 403 -\u003e ErrForbidden)\n- [ ] Unit tests with mock server","status":"open","priority":2,"issue_type":"feature","owner":"mail@oliverjakoubek.de","created_at":"2026-01-28T09:39:53.980583894+01:00","created_by":"Oliver Jakoubek","updated_at":"2026-01-28T09:39:53.980583894+01:00"}
|
||||
{"id":"bookstack-api-9xo","title":"Implement BooksService (List, Get)","description":"Implement the BooksService with List and Get operations.\n\n## Requirements\nFrom PRD Section 5:\n\n| Method | Endpoint | Description |\n|--------|----------|-------------|\n| List | GET /api/books | All books |\n| Get | GET /api/books/{id} | Single book |\n\n## API Methods\n```go\ntype BooksService struct {\n client *Client\n}\n\nfunc (s *BooksService) List(ctx context.Context, opts *ListOptions) ([]*Book, error)\nfunc (s *BooksService) Get(ctx context.Context, id int) (*Book, error)\n```\n\n## ListOptions\nSupport pagination parameters:\n- count (max 500)\n- offset\n- sort (+name, -created_at, etc.)\n- filter[field]\n\n## Acceptance Criteria\n- [ ] BooksService struct created\n- [ ] List() returns paginated books\n- [ ] Get() returns single book by ID\n- [ ] Proper error handling (404 -\u003e ErrNotFound)\n- [ ] Unit tests with mock server","status":"open","priority":0,"issue_type":"feature","owner":"mail@oliverjakoubek.de","created_at":"2026-01-28T09:39:30.949469353+01:00","created_by":"Oliver Jakoubek","updated_at":"2026-01-28T09:39:30.949469353+01:00"}
|
||||
{"id":"bookstack-api-adp","title":"Set up Go module and project structure","description":"Initialize the Go module and create the basic project structure as defined in the PRD.\n\n## Requirements\n- Initialize go.mod with module name\n- Create placeholder files for the flat package structure:\n - bookstack.go (Client, Config, NewClient)\n - types.go (data structures)\n - errors.go (error types)\n - http.go (HTTP helpers)\n- Set up .gitignore for Go projects\n\n## Technical Details\n- Go 1.21+ required\n- Zero external dependencies (standard library only)\n- Module should be publishable as standalone Go module\n\n## Acceptance Criteria\n- [ ] go.mod exists with proper module name\n- [ ] Basic file structure created\n- [ ] `go build ./...` succeeds\n- [ ] .gitignore includes Go-specific patterns","status":"in_progress","priority":0,"issue_type":"task","owner":"mail@oliverjakoubek.de","created_at":"2026-01-28T09:39:05.818311718+01:00","created_by":"Oliver Jakoubek","updated_at":"2026-01-30T09:33:48.689831698+01:00"}
|
||||
{"id":"bookstack-api-adp","title":"Set up Go module and project structure","description":"Initialize the Go module and create the basic project structure as defined in the PRD.\n\n## Requirements\n- Initialize go.mod with module name\n- Create placeholder files for the flat package structure:\n - bookstack.go (Client, Config, NewClient)\n - types.go (data structures)\n - errors.go (error types)\n - http.go (HTTP helpers)\n- Set up .gitignore for Go projects\n\n## Technical Details\n- Go 1.21+ required\n- Zero external dependencies (standard library only)\n- Module should be publishable as standalone Go module\n\n## Acceptance Criteria\n- [ ] go.mod exists with proper module name\n- [ ] Basic file structure created\n- [ ] `go build ./...` succeeds\n- [ ] .gitignore includes Go-specific patterns","status":"closed","priority":0,"issue_type":"task","owner":"mail@oliverjakoubek.de","created_at":"2026-01-28T09:39:05.818311718+01:00","created_by":"Oliver Jakoubek","updated_at":"2026-01-30T09:38:24.407997076+01:00","closed_at":"2026-01-30T09:38:24.407997076+01:00","close_reason":"Closed"}
|
||||
{"id":"bookstack-api-bu8","title":"Add GoDoc documentation for all public APIs","description":"Ensure all exported types and functions have proper GoDoc comments.\n\n## Requirements\nFrom PRD Section 8 (Definition of Done):\n- Alle public APIs dokumentiert (GoDoc)\n\n## Documentation Standards\n- Package-level doc comment in bookstack.go\n- All exported types documented\n- All exported functions documented\n- All exported constants/variables documented\n- Include usage examples in doc comments where helpful\n\n## Example\n```go\n// Client is the Bookstack API client. Use NewClient to create a new instance.\n// Client is safe for concurrent use.\ntype Client struct {\n // Books provides access to the Books API.\n Books *BooksService\n ...\n}\n\n// NewClient creates a new Bookstack API client with the provided configuration.\n// BaseURL, TokenID, and TokenSecret are required.\n//\n// Example:\n//\n// client := bookstack.NewClient(bookstack.Config{\n// BaseURL: \"https://docs.example.com\",\n// TokenID: \"token-id\",\n// TokenSecret: \"token-secret\",\n// })\nfunc NewClient(cfg Config) *Client\n```\n\n## Acceptance Criteria\n- [ ] Package documentation present\n- [ ] All exported types documented\n- [ ] All exported functions documented\n- [ ] Documentation renders correctly in pkg.go.dev style\n- [ ] No golint documentation warnings","status":"open","priority":1,"issue_type":"task","owner":"mail@oliverjakoubek.de","created_at":"2026-01-28T09:40:24.752365504+01:00","created_by":"Oliver Jakoubek","updated_at":"2026-01-28T09:40:24.752365504+01:00"}
|
||||
{"id":"bookstack-api-cpg","title":"Implement PagesService (List, Get)","description":"Implement the PagesService with List and Get operations.\n\n## Requirements\nFrom PRD Section 5:\n\n| Method | Endpoint | Description |\n|--------|----------|-------------|\n| List | GET /api/pages | All pages |\n| Get | GET /api/pages/{id} | Single page |\n\n## API Methods\n```go\ntype PagesService struct {\n client *Client\n}\n\nfunc (s *PagesService) List(ctx context.Context, opts *ListOptions) ([]*Page, error)\nfunc (s *PagesService) Get(ctx context.Context, id int) (*Page, error)\n```\n\n## Page Content\nThe Get response includes:\n- HTML content\n- RawHTML content \n- Markdown content (if available)\n\n## Acceptance Criteria\n- [ ] PagesService struct created\n- [ ] List() returns paginated pages\n- [ ] Get() returns single page by ID with content\n- [ ] Proper error handling (404 -\u003e ErrNotFound)\n- [ ] Unit tests with mock server","status":"open","priority":0,"issue_type":"feature","owner":"mail@oliverjakoubek.de","created_at":"2026-01-28T09:39:31.188568742+01:00","created_by":"Oliver Jakoubek","updated_at":"2026-01-28T09:39:31.188568742+01:00"}
|
||||
{"id":"bookstack-api-d2c","title":"Implement Pages Create and Update","description":"Implement write operations for Pages: Create and Update.\n\n## Requirements\nFrom PRD Section 5:\n\n| Method | Endpoint | Description |\n|--------|----------|-------------|\n| Create | POST /api/pages | Create page |\n| Update | PUT /api/pages/{id} | Update page |\n\n## API Methods\n```go\ntype PageCreateRequest struct {\n BookID int `json:\"book_id\"`\n ChapterID int `json:\"chapter_id,omitempty\"`\n Name string `json:\"name\"`\n HTML string `json:\"html,omitempty\"`\n Markdown string `json:\"markdown,omitempty\"`\n}\n\ntype PageUpdateRequest struct {\n Name string `json:\"name,omitempty\"`\n HTML string `json:\"html,omitempty\"`\n Markdown string `json:\"markdown,omitempty\"`\n}\n\nfunc (s *PagesService) Create(ctx context.Context, req *PageCreateRequest) (*Page, error)\nfunc (s *PagesService) Update(ctx context.Context, id int, req *PageUpdateRequest) (*Page, error)\n```\n\n## Workflow (from PRD)\n1. Get page\n2. Edit content locally\n3. Update page\n\n## Acceptance Criteria\n- [ ] PageCreateRequest and PageUpdateRequest structs\n- [ ] Create() creates new page in book or chapter\n- [ ] Update() modifies existing page\n- [ ] Returns updated Page object\n- [ ] Proper error handling (400 -\u003e ErrBadRequest)\n- [ ] Unit tests with mock server","status":"open","priority":1,"issue_type":"feature","owner":"mail@oliverjakoubek.de","created_at":"2026-01-28T09:39:53.734987403+01:00","created_by":"Oliver Jakoubek","updated_at":"2026-01-28T09:39:53.734987403+01:00"}
|
||||
|
|
|
|||
4
.beads/metadata.json
Normal file
4
.beads/metadata.json
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"database": "beads.db",
|
||||
"jsonl_export": "issues.jsonl"
|
||||
}
|
||||
3
.gitattributes
vendored
Normal file
3
.gitattributes
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
|
||||
# Use bd merge for beads JSONL files
|
||||
.beads/issues.jsonl merge=beads
|
||||
40
AGENTS.md
Normal file
40
AGENTS.md
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
# Agent Instructions
|
||||
|
||||
This project uses **bd** (beads) for issue tracking. Run `bd onboard` to get started.
|
||||
|
||||
## Quick Reference
|
||||
|
||||
```bash
|
||||
bd ready # Find available work
|
||||
bd show <id> # View issue details
|
||||
bd update <id> --status in_progress # Claim work
|
||||
bd close <id> # Complete work
|
||||
bd sync # Sync with git
|
||||
```
|
||||
|
||||
## Landing the Plane (Session Completion)
|
||||
|
||||
**When ending a work session**, you MUST complete ALL steps below. Work is NOT complete until `git push` succeeds.
|
||||
|
||||
**MANDATORY WORKFLOW:**
|
||||
|
||||
1. **File issues for remaining work** - Create issues for anything that needs follow-up
|
||||
2. **Run quality gates** (if code changed) - Tests, linters, builds
|
||||
3. **Update issue status** - Close finished work, update in-progress items
|
||||
4. **PUSH TO REMOTE** - This is MANDATORY:
|
||||
```bash
|
||||
git pull --rebase
|
||||
bd sync
|
||||
git push
|
||||
git status # MUST show "up to date with origin"
|
||||
```
|
||||
5. **Clean up** - Clear stashes, prune remote branches
|
||||
6. **Verify** - All changes committed AND pushed
|
||||
7. **Hand off** - Provide context for next session
|
||||
|
||||
**CRITICAL RULES:**
|
||||
- Work is NOT complete until `git push` succeeds
|
||||
- NEVER stop before pushing - that leaves work stranded locally
|
||||
- NEVER say "ready to push when you are" - YOU must push
|
||||
- If push fails, resolve and retry until it succeeds
|
||||
|
||||
102
CLAUDE.md
Normal file
102
CLAUDE.md
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## Project Overview
|
||||
|
||||
A Go library for the Bookstack REST API. Primary consumers are AI agents via CLI (with `--json` flag) and Go developers needing programmatic Bookstack access.
|
||||
|
||||
## Build & Test Commands
|
||||
|
||||
```bash
|
||||
# Build
|
||||
go build ./...
|
||||
|
||||
# Run all tests
|
||||
go test ./...
|
||||
|
||||
# Run single test
|
||||
go test -run TestName ./...
|
||||
|
||||
# Run tests with coverage
|
||||
go test -cover ./...
|
||||
|
||||
# Lint (if golangci-lint is installed)
|
||||
golangci-lint run
|
||||
|
||||
# Format code
|
||||
gofmt -w .
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
### Flat Package Structure
|
||||
|
||||
All code lives in the root package `bookstack`. No subpackages.
|
||||
|
||||
```
|
||||
bookstack.go # Client, Config, NewClient()
|
||||
books.go # BooksService
|
||||
pages.go # PagesService
|
||||
chapters.go # ChaptersService
|
||||
shelves.go # ShelvesService
|
||||
search.go # SearchService
|
||||
types.go # All data structures (Book, Page, Chapter, Shelf, SearchResult)
|
||||
errors.go # Error types (ErrNotFound, ErrUnauthorized, APIError, etc.)
|
||||
http.go # HTTP helpers, request building
|
||||
iterator.go # Pagination iterator using Go 1.23+ iter.Seq
|
||||
```
|
||||
|
||||
### Client Pattern
|
||||
|
||||
Services are attached to the main `Client` struct:
|
||||
|
||||
```go
|
||||
client := bookstack.NewClient(bookstack.Config{
|
||||
BaseURL: "https://docs.example.com",
|
||||
TokenID: os.Getenv("BOOKSTACK_TOKEN_ID"),
|
||||
TokenSecret: os.Getenv("BOOKSTACK_TOKEN_SECRET"),
|
||||
})
|
||||
|
||||
// Access services via client
|
||||
books, err := client.Books.List(ctx, nil)
|
||||
page, err := client.Pages.Get(ctx, 123)
|
||||
```
|
||||
|
||||
### Pagination via Iterators
|
||||
|
||||
Use Go 1.23+ iterator pattern for list operations:
|
||||
|
||||
```go
|
||||
for book, err := range client.Books.ListAll(ctx) {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// process book
|
||||
}
|
||||
```
|
||||
|
||||
### Error Handling
|
||||
|
||||
Use sentinel errors with `errors.Is()`:
|
||||
|
||||
```go
|
||||
if errors.Is(err, bookstack.ErrNotFound) {
|
||||
// handle 404
|
||||
}
|
||||
```
|
||||
|
||||
`APIError` provides detailed information when needed.
|
||||
|
||||
## Key Design Decisions
|
||||
|
||||
- **Zero external dependencies** - Only Go standard library
|
||||
- **Go 1.21+** required
|
||||
- **No caching/rate-limiting** - Caller responsibility
|
||||
- **Token auth** via `Authorization: Token <id>:<secret>` header
|
||||
- **Bookstack hierarchy**: Shelf → Book → Chapter → Page
|
||||
|
||||
## Bookstack API Reference
|
||||
|
||||
- Rate limit: 180 req/min (server configurable)
|
||||
- Pagination: `count` (max 500), `offset`, `sort`, `filter[field]`
|
||||
498
PRD.md
Normal file
498
PRD.md
Normal file
|
|
@ -0,0 +1,498 @@
|
|||
# Product Requirements Document: bookstack-api
|
||||
|
||||
## 1. Projektübersicht
|
||||
|
||||
- **Ziel und Vision:**
|
||||
Eine Go-Library für die Bookstack REST-API, die programmatischen Zugriff auf das Dokumentationssystem ermöglicht. Die Library wird in hqcli integriert und soll veröffentlichungsfähig sein.
|
||||
|
||||
- **Zielgruppe:**
|
||||
- Primär: AI-Agenten (via hqcli mit `--json` Flag)
|
||||
- Sekundär: Go-Entwickler, die Bookstack programmatisch nutzen wollen
|
||||
|
||||
- **Erfolgs-Metriken:**
|
||||
- Vollständige Abdeckung der Kern-API (Books, Pages, Search)
|
||||
- Nutzbar in hqcli für AI-gestützte Dokumentationssuche
|
||||
- Veröffentlichung als eigenständiges Go-Modul
|
||||
|
||||
- **Projektscope:**
|
||||
- **In Scope:** REST-API-Client für Bookstack, Iterator-basierte Pagination, Export-Funktionen
|
||||
- **Out of Scope:** Webhooks, Caching, Admin-Funktionen (Users, Roles)
|
||||
|
||||
## 2. Funktionale Anforderungen
|
||||
|
||||
### Kern-Features
|
||||
|
||||
| Feature | Priorität | Version |
|
||||
|---------|-----------|---------|
|
||||
| Books: List, Get | P0 | v0.1 |
|
||||
| Pages: List, Get | P0 | v0.1 |
|
||||
| Search: All | P0 | v0.1 |
|
||||
| Pages: Export (Markdown, PDF) | P1 | v0.2 |
|
||||
| Chapters: List, Get | P1 | v0.2 |
|
||||
| Shelves: List, Get | P1 | v0.2 |
|
||||
| Pages: Create, Update | P1 | v0.3 |
|
||||
| Pages: Delete | P2 | v0.4 |
|
||||
| Attachments: CRUD | P2 | v0.4 |
|
||||
| Comments: CRUD | P3 | v0.5 |
|
||||
|
||||
### User Stories
|
||||
|
||||
**US1: Dokumentation durchsuchen (AI-Agent)**
|
||||
> Als AI-Agent möchte ich die Bookstack-Dokumentation durchsuchen können, um relevante Seiten für Benutzeranfragen zu finden.
|
||||
|
||||
```bash
|
||||
hqcli docs search "deployment" --json
|
||||
```
|
||||
|
||||
**US2: Seite abrufen**
|
||||
> Als Benutzer möchte ich eine Dokumentationsseite anzeigen können, um deren Inhalt zu lesen.
|
||||
|
||||
```bash
|
||||
hqcli docs page 123
|
||||
hqcli docs page deployment-guide # via Slug
|
||||
```
|
||||
|
||||
**US3: Bücher auflisten**
|
||||
> Als Benutzer möchte ich alle verfügbaren Bücher sehen, um die Dokumentationsstruktur zu verstehen.
|
||||
|
||||
```bash
|
||||
hqcli docs books --json
|
||||
```
|
||||
|
||||
**US4: Seite exportieren**
|
||||
> Als Benutzer möchte ich eine Seite als Markdown oder PDF exportieren können.
|
||||
|
||||
```bash
|
||||
hqcli docs page 123 --export=md > page.md
|
||||
hqcli docs page 123 --export=pdf > page.pdf
|
||||
```
|
||||
|
||||
**US5: Seite im Browser öffnen**
|
||||
> Als Benutzer möchte ich eine Seite schnell im Browser öffnen können.
|
||||
|
||||
```bash
|
||||
hqcli docs open 123
|
||||
```
|
||||
|
||||
### Detaillierte Workflows
|
||||
|
||||
**Workflow: Suche und Anzeige**
|
||||
```
|
||||
1. Benutzer/Agent führt Suche aus
|
||||
2. API gibt Liste von Treffern zurück (ID, Typ, Name, Preview)
|
||||
3. Benutzer/Agent wählt Treffer aus
|
||||
4. Seite wird abgerufen und angezeigt (Markdown oder JSON)
|
||||
```
|
||||
|
||||
**Workflow: Seite bearbeiten (v0.3)**
|
||||
```
|
||||
1. Seite abrufen (Get)
|
||||
2. Inhalt lokal bearbeiten
|
||||
3. Seite aktualisieren (Update)
|
||||
```
|
||||
|
||||
### Feature-Prioritäten
|
||||
|
||||
- **Must-have (v1):** List, Get, Search für Books/Pages
|
||||
- **Should-have (v1):** Export Markdown/PDF, Chapters, Shelves
|
||||
- **Nice-to-have (v2):** Create, Update, Delete
|
||||
- **Future:** Attachments, Comments, Image Gallery
|
||||
|
||||
## 3. Technische Anforderungen
|
||||
|
||||
- **Performance-Ziele:**
|
||||
- API-Calls < 500ms (abhängig von Netzwerk)
|
||||
- Iterator verarbeitet 10.000+ Einträge ohne Memory-Probleme
|
||||
|
||||
- **Concurrent User-Kapazität:**
|
||||
Nicht zutreffend (Library, kein Server)
|
||||
|
||||
- **Real-time Features:**
|
||||
Nicht zutreffend
|
||||
|
||||
- **Sicherheitsstandards:**
|
||||
- Token-basierte Authentifizierung (Token ID + Secret)
|
||||
- Keine Speicherung von Credentials (Aufrufer-Verantwortung)
|
||||
|
||||
- **Compliance-Vorgaben:**
|
||||
Keine speziellen
|
||||
|
||||
- **Plattform-Support:**
|
||||
- Go 1.21+
|
||||
- Linux, macOS, Windows
|
||||
|
||||
## 4. Datenarchitektur
|
||||
|
||||
*Nicht zutreffend – keine eigene Datenhaltung*
|
||||
|
||||
### Bookstack-Hierarchie (extern)
|
||||
|
||||
```
|
||||
Shelf (Regal)
|
||||
└── Book (Buch)
|
||||
├── Chapter (Kapitel)
|
||||
│ └── Page (Seite)
|
||||
└── Page (Seite)
|
||||
```
|
||||
|
||||
### Datenstrukturen
|
||||
|
||||
```go
|
||||
// Book repräsentiert ein Bookstack-Buch
|
||||
type Book struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Slug string `json:"slug"`
|
||||
Description string `json:"description"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
CreatedBy int `json:"created_by"`
|
||||
UpdatedBy int `json:"updated_by"`
|
||||
}
|
||||
|
||||
// Page repräsentiert eine Bookstack-Seite
|
||||
type Page struct {
|
||||
ID int `json:"id"`
|
||||
BookID int `json:"book_id"`
|
||||
ChapterID int `json:"chapter_id"`
|
||||
Name string `json:"name"`
|
||||
Slug string `json:"slug"`
|
||||
HTML string `json:"html"`
|
||||
RawHTML string `json:"raw_html"`
|
||||
Markdown string `json:"markdown"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
// Chapter repräsentiert ein Bookstack-Kapitel
|
||||
type Chapter struct {
|
||||
ID int `json:"id"`
|
||||
BookID int `json:"book_id"`
|
||||
Name string `json:"name"`
|
||||
Slug string `json:"slug"`
|
||||
Description string `json:"description"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
// Shelf repräsentiert ein Bookstack-Regal
|
||||
type Shelf struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Slug string `json:"slug"`
|
||||
Description string `json:"description"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
// SearchResult repräsentiert ein Suchergebnis
|
||||
type SearchResult struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Slug string `json:"slug"`
|
||||
Type string `json:"type"` // page, chapter, book, bookshelf
|
||||
URL string `json:"url"`
|
||||
Preview string `json:"preview"`
|
||||
}
|
||||
```
|
||||
|
||||
## 5. API & Interface-Spezifikation
|
||||
|
||||
### Client-Initialisierung
|
||||
|
||||
```go
|
||||
type Config struct {
|
||||
BaseURL string // z.B. "https://docs.jakoubek.net"
|
||||
TokenID string // API Token ID
|
||||
TokenSecret string // API Token Secret
|
||||
HTTPClient *http.Client // optional, für Tests/Mocking
|
||||
}
|
||||
|
||||
func NewClient(cfg Config) *Client
|
||||
```
|
||||
|
||||
**Beispiel:**
|
||||
```go
|
||||
client := bookstack.NewClient(bookstack.Config{
|
||||
BaseURL: "https://docs.jakoubek.net",
|
||||
TokenID: os.Getenv("BOOKSTACK_TOKEN_ID"),
|
||||
TokenSecret: os.Getenv("BOOKSTACK_TOKEN_SECRET"),
|
||||
})
|
||||
```
|
||||
|
||||
### Service-Struktur
|
||||
|
||||
```go
|
||||
type Client struct {
|
||||
Books *BooksService
|
||||
Pages *PagesService
|
||||
Chapters *ChaptersService
|
||||
Shelves *ShelvesService
|
||||
Search *SearchService
|
||||
}
|
||||
```
|
||||
|
||||
### REST-Endpoints (Bookstack API)
|
||||
|
||||
| Service | Methode | Endpoint | Beschreibung |
|
||||
|---------|---------|----------|--------------|
|
||||
| Books | List | GET /api/books | Alle Bücher |
|
||||
| Books | Get | GET /api/books/{id} | Einzelnes Buch |
|
||||
| Pages | List | GET /api/pages | Alle Seiten |
|
||||
| Pages | Get | GET /api/pages/{id} | Einzelne Seite |
|
||||
| Pages | Create | POST /api/pages | Seite erstellen |
|
||||
| Pages | Update | PUT /api/pages/{id} | Seite aktualisieren |
|
||||
| Pages | Delete | DELETE /api/pages/{id} | Seite löschen |
|
||||
| Pages | ExportMD | GET /api/pages/{id}/export/markdown | Markdown-Export |
|
||||
| Pages | ExportPDF | GET /api/pages/{id}/export/pdf | PDF-Export |
|
||||
| Chapters | List | GET /api/chapters | Alle Kapitel |
|
||||
| Chapters | Get | GET /api/chapters/{id} | Einzelnes Kapitel |
|
||||
| Shelves | List | GET /api/shelves | Alle Regale |
|
||||
| Shelves | Get | GET /api/shelves/{id} | Einzelnes Regal |
|
||||
| Search | All | GET /api/search?query=... | Volltextsuche |
|
||||
|
||||
### Authentifizierung
|
||||
|
||||
```
|
||||
Authorization: Token <token_id>:<token_secret>
|
||||
```
|
||||
|
||||
### Pagination (Iterator-Pattern)
|
||||
|
||||
```go
|
||||
// ListAll gibt einen Iterator über alle Einträge zurück
|
||||
// Nutzt Go 1.23+ iter.Seq oder eigene Implementation
|
||||
func (s *BooksService) ListAll(ctx context.Context) iter.Seq2[*Book, error]
|
||||
|
||||
// Nutzung:
|
||||
for book, err := range client.Books.ListAll(ctx) {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println(book.Name)
|
||||
}
|
||||
```
|
||||
|
||||
**Begründung:** Iterator-Pattern ist Go-idiomatisch (ab 1.23), Memory-effizient und ermöglicht frühen Abbruch.
|
||||
|
||||
### Rate Limiting
|
||||
|
||||
- Bookstack: 180 Requests/Minute (default)
|
||||
- **Keine Library-interne Behandlung** – Aufrufer muss Rate-Limiting selbst handhaben
|
||||
- Bei 429-Response: `ErrRateLimited` zurückgeben
|
||||
|
||||
## 6. Benutzeroberfläche
|
||||
|
||||
*Nicht zutreffend – Library ohne UI*
|
||||
|
||||
### hqcli-Integration (separates Projekt)
|
||||
|
||||
```bash
|
||||
# Bücher auflisten
|
||||
hqcli docs books
|
||||
hqcli docs books --json
|
||||
|
||||
# Seiten eines Buchs
|
||||
hqcli docs pages --book=<id|slug>
|
||||
|
||||
# Seite anzeigen
|
||||
hqcli docs page <id|slug>
|
||||
hqcli docs page <id> --json
|
||||
|
||||
# Seite exportieren
|
||||
hqcli docs page <id> --export=md
|
||||
hqcli docs page <id> --export=pdf
|
||||
|
||||
# Suche
|
||||
hqcli docs search "query"
|
||||
hqcli docs search "query" --json
|
||||
|
||||
# Im Browser öffnen
|
||||
hqcli docs open <id|slug>
|
||||
```
|
||||
|
||||
**Output-Priorität:** `--json` für AI-Agenten ist Hauptanwendungsfall
|
||||
|
||||
## 7. Nicht-funktionale Anforderungen
|
||||
|
||||
- **Verfügbarkeit:**
|
||||
Nicht zutreffend (Library)
|
||||
|
||||
- **Dependencies:**
|
||||
Nur Go-Standardbibliothek (net/http, encoding/json, etc.)
|
||||
|
||||
- **Backward Compatibility:**
|
||||
Semantic Versioning (v0.x während Entwicklung, v1.x nach Stabilisierung)
|
||||
|
||||
- **Logging-Strategie:**
|
||||
Keine eigene Logging – Fehler werden als `error` zurückgegeben
|
||||
|
||||
- **Konfiguration:**
|
||||
Via `Config`-Struct bei Client-Erstellung
|
||||
|
||||
## 8. Qualitätssicherung
|
||||
|
||||
### Definition of Done
|
||||
|
||||
- [ ] Alle public APIs dokumentiert (GoDoc)
|
||||
- [ ] Unit-Tests für alle Services (≥80% Coverage)
|
||||
- [ ] Integration-Tests gegen Mock-Server
|
||||
- [ ] Beispiel-Code in examples/
|
||||
- [ ] README mit Quick-Start
|
||||
|
||||
### Test-Anforderungen
|
||||
|
||||
```go
|
||||
// Unit-Tests mit Mock-HTTP-Client
|
||||
func TestBooksService_List(t *testing.T) {
|
||||
server := httptest.NewServer(...)
|
||||
client := bookstack.NewClient(bookstack.Config{
|
||||
BaseURL: server.URL,
|
||||
TokenID: "test",
|
||||
TokenSecret: "test",
|
||||
})
|
||||
|
||||
books, err := client.Books.List(ctx, nil)
|
||||
// assertions...
|
||||
}
|
||||
```
|
||||
|
||||
### Launch-Kriterien v1.0
|
||||
|
||||
- [ ] Books, Pages, Search vollständig implementiert
|
||||
- [ ] Export (Markdown, PDF) funktioniert
|
||||
- [ ] Dokumentation vollständig
|
||||
- [ ] Keine bekannten Bugs
|
||||
- [ ] hqcli-Integration getestet
|
||||
|
||||
## 9. Technische Implementierungshinweise
|
||||
|
||||
### Go-Projektstruktur
|
||||
|
||||
```
|
||||
bookstack-api/
|
||||
├── bookstack.go # Client, Config, NewClient()
|
||||
├── books.go # BooksService
|
||||
├── pages.go # PagesService
|
||||
├── chapters.go # ChaptersService
|
||||
├── shelves.go # ShelvesService
|
||||
├── search.go # SearchService
|
||||
├── types.go # Alle Datenstrukturen
|
||||
├── errors.go # Error-Typen
|
||||
├── http.go # HTTP-Helfer, Request-Building
|
||||
├── iterator.go # Pagination-Iterator
|
||||
├── bookstack_test.go # Tests
|
||||
├── README.md
|
||||
├── go.mod
|
||||
├── go.sum
|
||||
└── examples/
|
||||
└── basic/
|
||||
└── main.go
|
||||
```
|
||||
|
||||
### Error-Handling-Strategie
|
||||
|
||||
```go
|
||||
// Definierte Error-Typen für häufige Fälle
|
||||
var (
|
||||
ErrNotFound = errors.New("bookstack: resource not found")
|
||||
ErrUnauthorized = errors.New("bookstack: unauthorized")
|
||||
ErrForbidden = errors.New("bookstack: forbidden")
|
||||
ErrRateLimited = errors.New("bookstack: rate limited")
|
||||
ErrBadRequest = errors.New("bookstack: bad request")
|
||||
)
|
||||
|
||||
// APIError für detaillierte Fehlerinformationen
|
||||
type APIError struct {
|
||||
StatusCode int
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Body []byte // Original Response Body
|
||||
}
|
||||
|
||||
func (e *APIError) Error() string {
|
||||
return fmt.Sprintf("bookstack: API error %d: %s", e.StatusCode, e.Message)
|
||||
}
|
||||
|
||||
func (e *APIError) Is(target error) bool {
|
||||
switch target {
|
||||
case ErrNotFound:
|
||||
return e.StatusCode == 404
|
||||
case ErrUnauthorized:
|
||||
return e.StatusCode == 401
|
||||
case ErrForbidden:
|
||||
return e.StatusCode == 403
|
||||
case ErrRateLimited:
|
||||
return e.StatusCode == 429
|
||||
case ErrBadRequest:
|
||||
return e.StatusCode == 400
|
||||
}
|
||||
return false
|
||||
}
|
||||
```
|
||||
|
||||
**Begründung:** `errors.Is()` ermöglicht einfache Fehlerprüfung, `APIError` bietet Details wenn nötig.
|
||||
|
||||
### HTTP-Wrapper
|
||||
|
||||
```go
|
||||
// Interner HTTP-Helfer
|
||||
func (c *Client) do(ctx context.Context, method, path string, body, result any) error {
|
||||
// 1. Request bauen
|
||||
// 2. Auth-Header setzen
|
||||
// 3. Request ausführen
|
||||
// 4. Response prüfen
|
||||
// 5. Bei Fehler: APIError zurückgeben
|
||||
// 6. Bei Erfolg: JSON in result unmarshalen
|
||||
}
|
||||
```
|
||||
|
||||
### Entwicklungs-Prioritäten
|
||||
|
||||
1. **Phase 1 (v0.1):** Foundation
|
||||
- Client-Setup, Auth, HTTP-Wrapper
|
||||
- Books.List, Books.Get
|
||||
- Pages.List, Pages.Get
|
||||
- Error-Handling
|
||||
|
||||
2. **Phase 2 (v0.2):** Core Features
|
||||
- Search.All
|
||||
- Pages.ExportMarkdown, Pages.ExportPDF
|
||||
- Iterator für Pagination
|
||||
- Chapters, Shelves
|
||||
|
||||
3. **Phase 3 (v0.3):** Write Operations
|
||||
- Pages.Create
|
||||
- Pages.Update
|
||||
|
||||
4. **Phase 4 (v1.0):** Release
|
||||
- Dokumentation
|
||||
- Beispiele
|
||||
- CI/CD
|
||||
- Veröffentlichung
|
||||
|
||||
### Potenzielle Risiken
|
||||
|
||||
| Risiko | Wahrscheinlichkeit | Mitigation |
|
||||
|--------|-------------------|------------|
|
||||
| API-Änderungen in Bookstack | Niedrig | Semantic Versioning, Tests |
|
||||
| Rate-Limiting-Probleme | Mittel | Dokumentation für Aufrufer |
|
||||
| Große PDF-Exports | Mittel | Streaming statt Buffer |
|
||||
|
||||
---
|
||||
|
||||
## Anhang: Bookstack API-Referenz
|
||||
|
||||
- **Basis-URL:** https://docs.jakoubek.net/api
|
||||
- **Dokumentation:** https://docs.jakoubek.net/api/docs
|
||||
- **Beispiele:** https://codeberg.org/bookstack/api-scripts
|
||||
- **Rate Limit:** 180 req/min (konfigurierbar serverseitig)
|
||||
|
||||
### Pagination-Parameter
|
||||
|
||||
| Parameter | Beschreibung | Default |
|
||||
|-----------|--------------|---------|
|
||||
| count | Anzahl Ergebnisse | 100 (max 500) |
|
||||
| offset | Start-Position | 0 |
|
||||
| sort | Sortierung (+name, -created_at) | - |
|
||||
| filter[field] | Filter (eq, ne, gt, lt, like) | - |
|
||||
3
go.mod
Normal file
3
go.mod
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
module code.beautifulmachines.dev/jakoubek/bookstack-api
|
||||
|
||||
go 1.25.6
|
||||
Loading…
Add table
Add a link
Reference in a new issue