Files
tech-log-backend/docs/superpowers/specs/2026-07-28-fileserver-r2-control-plane-provider-selection-design.md
T

26 KiB

Fileserver R2 Control Plane and Provider Selection Design

  • Date: 2026-07-28
  • Status: 구현·전체 repository gate·독립 spec/quality review 완료
  • Scope: provider-neutral R2 control plane, explicit destination/provider selection, first local-persistent qualification provider
  • Parent: Fileserver Production Capability Deep Design

1. 목표

현재 LocalFilePublicationAdapter의 single-node process-restart R1을 운영 topology의 기본값으로 승격하지 않는다. 이번 increment는 다음을 구현한다.

  1. application에는 기존 provider-neutral FilePublicationPort만 유지한다.
  2. adapter 내부에 destination binding, provider descriptor, durable operation/manifest/reference control plane을 둔다.
  3. 활성화된 Fileserver는 정확한 destination과 provider를 명시해야 하며 implicit local fallback을 금지한다.
  4. 첫 qualification provider로 pre-provisioned persistent filesystem을 사용하는 local-persistent를 구현한다.
  5. shared-mountedsftp가 같은 control-plane state machine을 재사용할 수 있게 하되 이번 increment에서 가짜 provider나 동작하지 않는 bean을 만들지 않는다.

local-persistent는 container writable layer나 임시 디렉터리를 의미하지 않는다. 단일 노드 또는 node-attached persistent volume과 private owner boundary가 증명된 환경만 대상으로 한다.

2. 비범위

이번 increment에 포함하지 않는다.

  • NFS 또는 다른 shared mount의 multi-client correctness;
  • SFTP SDK, connection pool, credential, OpenSSH qualification;
  • cross-node producer fencing;
  • background reaper, retention delete, quota reservation;
  • metrics/tracing/health implementation;
  • optional content read/delete/list API;
  • object storage. Object storage는 별도 outbound leaf의 책임이다.

이 항목은 seam만 만들지 않는다. 실제 semantic provider를 구현하는 후속 increment에서만 dependency, bean, setting을 추가한다.

3. 검토한 접근

A. 현재 local adapter를 바로 R2로 표시

설정과 change surface는 작지만 provider selector, terminal manifest, opaque-reference direct lookup과 strict startup evidence가 없다. R2를 과장하므로 선택하지 않는다.

B. Local, NFS, SFTP를 동시에 구현

최종 기능은 많지만 서로 다른 보장과 real-service CI가 한 change surface에 결합된다. NFS와 OpenSSH 인프라가 없으면 검증되지 않은 provider가 남으므로 선택하지 않는다.

C. Provider-neutral control plane + local-persistent 첫 qualification

공통 state machine과 binding을 먼저 고정하고 한 provider를 실제 crash/security 테스트로 qualification한다. 이후 provider가 control-plane 계약을 재사용하면서도 각자의 보장을 별도로 증명할 수 있다. 이 접근을 선택한다.

4. 계층과 모듈 경계

application-core
  FilePublicationPort
  FilePublishRequest
  FilePublishReceipt
          |
          v
adapter:outbound:fileserver
  RoutingFilePublicationAdapter
          |
          +-- DestinationBindingRegistry
          +-- FilePublicationProviderRegistry
          +-- DurablePublicationCoordinator
          +-- ProviderControlPlane
                    |
                    +-- LocalPersistentPublicationProvider
  • application/domain에는 provider ID, filesystem path, manifest locator, Spring 또는 NIO 타입을 추가하지 않는다.
  • RoutingFilePublicationAdapter만 production FilePublicationPort bean이다.
  • provider와 control-plane SPI는 fileserver package 내부 타입이다. 범용 filesystem/SDK API를 public bean으로 노출하지 않는다.
  • shared-mountedsftp 타입 값은 구현 전까지 accepted setting으로 등록하지 않는다.

5. Application 계약 변경

기존 request와 opaque reference를 유지한다. R2 provider가 달성한 보장을 정확히 보고할 수 있도록 FilePublishReceipt.DurabilityGuarantee에 다음 값만 추가한다.

FILE_AND_DIRECTORY_SYNC

이 값은 startup probe와 process-crash qualification을 모두 통과한 provider만 반환한다. 호출한 sync가 물리 device, volume replica 또는 storage-controller power-loss protection까지 완료됐다는 뜻은 아니다. 그 축은 deployment/storage evidence로 별도 판정한다. PROCESS_LOCAL_SYNC 또는 PROVIDER_ACK_ONLY를 요구 보장보다 약한 상태에서 자동으로 R2 값으로 올리지 않는다.

새 opaque reference 형식은 다음 의미를 가지되 application은 내부 segment를 해석하지 않는다.

fsr1.<route-token>.<file-id>.<check-digits>
  • route-token: destination binding의 canonical policy digest에서 재시작 안정적으로 파생한 bounded route allowlist 값. 형식은 r + digest의 첫 31 lowercase hex이며 startup에서 token collision을 거부한다;
  • file-id: CSPRNG 128-bit 이상;
  • check-digits: accidental truncation/corruption 검출;
  • provider locator, operation ID, tenant/user ID, host/path는 포함하지 않는다.

Reference는 authorization token이 아니다. authorization은 application use case의 책임이다.

6. 명시적 설정과 선택

새 canonical prefix는 app.fileserver다.

app:
  fileserver:
    enabled: false
    destinations:
      local-export:
        provider-ref: local-primary
        required-publication: unique-atomic-create
        required-durability: file-and-directory-sync
        maximum-rows: 1000000
        maximum-encoded-bytes: 1073741824
    providers:
      local-primary:
        type: local-persistent
        root-directory: ${APP_FILESERVER_LOCAL_ROOT:}
        auto-create: false
        strict-path-security: true
        expected-file-store-name: ${APP_FILESERVER_LOCAL_EXPECTED_FILE_STORE_NAME:}
        expected-file-store-type: ${APP_FILESERVER_LOCAL_EXPECTED_FILE_STORE_TYPE:}
        mount-sentinel-name: .ca-fileserver-volume
        mount-sentinel-sha256: ${APP_FILESERVER_LOCAL_MOUNT_SENTINEL_SHA256:}
        expected-owner: ${APP_FILESERVER_LOCAL_EXPECTED_OWNER:}
        maximum-root-mode: "0750"

규칙:

  • enabled=true이면 destination과 provider가 각각 하나 이상 필요하다.
  • 모든 destination은 존재하는 provider 하나를 참조한다.
  • provider ID별로 provider/control/payload runtime을 정확히 하나만 만들며 같은 provider를 참조하는 destination은 그 인스턴스를 공유한다. 서로 다른 provider ID가 같은 normalized root를 가리키면 동일 control namespace의 이중 소유가 되므로 startup에서 거부한다.
  • request destination에 binding이 없으면 producer 호출 전에 실패한다.
  • provider type의 기본값은 없다.
  • local-persistent root는 absolute, existing, pre-provisioned directory여야 한다.
  • auto-create=truelocal-persistent에서 거부한다.
  • root와 mount sentinel은 operator가 미리 만든다. Root attestation이 끝난 뒤 adapter가 private top-level control/data directory와 bounded hash shard를 restrictive POSIX creation mode로 생성할 수 있으며, 생성할 때마다 parent identity와 directory sync를 확인한다.
  • container ephemeral 경로를 위한 local-dev는 별도 후속 profile이다. production 설정과 같은 guarantee를 공유하지 않는다.
  • 기존 ca-skeleton.fileserver.*는 R1/legacy compatibility selector로만 남는다. 새 R2 설정과 동시에 활성화되면 어느 쪽 filesystem 초기화보다 먼저 startup을 실패시킨다. 양쪽 bean factory가 같은 ambiguity validator를 호출해 Spring bean 생성 순서에 의존하지 않으며, 암묵 migration이나 conditional precedence를 두지 않는다.
  • R2 settings는 unknown field를 거부해 provider/destination 키 오타를 silent fallback으로 취급하지 않는다.

7. Startup capability compilation

application traffic을 받기 전에 destination별 effective descriptor를 한 번 compile한다.

Descriptor compilation과 first reservation은 새 설정 키 없이 같은 canonical digest helper를 사용한다.

  • startup descriptor는 destination ID, provider ID, limits, required guarantees, format/encoder revision을 length-prefixed canonical encoding으로 직렬화한 effectivePolicyDigest를 freeze한다;
  • ordered schema ID/version/column contract를 같은 canonical encoding 규칙으로 계산하는 request별 schemaDigest는 first reservation에서 계산한다;
  • startup descriptor는 format/encoder revision과 canonical options의 formatPolicyDigest를 freeze한다;
  • r + effectivePolicyDigest의 첫 31 lowercase hex로 만든 32-character deterministic route token.

문자열 단순 연결이나 JVM/JSON map iteration order에 digest를 의존시키지 않는다. 같은 startup allowlist 안에서 route token이 충돌하면 더 긴 prefix로 임의 복구하지 않고 startup을 실패시킨다. 기존 operation은 journal에 freeze된 revision/digest/token으로만 복구하며 현재 설정으로 조용히 재해석하지 않는다.

local-persistent는 다음을 모두 검증한다.

  1. root와 모든 ancestor가 symbolic link가 아니다.
  2. root real path가 설정 absolute path와 일치한다.
  3. configured owner와 실제 owner가 일치한다.
  4. POSIX permission이 configured maximum보다 넓지 않고 group/world writable이 아니다.
  5. FileStore.name()type()이 설정 값과 일치한다.
  6. mount sentinel이 regular no-follow file이고 configured SHA-256와 일치한다.
  7. data, staging, operations, manifests, references, quarantine directory가 같은 FileStore에 있다.
  8. control directory는 private owner boundary이며 symlink가 아니다.
  9. SecureDirectoryStream을 열 수 있다.
  10. exclusive create, file force, hard-link create, directory force가 private probe directory에서 성공한다.

Probe artifact는 unique name만 사용하며 successful cleanup과 parent directory force까지 완료해야 한다. Probe 실패는 capability downgrade가 아니라 startup failure다.

JDK가 directory-relative hard-link primitive를 제공하지 않으므로 hard-link publish는 다음 boundary에서만 허용한다.

  • root/control/data directories가 adapter owner 전용이고 untrusted writer가 없음;
  • publish 직전과 직후 root identity, directory file key, mount sentinel을 다시 확인;
  • target은 CSPRNG unique name;
  • pre/post identity가 바뀌면 성공을 반환하지 않고 PUBLISH_INDETERMINATE;
  • privileged host administrator 또는 same-owner malicious process와의 경쟁은 guarantee 범위가 아니며 deployment isolation requirement로 기록한다.

untrusted writer가 같은 root에 entry를 만들 수 있는 환경은 strict local R2가 아니다.

8. Durable control plane

.ca-fileserver/
  operations/<prefix>/<operation-id>.json
  manifests/<prefix>/<file-id>.json
  references/<prefix>/<file-id>.json
  staging/<prefix>/<operation-id>.part
  quarantine/
  probe/
data/<prefix>/<generated-file-name>

모든 locator는 validated single segment 또는 adapter가 생성한 bounded relative segment다. Caller path를 받지 않는다. Manifest/reference의 internalLocator는 generated filename 한 segment만 저장하고, data shard는 fileId의 첫 두 hex에서 파생한다. 따라서 실제 lookup은 data/<file-id-prefix>/<internalLocator>이며 control record에 slash를 저장하지 않는다.

8.1 Operation journal v2

필수 필드:

schemaVersion
stateRevision
state
operationId
requestFingerprint
effectivePolicyRevision
effectivePolicyDigest
destinationId
providerId
fileId
routeToken
publishedFileName
stageFileName
byteSize
rowCount
columnCount
sha256
formulaMitigatedCount
manifestDigest
referenceDigest
createdAt
sealedAt
publishedAt
lastFailureCode
receiptSnapshot

State는 WRITING, SEALED, DATA_PUBLISHED, MANIFEST_PUBLISHED, REFERENCE_PUBLISHED, PUBLISHED, QUARANTINED다.

8.2 Private manifest v1

Manifest는 operation/file/provider/reference/fingerprint, schema·format·policy digest, byte/count, SHA-256, achieved guarantees, internal relative locator를 기록한다. Absolute path, raw row/cell, credential, raw tenant/user ID는 저장하지 않는다.

8.3 Reference index v1

Reference index는 opaque file-id에서 operation ID, file version, manifest digest와 internal relative locator로 direct lookup한다. Directory scan은 receipt restoration의 authority가 아니다.

8.4 Record update

각 control record는:

  1. sibling private temp file을 CREATE_NEW;
  2. bounded canonical JSON encoding;
  3. file force(true);
  4. same-directory atomic replace;
  5. parent directory force;
  6. read-back schema/revision/digest verification;

순서로 갱신한다. 낮은 revision, fingerprint mismatch, newer schema는 자동 덮어쓰지 않는다.

Operation schema v2는 별도 formatPolicyDigest snapshot을 저장하지 않으므로 recovery는 저장된 effectivePolicyRevisioneffectivePolicyDigest가 현재 compiled destination과 정확히 같을 때만 현재 format-policy digest를 사용한다. Encoder/policy 변경으로 digest가 달라지면 과거 format을 추정하지 않고 indeterminate로 중단한다. 여러 format revision에 대한 forward recovery는 non-secret policy snapshot을 포함하는 후속 operation schema에서만 지원한다.

Operation direct lookup은 같은 secure relative read에서 schema를 typed dispatch한다. Schema v2는 현재 R2 record로만 decode/write하고, schema v1은 strict UTF-8 decode 후 canonical v1 re-encode byte equality를 만족하는 terminal compatibility record만 read-only로 반환한다. Unknown/newer schema, malformed UTF-8, non-canonical v1은 absent로 취급하지 않는다.

Crash qualification을 위해 control-plane fault context는 package-private로 record kind, record identity, 해당하는 경우 operation state/revision, force boundary를 함께 전달한다. Production 기본 callback은 no-op이며 runtime 설정이나 public bean으로 노출하지 않는다.

9. Publication ordering

J-WRITING
  -> stage stream/force
J-SEALED
  -> exclusive hard-link data publish
  -> data directory force
J-DATA_PUBLISHED
  -> private manifest publish/force
J-MANIFEST_PUBLISHED
  -> reference index publish/force
J-REFERENCE_PUBLISHED
  -> terminal journal + receipt snapshot publish/force
J-PUBLISHED
  -> receipt return
  • Producer는 accepted attempt에서 최대 한 번 호출한다.
  • SEALED 이후 retry/recovery는 staged bytes만 사용한다.
  • terminal journal force 전에는 receipt를 반환하지 않는다.
  • target collision, digest mismatch 또는 root identity change는 자동 overwrite하지 않는다.
  • final data가 있어도 manifest/reference가 없으면 아직 terminal success가 아니다.
  • staging/data shard 생성, stage force, stable no-follow read/digest, exact delete는 package-private PayloadOperations를 통해 SecureDirectoryStream 상대 연산으로 수행한다. Portable relative primitive가 없는 hard-link와 directory force만 private-owner boundary 안에서 root/directory/file identity pre/post 검증으로 감싼다.
  • hard-link 뒤 journal 갱신 전에 중단된 SEALED + matching data 복구는 기존 data shard를 다시 identity 검증하고 directory force한 뒤에만 DATA_PUBLISHED로 전이한다. 이미 존재하는 data를 overwrite-capable publication 경로에 다시 넣지 않는다.
  • WRITING 저장 뒤 producer 또는 stage/write가 실패하면 partial stage를 exact cleanup하고 unsealed QUARANTINED evidence를 남긴다. 원래 producer exception은 보존하고 cleanup/control failure는 suppressed로 연결한다. Retry 진입 시 기존 WRITING 또는 unsealed QUARANTINED가 보이면 producer를 다시 호출하지 않고 indeterminate/quarantine으로 fail-closed한다.

10. Deterministic recovery

Recovery는 operation ID direct lookup으로 실행하며 startup full scan에 의존하지 않는다.

확인된 상태 조치
terminal journal + matching manifest/reference/data 저장된 receipt 복원
SEALED + valid stage, data 없음 data publication부터 재개
SEALED + matching data manifest publication부터 재개
DATA_PUBLISHED + matching data manifest publication 재개
MANIFEST_PUBLISHED + matching manifest/data reference publication 재개
REFERENCE_PUBLISHED + all matching terminal journal 완성
non-terminal data/manifest/reference digest mismatch QUARANTINED, integrity failure
PUBLISHED artifact/metadata/receipt mismatch terminal journal과 artifacts를 불변 보존하고 typed integrity/indeterminate
required manifest/reference/data 누락 성공 복원 금지, fail-closed indeterminate/quarantine
marker/manifest/reference schema newer 보존 후 fail-fast/quarantine
fingerprint conflict typed conflict, 기존 artifact 보존
root/mount identity change indeterminate, write/recovery 중단

Truth priority:

matching data + private manifest + reference
  > terminal operation record
  > non-terminal operation record
  > in-memory state

모순이 있으면 임의 성공이나 삭제를 하지 않는다. Non-terminal operation은 기존 operation journal을 QUARANTINED로 전이할 수 있다. 이미 PUBLISHED인 operation은 terminal receipt snapshot을 지우거나 journal을 덮지 않고 관련 data/manifest/reference도 보존한 채 typed integrity/indeterminate로 실패한다. 별도 immutable quarantine incident record는 후속 설계 전까지 가정하지 않는다.

Recovery verifier는 operation, incoming request, data, manifest, reference, receipt snapshot의 identity/digest/locator/count/time/guarantee를 모두 교차검증한다. Terminal receipt는 verified manifest/reference에서 재구성한 expected receipt와 전체 equality가 확인될 때만 반환한다. Operation record의 일부 필드만 맞거나 durability/publication guarantee, file version, format/media/charset가 다르면 terminal success가 아니다. Crash 뒤 먼저 발견한 immutable manifest/reference의 verified publishedAt은 새 clock 값으로 덮지 않고 recovery context로 재사용한다. 새 attempt에만 현재 configured maximum을 적용하고, sealed recovery artifact는 operation에 freeze된 exact byte size로 bounded inspection한다. Stage와 data가 함께 있으면 digest equality만이 아니라 stable file key가 같은 hard-link인지 확인한 뒤에만 stage를 exact-delete한다.

11. Compatibility

  • R1 compatibility는 별도 미설정 root나 동시에 활성화된 legacy bean이 아니다. Operator가 기존 R1 root를 owner/mode/FileStore/sentinel 등 R2 attestation 조건에 맞춰 명시적으로 pre-provision한 뒤, 그 root를 R2 destination으로 전환하는 in-place read-only migration이다.
  • R1과 R2 operation journal은 같은 hashed path를 사용하므로 secure relative typed schema dispatch로 schema v1을 읽고 schema v2만 쓴다.
  • R1 journal schema v1은 strict UTF-8와 canonical re-encode byte equality를 만족하는 terminal record만 읽을 수 있어야 한다.
  • R1 terminal receipt는 기존 PROCESS_LOCAL_SYNC 보장 그대로 복원한다.
  • R1 root-level artifact도 attested root의 SecureDirectoryStream 상대 no-follow bounded streaming inspection으로 journal의 byte size와 SHA-256을 확인한 뒤에만 receipt를 복원한다.
  • R1 artifact를 자동으로 R2 manifest/reference로 승격하지 않는다.
  • R2 writer는 journal v2만 생성한다.
  • 기존 overwrite-capable legacy port는 별도 root와 opt-in을 유지하며 R2 control plane에 접근하지 않는다.
  • R1과 R2 selector가 동시에 활성화되면 ambiguous composition으로 startup을 실패시킨다.

12. Failure semantics

  • 설정/보장 mismatch: startup failure;
  • destination 없음: producer 전 deterministic request failure;
  • stage 이전 capacity/validation failure: not applied;
  • stage/write failure: failed, partial stage는 recovery evidence가 아니면 exact cleanup하고 unsealed QUARANTINED로 producer replay를 차단;
  • sealed 이후 filesystem timeout/IO/root identity change: indeterminate;
  • non-terminal published data와 metadata 불일치: integrity/quarantine;
  • terminal PUBLISHED data/metadata/receipt 불일치: terminal evidence 불변 보존 후 typed integrity/indeterminate;
  • journal/control record corruption: provider exception을 노출하지 않고 typed indeterminate;
  • guarantee를 낮춰 성공시키는 fallback은 없다.

13. 테스트와 증거

13.1 Unit/contract

  • exact destination/provider selection과 no-default;
  • R1/R2 simultaneous activation rejection;
  • reference grammar/check digits/forged route rejection;
  • journal v2, manifest, reference canonical round-trip;
  • deterministic route token collision rejection과 canonical policy/schema/format digest;
  • same operation path의 strict canonical R1 read-only/v2 write-only typed dispatch;
  • state revision과 fingerprint conflict;
  • achieved durability value invariants.

13.2 Local integration

  • pre-provisioned root requirement;
  • owner/mode/FileStore/sentinel mismatch startup failure;
  • symlink ancestor/control/data rejection;
  • staging/final/control same FileStore;
  • successful capability probe와 cleanup;
  • partial final visibility 0건;
  • same operation concurrency와 producer once;
  • unsealed WRITING failure quarantine와 retry producer 0회;
  • target collision no overwrite;
  • non-terminal data/manifest/reference digest mismatch quarantine;
  • terminal mismatch의 PUBLISHED journal/artifact 불변 보존과 typed integrity/indeterminate.

13.3 Crash qualification

Forked JVM helper를 사용해 다음 force boundary 직후 process를 강제 종료하고 새 JVM에서 같은 operation을 재시도한다.

J-WRITING
stage force
J-SEALED
data link
data directory force
manifest force
manifest directory force
reference force
reference directory force
terminal journal force
terminal journal directory force

각 boundary에서 결과는 다음 중 하나여야 한다.

  • producer 재실행 없이 동일 receipt 복원;
  • verified sealed bytes로 publication 완성;
  • typed indeterminate/quarantine.

partial final, overwrite, 다른 receipt, silent guarantee downgrade는 허용하지 않는다.

같은 attested root와 operation ID에 대해 process A가 OS operation lock을 보유하는 동안 forked process B의 bounded non-blocking/timed acquire가 critical section에 진입하지 못하고, A의 release 또는 강제 종료 뒤 B가 획득하는지도 별도로 증명한다. 이 증거는 동일 JVM stripe 테스트로 대체하지 않는다.

13.4 플랫폼

  • Linux/POSIX + SecureDirectoryStream + directory force qualification lane에서만 FILE_AND_DIRECTORY_SYNC을 검증한다.
  • capability가 없는 일반 unit-test filesystem에서는 R1 보장만 테스트하며 R2 service test를 skip 성공으로 처리하지 않는다.

14. 완료 기준

이번 increment의 완료는 “Fileserver 전체가 모든 운영환경에서 R2”라는 뜻이 아니다.

완료를 주장하려면:

  1. provider 기본값 없이 exact binding이 동작한다.
  2. local-persistent startup probe가 모든 required capability를 증명한다.
  3. terminal manifest/reference direct lookup이 구현된다.
  4. 모든 publication force boundary의 crash test가 deterministic result를 낸다.
  5. strict path/mount identity/security tests가 통과한다.
  6. public path와 clean architecture gate가 통과한다.
  7. R1 compatibility artifact를 R2로 자동 승격하지 않는다.
  8. 문서와 receipt는 local-persistent qualification만 R2라고 표시한다.

후속 순서는 Phase 3 maintenance/resource limits, Phase 4 SFTP, Phase 5 shared-mounted/NFS evidence다.

15. 구현 및 readiness 판정

2026-07-28 구현은 다음 경계를 만족한다.

  • application에는 provider/path/framework 타입이 없는 FilePublicationPort만 유지한다.
  • adapter 내부의 canonical operation/manifest/reference model, opaque reference, provider SPI, exact destination router는 provider-neutral control/selection boundary로 구현되었다.
  • app.fileserver.enabled는 disabled-default이며, enable 시 destination/provider를 exact compile한다. Unknown destination은 producer 호출 전에 실패하고 implicit local fallback은 없다.
  • 같은 provider ID를 참조하는 destination은 하나의 provider/control/payload runtime을 공유한다. 서로 다른 provider ID가 같은 normalized root를 소유하면 startup에서 실패한다.
  • R2 provider는 local-persistent 하나만 구현·qualification한다. Absolute/existing pre-provisioned root와 owner/mode/FileStore/sentinel/path/capability attestation이 모두 성공해야 bean이 구성된다.
  • operation v2, private manifest, direct reference index, ordered force publication과 deterministic recovery를 구현했다. Forked-process qualification은 각 force boundary와 OS operation lock을 대상으로 하며, focused/module/full gate 결과와 함께 완료 증거를 판정한다.
  • 기존 schema-v1 terminal record와 root-level R1 artifact는 strict UTF-8/canonical/direct read-only compatibility다. 원래 PROCESS_LOCAL_SYNC receipt만 복원하며 schema-v2 rewrite, manifest/reference 생성, FILE_AND_DIRECTORY_SYNC 자동 승격을 하지 않는다.

FILE_AND_DIRECTORY_SYNC는 attested local filesystem protocol에서 file과 관련 directory force가 성공했다는 의미다. Physical device, volatile storage-controller cache, volume replica, backup 또는 site 단위 power-loss protection을 주장하지 않는다. 그 보장은 Fileserver 코드가 아니라 선택한 storage/deployment의 별도 evidence가 필요하다.

다음 capability는 구현되지 않았고 setting/env/bean으로 노출하지 않는다.

  • shared-mounted/NFS multi-client correctness와 cross-node producer fencing;
  • SFTP SDK, connection/session pool, host-key/credential, remote reconciliation;
  • background reconcile/reaper, managed retention/delete;
  • quota reservation, backpressure, capacity admission;
  • Fileserver 전용 readiness/health, metrics, tracing, audit.

따라서 이 increment의 운영 claim은 “모든 Fileserver topology가 R2”가 아니라 “strictly attested local-persistent profile만 R2”다.