# 게이트웨이가 적은 검사 순서 PolicyAwareMongoNativeGateway.java:8 /** PolicyAwareMongoNativeGateway.java:9 * The D3 capability gateway (design §5). PolicyAwareMongoNativeGateway.java:10 * PolicyAwareMongoNativeGateway.java:11 *

Runs the design's stated sequence and stops at the first refusal: registration, capability, PolicyAwareMongoNativeGateway.java:12 * database profile, collection profile, timeout, category, then execution. The audit record carries PolicyAwareMongoNativeGateway.java:13 * the operation id and the outcome and never the BSON arguments — the arguments are the part that PolicyAwareMongoNativeGateway.java:14 * contains data, and an audit trail that leaks data is a liability rather than a control. PolicyAwareMongoNativeGateway.java:15 */ README 가 적은 순서 : README.md:65 D3는 raw client escape가 아니다. `PolicyAwareMongoNativeGateway`가 capability → database profile → README.md:66 collection allowlist → operation name → timeout → consistency → result limit → trace → redaction → README.md:67 command category → D4 차단 순서를 고정한다. # 게이트웨이가 실제로 하는 일 PolicyAwareMongoNativeGateway.java:33 @Override PolicyAwareMongoNativeGateway.java:34 public T execute(ApprovedMongoNativeOperation operation) { PolicyAwareMongoNativeGateway.java:35 Objects.requireNonNull(operation, "operation"); PolicyAwareMongoNativeGateway.java:36 policy.require(operation); PolicyAwareMongoNativeGateway.java:37 boolean succeeded = false; PolicyAwareMongoNativeGateway.java:38 try { PolicyAwareMongoNativeGateway.java:39 T result = operation.body().apply(databaseResolver.apply(operation.databaseProfile())); PolicyAwareMongoNativeGateway.java:40 succeeded = true; PolicyAwareMongoNativeGateway.java:41 return result; PolicyAwareMongoNativeGateway.java:42 } finally { PolicyAwareMongoNativeGateway.java:43 auditRecorder.accept(operation.operationId(), succeeded); PolicyAwareMongoNativeGateway.java:44 } PolicyAwareMongoNativeGateway.java:45 } PolicyAwareMongoNativeGateway.java:46 } # 정책이 실제로 거부하는 것 MongoNativeOperationPolicy.java:52 public void require(ApprovedMongoNativeOperation operation) { MongoNativeOperationPolicy.java:53 Objects.requireNonNull(operation, "operation"); MongoNativeOperationPolicy.java:54 MongoCapability registered = capabilityByOperation.get(operation.operationId()); MongoNativeOperationPolicy.java:55 if (registered == null) { MongoNativeOperationPolicy.java:56 throw MongoOperationRejectedException.of( MongoNativeOperationPolicy.java:57 "native.operation", MongoNativeOperationPolicy.java:58 "native operation '" MongoNativeOperationPolicy.java:59 + operation.operationId() MongoNativeOperationPolicy.java:60 + "' is not registered; the platform executes only pre-registered operation " MongoNativeOperationPolicy.java:61 + "implementations and never a caller-supplied command"); MongoNativeOperationPolicy.java:62 } MongoNativeOperationPolicy.java:63 if (registered != operation.capability()) { MongoNativeOperationPolicy.java:64 throw MongoOperationRejectedException.of( MongoNativeOperationPolicy.java:65 "native.operation", MongoNativeOperationPolicy.java:66 "native operation '" MongoNativeOperationPolicy.java:67 + operation.operationId() MongoNativeOperationPolicy.java:68 + "' is registered under capability " MongoNativeOperationPolicy.java:69 + registered MongoNativeOperationPolicy.java:70 + " but was submitted as " MongoNativeOperationPolicy.java:71 + operation.capability()); MongoNativeOperationPolicy.java:72 } MongoNativeOperationPolicy.java:73 MongoCapabilitySupport support = capabilities.require(registered); MongoNativeOperationPolicy.java:74 if (support.level() == MongoSupportLevel.UNSUPPORTED) { MongoNativeOperationPolicy.java:75 throw MongoOperationRejectedException.of( MongoNativeOperationPolicy.java:76 "native.operation", MongoNativeOperationPolicy.java:77 "capability " + registered + " is unsupported here: " + support.constraints()); MongoNativeOperationPolicy.java:78 } MongoNativeOperationPolicy.java:79 if (!allowedDatabaseProfiles.contains(operation.databaseProfile())) { MongoNativeOperationPolicy.java:80 throw MongoOperationRejectedException.of( MongoNativeOperationPolicy.java:81 "native.operation", MongoNativeOperationPolicy.java:82 "database profile '" + operation.databaseProfile() + "' is not on the native allowlist"); MongoNativeOperationPolicy.java:83 } MongoNativeOperationPolicy.java:84 if (!allowedCollectionProfiles.contains(operation.collectionProfile())) { MongoNativeOperationPolicy.java:85 throw MongoOperationRejectedException.of( MongoNativeOperationPolicy.java:86 "native.operation", MongoNativeOperationPolicy.java:87 "collection profile '" MongoNativeOperationPolicy.java:88 + operation.collectionProfile() MongoNativeOperationPolicy.java:89 + "' is not on the native allowlist"); MongoNativeOperationPolicy.java:90 } MongoNativeOperationPolicy.java:91 if (!operation.category().allowedOnCapabilityPlane()) { MongoNativeOperationPolicy.java:92 throw MongoOperationRejectedException.of( MongoNativeOperationPolicy.java:93 "native.operation", MongoNativeOperationPolicy.java:94 "operation '" MongoNativeOperationPolicy.java:95 + operation.operationId() MongoNativeOperationPolicy.java:96 + "' is an administrative command; drop, collMod, shard and user management run on " MongoNativeOperationPolicy.java:97 + "the D4 admin plane with its own credential"); MongoNativeOperationPolicy.java:98 } MongoNativeOperationPolicy.java:99 } MongoNativeOperationPolicy.java:100 require 안에서 예외를 던지는 자리 : 6 개 # 승인된 연산 값 타입이 선언한 것 ApprovedMongoNativeOperation.java:20 public record ApprovedMongoNativeOperation( ApprovedMongoNativeOperation.java:21 String operationId, ApprovedMongoNativeOperation.java:22 MongoCapability capability, ApprovedMongoNativeOperation.java:23 MongoNativeCommandCategory category, ApprovedMongoNativeOperation.java:24 String databaseProfile, ApprovedMongoNativeOperation.java:25 String collectionProfile, ApprovedMongoNativeOperation.java:26 Duration timeout, ApprovedMongoNativeOperation.java:27 int maxResults, ApprovedMongoNativeOperation.java:28 Function body) { ApprovedMongoNativeOperation.java:29 ApprovedMongoNativeOperation.java:30 public ApprovedMongoNativeOperation { ApprovedMongoNativeOperation.java:31 Objects.requireNonNull(operationId, "operationId"); ApprovedMongoNativeOperation.java:32 Objects.requireNonNull(capability, "capability"); ApprovedMongoNativeOperation.java:33 Objects.requireNonNull(category, "category"); ApprovedMongoNativeOperation.java:34 Objects.requireNonNull(databaseProfile, "databaseProfile"); ApprovedMongoNativeOperation.java:35 Objects.requireNonNull(collectionProfile, "collectionProfile"); ApprovedMongoNativeOperation.java:36 Objects.requireNonNull(timeout, "timeout"); ApprovedMongoNativeOperation.java:37 if (operationId.isBlank()) { ApprovedMongoNativeOperation.java:38 throw new IllegalArgumentException("a native operation needs an id"); ApprovedMongoNativeOperation.java:39 } ApprovedMongoNativeOperation.java:40 if (timeout.isNegative()) { ApprovedMongoNativeOperation.java:41 throw new IllegalArgumentException("a native operation timeout must not be negative"); ApprovedMongoNativeOperation.java:42 } ApprovedMongoNativeOperation.java:43 } ApprovedMongoNativeOperation.java:44 ApprovedMongoNativeOperation.java:45 /** ApprovedMongoNativeOperation.java:46 * A named operation with no body. ApprovedMongoNativeOperation.java:47 * ApprovedMongoNativeOperation.java:48 *

Exists so the gateway's rejection path is reachable and testable: an id nobody registered ApprovedMongoNativeOperation.java:49 * cannot be executed, and this is what asking for one looks like. ApprovedMongoNativeOperation.java:50 */ ApprovedMongoNativeOperation.java:51 public static ApprovedMongoNativeOperation unregistered(String operationId) { ApprovedMongoNativeOperation.java:52 return new ApprovedMongoNativeOperation<>( ApprovedMongoNativeOperation.java:53 operationId, ApprovedMongoNativeOperation.java:54 MongoCapability.ADMIN_PLANE, ApprovedMongoNativeOperation.java:55 MongoNativeCommandCategory.ADMIN, ApprovedMongoNativeOperation.java:56 "unspecified", ApprovedMongoNativeOperation.java:57 "unspecified", ApprovedMongoNativeOperation.java:58 Duration.ZERO, ApprovedMongoNativeOperation.java:59 0, ApprovedMongoNativeOperation.java:60 database -> null); ApprovedMongoNativeOperation.java:61 } ApprovedMongoNativeOperation.java:62 ApprovedMongoNativeOperation.java:63 /** True when this operation carries an executable body. */ ApprovedMongoNativeOperation.java:64 public boolean hasBody() { ApprovedMongoNativeOperation.java:65 return timeout.isPositive(); ApprovedMongoNativeOperation.java:66 } ApprovedMongoNativeOperation.java:67 } # 그 타입의 timeout 과 maxResults 를 읽는 자리 ApprovedMongoNativeOperation 을 참조하는 main 파일 : ApprovedMongoNativeOperation.java MongoNativeCapabilityGateway.java MongoNativeOperationPolicy.java PolicyAwareMongoNativeGateway.java 그 파일들 안에서 .timeout() 또는 .maxResults() 를 부르는 줄 : 0 개 ApprovedMongoNativeOperation.java:26 Duration timeout, ApprovedMongoNativeOperation.java:36 Objects.requireNonNull(timeout, "timeout"); ApprovedMongoNativeOperation.java:40 if (timeout.isNegative()) { ApprovedMongoNativeOperation.java:41 throw new IllegalArgumentException("a native operation timeout must not be negative"); ApprovedMongoNativeOperation.java:65 return timeout.isPositive(); PolicyAwareMongoNativeGateway.java:12 * database profile, collection profile, timeout, category, then execution. The audit record carries hasBody 를 부르는 줄 (선언 제외) : 0 개 # [대조] 같은 이름의 접근자를 실제로 적용하는 다른 타입들 PolicyAwareMongoAggregationExecutor.java:78 if (mapped.size() > effective.maxResults()) { PolicyAwareMongoAggregationExecutor.java:84 + effective.maxResults()); PolicyAwareMongoAggregationExecutor.java:92 long contextMillis = Math.max(1L, context.timeout().toMillis()); PolicyAwareMongoAggregationExecutor.java:94 registered.maxResults(), DefaultMongoImperativeExecutor.java:83 ScopedAccess access = new ScopedAccess(physicalCollection, operations, context.timeout()); DefaultMongoImperativeExecutor.java:93 if (elapsed.compareTo(context.timeout()) > 0) { DefaultMongoImperativeExecutor.java:103 + context.timeout().toMillis() PolicyAwareMongoQueryBuilder.java:199 query.limit(budget.maxResults()); MongoBudgetEnforcer.java:32 + requested.maxResults() MongoBudgetEnforcer.java:40 + registered.maxResults() DefaultReactiveMongoExecutor.java:76 .timeout(context.timeout()) DefaultReactiveMongoExecutor.java:108 .timeout(context.timeout()) DefaultReactiveMongoExecutor.java:154 context.operationName(), operationType, context.timeout()), MongoReactiveCursorPublisher.java:59 .limit(budget.maxResults()); MongoResultBudgetTracker.java:51 if (seen > budget.maxResults()) { MongoResultBudgetTracker.java:54 "the result stream produced more than the declared " + budget.maxResults() + " results"); SpringMongoTransactionSessionFactory.java:74 .defaultTransactionOptions(transactionOptions(descriptor, profile.timeout())) SpringReactiveMongoTransactionSessionFactory.java:76 transactionOptions(descriptor, profile.timeout())) # 이 게이트웨이가 조립되는가 두 이름이 나오는 자리 전부 : main · MongoNativeCapabilityGateway.java:10 public interface MongoNativeCapabilityGateway { main · PolicyAwareMongoNativeGateway.java:16 public final class PolicyAwareMongoNativeGateway implements MongoNativeCapabilityGateway { main · PolicyAwareMongoNativeGateway.java:24 public PolicyAwareMongoNativeGateway( test · PolicyAwareMongoNativeGatewayTest.java:19 class PolicyAwareMongoNativeGatewayTest { test · PolicyAwareMongoNativeGatewayTest.java:28 PolicyAwareMongoNativeGateway gateway = gateway(); test · PolicyAwareMongoNativeGatewayTest.java:114 PolicyAwareMongoNativeGateway gateway = test · PolicyAwareMongoNativeGatewayTest.java:115 new PolicyAwareMongoNativeGateway( test · PolicyAwareMongoNativeGatewayTest.java:139 private PolicyAwareMongoNativeGateway gateway() { test · PolicyAwareMongoNativeGatewayTest.java:140 return new PolicyAwareMongoNativeGateway( Bean 이나 Configuration 이 이 타입을 만드는 줄 : 0 개