Add architecture, deployment, and development documentation for b0esche.cloud

This commit is contained in:
Leon Bösche
2026-01-13 19:34:46 +01:00
parent 294b28d1a8
commit 804e994e76
5 changed files with 2138 additions and 1 deletions

596
docs/API.md Normal file
View File

@@ -0,0 +1,596 @@
# b0esche.cloud API Reference
Base URL: `https://go.b0esche.cloud`
## Authentication
All authenticated endpoints require a JWT token in the Authorization header:
```
Authorization: Bearer <token>
```
---
## Health Check
### GET /health
Check if the API is running.
**Response:**
```json
{
"status": "ok",
"timestamp": "2026-01-13T19:00:00Z"
}
```
---
## Authentication Endpoints
### Passkey Registration
#### POST /auth/passkey/register/start
Start passkey registration for a new user.
**Request Body:**
```json
{
"username": "johndoe"
}
```
**Response:**
```json
{
"publicKey": {
"challenge": "base64-encoded-challenge",
"rp": {
"name": "b0esche.cloud",
"id": "www.b0esche.cloud"
},
"user": {
"id": "base64-user-id",
"name": "johndoe",
"displayName": "johndoe"
},
"pubKeyCredParams": [...],
"timeout": 300000,
"attestation": "none"
}
}
```
#### POST /auth/passkey/register/verify
Complete passkey registration.
**Request Body:**
```json
{
"username": "johndoe",
"credential": {
"id": "credential-id",
"rawId": "base64-raw-id",
"type": "public-key",
"response": {
"clientDataJSON": "base64-client-data",
"attestationObject": "base64-attestation"
}
}
}
```
**Response:**
```json
{
"user": {
"id": "uuid",
"username": "johndoe"
},
"token": "jwt-token"
}
```
### Passkey Login
#### POST /auth/passkey/login/start
Start passkey authentication.
**Request Body:**
```json
{
"username": "johndoe"
}
```
**Response:**
```json
{
"publicKey": {
"challenge": "base64-challenge",
"timeout": 300000,
"rpId": "www.b0esche.cloud",
"allowCredentials": [...]
}
}
```
#### POST /auth/passkey/login/verify
Complete passkey authentication.
**Request Body:**
```json
{
"username": "johndoe",
"credential": {
"id": "credential-id",
"rawId": "base64-raw-id",
"type": "public-key",
"response": {
"clientDataJSON": "base64-client-data",
"authenticatorData": "base64-auth-data",
"signature": "base64-signature"
}
}
}
```
**Response:**
```json
{
"user": {
"id": "uuid",
"username": "johndoe",
"role": "user"
},
"token": "jwt-token"
}
```
### Device Management
#### GET /auth/passkey/devices
List user's registered passkeys.
**Response:**
```json
{
"devices": [
{
"id": "uuid",
"credentialId": "credential-id",
"deviceLabel": "MacBook Pro",
"createdAt": "2026-01-01T00:00:00Z",
"lastUsedAt": "2026-01-13T19:00:00Z",
"backupEligible": true
}
]
}
```
#### POST /auth/passkey/devices/add
Add a new passkey to existing account.
#### DELETE /auth/passkey/devices/{passkeyId}
Remove a passkey from account.
### Recovery Codes
#### POST /auth/recovery/codes/generate
Generate new recovery codes (invalidates old ones).
**Response:**
```json
{
"codes": [
"XXXX-XXXX-XXXX",
"YYYY-YYYY-YYYY",
...
],
"expiresAt": "2027-01-13T00:00:00Z"
}
```
#### POST /auth/recovery/codes/use
Use a recovery code to authenticate.
**Request Body:**
```json
{
"username": "johndoe",
"code": "XXXX-XXXX-XXXX"
}
```
### Password (Optional Fallback)
#### POST /auth/password/add
Add password to account.
**Request Body:**
```json
{
"password": "secure-password"
}
```
#### DELETE /auth/password/remove
Remove password from account.
---
## User Endpoints
### GET /api/me
Get current user profile.
**Response:**
```json
{
"id": "uuid",
"username": "johndoe",
"email": "john@example.com",
"displayName": "John Doe",
"role": "user",
"createdAt": "2026-01-01T00:00:00Z"
}
```
### PATCH /api/me
Update user profile.
**Request Body:**
```json
{
"displayName": "John D.",
"email": "newemail@example.com"
}
```
---
## Organization Endpoints
### GET /api/organizations
List user's organizations.
**Response:**
```json
{
"organizations": [
{
"id": "uuid",
"name": "My Team",
"slug": "my-team",
"role": "owner",
"memberCount": 5,
"createdAt": "2026-01-01T00:00:00Z"
}
]
}
```
### POST /api/organizations
Create a new organization.
**Request Body:**
```json
{
"name": "My New Team",
"slug": "my-new-team"
}
```
### GET /api/organizations/{orgId}
Get organization details.
### PATCH /api/organizations/{orgId}
Update organization.
### DELETE /api/organizations/{orgId}
Delete organization (owner only).
### GET /api/organizations/{orgId}/members
List organization members.
**Response:**
```json
{
"members": [
{
"id": "uuid",
"userId": "user-uuid",
"username": "johndoe",
"displayName": "John Doe",
"role": "owner",
"joinedAt": "2026-01-01T00:00:00Z"
}
]
}
```
### POST /api/organizations/{orgId}/members
Add member to organization.
**Request Body:**
```json
{
"userId": "user-uuid",
"role": "member"
}
```
### PATCH /api/organizations/{orgId}/members/{memberId}
Update member role.
### DELETE /api/organizations/{orgId}/members/{memberId}
Remove member from organization.
---
## File Endpoints
### GET /api/files
List files in a directory.
**Query Parameters:**
| Parameter | Type | Description |
|-----------|------|-------------|
| `path` | string | Directory path (default: `/`) |
| `orgId` | string | Organization ID (optional) |
**Response:**
```json
{
"files": [
{
"id": "uuid",
"name": "document.pdf",
"path": "/documents/document.pdf",
"type": "file",
"mimeType": "application/pdf",
"size": 1048576,
"createdAt": "2026-01-01T00:00:00Z",
"modifiedAt": "2026-01-13T19:00:00Z"
},
{
"id": "uuid",
"name": "photos",
"path": "/photos",
"type": "folder",
"createdAt": "2026-01-01T00:00:00Z"
}
]
}
```
### POST /api/files/upload
Upload a file.
**Request:** `multipart/form-data`
| Field | Type | Description |
|-------|------|-------------|
| `file` | file | The file to upload |
| `path` | string | Destination path |
| `orgId` | string | Organization ID (optional) |
**Response:**
```json
{
"file": {
"id": "uuid",
"name": "uploaded-file.pdf",
"path": "/documents/uploaded-file.pdf",
"size": 1048576
}
}
```
### GET /api/files/download
Download a file.
**Query Parameters:**
| Parameter | Type | Description |
|-----------|------|-------------|
| `path` | string | File path |
| `orgId` | string | Organization ID (optional) |
**Response:** File binary with appropriate Content-Type header.
### POST /api/files/folder
Create a folder.
**Request Body:**
```json
{
"path": "/new-folder",
"orgId": "org-uuid"
}
```
### DELETE /api/files
Delete a file or folder.
**Query Parameters:**
| Parameter | Type | Description |
|-----------|------|-------------|
| `path` | string | Path to delete |
| `orgId` | string | Organization ID (optional) |
### POST /api/files/move
Move/rename a file or folder.
**Request Body:**
```json
{
"sourcePath": "/old-name.pdf",
"destinationPath": "/new-name.pdf",
"orgId": "org-uuid"
}
```
### POST /api/files/copy
Copy a file or folder.
**Request Body:**
```json
{
"sourcePath": "/original.pdf",
"destinationPath": "/copy.pdf",
"orgId": "org-uuid"
}
```
---
## Admin Endpoints
*Requires admin or superadmin role.*
### GET /api/admin/users
List all users.
**Query Parameters:**
| Parameter | Type | Description |
|-----------|------|-------------|
| `page` | int | Page number (default: 1) |
| `limit` | int | Items per page (default: 50) |
| `search` | string | Search by username/email |
### GET /api/admin/users/{userId}
Get user details.
### PATCH /api/admin/users/{userId}
Update user (role, status).
### DELETE /api/admin/users/{userId}
Delete user account.
### Admin Invitations
#### GET /auth/admin/invitations
List admin invitations.
#### POST /auth/admin/invitations
Create admin invitation.
**Request Body:**
```json
{
"username": "newadmin",
"roleId": "admin-role-uuid",
"expiresIn": 86400
}
```
**Response:**
```json
{
"invitation": {
"id": "uuid",
"token": "invite-token",
"expiresAt": "2026-01-14T19:00:00Z"
}
}
```
#### POST /auth/admin/invitations/{token}/accept
Accept an admin invitation.
#### DELETE /auth/admin/invitations/{token}
Revoke an invitation.
---
## Activity Endpoints
### GET /api/activities
Get activity log.
**Query Parameters:**
| Parameter | Type | Description |
|-----------|------|-------------|
| `page` | int | Page number |
| `limit` | int | Items per page |
| `orgId` | string | Filter by organization |
| `userId` | string | Filter by user |
| `action` | string | Filter by action type |
**Response:**
```json
{
"activities": [
{
"id": "uuid",
"userId": "user-uuid",
"username": "johndoe",
"action": "file.upload",
"resourceType": "file",
"resourceId": "/documents/report.pdf",
"metadata": {
"size": 1048576
},
"createdAt": "2026-01-13T19:00:00Z"
}
],
"pagination": {
"page": 1,
"limit": 50,
"total": 150
}
}
```
---
## Error Responses
All errors follow this format:
```json
{
"error": {
"code": "ERROR_CODE",
"message": "Human-readable error message",
"details": {}
}
}
```
### Common Error Codes
| Code | HTTP Status | Description |
|------|-------------|-------------|
| `UNAUTHORIZED` | 401 | Missing or invalid token |
| `FORBIDDEN` | 403 | Insufficient permissions |
| `NOT_FOUND` | 404 | Resource not found |
| `VALIDATION_ERROR` | 400 | Invalid request data |
| `CONFLICT` | 409 | Resource already exists |
| `INTERNAL_ERROR` | 500 | Server error |
---
## Rate Limiting
- **Authentication endpoints**: 10 requests/minute
- **API endpoints**: 100 requests/minute
- **File uploads**: 50 requests/hour
Rate limit headers:
```
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1705172400
```
---
## Webhooks (Future)
Planned webhook events:
- `user.created`
- `user.deleted`
- `file.uploaded`
- `file.deleted`
- `org.member.added`
- `org.member.removed`