epic-12: after epic audit and init commit
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
import com.correx.core.approvals.Tier
|
||||
import com.correx.core.approvals.domain.DefaultApprovalEngine
|
||||
import com.correx.core.approvals.model.ApprovalContext
|
||||
import com.correx.core.approvals.model.ApprovalGrant
|
||||
import com.correx.core.approvals.model.ApprovalScopeIdentity
|
||||
import com.correx.core.approvals.ApprovalStatus
|
||||
import com.correx.core.approvals.GrantScope
|
||||
import com.correx.core.events.types.GrantId
|
||||
import com.correx.core.events.types.ProjectId
|
||||
import com.correx.core.events.types.SessionId
|
||||
import com.correx.core.events.types.StageId
|
||||
import com.correx.core.sessions.ApprovalMode
|
||||
import com.correx.testing.fixtures.request
|
||||
import kotlinx.datetime.Instant
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
class ApprovalEngineEdgeCasesTest {
|
||||
|
||||
private val engine = DefaultApprovalEngine()
|
||||
private val now = Instant.parse("2026-01-01T00:00:01Z")
|
||||
|
||||
private fun context(mode: ApprovalMode) = ApprovalContext(
|
||||
ApprovalScopeIdentity(SessionId("s1"), StageId("st1"), ProjectId("p1")),
|
||||
mode
|
||||
)
|
||||
|
||||
@Test
|
||||
fun `grants from different scopes apply only to matching identity`() {
|
||||
val sessionGrant = ApprovalGrant(
|
||||
id = GrantId("g1"),
|
||||
scope = GrantScope.SESSION,
|
||||
permittedTiers = setOf(Tier.T3),
|
||||
reason = "",
|
||||
timestamp = Instant.parse("2026-01-01T00:00:00Z")
|
||||
)
|
||||
val stageGrant = ApprovalGrant(
|
||||
id = GrantId("g2"),
|
||||
scope = GrantScope.STAGE(StageId("st2")),
|
||||
permittedTiers = setOf(Tier.T4),
|
||||
reason = "",
|
||||
timestamp = Instant.parse("2026-01-01T00:00:00Z")
|
||||
)
|
||||
|
||||
val decision = engine.evaluate(
|
||||
request("r1", Tier.T4),
|
||||
context(ApprovalMode.DENY),
|
||||
listOf(sessionGrant, stageGrant),
|
||||
now
|
||||
)
|
||||
assertEquals(
|
||||
ApprovalStatus.PENDING, decision.state,
|
||||
"Stage grant for different stage should not apply"
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `expired grant is ignored`() {
|
||||
val past = Instant.parse("2025-12-31T23:59:59Z")
|
||||
val expiredGrant = ApprovalGrant(
|
||||
id = GrantId("g1"),
|
||||
scope = GrantScope.SESSION,
|
||||
permittedTiers = setOf(Tier.T2),
|
||||
reason = "",
|
||||
timestamp = past,
|
||||
expiresAt = past // expired before 'now'
|
||||
)
|
||||
val decision = engine.evaluate(
|
||||
request("r1", Tier.T2),
|
||||
context(ApprovalMode.DENY),
|
||||
listOf(expiredGrant),
|
||||
now
|
||||
)
|
||||
assertEquals(ApprovalStatus.PENDING, decision.state)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `timestamp passed to evaluate is used as resolution timestamp`() {
|
||||
val myNow = Instant.parse("2026-07-01T12:00:00Z")
|
||||
val decision = engine.evaluate(
|
||||
request("r1", Tier.T0),
|
||||
context(ApprovalMode.YOLO),
|
||||
emptyList(),
|
||||
myNow
|
||||
)
|
||||
assertEquals(myNow, decision.resolutionTimestamp)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user