Skip to content

feat: add credential properties. - #46

Merged
ksqeib merged 1 commit into
HyperZoneLogin:masterfrom
qyl27:feat/credential-properties
Oct 14, 2026
Merged

ksqeib merged 1 commit into
HyperZoneLogin:masterfrom
qyl27:feat/credential-properties

Conversation

@qyl27

@qyl27 qyl27 commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

变更说明

为Credential增加Properties,用于特定信息的跨模块传递需求。

为YggdrasilHyperZoneCredential增加yggdrasil-entry-id属性,用于标识yggdrasil的entryId,作为公开API的一部分。

关联范围

  • openvc
  • auth-yggd
  • auth-offline
  • data-merge
  • profile-skin
  • api
  • 文档
  • GitHub 工作流 / 仓库配置

变更类型

  • Bug 修复
  • 新功能
  • 重构
  • 文档更新
  • 构建 / CI 调整
  • 其他

测试与验证

请说明你做了哪些验证,例如:

  • 已本地构建通过
  • 已运行相关测试
  • 已验证配置生成 / 加载正常
  • 已验证迁移逻辑或命令行为
  • 已更新相关文档

兼容性与风险

无兼容性风险。

其他补充

N/A

Summary by Sourcery

Enable credentials to carry extensible properties and expose the associated Yggdrasil entry identifier.

New Features:

  • Add a properties API to credentials for passing credential-specific information across modules.
  • Expose the Yggdrasil entry ID through the public yggdrasil-entry-id credential property.

Signed-off-by: 秋雨落 <i@rain.cx>
@sourcery-ai

sourcery-ai Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Reviewer's Guide

The PR adds a property-based metadata mechanism to the API by extending HyperZoneCredential with IPropertiesHolder, then exposes the normalized Yggdrasil entry ID as the public yggdrasil-entry-id property on Yggdrasil credentials.

Sequence diagram for Yggdrasil credential property initialization

sequenceDiagram
    participant Caller
    participant YggdrasilHyperZoneCredential
    participant IPropertiesHolder

    Caller->>YggdrasilHyperZoneCredential: create(entryId, authenticatedUUID)
    YggdrasilHyperZoneCredential->>IPropertiesHolder: setProperty(YGGDRASIL_ENTRY_ID_PROPERTY, entryId.lowercase(Locale.getDefault()))
    IPropertiesHolder-->>YggdrasilHyperZoneCredential: property stored
    Caller->>YggdrasilHyperZoneCredential: getProperty(YGGDRASIL_ENTRY_ID_PROPERTY)
    YggdrasilHyperZoneCredential-->>Caller: normalized entryId
Loading

File-Level Changes

Change Details Files
Adds a reusable credential property API and makes all HyperZone credentials property-capable.
  • Introduces a property-holder interface with read, write, existence, and removal operations.
  • Extends the credential contract so implementations expose properties with a default per-instance map.
api/src/main/kotlin/icu/h2l/api/util/IPropertiesHolder.kt
api/src/main/kotlin/icu/h2l/api/profile/HyperZoneCredential.kt
Publishes the Yggdrasil entry ID through the credential properties API.
  • Initializes the public yggdrasil-entry-id property from entryId, normalized to lowercase.
  • Defines a public constant for the property key.
auth-yggd/src/main/kotlin/icu/h2l/login/auth/online/credential/YggdrasilHyperZoneCredential.kt

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@ksqeib
ksqeib merged commit 9fe42cd into HyperZoneLogin:master Oct 14, 2026
1 of 2 checks passed

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 3 issues

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="api/src/main/kotlin/icu/h2l/api/util/IPropertiesHolder.kt" line_range="26" />
<code_context>
+
+interface IPropertiesHolder {
+    val properties: HashMap<String, String>
+        get() = HashMap()
+
+    fun getProperty(key: String): String {
</code_context>
<issue_to_address>
**Credential properties disappear**

When a credential uses the inherited default `properties` getter, `properties` returns a fresh `HashMap` on each access, so `setProperty` writes to a discarded map and later `hasProperty` or `getProperty` calls cannot see the value; callers cannot retrieve the Yggdrasil entry ID.

Keep one persistent backing map per credential instead of creating a new map on each access.

Also at `auth-yggd/src/main/kotlin/icu/h2l/login/auth/online/credential/YggdrasilHyperZoneCredential.kt:40`.
</issue_to_address>

### Comment 2
<location path="api/src/main/kotlin/icu/h2l/api/profile/HyperZoneCredential.kt" line_range="33" />
<code_context>
  * 是否已绑定、如何绑定到 Profile,都由各认证模块自己的实现负责。
  */
-interface HyperZoneCredential {
+interface HyperZoneCredential : IPropertiesHolder {
     /**
      * 认证渠道唯一标识,由子模块负责稳定定义。
</code_context>
<issue_to_address>
**Java credential implementations break**

When a Java module has an existing `HyperZoneCredential` implementation compiled against this API, a Java credential implementation compiled against the previous API has no implementations of the newly inherited property methods; with Kotlin’s default JVM interface mode, calls to those methods fail with `AbstractMethodError`, and recompiling the implementation requires adding them.

Preserve Java implementor compatibility by emitting JVM default methods for the new interface API or by providing a compatibility adapter that does not require new implementation methods.
</issue_to_address>

### Comment 3
<location path="auth-yggd/src/main/kotlin/icu/h2l/login/auth/online/credential/YggdrasilHyperZoneCredential.kt" line_range="40" />
<code_context>
     override val credentialId: String = "$entryId:$authenticatedUUID"

+    init {
+        setProperty(YGGDRASIL_ENTRY_ID_PROPERTY, entryId.lowercase(Locale.getDefault()))
+    }
+
</code_context>
<issue_to_address>
**Entry IDs stop matching**

When the default locale is Turkish and an entry ID contains uppercase `I`, `entryId.lowercase(Locale.getDefault())` produces a dotless `ı`, while `EntryTableManager` normalizes IDs with locale-independent `lowercase()`; consumers receive a property value that does not match the registered entry ID.

Normalize the entry ID with locale-independent lowercasing.
</issue_to_address>

Sourcery assessment

Approval pending. 3 findings to address first.

Blocking findings: api/src/main/kotlin/icu/h2l/api/util/IPropertiesHolder.kt:26, api/src/main/kotlin/icu/h2l/api/profile/HyperZoneCredential.kt:33, auth-yggd/src/main/kotlin/icu/h2l/login/auth/online/credential/YggdrasilHyperZoneCredential.kt:40


Sourcery is free for open source - if you like our reviews please consider sharing them ✨


interface IPropertiesHolder {
val properties: HashMap<String, String>
get() = HashMap()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 High · Credential properties disappear

When a credential uses the inherited default properties getter, properties returns a fresh HashMap on each access, so setProperty writes to a discarded map and later hasProperty or getProperty calls cannot see the value; callers cannot retrieve the Yggdrasil entry ID.

Keep one persistent backing map per credential instead of creating a new map on each access.

Also at auth-yggd/src/main/kotlin/icu/h2l/login/auth/online/credential/YggdrasilHyperZoneCredential.kt:40.

Prompt for AI agents
In `api/src/main/kotlin/icu/h2l/api/util/IPropertiesHolder.kt` at line 26:

**Credential properties disappear**

When a credential uses the inherited default `properties` getter, `properties` returns a fresh `HashMap` on each access, so `setProperty` writes to a discarded map and later `hasProperty` or `getProperty` calls cannot see the value; callers cannot retrieve the Yggdrasil entry ID.

Keep one persistent backing map per credential instead of creating a new map on each access.

Also at `auth-yggd/src/main/kotlin/icu/h2l/login/auth/online/credential/YggdrasilHyperZoneCredential.kt:40`.

* 是否已绑定、如何绑定到 Profile,都由各认证模块自己的实现负责。
*/
interface HyperZoneCredential {
interface HyperZoneCredential : IPropertiesHolder {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium · Java credential implementations break

When a Java module has an existing HyperZoneCredential implementation compiled against this API, a Java credential implementation compiled against the previous API has no implementations of the newly inherited property methods; with Kotlin’s default JVM interface mode, calls to those methods fail with AbstractMethodError, and recompiling the implementation requires adding them.

Preserve Java implementor compatibility by emitting JVM default methods for the new interface API or by providing a compatibility adapter that does not require new implementation methods.

Prompt for AI agents
In `api/src/main/kotlin/icu/h2l/api/profile/HyperZoneCredential.kt` at line 33:

**Java credential implementations break**

When a Java module has an existing `HyperZoneCredential` implementation compiled against this API, a Java credential implementation compiled against the previous API has no implementations of the newly inherited property methods; with Kotlin’s default JVM interface mode, calls to those methods fail with `AbstractMethodError`, and recompiling the implementation requires adding them.

Preserve Java implementor compatibility by emitting JVM default methods for the new interface API or by providing a compatibility adapter that does not require new implementation methods.

override val credentialId: String = "$entryId:$authenticatedUUID"

init {
setProperty(YGGDRASIL_ENTRY_ID_PROPERTY, entryId.lowercase(Locale.getDefault()))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium · Entry IDs stop matching

When the default locale is Turkish and an entry ID contains uppercase I, entryId.lowercase(Locale.getDefault()) produces a dotless ı, while EntryTableManager normalizes IDs with locale-independent lowercase(); consumers receive a property value that does not match the registered entry ID.

Normalize the entry ID with locale-independent lowercasing.

Prompt for AI agents
In `auth-yggd/src/main/kotlin/icu/h2l/login/auth/online/credential/YggdrasilHyperZoneCredential.kt` at line 40:

**Entry IDs stop matching**

When the default locale is Turkish and an entry ID contains uppercase `I`, `entryId.lowercase(Locale.getDefault())` produces a dotless `ı`, while `EntryTableManager` normalizes IDs with locale-independent `lowercase()`; consumers receive a property value that does not match the registered entry ID.

Normalize the entry ID with locale-independent lowercasing.

@qyl27
qyl27 deleted the feat/credential-properties branch October 14, 2026 14:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants