Topolo Docs Topolo Platform
Open workspace

Refresh a placement’s diagnostic status

Recheck current access and provider reference while preserving stored pins, stale-label limits and clear partial-outcome handling.

Outcome

Recheck one visible placement’s access and current provider reference, then save the resulting local diagnostic snapshot.

POST /api/developer-console/placements/{placementId}/refresh

Action: app_topolo_developers.placements.refresh.

Before you start

Use the original authenticated active organization with Developers connections:write and current consumer-workspace read access to the visible placement. This POST writes the saved check status/label/time and may read the provider as the caller; it is not a zero-effect GET. Review the actual provider-read/cache-update plan before confirming. No administrator shortcut or consumer read_write minimum is imposed by this selected helper.

Discover the exact current placement with placements.get/list. Input is only placementId matching ^plc_[A-Za-z0-9-]{1,80}$; no organization/workspace selector, desired status/label/version or target URL is accepted. Preserve the stored reference and prior check fields before a refresh.

Where the reference is workspace-scoped, current provider workspace access and the connection’s all/linked workspace-pair policy are checked before the provider read. Organization-wide types use no provider workspace resource binding. No new workspace grant, connection enable, link approval or provider mutation is implicit in refresh.

Five complete source-derived synthetic UNRUN responses follow. The provider results used as fixture premises are hypothetical callback inputs, not captures or claims about a real provider’s full API. No actual refresh, private/provider/grant/Notify/business operation, app import/test or source edit was performed. Current descriptor matches immutable7b89, not served-runtime certification.

Request

Discover the actual placement; this id is fictional:

{
  "placementId": "plc_docs-example-b"
}

Access, provider reads and saved status

POST /api/developer-console/placements/{placementId}/refresh first requires a live visible placement in the original organization and consumer workspace, using read access. Missing/soft-deleted/inaccessible placement returns404 placement_not_found; unavailable Auth workspace data returns503 workspace_access_unavailable before the selected cache write. Native action permission remains connections:write even though this helper only needs consumer read access.

The service reads the original pair’s stored connection and provider reference-type declaration before deriving a check. Missing/soft-removed connection or a stored status other than active/degraded yields access_removed with reason connection_inactive. Missing declared provider type yields unavailable/provider_contract_missing. These are saved check outcomes in a normal200 response, not corresponding HTTP403/404 errors. Source store failures can instead propagate before a check is saved.

For a workspace-scoped type, absent current provider workspace access produces access_removed/provider_workspace_access, and a required missing active nonremoved workspace link produces access_removed/workspace_link_required. Scope all bypasses the stored-link predicate, not person/provider permission checks. An unavailable provider workspace lookup throws503 rather than storing a guessed access denial.

When those checks pass, the selected caller port invokes the declared provider get action through SDK.readAction with input {id:reference.id}, using the original caller credential and provider workspace binding for workspace-scoped types. The stored version pin is not sent as a historical-read parameter: this fetches the provider’s current result and then compares locally. Underlying SDK/provider authorization still applies; this guide certifies no particular provider’s endpoint or response.

The resource extractor searches data.<kind>, data, root.<kind>, then root for a string/numeric id, where kind is the portion after the first dot in the reference type. Normalization uses label/name/title, otherwise the returned id; a positive safe integer version becomes currentVersion. For a successfully normalized candidate, a stored pin and a nonnull reported current version that differs produce changed with reason provider version N; otherwise that normal path produces ready. A missing reported version on a valid normalized candidate can therefore yield ready without proving the pin matches. There is an additional malformed-response edge: if normalization returns null, candidate?.currentVersion is undefined, and the source comparison undefined !== null is true. With a stored pin this produces changed with the literal reason provider version undefined and a null check label; without a pin it produces ready with a null check label. The store’s COALESCE can retain an old label in either case. Neither outcome proves valid provider identity, a matching version or business integrity.

This check does not separately assert the returned provider id equals the stored reference id or validate provider business status. It is a local best-effort projection, not an integrity, publication or availability certificate; malformed normalization must not be treated as strong resource proof. The stored reference id/version/referenceString are not rewritten by refresh, including when changed is reported.

If no identifiable item is extracted, the check becomes removed/reference_not_found. A selected ProviderActionError404 becomes removed with its mapped code;403 becomes access_removed; other mapped provider failures become unavailable. The default caller maps401/403 to reference_access_denied,404 or code containing not_found to reference_not_found, and other SDK failures to provider_unavailable. These handled failures normally produceHTTP200 refreshed with the saved diagnostic status; unexpected nonmapped/store errors may escape.

The cache UPDATE saves status/statusReason, lastCheckedAt and updatedAt only on the still-non-soft-deleted row. Label uses SQL COALESCE(newLabel,oldLabel): a null result label does not clear an old label, even after lost access or provider absence. lastCheckedAt can advance after an early access/connection check without a provider get call. Neither timestamp nor a retained label proves a fresh successful provider read.

The complete normal200 envelope is {success:true,message:"OK",data:{outcome:"refreshed",previousStatus,placement:<full stored PlacementRecord>}}. previousStatus comes from the initial read; final placement comes from a separate reload after the check write. No expectedRevision, whole-operation transaction or rowsWritten check exists. Concurrent soft deletion can make the update affect zero rows, and a missing final row may serialize placement:null despite the TypeScript assertion.

Stored status removed means the provider check found no resource; it is not local soft deletion. removedBy/removedAt stay unchanged and a still-visible row remains readable. The selected refresh does not delete the provider resource, change reference pins, approve a connection, alter links/grants/subscriptions or send Notify events. Shared authentication/dependency initialization remains outside this selected-path statement.

Worked responses

Current provider version differs from the stored pin

Complete synthetic UNRUN HTTP200. The original stored reference is pinned at9 and status unavailable; current consumer/provider access, usable connection and workspace-pair checks pass. A hypothetical get callback returns a well-formed item with matching id, name Fixture item and positive version10. This is a callback premise, not an actual provider API capture.

{
  "success": true,
  "message": "OK",
  "data": {
    "outcome": "refreshed",
    "previousStatus": "unavailable",
    "placement": {
      "id": "plc_docs-example-b",
      "organizationId": "org_docs_fixture",
      "consumer": {
        "appId": "app_example_consumer",
        "workspaceId": "ws_consumer_example",
        "kind": "example.page",
        "id": "page_other"
      },
      "slot": null,
      "reference": {
        "app": "app_example_provider",
        "workspace": "ws_provider_example",
        "type": "example.item",
        "id": "item_example",
        "version": 9
      },
      "referenceString": "topolo:app_example_provider/ws_provider_example/example.item/item_example@9",
      "label": "Fixture item",
      "status": "changed",
      "statusReason": "provider version 10",
      "lastCheckedAt": "2026-10-22T18:00:00.000Z",
      "createdBy": "user_docs_fixture",
      "createdAt": "2026-10-20T10:00:00.000Z",
      "updatedAt": "2026-10-22T18:00:00.000Z",
      "removedBy": null,
      "removedAt": null
    }
  }
}

The pin/referenceString remain at9 while status is changed and reason records10. No provider or reference version was mutated.

Inactive connection saves a diagnostic while retaining an old label

Complete synthetic UNRUN HTTP200. The initial unavailable placement has label Previously saved label; its consumer remains visible, but no usable original connection exists. Provider declaration lookup completes and the branch skips provider get.

{
  "success": true,
  "message": "OK",
  "data": {
    "outcome": "refreshed",
    "previousStatus": "unavailable",
    "placement": {
      "id": "plc_docs-example-b",
      "organizationId": "org_docs_fixture",
      "consumer": {
        "appId": "app_example_consumer",
        "workspaceId": "ws_consumer_example",
        "kind": "example.page",
        "id": "page_other"
      },
      "slot": null,
      "reference": {
        "app": "app_example_provider",
        "workspace": "ws_provider_example",
        "type": "example.item",
        "id": "item_example"
      },
      "referenceString": "topolo:app_example_provider/ws_provider_example/example.item/item_example",
      "label": "Previously saved label",
      "status": "access_removed",
      "statusReason": "connection_inactive",
      "lastCheckedAt": "2026-10-22T18:00:00.000Z",
      "createdBy": "user_docs_fixture",
      "createdAt": "2026-10-20T10:00:00.000Z",
      "updatedAt": "2026-10-22T18:00:00.000Z",
      "removedBy": null,
      "removedAt": null
    }
  }
}

lastCheckedAt advances despite no provider get. SQL COALESCE retains the old label; access_removed does not supply current access or a fresh label.

Provider not found does not soft-delete the placement

Complete synthetic UNRUN HTTP200. Current prerequisite checks pass and the hypothetical provider-read port raises the mapped404/reference_not_found. The original unavailable placement has the same retained old label.

{
  "success": true,
  "message": "OK",
  "data": {
    "outcome": "refreshed",
    "previousStatus": "unavailable",
    "placement": {
      "id": "plc_docs-example-b",
      "organizationId": "org_docs_fixture",
      "consumer": {
        "appId": "app_example_consumer",
        "workspaceId": "ws_consumer_example",
        "kind": "example.page",
        "id": "page_other"
      },
      "slot": null,
      "reference": {
        "app": "app_example_provider",
        "workspace": "ws_provider_example",
        "type": "example.item",
        "id": "item_example"
      },
      "referenceString": "topolo:app_example_provider/ws_provider_example/example.item/item_example",
      "label": "Previously saved label",
      "status": "removed",
      "statusReason": "reference_not_found",
      "lastCheckedAt": "2026-10-22T18:00:00.000Z",
      "createdBy": "user_docs_fixture",
      "createdAt": "2026-10-20T10:00:00.000Z",
      "updatedAt": "2026-10-22T18:00:00.000Z",
      "removedBy": null,
      "removedAt": null
    }
  }
}

status removed is a check outcome; removedBy and removedAt remain null. The local placement remains visible until a separately authorized deletion.

Consumer workspace access is unavailable

Complete synthetic UNRUN HTTP503 before the selected check update when consumer workspace lookup returns null.

{
  "success": false,
  "error": {
    "message": "Topolo Auth could not confirm your workspaces; retry later",
    "code": "workspace_access_unavailable"
  }
}

Preserve unknown access; do not convert it into a ready/removed check, an empty workspace list or an automatic grant expansion.

The placement is missing, deleted or hidden

Complete synthetic UNRUN HTTP404 before provider access and the selected cache write.

{
  "success": false,
  "error": {
    "message": "No placement plc_docs-example-b you can see in this organization",
    "code": "placement_not_found"
  }
}

Reconcile the original id/context and prior outcome. Do not create a replacement or probe another organization.

Verify and recover

  1. Compare actual previousStatus, returned placement.id/consumer/reference and stored check fields to the original preimage. Keep the original organization, credential and reference pin; do not mistake changed for an automatic pin update.

  2. Interpret HTTP status and placement.status separately. A200 with access_removed/removed/unavailable is a saved diagnostic result, not successful provider access or a local deletion receipt. Inspect statusReason and retain actual request ids/errors.

  3. Use placements.get to inspect the current stored result when authorized; remember concurrent writes and stale labels. lastCheckedAt alone does not prove the provider was called, and ready does not prove a missing version pin matched or business resource is published.

  4. After a failure/timeout, reconcile the saved result and known provider-read outcome before any approved later refresh. Do not automatically enable connections, approve links, broaden grants, overwrite a version pin, recreate or delete a provider resource as repair.

No automatic inverse for a diagnostic refresh. Preserve actual saved status/check time/reference and any provider-read outcome; use only a separately reviewed later refresh when the concrete dependency/access issue is resolved. Do not restore stale check fields, change pins, enable/approve/grant or delete/recreate resources as automatic repair.

Change log

  • 2026-10-22: Added exact access/provider/check branches, full diagnostic responses, preserved pins/labels, stored removed versus soft deletion and timestamp/partial-write limits. All cases synthetic UNRUN; no actual provider read or refresh executed.