← All guided builds

Guided build · 12

Take a live dashboard through connector handoff

Continue the live revenue build at its source boundary: admit one connector event, prove the existing dashboard settles exactly once, and prepare its production handoff.

You will finish with: A connector-backed revenue app with bounded ingress failure checks, idempotent delivery, downstream proof, and named production evidence.

30 minIntermediateSource checked for Grid 0.61.0Reviewed 2026-08-26
Related canonical example21-live-revenue-kpi.grid
Get Grid
Connector eventorder-status-paid.jsonA pinned pending-to-paid order upsert with a unique sequence and idempotency key.

Watch it in Grid

See the workflow before you build it.

Follow the finished interaction, then use the written steps below to build and inspect it yourself.

Companion film

From dirty rows to trusted data

Run four visible Dataset transforms, explicitly publish three clean rows to TrustedOrders, and verify the bound Table reads only that result.

30 secGrid 0.63.2
Open film page
On this page

What you will build

This is the operational continuation of Build a live revenue dashboard. That build already created the Orders, Customers, and Products tables; filtered, joined, and grouped them; published four semantic KPIs; and bound those KPIs to Layout.

Here you will leave that model logic unchanged. You will hand the Orders source boundary to an operator-configured connector adapter, reject one deliberately misbound event, deliver the pending-to-paid change exactly once, prove the existing dashboard settles, and prepare the model for production handoff.

The included event is a deterministic local fixture. This tutorial does not claim that the public site has executed it or published a Runtime Host receipt.

Before you begin

Complete the live-revenue-dashboard build first. That predecessor ends after changing o4 to paid, so perform this explicit handoff before connector work:

  1. In the same table editor or source mutation surface used by the preceding build, change only o4.status from paid back to pending.
  2. Wait for the model to settle and confirm TotalRevenue = 90000, TotalMargin = 63000, ActiveSegments = 2, and RevenueAlert = false in the model and Layout.
  3. Confirm that this exact resident model is deployed in the Server Build's public model API. Obtain its actual ID from your host or operator; do not assume a display name is the API ID.
  4. Export that exact ID for every request in this tutorial:
export GRID_MODEL_ID="replace-with-the-completed-dashboard-model-id"

If the completed dashboard is not present in GET /api/model-summaries, use your host's supported publish/deploy handoff to place that completed model and its seeded source tables in the Server Build first. The public API does not document a portable stateful-table export command, so do not continue against a newly deployed empty starter model.

The API-addressable model must now have:

  • o4 stored in Orders with status pending;
  • baseline TotalRevenue = 90000, TotalMargin = 63000, ActiveSegments = 2, and RevenueAlert = false;
  • the four Layout tiles bound to those named outputs.

You also need curl, jq, a public API token, a separate connector-ingress token, and the order-status-paid.json asset above.

Your operator must provision this exact adapter contract for the deployed model:

Binding field Required value
HTTP source ID revenue-orders
Delivered symbol order-upsert
Target model exact value of GRID_MODEL_ID
Target Orders table upsert adapter
Stable row key value.order_id
Accepted fields order_id, customer_id, product_id, amount, status

The public API does not document a binding-creation route or a universal table-upsert adapter configuration. This tutorial starts after the operator has configured and tested that boundary on the exact deployment. Do not reinterpret connector ingress as arbitrary cell mutation.

export GRID_URL="http://localhost:3000"
export GRID_TOKEN="replace-with-your-api-token"
export GRID_INGRESS_TOKEN="replace-with-your-ingress-token"

Confirm the ID resolves to the intended resident model before the operator binds it:

curl --fail-with-body \
  -H "Authorization: Bearer $GRID_TOKEN" \
  "$GRID_URL/api/models/$GRID_MODEL_ID/manifest" \
  | jq '{id, sourceHash, declaredOutputs, protectedMode}'

The returned id must exactly equal GRID_MODEL_ID, and the manifest must expose the four KPI symbols. Give that exact ID—not the tutorial's title—to the operator provisioning the binding.

All HTTP requests target Node. Runtime Host and GRID_RUNTIME_RPC_TOKEN remain private. Review connector ingress and production credentials before continuing.

1. Confirm the handoff boundary

Resolve the public KPIs without reading the connector fixture:

curl --fail-with-body \
  -H "Authorization: Bearer $GRID_TOKEN" \
  -H "Content-Type: application/json" \
  -X POST "$GRID_URL/api/models/$GRID_MODEL_ID/symbols/resolve" \
  --data '{"symbols":["TotalRevenue","TotalMargin","ActiveSegments","RevenueAlert"]}' \
  | tee /tmp/live-revenue-before.json \
  | jq '{
      revenue: .TotalRevenue.value.value,
      margin: .TotalMargin.value.value,
      segments: .ActiveSegments.value.value,
      alert: .RevenueAlert.value.value,
      requestRev: .TotalRevenue.requestRev,
      resolvedRev: .TotalRevenue.resolvedRev
    }'

Expected checkpoint from the preceding build: revenue 90000, margin 63000, segments 2, and alert false. Revision numbers are server-owned; record them so you can prove the later result is newer.

If the values differ, stop and inspect o4, the exact API model ID, and its settled revision. Do not tune the connector event around unexplained starting state.

2. Validate the event locally

jq -e '
  .sourceKind == "adapter" and
  (.events | length) == 1 and
  .events[0].sourceSymbol == "order-upsert" and
  .events[0].value.order_id == "o4" and
  .events[0].value.status == "paid" and
  .events[0].sequence == 5 and
  .events[0].idempotencyKey == "revenue-order-o4-status-5"
' order-status-paid.json

jq '.events[0] | {
  sourceSymbol,
  rowKey: .value.order_id,
  status: .value.status,
  sequence,
  idempotencyKey
}' order-status-paid.json

Deterministic local checkpoint:

{
  "sourceSymbol": "order-upsert",
  "rowKey": "o4",
  "status": "paid",
  "sequence": 5,
  "idempotencyKey": "revenue-order-o4-status-5"
}

This validates only the authored event. The binding and application counters must come from the live ingress response.

3. Deliberately use the wrong binding

Create a disposable payload with a misspelled source symbol and a different event identity:

jq '
  .events[0].sourceSymbol = "order-upsert-typo" |
  .events[0].sequence = 4 |
  .events[0].idempotencyKey = "revenue-order-o4-status-4-typo"
' order-status-paid.json > /tmp/order-status-unbound.json

curl --fail-with-body \
  -H "Authorization: Bearer $GRID_INGRESS_TOKEN" \
  -H "Content-Type: application/json" \
  -X POST "$GRID_URL/api/pipes/sources/revenue-orders/events" \
  --data-binary @/tmp/order-status-unbound.json \
  | tee /tmp/order-status-unbound-response.json \
  | jq '{sourceId, admitted, deduped, unbound, applied, stream}'

Expected failure signal: the typo event applies no table write and is reported as unbound by the configured adapter path. Resolve the KPIs again; they must remain at the baseline.

If the typo applies a write, stop. The deployment binding is broader than the contract above and must be reviewed before untrusted connector data is admitted.

Minimal repair is to restore the exact order-upsert symbol. Do not add a wildcard binding, route around ingress with a direct cell write, or reuse the typo event's identity for corrected content.

4. Deliver the deliberate pending-to-paid change

Send the unchanged checked fixture through the exact source ID:

curl --fail-with-body \
  -H "Authorization: Bearer $GRID_INGRESS_TOKEN" \
  -H "Content-Type: application/json" \
  -X POST "$GRID_URL/api/pipes/sources/revenue-orders/events" \
  --data-binary @order-status-paid.json \
  | tee /tmp/order-status-paid-response.json \
  | jq '{sourceId, admitted, deduped, coalesced, unbound, applied, stream}'

For the resident configured target, require unbound = 0 and confirm applied includes the Orders upsert. admitted alone is not downstream proof.

Resolve the KPIs again:

curl --fail-with-body \
  -H "Authorization: Bearer $GRID_TOKEN" \
  -H "Content-Type: application/json" \
  -X POST "$GRID_URL/api/models/$GRID_MODEL_ID/symbols/resolve" \
  --data '{"symbols":["TotalRevenue","TotalMargin","ActiveSegments","RevenueAlert"]}' \
  | tee /tmp/live-revenue-after.json \
  | jq '{
      revenue: .TotalRevenue.value.value,
      margin: .TotalMargin.value.value,
      segments: .ActiveSegments.value.value,
      alert: .RevenueAlert.value.value,
      requestRev: .TotalRevenue.requestRev,
      resolvedRev: .TotalRevenue.resolvedRev
    }'

Expected downstream checkpoint after a confirmed application: revenue 170000, margin 111000, segments 3, and alert true. The returned settled revision must not be older than the baseline revision.

Open Dashboard and confirm its four existing tiles show the same values. No table query, KPI formula, or Layout configuration changes in this tutorial.

5. Retry the same event safely

Send order-status-paid.json again byte for byte:

curl --fail-with-body \
  -H "Authorization: Bearer $GRID_INGRESS_TOKEN" \
  -H "Content-Type: application/json" \
  -X POST "$GRID_URL/api/pipes/sources/revenue-orders/events" \
  --data-binary @order-status-paid.json \
  | jq '{admitted, deduped, applied, stream}'

Expected checkpoint: Grid reports the delivery as deduplicated or duplicate rather than creating a second logical upsert. The four KPI values remain unchanged.

Reusing the same idempotency key with different content can return 409. A new source observation needs a new stable sequence and idempotency key. Preserve Retry-After and retry only identical idempotent content after overload.

6. Establish production observability

Before handing the model to operators, create monitors or release checks for:

  • /readyz status and every failing probe;
  • 429 and overloaded 503 responses with Retry-After;
  • ingress unbound, deduped, applied, and stream.batchStatus trends;
  • source ID, sequence, idempotency key, target model ID, and approximate failure time;
  • model source hash and last settled revision;
  • model event archive, model ledger, and connector Stream state durability if those capabilities are enabled.

Do not log event payloads blindly: they can contain customer or commercial data. Store only the minimum identity needed for diagnosis under your data-handling policy.

See connector failure diagnosis for exact counter meanings.

7. Complete the production handoff

Use the operator's deployment-specific procedure to:

  1. Confirm Node is public and Runtime Host is private.
  2. Keep API, ingress, admin, and private RPC credentials separate.
  3. Classify enabled model, event, ledger, and Stream paths as durable or intentionally ephemeral.
  4. Capture the candidate product version and catalogSha256 from /api/capabilities.
  5. Exercise the order-status-paid.json canary against an isolated staging model with a fresh identity.
  6. Confirm a typo remains unbound and an identical retry remains deduplicated.
  7. Restore staged state and exercise rollback on the exact candidate build.
  8. Route traffic only after /readyz is 200 with status: "ok".

The public documentation does not provide a universal image pull, drain, adapter-provisioning, backup, or restore command. Record and test the exact mechanisms your deployment actually uses rather than inventing portable-looking commands.

You are done when

  • The completed live-dashboard model is explicitly reset to the pending baseline and addressed by its actual GRID_MODEL_ID; no relational or Layout logic was recreated.
  • The local fixture has the exact source symbol, row key, sequence, and idempotency key.
  • The typo event applies no write and the corrected event reports unbound = 0 with a confirmed upsert.
  • One connector event moves the four existing KPIs to 170000, 111000, 3, and true.
  • An identical retry does not create a second logical change.
  • Readiness, counter monitoring, durable state, credential separation, canary, restore, and rollback have named owners and evidence.

Continue with Send connector events to Grid for route details and Run Grid in production for the supported Server Build boundary.

Build statusReached the expected checkpoint?