Documentation / Reference

Local HTTPS deployment, async callbacks and diagnostics

HTTPS routes, scoped HMAC callback tokens, slim launcher budgets, structured failure reports and bounded multi-model review semantics.

1. Local HTTPS endpoints and authentication

rippflow deploy --local starts a concurrent background HTTPS daemon (ports 8443–8543) sharing one callback router across workflow runs and external workers.

Method & routeAuthenticationBehavior & saved artifacts
POST /v1/workflows/<name>/run
POST /v1/run (?timeoutSeconds=1..900)
Authorization: Bearer rf_tok_...Executes the workflow concurrently, persists .outputs/run-<wf>-<runId>.json and .outputs/last-run.json, and returns 200 (completed), 422 (failed/stalled), 504 (timed out), or 499 (cancelled) with resultsUrl.
POST /v1/callbacks
POST /v1/workflows/<name>/callbacks
callbackToken (rfacb_v1_... scoped_token_hmac)Authenticates external async_tool workers without exposing admin rf_tok_... while enforcing Origin/Sec-Fetch-Site CSRF checks. Exact duplicate delivery returns 200 (duplicate: true); mutated replay returns 409 (CALLBACK_REPLAY_CONFLICT).
GET /v1/runs, GET /v1/runs/latest,
GET /v1/runs/<runId>
Authorization: Bearer rf_tok_...Lists up to 50 recent run summaries or returns the full redacted RunReport envelope (including failed, timed-out, and cancelled runs).
GET /v1/status, GET /v1/analytics,
POST /v1/stop
Authorization: Bearer rf_tok_...Returns redacted deployment metadata, memory/callback profile analytics, or cancels active RunScope process groups and stops the daemon.
json
{
  "action": "async_callback",
  "tenantId": "local",
  "workflowId": "<requestId>",
  "phaseId": "reviewer_a",
  "iterationId": "<iterationId>",
  "operationId": "<operationId>",
  "dispatchGeneration": 1,
  "callbackToken": "rfacb_v1_<scoped-hmac>",
  "status": "COMPLETED",
  "resultPayload": { "verdict": "approved", "reviewedCommitSha": "abc1234" }
}

2. Slim launcher budgets and runtime diagnostics

An async_tool launcher runs inside the 8-slot active handler pool only until it prints {"outcome":"dispatched"}; worker capacity is then released while external callback wait accrues separately.

ContractFields & runtime behavior
Active vs callback wait budgetexecutionTimeMs and peak RSS enforce the runtime group's active slice/timeout; external wait is recorded in callbackWaitTimeMs under callback.timeout / --timeout-seconds (max 900s).
Partial reports & phase timelinesEvery failure, timeout, and SIGINT/SIGTERM cancellation (exit 130) writes RunReport.phaseTimeline (invocation, phase, shard, loopCount, attempt, operationId, iterationId, dispatchGeneration, startedAtMs, durationMs, callbackWaitMs, failureReason).
Attributed logs & secret redactionChild stderr is piped non-blockingly, scrubbed of rfacb_v1_*, rf_tok_*, and RIPPFLOW_CALLBACK_SIGNING_KEY, prefixed as [<phase>#<shard> round=<L> inv=<N>], and stored in RunReport.logs.
Credential-safe callback rejectionsRejected callbacks return 400/403/409 JSON with code, remediation, and tokenFingerprint (sha256:<8-hex>), emit async_callback_rejected, and append rejection summaries if the phase later times out.
Failed vs genuinely stalledRunReport.failure classifies HANDLER_EXECUTION_FAILED, HANDLER_TIMEOUT, WORKFLOW_TIMEOUT, callback FAILED/TIMED_OUT, and REWORK_LIMIT_EXHAUSTED distinctly from WORKFLOW_STALLED (queue drained with 0 terminal events). Non-completed phases never report profile PASS.

3. Bounded multi-model build and review loops

Root workflows can run cyclic build-and-dual-review loops (build -> publish_pr -> {reviewer_a, reviewer_b} -> decision -> human_gate) with deterministic convergence or fail-closed exhaustion.

DimensionRuntime status & authoring requirement
Backward rerun_phase loopsSupported for Root DAGs via per-phase phaseStates fencing and loop-scoped joinContributorKeys. With max_loops: 9, rounds 0..=9 run up to 10 total rounds and fail closed with REWORK_LIMIT_EXHAUSTED on round 10 without invoking human_gate.
Out-of-order sibling callbacksSupported: reviewer_b completing before reviewer_a records per-phase state without fencing out its sibling, opening the decision barrier once all requires branches complete.
No native early-exit ANY joinExplicit constraint: requires: [reviewer_a, reviewer_b] is an ALL join. Early exit on first approval (cancelling in-flight sibling reviewers) is not built in; evaluate logical OR/AND inside decision after both callbacks settle.
Explicit sibling payload persistenceExplicit constraint: fan-in passes the final arriving branch's payload rather than unioning sibling payloads. Persist per-(requestId, loopCount, headSha, reviewerId) verdicts in shared run storage and read all reviewers in decision. Also note Root <-> PerShard crossings reset loop_count and type: loop (loop.body) is schema-only.
Verified sources

Checked 2026-11-05.

Let's talk

Contact Rippflow

Tell us about your workflows, deployment or pricing.

We'll reply to your email.

Search docs

Search workflows, handlers and operations.