Skip to content

api-admin Overview

apps/admin is the REST API for 4D operations staff. It is implemented with Hono + Bun and uses PostgreSQL as its data store. It provides CRUD for admin accounts, organizations, projects, and users, as well as session management backed by AWS Cognito.


Architecture

A 4-layer structure: Routes โ†’ Services โ†’ Repositories โ†’ Database.

Client Request
    โ†“
Middlewares (auth, logging, error handling)
    โ†“
Routes (request validation, response formatting)
    โ†“
Services (business logic)
    โ†“
Repositories (data access)
    โ†“
PostgreSQL / AWS Cognito

Key differences from api-user:

Item api-admin api-user
Database PostgreSQL PostgreSQL
Session management Token hash stored in PostgreSQL session table Cognito JWT only

Endpoint List

All endpoints are versioned under the /v1 prefix.

Path File Description
/v1/auth/* routes/v1/auth.ts Login, logout, session cleanup
/v1/admins/* routes/v1/admin.ts Admin account CRUD
/v1/organizations/* routes/v1/organization.ts Organization CRUD
/v1/projects/* routes/v1/project.ts Project management
/v1/users/* routes/v1/user.ts App user management
/v1/projects/{project_id}/users/* routes/v1/user-project.ts Project user access assignments
/v1/ping routes/v1/ping.ts Health check

Middleware Pipeline

Middleware File Role
requestId() hono/request-id Attaches a unique request ID for tracing
winstonLogger() middlewares/winston-logger.ts Structured request / response logging (including duration)
cors() hono/cors Cross-origin resource sharing
compress() hono/compress Gzip response compression
protectedRoute middlewares/protected-route.ts JWT verification and Cognito sub extraction
errorHandler middlewares/error-handler.ts Centralized error handling with unified response format

Authentication and Session Flow

sequenceDiagram
    participant Admin as Service Admin
    participant API as API Gateway
    participant Lambda as Lambda (api-admin)
    participant Cognito as AWS Cognito
    participant DB as PostgreSQL

    Admin->>API: POST /v1/auth/login
    API->>Lambda: Forward request
    Lambda->>Cognito: initiateAuth()
    Cognito-->>Lambda: JWT access token
    Lambda->>DB: Create session (token_hash, IP, User-Agent)
    Lambda-->>Admin: 200 { token, admin }

    Admin->>API: Call protected endpoint
    API->>Lambda: Authorization: Bearer <token>
    Lambda->>Cognito: Verify JWT
    Lambda->>DB: Look up session by token_hash
    DB-->>Lambda: Session active
    Lambda-->>Admin: Response

    Admin->>API: POST /v1/auth/logout
    API->>Lambda: Forward request
    Lambda->>Cognito: globalSignOut()
    Lambda->>DB: Revoke session (set revoked_at)
    Lambda-->>Admin: 200

Session Lifecycle

stateDiagram-v2
    [*] --> Created: Admin login
    Created --> Active: Session stored in DB
    Active --> Expired: expires_at passed
    Active --> Revoked: Admin logout
    Active --> Revoked: Password reset
    Active --> Revoked: Global sign-out
    Expired --> CleanedUp: Scheduled cleanup job
    Revoked --> CleanedUp: Scheduled cleanup job
    CleanedUp --> [*]: Soft deleted (deleted_at set)

Sessions are retained for SESSION_RETENTION_DAYS (default: 90 days) after expiry before being soft-deleted.


Error Handling

All errors are returned in the following JSON format.

{
  "error": {
    "message": "Error description",
    "code": "ERROR_CODE",
    "details": {}
  }
}
Status Usage
400 Bad Request Invalid input data
401 Unauthorized Missing or invalid authentication
403 Forbidden Insufficient permissions
404 Not Found Resource not found
409 Conflict Resource conflict (e.g. duplicate)
500 Internal Server Error Unexpected server error

Key Environment Variables

Variable Required Description
ADMIN_COGNITO_USER_POOL_ID Yes AWS Cognito User Pool ID
ADMIN_COGNITO_CLIENT_ID Yes AWS Cognito App Client ID
ADMIN_COGNITO_REGION No AWS region (default: ap-northeast-1)
DATABASE_NAME Yes PostgreSQL database name
DATABASE_USER Yes PostgreSQL user
DATABASE_PASSWORD Yes PostgreSQL password
DATABASE_HOST No PostgreSQL host (default: localhost)
DATABASE_PORT No PostgreSQL port (default: 5432)
SESSION_CLEANUP_API_KEY Yes API key for session cleanup endpoint
SESSION_RETENTION_DAYS No Days to retain expired sessions (default: 90)
ALLOWED_ORIGINS No Comma-separated CORS origins
PORT No Server port (default: 8081)