Gongbu server operations#
Advanced: most operators run Gongbu through the managed local stack (
hubu stack); this page covers runninggongbu-serverby hand. See the local stack quick start.
gongbu-server is the supported persistent local execution-plane runtime. It
owns the Gongbu API, SQLite database, artifact store, Temporal worker, and—in
managed_local mode—the local Temporal child. Hubu remains a separately
provisioned service.
Build and configure#
cargo build --release --locked -p gongbu-api --bin gongbu-server
Copy examples/gongbu/gongbu.server.json
to an operator-owned absolute path. The file passed to --config is the only
runtime configuration source; unknown fields are rejected and changes require
a graceful restart. Replace REPLACE_WITH_EXACT_HUBU_PRODUCT_VERSION with the
exact product_version reported by the selected hubu-server --version,
including any leading v and prerelease suffix. Hubu and Gongbu binaries must
come from one compatible, release-stamped lineage. The exact-tag source
installer is the recommended initial-user macOS path.
All state, catalog, artifact, and managed Temporal paths must be absolute. Raw tokens and provider keys never belong in JSON. Provider and explicit service overrides use Gongbu-owned secret coordinates. A launcher-managed stack instead uses fixed internal service references backed by private profile state; those locations are derived and never become operator JSON or TOML input. Schema version 3 selects no execution account or agent: the authenticated caller capability identifies the installation/service and contains no execution identity claim.
gongbu-server credentials bootstrap-managed is a launcher-internal interface,
not a human setup command. After the final Hubu process is ready, it reads the
Hubu capability from a file descriptor-safe private path, proves that capability
against a protected Hubu route, and creates or reuses Gongbu's caller and Hubu
handoff state with private permissions. Repeated calls are idempotent, conflicts
fail closed, and output is categorical; secret values never enter arguments,
configuration, output, or logs.
Use providers: {"mode":"disabled"} for dependency or configuration work that
must not permit provider traffic. Live mode requires an exact target, complete
pricing, a credential reference, a positive spend ceiling, and the literal
live-spend acknowledgement.
Accounting-units database upgrade#
Gongbu v0.2.4 records authorizations, Hubu authorization snapshots and
receipts in micro-units. When it opens its repository it adds the
*_units and units_scale columns and converts every existing whole-cent
amount exactly (×10⁴) in one transaction. It checks every row before
committing and refuses to migrate an amount beyond the micro-unit range. The
whole-cent columns stay as conservative projections. Reopening the database is
idempotent. Take a cold backup of Gongbu state before upgrading, as for any
migration.
Precise-cost database upgrade#
The precise-cost database migration runs when Gongbu opens its SQLite repository. It converts
legacy v4.3 provider-attempt and receipt minor-unit amounts to exact integer
amounts with decimal scale 2 and the already stored currency. Existing frozen
execution pricing JSON, execution IDs, provider-attempt IDs, receipt IDs, and
Hubu settlement IDs remain unchanged. A migrated legacy receipt records the
same retry payload the old binary sent: provider_request_id is its receipt ID,
and price_model_snapshot is the old reduced provider/model/estimated-price
projection reconstructed from the frozen execution snapshot. New receipts keep
the provider-reported reference and complete frozen snapshot. Reopening the
database is idempotent and must not rewrite an already precise receipt.
Hubu performs a separate migration in the Hubu database. Do not copy either database over the other, point one process at the other process's state, or expect one migration to repair both stores. Before upgrading, stop the stack and take independent cold backups of Hubu state and Gongbu state. An older binary that knows only the legacy columns must use its matching pre-upgrade backup; do not use an upgraded database as a rollback mechanism.
The precise-receipt migration does not change the executor contract version by itself. The current contract, v4.5, still accepts the legacy cents receipt shape, and all four binaries must report the same contract version. New precise receipts carry exact amount, scale, currency, and the complete frozen pricing snapshot. If an older Hubu rejects that additive shape after a provider charge, Gongbu retains the receipt and enters reconciliation. Upgrade the installation before resolving the charge; never retry the provider or discard precision to force settlement.
Temporal mode#
In managed_local mode, configure an absolute, version-pinned Temporal CLI.
Gongbu runs the local service on loopback, retains its data and log, supervises
the child, and stops only that child during shutdown.
For an external service:
{
"mode": "external",
"address": "http://127.0.0.1:7233",
"namespace": "default",
"task_queue": "gongbu-local-executions",
"ui_url": "http://127.0.0.1:8233"
}
Gongbu never starts or stops external Temporal. In both modes, readiness requires an active worker polling the configured task queue.
Startup still requires a positive Temporal poller proof and Hubu compatibility proof before Gongbu can become ready. After startup, a single failed dependency probe does not stop Gongbu. Hubu probes include protected access with the credential Gongbu loaded, not just public health and version. The supervisor allows a fixed 30-second recovery grace so routine gRPC connection rotation and other transient transport failures can reconnect.
Temporal's normal task-queue RPC receives one immediate bounded confirmation
when it returns gRPC Code::Cancelled. If that confirmation is also cancelled,
the monitor keeps tracking the failure count and original grace-window start,
but preserves readiness only when startup already supplied the positive poller
proof and only while the window remains strictly below 30 seconds. Cancellation
never establishes or restores readiness. Every successful Temporal task-queue
RPC confirms runtime reachability, including a response with an empty historical
poller list. Every non-cancelled Temporal error and any Hubu failure withdraw
readiness and new execution admission immediately. A healthy sample restores
readiness only after all dependencies are healthy and resets its own failure
window. An uninterrupted cancellation sequence withdraws readiness at the
grace boundary, but dependency observations never terminate Gongbu. Runtime
probe intervals are capped at the grace duration so readiness is re-evaluated
within the documented bound while recovery probing continues.
The gongbu_dependency_probe log event records only the dependency, outcome,
consecutive monitor-sample count, and a redacted gRPC status code when
available. The two RPCs in one cancellation confirmation do not increment that
monitor-sample count separately.
Validate and start#
Validation creates no state, reads no Keychain secret, and connects to no dependency:
target/release/gongbu-server validate-config --config /absolute/path/gongbu.json
Start the independently configured Hubu service first, then Gongbu:
target/release/gongbu-server serve --config /absolute/path/gongbu.json
curl -fsS http://127.0.0.1:8788/livez
curl -fsS http://127.0.0.1:8788/readyz
curl -fsS http://127.0.0.1:8788/version
These GET endpoints expose safe status and compatibility metadata only. All
execution and artifact endpoints require the caller capability. A 503 from
/readyz means new admission is closed. Runtime Temporal or Hubu degradation
withdraws /readyz without terminating Gongbu or its managed Temporal child;
/livez remains successful while the HTTP process is functioning. Gongbu keeps
probing withdrawn dependencies and restores readiness automatically after they
recover. Existing execution and artifact reads remain available while readiness
is withdrawn.
An authenticated GET /v1/provider-catalog returns the sanitized schema-v1
provider contract projection. For the shipped FLUX provider contract it includes the
exact target, model, presets, rational USD pricing, policy versions, and the
separate configured, credential-reference-present, production-validated, and
live-qualified facts. It never exposes Keychain coordinates or values and does
not call BFL. credential_reference_present becomes true only after server
startup resolved the configured item; live_qualified remains false with
not_performed in this release.
The same installation caller can access a known execution and its artifacts regardless of which of the owner's agents Hubu attributed it to. This is not an owner-wide browsing API—clients must already know the execution or artifact ID—and it is not strong multi-user or per-agent isolation.
Submit and inspect#
The version-2 execution request supplies only the authorization token and execution intent selected from operator configuration:
{
"schema_version": 2,
"spend_auth_token_id": "00000000-0000-4000-8000-000000000123",
"input": {"prompt": "A small blue circle", "image_count": 1},
"input_schema_version": 1,
"target_id": "gongbu:target:v1:DISCOVERED_OPAQUE_ID"
}
curl -fsS -H "Authorization: Bearer $CAPABILITY" \
-H 'Content-Type: application/json' \
-d @execution.json \
http://127.0.0.1:8788/v2/executions
curl -fsS -H "Authorization: Bearer $CAPABILITY" \
http://127.0.0.1:8788/v1/executions/EXECUTION_ID
curl -fsS -H "Authorization: Bearer $CAPABILITY" \
http://127.0.0.1:8788/v1/executions/EXECUTION_ID/artifacts
For a new token, Hubu's resolved spend authorization is authoritative for the persisted execution account and agent. Submitting an identical body first replays the persisted token locally and does not ask Hubu to resolve a token that may already be claimed or settled. A changed immutable field conflicts. Settlement and release use the persisted execution agent. On restart, Gongbu reschedules nonterminal executions at their stable workflow IDs and never creates a second provider or financial side effect merely to recover scheduling.
New POST /v2/executions admission returns retryable 503 not_ready while
readiness is withdrawn. A Temporal scheduling failure that races with admission
uses the same response after Gongbu has durably created the pending execution.
Retry the identical request with the same spend-auth token: Gongbu reuses that
pending execution locally and schedules its stable workflow ID instead of
resolving the Hubu authorization or creating another execution.
For asynchronous FLUX work, that stable workflow separates one
patch-protected submit_provider activity from
poll_provider_operation. A successful submit checkpoints only the safe
request ID, operation ID, validated BFL polling host, and original absolute
deadline in Gongbu SQLite before long polling. Temporal carries only the
execution ID and phase enum; credentials, raw bodies, polling or signed URLs,
and artifact storage paths remain outside its payloads.
Use these recovery dispositions when inspecting an interrupted execution:
- A failure proven to precede transmission is non-billable and may release the Hubu authorization.
- If submission may have succeeded but interruption occurred before the operation checkpoint committed, preserve the execution for reconciliation. Do not create a new operation key, resubmit the generation, or release the claim.
- If the checkpoint committed, restart Gongbu normally. The worker resumes GET
polling for that same operation under the original deadline, with the same
ProviderAttemptand no second Hubu financial mutation.
An expired original deadline is not refreshed by restart. Execution detail
stops recommending reinspect, Gongbu refuses to reopen the poll-existing
path, and the operator should contact provider support while continuing to
inspect the existing execution and reconciliation record. Never submit a
replacement operation.
Agents normally use these routes through Unified MCP.
Diagnose rejected admission#
An HTTP 400 response may add one safe diagnostic to the existing
invalid_request error: target_not_selectable names either target_id or the
four legacy target fields, while pricing_selector_not_matched names
input.image_size. Gongbu reports field paths only and never echoes their
submitted values. Use authenticated GET /v2/execution-targets (normally via
gongbu_list_execution_targets) to refresh the active operator-approved
choices before creating corrected work.
The first occurrence of each allowlisted route-version/reason pair in a Gongbu process writes one structured line to stderr (and thus to a launcher-managed Gongbu process log when stderr is captured):
{"event":"gongbu_admission_rejected","route":"create_execution","route_version":2,"status":400,"code":"invalid_request","reason_code":"pricing_selector_not_matched","fields":["input.image_size"]}
No event is written for generic, malformed, or unknown diagnostics. The event
never contains request bodies, values, identifiers, target values, or raw
errors, so use the returned field paths to compare the request with the active
operator configuration rather than expecting the log to reproduce either.
Managed Gongbu logs append across process starts, so an event may predate the
current process. Admission rejections have no execution ID; inspect them with
hubu stack logs --component gongbu --lines 100, without --execution-id.
Shutdown and backup#
Send SIGINT or SIGTERM. Gongbu removes readiness, stops accepting requests, drains its worker within a bound, and stops only a managed Temporal child. Hubu and external Temporal remain untouched.
For a consistent cold backup, stop Gongbu and copy its SQLite database, artifact root, managed bootstrap credential state, and managed Temporal data directory together. Do not restore only one part of that set. Treat the backup as secret material and preserve private access controls.
When billing is ambiguous, preserve the execution and provider evidence and use the authenticated reconciliation path. Do not create a new operation key, blindly repeat provider work, or release the Hubu claim.