Add secure administrator operations console

Provide TOTP-authenticated, role-controlled user and credit workflows with paginated audit data and SQL-backed statistics so operations can manage growth safely.
This commit is contained in:
Rocky
2026-08-17 15:20:34 +08:00
parent 676bfd2451
commit 1a9c518f96
76 changed files with 14602 additions and 3 deletions
@@ -80,6 +80,161 @@ class CreditServiceTest : FunSpec({
store.ledger.filter { it.type == LedgerEntryType.SIGNUP_TRIAL } shouldHaveSize 1
}
test("manual grant appends one linked audit and ledger entry") {
val store = storeWithRates(now)
val service = service(store, now)
val userId = UUID.randomUUID()
store.registeredUsers += userId
val result = service.grantManual(
operatorId = TEST_OPERATOR_ID,
userId = userId,
credits = 250,
reason = "Customer support adjustment",
requestId = "support-ticket-1042",
idempotencyKey = "manual-grant-key-001",
)
result.replayed shouldBe false
result.balanceAfter shouldBeExactly 250
store.balance(userId) shouldBeExactly 250
store.manualGrants.single() shouldBe result.grant
store.adminAudits.single().id shouldBe result.grant.auditLogId
store.ledger.single { it.type == LedgerEntryType.MANUAL_GRANT }.let { ledger ->
ledger.referenceId shouldBe result.grant.id
ledger.id shouldBe result.grant.ledgerEntryId
}
}
test("manual grant replay is stable and rejects changed parameters") {
val store = storeWithRates(now)
val service = service(store, now)
val userId = UUID.randomUUID()
store.registeredUsers += userId
val first = service.grantManual(
TEST_OPERATOR_ID,
userId,
100,
"Retention credit",
"support-ticket-1043",
"manual-grant-key-002",
)
val replay = service.grantManual(
TEST_OPERATOR_ID,
userId,
100,
"Retention credit",
"support-ticket-1043",
"manual-grant-key-002",
)
replay.grant shouldBe first.grant
replay.replayed shouldBe true
shouldThrow<CreditConflict> {
service.grantManual(
TEST_OPERATOR_ID,
userId,
101,
"Retention credit",
"support-ticket-1043",
"manual-grant-key-002",
)
}
store.balance(userId) shouldBeExactly 100
store.manualGrants shouldHaveSize 1
store.ledger.filter { it.type == LedgerEntryType.MANUAL_GRANT } shouldHaveSize 1
}
test("manual grant validates positive amount and rolls back an audit failure") {
val store = storeWithRates(now)
val service = service(store, now)
val userId = UUID.randomUUID()
store.registeredUsers += userId
shouldThrow<InvalidCreditRequest> {
service.grantManual(
TEST_OPERATOR_ID,
userId,
0,
"Invalid adjustment",
"support-ticket-1044",
"manual-grant-key-003",
)
}
store.failNextManualGrantInsert = true
shouldThrow<IllegalStateException> {
service.grantManual(
TEST_OPERATOR_ID,
userId,
50,
"Rollback adjustment",
"support-ticket-1045",
"manual-grant-key-004",
)
}
store.balance(userId) shouldBeExactly 0
store.manualGrants shouldHaveSize 0
store.adminAudits shouldHaveSize 0
store.ledger.filter { it.type == LedgerEntryType.MANUAL_GRANT } shouldHaveSize 0
}
test("concurrent manual grant replay credits exactly once") {
val store = storeWithRates(now)
val service = service(store, now)
val userId = UUID.randomUUID()
store.registeredUsers += userId
val results = coroutineScope {
List(8) {
async(Dispatchers.Default) {
service.grantManual(
TEST_OPERATOR_ID,
userId,
75,
"Concurrent adjustment",
"support-ticket-1046",
"manual-grant-key-005",
)
}
}.awaitAll()
}
results.map { it.grant.id }.distinct() shouldHaveSize 1
store.balance(userId) shouldBeExactly 75
store.manualGrants shouldHaveSize 1
store.ledger.filter { it.type == LedgerEntryType.MANUAL_GRANT } shouldHaveSize 1
}
test("manual grant supports the maximum balance and rejects overflow") {
val store = storeWithRates(now)
val service = service(store, now)
val userId = UUID.randomUUID()
store.registeredUsers += userId
service.grantManual(
TEST_OPERATOR_ID,
userId,
Long.MAX_VALUE,
"Maximum supported adjustment",
"support-ticket-1047",
"manual-grant-key-006",
)
shouldThrow<InvalidCreditRequest> {
service.grantManual(
TEST_OPERATOR_ID,
userId,
1,
"Overflow adjustment",
"support-ticket-1048",
"manual-grant-key-007",
)
}
store.balance(userId) shouldBeExactly Long.MAX_VALUE
store.manualGrants shouldHaveSize 1
}
test("balance overflow rolls back without appending a ledger entry") {
val store = storeWithRates(now)
val service = service(store, now)
@@ -574,3 +729,5 @@ private fun llmRate(now: Instant) = CreditRateVersion(
outputCreditsNumerator = 3,
outputTokensDenominator = 1_000,
)
private val TEST_OPERATOR_ID = UUID.fromString("11111111-1111-1111-1111-111111111111")