Sub-scope 03 (cache-redis) sdk/api/key + error + command + reactive — manifest and probes
revision=a24ece9cf797f7ea647e33bf846b115208ed1ba5
generatedAt=2026-08-30T04:41:02+00:00

=== OWNED FILES ===
7d962093375f0c36434d719a09907a754381fba3 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/command/AdvancedOperationPermit.java 19
e4a4f7d278375104757f5ecd0a3c346d5ca7da31 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/command/CommandAccess.java 17
131e7c9bbdd7a2e23f0d8d0957c72c37cb6c585d main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/command/CommandId.java 85
6112df8fa18da163230367f89313984aba55c367 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/command/CommandSupport.java 17
360a583fbefc2bdd84587bb477ece62a5e20a2a5 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/command/KeySpec.java 76
fe9a3abb85761461514966f8d1405ee531625cd8 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/command/MultiKeyPermit.java 16
05028e3b1776e895906398640fb1dcbabedef274 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/command/OperationBudget.java 54
c37cf3b690f18a08ada8832eab4cfe3994dd8148 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/command/PersistentKeyPermit.java 16
4bf3808adfef86de7ef1052a3141a7c8fedeec4c main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/command/RedisCommandDescriptor.java 60
afb4b1bf976b42e9688efc76cea1aacded73d96c main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/command/RedisPermitVerifier.java 34
169daebddd2191ef5d74820b224aad5561ec9133 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/command/RedisPolicyAuthority.java 34
81a060369f496b1d00cc107b8d299b0acef1052a main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/command/RedisRiskLevel.java 31
447e777029e7682f6db4560a3fad669d4ee7861c main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/command/TimeoutProfile.java 42
2cbe99146bf79f371b9e3a171645cf5efa168c02 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/error/RedisAccessDeniedException.java 28
50d3fdc25bd971caa27a8491939a62b13210d1fa main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/error/RedisAmbiguousExecutionException.java 31
582d3dc835dee3ac3e3e1f82a79b1086dd335ab1 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/error/RedisBusyException.java 28
d3e2640731f096877327f5b001786ee25eb911a4 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/error/RedisCapabilityUnavailableException.java 29
4c40194c7e1f58b3c86c2d6b600e7cdb8ddc9121 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/error/RedisCommandRejectedException.java 29
c4a8e084d5670092265d860b93a316004bccdf35 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/error/RedisConnectionException.java 28
3fc7929765ff43d2f45c295e6dcc45b137595aea main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/error/RedisCrossSlotException.java 28
0572a35da76bd519b6a330bf6e7d18ed627e775f main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/error/RedisDataTypeMismatchException.java 29
a402d3b6c7370647521d0168e1f4e8eaaa3f7615 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/error/RedisFailureMetadata.java 106
a96ed0bf7af82ec61fcb1b04d0728c54def23140 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/error/RedisNoScriptException.java 28
d558d87666acd779b42692013bb760890f65b62b main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/error/RedisOperationException.java 58
11985da1f6c97dbeb55d7337c5677255ec990c50 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/error/RedisRedirectionException.java 28
4f6cc4740449cc386983c7d561bbd50570783fb5 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/error/RedisSerializationException.java 32
db98a87e30b031319274ca50008877b6d7531994 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/error/RedisTimeoutException.java 28
3b16f5498a0845e2b229434dd97b7f60010f9162 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/key/BitmapKey.java 17
eb8c5391da357f39ef13dfda4f62a1551bd551d2 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/key/GeoKey.java 19
e73bac153261577fc9be192a7d88df4e8b932429 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/key/HashKey.java 24
46d7ff5dfd5dc47c1e16264fe84bd07c79ba0751 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/key/HyperLogLogKey.java 20
21f1498ac07bbdfabc99b57dbb809f46d1a9c226 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/key/ListKey.java 20
c572cb9c1d6c4ddddfcb8d47fd0506c098094847 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/key/QualifiedRedisKey.java 49
5dfaa3350559cff62d0ea587d964ed4d38dc9ee5 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/key/RedisKeyName.java 15
f9ec9cd3ac14adcd50f1816fef01fa689ded8370 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/key/RedisKeyRenderer.java 69
55a7b9d74b3c8e48e872de189f318ab475edad1a main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/key/RedisKeyRules.java 101
56c73270d657b105ffd1454671efad1cddfded65 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/key/RedisNamespace.java 29
6203eeb20f8e52ef8fc25cd569f121fa67e4c113 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/key/RedisSlotTag.java 17
3b6ab0a06a2b425f0b56c189722f70291fd58e60 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/key/RedisTypedKey.java 26
73238fa9db52df2498392e599c5e92e2fd966e69 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/key/SetKey.java 19
fd2d1444bca91ed05c71eb1cbb60a1fcf035a440 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/key/SortedSetKey.java 20
9de8ed5736db8ea61abecbfc3a673afa4c889518 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/key/StreamKey.java 20
ce887cd0141b876bdf057fc3e791271886e34aa1 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/key/TypedRedisKeys.java 217
4a0371eb46afe4aa9bc3bf866bf456f86c00a1e1 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/key/ValueKey.java 20
544c98b1e8070aceec7cb0ac72145a9738c57454 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/reactive/ReactiveRedisBatchOperations.java 19
fb776ae0d021527e7d943c2caf2827ef7d254cb4 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/reactive/ReactiveRedisBitFieldOperations.java 28
a58ae7b617c8a459906224680ff6571a08aeb76f main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/reactive/ReactiveRedisBitmapOperations.java 69
6168d8c02497f01f218aef7b96d24c3173f3a1bb main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/reactive/ReactiveRedisBlockingListOperations.java 48
e11b517f2a1921b5b40f5d79eee79b9eb3d41922 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/reactive/ReactiveRedisBlockingStreamOperations.java 46
2f6a10d87deea0ac91617bb01c37f0229fc0b5e5 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/reactive/ReactiveRedisGeoOperations.java 82
598e00d8481b8fe1aef4ce9253f6e4a7a167258c main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/reactive/ReactiveRedisHashFieldExpirationOperations.java 51
269ce5a7289e3e771e47c20e317929d0dffe6d17 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/reactive/ReactiveRedisHashOperations.java 150
fe7a26f6e8c33e39b8bfde63fe4eed0ef1b689b4 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/reactive/ReactiveRedisHyperLogLogOperations.java 42
682733bb7aea5fa65521d6ecda60256bb1e9428f main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/reactive/ReactiveRedisKeyOperations.java 133
f895b644161fbfbb40c29e107ab87fdbb1a51586 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/reactive/ReactiveRedisListOperations.java 160
8f8c69eb989cfd1d1537e4729b939aa6dabeef7c main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/reactive/ReactiveRedisPubSubOperations.java 44
650a75218a60ae8a655551f86070b728601cea8b main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/reactive/ReactiveRedisSetOperations.java 168
1b61d246aa7b5cb154566e7765a0617d373b1052 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/reactive/ReactiveRedisShardedPubSubOperations.java 29
26655ff49e817146815e436d1facaf97099d819a main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/reactive/ReactiveRedisSortedSetOperations.java 196
5443d0091ca147737ba0932d5ebbb8f25bc1efd9 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/reactive/ReactiveRedisStreamOperations.java 202
621356218e9051ba5b09709f6cf57c40889369e5 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/reactive/ReactiveRedisValueOperations.java 163
d5b25f5ff10a32318609756fb03006d76faa6982 test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/command/OperationBudgetTest.java 36
8576733068fdf68d13b00d8b54d0952bbbb65225 test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/key/RedisKeyRendererTest.java 64
5439821ee078d9eee8a0a327e529ae1ce5e1f517 test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/key/RedisKeyRulesTest.java 69

main: 61  test: 3
=== 8.1 도달 불가 검증 분기: requireIdentifier의 다섯 검사 ===
$ sed -n '22,30p;60,80p' adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/key/RedisKeyRules.java

  private static final Pattern IDENTIFIER = Pattern.compile("^[A-Za-z0-9][A-Za-z0-9._~-]{0,127}$");

  private static final Pattern JSON_WEB_TOKEN =
      Pattern.compile("^[A-Za-z0-9_-]{8,}\\.[A-Za-z0-9_-]{8,}\\.[A-Za-z0-9_-]{8,}$");

  private static final Pattern INTERNATIONAL_PHONE = Pattern.compile("^\\+\\d[\\d.~-]{7,}$");

  private RedisKeyRules() {
    if (value == null || !IDENTIFIER.matcher(value).matches()) {
      throw new IllegalArgumentException(
          "identifier must be 1..128 characters of [A-Za-z0-9._~-] and must not contain a"
              + " key separator");
    }
    String lowerCase = value.toLowerCase(Locale.ROOT);
    if (value.indexOf('@') >= 0) {
      throw new IllegalArgumentException("identifier must not contain a mail address");
    }
    if (JSON_WEB_TOKEN.matcher(value).matches()) {
      throw new IllegalArgumentException("identifier must not contain a JSON web token");
    }
    if (INTERNATIONAL_PHONE.matcher(value).matches()) {
      throw new IllegalArgumentException("identifier must not contain a phone number");
    }
    if (lowerCase.startsWith("bearer") || lowerCase.startsWith("eyj")) {
      throw new IllegalArgumentException("identifier must not contain authentication material");
    }
    return value;
  }

exit=0

--- IDENTIFIER 문자 클래스가 '@'와 '+'를 이미 배제하는가 ---
$ grep -n 'IDENTIFIER =' adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/key/RedisKeyRules.java
23:  private static final Pattern IDENTIFIER = Pattern.compile("^[A-Za-z0-9][A-Za-z0-9._~-]{0,127}$");
exit=0

$ grep -n 'rejectsEmailInIdentifier' -A 5 adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/key/RedisKeyRulesTest.java
12:  void rejectsEmailInIdentifier() {
13-    assertThatThrownBy(() -> new RedisKeyName("user", "person@example.com"))
14-        .isInstanceOf(IllegalArgumentException.class);
15-  }
16-
17-  @Test
exit=0

$ grep -n 'rejectsInternationalPhoneNumbersInIdentifier' -A 8 adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/key/RedisKeyRulesTest.java
31:  void rejectsInternationalPhoneNumbersInIdentifier() {
32-    assertThatThrownBy(() -> new RedisKeyName("contact", "+821012345678"))
33-        .isInstanceOf(IllegalArgumentException.class);
34-  }
35-
36-  @Test
37-  void rejectsSeparatorInjectionInEveryKeyPart() {
38-    assertThatThrownBy(() -> new RedisKeyName("user", "1:2"))
39-        .isInstanceOf(IllegalArgumentException.class);
exit=0

=== 8.1b 선언되었으나 읽히지 않는 술어 ===
$ git grep -n 'requiresPermit()' -- 'adapter/outbound/cache-redis/src'
adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/command/RedisRiskLevel.java:19:  public boolean requiresPermit() {
exit=0

$ git grep -n 'deniedToApplications()' -- 'adapter/outbound/cache-redis/src'
adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/command/RedisRiskLevel.java:28:  public boolean deniedToApplications() {
adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/command/CommandPolicyGuard.java:126:    if (policy.riskLevel().deniedToApplications()
adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/raw/RawCommandApprovals.java:116:    if (policy.riskLevel().deniedToApplications()) {
exit=0

=== 8.2 sync/reactive 대칭: getRange 포함 실제 대조 ===
$ grep -c ';' adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/operations/RedisValueOperations.java adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/reactive/ReactiveRedisValueOperations.java
adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/operations/RedisValueOperations.java:20
adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/reactive/ReactiveRedisValueOperations.java:25
exit=0

$ diff <(grep -oE '[a-z][A-Za-z]*\(' adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/operations/RedisValueOperations.java | sort -u) <(grep -oE '[a-z][A-Za-z]*\(' adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/reactive/ReactiveRedisValueOperations.java | sort -u)
exit=0

=== 8.2b RedisCommandDescriptor 교차 필드 불변식 ===
$ grep -n 'throw new IllegalArgumentException' -B 4 adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/command/RedisCommandDescriptor.java
30-    Objects.requireNonNull(access, "access must be non-null");
31-    Objects.requireNonNull(keySpec, "key specification must be non-null");
32-    Objects.requireNonNull(timeoutProfile, "timeout profile must be non-null");
33-    if (support == CommandSupport.BLOCKED && access != CommandAccess.NONE) {
34:      throw new IllegalArgumentException("a blocked command must not carry an ACL account");
35-    }
36-    if (riskLevel == RedisRiskLevel.R4 && support != CommandSupport.BLOCKED) {
37:      throw new IllegalArgumentException("an R4 command must be blocked");
38-    }
39-    if (riskLevel == RedisRiskLevel.R3
40-        && support != CommandSupport.ADMIN_ONLY
41-        && support != CommandSupport.BLOCKED) {
42:      throw new IllegalArgumentException("an R3 command must be admin-only or blocked");
43-    }
44-    if (!readOnly && retrySafe && mayBeAmbiguous) {
45:      throw new IllegalArgumentException(
exit=0

=== 8.3 실패 메타데이터: 모호 실행과 재시도의 배타 ===
$ grep -n 'ambiguousExecution\|retryable\|storedDataCorruption\|notSent' adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/error/RedisFailureMetadata.java | head -20
21:    boolean retryable,
22:    boolean ambiguousExecution,
41:    if (retryable && ambiguousExecution) {
42:      throw new IllegalArgumentException("an ambiguous execution must never be marked retryable");
61:   * <p>Deliberately not {@link #notSent}: that factory derives {@code retryable} from {@code
71:   * @return metadata marked not retryable and not ambiguous
73:  public static RedisFailureMetadata storedDataCorruption(
90:  public static RedisFailureMetadata notSent(
exit=0

$ git grep -n 'storedDataCorruption(' -- 'adapter/outbound/cache-redis/src/main' | head
adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/error/RedisFailureMetadata.java:73:  public static RedisFailureMetadata storedDataCorruption(
adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/codec/JsonEnvelopeFraming.java:202:        RedisFailureMetadata.storedDataCorruption(
adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/codec/VersionedJsonCodec.java:103:        RedisFailureMetadata.storedDataCorruption(
exit=0

=== 8.4 예외 계층: transient metadata ===
$ grep -n 'transient\|serialVersionUID' adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/error/RedisOperationException.java
14:  private static final long serialVersionUID = 1L;
16:  private final transient RedisFailureMetadata metadata;
exit=0

$ git ls-files 'adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/error' | wc -l
14
exit=0

