From 6196ff532d182c67f30a8e35a77bab8015ed796b Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 19 Jun 2026 03:43:37 +0000 Subject: [PATCH] docs: add C4 architecture model Add a C4 software architecture model for the repo: - docs/architecture/workspace.dsl: Structurizr DSL source of truth (system context, containers, CLI & Reporter components) - docs/architecture/README.md: GitHub-renderable Mermaid C4 diagrams (L1 context, L2 containers, L3 components) - Link the model from the top-level README Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01GrG9pynE6hPRG8JYsdKGxZ --- README.md | 1 + docs/architecture/README.md | 210 ++++++++++++++++++++++++++++++++ docs/architecture/workspace.dsl | 166 +++++++++++++++++++++++++ 3 files changed, 377 insertions(+) create mode 100644 docs/architecture/README.md create mode 100644 docs/architecture/workspace.dsl diff --git a/README.md b/README.md index 3988fc2..dff0864 100644 --- a/README.md +++ b/README.md @@ -217,6 +217,7 @@ npx postgresai checkup --json postgresql://... | claude -p "find issues and sugg |---|---| | **Demo** | [demo.postgres.ai](https://demo.postgres.ai) (login: `demo` / `demo`) | | **Docs** | [postgres.ai/docs](https://postgres.ai/docs) | +| **Architecture** | [C4 model](docs/architecture/README.md) | | **Issues** | [GitLab](https://gitlab.com/postgres-ai/postgresai/-/issues) | | **Community** | [Postgres.FM](https://postgres.fm) · [Postgres.TV](https://postgres.tv) | diff --git a/docs/architecture/README.md b/docs/architecture/README.md new file mode 100644 index 0000000..c7fc322 --- /dev/null +++ b/docs/architecture/README.md @@ -0,0 +1,210 @@ +# PostgresAI — C4 Architecture Model + +This directory holds the [C4 model](https://c4model.com/) for PostgresAI, an +AI-native PostgreSQL observability platform (monitoring, health checks, and root +cause analysis). + +The model is maintained in two complementary forms: + +| File | Purpose | +|------|---------| +| [`workspace.dsl`](./workspace.dsl) | **Source of truth.** [Structurizr DSL](https://docs.structurizr.com/dsl) describing people, systems, containers, components and their relationships. Renders all C4 levels and stays in sync as a single definition. | +| `README.md` (this file) | GitHub-renderable [Mermaid](https://mermaid.js.org/syntax/c4.html) diagrams for quick reading without tooling. | + +The C4 model describes architecture at four levels of zoom: **System Context** +(L1) → **Containers** (L2) → **Components** (L3) → Code (L4, left to the source). + +## How to view the Structurizr model + +```bash +# Render/edit interactively with Structurizr Lite +docker run -it --rm -p 8080:8080 \ + -v "$(pwd)/docs/architecture:/usr/local/structurizr" \ + structurizr/lite +# then open http://localhost:8080 +``` + +--- + +## Level 1 — System Context + +How PostgresAI fits among its users and the external systems it talks to. + +```mermaid +C4Context + title System Context — PostgresAI + + Person(dba, "Engineer / DBA", "Runs health checks, reviews dashboards, resolves issues") + Person(ai, "AI Coding Agent", "Claude Code, Cursor, Windsurf — consumes reports & MCP tools") + + System(pgai, "PostgresAI", "AI-native PostgreSQL observability platform") + + System_Ext(target, "Target PostgreSQL", "Databases being observed (self-hosted, RDS/Aurora, CloudSQL, Supabase)") + System_Ext(console, "console.postgres.ai", "Managed cloud: UI, Issues API, report/file storage, auth") + System_Ext(supabase, "Supabase Management API", "Executes SQL on Supabase databases") + System_Ext(aws, "AWS / Amazon Managed Prometheus", "RDS/Aurora + managed metrics") + System_Ext(llm, "LLM Provider", "Anthropic Claude / OpenAI GPT") + + Rel(dba, pgai, "Runs checkups, views dashboards, manages issues") + Rel(ai, pgai, "Reads reports, calls MCP tools") + Rel(pgai, target, "Connects to & queries", "SQL") + Rel(pgai, console, "Uploads reports, syncs issues, authenticates", "HTTPS") + Rel(pgai, supabase, "Executes SQL", "HTTPS") + Rel(pgai, aws, "Reads metrics", "HTTPS") + Rel(ai, llm, "Analyzes JSON reports") + + UpdateLayoutConfig($c4ShapeInRow="3", $c4BoundaryInRow="2") +``` + +--- + +## Level 2 — Containers + +The separately deployable/runnable units inside PostgresAI. The CLI delivers the +zero-setup express checkup; the rest form the optional full monitoring stack +(`docker-compose.yml` / Helm chart). + +```mermaid +C4Container + title Containers — PostgresAI + + Person(dba, "Engineer / DBA") + Person(ai, "AI Coding Agent") + + System_Ext(target, "Target PostgreSQL") + System_Ext(console, "console.postgres.ai") + System_Ext(supabase, "Supabase Management API") + System_Ext(aws, "Amazon Managed Prometheus") + + System_Boundary(pgai, "PostgresAI") { + Container(cli, "CLI", "Node.js / TypeScript", "Express checkup, stack install, prepare-db, auth (postgresai / pgai)") + Container(mcp, "MCP Server", "Node.js / TypeScript", "Exposes Issues tools to AI agents") + Container(reporter, "Reporter", "Python", "Generates 45+ structured health-check reports") + Container(flask, "Monitoring Backend", "Python / Flask", "Query history + PromQL proxy API") + Container(pgwPg, "pgwatch → Postgres", "Go", "Collects metrics into the Postgres sink") + Container(pgwProm, "pgwatch → Prometheus", "Go", "Collects metrics into VictoriaMetrics") + ContainerDb(vm, "VictoriaMetrics", "TSDB", "Prometheus-compatible metrics store") + ContainerDb(sink, "Postgres Sink", "PostgreSQL 17", "Historical metrics & check data") + Container(grafana, "Grafana", "Grafana 12", "13+ observability dashboards") + Container(telemetry, "Telemetry Agent", "Node.js", "Hourly system telemetry") + Container(pilot, "pg_index_pilot", "SQL / PL-pgSQL", "Autonomous index lifecycle") + } + + Rel(dba, cli, "Runs commands") + Rel(dba, grafana, "Views dashboards", "HTTPS") + Rel(ai, mcp, "Calls tools", "MCP/stdio") + + Rel(cli, target, "Health-check & prepare-db SQL", "SQL") + Rel(cli, console, "Uploads reports, syncs issues, auth", "HTTPS") + Rel(cli, supabase, "Runs queries", "HTTPS") + Rel(cli, reporter, "Triggers report generation") + Rel(mcp, console, "Reads/writes issues", "HTTPS") + + Rel(pgwPg, target, "Scrapes", "SQL") + Rel(pgwProm, target, "Scrapes", "SQL") + Rel(pgwPg, sink, "Writes metrics", "SQL") + Rel(pgwProm, vm, "Writes metrics", "HTTP") + + Rel(reporter, vm, "Reads metrics", "PromQL") + Rel(reporter, sink, "Reads history", "SQL") + Rel(reporter, aws, "Reads metrics", "HTTPS") + Rel(reporter, console, "Uploads reports", "HTTPS") + + Rel(flask, vm, "Proxies PromQL", "HTTP") + Rel(flask, sink, "Reads query history", "SQL") + Rel(grafana, vm, "Queries metrics", "PromQL") + Rel(grafana, sink, "Queries history", "SQL") + Rel(grafana, flask, "Calls backend API", "HTTP") + + Rel(telemetry, console, "Posts telemetry", "HTTPS") + Rel(pilot, target, "Manages indexes", "SQL") + + UpdateLayoutConfig($c4ShapeInRow="3", $c4BoundaryInRow="1") +``` + +--- + +## Level 3 — Components: CLI + +The CLI is the primary entry point and the most component-rich container +(`cli/lib/*.ts`). + +```mermaid +C4Component + title Components — CLI + + Person(dba, "Engineer / DBA") + System_Ext(target, "Target PostgreSQL") + System_Ext(console, "console.postgres.ai") + System_Ext(supabase, "Supabase Management API") + + Container_Boundary(cli, "CLI") { + Component(cmd, "Command Dispatch", "postgres-ai.ts", "Parses commands/flags, orchestrates workflows") + Component(checkup, "Checkup Engine", "checkup.ts", "Runs 45+ health checks, builds JSON reports") + Component(checkupApi, "Checkup API Client", "checkup-api.ts", "Uploads/fetches reports") + Component(init, "DB Init / prepare-db", "init.ts", "Creates monitoring role, schema, permissions") + Component(instances, "Targets / Instances", "instances.ts", "Manages monitored targets") + Component(issues, "Issues Client", "issues.ts", "Console Issues API CRUD") + Component(auth, "Auth (OAuth2/PKCE)", "auth-server.ts, pkce.ts", "Login & API-key handling") + Component(storage, "Storage Client", "storage.ts", "File upload/download") + Component(sb, "Supabase Client", "supabase.ts", "Runs SQL via Supabase API") + Component(cfg, "Local Config", "config.ts, util.ts", "~/.postgres-ai settings") + } + + Rel(dba, cmd, "Runs commands") + Rel(cmd, checkup, "Invokes") + Rel(cmd, init, "Invokes") + Rel(cmd, instances, "Invokes") + Rel(cmd, issues, "Invokes") + Rel(cmd, auth, "Invokes") + + Rel(checkup, target, "Runs SQL", "SQL") + Rel(checkup, checkupApi, "Uploads report") + Rel(checkup, cfg, "Reads settings") + Rel(checkupApi, console, "HTTPS") + Rel(init, target, "Creates role/schema", "SQL") + Rel(issues, console, "HTTPS") + Rel(auth, console, "OAuth2/PKCE", "HTTPS") + Rel(storage, console, "Uploads files", "HTTPS") + Rel(sb, supabase, "HTTPS") + + UpdateLayoutConfig($c4ShapeInRow="3", $c4BoundaryInRow="1") +``` + +--- + +## Level 3 — Components: Reporter + +```mermaid +C4Component + title Components — Reporter + + System_Ext(aws, "Amazon Managed Prometheus") + System_Ext(console, "console.postgres.ai") + ContainerDb(vm, "VictoriaMetrics") + ContainerDb(sink, "Postgres Sink") + + Container_Boundary(reporter, "Reporter") { + Component(gen, "Report Generators", "postgres_reports.py", "Per-check report logic (A/D/F/H/I/K/M/N series)") + Component(schemas, "Report Schemas", "schemas/*.schema.json", "29 JSON Schemas validating output") + } + + Rel(gen, vm, "Reads metrics", "PromQL") + Rel(gen, sink, "Reads history", "SQL") + Rel(gen, aws, "Reads metrics", "HTTPS") + Rel(gen, schemas, "Validates against") + Rel(gen, console, "Uploads reports", "HTTPS") + + UpdateLayoutConfig($c4ShapeInRow="2", $c4BoundaryInRow="1") +``` + +--- + +## Maintaining this model + +- Treat `workspace.dsl` as the source of truth; update it when containers, + components, or integrations change. +- Keep the Mermaid diagrams above in sync for at-a-glance reading on GitHub. +- Useful references: [c4model.com](https://c4model.com/), + [Structurizr DSL docs](https://docs.structurizr.com/dsl), + [Mermaid C4 syntax](https://mermaid.js.org/syntax/c4.html). diff --git a/docs/architecture/workspace.dsl b/docs/architecture/workspace.dsl new file mode 100644 index 0000000..54b9d21 --- /dev/null +++ b/docs/architecture/workspace.dsl @@ -0,0 +1,166 @@ +workspace "PostgresAI" "AI-native PostgreSQL observability: monitoring, health checks, and root cause analysis." { + + !identifiers hierarchical + + model { + # --------------------------------------------------------------- + # People / external actors + # --------------------------------------------------------------- + dba = person "Engineer / DBA" "Runs health checks, reviews dashboards, and resolves issues." + aiAgent = person "AI Coding Agent" "Claude Code, Cursor, Windsurf, etc. Consumes structured reports and the MCP server." "AI" + + # --------------------------------------------------------------- + # External software systems + # --------------------------------------------------------------- + targetPg = softwareSystem "Target PostgreSQL" "The PostgreSQL database(s) being observed (self-hosted, RDS/Aurora, CloudSQL, Supabase, etc.)." "External, Database" + console = softwareSystem "console.postgres.ai" "PostgresAI managed cloud: web UI, Issues API, report & file storage, auth (OAuth2/PKCE)." "External" + supabaseApi = softwareSystem "Supabase Management API" "Executes SQL against Supabase-hosted databases." "External" + awsApm = softwareSystem "AWS / Amazon Managed Prometheus" "RDS, Aurora and Amazon Managed Prometheus metrics sources." "External" + llm = softwareSystem "LLM Provider" "Anthropic Claude / OpenAI GPT used to analyze JSON reports." "External, AI" + + # --------------------------------------------------------------- + # The PostgresAI system and its containers + # --------------------------------------------------------------- + pgai = softwareSystem "PostgresAI" "AI-native PostgreSQL observability platform." { + + cli = container "CLI" "Express checkup, stack install, target & DB prep, auth. Binaries: postgresai / pgai." "Node.js / TypeScript" "EntryPoint" { + cmd = component "Command Dispatch" "Parses commands and flags, orchestrates workflows." "postgres-ai.ts" + checkup = component "Checkup Engine" "Runs 45+ health checks and builds structured JSON reports." "checkup.ts" + checkupApi = component "Checkup API Client" "Uploads/fetches reports to/from console.postgres.ai." "checkup-api.ts" + init = component "DB Init / prepare-db" "Creates monitoring role, schema and permissions on targets." "init.ts" + instances = component "Targets / Instances" "Manages monitored targets (instances.yml)." "instances.ts" + issues = component "Issues Client" "CRUD against the console Issues API." "issues.ts" + auth = component "Auth (OAuth2/PKCE)" "Browser-based login and API-key handling." "auth-server.ts, pkce.ts" + storage = component "Storage Client" "Uploads/downloads files to PostgresAI storage." "storage.ts" + supabase = component "Supabase Client" "Runs queries via the Supabase Management API." "supabase.ts" + config = component "Local Config" "Reads/writes ~/.postgres-ai settings." "config.ts, util.ts" + } + + mcp = container "MCP Server" "Model Context Protocol server exposing Issues tools to AI coding agents." "Node.js / TypeScript" "EntryPoint" { + mcpTools = component "MCP Tools" "list_issues, view_issue, create_issue, update_issue, ..." "mcp-server.ts" + } + + pgwatchPg = container "pgwatch (Postgres sink)" "Collects pg_stat_statements, wait events, table/index stats; writes to the Postgres sink." "Go (patched v3.7.0)" + pgwatchProm = container "pgwatch (Prometheus sink)" "Same collector, writes metrics to VictoriaMetrics." "Go (patched v3.7.0)" + + reporter = container "Reporter" "Generates 45+ structured health-check reports (A/D/F/H/I/K/M/N series) from metrics & history." "Python" { + reportGen = component "Report Generators" "Per-check report logic." "postgres_reports.py" + schemas = component "Report Schemas" "29 JSON Schemas validating report output." "schemas/*.schema.json" + } + + flask = container "Monitoring Backend" "API for pg_stat_statements query history and PromQL proxying." "Python / Flask + Gunicorn" { + api = component "API Endpoints" "Query history, query-id mapping, PromQL proxy." "app.py" + promql = component "PromQL Utils" "Escaping/formatting PromQL." "promql_utils.py" + } + + grafana = container "Grafana" "13+ dashboards (Four Golden Signals, wait events, indexes, replication, ...)." "Grafana 12.x" "WebUI" + vmetrics = container "VictoriaMetrics" "Prometheus-compatible time-series store for metrics." "VictoriaMetrics" "Database" + sinkPg = container "Postgres Sink" "Stores historical metrics and check data." "PostgreSQL 17" "Database" + + telemetry = container "Telemetry Agent" "Hourly system metrics (OOM, free RAM/disk) posted to the platform." "Node.js / TypeScript" + indexPilot = container "pg_index_pilot" "Autonomous index lifecycle: bloat estimation, recommendations, reindexing." "SQL / PL-pgSQL + Bash" + } + + # --------------------------------------------------------------- + # Relationships — Context level + # --------------------------------------------------------------- + dba -> pgai "Runs checkups, views dashboards, manages issues" + aiAgent -> pgai "Reads reports, calls MCP tools" + pgai -> targetPg "Connects to and queries" + pgai -> console "Uploads reports, syncs issues, authenticates" "HTTPS" + pgai -> supabaseApi "Executes SQL" "HTTPS" + pgai -> awsApm "Reads metrics" "HTTPS" + aiAgent -> llm "Analyzes JSON reports" + + # --------------------------------------------------------------- + # Relationships — Container level + # --------------------------------------------------------------- + dba -> pgai.cli "Runs commands" + dba -> pgai.grafana "Views dashboards" "HTTPS" + aiAgent -> pgai.mcp "Calls tools" "MCP/stdio" + + pgai.cli -> targetPg "Runs health-check & prepare-db SQL" "SQL/TCP" + pgai.cli -> console "Uploads reports, syncs issues, auth" "HTTPS" + pgai.cli -> supabaseApi "Runs queries" "HTTPS" + pgai.cli -> pgai.reporter "Triggers report generation" + + pgai.mcp -> console "Reads/writes issues" "HTTPS" + + pgai.pgwatchPg -> targetPg "Scrapes metrics" "SQL/TCP" + pgai.pgwatchProm -> targetPg "Scrapes metrics" "SQL/TCP" + pgai.pgwatchPg -> pgai.sinkPg "Writes metrics" "SQL/TCP" + pgai.pgwatchProm -> pgai.vmetrics "Writes metrics" "HTTP" + + pgai.reporter -> pgai.vmetrics "Reads metrics" "PromQL/HTTP" + pgai.reporter -> pgai.sinkPg "Reads history" "SQL/TCP" + pgai.reporter -> awsApm "Reads metrics" "HTTPS" + pgai.reporter -> console "Uploads reports" "HTTPS" + + pgai.flask -> pgai.vmetrics "Proxies PromQL" "HTTP" + pgai.flask -> pgai.sinkPg "Reads query history" "SQL/TCP" + pgai.grafana -> pgai.vmetrics "Queries metrics" "PromQL/HTTP" + pgai.grafana -> pgai.sinkPg "Queries history" "SQL/TCP" + pgai.grafana -> pgai.flask "Calls backend API" "HTTP" + + pgai.telemetry -> console "Posts system telemetry" "HTTPS" + pgai.indexPilot -> targetPg "Manages indexes" "SQL/TCP" + + # --------------------------------------------------------------- + # Relationships — Component level (CLI) + # --------------------------------------------------------------- + pgai.cli.cmd -> pgai.cli.checkup "Invokes" + pgai.cli.cmd -> pgai.cli.init "Invokes" + pgai.cli.cmd -> pgai.cli.instances "Invokes" + pgai.cli.cmd -> pgai.cli.issues "Invokes" + pgai.cli.cmd -> pgai.cli.auth "Invokes" + pgai.cli.checkup -> targetPg "Runs SQL" "SQL/TCP" + pgai.cli.checkup -> pgai.cli.checkupApi "Uploads report" + pgai.cli.checkupApi -> console "HTTPS" + pgai.cli.init -> targetPg "Creates role/schema" "SQL/TCP" + pgai.cli.issues -> console "HTTPS" + pgai.cli.auth -> console "OAuth2/PKCE" "HTTPS" + pgai.cli.storage -> console "Uploads files" "HTTPS" + pgai.cli.supabase -> supabaseApi "HTTPS" + pgai.cli.checkup -> pgai.cli.config "Reads settings" + } + + views { + systemContext pgai "SystemContext" { + include * + autolayout lr + description "C4 Level 1 — PostgresAI in context." + } + + container pgai "Containers" { + include * + autolayout lr + description "C4 Level 2 — containers inside PostgresAI." + } + + component pgai.cli "CliComponents" { + include * + autolayout lr + description "C4 Level 3 — components inside the CLI." + } + + component pgai.reporter "ReporterComponents" { + include * + autolayout lr + description "C4 Level 3 — components inside the Reporter." + } + + styles { + element "Person" { shape person background #08427b color #ffffff } + element "AI" { background #6b3fa0 color #ffffff } + element "Software System" { background #1168bd color #ffffff } + element "External" { background #999999 color #ffffff } + element "Container" { background #438dd5 color #ffffff } + element "Component" { background #85bbf0 color #000000 } + element "Database" { shape cylinder } + element "WebUI" { shape webBrowser } + element "EntryPoint" { shape roundedBox } + } + + theme default + } +}