RelayCtl is an open-source control plane for monitoring and managing NewAPI, CLIProxyAPI, CPA Manager Plus, and Sub2API from one place.
It is deliberately out of band: model traffic continues to flow through your existing gateways. RelayCtl normalizes health and usage signals, keeps edge metrics separate from upstream metrics, and exposes only a fixed allowlist of official management actions.
The first stable self-hosted release provides:
- Go HTTP API with PostgreSQL persistence and an explicit in-memory test mode.
- Envelope-encrypted platform credentials.
- Read-only connection probes for NewAPI, CLIProxyAPI, CPAMP, and Sub2API.
- Embedded, checksum-verified database migrations and a leased multi-stream collection scheduler.
- Sub2API account inventory with field allowlisting, paginated snapshots, soft deletion, and ETag support.
- Sub2API 30-day daily usage collection with idempotent PostgreSQL buckets and ETag
304preservation. - NewAPI channel inventory with paginated, key-free field allowlisting and soft deletion.
- NewAPI 30-day edge usage from hourly dashboard aggregates, including successful requests, total tokens, and quota-derived USD cost.
- CLIProxyAPI auth-file inventory with strict token/path/account field exclusion and HMAC-only external identities.
- CLIProxyAPI API-key request monitoring from the process-local 200-minute window, normalized into persisted 10-minute buckets without storing raw keys.
- CLIProxyAPI masked client-key inventory and an allowlisted configuration resource assembled from eight narrow official endpoints; the full upstream configuration document is never fetched.
- CPAMP collector-state inventory, bounded Dashboard Summary aggregates, and UTC daily calls, success/failure, token, and estimated USD-cost analytics.
- Sub2API group inventory with account, usage, and capacity summaries when those optional official endpoints are supported.
- Server-side resource search, health assessment, sorting, pagination, resource detail, and collection-stream diagnostics.
- Usage reporting with equal-length period comparison, per-instance source coverage, honest unavailable/no-data states, and database-side aggregation.
- Safe usage breakdowns for NewAPI model data and any optional channel/group dimensions actually returned by the upstream, plus CLIProxyAPI provider/upstream-host/API-key fingerprints, including current and previous totals.
- React dashboard with resource investigation, usage rankings and efficiency indicators, manual sync, connection testing, instance management, events, and settings views.
- Resource management with explicit confirmation, structured operation audit, and automatic post-action resource refresh.
- Versioned management forms for NewAPI channel routing, Sub2API group/account membership, and CLIProxyAPI safe runtime configuration and client-key lifecycle operations.
- Persistent management tasks that preview and execute one allowlisted action across up to 100 compatible resources, with bounded concurrency, cancellation, and failed-item retry.
- Persistent alert and incident center for instance outages, stale collectors, unavailable resources, consecutive failures, usage thresholds, and cost budgets.
- Fingerprint-based alert deduplication with acknowledgement, timed silence, automatic recovery, operator recovery, and a complete event timeline.
- Encrypted Webhook, Telegram, and SMTP notification channels with bounded retries, HMAC webhook signing, test deliveries, and delivery history.
- Dashboard alert severity counts and aggregated risk-resource groups without creating one incident per account.
- Persistent
managesandroutes_torelationships, including NewAPI channel-to-CLIProxyAPI/Sub2API mapping, traffic shares, notes, enable/disable, and a real-topology dashboard summary. - Cross-platform topology attribution for entry success rate, upstream success rate, retry amplification, edge/upstream cost, and cost difference, with explicit observed, estimated, partial, and unavailable quality states.
- Route-stage fault localization and capacity views covering edge instances, channels, upstream instances, resource pools, collectors, attribution coverage, and CPAMP management links.
- Persisted per-instance capability matrices with endpoint, method, access mode, minimum version, evidence, and unsupported reason. Discovery sends only allowlisted read requests; write support is derived without mutating upstream state.
- CLIProxyAPI plugin inventory with strict metadata allowlisting, CPAMP recognition, and one-step creation or linking of a CPAMP instance plus its
managesrelationship. - Collection diagnostics for failed, stale, zero-row,
304 Not Modified, unsupported, denied, version-blocked, and field-missing states, including a dedicated CLIProxyAPI usage-zero decision tree. - Capability-driven single-resource forms and batch actions, so unsupported management controls are omitted by the API instead of failing only after an operator submits them.
- Unified request telemetry from Sub2API Ops, NewAPI request logs, and allowlisted CLIProxyAPI Gin summaries, normalized into one client/channel/account/rate-limit/quota/model/upstream error taxonomy.
- A request reliability workspace with P50/P95/P99 latency, throughput, error rate, editable availability SLOs and 1h/6h/24h burn rates, source coverage, explicitly scored exact/estimated cross-platform correlations, anomaly detection, capacity forecasts, and a combined failure timeline.
- A unified tenant and billing catalog for NewAPI users, administrator-scoped Tokens, subscriptions, plans, and redemption codes, plus Sub2API users, API Keys, balances, subscriptions, effective RPM, and per-platform quotas.
- Tenant-level revenue, upstream cost, gross margin, budget utilization, seven-day balance burn, estimated exhaustion, and anomalous-call rankings, with explicit unavailable or partial coverage when an upstream omits a dimension.
- Revision-checked fixed forms and a persistent approval queue for every upstream balance, quota, Token, API Key, RPM, or redemption-code change. Approval history includes the preview, impact, decision, execution result, and timeline without retaining plaintext credentials.
- Periodic and on-demand configuration snapshots with checksums, field coverage, field-level diffs, revisioned desired-state templates, open/resolved drift, and non-executing remediation suggestions.
- Scheduled governance changes with timezone-aware maintenance windows, a separate explicit approval step, leased execution, verified fixed-form rollback, and an append-only change timeline.
- Alert runbook bindings that turn matching resource-unavailable incidents into approval-required fixed-action suggestions and reuse sanitized failure notifications when an approved recovery fails.
- Loopback Host/Origin enforcement for every API write, with optional session-scoped operator-token authentication.
- NewAPI single-channel enable/disable, connection test, and supported-channel balance refresh.
- Sub2API account enable/disable, scheduling pause/resume, runtime-state recovery, and OAuth credential refresh.
- CLIProxyAPI auth-file enable/disable and quota/cooldown reset without exposing the upstream auth-file locator.
- Versioned fixed forms for NewAPI channel routing, Sub2API group/account membership, and CLIProxyAPI safe configuration plus client-key creation, rotation, and deletion.
- Persistent batch tasks with impact preview, a 100-resource limit, concurrency from 1 through 8, leased execution and recovery, truthful cancellation states, per-item progress, and failed-item retry.
- Immutable task-item scope snapshots that keep resource and instance names, platform, and resource kind readable after the live resource or instance is deleted.
- Local multi-user authentication with Argon2id passwords, revocable idle/absolute sessions, six built-in roles, and route-level permissions for every API operation.
- Restricted API Clients with one-time creation and revision-checked in-place token rotation, immediate old-token revocation, read-only or event-publish scopes, rate limits, and idempotent third-party event ingestion.
- Hourly request downsampling, configurable historical retention, expired-session cleanup, and operator-visible maintenance history.
- PostgreSQL custom-format backups with SHA-256 manifests, minimum-count retention, and scheduled restores into disposable isolation databases.
- Prometheus/OpenMetrics, OTLP/HTTP tracing, a provisioned Grafana dashboard, OpenAPI 3.1 integration contracts, and a tested Go connector SDK.
- Production Docker and Windows Service assets, metadata-only release checks, verified upgrade/rollback scripts, and a deployment runbook.
- Connector contract and security tests.
- Production deployment: English | 简体中文
- Maintainer release and version updates: English | 简体中文
- RelayCtl v1.0.0 release notes
- Architecture, connector contracts, and integration API
- Security policy and contribution guide
Requirements: Go 1.24 or later, Node.js 22 or later, and PostgreSQL 17.
Create a dedicated local database and role (skip this if they already exist):
CREATE ROLE relayctl LOGIN;
CREATE DATABASE relayctl OWNER relayctl;Generate one stable master key and start the API from PowerShell:
$bytes = New-Object byte[] 32
$random = [Security.Cryptography.RandomNumberGenerator]::Create()
$random.GetBytes($bytes)
$random.Dispose()
$env:APIM_MASTER_KEY = [Convert]::ToBase64String($bytes)
$env:APIM_STORE = "postgres"
$env:APIM_DATABASE_URL = "postgres://relayctl@127.0.0.1:5432/relayctl?sslmode=disable"
$env:APIM_DEMO_DATA = "false"
$env:APIM_ALERTS_ENABLED = "true"
go run ./cmd/serverKeep the same APIM_MASTER_KEY across restarts. Changing or losing it makes previously stored credentials undecryptable. Numbered migrations run automatically during startup.
For local Windows development, the helper script generates and reuses an ignored .relayctl/master-key file:
.\scripts\start-api.ps1Back up that key securely before storing real platform credentials. RelayCtl rejects a different key on later startups. The default configuration refuses non-loopback APIM_ADDRESS values.
For a remote deployment, set APIM_ALLOW_REMOTE=true only behind TLS, set APIM_SESSION_SECURE=true, list each exact HTTPS origin in APIM_ALLOWED_ORIGINS, and list only the API-facing reverse proxies in APIM_TRUSTED_PROXY_CIDRS. Forwarded client addresses are ignored unless the direct peer is trusted. Remote cookie writes require an allowed Origin and cross-site writes are rejected. Interactive /auth/setup remains loopback-only; use the one-time APIM_BOOTSTRAP_ADMIN_USERNAME and APIM_BOOTSTRAP_ADMIN_PASSWORD variables for initial remote provisioning.
The alert worker is enabled by default and evaluates enabled rules every 30 seconds. APIM_ALERTS_ENABLED=false stops both evaluation and notification delivery while keeping rule, incident, and history data readable. Built-in health rules are enabled by default; usage and cost-budget rules remain disabled until you set a meaningful threshold in 告警与事件 → 规则. Notification channel connection data is encrypted with the same stable APIM_MASTER_KEY used for platform credentials, and is never returned by the API.
The persistent management worker is also enabled by default. APIM_MANAGEMENT_WORKER_ENABLED=false stops queued task execution while keeping task and item history readable. Single-resource actions and versioned forms remain available through their normal request paths.
The governance worker is enabled by default. APIM_GOVERNANCE_WORKER_ENABLED=false keeps snapshots, drift evaluation, suggestions, approvals, maintenance windows, and timelines readable, but stops approved governance changes and rollbacks from being claimed. Run exactly one governance worker set against a production database unless horizontal worker leasing has been deliberately tested for that deployment.
For an additional write-authentication layer, generate a separate operator token before starting the API:
$operatorBytes = New-Object byte[] 32
$operatorRandom = [Security.Cryptography.RandomNumberGenerator]::Create()
$operatorRandom.GetBytes($operatorBytes)
$operatorRandom.Dispose()
$env:APIM_OPERATOR_TOKEN = [Convert]::ToBase64String($operatorBytes)When APIM_OPERATOR_TOKEN is configured, every POST, PUT, PATCH, DELETE, or other non-read API request must send the same value in X-RelayCtl-Operator-Token. In the web app, open 设置 → 写操作认证 and save the token for the current tab. The browser stores it only in sessionStorage, sends it only on write requests, and removes it when you clear the setting or close the tab. RelayCtl never stores this token in PostgreSQL or includes it in logs or API responses. The PowerShell helper inherits APIM_OPERATOR_TOKEN when it is already set.
If the web app runs on a different local port, add its exact origin to APIM_ALLOWED_ORIGINS, for example http://127.0.0.1:5173. When APIM_OPERATOR_TOKEN is not set, the existing loopback workflow continues without a token.
Start the web app in a second terminal:
cd web
npm install
npm run devOpen http://localhost:5173. On the first visit, create the initial Owner with your own username and strong password; RelayCtl does not ship a default login. The API health endpoints are healthz and readyz.
For an ephemeral demo without PostgreSQL:
$env:APIM_STORE = "memory"
$env:APIM_DEMO_DATA = "true"
go run ./cmd/serverBefore using real credentials, generate a stable 32-byte master key in PowerShell:
$bytes = New-Object byte[] 32
[Security.Cryptography.RandomNumberGenerator]::Fill($bytes)
$env:APIM_MASTER_KEY = [Convert]::ToBase64String($bytes)
$env:APIM_DEMO_DATA = "false"
go run ./cmd/serverCredential requirements:
| Platform | Required credential |
|---|---|
| NewAPI | Administrator system access token and decimal administrator user ID |
| CPA Manager Plus | Independent CPAMP admin key |
| CLIProxyAPI | Management key; remote access must be enabled upstream |
| Sub2API | Long-lived admin API key sent as x-api-key |
Do not paste credentials into issue reports or logs. RelayCtl never returns stored credential values through its API.
- CPA
usage-queueis never read because that operation consumes records. - NewAPI edge requests and upstream attempts are never combined into a single total.
- CPAMP becomes the usage authority when it manages a CPA instance.
- Redirects are disabled for management requests.
- HTTP response bodies are limited and sensitive raw payloads are not persisted.
- Sub2API compliance-required state is shown as degraded rather than a bad credential.
- The browser can request only action IDs advertised by RelayCtl; it cannot supply an upstream method, path, headers, or payload.
- API writes require a loopback Host by default. Explicit remote mode accepts only configured HTTPS browser origins; an optional
APIM_OPERATOR_TOKENadds a second factor to authenticated management writes. - Every action is confirmed in the UI and recorded as
running,succeeded, orfailed. Audits store safe result fields and error codes, never upstream response text. - NewAPI channel tests send a real upstream request and may incur a small charge. RelayCtl does not expose arbitrary upstream bulk endpoints; its persistent task worker can only orchestrate an existing allowlisted single-resource action after a fresh preview and explicit confirmation.
- Management forms use an upstream-derived revision, reject stale edits, send only fixed allowlisted fields, and verify the resulting state by reading it back.
- Newly generated CLIProxyAPI client keys are returned once in
oneTimeSecret; RelayCtl does not persist them in its database, audit records, resource snapshots, or task results. - Expired task items are replayed automatically only for explicitly idempotent actions. Connection tests and credential refreshes become
execution_outcome_unknownand require an operator to inspect the upstream before explicitly retrying. - A
404or405from an optional official action is reported as unsupported by that instance version, not as an instance outage. - Request observations retain only fixed normalized fields, allowlisted dimensions, and SHA-256 request fingerprints. Raw request IDs, IPs, paths, authorization headers, API keys, upstream response bodies, and complete CPA log lines are never stored or returned.
- Tenant budgets are RelayCtl-local operating controls and never change an upstream balance. Upstream balance, quota, Token, API Key, RPM, and redemption-code forms cannot bypass the approval queue; approval re-resolves the resource and revision before executing the connector-owned payload.
- NewAPI's official Token list is administrator-self scoped. Sub2API platform-quota writes replace the complete per-user platform list, so RelayCtl rereads it, preserves other supported platforms, previews the replacement scope, and verifies the final state.
See connector contracts and architecture for details.
The third-stage deep-management milestone is implemented with these boundaries:
| Area | Delivered behavior | Boundary |
|---|---|---|
| CPAMP collection | Health and authenticated probes, a sanitized /status collector resource enriched by a bounded Dashboard Summary, and ETag-aware UTC daily analytics for calls, outcomes, tokens, and estimated USD cost. |
Dashboard Summary and analytics are optional official endpoints. 404 or 405 is reported as unsupported; RelayCtl does not invent missing metrics or expose a CPAMP write form. |
| NewAPI fixed form | Per-channel weight, priority, model selection, and group selection with an upstream-derived revision, impact preview, stale-write rejection, a strict payload, and read-back verification. | This is not an unrestricted channel editor. Secrets, base URLs, headers, and arbitrary fields are excluded. |
| Sub2API fixed forms | Group activation and account group-membership maintenance, including active-group validation and the official mixed-channel preflight before a membership write. | Full account edits, credential backup, quota reset, and arbitrary batch requests remain outside the allowlist. |
| CLIProxyAPI fixed forms | Eight independently readable safe configuration fields plus client-key creation, rotation, and deletion. | The complete /v0/management/config document is never fetched. Unsupported versions do not receive unusable form descriptors. |
| Recoverable batch tasks | A fresh compatibility preview and impact scope, explicit confirmation, at most 100 resources, concurrency from 1 through 8, per-item attempts and safe errors, 60-second worker leases, and failed-item retry. | This is RelayCtl orchestration over existing allowlisted single-resource actions, not an upstream bulk endpoint. Only explicitly replay-safe actions are requeued after an expired lease. |
CLIProxyAPI keys created or rotated through a fixed form are returned once as oneTimeSecret. RelayCtl never writes the plaintext to PostgreSQL, logs, operation audits, resource snapshots, or task results; later inventory contains only a masked label and HMAC identity.
Cancellation reflects the remote execution boundary. A queued task can finish as canceled immediately. If any item is already running, RelayCtl cancels queued items and changes the task to cancel_requested; the UI shows 取消中, disables another cancel request, and keeps polling. RelayCtl cannot retract an HTTP request that the upstream has already accepted. After every running item reports its real outcome, the task derives its terminal succeeded, partial, failed, or canceled state from the final item summary.
Each task item stores an immutable scope snapshot containing the resource and instance identifiers and names, platform, and resource kind. Deleting the live resource clears only its nullable foreign-key reference. Task history and its safe result/error state remain readable; a missing live resource is never silently substituted with another resource.
Open 拓扑归因 and add one of these local control-plane relationships:
manages: CPA Manager Plus instance to CLIProxyAPI instance.routes_to: NewAPI instance or one of its collected channels to a CLIProxyAPI or Sub2API instance.
Topology changes update only RelayCtl's instance_relationships table. They do not edit NewAPI channels, proxy routing, accounts, or auth files upstream. Enabled traffic shares for the same source endpoint may total at most 100 percent.
The API surface is intentionally narrow:
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/api/v1/topology?from=...&to=... |
Read relationships, chains, attributed metrics, faults, and capacities |
GET |
/api/v1/topology/relations |
List saved relationships |
POST |
/api/v1/topology/relations |
Create a relationship |
PATCH |
/api/v1/topology/relations/{id} |
Change enabled state, traffic share, or notes |
DELETE |
/api/v1/topology/relations/{id} |
Remove a relationship from future attribution |
RelayCtl never promotes missing dimensions into exact data. A NewAPI detail row with channel_id = 0 cannot be assigned to a configured channel, so channel-level request, success, retry, and cost metrics remain unavailable. When valid channel IDs exist, the edge side can be observed directly. A shared upstream total may be estimated across routes only when entry request weights are available. Success rates require both success and error counters; retry amplification is attributed upstream attempts divided by edge requests; cost difference is attributed upstream cost minus edge billed cost.
Health probes persist both the connector's stable capability IDs and a detailed matrix in the existing instance_capabilities table. A supported read capability means RelayCtl received a successful response from the listed allowlisted endpoint. A write or execute capability is marked supported only when its read dependency and minimum version are satisfied; capability discovery never sends POST, PUT, PATCH, or DELETE upstream.
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/api/v1/diagnostics |
Read all instance, stream, capability, plugin, and field diagnostics |
GET |
/api/v1/diagnostics?instanceId={id} |
Read one instance diagnostic |
GET |
/api/v1/instances/{id}/capabilities |
Read the persisted capability matrix |
POST |
/api/v1/resources/{pluginId}/cpamp-link |
Create or link a CPAMP instance from a recognized CLIProxyAPI plugin |
The CPAMP link request accepts mode: "link" with an existing CPAMP instanceId, or mode: "create" with name, baseUrl, and adminKey. The CPAMP admin key is independent from the CLIProxyAPI management key. On create, RelayCtl compensates a failed relationship write by deleting only the CPAMP instance created by that request.
The CLIProxyAPI plugin collector stores plugin ID, display metadata, version, author, repository, lifecycle flags, OAuth support, and the CPAMP recognition result. It deliberately excludes filesystem paths, logos, config fields, config values, and arbitrary plugin payloads.
Open 请求可靠性 at /reliability to inspect the request-level read model. RelayCtl prefers NewAPI edge observations for global metrics and SLOs so one client request is not added to its downstream attempts. When the selected range has no edge observations, it explicitly falls back to the upstream sources and warns that multi-hop totals may overlap.
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/api/v1/reliability?from=...&to=...&instanceId=... |
Read normalized metrics, trend points, error classes, sources, correlations, anomalies, capacity forecasts, and timeline events for a range of at most 30 days |
GET |
/api/v1/reliability/slo |
Read the global request availability and latency policy |
PATCH |
/api/v1/reliability/slo |
Update the policy name, four-decimal target from 90 inclusive to 100 exclusive, 50..600000 ms latency objective, or 1..30 day window |
Unknown outcomes are excluded from the success-rate denominator and missing latency is excluded from percentiles. Burn rate is the observed error rate divided by the policy error budget for 1h, 6h, and 24h windows. Exact cross-platform correlations require a matching SHA-256 request fingerprint. Without a shared public request ID, RelayCtl scores a one-to-one estimate from time offset, model, channel, outcome, error class, and an enabled routes_to relation, then labels the result high, medium, or low confidence.
Ranges beyond the configured raw-request window read request_rollups_hourly together with the remaining request rows. Maintenance uses one DELETE ... RETURNING statement to publish exactly the raw evidence it removes; rows arriving outside that statement snapshot remain visible until the next merge. Only rollup hours wholly contained in [from,to) are used; partial boundary hours are omitted instead of being scaled or overcounted. Historical request counts and error classes remain exact, while merged latency percentiles and latency-SLO compliance are explicitly estimated from a stable 24-bucket histogram. Correlations and request-dimension capacity trends continue to use raw evidence only.
Anomaly detection compares the latest hour with the preceding six hours and requires minimum sample counts before reporting error-rate spikes, P95 latency spikes, or throughput drops. Capacity analysis forecasts Sub2API group RPM from recent request trend and NewAPI USD channel balance from observed seven-day channel cost. Missing capacity or cost evidence remains unavailable; a zero balance without consumption evidence is not promoted to an exhaustion alert.
Request observation and hourly-rollup retention are controlled independently from the operations page. (instance_id, source, source_key) is the raw idempotency boundary, and every accepted source must satisfy a fixed source-specific dimension contract before persistence. A high-volume first Sub2API collection progressively narrows its lookback toward a 25-page target, permits at most 100 pages at the 15-minute floor, marks the report as truncated, and then resumes normal cursor-based collection with a one-minute overlap.
Open 租户与计费 at /tenant-operations. The page combines the latest normalized tenant resources with persisted tenant-attributed request and usage signals. Money is stored as integer microunits. A value is reported as unavailable instead of zero when the upstream did not supply the necessary revenue or cost evidence.
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/api/v1/tenant-operations?from=...&to=...&instanceId=...&query=... |
Read KPI totals, daily economics, tenant risk, catalog, and source coverage for at most 90 days |
PUT |
/api/v1/tenant-budgets/{resourceId} |
Create or revise a RelayCtl-local weekly, monthly, or rolling-30-day tenant budget using optimistic revision control |
GET |
/api/v1/management/approvals?status=...&instanceId=... |
List approval records and their timelines |
POST |
/api/v1/management/approvals |
Persist the fresh fixed-form preview and request a decision |
GET |
/api/v1/management/approvals/{id} |
Read one approval, field diff, impact, result, and timeline |
POST |
/api/v1/management/approvals/{id}/approve |
Approve, immediately execute the revision-checked connector form, and record success or failure |
POST |
/api/v1/management/approvals/{id}/reject |
Reject a pending approval without calling the upstream |
NewAPI collection covers users and quotas, the current administrator's Tokens, subscription plans and per-user subscriptions, and redemption codes when the corresponding official endpoints exist. Its fixed forms cover user quota set/add/subtract, Token status and quota/expiry, and redemption status and value/expiry. The official Token endpoint does not provide every user's Tokens, so that catalog is explicitly marked partial.
Sub2API collection covers users, balances, embedded subscriptions, per-user API Keys, effective RPM, and Anthropic, OpenAI, Gemini, Antigravity, and Grok platform quotas. Its fixed forms cover balance set/add/subtract, RPM, API Key group, API Key 5h/1d/7d usage reset, and daily/weekly/monthly platform limits. The official balance endpoint requires a positive amount, so RelayCtl does not present a direct set-to-zero operation.
All of these upstream-changing forms are connector-owned allowlists. Preview and approval values reject secret-shaped fields, only one open approval may exist for the same resource and form, and approval performs remote HTTP outside database transactions. A failed read-back becomes a terminal failed approval with a safe error code and message; it is never silently reported as successful.
The seventh-stage governance milestone is available at 配置治理 (/governance):
| Area | Delivered behavior | Boundary |
|---|---|---|
| Configuration snapshots | Every successful resource collection captures the supported fixed-form values. Operators can also capture all instances or one instance on demand. Snapshots include a SHA-256 checksum, field coverage, missing fields, and field-level added/changed/removed diffs. | Snapshots contain only fields already exposed by connector-owned fixed forms. Secrets and arbitrary upstream configuration documents are never copied into governance storage. |
| Desired state and drift | Revisioned templates can target a platform or one instance and currently cover NewAPI channel routing, CLIProxyAPI safe configuration, Sub2API group state, and Sub2API account groups. Collection and manual capture reconcile open/resolved drift and create or refresh a remediation suggestion. | A template cannot introduce a field or value outside the existing form schema. Disabling or deleting a template resolves its drift and expires unhandled suggestions. |
| Change planning | A suggestion may be dismissed or submitted with an optional future time, maintenance window, and automatic rollback policy. Submission creates a separate pending_approval change and a durable event timeline. |
Submission is not approval. The browser requires another explicit confirmation before approve; rejected changes never enter the worker queue. |
| Execution and rollback | The leased governance worker executes approved fixed forms/actions at the selected time and inside the selected timezone-aware maintenance window. Form writes revalidate the current revision and are read back. Failed form changes can enter rollback and verify the restored values. | Fixed actions with an uncertain outcome are never replayed automatically after a worker lease expires. Automatic rollback is available only when a complete reversible form snapshot exists. |
| Alert runbooks | Enabled bindings match resource_unavailable incidents to an advertised fixed recovery action. The built-in Sub2API account runbook proposes recover_state, then emits the existing failure notification path if execution fails. |
Alert evaluation only creates a suggestion. The action still requires submission and explicit approval; runbooks cannot provide an upstream URL, method, headers, or arbitrary payload. |
The governance state flow is:
suggested -> submitted/pending_approval -> approved -> scheduled -> executing -> succeeded
| |
| +-> failed -> rollback_pending -> rolled_back
+-> rejected \-> rollback_failed
For a read-only maintenance or migration session, stop every background executor while leaving the API available:
$env:APIM_SCHEDULER_ENABLED = "false"
$env:APIM_ALERTS_ENABLED = "false"
$env:APIM_MANAGEMENT_WORKER_ENABLED = "false"
$env:APIM_GOVERNANCE_WORKER_ENABLED = "false"Normal production operation needs the scheduler for periodic snapshots, the alert worker for runbook suggestions, and the governance worker for explicitly approved execution. A manual 立即采集快照 remains available when the scheduler is disabled.
Docker is optional when using native PostgreSQL for local development. Once Docker Desktop is installed, the prepared development database can instead be started with:
docker compose -f deploy/docker-compose.yml up -dFor native PostgreSQL, use the passwordless local APIM_DATABASE_URL shown above. Schema migrations are owned by the application, not the container entrypoint.
The Compose service uses port 5433 to avoid colliding with a native PostgreSQL installation. Its connection URL is:
postgres://relayctl:relayctl-dev@127.0.0.1:5433/relayctl?sslmode=disable
cmd/server Go API entry point
internal/application Use cases and dashboard aggregation
internal/connectors Platform-specific collection and allowlisted management adapters
internal/domain Shared domain types
internal/httpapi REST transport
internal/secretbox Envelope encryption
internal/store Store interface, memory implementation, and PostgreSQL repository
internal/database PostgreSQL pool and embedded migration runner
internal/scheduler Leased background health collection
web React + Vite application
migrations PostgreSQL schema
deploy Local infrastructure
docs Architecture and connector contracts
- Longer-lived SLO history, maintenance-window-aware burn alerts, and configurable seasonal anomaly baselines.
- Local Agent for private management networks.
- Escalation policies, change-freeze calendars, and signed release provenance.
- External identity providers, SCIM provisioning, and optional database row-level tenant isolation.
Apache License 2.0. See LICENSE.