Outcome
Update one organization.
Examples were captured from actual isolated Auth handlers and repository/session SQL with synthetic identities.
Before you start
-
Verify the pinned identity, exact target organization and runtime authority. Fixture ids and token scenarios authorize no live mutation.
-
Read the exact current organization and preserve an authorized pre-change snapshot before replacing any fields or settings.
-
Review effects, response limits, recovery and the unchanged plan before a separately authorized confirmed call.
Discover the exact target
topolo whoami --json
topolo context ls --json
topolo actions get app_topolo_auth.organizations.update --detail --json
topolo actions get app_topolo_auth.organizations.get --detail --json
The credential supplies its own verified identity. Resolve the organization from an authorized directory/detail or pinned identity context; fixture token names are not action input fields.
Input fields
| Field | Required | Meaning |
|---|---|---|
orgId | Yes | Exact discovered organization id. Display names and fixture ids do not authorize a mutation. Update accepts its bound organization manager or platform authority; delete/restore require platform authority. |
name | No | Replacement organization name. Success returns no updated row; verify the exact target afterward. |
domain | No | Replacement domain text, or null to clear it. This update performs no domain ownership verification. |
slug | No | Replacement organization slug; trimmed and lowercased by the handler, then checked for 3–63 lowercase letters, digits and hyphens. Conflicting uniqueness can fail in the database. |
logo_url | No | Replacement absolute logo URL, or null to clear it. The update does not upload a logo or verify the remote image. |
settings | No | Complete replacement settings object, serialized as JSON. It is not a merge: retain and review required existing settings before replacement. |
status | No | Replacement stored lifecycle status. Setting deleted here does not invoke the dedicated delete handler or its session revocation workflow. |
isActive | No | Boolean or 0/1 mapped to active/inactive status. Do not combine with status because both write the same database column. |
Response and state changes
Success contains success=true, message, data=null and an ISO timestamp. No updated organization row, affected-row count or session-revocation total is returned. State observations below are separate isolated SQL read-backs and are never part of the server response.
Verified platform authority or an owner, super_admin or admin token bound to the exact organization may update it. A foreign organization administrator receives HTTP 401 AUTH_ERROR; denied authority is not proof of expired OAuth.
The successful envelope has data=null and contains no affected-row count or organization id. The current SQL update returns success even when no organization row exists. Read the exact target to establish both existence and persisted changes.
Supplied fields replace their stored values. Omitted fields stay unchanged; settings replaces the entire JSON object rather than merging it. The handler normalizes slug before format validation. A uniqueness violation produces SERVER_ERROR; do not assume no write or change the target.
isActive maps truthiness to active/inactive and status writes the same column. Use only one. Setting status=deleted through update changes the row without the dedicated deletion session workflow. No membership, entitlement, session, domain verification or image upload is performed.
Worked examples
Every organization, user, address, token row and session below is synthetic. Validate and plan with discovered live identifiers; a confirmed mutation command requires human authorization for the concrete live effects. These local examples do not execute any live side effects.
Owner updates the organization name; success data is null
Input · payload.json:
{
"orgId": "org_lifecycle_fixture",
"name": "Fixture renamed"
}
CLI after authorization of the unchanged plan:
topolo actions validate app_topolo_auth.organizations.update --data @payload.json --json
topolo actions plan app_topolo_auth.organizations.update --data @payload.json --confirm --json
topolo actions call app_topolo_auth.organizations.update --data @payload.json --confirm --detail --json
MCP call after topolo_validate_action and confirmed topolo_plan_action:
{
"tool": "topolo_call_action",
"arguments": {
"actionId": "app_topolo_auth.organizations.update",
"input": {
"orgId": "org_lifecycle_fixture",
"name": "Fixture renamed"
},
"confirm": true
}
}
Captured local handler response · HTTP 200:
{
"success": true,
"message": "Organization updated successfully",
"data": null,
"timestamp": "2026-10-03T00:00:00.000Z"
}
Separate local SQL observations · fixture evidence, not response fields:
{
"before": {
"organization": {
"id": "org_lifecycle_fixture",
"name": "org_lifecycle_fixture",
"slug": "org-lifecycle-fixture",
"domain": null,
"settings": "{\"retained\":true}",
"status": "active",
"updated_at": null
},
"humanSessions": [
{
"organization_id": "org_lifecycle_fixture",
"status": "active"
},
{
"organization_id": "org_other_fixture",
"status": "active"
}
],
"humanRefreshRevokedAt": null,
"agentSessionStatuses": [
"active",
"active"
],
"serviceSessionStatuses": [
"active",
"active"
],
"oauthRefreshRevokedAt": null
},
"after": {
"organization": {
"id": "org_lifecycle_fixture",
"name": "Fixture renamed",
"slug": "org-lifecycle-fixture",
"domain": null,
"settings": "{\"retained\":true}",
"status": "active",
"updated_at": 1790985600
},
"humanSessions": [
{
"organization_id": "org_lifecycle_fixture",
"status": "active"
},
{
"organization_id": "org_other_fixture",
"status": "active"
}
],
"humanRefreshRevokedAt": null,
"agentSessionStatuses": [
"active",
"active"
],
"serviceSessionStatuses": [
"active",
"active"
],
"oauthRefreshRevokedAt": null
}
}
Settings replace the stored JSON object; slug normalizes and isActive maps to inactive
Input · payload.json:
{
"orgId": "org_lifecycle_fixture",
"slug": " Fixture-Renamed ",
"settings": {
"replacement": true
},
"isActive": 0
}
CLI after authorization of the unchanged plan:
topolo actions validate app_topolo_auth.organizations.update --data @payload.json --json
topolo actions plan app_topolo_auth.organizations.update --data @payload.json --confirm --json
topolo actions call app_topolo_auth.organizations.update --data @payload.json --confirm --detail --json
MCP call after topolo_validate_action and confirmed topolo_plan_action:
{
"tool": "topolo_call_action",
"arguments": {
"actionId": "app_topolo_auth.organizations.update",
"input": {
"orgId": "org_lifecycle_fixture",
"slug": " Fixture-Renamed ",
"settings": {
"replacement": true
},
"isActive": 0
},
"confirm": true
}
}
Captured local handler response · HTTP 200:
{
"success": true,
"message": "Organization updated successfully",
"data": null,
"timestamp": "2026-10-03T00:00:00.000Z"
}
Separate local SQL observations · fixture evidence, not response fields:
{
"before": {
"organization": {
"id": "org_lifecycle_fixture",
"name": "Fixture renamed",
"slug": "org-lifecycle-fixture",
"domain": null,
"settings": "{\"retained\":true}",
"status": "active",
"updated_at": 1790985600
},
"humanSessions": [
{
"organization_id": "org_lifecycle_fixture",
"status": "active"
},
{
"organization_id": "org_other_fixture",
"status": "active"
}
],
"humanRefreshRevokedAt": null,
"agentSessionStatuses": [
"active",
"active"
],
"serviceSessionStatuses": [
"active",
"active"
],
"oauthRefreshRevokedAt": null
},
"after": {
"organization": {
"id": "org_lifecycle_fixture",
"name": "Fixture renamed",
"slug": "fixture-renamed",
"domain": null,
"settings": "{\"replacement\":true}",
"status": "inactive",
"updated_at": 1790985600
},
"humanSessions": [
{
"organization_id": "org_lifecycle_fixture",
"status": "active"
},
{
"organization_id": "org_other_fixture",
"status": "active"
}
],
"humanRefreshRevokedAt": null,
"agentSessionStatuses": [
"active",
"active"
],
"serviceSessionStatuses": [
"active",
"active"
],
"oauthRefreshRevokedAt": null
}
}
Current update reports success for a missing row; read-back must establish existence
Input · payload.json:
{
"orgId": "org_missing",
"name": "Missing fixture"
}
CLI after authorization of the unchanged plan:
topolo actions validate app_topolo_auth.organizations.update --data @payload.json --json
topolo actions plan app_topolo_auth.organizations.update --data @payload.json --confirm --json
topolo actions call app_topolo_auth.organizations.update --data @payload.json --confirm --detail --json
MCP call after topolo_validate_action and confirmed topolo_plan_action:
{
"tool": "topolo_call_action",
"arguments": {
"actionId": "app_topolo_auth.organizations.update",
"input": {
"orgId": "org_missing",
"name": "Missing fixture"
},
"confirm": true
}
}
Captured local handler response · HTTP 200:
{
"success": true,
"message": "Organization updated successfully",
"data": null,
"timestamp": "2026-10-03T00:00:00.000Z"
}
Separate local SQL observations · fixture evidence, not response fields:
{
"before": {
"organization": null,
"humanSessions": [
{
"organization_id": "org_lifecycle_fixture",
"status": "active"
},
{
"organization_id": "org_other_fixture",
"status": "active"
}
],
"humanRefreshRevokedAt": null,
"agentSessionStatuses": [
"active",
"active"
],
"serviceSessionStatuses": [
"active",
"active"
],
"oauthRefreshRevokedAt": null
},
"after": {
"organization": null,
"humanSessions": [
{
"organization_id": "org_lifecycle_fixture",
"status": "active"
},
{
"organization_id": "org_other_fixture",
"status": "active"
}
],
"humanRefreshRevokedAt": null,
"agentSessionStatuses": [
"active",
"active"
],
"serviceSessionStatuses": [
"active",
"active"
],
"oauthRefreshRevokedAt": null
}
}
Verify the result
- Read organizations.get for the same orgId and compare each intended field. A missing row despite success is unresolved; preserve the request evidence instead of claiming a change.
Errors and recovery
Too-short slug is rejected before persistence
Input:
{
"orgId": "org_lifecycle_fixture",
"slug": "qa"
}
Captured local refusal · HTTP 400:
{
"success": false,
"error": {
"message": "Invalid organization slug format (3-63 characters, lowercase letters, numbers, and hyphens only)",
"code": "VALIDATION_ERROR",
"details": {
"slug": true
},
"timestamp": "2026-10-03T00:00:00.000Z"
}
}
Foreign organization administrator is refused
Input:
{
"orgId": "org_lifecycle_fixture",
"name": "Forbidden"
}
Captured local refusal · HTTP 401:
{
"success": false,
"error": {
"message": "You can only update your own organization",
"code": "AUTH_ERROR",
"details": null,
"timestamp": "2026-10-03T00:00:00.000Z"
}
}
Missing credential is refused
Input:
{
"orgId": "org_lifecycle_fixture",
"name": "Unauthenticated"
}
Captured local refusal · HTTP 401:
{
"success": false,
"error": {
"message": "Access token required",
"code": "AUTH_ERROR",
"details": null,
"timestamp": "2026-10-03T00:00:00.000Z"
}
}
Published recovery guidance
-
state_conflict(HTTP 409): Read the current resource state, reconcile the intended change, and retry only if still valid. -
AUTH_ERROR(HTTP 401): Verify the same pinned credential and exact required authority. Stop on denied authority; do not switch organization or infer expiry from this code alone. -
VALIDATION_ERROR(HTTP 400): Correct the organization slug against the published format, validate and review a new plan before any call. -
SERVER_ERROR(HTTP 500): Inspect the exact stored organization before retrying because a prior write may have committed. Preserve sanitized request evidence for an authorized maintainer and verify session outcomes separately.
Recovery boundary
Retain the authorized pre-change values. After read-back, a separately authorized organizations.update of only the intended fields can compensate; no published operation atomically restores prior settings or sessions.
Evidence
Actual isolated lifecycle handlers and repository/session-store SQL; no live organization or session changed.
Real: Lifecycle handlers and authorization helpers; Repository update/delete/restore SQL; Session and refresh-token revocation SQL; Canonical migrations and separate core/session SQLite engines; Response serialization and post-write state observations. Simulated: Verified token identities; Synthetic organizations, memberships, principals and session/token rows; Fixed clock; Access bindings co-located with core; no live split-D1 parity; Missing session tables and injected post-delete membership lookup failure. No live organization, session, token, permission or application data changed.