GoodMemGoodMem
ReferenceSdkV2.NET

Service Identities

Production service identity creation, ownership, and lifecycle.

Namespace: Goodmem.Client.Api · Class: ServiceIdentitiesApi

Reach this surface as client.ServiceIdentities on a GoodmemClient. Every network method is asynchronous — it returns a Task<T> (or an IAsyncEnumerable<T> for pagination and streaming) and accepts a CancellationToken; the Async suffix marks the standard .NET Task-based async pattern.

Methods

MethodSummary
CreateAsyncCreate a service identity.
GetAsyncGet a service identity.
ListAsyncList service identities.
UpdateAsyncUpdate a service identity.
DeleteAsyncDelete a service identity.
TransferOwnershipAsyncTransfer service-identity ownership.

CreateAsync

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

Declaration

public Task<ServiceIdentityResponse> CreateAsync(CreateServiceIdentityRequest request, CancellationToken ct = default)

HTTPPOST /v1/service-identities

Parameters

TypeNameDescription
CreateServiceIdentityRequestrequestThe request payload; the linked model lists every field and its JSON wire name.
CancellationTokenctCancellation / deadline signal for the call. (optional)

Returns

Task<ServiceIdentityResponse> — an awaitable that resolves to ServiceIdentityResponse.

Exceptions

TypeCondition
ArgumentNullExceptionrequest is null.
NetworkExceptionThe request could not reach the server (DNS, connection, or TLS failure).
ApiExceptionThe server returned a non-success (non-2xx) status. A status-specific subtype is thrown where it applies — e.g. NotFoundException (404), PermissionDeniedException (403), ConflictException (409).

Example

var identity = await client.ServiceIdentities.CreateAsync(
    new CreateServiceIdentityRequest
    {
        DisplayName = "production-indexer",
        Description = "Indexes newly uploaded memories",
        Labels = new Dictionary<string, string> { ["environment"] = "production" },
    }
);


GetAsync

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

Declaration

public Task<ServiceIdentityResponse> GetAsync(string id, ServiceIdentitiesGetOptions? options = null, CancellationToken ct = default)

HTTPGET /v1/service-identities/&#123;id&#125;

Parameters

TypeNameDescription
stringidService-identity UUID
ServiceIdentitiesGetOptionsoptionsOptions bag carrying the lookup key(s) / convenience knobs; the linked type lists them all. (optional)
CancellationTokenctCancellation / deadline signal for the call. (optional)

Returns

Task<ServiceIdentityResponse> — an awaitable that resolves to ServiceIdentityResponse.

Exceptions

TypeCondition
ArgumentExceptionid is null or empty.
NetworkExceptionThe request could not reach the server (DNS, connection, or TLS failure).
ApiExceptionThe server returned a non-success (non-2xx) status. A status-specific subtype is thrown where it applies — e.g. NotFoundException (404), PermissionDeniedException (403), ConflictException (409).

Example

var fetchedIdentity = await client.ServiceIdentities.GetAsync("your-service-identity-id");


ListAsync

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).

Declaration

public IAsyncEnumerable<ServiceIdentityResponse> ListAsync(ServiceIdentitiesListOptions? options = null, CancellationToken ct = default)

HTTPGET /v1/service-identities

Parameters

TypeNameDescription
ServiceIdentitiesListOptionsoptionsOptions bag carrying the lookup key(s) / convenience knobs; the linked type lists them all. (optional)
CancellationTokenctCancellation / deadline signal for the call. (optional)

Returns

IAsyncEnumerable<ServiceIdentityResponse> — an async stream; await foreach yields each ServiceIdentityResponse across pages / events.

Exceptions

TypeCondition
NetworkExceptionThe request could not reach the server (DNS, connection, or TLS failure).
ApiExceptionThe server returned a non-success (non-2xx) status. A status-specific subtype is thrown where it applies — e.g. NotFoundException (404), PermissionDeniedException (403), ConflictException (409).

Example

await foreach (
    var item in client.ServiceIdentities.ListAsync(
        new ServiceIdentitiesListOptions { MaxResults = 25 }
    )
)
    Console.WriteLine($"{item.ServiceIdentityId} {item.DisplayName}");


UpdateAsync

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

Declaration

public Task<ServiceIdentityResponse> UpdateAsync(string id, UpdateServiceIdentityRequest request, CancellationToken ct = default)

HTTPPUT /v1/service-identities/&#123;id&#125;

Parameters

TypeNameDescription
stringidService-identity UUID
UpdateServiceIdentityRequestrequestThe request payload; the linked model lists every field and its JSON wire name.
CancellationTokenctCancellation / deadline signal for the call. (optional)

Returns

Task<ServiceIdentityResponse> — an awaitable that resolves to ServiceIdentityResponse.

Exceptions

TypeCondition
ArgumentExceptionid is null or empty.
ArgumentNullExceptionrequest is null.
NetworkExceptionThe request could not reach the server (DNS, connection, or TLS failure).
ApiExceptionThe server returned a non-success (non-2xx) status. A status-specific subtype is thrown where it applies — e.g. NotFoundException (404), PermissionDeniedException (403), ConflictException (409).

Example

var updatedIdentity = await client.ServiceIdentities.UpdateAsync(
    "your-service-identity-id",
    new UpdateServiceIdentityRequest
    {
        Description = "Indexes production knowledge sources",
    }
);


DeleteAsync

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.

Declaration

public Task DeleteAsync(string id, CancellationToken ct = default)

HTTPDELETE /v1/service-identities/&#123;id&#125;

Parameters

TypeNameDescription
stringidService-identity UUID
CancellationTokenctCancellation / deadline signal for the call. (optional)

Returns

Task — completes when the operation finishes; there is no response body.

Exceptions

TypeCondition
ArgumentExceptionid is null or empty.
NetworkExceptionThe request could not reach the server (DNS, connection, or TLS failure).
ApiExceptionThe server returned a non-success (non-2xx) status. A status-specific subtype is thrown where it applies — e.g. NotFoundException (404), PermissionDeniedException (403), ConflictException (409).

Example

await client.ServiceIdentities.DeleteAsync("your-service-identity-id");


TransferOwnershipAsync

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.

Declaration

public Task<TransferServiceIdentityOwnershipResponse> TransferOwnershipAsync(string id, TransferOwnershipRequest request, CancellationToken ct = default)

HTTPPOST /v1/service-identities/&#123;id&#125;:transferOwnership

Parameters

TypeNameDescription
stringidService-identity UUID
TransferOwnershipRequestrequestThe request payload; the linked model lists every field and its JSON wire name.
CancellationTokenctCancellation / deadline signal for the call. (optional)

Returns

Task<TransferServiceIdentityOwnershipResponse> — an awaitable that resolves to TransferServiceIdentityOwnershipResponse.

Exceptions

TypeCondition
ArgumentExceptionid is null or empty.
ArgumentNullExceptionrequest is null.
NetworkExceptionThe request could not reach the server (DNS, connection, or TLS failure).
ApiExceptionThe server returned a non-success (non-2xx) status. A status-specific subtype is thrown where it applies — e.g. NotFoundException (404), PermissionDeniedException (403), ConflictException (409).

Example

var transferredIdentity = await client.ServiceIdentities.TransferOwnershipAsync(
    "your-service-identity-id",
    new TransferOwnershipRequest
    {
        NewOwnerId = "your-new-owner-principal-id",
    }
);


Data Models

Types in the Goodmem.Client.Models namespace. Each row lists the C# property, its type, the JSON wire name, and a description.

CreateServiceIdentityRequest

Creates a service identity owned by the authenticated human. It does not create credentials, roles, or grants.

PropertyTypeJSON (wire)Description
ServiceIdentityIdstringserviceIdentityIdOptional client-provided UUID; generated by the server when omitted. (optional)
DisplayNamestringdisplayNameGlobally unique, nonblank operator-facing name.
DescriptionstringdescriptionOptional operator description. (optional)
LabelsIReadOnlyDictionary<string, string>labelsOptional labels for organization and filtering. At most 20 entries; keys and values contain at most 255 characters; keys use [a-z0-9._-]. (optional)

ServiceIdentityResponse

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

PropertyTypeJSON (wire)Description
ServiceIdentityIdstringserviceIdentityIdOUTPUT_ONLY; immutable service-identity UUID.
DisplayNamestringdisplayNameOUTPUT_ONLY; unique operator-facing display name.
DescriptionstringdescriptionOUTPUT_ONLY; optional operator description. (optional)
OwnerPrincipalIdstringownerPrincipalIdOUTPUT_ONLY; current administrative owner principal UUID.
CreatorPrincipalIdstringcreatorPrincipalIdOUTPUT_ONLY; immutable HUMAN creator-principal UUID.
LabelsIReadOnlyDictionary<string, string>labelsOUTPUT_ONLY; mutable labels. At most 20 entries; keys and values contain at most 255 characters; keys use [a-z0-9._-].
DeletedAtDateTimeOffsetdeletedAtOUTPUT_ONLY; permanent deletion time in milliseconds, absent while active. (optional)
DeletedByIdstringdeletedByIdOUTPUT_ONLY; exact deleting actor UUID, absent while active. (optional)
CreatedAtDateTimeOffsetcreatedAtOUTPUT_ONLY; creation time in milliseconds since the epoch.
UpdatedAtDateTimeOffsetupdatedAtOUTPUT_ONLY; most recent mutation time in milliseconds since the epoch.
CreatedByIdstringcreatedByIdOUTPUT_ONLY; exact creating actor UUID.
UpdatedByIdstringupdatedByIdOUTPUT_ONLY; exact actor UUID for the most recent mutation.

ListServiceIdentitiesResponse

One authorization-filtered page of service identities.

PropertyTypeJSON (wire)Description
ServiceIdentitiesIReadOnlyList<ServiceIdentityResponse>serviceIdentitiesOUTPUT_ONLY; service identities in stable keyset order.
NextTokenstringnextTokenOUTPUT_ONLY; opaque continuation token, omitted after the final page. (optional)

TransferServiceIdentityOwnershipResponse

The service identity after its administrative ownership transfer.

PropertyTypeJSON (wire)Description
ServiceIdentityServiceIdentityResponseserviceIdentityOUTPUT_ONLY; updated service identity.

UpdateServiceIdentityRequest

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

PropertyTypeJSON (wire)Description
DisplayNamestringdisplayNameReplacement display name. A present blank value is invalid. (optional)
DescriptionstringdescriptionReplacement description. An empty string clears the description. (optional)
ReplaceLabelsIReadOnlyDictionary<string, string>replaceLabelsComplete replacement label map; an empty map clears all labels and is mutually exclusive with mergeLabels. At most 20 entries; keys and values contain at most 255 characters; keys use [a-z0-9._-]. (optional)
MergeLabelsIReadOnlyDictionary<string, string>mergeLabelsLabels to upsert; must contain at least one entry and is mutually exclusive with replaceLabels. The final stored map may contain at most 20 entries; keys and values contain at most 255 characters; keys use [a-z0-9._-]. (optional)