docs: fix stale references, seed data case bugs, and convert ASCII diagrams to Mermaid

Audit all docs and examples against current codebase state. Fix seed_demo.sql
domain constant casing (IssuerType, TargetType, AgentStatus) that would cause
agent dispatch failures. Fix example docker-compose health endpoints (/health
not /api/v1/health) and env var names (CERTCTL_DATABASE_URL). Update connector
counts, test numbers, and planned→implemented status across docs. Convert 3
ASCII flow diagrams to Mermaid.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Shankar
2026-04-03 16:11:42 -04:00
parent b1178c177c
commit b9e8630cd7
16 changed files with 102 additions and 107 deletions
+7 -3
View File
@@ -90,8 +90,10 @@ flowchart TB
T5["HAProxy\n(combined PEM + reload)"] T5["HAProxy\n(combined PEM + reload)"]
T6["Traefik\n(file provider)"] T6["Traefik\n(file provider)"]
T7["Caddy\n(admin API / file)"] T7["Caddy\n(admin API / file)"]
T8["Envoy\n(file-based SDS)"]
T9["Postfix/Dovecot\n(file + service reload)"]
T2["F5 BIG-IP\n(proxy agent + iControl REST, planned)"] T2["F5 BIG-IP\n(proxy agent + iControl REST, planned)"]
T3["IIS\n(agent-local PowerShell, planned)"] T3["IIS\n(WinRM + local)"]
end end
DASH --> API DASH --> API
@@ -119,7 +121,7 @@ The server exposes a REST API under `/api/v1/` and optionally serves the web das
### Agents ### Agents
Lightweight Go processes that run on or near your infrastructure. Agents generate ECDSA P-256 private keys locally, create CSRs, and submit them to the control plane for signing — private keys never leave agent infrastructure. Agents also handle certificate deployment to target systems (NGINX, Apache httpd, HAProxy fully implemented; F5 BIG-IP, IIS interface only with V2 implementations planned) and report job status. They communicate with the control plane via HTTP and authenticate with API keys. Lightweight Go processes that run on or near your infrastructure. Agents generate ECDSA P-256 private keys locally, create CSRs, and submit them to the control plane for signing — private keys never leave agent infrastructure. Agents also handle certificate deployment to target systems (NGINX, Apache httpd, HAProxy, Traefik, Caddy, Envoy, Postfix, Dovecot, IIS fully implemented; F5 BIG-IP interface stub only) and report job status. They communicate with the control plane via HTTP and authenticate with API keys.
The agent runs two background loops: a heartbeat (every 60 seconds) to signal it's alive, and a work poll (every 30 seconds) to check for actionable jobs via `GET /api/v1/agents/{id}/work`. Jobs may be `AwaitingCSR` (agent needs to generate key + submit CSR) or `Deployment` (agent needs to deploy a certificate). Private keys are stored in `CERTCTL_KEY_DIR` (default `/var/lib/certctl/keys`) with 0600 permissions. The agent runs two background loops: a heartbeat (every 60 seconds) to signal it's alive, and a work poll (every 30 seconds) to check for actionable jobs via `GET /api/v1/agents/{id}/work`. Jobs may be `AwaitingCSR` (agent needs to generate key + submit CSR) or `Deployment` (agent needs to deploy a certificate). Private keys are stored in `CERTCTL_KEY_DIR` (default `/var/lib/certctl/keys`) with 0600 permissions.
@@ -521,8 +523,10 @@ flowchart TB
TI --> HP["HAProxy"] TI --> HP["HAProxy"]
TI --> TF["Traefik"] TI --> TF["Traefik"]
TI --> CD["Caddy"] TI --> CD["Caddy"]
TI --> EV["Envoy"]
TI --> PO["Postfix/Dovecot"]
TI --> IIS["IIS"]
TI --> F5["F5 BIG-IP (interface only)"] TI --> F5["F5 BIG-IP (interface only)"]
TI --> IIS["IIS (interface only)"]
end end
subgraph "Notifier Connectors" subgraph "Notifier Connectors"
+2 -2
View File
@@ -125,9 +125,9 @@ Agents also report **metadata** about themselves — their operating system, CPU
### Deployment Targets ### Deployment Targets
Targets are the systems where certificates actually get installed — NGINX web servers, Apache httpd servers, HAProxy load balancers, F5 BIG-IP appliances, Microsoft IIS servers. Each target type has a **connector** that knows how to deploy certificates to that specific system (e.g., writing files and reloading NGINX or Apache config, building a combined PEM for HAProxy). Targets are the systems where certificates actually get installed — NGINX web servers, Apache httpd servers, HAProxy load balancers, Traefik reverse proxies, Caddy servers, Envoy gateways, Postfix/Dovecot mail servers, Microsoft IIS servers, and network appliances. Each target type has a **connector** that knows how to deploy certificates to that specific system (e.g., writing files and reloading NGINX or Apache config, building a combined PEM for HAProxy).
For targets where an agent runs directly on the machine (NGINX, Apache, HAProxy, IIS), the agent deploys certificates locally — no remote access needed. For network appliances where you can't install an agent (F5 BIG-IP, Palo Alto, etc.), a **proxy agent** in the same network zone picks up the deployment job and calls the appliance's API. The server never initiates outbound connections to any target. For targets where an agent runs directly on the machine (NGINX, Apache, HAProxy, Traefik, Caddy, Envoy, Postfix, Dovecot, IIS), the agent deploys certificates locally — no remote access needed. For network appliances where you can't install an agent (F5 BIG-IP, Palo Alto, etc.), a **proxy agent** in the same network zone picks up the deployment job and calls the appliance's API. The server never initiates outbound connections to any target.
## The Certificate Lifecycle ## The Certificate Lifecycle
+2 -2
View File
@@ -53,8 +53,8 @@ Connectors extend certctl to integrate with external systems for certificate iss
Three types of connectors: Three types of connectors:
1. **Issuer Connector** — Obtains certificates from CAs (Local CA with sub-CA support, ACME with HTTP-01 + DNS-01 + DNS-PERSIST-01, step-ca, OpenSSL/Custom CA implemented; additional CA integrations planned) 1. **Issuer Connector** — Obtains certificates from CAs (Local CA with sub-CA support, ACME with HTTP-01 + DNS-01 + DNS-PERSIST-01, step-ca, OpenSSL/Custom CA, Vault PKI, DigiCert implemented; additional CA integrations planned)
2. **Target Connector** — Deploys certificates to infrastructure (NGINX, Apache httpd, HAProxy, Traefik, Caddy, Envoy, IIS implemented; F5 via proxy agent planned; additional cloud and network targets planned) 2. **Target Connector** — Deploys certificates to infrastructure (NGINX, Apache httpd, HAProxy, Traefik, Caddy, Envoy, Postfix, Dovecot, IIS implemented; F5 via proxy agent planned; additional cloud and network targets planned)
3. **Notifier Connector** — Sends alerts about certificate events (Email, Webhooks, Slack, Microsoft Teams, PagerDuty, OpsGenie implemented) 3. **Notifier Connector** — Sends alerts about certificate events (Email, Webhooks, Slack, Microsoft Teams, PagerDuty, OpsGenie implemented)
All connectors accept JSON configuration at initialization, support config validation, and are registered in the service layer. Issuer connectors run on the control plane; target connectors run on agents. For network appliances where agents can't be installed, a **proxy agent** in the same network zone handles deployment — the server never initiates outbound connections. All connectors accept JSON configuration at initialization, support config validation, and are registered in the service layer. Issuer connectors run on the control plane; target connectors run on agents. For network appliances where agents can't be installed, a **proxy agent** in the same network zone handles deployment — the server never initiates outbound connections.
+2 -2
View File
@@ -307,8 +307,8 @@ flowchart TD
A --> F["ACME\n(Let's Encrypt)"] A --> F["ACME\n(Let's Encrypt)"]
A --> G["step-ca\n(implemented)"] A --> G["step-ca\n(implemented)"]
A --> H["OpenSSL / Custom CA\n(script-based)"] A --> H["OpenSSL / Custom CA\n(script-based)"]
A --> J["DigiCert API\n(planned)"] A --> J["DigiCert API\n(implemented)"]
A --> K["Vault PKI\n(planned)"] A --> K["Vault PKI\n(implemented)"]
A --> L["Entrust / GlobalSign\n(planned)"] A --> L["Entrust / GlobalSign\n(planned)"]
A --> M["Google CAS / EJBCA\n(planned)"] A --> M["Google CAS / EJBCA\n(planned)"]
``` ```
+7 -7
View File
@@ -1286,11 +1286,11 @@ The web dashboard is the primary operational interface for certctl. Built with *
- **Docker Tags** — `:latest`, `:v{version}` (`shankar0123.docker.scarf.sh/certctl-server`, `shankar0123.docker.scarf.sh/certctl-agent`) - **Docker Tags** — `:latest`, `:v{version}` (`shankar0123.docker.scarf.sh/certctl-server`, `shankar0123.docker.scarf.sh/certctl-agent`)
### Test Suite ### Test Suite
- **Unit Tests** — 625+ test functions across service, handler, middleware, domain layers - **Unit Tests** — 1,088+ test functions across service, handler, middleware, domain layers
- **Integration Tests** — End-to-end workflows (issuance→renewal→deployment) - **Integration Tests** — End-to-end workflows (issuance→renewal→deployment)
- **Negative Tests** — Malformed input, nonexistent resources, error conditions - **Negative Tests** — Malformed input, nonexistent resources, error conditions
- **Frontend Tests** — 86 Vitest tests (API client, utilities, stats/metrics, full endpoint coverage) - **Frontend Tests** — 211 Vitest tests (API client, utilities, stats/metrics, full endpoint coverage)
- **Total Coverage** — 900+ tests (Go + frontend combined) - **Total Coverage** — 1,554+ tests (Go + frontend combined)
### Licensing ### Licensing
- **License** — Business Source License 1.1 (BSL 1.1) - **License** — Business Source License 1.1 (BSL 1.1)
@@ -1478,10 +1478,10 @@ Each guide includes an evidence summary table mapping specific criteria to certc
| Category | Count | | Category | Count |
|----------|-------| |----------|-------|
| **API Endpoints** | 95 (under /api/v1/ + /.well-known/est/) | | **API Endpoints** | 97 (under /api/v1/ + /.well-known/est/) |
| **Dashboard** | Full web GUI | | **Dashboard** | Full web GUI |
| **Issuer Connectors** | 4 (Local CA, ACME, step-ca, OpenSSL) | | **Issuer Connectors** | 6 (Local CA, ACME, step-ca, OpenSSL, Vault PKI, DigiCert) |
| **Target Connectors** | 5 (3 impl: NGINX, Apache, HAProxy; 2 stubs: F5, IIS) | | **Target Connectors** | 10 (9 impl: NGINX, Apache, HAProxy, Traefik, Caddy, Envoy, IIS, Postfix, Dovecot; 1 stub: F5) |
| **Notifier Channels** | 6 (Email, Webhook, Slack, Teams, PagerDuty, OpsGenie) | | **Notifier Channels** | 6 (Email, Webhook, Slack, Teams, PagerDuty, OpsGenie) |
| **Job Types** | 4 (Issuance, Renewal, Deployment, Validation) | | **Job Types** | 4 (Issuance, Renewal, Deployment, Validation) |
| **Job States** | 7 (Pending, AwaitingCSR, AwaitingApproval, Running, Completed, Failed, Cancelled) | | **Job States** | 7 (Pending, AwaitingCSR, AwaitingApproval, Running, Completed, Failed, Cancelled) |
@@ -1492,6 +1492,6 @@ Each guide includes an evidence summary table mapping specific criteria to certc
| **MCP Tools** | 76 (16 resource domains) | | **MCP Tools** | 76 (16 resource domains) |
| **CLI Subcommands** | 10 | | **CLI Subcommands** | 10 |
| **Database Tables** | 19 | | **Database Tables** | 19 |
| **Test Suite** | 900+ tests (Go backend + frontend) | | **Test Suite** | 1,554+ tests (Go backend + frontend) |
| **Environment Variables** | 41+ configuration options | | **Environment Variables** | 41+ configuration options |
+2 -2
View File
@@ -1600,7 +1600,7 @@ curl -s -w "\nHTTP %{http_code}\n" -X POST -H "$AUTH" -H "$CT" \
--- ---
**Test 7.1.6 — Create IIS target (stub)** **Test 7.1.6 — Create IIS target**
```bash ```bash
curl -s -w "\nHTTP %{http_code}\n" -X POST -H "$AUTH" -H "$CT" \ curl -s -w "\nHTTP %{http_code}\n" -X POST -H "$AUTH" -H "$CT" \
@@ -5833,7 +5833,7 @@ These must be green before starting manual QA:
| 7.1.3 | Create Apache target | Manual | ☐ | | | | 7.1.3 | Create Apache target | Manual | ☐ | | |
| 7.1.4 | Create HAProxy target | Manual | ☐ | | | | 7.1.4 | Create HAProxy target | Manual | ☐ | | |
| 7.1.5 | Create F5 BIG-IP target (stub) | Auto | ☑ | 2026-03-30 | | | 7.1.5 | Create F5 BIG-IP target (stub) | Auto | ☑ | 2026-03-30 | |
| 7.1.6 | Create IIS target (stub) | Auto | ☑ | 2026-03-30 | | | 7.1.6 | Create IIS target | Auto | ☑ | 2026-03-30 | |
| 7.1.7 | Get target verifies type-specific config stored | Manual | ☐ | | | | 7.1.7 | Get target verifies type-specific config stored | Manual | ☐ | | |
| 7.1.8 | Update target config | Manual | ☐ | | | | 7.1.8 | Update target config | Manual | ☐ | | |
| 7.1.9 | Delete target returns 204 | Auto | ☑ | 2026-03-30 | | | 7.1.9 | Delete target returns 204 | Auto | ☑ | 2026-03-30 | |
+12 -10
View File
@@ -13,16 +13,18 @@ This example demonstrates certctl's core use case: **automatically manage TLS ce
## Architecture ## Architecture
``` ```mermaid
Your Domain (example.com) flowchart TD
↓ [HTTP-01 validation, port 80] A["Your Domain (example.com)"]
Let's Encrypt ACME B["Let's Encrypt ACME"]
↓ [CSR submission] C["certctl Server (control plane)"]
certctl Server (control plane) D["certctl Agent (on NGINX server)"]
↓ [API polling] E["NGINX Reverse Proxy"]
certctl Agent (on NGINX server)
↓ [deploy cert+key] A -->|HTTP-01 validation<br/>port 80| B
NGINX Reverse Proxy B -->|CSR submission| C
C -->|API polling| D
D -->|deploy cert+key| E
``` ```
## Prerequisites ## Prerequisites
+2 -2
View File
@@ -26,7 +26,7 @@ services:
container_name: certctl-server-acme-nginx container_name: certctl-server-acme-nginx
environment: environment:
# Database # Database
DATABASE_URL: postgres://certctl:${DB_PASSWORD:-certctl-dev-password}@postgres:5432/certctl?sslmode=disable CERTCTL_DATABASE_URL: postgres://certctl:${DB_PASSWORD:-certctl-dev-password}@postgres:5432/certctl?sslmode=disable
# Server settings # Server settings
CERTCTL_SERVER_PORT: 8443 CERTCTL_SERVER_PORT: 8443
@@ -61,7 +61,7 @@ services:
networks: networks:
- certctl-network - certctl-network
healthcheck: healthcheck:
test: ['CMD-SHELL', 'curl -sf http://localhost:8443/api/v1/health || exit 1'] test: ['CMD-SHELL', 'curl -sf http://localhost:8443/health || exit 1']
interval: 10s interval: 10s
timeout: 5s timeout: 5s
retries: 3 retries: 3
@@ -50,7 +50,7 @@ services:
container_name: certctl-server-dns01 container_name: certctl-server-dns01
environment: environment:
# Database # Database
DATABASE_URL: postgres://certctl:${DB_PASSWORD:-certctl-dev-password}@postgres:5432/certctl?sslmode=disable CERTCTL_DATABASE_URL: postgres://certctl:${DB_PASSWORD:-certctl-dev-password}@postgres:5432/certctl?sslmode=disable
# Server settings # Server settings
CERTCTL_SERVER_PORT: 8443 CERTCTL_SERVER_PORT: 8443
@@ -113,7 +113,7 @@ services:
- certctl-network - certctl-network
healthcheck: healthcheck:
test: ['CMD-SHELL', 'curl -sf http://localhost:8443/api/v1/health || exit 1'] test: ['CMD-SHELL', 'curl -sf http://localhost:8443/health || exit 1']
interval: 10s interval: 10s
timeout: 5s timeout: 5s
retries: 3 retries: 3
+2 -2
View File
@@ -27,7 +27,7 @@ services:
container_name: certctl-server-multi-issuer container_name: certctl-server-multi-issuer
environment: environment:
# Database # Database
DATABASE_URL: postgres://certctl:${DB_PASSWORD:-certctl-dev-password}@postgres:5432/certctl?sslmode=disable CERTCTL_DATABASE_URL: postgres://certctl:${DB_PASSWORD:-certctl-dev-password}@postgres:5432/certctl?sslmode=disable
# Server settings # Server settings
CERTCTL_SERVER_PORT: 8443 CERTCTL_SERVER_PORT: 8443
@@ -64,7 +64,7 @@ services:
networks: networks:
- certctl-network - certctl-network
healthcheck: healthcheck:
test: ['CMD-SHELL', 'curl -sf http://localhost:8443/api/v1/health || exit 1'] test: ['CMD-SHELL', 'curl -sf http://localhost:8443/health || exit 1']
interval: 10s interval: 10s
timeout: 5s timeout: 5s
retries: 3 retries: 3
+24 -22
View File
@@ -13,27 +13,29 @@ With certctl, both issuer types are configured and available. You assign each ce
## Architecture ## Architecture
``` ```mermaid
┌─────────────────────────────────────────────────────────────────┐ flowchart TD
certctl Server (Control Plane) subgraph Server ["certctl Server (Control Plane)"]
│ - Let's Encrypt ACME issuer (HTTP-01 challenges) A["Let's Encrypt ACME issuer<br/>(HTTP-01 challenges)"]
│ - Local CA issuer (self-signed or sub-CA mode) B["Local CA issuer<br/>(self-signed or sub-CA mode)"]
│ - PostgreSQL database (cert inventory, audit, jobs) C["PostgreSQL database<br/>(cert inventory, audit, jobs)"]
└─────────────────────────────────────────────────────────────────┘ end
│ API polling subgraph Agent ["certctl Agent"]
D["Discovers existing certs<br/>(/etc/nginx/ssl, /etc/app/ssl)"]
┌─────────────────────────────────────────────────────────────────┐ E["Polls server for<br/>renewal/issuance/deployment jobs"]
│ certctl Agent │ F["Generates keys locally<br/>(agent-side crypto)"]
│ - Discovers existing certs in /etc/nginx/ssl and /etc/app/ssl │ G["Deploys certs to NGINX<br/>and app service directories"]
│ - Polls server for renewal/issuance/deployment jobs │ end
│ - Generates keys locally (agent-side crypto) │
│ - Deploys certs to NGINX and app service directories │ subgraph Targets ["Target Services"]
└─────────────────────────────────────────────────────────────────┘ H["NGINX (public TLS)<br/>(Let's Encrypt certs)"]
│ │ I["App Services (internal TLS)<br/>(Local CA certs)"]
▼ ▼ end
NGINX (public TLS) App Services (internal TLS)
(Let's Encrypt certs) (Local CA certs) Server -->|API polling| Agent
Agent -->|Deploy| H
Agent -->|Deploy| I
``` ```
## Prerequisites ## Prerequisites
@@ -212,7 +214,7 @@ Each agent independently manages its local cert inventory and deployments. The s
- For ACME, ensure ports 80/443 are open and your domain resolves - For ACME, ensure ports 80/443 are open and your domain resolves
### Agent can't reach server ### Agent can't reach server
- Check network: `docker compose exec certctl-agent curl http://certctl-server:8443/api/v1/health` - Check network: `docker compose exec certctl-agent curl http://certctl-server:8443/health`
- Verify `CERTCTL_SERVER_URL` environment variable - Verify `CERTCTL_SERVER_URL` environment variable
### No issuers showing up ### No issuers showing up
@@ -26,7 +26,7 @@ services:
container_name: certctl-server-private-ca container_name: certctl-server-private-ca
environment: environment:
# Database # Database
DATABASE_URL: postgres://certctl:${DB_PASSWORD:-certctl-dev-password}@postgres:5432/certctl?sslmode=disable CERTCTL_DATABASE_URL: postgres://certctl:${DB_PASSWORD:-certctl-dev-password}@postgres:5432/certctl?sslmode=disable
# Server settings # Server settings
CERTCTL_SERVER_PORT: 8443 CERTCTL_SERVER_PORT: 8443
@@ -77,7 +77,7 @@ services:
networks: networks:
- certctl-network - certctl-network
healthcheck: healthcheck:
test: ['CMD-SHELL', 'curl -sf http://localhost:8443/api/v1/health || exit 1'] test: ['CMD-SHELL', 'curl -sf http://localhost:8443/health || exit 1']
interval: 10s interval: 10s
timeout: 5s timeout: 5s
retries: 3 retries: 3
@@ -17,29 +17,16 @@ This example demonstrates certctl managing certificates for **internal services
## Architecture ## Architecture
``` ```mermaid
┌──────────────────┐ flowchart TD
certctl-server(Local CA issuer) A["certctl-server<br/>(control plane)<br/>(Local CA issuer)"]
│ (control │ B["certctl-agent<br/>(certificate deployer)"]
│ plane) │ C["Traefik<br/>(watches cert directory)"]
└────────┬─────────┘ D["[Internal Services]"]
REST API (job polling) A -->|REST API<br/>job polling| B
B -->|Write cert/key files| C
┌────────▼──────────┐ C -->|TLS handshakes| D
│ certctl-agent │ (certificate deployer)
└────────┬──────────┘
│ Write cert/key files
┌────────▼──────────────────────┐
│ Traefik │
│ (watches cert directory) │
└────────────────────────────────┘
│ TLS handshakes
[Internal Services]
``` ```
## Quick Start (Self-Signed CA) ## Quick Start (Self-Signed CA)
+2 -2
View File
@@ -81,7 +81,7 @@ services:
container_name: certctl-server-stepca-haproxy container_name: certctl-server-stepca-haproxy
environment: environment:
# Database # Database
DATABASE_URL: postgres://certctl:${DB_PASSWORD:-certctl-dev-password}@postgres:5432/certctl?sslmode=disable CERTCTL_DATABASE_URL: postgres://certctl:${DB_PASSWORD:-certctl-dev-password}@postgres:5432/certctl?sslmode=disable
# Server settings # Server settings
CERTCTL_SERVER_PORT: 8443 CERTCTL_SERVER_PORT: 8443
@@ -119,7 +119,7 @@ services:
networks: networks:
- certctl-network - certctl-network
healthcheck: healthcheck:
test: ['CMD-SHELL', 'curl -sf http://localhost:8443/api/v1/health || exit 1'] test: ['CMD-SHELL', 'curl -sf http://localhost:8443/health || exit 1']
interval: 10s interval: 10s
timeout: 5s timeout: 5s
retries: 3 retries: 3
+1 -1
View File
@@ -315,7 +315,7 @@ Common issues:
Verify network: Verify network:
```bash ```bash
docker compose exec certctl-agent curl http://certctl-server:8443/api/v1/health docker compose exec certctl-agent curl http://certctl-server:8443/health
``` ```
### HAProxy config validation fails ### HAProxy config validation fails
+23 -23
View File
@@ -39,11 +39,11 @@ ON CONFLICT (id) DO NOTHING;
-- 3. Issuers -- 3. Issuers
-- ============================================================ -- ============================================================
INSERT INTO issuers (id, name, type, config, enabled, created_at, updated_at) VALUES INSERT INTO issuers (id, name, type, config, enabled, created_at, updated_at) VALUES
('iss-local', 'Local Dev CA', 'local', '{"ca_common_name": "CertCtl Demo CA", "validity_days": 90}', true, NOW() - INTERVAL '180 days', NOW() - INTERVAL '180 days'), ('iss-local', 'Local Dev CA', 'GenericCA', '{"ca_common_name": "CertCtl Demo CA", "validity_days": 90}', true, NOW() - INTERVAL '180 days', NOW() - INTERVAL '180 days'),
('iss-acme-le', 'Let''s Encrypt Staging', 'acme', '{"directory_url": "https://acme-staging-v02.api.letsencrypt.org/directory", "email": "admin@example.com", "challenge_type": "http-01"}', true, NOW() - INTERVAL '150 days', NOW() - INTERVAL '150 days'), ('iss-acme-le', 'Let''s Encrypt Staging', 'ACME', '{"directory_url": "https://acme-staging-v02.api.letsencrypt.org/directory", "email": "admin@example.com", "challenge_type": "http-01"}', true, NOW() - INTERVAL '150 days', NOW() - INTERVAL '150 days'),
('iss-stepca', 'step-ca Internal', 'stepca', '{"ca_url": "https://ca.internal:9000", "provisioner_name": "certctl", "validity_days": 90}', true, NOW() - INTERVAL '120 days', NOW() - INTERVAL '120 days'), ('iss-stepca', 'step-ca Internal', 'StepCA', '{"ca_url": "https://ca.internal:9000", "provisioner_name": "certctl", "validity_days": 90}', true, NOW() - INTERVAL '120 days', NOW() - INTERVAL '120 days'),
('iss-acme-zs', 'ZeroSSL (EAB)', 'acme', '{"directory_url": "https://acme.zerossl.com/v2/DV90", "email": "admin@example.com", "challenge_type": "http-01"}', true, NOW() - INTERVAL '60 days', NOW() - INTERVAL '60 days'), ('iss-acme-zs', 'ZeroSSL (EAB)', 'ACME', '{"directory_url": "https://acme.zerossl.com/v2/DV90", "email": "admin@example.com", "challenge_type": "http-01"}', true, NOW() - INTERVAL '60 days', NOW() - INTERVAL '60 days'),
('iss-openssl', 'Custom OpenSSL CA', 'openssl', '{"sign_script": "/opt/ca/sign.sh", "timeout_seconds": 30}', false, NOW() - INTERVAL '30 days', NOW() - INTERVAL '30 days'), ('iss-openssl', 'Custom OpenSSL CA', 'OpenSSL', '{"sign_script": "/opt/ca/sign.sh", "timeout_seconds": 30}', false, NOW() - INTERVAL '30 days', NOW() - INTERVAL '30 days'),
('iss-vault', 'HashiCorp Vault PKI', 'VaultPKI', '{"addr": "https://vault.internal:8200", "mount": "pki", "role": "web-certs", "ttl": "8760h"}', true, NOW() - INTERVAL '20 days', NOW() - INTERVAL '20 days'), ('iss-vault', 'HashiCorp Vault PKI', 'VaultPKI', '{"addr": "https://vault.internal:8200", "mount": "pki", "role": "web-certs", "ttl": "8760h"}', true, NOW() - INTERVAL '20 days', NOW() - INTERVAL '20 days'),
('iss-digicert', 'DigiCert CertCentral', 'DigiCert', '{"base_url": "https://www.digicert.com/services/v2", "product_type": "ssl_basic"}', true, NOW() - INTERVAL '15 days', NOW() - INTERVAL '15 days') ('iss-digicert', 'DigiCert CertCentral', 'DigiCert', '{"base_url": "https://www.digicert.com/services/v2", "product_type": "ssl_basic"}', true, NOW() - INTERVAL '15 days', NOW() - INTERVAL '15 days')
ON CONFLICT (id) DO NOTHING; ON CONFLICT (id) DO NOTHING;
@@ -52,33 +52,33 @@ ON CONFLICT (id) DO NOTHING;
-- 4. Agents (8 agents across multiple platforms) -- 4. Agents (8 agents across multiple platforms)
-- ============================================================ -- ============================================================
INSERT INTO agents (id, name, hostname, status, last_heartbeat_at, registered_at, api_key_hash, os, architecture, ip_address, version) VALUES INSERT INTO agents (id, name, hostname, status, last_heartbeat_at, registered_at, api_key_hash, os, architecture, ip_address, version) VALUES
('ag-web-prod', 'web-prod-agent', 'web-prod-01.internal', 'online', NOW() - INTERVAL '30 seconds', NOW() - INTERVAL '120 days', 'demo_hash_1', 'linux', 'amd64', '10.0.1.10', '2.0.14'), ('ag-web-prod', 'web-prod-agent', 'web-prod-01.internal', 'Online', NOW() - INTERVAL '30 seconds', NOW() - INTERVAL '120 days', 'demo_hash_1', 'linux', 'amd64', '10.0.1.10', '2.0.14'),
('ag-web-staging', 'web-staging-agent', 'web-stg-01.internal', 'online', NOW() - INTERVAL '45 seconds', NOW() - INTERVAL '90 days', 'demo_hash_2', 'linux', 'amd64', '10.0.2.20', '2.0.14'), ('ag-web-staging', 'web-staging-agent', 'web-stg-01.internal', 'Online', NOW() - INTERVAL '45 seconds', NOW() - INTERVAL '90 days', 'demo_hash_2', 'linux', 'amd64', '10.0.2.20', '2.0.14'),
('ag-lb-prod', 'lb-prod-agent', 'lb-prod-01.internal', 'online', NOW() - INTERVAL '15 seconds', NOW() - INTERVAL '150 days', 'demo_hash_3', 'linux', 'amd64', '10.0.1.50', '2.0.14'), ('ag-lb-prod', 'lb-prod-agent', 'lb-prod-01.internal', 'Online', NOW() - INTERVAL '15 seconds', NOW() - INTERVAL '150 days', 'demo_hash_3', 'linux', 'amd64', '10.0.1.50', '2.0.14'),
('ag-iis-prod', 'iis-prod-agent', 'iis-prod-01.internal', 'offline', NOW() - INTERVAL '3 hours', NOW() - INTERVAL '60 days', 'demo_hash_4', 'windows', 'amd64', '10.0.3.15', '2.0.12'), ('ag-iis-prod', 'iis-prod-agent', 'iis-prod-01.internal', 'Offline', NOW() - INTERVAL '3 hours', NOW() - INTERVAL '60 days', 'demo_hash_4', 'windows', 'amd64', '10.0.3.15', '2.0.12'),
('ag-data-prod', 'data-prod-agent', 'data-prod-01.internal', 'online', NOW() - INTERVAL '20 seconds', NOW() - INTERVAL '90 days', 'demo_hash_5', 'linux', 'arm64', '10.0.4.30', '2.0.14'), ('ag-data-prod', 'data-prod-agent', 'data-prod-01.internal', 'Online', NOW() - INTERVAL '20 seconds', NOW() - INTERVAL '90 days', 'demo_hash_5', 'linux', 'arm64', '10.0.4.30', '2.0.14'),
('ag-edge-01', 'edge-eu-agent', 'edge-eu-01.internal', 'online', NOW() - INTERVAL '50 seconds', NOW() - INTERVAL '45 days', 'demo_hash_6', 'linux', 'arm64', '10.0.5.10', '2.0.14'), ('ag-edge-01', 'edge-eu-agent', 'edge-eu-01.internal', 'Online', NOW() - INTERVAL '50 seconds', NOW() - INTERVAL '45 days', 'demo_hash_6', 'linux', 'arm64', '10.0.5.10', '2.0.14'),
('ag-k8s-prod', 'k8s-prod-agent', 'k8s-node-01.internal', 'online', NOW() - INTERVAL '10 seconds', NOW() - INTERVAL '30 days', 'demo_hash_7', 'linux', 'amd64', '10.0.6.10', '2.0.14'), ('ag-k8s-prod', 'k8s-prod-agent', 'k8s-node-01.internal', 'Online', NOW() - INTERVAL '10 seconds', NOW() - INTERVAL '30 days', 'demo_hash_7', 'linux', 'amd64', '10.0.6.10', '2.0.14'),
('ag-mac-dev', 'mac-dev-agent', 'dev-mac-01.internal', 'online', NOW() - INTERVAL '60 seconds', NOW() - INTERVAL '15 days', 'demo_hash_8', 'darwin', 'arm64', '10.0.7.5', '2.0.14') ('ag-mac-dev', 'mac-dev-agent', 'dev-mac-01.internal', 'Online', NOW() - INTERVAL '60 seconds', NOW() - INTERVAL '15 days', 'demo_hash_8', 'darwin', 'arm64', '10.0.7.5', '2.0.14')
ON CONFLICT (id) DO NOTHING; ON CONFLICT (id) DO NOTHING;
-- Sentinel agent for network-discovered certificates -- Sentinel agent for network-discovered certificates
INSERT INTO agents (id, name, hostname, status, last_heartbeat_at, registered_at, api_key_hash, os, architecture, ip_address, version) VALUES INSERT INTO agents (id, name, hostname, status, last_heartbeat_at, registered_at, api_key_hash, os, architecture, ip_address, version) VALUES
('server-scanner', 'Network Scanner (Server-Side)', 'certctl-server', 'online', NOW(), NOW() - INTERVAL '90 days', 'sentinel_no_auth', 'linux', 'amd64', '127.0.0.1', '2.0.14') ('server-scanner', 'Network Scanner (Server-Side)', 'certctl-server', 'Online', NOW(), NOW() - INTERVAL '90 days', 'sentinel_no_auth', 'linux', 'amd64', '127.0.0.1', '2.0.14')
ON CONFLICT (id) DO NOTHING; ON CONFLICT (id) DO NOTHING;
-- ============================================================ -- ============================================================
-- 5. Deployment Targets (8 targets across multiple connector types) -- 5. Deployment Targets (8 targets across multiple connector types)
-- ============================================================ -- ============================================================
INSERT INTO deployment_targets (id, name, type, agent_id, config, enabled, created_at, updated_at) VALUES INSERT INTO deployment_targets (id, name, type, agent_id, config, enabled, created_at, updated_at) VALUES
('tgt-nginx-prod', 'NGINX Production', 'nginx', 'ag-web-prod', '{"cert_path": "/etc/nginx/ssl/cert.pem", "key_path": "/etc/nginx/ssl/key.pem", "reload_command": "nginx -s reload"}', true, NOW() - INTERVAL '120 days', NOW()), ('tgt-nginx-prod', 'NGINX Production', 'NGINX', 'ag-web-prod', '{"cert_path": "/etc/nginx/ssl/cert.pem", "key_path": "/etc/nginx/ssl/key.pem", "reload_command": "nginx -s reload"}', true, NOW() - INTERVAL '120 days', NOW()),
('tgt-nginx-staging', 'NGINX Staging', 'nginx', 'ag-web-staging', '{"cert_path": "/etc/nginx/ssl/cert.pem", "key_path": "/etc/nginx/ssl/key.pem", "reload_command": "nginx -s reload"}', true, NOW() - INTERVAL '90 days', NOW()), ('tgt-nginx-staging', 'NGINX Staging', 'NGINX', 'ag-web-staging', '{"cert_path": "/etc/nginx/ssl/cert.pem", "key_path": "/etc/nginx/ssl/key.pem", "reload_command": "nginx -s reload"}', true, NOW() - INTERVAL '90 days', NOW()),
('tgt-haproxy-prod', 'HAProxy Production', 'haproxy', 'ag-lb-prod', '{"combined_pem_path": "/etc/haproxy/ssl/site.pem", "reload_command": "systemctl reload haproxy"}', true, NOW() - INTERVAL '150 days', NOW()), ('tgt-haproxy-prod', 'HAProxy Production', 'HAProxy', 'ag-lb-prod', '{"combined_pem_path": "/etc/haproxy/ssl/site.pem", "reload_command": "systemctl reload haproxy"}', true, NOW() - INTERVAL '150 days', NOW()),
('tgt-apache-prod', 'Apache Production', 'apache', 'ag-web-prod', '{"cert_path": "/etc/httpd/ssl/cert.pem", "key_path": "/etc/httpd/ssl/key.pem", "chain_path": "/etc/httpd/ssl/chain.pem", "reload_command": "apachectl graceful"}', true, NOW() - INTERVAL '100 days', NOW()), ('tgt-apache-prod', 'Apache Production', 'Apache', 'ag-web-prod', '{"cert_path": "/etc/httpd/ssl/cert.pem", "key_path": "/etc/httpd/ssl/key.pem", "chain_path": "/etc/httpd/ssl/chain.pem", "reload_command": "apachectl graceful"}', true, NOW() - INTERVAL '100 days', NOW()),
('tgt-iis-prod', 'IIS Production', 'iis', 'ag-iis-prod', '{"site_name": "Default Web Site", "binding_info": "*:443:"}', true, NOW() - INTERVAL '60 days', NOW()), ('tgt-iis-prod', 'IIS Production', 'IIS', 'ag-iis-prod', '{"site_name": "Default Web Site", "binding_info": "*:443:"}', true, NOW() - INTERVAL '60 days', NOW()),
('tgt-traefik-prod', 'Traefik Production', 'traefik', 'ag-k8s-prod', '{"watch_dir": "/etc/traefik/dynamic/certs"}', true, NOW() - INTERVAL '30 days', NOW()), ('tgt-traefik-prod', 'Traefik Production', 'Traefik', 'ag-k8s-prod', '{"watch_dir": "/etc/traefik/dynamic/certs"}', true, NOW() - INTERVAL '30 days', NOW()),
('tgt-caddy-prod', 'Caddy Production', 'caddy', 'ag-edge-01', '{"mode": "api", "admin_url": "http://localhost:2019"}', true, NOW() - INTERVAL '45 days', NOW()), ('tgt-caddy-prod', 'Caddy Production', 'Caddy', 'ag-edge-01', '{"mode": "api", "admin_url": "http://localhost:2019"}', true, NOW() - INTERVAL '45 days', NOW()),
('tgt-nginx-data', 'NGINX Data Services', 'nginx', 'ag-data-prod', '{"cert_path": "/etc/nginx/ssl/cert.pem", "key_path": "/etc/nginx/ssl/key.pem", "reload_command": "nginx -s reload"}', true, NOW() - INTERVAL '90 days', NOW()) ('tgt-nginx-data', 'NGINX Data Services', 'NGINX', 'ag-data-prod', '{"cert_path": "/etc/nginx/ssl/cert.pem", "key_path": "/etc/nginx/ssl/key.pem", "reload_command": "nginx -s reload"}', true, NOW() - INTERVAL '90 days', NOW())
ON CONFLICT (id) DO NOTHING; ON CONFLICT (id) DO NOTHING;
-- ============================================================ -- ============================================================
@@ -128,7 +128,7 @@ INSERT INTO certificate_profiles (id, name, description, allowed_key_algorithms,
ON CONFLICT (id) DO NOTHING; ON CONFLICT (id) DO NOTHING;
-- ============================================================ -- ============================================================
-- 7. Managed Certificates (35 certs across multiple issuers and environments) -- 7. Managed Certificates (32 certs across multiple issuers and environments)
-- ============================================================ -- ============================================================
INSERT INTO managed_certificates (id, name, common_name, sans, environment, owner_id, team_id, issuer_id, renewal_policy_id, status, expires_at, tags, last_renewal_at, last_deployment_at, created_at, updated_at) VALUES INSERT INTO managed_certificates (id, name, common_name, sans, environment, owner_id, team_id, issuer_id, renewal_policy_id, status, expires_at, tags, last_renewal_at, last_deployment_at, created_at, updated_at) VALUES
-- ---- Active, healthy production certs (Local CA) ---- -- ---- Active, healthy production certs (Local CA) ----