This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. Always create a new git branch before making changes. Branch names should follow the pattern feature/. Changes should include updates to README.md whenever the public API changes, and updates to CLAUDE.md whenever there is a structural change. Always check ALL unit tests after making changes.
SwiftLDAP is a pure-Swift LDAPv3 client library with async/await support. Zero external dependencies — built on Foundation and Darwin/CoreFoundation only. Targets macOS 13+ / iOS 16+ (Darwin-only due to CFStream-based transport). Uses Swift 6.0 strict concurrency throughout.
Implements RFC 4511 (LDAPv3), RFC 4513 (auth/TLS), RFC 4515 (filter strings), RFC 4512 (rootDSE/server info), RFC 4532 (Who Am I?).
swift build # Build the library
swift test # Run unit tests only
swift test --filter SwiftLDAPTests # Run unit tests explicitly
swift test --filter SwiftLDAPTests.<SuiteName> # Run a specific test suite (e.g. BEREncoderTests)
# Integration tests (require Docker)
./scripts/integration-tests.sh # Full cycle: generate certs, start OpenLDAP, run tests, tear down
./scripts/integration-tests.sh --keep # Keep container running after tests
# Manual integration test workflow
bash scripts/generate-test-certs.sh
docker compose up -d --wait
LDAP_INTEGRATION_TESTS=1 swift test --filter IntegrationTests
docker compose down -v-
Transport (
Sources/SwiftLDAP/Transport/) —StreamTransport(private) wraps POSIX sockets + CFStream for TCP I/O with TLS support.LDAPConnection(internal actor) frames complete BER messages from the raw byte stream.LDAPSecurityModeenum defines.none,.startTLS,.ldaps.LDAPConnectionConfig(public struct) exposes configurable limits:connectTimeout,operationTimeout,maxMessageSize(10 MB default),maxSearchEntries, andtlsVerifyPeer. -
BER (
Sources/SwiftLDAP/BER/) — ASN.1 BER encoding/decoding.BEREncoderbuilds TLV byte arrays via a closure-based sub-encoder pattern for constructed types.BERDecoderreads TLV elements sequentially from a byte slice.ASN1Tagdefines all universal and LDAP application-specific tags. -
Protocol (
Sources/SwiftLDAP/Protocol/) —LDAPCodectranslates betweenLDAPOperationenum (21 cases for all request/response PDUs) and BER bytes.LDAPFilteris an indirect enum with BER encode/decode and an RFC 4515 recursive-descent string parser; convenience constructors include.equal(attr, value),.exists(attr),.substring(attr, pattern).LDAPResultCodecovers all 37 RFC 4511 codes.LDAPMessage.swiftdefines shared protocol structures:LDAPControl,ModifyItem,SearchParameters,BindAuthentication,SearchScope,DerefAliases,ModifyOperation. -
Models (
Sources/SwiftLDAP/Models/) —LDAPEntry(dn +[String: [Data]]attributes),LDAPAttribute,LDAPError(8-case enum covering server errors, TLS, protocol, timeout, I/O),LDAPServerFingerprint(rootDSE-derived server info),LDAPServerTypeenum (.openLDAP,.activeDirectory,.directoryServer389,.apacheDS,.unknown). -
Client (
LDAPClient.swift) — The sole public entry point. Anactorthat allocates message IDs, encodes requests viaLDAPCodec, sends/receives viaLDAPConnection, decodes responses, and returns typed results. Operations:connect,simpleBind,search,searchStream,add,modify,delete,modifyDN,compare,whoAmI,extendedOperation,fingerprint.
- Actor isolation:
LDAPClient(public) andLDAPConnection(internal) are actors.StreamTransportis@unchecked Sendablewith serial DispatchQueues for read/write. - Message framing:
LDAPConnection.receiveMessage()accumulates bytes until a complete BER TLV is available, handling multi-chunk reads. - Streaming search:
searchStream()returnsAsyncThrowingStream<LDAPEntry, Error>for memory-efficient large result sets.
- Unit tests (
Tests/SwiftLDAPTests/) use Swift Testing framework (@Suite,@Test). All pure in-memory, no network. - Integration tests (
Tests/IntegrationTests/) are gated by theLDAP_INTEGRATION_TESTSenv var. Tests use.enabled(if: integrationEnabled). All suites are.serializedto avoid concurrent mutations against the shared OpenLDAP instance. - Test data:
Tests/IntegrationTests/Fixtures/seed.ldifseedsdc=example,dc=orgwith users and groups. - Integration test env vars:
LDAP_TEST_HOST(defaultlocalhost),LDAP_TEST_PORT(default1389),LDAP_TEST_LDAPS_PORT(default1636).