Topolo Docs Topolo Platform
Open workspace

Archive an empty Developers workspace

Archive the canonical Developers workspace through Auth, then remove local mirrors after selected emptiness checks.

Action and scope

app_topolo_developers.workspaces.delete

DELETE /api/developer-console/workspaces/{workspaceId}

Archive the canonical Developers workspace through Auth, then remove local mirrors after selected emptiness checks.

Before you start

Use the intended environment, authenticated identity and organization. Discover the canonical app-scoped Developers workspace through supported Auth workspace discovery, then use the same actual workspaceId in the action input and resource binding. A path/header is a request, not an access grant. Platform membership resolution is required; an organization role alone is not proof of a sufficient workspace grant.

Required application permission: app_topolo_developers.workspace:delete. Platform workspace minimum access requested by the route: admin. Service permission and the actual workspace authorization are separate checks.

This is a declared destructive action requiring explicit caller confirmation. No example or public guide authorizes executing it.

Input

  • workspaceId — required, nonempty string. It must match the actual platform-approved workspace resource.
  • Additional input properties are not accepted. Do not add a JSON confirmation flag.

What it does

Despite its workspaces.delete action ID and legacy catalog wording, the pinned source ARCHIVES the canonical Auth workspace and then removes app-local identity mirrors. It does not prove permanent destruction of the canonical identity. No restoration/unarchive path was audited, and this action offers none. Keep the declared destructive confirmation requirement.

The local emptiness gate checks control tables developer_profiles, developer_apps, developer_app_submissions, developer_app_commerce, developer_payout_accounts and developer_payout_events; integrations tables developer_app_p2p_capabilities and developer_app_api_key_resources; and artifacts table developer_mobile_artifacts. A profile alone blocks archival. These selected counts are not proof that all provider or downstream data is empty, and other dependent rows can be affected by mirror cascades. The count reads do not reserve an atomic empty state against concurrent writes before the later Auth request.

After authentication and organization selection, platform workspace resolution requests admin access for this DELETE route and can ensure a local control mirror. The URL ID must equal the resolved workspace; the control mirror must still exist. The lifecycle handler is separate from the shared developer-profile resolver used by the data routes, so do not copy their suspended-profile behavior onto this operation.

When the selected local counts are all zero, the route uses a service client to request POST /api/internal/workspaces/{id}/archive with organizationId, actorUserId and reason archived_from_developers. This is a delegated internal step of this action, not a separately authorized endpoint for the reader to call. Auth acceptance and upstream implementation are separate from local cleanup.

An upstream409 maps to409; other non-OK responses or a rejected fetch map to502 with the same platform-refused message. On that branch local mirror cleanup is not begun, but a transport failure can hide an accepted Auth operation. After OK, integrations/artifacts mirrors are removed concurrently and then the control mirror is removed. A local failure can follow canonical archival and some successful mirror removals. No cross-service transaction or rollback is implemented.

Worked examples — synthetic and unrun

Every identifier, value, store result and response below is fictional. The full bodies are conditional illustrations of the pinned source branches; no live action or test was run.

The empty workspace is archived and local mirrors removed

SYNTHETIC / UNRUN. The caller is authenticated and platform-authorized for this workspace; all selected child-table counts are zero, the Auth archive request returns OK, then both ancillary mirrors and the control mirror are removed. This proves the stipulated branch shape, not provider execution or permanent canonical identity destruction.

Request input:

{
  "workspaceId": "ws_synthetic_developers"
}

Illustrative HTTP 200 response under the stated fictional preconditions. No action was executed.

{
  "success": true,
  "message": "Developer workspace archived successfully.",
  "data": {
    "workspaceId": "ws_synthetic_developers"
  }
}

No apps, but a profile still occupies the workspace

SYNTHETIC / UNRUN. The selected developer_profiles table has one row even though developer_apps is empty. Any selected child-table count above zero prevents the Auth archive request. Moving apps alone is not sufficient.

Request input:

{
  "workspaceId": "ws_synthetic_developers"
}

Illustrative HTTP 409 response under the stated fictional preconditions. No action was executed.

{
  "success": false,
  "error": {
    "message": "Only an empty workspace can be archived."
  }
}

The URL targets another workspace

SYNTHETIC / UNRUN. The platform resolved a different authorized workspace; the path mismatch is refused before emptiness checks/archival. Resolver mirror initialization is separate.

Request input:

{
  "workspaceId": "ws_synthetic_developers"
}

Illustrative HTTP 403 response under the stated fictional preconditions. No action was executed.

{
  "success": false,
  "error": {
    "message": "You do not have access to this workspace."
  }
}

A local mirror disappears before its presence check

SYNTHETIC / UNRUN. Conditional race: platform resolution ensured the control mirror, but another authorized operation removes it before findDeveloperWorkspaceMirror reads it. This is not an assumed normal missing-workspace recovery path.

Request input:

{
  "workspaceId": "ws_synthetic_developers"
}

Illustrative HTTP 404 response under the stated fictional preconditions. No action was executed.

{
  "success": false,
  "error": {
    "message": "Developer workspace not found."
  }
}

The platform refuses with a conflict

SYNTHETIC / UNRUN. Selected local tables are empty; the Auth archive request returns HTTP409, so local mirror cleanup is not started. The response does not expose the upstream body or a source machine error code.

Request input:

{
  "workspaceId": "ws_synthetic_developers"
}

Illustrative HTTP 409 response under the stated fictional preconditions. No action was executed.

{
  "success": false,
  "error": {
    "message": "The platform refused to archive this workspace."
  }
}

The archive request has an unknown transport outcome

SYNTHETIC / UNRUN. The archive fetch rejects and is caught as null. It may have reached Auth before the response was lost. The local cleanup branch is skipped, but canonical archival remains UNKNOWN. Other upstream non-OK statuses besides409 are also mapped to502.

Request input:

{
  "workspaceId": "ws_synthetic_developers"
}

Illustrative HTTP 502 response under the stated fictional preconditions. No action was executed.

{
  "success": false,
  "error": {
    "message": "The platform refused to archive this workspace."
  }
}

Auth accepted, then local cleanup failed

SYNTHETIC / UNRUN. Auth archive returned OK, but one ancillary mirror deletion throws Error("Synthetic local mirror cleanup failure."). The other concurrent ancillary deletion may already have succeeded, and control cleanup has not yet been reached. No compensating Auth unarchive is attempted; reconcile the actual state instead of replaying blindly.

Request input:

{
  "workspaceId": "ws_synthetic_developers"
}

Illustrative HTTP 500 response under the stated fictional preconditions. No action was executed.

{
  "success": false,
  "error": {
    "message": "Synthetic local mirror cleanup failure."
  }
}

Errors and recovery

This is an explanatory label, not a wire error.code. The source message is You do not have access to this workspace. Reconcile URL/input and actual platform-approved resource context; do not substitute an unauthorized target.

This is an explanatory label, not a stable wire code. The outer handler returns an Error message; preserve the request and UNKNOWN/partial effects. No restore is provided by this action; canonical Auth restoration semantics are unreviewed. After a lost/error response, ask the authorized Auth and Developers owners to reconcile canonical workspace status and all three local mirrors before considering a new request. Do not infer no effect from502/500, regenerate a workspace identity, or bypass an archive/ownership hold.

Source error.message distinguishes Only an empty workspace can be archived. from The platform refused to archive this workspace. No error.code is emitted. Resolve the actual condition with its owner; removing apps alone may leave other selected children.

Source emits Developer workspace not found. with no code if the control mirror is absent at the presence check. Do not invent/reseed canonical identity to bypass a refusal.

Source emits The platform refused to archive this workspace. with no code for non409 upstream refusal or transport rejection. Canonical outcome can be UNKNOWN; reconcile with Auth before any replay.

Other authentication, service-permission, workspace-grant and shared-context failures may occur before these source branches. Their exact deployed envelopes are not asserted here. The descriptor’s generic labels do not make these illustrated messages stable machine codes.

Verify the result

Use supported canonical Auth workspace discovery/status and authorized Developers owner readback to reconcile archival and local mirror cleanup. Absence from one app list alone is not proof of permanent canonical deletion.

Preserve actual operation context/request identifiers and upstream/local outcome evidence. A clean200 describes the route completion boundary only, not every downstream provider or a verified unarchive path.

Recovery boundary

No restore is provided by this action; canonical Auth restoration semantics are unreviewed. After a lost/error response, ask the authorized Auth and Developers owners to reconcile canonical workspace status and all three local mirrors before considering a new request. Do not infer no effect from502/500, regenerate a workspace identity, or bypass an archive/ownership hold.

Source and limits

Reviewed against Topolo-io/TopoloDevelopers@7b89bd3b39092cdc29f87540847bf99a243f0a40:apps/api/functions/api/developer-console/workspace-lifecycle-routes.ts and the application action declaration at 7b89bd3b39092cdc29f87540847bf99a243f0a40. Shared context, workspace access and response wrappers were reviewed at the same revision. The retained data-protection test source was read for its fixtures only; it was not imported or run. Source/declaration association is not proof of serving runtime, completed provider effects or automatic Knowledge invocation.

Change log

  • 2026-10-23: Documented this action’s exact schemas, source behavior, conditional complete request/response examples, authorization, verification and recovery limits. Distinguished source behavior from misleading catalog shortcuts. This records a documentation change, not an executed data operation.