Sub-scope 05 (fileserver) platform/local failure·probe·health·orphan + verification + security + audit
revision=a24ece9cf797f7ea647e33bf846b115208ed1ba5
generatedAt=2026-08-30T01:27:59+00:00

=== OWNED FILES (24 main + 5 test) ===
9e61e441e81fd868a99c09b8afd1c4fa9a9e9172 platform/local/FilesystemFailureClassifier.java 51
67318269844b61a021bf3ed964ffb92b0abe7b30 platform/local/FilesystemOutcome.java 23
62e9aac34c4ae1696ac86c36b7caed19380ac075 platform/local/AmbiguousFilesystemOperationDetector.java 91
04b3b101d17e0b2d4148219c24466d1a1a27e797 platform/local/LocalStorageFailures.java 48
53e89c47a91b09940d297ea204b1a76fd70f9af7 platform/local/LocalStorageCapabilityProbe.java 302
7b803247f076a9bc79ec2fa084c6bac3b0e580f5 platform/local/LocalStorageProbeResult.java 53
ee5121e14abe0da88103aa3e713954c52a8c7b14 platform/local/LocalStorageHealthAdapter.java 70
636b22ca38c666258c5888a667234d20e4212cce platform/local/LocalStorageUsageProbe.java 46
527677720cbc2381fb41fd3b50c61285d25d5bfd platform/local/LocalReconciliationContentProbe.java 84
2bc58d8cd0dd9c54dbf756cbf832c05a1c04efff platform/local/LocalOrphanScanAdapter.java 239
cae4bf09a9d405aa927e4442007ca778aa1aa8a6 platform/verification/FilenamePolicyVerifier.java 38
30fc5c76d7c0f2ab45df7f6f4297566a5c4166f3 platform/verification/LengthVerifier.java 41
d24d5bc45303f4cd062266af4cf3d32b4eecc320 platform/verification/LocalVerificationContentReader.java 68
995e30a163712f4afc85e0f6ceb1a89470cf890a platform/verification/MediaTypeVerifier.java 108
3e2a1958457d413e71e581d2a2057fc53a004eae platform/verification/Sha256Verifier.java 32
ff6d5cdf0f6379464f4dc43c3c53d035fdab1bc6 platform/verification/ScriptableContentPolicy.java 57
6b592a50a5e46d8f110100248fef5e360295e692 platform/verification/VerificationContentReader.java 16
84602304e188c7942841d193650872e8b8c34246 platform/verification/VerificationCoordinator.java 67
0aec00fdd700990879833c03f48a653daad5a587 platform/verification/VerificationPolicyCombiner.java 43
3739210eadfbd16afede10a169a60bd1ffe5885d platform/verification/VerificationVerdictPrecedence.java 11
815473a43331d452ecc23ae7ed10b1a08bece58c platform/security/RoleBasedFileAccessPolicy.java 98
3f4c47032cea3783ec230e834d1ca385c71d74df platform/security/UnenforcedFileAccessPolicy.java 27
afec1144e343f5817ebb1e848770032ebf420c42 platform/audit/StructuredAdminAuditAdapter.java 35
4e9094c7a1a194345bae9f9208ed9f6aa05aa256 platform/audit/StructuredFileserverAuditAdapter.java 30

=== 8.1 resolving the sub-scope 01 forward reference: are these real implementations? ===
$ grep -n 'implements ' adapter/outbound/fileserver/src/main/java/dev/caskeleton/adapter/outbound/fileserver/platform/audit/*.java adapter/outbound/fileserver/src/main/java/dev/caskeleton/adapter/outbound/fileserver/platform/security/*.java adapter/outbound/fileserver/src/main/java/dev/caskeleton/adapter/outbound/fileserver/platform/local/LocalStorageHealthAdapter.java adapter/outbound/fileserver/src/main/java/dev/caskeleton/adapter/outbound/fileserver/platform/local/LocalStorageUsageProbe.java adapter/outbound/fileserver/src/main/java/dev/caskeleton/adapter/outbound/fileserver/platform/local/LocalOrphanScanAdapter.java adapter/outbound/fileserver/src/main/java/dev/caskeleton/adapter/outbound/fileserver/platform/local/LocalReconciliationContentProbe.java
adapter/outbound/fileserver/src/main/java/dev/caskeleton/adapter/outbound/fileserver/platform/audit/StructuredAdminAuditAdapter.java:19:public final class StructuredAdminAuditAdapter implements AdminAuditPort {
adapter/outbound/fileserver/src/main/java/dev/caskeleton/adapter/outbound/fileserver/platform/audit/StructuredFileserverAuditAdapter.java:15:public final class StructuredFileserverAuditAdapter implements FileserverAuditPort {
adapter/outbound/fileserver/src/main/java/dev/caskeleton/adapter/outbound/fileserver/platform/security/RoleBasedFileAccessPolicy.java:27:public final class RoleBasedFileAccessPolicy implements FileAccessPolicy {
adapter/outbound/fileserver/src/main/java/dev/caskeleton/adapter/outbound/fileserver/platform/security/UnenforcedFileAccessPolicy.java:20:public final class UnenforcedFileAccessPolicy implements FileAccessPolicy {
adapter/outbound/fileserver/src/main/java/dev/caskeleton/adapter/outbound/fileserver/platform/local/LocalStorageHealthAdapter.java:24:public final class LocalStorageHealthAdapter implements StorageHealthPort {
adapter/outbound/fileserver/src/main/java/dev/caskeleton/adapter/outbound/fileserver/platform/local/LocalStorageUsageProbe.java:21:public final class LocalStorageUsageProbe implements StorageUsageProbe {
adapter/outbound/fileserver/src/main/java/dev/caskeleton/adapter/outbound/fileserver/platform/local/LocalOrphanScanAdapter.java:45:public final class LocalOrphanScanAdapter implements OrphanScanPort {
adapter/outbound/fileserver/src/main/java/dev/caskeleton/adapter/outbound/fileserver/platform/local/LocalReconciliationContentProbe.java:22:public final class LocalReconciliationContentProbe implements ReconciliationContentProbe {
exit=0

$ git grep -rn 'new StructuredAdminAuditAdapter\|new StructuredFileserverAuditAdapter\|new LocalStorageHealthAdapter\|new LocalStorageUsageProbe\|new LocalOrphanScanAdapter\|new LocalReconciliationContentProbe\|new RoleBasedFileAccessPolicy\|new UnenforcedFileAccessPolicy' -- app-bootstrap/src/main
app-bootstrap/src/main/java/dev/caskeleton/bootstrap/autoconfigure/fileserver/FileserverSecurityConfiguration.java:51:          new RoleBasedFileAccessPolicy(
app-bootstrap/src/main/java/dev/caskeleton/bootstrap/autoconfigure/fileserver/FileserverSecurityConfiguration.java:71:    return new StructuredAdminAuditAdapter();
app-bootstrap/src/main/java/dev/caskeleton/bootstrap/autoconfigure/fileserver/FileserverSecurityConfiguration.java:77:    return new StructuredFileserverAuditAdapter();
app-bootstrap/src/main/java/dev/caskeleton/bootstrap/autoconfigure/fileserver/FileserverSecurityConfiguration.java:90:    return new UnenforcedFileAccessPolicy();
app-bootstrap/src/main/java/dev/caskeleton/bootstrap/autoconfigure/fileserver/FileserverStorageConfiguration.java:179:    return new LocalStorageHealthAdapter(properties, probeResult, store);
app-bootstrap/src/main/java/dev/caskeleton/bootstrap/autoconfigure/fileserver/FileserverStorageConfiguration.java:189:    return new LocalOrphanScanAdapter(
app-bootstrap/src/main/java/dev/caskeleton/bootstrap/autoconfigure/fileserver/FileserverStorageConfiguration.java:196:    return new LocalStorageUsageProbe(properties.root());
app-bootstrap/src/main/java/dev/caskeleton/bootstrap/autoconfigure/fileserver/FileserverStorageConfiguration.java:203:    return new LocalReconciliationContentProbe(store, stagingLocator);
exit=0

$ grep -rn 'not implemented' adapter/outbound/fileserver/README.md
103:`shared-mounted`/NFS and SFTP providers are not implemented. Cross-node producer fencing,
105:tracing, and audit are also not implemented. No setting or bean for those capabilities is exposed.
exit=0

=== 8.2 the scriptable-content marker: anchored at the prefix start ===
$ grep -n 'SCRIPTABLE_MARKERS\|stripLeading\|startsWith' -B 2 -A 2 adapter/outbound/fileserver/src/main/java/dev/caskeleton/adapter/outbound/fileserver/platform/verification/ScriptableContentPolicy.java
21-  private static final int PREFIX_BYTES = 1024;
22-
23:  private static final List<String> SCRIPTABLE_MARKERS =
24-      List.of("<!doctype html", "<html", "<script", "<svg", "<?xml", "<!entity");
25-
--
42-    byte[] prefix = contentReader.readPrefix(request, PREFIX_BYTES);
43-    String text =
44:        new String(prefix, StandardCharsets.UTF_8).toLowerCase(Locale.ROOT).stripLeading();
45:    boolean scriptable = SCRIPTABLE_MARKERS.stream().anyMatch(text::startsWith);
46-
47-    if (!scriptable) {
exit=0

$ grep -n 'Detection is on content' -A 3 adapter/outbound/fileserver/src/main/java/dev/caskeleton/adapter/outbound/fileserver/platform/verification/ScriptableContentPolicy.java
15: * <p>Detection is on content, not on the claimed type or the extension, because both are attacker
16- * controlled. Unless an explicit safe profile is enabled, scriptable content is quarantined rather
17- * than published.
18- */
exit=0

=== EXECUTION PROBE: what ScriptableContentPolicy actually quarantines ===
One temporary test class was added, run, and removed:
  src/test/.../platform/verification/Ss05ScriptableProbe.java
inlineSafeProfile=false (the enforcing profile); the reader returns each candidate verbatim.

PROBE plain <script>                 -> QUARANTINE / SCRIPTABLE_CONTENT
PROBE plain <html>                   -> QUARANTINE / SCRIPTABLE_CONTENT
PROBE leading whitespace + <html>    -> QUARANTINE / SCRIPTABLE_CONTENT
PROBE UTF-8 BOM + <html>             -> ACCEPT / NO_SCRIPTABLE_CONTENT
PROBE HTML comment then <script>     -> ACCEPT / NO_SCRIPTABLE_CONTENT
PROBE uppercase <SCRIPT>             -> QUARANTINE / SCRIPTABLE_CONTENT
PROBE <svg onload>                   -> QUARANTINE / SCRIPTABLE_CONTENT
PROBE NUL byte then <html>           -> ACCEPT / NO_SCRIPTABLE_CONTENT
PROBE plain text                     -> ACCEPT / NO_SCRIPTABLE_CONTENT

Reading: the check is text.stripLeading().startsWith(marker). String.stripLeading removes
only Character.isWhitespace, so a UTF-8 BOM (U+FEFF) or a NUL byte before the markup
defeats it, and any leading HTML comment does too. A browser renders all three as HTML.

=== 8.2b the sibling verifier decides on content the same way; does it anchor? ===
$ grep -n 'signature.matches(prefix)\|prefix\[index\]' -B 2 -A 2 adapter/outbound/fileserver/src/main/java/dev/caskeleton/adapter/outbound/fileserver/platform/verification/MediaTypeVerifier.java
70-  private static Optional<String> detect(byte[] prefix) {
71-    for (Signature signature : SIGNATURES) {
72:      if (signature.matches(prefix)) {
73-        return Optional.of(signature.mediaType());
74-      }
--
99-      }
100-      for (int index = 0; index < magic.size(); index++) {
101:        if ((prefix[index] & 0xFF) != magic.get(index)) {
102-          return false;
103-        }
exit=0

=== 8.3 fail-closed composition around the verifiers ===
$ grep -n 'VERIFIER_TIMEOUT\|VERIFIER_UNAVAILABLE\|VERIFIER_INTERRUPTED\|NO_VERIFIER_ANSWERED' adapter/outbound/fileserver/src/main/java/dev/caskeleton/adapter/outbound/fileserver/platform/verification/VerificationCoordinator.java adapter/outbound/fileserver/src/main/java/dev/caskeleton/adapter/outbound/fileserver/platform/verification/VerificationPolicyCombiner.java
adapter/outbound/fileserver/src/main/java/dev/caskeleton/adapter/outbound/fileserver/platform/verification/VerificationCoordinator.java:59:      return VerificationResult.retry("VERIFIER_TIMEOUT");
adapter/outbound/fileserver/src/main/java/dev/caskeleton/adapter/outbound/fileserver/platform/verification/VerificationCoordinator.java:62:      return VerificationResult.retry("VERIFIER_INTERRUPTED");
adapter/outbound/fileserver/src/main/java/dev/caskeleton/adapter/outbound/fileserver/platform/verification/VerificationCoordinator.java:64:      return VerificationResult.retry("VERIFIER_UNAVAILABLE");
adapter/outbound/fileserver/src/main/java/dev/caskeleton/adapter/outbound/fileserver/platform/verification/VerificationPolicyCombiner.java:21:      return VerificationResult.retry("NO_VERIFIER_ANSWERED");
exit=0

$ grep -n 'REJECT > QUARANTINE > RETRY > ACCEPT' -B 2 -A 2 adapter/outbound/fileserver/src/main/java/dev/caskeleton/adapter/outbound/fileserver/platform/verification/VerificationPolicyCombiner.java
9- * Reduces per-verifier answers to one verdict.
10- *
11: * <p>Precedence is {@code REJECT > QUARANTINE > RETRY > ACCEPT}. Because {@code RETRY} outranks
12- * {@code ACCEPT}, a scanner that timed out can never be silently overridden by the verifiers that
13- * did answer.
exit=0

=== 8.4 message hygiene: does any failure or audit line carry a path? ===
$ grep -rn 'exception.getMessage()\|root\b' adapter/outbound/fileserver/src/main/java/dev/caskeleton/adapter/outbound/fileserver/platform/local/LocalStorageFailures.java
16: * <p>No message carries a path, a mount, or a storage root: transports map on the error code alone.
exit=0

$ grep -rn 'record.subjectId()\|actorFingerprint' adapter/outbound/fileserver/src/main/java/dev/caskeleton/adapter/outbound/fileserver/platform/audit/*.java
adapter/outbound/fileserver/src/main/java/dev/caskeleton/adapter/outbound/fileserver/platform/audit/StructuredAdminAuditAdapter.java:30:        record.actorFingerprint(),
adapter/outbound/fileserver/src/main/java/dev/caskeleton/adapter/outbound/fileserver/platform/audit/StructuredAdminAuditAdapter.java:31:        record.subjectId(),
adapter/outbound/fileserver/src/main/java/dev/caskeleton/adapter/outbound/fileserver/platform/audit/StructuredFileserverAuditAdapter.java:26:        event.actorFingerprint(),
exit=0

$ grep -n 'names neither the required role' -A 3 adapter/outbound/fileserver/src/main/java/dev/caskeleton/adapter/outbound/fileserver/platform/security/RoleBasedFileAccessPolicy.java
86:   * <p>The message names neither the required role nor the subject's roles: a denial that reported
87-   * what was missing would turn every 403 into a readable description of the role model.
88-   */
89-  private static FileAccessDeniedException denied(FileserverErrorCode code, String message) {
exit=0

$ git status --short | wc -l
0
exit=0

