445 lines
13 KiB
YAML
445 lines
13 KiB
YAML
openapi: 3.0.3
|
|
info:
|
|
title: Tingz Deployer API
|
|
description: A secure, lightweight HTTP service for deploying static sites. The service receives tarball artifacts, validates and publishes them under a per-user directory structure for docs.yigid.dev. Designed for CI/CD automation with GitHub Actions, GitLab CI, etc.
|
|
version: 1.0.0
|
|
contact:
|
|
name: Yigid BALABAN
|
|
email: hey@yigid.dev
|
|
url: https://yigid.dev/
|
|
license:
|
|
name: AGPL-3.0-only
|
|
url: https://opensource.org/license/agpl-v3
|
|
servers:
|
|
- url: https://docs.yigid.dev
|
|
description: Production server
|
|
- url: http://localhost:8080
|
|
description: Development server
|
|
paths:
|
|
/api/v1/auth:
|
|
post:
|
|
tags:
|
|
- Authentication
|
|
summary: Create or reroll user token
|
|
description: Creates a new user or generates a new token for an existing user. Admin only endpoint.
|
|
operationId: createOrRerollUser
|
|
security:
|
|
- AdminAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/CreateUserRequest'
|
|
example:
|
|
username: alice
|
|
responses:
|
|
'200':
|
|
description: User created or token rerolled successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/AuthResponse'
|
|
example:
|
|
status: ok
|
|
token: 82lz0BVOWtV4uVj9DBZBuKMeyVDwidL2
|
|
'400':
|
|
description: Invalid request body or username format
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
examples:
|
|
invalidBody:
|
|
summary: Invalid request body
|
|
value:
|
|
status: error
|
|
error: invalid request body
|
|
invalidUsername:
|
|
summary: Invalid username format
|
|
value:
|
|
status: error
|
|
error: invalid username format
|
|
'401':
|
|
description: Unauthorized - Invalid admin token
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
example:
|
|
status: error
|
|
error: invalid admin token
|
|
'500':
|
|
description: Internal server error
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
example:
|
|
status: error
|
|
error: failed to create user
|
|
delete:
|
|
tags:
|
|
- Authentication
|
|
summary: Delete user
|
|
description: Deletes a user and optionally their files. Admin only endpoint.
|
|
operationId: deleteUser
|
|
security:
|
|
- AdminAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/DeleteUserRequest'
|
|
examples:
|
|
persistFiles:
|
|
summary: Delete user but keep files
|
|
value:
|
|
username: alice
|
|
files: persist
|
|
deleteFiles:
|
|
summary: Delete user and all files
|
|
value:
|
|
username: alice
|
|
files: delete
|
|
responses:
|
|
'200':
|
|
description: User deleted successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/SuccessResponse'
|
|
example:
|
|
status: ok
|
|
'400':
|
|
description: Invalid request body, username format, or files parameter
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
examples:
|
|
invalidBody:
|
|
summary: Invalid request body
|
|
value:
|
|
status: error
|
|
error: invalid request body
|
|
invalidUsername:
|
|
summary: Invalid username format
|
|
value:
|
|
status: error
|
|
error: invalid username format
|
|
invalidFiles:
|
|
summary: Invalid files parameter
|
|
value:
|
|
status: error
|
|
error: files must be 'persist' or 'delete'
|
|
'401':
|
|
description: Unauthorized - Invalid admin token
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
example:
|
|
status: error
|
|
error: invalid admin token
|
|
'500':
|
|
description: Internal server error
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
example:
|
|
status: error
|
|
error: user not found
|
|
/api/v1/deploy:
|
|
post:
|
|
tags:
|
|
- Deployment
|
|
summary: Deploy static site
|
|
description: Uploads and deploys a static site tarball. Creates a new release and atomically updates the live site via symlink swap.
|
|
operationId: deploySite
|
|
security:
|
|
- UserAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
multipart/form-data:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- project
|
|
- file
|
|
properties:
|
|
project:
|
|
type: string
|
|
description: Project name (must match username validation pattern)
|
|
pattern: ^[a-z0-9]([a-z0-9_-]{0,62}[a-z0-9])?$
|
|
minLength: 1
|
|
maxLength: 64
|
|
example: myproject
|
|
file:
|
|
type: string
|
|
format: binary
|
|
description: Tarball file (.tar.gz) containing the static site
|
|
responses:
|
|
'200':
|
|
description: Deployment successful
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/DeployResponse'
|
|
example:
|
|
status: ok
|
|
project: myproject
|
|
username: alice
|
|
url: https://docs.yigid.dev/alice/myproject/
|
|
release: 20251014T180806
|
|
'400':
|
|
description: Invalid request - missing file, invalid project name, or multipart form parsing error
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
examples:
|
|
missingFile:
|
|
summary: Missing or invalid file
|
|
value:
|
|
status: error
|
|
error: missing or invalid file
|
|
invalidProject:
|
|
summary: Invalid project name format
|
|
value:
|
|
status: error
|
|
error: invalid project name format
|
|
parseError:
|
|
summary: Failed to parse multipart form
|
|
value:
|
|
status: error
|
|
error: failed to parse multipart form
|
|
'401':
|
|
description: Unauthorized - Invalid user token
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
example:
|
|
status: error
|
|
error: unauthorized
|
|
'413':
|
|
description: Request entity too large - Upload exceeds maximum size limit
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
example:
|
|
status: error
|
|
error: request body too large
|
|
'500':
|
|
description: Internal server error during deployment
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
examples:
|
|
extractionError:
|
|
summary: Failed to extract tarball
|
|
value:
|
|
status: error
|
|
error: 'failed to extract tarball: path contains ''..'' component which is not allowed: ../../etc/passwd'
|
|
generalError:
|
|
summary: General deployment error
|
|
value:
|
|
status: error
|
|
error: deployment failed
|
|
/api/v1/status:
|
|
get:
|
|
tags:
|
|
- Health
|
|
summary: Health check
|
|
description: Returns the current status of the service
|
|
operationId: getStatus
|
|
responses:
|
|
'200':
|
|
description: Service is healthy
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/StatusResponse'
|
|
example:
|
|
status: ok
|
|
/api/hello:
|
|
get:
|
|
tags:
|
|
- Info
|
|
summary: Service information
|
|
description: Returns basic information about the service and author
|
|
operationId: getHello
|
|
responses:
|
|
'200':
|
|
description: Service information
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/HelloResponse'
|
|
example:
|
|
message: Close the world, .txen eht nepO
|
|
author: Yigid BALABAN <hey@yigid.dev>
|
|
authorHomepage: https://yigid.dev/
|
|
components:
|
|
securitySchemes:
|
|
AdminAuth:
|
|
type: http
|
|
scheme: bearer
|
|
description: Admin bearer token for user management operations
|
|
UserAuth:
|
|
type: http
|
|
scheme: bearer
|
|
description: User bearer token for deployment operations
|
|
schemas:
|
|
CreateUserRequest:
|
|
type: object
|
|
required:
|
|
- username
|
|
properties:
|
|
username:
|
|
type: string
|
|
description: Username for the new user (lowercase letters, numbers, hyphens, underscores only)
|
|
pattern: ^[a-z0-9]([a-z0-9_-]{0,62}[a-z0-9])?$
|
|
minLength: 1
|
|
maxLength: 64
|
|
example: alice
|
|
DeleteUserRequest:
|
|
type: object
|
|
required:
|
|
- username
|
|
properties:
|
|
username:
|
|
type: string
|
|
description: Username of the user to delete
|
|
pattern: ^[a-z0-9]([a-z0-9_-]{0,62}[a-z0-9])?$
|
|
minLength: 1
|
|
maxLength: 64
|
|
example: alice
|
|
files:
|
|
type: string
|
|
description: Whether to persist or delete user files
|
|
enum:
|
|
- persist
|
|
- delete
|
|
default: persist
|
|
example: persist
|
|
AuthResponse:
|
|
type: object
|
|
required:
|
|
- status
|
|
- token
|
|
properties:
|
|
status:
|
|
type: string
|
|
enum:
|
|
- ok
|
|
example: ok
|
|
token:
|
|
type: string
|
|
description: 32-character alphanumeric token for API access
|
|
minLength: 32
|
|
maxLength: 32
|
|
example: 82lz0BVOWtV4uVj9DBZBuKMeyVDwidL2
|
|
DeployResponse:
|
|
type: object
|
|
required:
|
|
- status
|
|
- project
|
|
- username
|
|
- url
|
|
- release
|
|
properties:
|
|
status:
|
|
type: string
|
|
enum:
|
|
- ok
|
|
example: ok
|
|
project:
|
|
type: string
|
|
description: Project name
|
|
example: myproject
|
|
username:
|
|
type: string
|
|
description: Username who deployed
|
|
example: alice
|
|
url:
|
|
type: string
|
|
format: uri
|
|
description: Public URL where the site is accessible
|
|
example: https://docs.yigid.dev/alice/myproject/
|
|
release:
|
|
type: string
|
|
description: 'Release ID (timestamp format: YYYYMMDDTHHMMSS)'
|
|
pattern: ^[0-9]{8}T[0-9]{6}$
|
|
example: 20251014T180806
|
|
StatusResponse:
|
|
type: object
|
|
required:
|
|
- status
|
|
properties:
|
|
status:
|
|
type: string
|
|
enum:
|
|
- ok
|
|
example: ok
|
|
HelloResponse:
|
|
type: object
|
|
required:
|
|
- message
|
|
- author
|
|
- authorHomepage
|
|
properties:
|
|
message:
|
|
type: string
|
|
description: Service message
|
|
example: Close the world, .txen eht nepO
|
|
author:
|
|
type: string
|
|
description: Author information
|
|
example: Yigid BALABAN <hey@yigid.dev>
|
|
authorHomepage:
|
|
type: string
|
|
format: uri
|
|
description: Author homepage URL
|
|
example: https://yigid.dev/
|
|
SuccessResponse:
|
|
type: object
|
|
required:
|
|
- status
|
|
properties:
|
|
status:
|
|
type: string
|
|
enum:
|
|
- ok
|
|
example: ok
|
|
ErrorResponse:
|
|
type: object
|
|
required:
|
|
- status
|
|
- error
|
|
properties:
|
|
status:
|
|
type: string
|
|
enum:
|
|
- error
|
|
example: error
|
|
error:
|
|
type: string
|
|
description: Error message describing what went wrong
|
|
example: invalid username format
|
|
tags:
|
|
- name: Authentication
|
|
description: User management operations (admin only)
|
|
- name: Deployment
|
|
description: Static site deployment operations
|
|
- name: Health
|
|
description: Service health and status endpoints
|
|
- name: Info
|
|
description: Service information endpoints
|