GoodMemGoodMem

Service Identities

Methods on this page are called as client.service_identities.<method>(...) where client is either a synchronous Goodmem or asynchronous AsyncGoodmem instance initialized below:

from goodmem import Goodmem
client = Goodmem(base_url='http://localhost:8080', api_key='gm_...')
from goodmem import AsyncGoodmem
client = AsyncGoodmem(base_url='http://localhost:8080', api_key='gm_...')

Create a service identity

service_identities.create(*, display_name: str, description: str = None, labels: dict[str, str] = None, service_identity_id: str = None) → ServiceIdentityResponse

Creates one production-workload identity owned by the authenticated human. No API key, role, grant, or authentication mapping is created implicitly.

Parameters:

  • display_name (str) — Globally unique, nonblank operator-facing name.
  • description (str, optional) — Optional operator description.
  • labels (dict[str, str], optional) — Optional labels for organization and filtering. At most 20 entries; keys and values contain at most 255 characters; keys use [a-z0-9._-].
  • service_identity_id (str, format: uuid, optional) — Optional client-provided UUID; generated by the server when omitted.

Returns:

ServiceIdentityResponse

Raises:

  • APIError — Any other non-2xx HTTP response (base class; exposes status_code and body).

Example

identity = client.service_identities.create(
    display_name="production-indexer",
    description="Indexes newly uploaded memories",
    labels={"environment": "production"},
)

Get a service identity

service_identities.get(*, id: str, include_deleted: bool = None) → ServiceIdentityResponse

Returns a service identity after applying READ_SERVICE_IDENTITY authority. include_deleted permits an authorized caller to inspect a permanent tombstone; it does not grant additional authority.

Parameters:

  • id (str) — Service-identity UUID
  • include_deleted (bool, optional, server default=False) — Permit an authorized read of a permanent tombstone

Returns:

ServiceIdentityResponse

Raises:

  • APIError — Any other non-2xx HTTP response (base class; exposes status_code and body).

Example

fetched_identity = client.service_identities.get(
    id=identity.service_identity_id,
)

List service identities

service_identities.list(*, include_deleted: bool = None, label: dict[str, str] = None, max_results: int = None, next_token: str = None, owner_principal_id: str = None) → Page[ServiceIdentityResponse]

Requires LIST_SERVICE_IDENTITY on the GoodMem instance and READ_SERVICE_IDENTITY on each returned row. Owner and label filters, lifecycle filtering, authorization, and keyset pagination execute in PostgreSQL.

LABEL FILTERS: Label filters accept either label.<key>=<value> or label[key]=value (for example, label.environment=production or label[environment]=production).

Parameters:

  • include_deleted (bool, optional, server default=False) — Include readable permanent tombstones
  • label (dict[str, str], optional) — Filter by label key-value pairs. Label filters accept either label.<key>=<value> or label[key]=value (for example, label.environment=production or label[environment]=production).
  • max_results (int, format: int32, optional, server default=50) — Page size; defaults to 50 and must be between 1 and 1000
  • next_token (str, optional) — Opaque continuation token
  • owner_principal_id (str, optional) — Exact current administrative-owner principal UUID

Returns:

Page[ServiceIdentityResponse]

Raises:

  • PermissionDeniedError — The caller lacks the permission the operation requires.
  • APIError — Any other non-2xx HTTP response (base class; exposes status_code and body).

Example

for item in client.service_identities.list(max_results=25):
    print(item.service_identity_id, item.display_name)

Update a service identity

service_identities.update(*, id: str, request: UpdateServiceIdentityRequest | dict) → ServiceIdentityResponse

Updates only fields present in the request. Empty description clears that optional field. Ownership changes use the dedicated transfer endpoint.

Parameters:

Returns:

ServiceIdentityResponse

Raises:

  • APIError — Any other non-2xx HTTP response (base class; exposes status_code and body).

Example

updated_identity = client.service_identities.update(
    id=fetched_identity.service_identity_id,
    request={"description": "Indexes production knowledge sources"},
)

Delete a service identity

service_identities.delete(*, id: str) → None

Permanently soft-deletes the principal. Its stored credentials remain audit records but can no longer authenticate because their subject is deleted. Repeating an authorized delete succeeds without rewriting audit data.

Parameters:

  • id (str) — Service-identity UUID

Returns:

None

Raises:

  • APIError — Any other non-2xx HTTP response (base class; exposes status_code and body).

Example

client.service_identities.delete(
    id=transferred.service_identity.service_identity_id,
)

Transfer service-identity ownership

service_identities.transfer_ownership(*, id: str, request: TransferOwnershipRequest | dict) → TransferServiceIdentityOwnershipResponse

Transfers administrative ownership to another active principal. A service identity cannot own itself. The service identity's subject, immutable creator, credentials, grants, and roles are unchanged.

Parameters:

Returns:

TransferServiceIdentityOwnershipResponse

Raises:

  • APIError — Any other non-2xx HTTP response (base class; exposes status_code and body).

Example

transferred = client.service_identities.transfer_ownership(
    id=updated_identity.service_identity_id,
    request={"new_owner_id": "70e025f6-76ca-4cbe-b8fc-7dab8e84590a"},
)

Async usage: client.service_identities exposes the same methods on AsyncGoodmem; use await / async for as needed.


Data Models

All data models are pydantic v2 models. Fields are shown with their Python attribute names; JSON responses use camelCase aliases (e.g., owner_idownerId).

ServiceIdentityResponse

A durable production workload identity. Credentials, grants, and roles are separate resources and are not included.

  • service_identity_id (str) — OUTPUT_ONLY; immutable service-identity UUID.
  • display_name (str) — OUTPUT_ONLY; unique operator-facing display name.
  • description (str, optional) — OUTPUT_ONLY; optional operator description.
  • owner_principal_id (str) — OUTPUT_ONLY; current administrative owner principal UUID.
  • creator_principal_id (str) — OUTPUT_ONLY; immutable HUMAN creator-principal UUID.
  • labels (dict[str, str]) — OUTPUT_ONLY; mutable labels. At most 20 entries; keys and values contain at most 255 characters; keys use [a-z0-9._-].
  • deleted_at (int, optional) — OUTPUT_ONLY; permanent deletion time in milliseconds, absent while active.
  • deleted_by_id (str, optional) — OUTPUT_ONLY; exact deleting actor UUID, absent while active.
  • created_at (int) — OUTPUT_ONLY; creation time in milliseconds since the epoch.
  • updated_at (int) — OUTPUT_ONLY; most recent mutation time in milliseconds since the epoch.
  • created_by_id (str) — OUTPUT_ONLY; exact creating actor UUID.
  • updated_by_id (str) — OUTPUT_ONLY; exact actor UUID for the most recent mutation.

UpdateServiceIdentityRequest

Updates explicitly present profile fields. Empty description clears it; omitted fields remain unchanged. Ownership is changed only through the transfer endpoint.

  • display_name (str, optional) — Replacement display name. A present blank value is invalid.
  • description (str, optional) — Replacement description. An empty string clears the description.
  • replace_labels (dict[str, str], optional) — Complete replacement label map; an empty map clears all labels and is mutually exclusive with merge_labels. At most 20 entries; keys and values contain at most 255 characters; keys use [a-z0-9._-].
  • merge_labels (dict[str, str], optional) — Labels to upsert; must contain at least one entry and is mutually exclusive with replace_labels. The final stored map may contain at most 20 entries; keys and values contain at most 255 characters; keys use [a-z0-9._-].

TransferServiceIdentityOwnershipResponse

The service identity after its administrative ownership transfer.