Bezel API api_production_deployment_runbook
internal prototype · canonical JSON + Dreamborn Forge HTML
internal generated
api_production_deployment_runbook · supabase_json

Bezel API api_production_deployment_runbook

api_production_deployment_runbook artifact · for Bezel API · status draft

Planning Surface

Use this to decide what happens next.

Status

draft

Agent Handoff
Start Here

api_production_deployment_runbook artifact · for Bezel API · status draft

Completion Evidence

No explicit evidence field yet. Require tests, screenshots, linked PRs, or reviewed outputs before marking complete.

Artifact Shape
  • vps: host: string, note: string, port: number, service: string, service_exec: string, worktree_path: string, node_version_observed: string
  • health: get: string, head: string, note: string
  • status: live
  • dns tls: dns: string, tls: string, nginx_site: string, certificate_renews: string
  • version: 1.0
  • database: schema_reason: string, migration_command: string
  • live smoke: command: string, last_verified_behavior: object, reusable_testnet_topic: string
  • repository: github: string, local_path: string, latest_verified_commit: string
  • updated at: 2026-05-08T16:38:39.141Z
  • deploy steps: 5 items
  • production url: https://api.bezeliq.ai
  • runtime config: env_file: string, doppler_config: string, database_schema: string, doppler_project: string, required_secret_names: object, database_ssl_reject_unauthorized: boolean
Structured Payload

Machine-readable source fields

vps
host

87.99.154.64

note

npm install emits dev-package engine warnings because some dependencies prefer Node 20.19+, but current build and runtime pass.

port

8787

service

bezel-api.service

service exec

/usr/local/bin/node dist/apps/api/src/cli.js

worktree path

/opt/bezel-api

node version observed

20.11.0

health
get

GET https://api.bezeliq.ai/healthz returns {"status":"ok"}

head

HEAD https://api.bezeliq.ai/healthz returns 200 with no body

note

Health route is no-auth and does not require database, Hedera, or agent principal resolution.

status

live

dns tls
dns

Cloudflare A api.bezeliq.ai -> 87.99.154.64, DNS-only

tls

Let’s Encrypt via certbot --nginx -d api.bezeliq.ai

nginx site

/etc/nginx/sites-available/bezel-api

certificate renews

certbot installed scheduled renewal task

version

1.0

database
schema reason

Shared Supabase public schema already contains tables such as public.tasks, so Bezel API isolates all runtime tables in bezel_api.

migration command

npm run build && DATABASE_SCHEMA=bezel_api npm run db:migrate:prod

live smoke
command

API_BASE_URL=https://api.bezeliq.ai SMOKE_ROLE_HCS_TOPIC_ID=<testnet-topic> SMOKE_ACCOUNT_EMAIL=<unique-email> SMOKE_ACCOUNT_PASSWORD=<password> SMOKE_AGENT_API_KEY=<api-key> npm run smoke:live:prod

last verified behavior
  • account create
  • login
  • workspace create
  • role create
  • agent register
  • plan submit
  • task claim
  • task complete
reusable testnet topic

0.0.8894240

repository
github

https://github.com/justinb2bea/bezel-api.git

local path

/Users/justinking/Vaults/Projects/bezel-api

latest verified commit

0a040d3 fix: support head health checks

updated at

2026-05-08T16:38:39.141Z

deploy steps
  • Run npm test, npm run typecheck, npm run build, and npm audit --audit-level=moderate locally.
  • Commit and push main.
  • rsync source to root@87.99.154.64:/opt/bezel-api excluding node_modules, dist, .git, and .env.
  • On VPS: npm ci, npm run build, npm prune --omit=dev, systemctl restart bezel-api.service.
  • Verify systemctl is-active bezel-api.service, GET /healthz, HEAD /healthz, and live smoke.
production url

https://api.bezeliq.ai

runtime config
env file

/etc/bezel-api.env

doppler config

prd

database schema

bezel_api

doppler project

bezel

required secret names
  • DATABASE_URL
  • HEDERA_NETWORK
  • HEDERA_OPERATOR_ID
  • HEDERA_OPERATOR_KEY
database ssl reject unauthorized

false