hanghang zhang 58e7a76e1a feat(calendar): GET /agent/status — read-only status query for plugin gate
Previously only POST /agent/status existed (for state transitions).
Fabric.OpenclawPlugin's triage on-call gate needs to check whether
the on-duty agent is currently on_call without flipping their state —
so the wake decision is read-only. GET returns {agent_id, status},
404 if unknown.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 22:34:10 +01:00

HarborForge Backend

The core REST API for HarborForge — an Agent/人类协同任务管理平台 (Agent/Human collaborative task-management platform).

Part of the HarborForge platform.

  • Role: core REST API — users, projects, tasks, milestones, proposals, RBAC, webhooks, worklogs, notifications, monitor telemetry.
  • Stack: Python 3.11 · FastAPI · SQLAlchemy · MySQL
  • Port: 8000

The service reads its database configuration from the AbstractWizard config volume (falling back to env/defaults) and authenticates requests with JWT (HS256) signed by SECRET_KEY.

Run / Build

Docker

docker build -t harborforge-backend .
docker run -p 8000:8000 \
  -e SECRET_KEY="$(openssl rand -hex 32)" \
  -v /path/to/config:/config \
  harborforge-backend

Local (uvicorn)

pip install -r requirements.txt
export SECRET_KEY="$(openssl rand -hex 32)"
uvicorn app.main:app --host 0.0.0.0 --port 8000

On startup the app creates/migrates the schema, runs AbstractWizard initialization (admin user, default project, default roles), and starts a background monitor-polling thread.

Configuration

Environment variables (also loadable from a .env file):

Variable Default Description
SECRET_KEY (none — must be set) JWT signing key (HS256). The server refuses to start with a weak/default/short value.
DATABASE_URL mysql+pymysql://harborforge:harborforge_pass@mysql:3306/harborforge Fallback DB URL when the wizard config volume is absent.
ALGORITHM HS256 JWT algorithm.
ACCESS_TOKEN_EXPIRE_MINUTES 30 Access-token lifetime.
LOG_LEVEL INFO Log level.
CONFIG_DIR /config AbstractWizard config volume directory.
CONFIG_FILE harborforge.json Config file name within CONFIG_DIR.

Database resolution order: wizard config volume ($CONFIG_DIR/$CONFIG_FILEdatabase block) → DATABASE_URL env → built-in default.

Security

The current code enforces the following security posture. These are operational requirements, not optional hardening.

Mandatory strong SECRET_KEY

app/core/config.py validates SECRET_KEY at import time and raises and refuses to start if the value is empty, shorter than 32 characters, or a known default/placeholder (e.g. change-me-in-production, secret, changeme). Operators must provide a strong random key:

openssl rand -hex 32

A weak signing key allows JWT forgery and full authentication bypass, so this check is intentionally fatal.

API-key management is admin-only and masked

The /api-keys endpoints (POST, GET, DELETE /api-keys/{id}) all require a global admin (require_admin). Listing never returns the full secret — keys are masked to a short prefix/suffix (e.g. abc123…9f). The full key is only returned once, on creation.

Webhooks router is admin-only with SSRF protection

The entire /webhooks router is mounted with dependencies=[Depends(require_admin)], so every webhook endpoint (create/list/get/update/delete/logs/retry) requires a global admin. Webhook delivery (app/services/webhook.py) validates the target URL before sending:

  • Only http/https schemes are allowed.
  • The host is DNS-resolved and every resolved address is rejected if it is private, loopback, link-local, multicast, reserved, or unspecified (SSRF protection).
  • HTTP redirects are disabled (follow_redirects=False).

Project role hierarchy enforcement

check_project_role in app/api/rbac.py enforces a real, ordered role hierarchy rather than a flat membership check:

guest(0) < viewer(1) < member(2) < dev(3) < mgr(4) < admin(5)

A caller below the required rank is denied with 403, and any unknown role on either side is denied by default. Global admins bypass project-level checks.

Authentication on previously open endpoints

The following endpoints now require an authenticated caller (JWT bearer token or X-API-Key) and enforce ownership/permission:

  • DELETE /milestones/{id} — requires milestone-edit permission.
  • POST /worklogs — worklogs are always attributed to the caller; only admins may log time for another user.
  • DELETE /worklogs/{id} — caller-scoped; non-admins cannot delete another user's worklog.
  • POST /tasks/{task_code}/assign and POST /tasks/batch/assign.
  • GET /activity.
  • GET /export/tasks.

Authentication

  • POST /auth/token — OAuth2 password grant; returns a JWT bearer token.
  • Authenticated requests send Authorization: Bearer <token> or X-API-Key: <key> (API keys map to a user and are created by admins).
  • GET /auth/me — current user.
  • GET /auth/me/permissions, GET /auth/me/apikey-permissions — permission introspection.

Key API Areas

Area Prefix / Routes Notes
Auth /auth/* token, current user, permission introspection
Users /users registration, list/detail/update (list & mutate are admin-only)
Projects /projects CRUD, members (/projects/{id}/members), worklog summary
Project members /projects/{id}/members add/list/remove with role
Milestones /projects/{id}/milestones, /milestones/{id} CRUD, items, progress
Milestone actions preflight / freeze / start / close lifecycle transitions
Tasks /tasks CRUD, transition, take, assign, batch transition/assign, tags, search
Comments /comments, /tasks/{id}/comments CRUD
Proposals /projects/{code}/proposals propose / accept / reject / reopen (legacy /proposes)
Essentials proposal essentials feature/improvement/refactor items
Meetings /meetings create/list/detail/update/delete/attend
Roles & RBAC /roles roles, permissions, role-permission assignment
Webhooks /webhooks admin-only; CRUD, logs, retry (SSRF-guarded delivery)
API keys /api-keys admin-only; create/list (masked)/revoke
Worklogs /worklogs, /tasks/{id}/worklogs, /users/{id}/worklogs time tracking & summaries
Notifications /notifications list, unread count, mark read / read-all
Activity /activity activity log (authenticated)
Export /export/tasks CSV export (authenticated)
Calendar /calendar scheduling / time slots
Monitor /monitor public overview, admin providers/servers, heartbeat telemetry
Dashboard /dashboard/stats aggregate statistics
System /health, /version, /config/status health, version, init status

Task Types

Type 用途
issue 普通任务
story 用户故事
test 测试用例
resolution 决议案Agent 僵局提交)

CLI

The legacy Python CLI (cli.py) has been retired. Use the Go-based hf CLI instead.

See HarborForge.Cli for installation and usage.

Tech Stack

  • Python 3.11 + FastAPI
  • SQLAlchemy + MySQL (auto schema create/migrate on startup)
  • JWT (python-jose, HS256) + bcrypt password hashing
  • Docker
Description
HarborForge Backend - FastAPI
Readme 1.8 MiB
Languages
Python 99.7%
Dockerfile 0.2%