localhost1978's picture
download
raw
19.1 kB
import Foundation
import Testing
@testable import SSK_DocGen
#if canImport(Darwin)
import Darwin
#endif
@Suite("ACP resource reads")
struct ACPResourceReadTests {
@Test("An allowlisted resource returns bounded and redacted content")
func allowlistedResourceIsRead() async throws {
let workspace = try makeTemporaryDirectory()
defer { try? FileManager.default.removeItem(at: workspace) }
let context = try ACPRequestContext(workspaceURL: workspace)
let reader = RecordingResourceReader(contents: [
.doccIndex: "{\"file\":\"/private/example/Secret.swift\"}"
])
let service = ACPService(context: context, resourceReader: reader)
let response = try await decodedResponse(
service,
line: "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"resources/read\",\"params\":{\"uri\":\"file:///SSK_Ledger_Vault/docc_index.json\"}}"
)
let result = try #require(response["result"] as? [String: Any])
let contents = try #require(result["contents"] as? [[String: Any]])
let resource = try #require(contents.first)
let text = try #require(resource["text"] as? String)
#expect(resource["mimeType"] as? String == "application/json")
#expect(!text.contains("/private/example/Secret.swift"))
#expect(text.contains("<redacted-path>"))
let readCount = await reader.readCount()
#expect(readCount == 1)
}
@Test("An unknown resource is rejected before any read")
func unknownResourceIsRejectedBeforeRead() async throws {
let workspace = try makeTemporaryDirectory()
defer { try? FileManager.default.removeItem(at: workspace) }
let context = try ACPRequestContext(workspaceURL: workspace)
let reader = RecordingResourceReader(contents: [:])
let service = ACPService(context: context, resourceReader: reader)
let response = try await decodedResponse(
service,
line: "{\"jsonrpc\":\"2.0\",\"id\":2,\"method\":\"resources/read\",\"params\":{\"uri\":\"file:///SSK_Ledger_Vault/other.json\"}}"
)
let error = try #require(response["error"] as? [String: Any])
#expect(error["code"] as? Int == -32004)
let readCount = await reader.readCount()
#expect(readCount == 0)
}
@Test("A missing approved resource returns typed not-found behavior")
func missingResourceReturnsNotFound() async throws {
let workspace = try makeTemporaryDirectory()
defer { try? FileManager.default.removeItem(at: workspace) }
let context = try ACPRequestContext(workspaceURL: workspace)
let service = ACPService(context: context, resourceReader: RecordingResourceReader(contents: [:]))
let response = try await decodedResponse(
service,
line: "{\"jsonrpc\":\"2.0\",\"id\":3,\"method\":\"resources/read\",\"params\":{\"uri\":\"file:///SSK_Ledger_Vault/graph.json\"}}"
)
let error = try #require(response["error"] as? [String: Any])
#expect(error["code"] as? Int == -32004)
}
@Test("A server without a vault stays available and reports the resource as unavailable")
func serverWithoutVaultStaysAvailable() async throws {
let workspace = try makeTemporaryDirectory()
defer { try? FileManager.default.removeItem(at: workspace) }
let context = try ACPRequestContext(workspaceURL: workspace)
let service = ACPService(context: context, resourceReader: ACPUnavailableResourceReader())
let response = try await decodedResponse(
service,
line: "{\"jsonrpc\":\"2.0\",\"id\":4,\"method\":\"resources/read\",\"params\":{\"uri\":\"file:///SSK_Ledger_Vault/graph.json\"}}"
)
let error = try #require(response["error"] as? [String: Any])
#expect(error["code"] as? Int == -32003)
}
@Test("The current DocC index size is below its P0 limit")
func currentIndexSizeIsAccepted() async throws {
let fixture = try ResourceFixture()
defer { fixture.remove() }
try fixture.write(byteCount: 1_456_000, to: "docc_index.json", json: true)
let content = try await fixture.reader().read(fixture.resource(.doccIndex))
#expect(content.utf8.count == 1_456_000)
}
@Test("Each approved resource accepts its exact byte limit", arguments: [
(ACPResourceHandler.doccIndex, "docc_index.json", 2 * 1024 * 1024),
(ACPResourceHandler.codebaseGraph, "graph.json", 256 * 1024),
(ACPResourceHandler.masterMarkdownIndex, "DocC_Index.md", 256 * 1024),
(ACPResourceHandler.refreshStatus, "refresh_status.json", 64 * 1024),
])
func exactPerResourceLimitsAreAccepted(
handler: ACPResourceHandler,
leafName: String,
limit: Int
) async throws {
let fixture = try ResourceFixture()
defer { fixture.remove() }
try fixture.write(
byteCount: limit,
to: leafName,
json: handler != .masterMarkdownIndex
)
let content = try await fixture.reader().read(fixture.resource(handler))
#expect(content.utf8.count == limit)
}
@Test("Each approved resource enforces its own byte limit", arguments: [
(ACPResourceHandler.doccIndex, "docc_index.json", 2 * 1024 * 1024),
(ACPResourceHandler.codebaseGraph, "graph.json", 256 * 1024),
(ACPResourceHandler.masterMarkdownIndex, "DocC_Index.md", 256 * 1024),
(ACPResourceHandler.refreshStatus, "refresh_status.json", 64 * 1024),
])
func perResourceLimitsAreEnforced(
handler: ACPResourceHandler,
leafName: String,
limit: Int
) async throws {
let fixture = try ResourceFixture()
defer { fixture.remove() }
try fixture.write(
byteCount: limit + 1,
to: leafName,
json: handler != .masterMarkdownIndex
)
let reader = try fixture.reader()
await #expect(throws: ACPResourceReadError.resourceTooLarge) {
try await reader.read(fixture.resource(handler))
}
}
@Test("A missing physical resource returns the typed not-found error")
func missingPhysicalResourceIsRejected() async throws {
let fixture = try ResourceFixture()
defer { fixture.remove() }
let reader = try fixture.reader()
await #expect(throws: ACPResourceReadError.resourceNotFound) {
try await reader.read(fixture.resource(.codebaseGraph))
}
}
@Test("Registration metadata cannot change the fixed resource mapping")
func mismatchedRegistrationIsRejected() async throws {
let fixture = try ResourceFixture()
defer { fixture.remove() }
let resource = ACPResourceRegistration(
uri: "file:///SSK_Ledger_Vault/docc_index.json",
name: "DocC Index",
mimeType: "text/plain",
handler: .doccIndex
)
let reader = try fixture.reader()
await #expect(throws: ACPResourceReadError.unreadableResource) {
try await reader.read(resource)
}
}
@Test("A vault root identity mismatch is rejected with a fixed typed error")
func replacedVaultRootIsRejected() throws {
let fixture = try ResourceFixture()
defer { fixture.remove() }
let hooks = ACPDescriptorReadHooks(rootIdentityForValidation: { identity in
ApprovedRootIdentity(device: identity.device, inode: identity.inode ^ 1)
})
#expect(throws: ACPResourceReadError.unreadableResource) {
try fixture.reader(hooks: hooks)
}
}
@Test("A resource leaf symbolic link is rejected")
func leafSymlinkIsRejected() async throws {
let fixture = try ResourceFixture()
defer { fixture.remove() }
let outside = fixture.root.appendingPathComponent("outside.json")
try "outside".write(to: outside, atomically: true, encoding: .utf8)
try FileManager.default.createSymbolicLink(
at: fixture.vault.appendingPathComponent("docc_index.json"),
withDestinationURL: outside
)
let reader = try fixture.reader()
await #expect(throws: ACPResourceReadError.unreadableResource) {
try await reader.read(fixture.resource(.doccIndex))
}
}
@Test("An opened approved-root descriptor is not redirected by root replacement")
func openedApprovedRootIsPinnedDuringReplacement() async throws {
let fixture = try ResourceFixture()
defer { fixture.remove() }
try #"{"value":"approved"}"#.write(to: fixture.vault.appendingPathComponent("docc_index.json"), atomically: true, encoding: .utf8)
let outside = fixture.root.appendingPathComponent("outside", isDirectory: true)
try FileManager.default.createDirectory(at: outside, withIntermediateDirectories: true)
try #"{"value":"outside"}"#.write(to: outside.appendingPathComponent("docc_index.json"), atomically: true, encoding: .utf8)
let openedVault = fixture.root.appendingPathComponent("opened-vault", isDirectory: true)
let hooks = ACPDescriptorReadHooks(afterOpeningApprovedRoot: {
try? FileManager.default.moveItem(at: fixture.vault, to: openedVault)
try? FileManager.default.createSymbolicLink(at: fixture.vault, withDestinationURL: outside)
})
let content = try await fixture.reader(hooks: hooks).read(fixture.resource(.doccIndex))
#expect(content == #"{"value":"approved"}"#)
}
@Test("An opened leaf descriptor does not return replacement content")
func openedLeafIsPinnedDuringReplacement() async throws {
let fixture = try ResourceFixture()
defer { fixture.remove() }
let leaf = fixture.vault.appendingPathComponent("docc_index.json")
let movedLeaf = fixture.vault.appendingPathComponent("opened-index.json")
let outside = fixture.root.appendingPathComponent("outside.json")
try #"{"value":"approved"}"#.write(to: leaf, atomically: true, encoding: .utf8)
try #"{"value":"outside"}"#.write(to: outside, atomically: true, encoding: .utf8)
let hooks = ACPDescriptorReadHooks(afterOpeningLeaf: {
try? FileManager.default.moveItem(at: leaf, to: movedLeaf)
try? FileManager.default.createSymbolicLink(at: leaf, withDestinationURL: outside)
})
let reader = try fixture.reader(hooks: hooks)
do {
let content = try await reader.read(fixture.resource(.doccIndex))
#expect(content == #"{"value":"approved"}"#)
#expect(content != #"{"value":"outside"}"#)
} catch {
#expect(error as? ACPResourceReadError == .unreadableResource)
}
}
@Test("Directories and FIFOs cannot be read as resources")
func specialFilesAreRejected() async throws {
let fixture = try ResourceFixture()
defer { fixture.remove() }
let leaf = fixture.vault.appendingPathComponent("docc_index.json")
try FileManager.default.createDirectory(at: leaf, withIntermediateDirectories: true)
var reader = try fixture.reader()
await #expect(throws: ACPResourceReadError.unreadableResource) {
try await reader.read(fixture.resource(.doccIndex))
}
try FileManager.default.removeItem(at: leaf)
#if canImport(Darwin)
#expect(mkfifo(leaf.path, S_IRUSR | S_IWUSR) == 0)
reader = try fixture.reader()
await #expect(throws: ACPResourceReadError.unreadableResource) {
try await reader.read(fixture.resource(.doccIndex))
}
#endif
}
@Test("Invalid UTF-8 is rejected")
func invalidUTF8IsRejected() async throws {
let fixture = try ResourceFixture()
defer { fixture.remove() }
try Data([0xFF]).write(to: fixture.vault.appendingPathComponent("docc_index.json"))
let reader = try fixture.reader()
await #expect(throws: ACPResourceReadError.unreadableResource) {
try await reader.read(fixture.resource(.doccIndex))
}
}
@Test("Invalid JSON is rejected before the response boundary")
func invalidJSONIsRejected() async throws {
let fixture = try ResourceFixture()
defer { fixture.remove() }
try "not-json".write(
to: fixture.vault.appendingPathComponent("docc_index.json"),
atomically: true,
encoding: .utf8
)
let reader = try fixture.reader()
await #expect(throws: ACPResourceReadError.unreadableResource) {
try await reader.read(fixture.resource(.doccIndex))
}
}
@Test("Redaction removes paths and sensitive JSON values and is idempotent")
func sensitiveContentIsRedacted() {
let content = #"{"/private/key/Secret.swift":{"file":"/private/My Project/Secret.swift"},"private_key":"key-data","nested":{"url":"ssk://spec:resource"}}"#
let once = ACPResourceContentRedactor.redactingAbsolutePaths(in: content)
let twice = ACPResourceContentRedactor.redactingAbsolutePaths(in: once)
#expect(once == twice)
#expect(once.contains("<redacted-path>"))
#expect(once.contains("<redacted-sensitive-value>"))
#expect(!once.contains("My Project"))
#expect(!once.contains("/private/key/Secret.swift"))
#expect(!once.contains("key-data"))
#expect(once.contains("ssk:\\/\\/spec:resource") || once.contains("ssk://spec:resource"))
}
@Test("Plain text redaction handles secrets, incomplete PEM data, paths, and line bounds")
func plainTextSensitiveContentIsRedacted() {
let content = """
password: hunter2
Authorization: Bearer abc.def
First /private/a.swift, then keep this text.
URL file:///Users/example/Secret.swift; keep this too.
-----BEGIN PRIVATE KEY-----
unterminated-private-key-data
"""
let redacted = ACPResourceContentRedactor.redactingAbsolutePaths(in: content)
#expect(!redacted.contains("hunter2"))
#expect(!redacted.contains("abc.def"))
#expect(!redacted.contains("/private/a.swift"))
#expect(!redacted.contains("file:///Users/example/Secret.swift"))
#expect(!redacted.contains("unterminated-private-key-data"))
#expect(redacted.contains("then keep this text."))
#expect(redacted.contains("keep this too."))
}
@Test("Quoted absolute paths with spaces are fully redacted")
func quotedPathWithSpacesIsRedacted() {
let content = #"Source: "/private/My Project/Secret.swift" and '/Users/example/Other Project/File.swift'."#
let redacted = ACPResourceContentRedactor.redactingAbsolutePaths(in: content)
#expect(!redacted.contains("My Project"))
#expect(!redacted.contains("Other Project"))
#expect(!redacted.contains("Secret.swift"))
#expect(!redacted.contains("File.swift"))
#expect(redacted.contains(#""<redacted-path>""#))
#expect(redacted.contains("'<redacted-path>'"))
}
@Test("Unsafe maximum byte limits are rejected before reading")
func unsafeMaximumLimitIsRejected() throws {
let fixture = try ResourceFixture()
defer { fixture.remove() }
let limits = ACPResourceReadLimits(
doccIndexBytes: Int.max,
codebaseGraphBytes: 1,
masterMarkdownIndexBytes: 1, refreshStatusBytes: 1
)
#expect(throws: ACPResourceReadError.unreadableResource) {
try ACPVaultLedgerResourceReader(paths: fixture.context.paths, limits: limits)
}
}
private func decodedResponse(_ service: ACPService, line: String) async throws -> [String: Any] {
let responseData = await service.response(for: line)
let data = try #require(responseData)
return try #require(JSONSerialization.jsonObject(with: data) as? [String: Any])
}
private func makeTemporaryDirectory() throws -> URL {
let directory = FileManager.default.temporaryDirectory
.appendingPathComponent("SSKDocGen-\(UUID().uuidString)", isDirectory: true)
try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true)
return directory
}
}
private struct ResourceFixture: @unchecked Sendable {
let root: URL
let workspace: URL
let vault: URL
let context: ACPRequestContext
init() throws {
root = FileManager.default.temporaryDirectory
.appendingPathComponent("SSKDocGenResource-\(UUID().uuidString)", isDirectory: true)
workspace = root.appendingPathComponent("workspace", isDirectory: true)
vault = root.appendingPathComponent("vault", isDirectory: true)
try FileManager.default.createDirectory(at: workspace, withIntermediateDirectories: true)
try FileManager.default.createDirectory(at: vault, withIntermediateDirectories: true)
context = try ACPRequestContext(workspaceURL: workspace, vaultURL: vault)
}
func reader(hooks: ACPDescriptorReadHooks = .none) throws -> ACPVaultLedgerResourceReader {
try ACPVaultLedgerResourceReader(paths: context.paths, hooks: hooks)
}
func resource(_ handler: ACPResourceHandler) -> ACPResourceRegistration {
switch handler {
case .doccIndex:
return context.registry.resource(uri: "file:///SSK_Ledger_Vault/docc_index.json")!
case .codebaseGraph:
return context.registry.resource(uri: "file:///SSK_Ledger_Vault/graph.json")!
case .masterMarkdownIndex:
return context.registry.resource(uri: "file:///SSK_Ledger_Vault/DocC_Index.md")!
case .refreshStatus:
return context.registry.resource(uri: "file:///SSK_Ledger_Vault/refresh_status.json")!
}
}
func write(byteCount: Int, to leafName: String, json: Bool = false) throws {
let data: Data
if json {
precondition(byteCount >= 8)
var value = Data(#"{"x":""#.utf8)
value.append(Data(repeating: 0x61, count: byteCount - 8))
value.append(contentsOf: Data(#""}"#.utf8))
data = value
} else {
data = Data(repeating: 0x61, count: byteCount)
}
try data.write(
to: vault.appendingPathComponent(leafName),
options: .atomic
)
}
func remove() {
try? FileManager.default.removeItem(at: root)
}
}
private actor RecordingResourceReader: ACPResourceReading {
private let contents: [ACPResourceHandler: String]
private var count = 0
init(contents: [ACPResourceHandler: String]) {
self.contents = contents
}
func read(_ resource: ACPResourceRegistration) async throws -> String {
count += 1
guard let content = contents[resource.handler] else {
throw ACPResourceReadError.resourceNotFound
}
return content
}
func readCount() -> Int { count }
}

Xet Storage Details

Size:
19.1 kB
·
Xet hash:
f338eb932de75fe8f7c483f0d642409c5f23dfe565d73fb734313ba46609ab68

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.