refactor(gateway): unify v3 auth payload builders and vectors

This commit is contained in:
Peter Steinberger
2026-02-26 15:08:40 +01:00
parent 8315c58675
commit 081b1aa1ed
10 changed files with 313 additions and 168 deletions

View File

@@ -0,0 +1,52 @@
package ai.openclaw.android.gateway
internal object DeviceAuthPayload {
fun buildV3(
deviceId: String,
clientId: String,
clientMode: String,
role: String,
scopes: List<String>,
signedAtMs: Long,
token: String?,
nonce: String,
platform: String?,
deviceFamily: String?,
): String {
val scopeString = scopes.joinToString(",")
val authToken = token.orEmpty()
val platformNorm = normalizeMetadataField(platform)
val deviceFamilyNorm = normalizeMetadataField(deviceFamily)
return listOf(
"v3",
deviceId,
clientId,
clientMode,
role,
scopeString,
signedAtMs.toString(),
authToken,
nonce,
platformNorm,
deviceFamilyNorm,
).joinToString("|")
}
internal fun normalizeMetadataField(value: String?): String {
val trimmed = value?.trim().orEmpty()
if (trimmed.isEmpty()) {
return ""
}
// Keep cross-runtime normalization deterministic (TS/Swift/Kotlin):
// lowercase ASCII A-Z only for auth payload metadata fields.
val out = StringBuilder(trimmed.length)
for (ch in trimmed) {
if (ch in 'A'..'Z') {
out.append((ch.code + 32).toChar())
} else {
out.append(ch)
}
}
return out.toString()
}
}

View File

@@ -372,7 +372,7 @@ class GatewaySession(
val signedAtMs = System.currentTimeMillis()
val payload =
buildDeviceAuthPayloadV3(
DeviceAuthPayload.buildV3(
deviceId = identity.deviceId,
clientId = client.id,
clientMode = client.mode,
@@ -584,42 +584,6 @@ class GatewaySession(
}
}
private fun buildDeviceAuthPayloadV3(
deviceId: String,
clientId: String,
clientMode: String,
role: String,
scopes: List<String>,
signedAtMs: Long,
token: String?,
nonce: String,
platform: String?,
deviceFamily: String?,
): String {
val scopeString = scopes.joinToString(",")
val authToken = token.orEmpty()
val platformNorm = normalizeDeviceMetadataField(platform)
val deviceFamilyNorm = normalizeDeviceMetadataField(deviceFamily)
val parts =
mutableListOf(
"v3",
deviceId,
clientId,
clientMode,
role,
scopeString,
signedAtMs.toString(),
authToken,
nonce,
platformNorm,
deviceFamilyNorm,
)
return parts.joinToString("|")
}
private fun normalizeDeviceMetadataField(value: String?): String =
value?.trim()?.lowercase(Locale.ROOT).orEmpty()
private fun normalizeCanvasHostUrl(
raw: String?,
endpoint: GatewayEndpoint,