Skip to content

Read and send an agent's owner as an object - #51

Open
thiva-k wants to merge 1 commit into
thunder-id:mainfrom
thiva-k:agent-owner-object
Open

thiva-k wants to merge 1 commit into
thunder-id:mainfrom
thiva-k:agent-owner-object

Conversation

@thiva-k

@thiva-k thiva-k commented Nov 5, 2026 •

Copy link
Copy Markdown

Purpose

ThunderID is changing an agent's owner from a string to an object, so the owner can be a person managed in another identity system (thunder-id/thunderid#6435):

"owner": {"id": "jane@example.com", "idType": "email", "isLocal": false}

The SDK still models owner as a String?. Once the server returns the object, Gson fails to read the agent (it expects a string and finds an object), so AgentsClient.get, the agent details and secret regeneration all break. Agent create also sends the owner as a string, which the server now rejects with 400 AGT-1001.


⚠️ Breaking Changes

🔧 Summary of Breaking Changes

  • owner on Agent, CreateAgentRequest and UpdateAgentRequest changes from String? to AgentOwner?.
  • The owner parameter of the AgentCreate composable changes from String? to AgentOwner?.

💥 Impact

Code that reads agent.owner as a string, or passes a string owner to AgentCreate or the create and update requests, no longer compiles. It must ship together with thunder-id/thunderid#6435, since the server change breaks the string form anyway.

🔄 Migration Guide

Read the owner's ID from agent.owner?.id, and pass the owner as an object:

AgentCreate(owner = AgentOwner(id = userId))

The server defaults idType to uuid and isLocal to true, so AgentOwner(id = userId) names a user of the same deployment. To name an external owner:

AgentOwner(id = "jane@example.com", idType = AgentOwnerIdType.EMAIL, isLocal = false)

Approach

  • dev.thunderid.android.management: adds AgentOwner (id, optional idType, optional isLocal) and the AgentOwnerIdType enum (UUID, EMAIL, MOBILE, mapped to the wire values with @SerializedName, like UserUsageBehavior). Agent, CreateAgentRequest and UpdateAgentRequest use it. Gson leaves out the fields that are null, so AgentOwner(id = ...) sends only the ID and the server applies its defaults.
  • AgentsClient.regenerateSecret copies the owner from the read into the update as before; it now carries the object.
  • BaseAgentDetails shows agent.owner?.id, still falling back to "No owner".
  • AgentCreate takes the owner as an AgentOwner? and sends it unchanged, so a caller can also name an external owner.
  • Playground: the sample agent uses AgentOwner(id = "usr-1").

No new strings, so no translation changes. No sample in thunder-id/samples uses AgentCreate or an agent's owner, so no samples change is needed.

Related Issues

  • N/A

Related PRs

SDK parity

Verification

  • ./gradlew ktlintCheck (SDK) and cd playground && ./gradlew ktlintCheck: both pass.
  • ./gradlew test, ./gradlew lint and ./gradlew build were not run: the machine this was written on has no Android SDK, and Gradle stops with "SDK location not found". The new and changed unit tests (below) have therefore not been run locally and rely on CI. The Kotlin was checked by reading every changed file and every use of the changed types.
  • New unit tests in ManagementApiTest: create sends the owner object (with idType as its wire value), create leaves out the owner fields it was not given, a read parses the owner object, and a read without an owner leaves it null. AdministrationApiTest's secret regeneration test now checks that the owner object read from the agent is sent back unchanged on the update.
  • No test covers the AgentDetails change: the unit tests here do not render composables.

Checklist

  • Followed the contribution guidelines.
  • Manual test round performed and verified.
  • Documentation provided. (Add links if there are any)
  • Tests provided. (Add links if there are any)
    • Unit Tests
    • Integration Tests
  • Breaking changes. (Fill if applicable)
    • Breaking changes section filled.
    • breaking change label added.
  • Cross-SDK parity. Exactly one of parity/prs-raised or parity/prs-not-needed added.
    • If parity/prs-raised, the port links are posted as a reply on the parity check's comment.

Security checks

  • Followed secure coding standards.
  • Confirmed that this PR doesn't commit any keys, passwords, tokens, usernames, or other secrets.

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

Important

  • Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

Run configuration

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@thiva-k thiva-k added parity/prs-raised Ports exist in the other SDKs, or are recorded as not applying there breaking change Changes public API or behaviour in a way that breaks existing apps labels Nov 5, 2026
@github-actions

github-actions Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

🔀 Cross-SDK feature parity, ports raised

This pull request is labelled parity/prs-raised, so the capability it introduces is expected in the other ThunderID SDKs as well.

Ports (DO NOT EDIT)

  • thunder-id/javascript-sdks, JavaScript (React, Vue, Nuxt, Next.js, Express, React Router, TanStack Router, Browser, Node) => #157
  • thunder-id/ios-sdks, iOS => #43
  • thunder-id/flutter-sdks, Flutter => #65

3 of 3 sibling SDKs accounted for.

Every sibling SDK is accounted for.

The contract is in the SDK development specification.

ThunderID now models an agent's owner as an object, so it can name a
person managed in another identity system (thunder-id/thunderid#6435).
The server returns `{"id", "idType", "isLocal"}` on reads and rejects a
string owner with 400 AGT-1001.

Add `AgentOwner` and `AgentOwnerIdType` and use them for `owner` on
`Agent`, `CreateAgentRequest` and `UpdateAgentRequest`. Agent details
show the owner's id, and `AgentCreate` takes the owner as an
`AgentOwner` and sends it as given. The playground sample agent and the
tests use the object.

Signed-off-by: thiva-k <kalyanasundaramthivaharan@gmail.com>
@thiva-k
thiva-k force-pushed the agent-owner-object branch from cca3fd5 to 3bd0e9a Compare November 6, 2026 17:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking change Changes public API or behaviour in a way that breaks existing apps parity/prs-raised Ports exist in the other SDKs, or are recorded as not applying there

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant