diff --git a/AGENTS.md b/AGENTS.md index b2d2d4b..d1c7dcf 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -12,7 +12,7 @@ Agentic principles and technical context for the `wolfram` repository. 6. **C-first, C++ where beneficial**: the SDK and generated clients are C23 at runtime. Development-time code generation and tests use C++ programs (`tools/*.cpp`, built as CMake targets); they must never become a runtime dependency. Prefer C++ where it is beneficial — RAII-based resource management (e.g. cJSON), performance-critical code, and third-party library integrations with no C equivalent — and use it rather than writing error-prone manual-cleanup C. All C++ code must be wrapped with `extern "C"` to maintain C23 compatibility. Always use `extern "C"` for any wrapper so the rest of the SDK can consume it without C++ headers or types. Where a C library equivalent exists, prefer the C one. Default to C for new code; introduce C++ where the complexity, resource management, or performance requirements justify it. 7. **Console/multi-platform support**: support for embedded and cross-compiled targets (Nintendo Wii, Wii U, 3DS, Windows, Linux/AArch64, etc.) is parity across platforms — platform-specific APIs are isolated in `src/platform/`. The Windows target is fully implemented against the Win32 API. Wii has real libogc primitives, mbedTLS HTTPS and WebSocket (RFC 6455 client), and P-256/did:key crypto; secp256k1 is also implemented via mbedTLS. Wii U has real wut primitives and uses the curl transport (see "Platform support"). 3DS has real libctru primitives (LightLock mutex, osGetTime clock, httpc transport) and mbedtls-based P-256/did:key crypto. 8. **No duplication**: if a piece of logic already exists elsewhere in this codebase, call into it rather than reimplementing it a second time — this applies within the SDK itself, not just against external libraries (see point 2). Two independent implementations of the same rule can silently drift apart, and only one of them getting fixed is worse than either alone. This matters most for security-sensitive logic (signature/nonce normalization, replay handling, constant-time comparisons), but applies generally: before writing a new helper, check whether an equivalent already exists nearby and extract/reuse it instead of copying it. -9. **Multithreaded by default**: the optional XRPC server (`WOLFRAM_BUILD_SERVER`) uses a libmicrohttpd thread pool whose size is controlled by `thread_count` (default 4). All shared server state — the route table, rate-limit buckets, SSE subscriber lists, and WebSocket stream registry — is guarded by a mutex. The client transport is also thread-safe: `wf_xrpc_client` holds a mutex around its mutable fields, and `wf_xrpc_query_async`/`wf_xrpc_procedure_async` issue requests on a worker thread using a config snapshot. New server-side code must document its locking discipline, use the `_locked` variant pattern (public wrapper locks, internal unlocked variant) to avoid recursive-lock deadlocks, and never assume single-threaded access even in single-threaded test configs. +9. **Multithreaded by default**: the optional XRPC server (`WOLFRAM_BUILD_SERVER`) uses a libmicrohttpd thread pool whose size is controlled by `thread_count` (auto-sized to CPU count × 2 when 0, default 8 on high-core hosts). All shared server state — the route table, rate-limit buckets, SSE subscriber lists, and WebSocket stream registry — is guarded by a mutex. The client transport is also thread-safe: `wf_xrpc_client` holds a mutex around its mutable fields, and `wf_xrpc_query_async`/`wf_xrpc_procedure_async` issue requests on a worker thread using a config snapshot. New server-side code must document its locking discipline, use the `_locked` variant pattern (public wrapper locks, internal unlocked variant) to avoid recursive-lock deadlocks, and never assume single-threaded access even in single-threaded test configs. ## Code style @@ -131,14 +131,14 @@ The bundled lexicon filenames currently match the local upstream checkout, but f - `WF_OK` means the promised output is initialized and owned as documented. On failure, leave outputs safely freeable and release every partial allocation. Do not collapse protocol-specific failures into success or infer missing union members. - The presence of a wrapper does not establish complete behavior. Several typed conveniences are intentionally honest stubs because no matching lexicon endpoint exists, and some repository-store paths still map protocol-specific errors to broad status codes. Search the implementation and tests before claiming coverage. - Platform implementations are not interchangeable: desktop crypto/HTTP uses OpenSSL/libcurl and optional secp256k1, while Wii uses mbedTLS plus compatibility code and excludes substantial desktop surface. Test the backend whose behavior changed. -- All server-side shared state must be thread-safe. The XRPC server runs on a libmicrohttpd thread pool (default 4 threads); route table mutations, rate-limit bucket access, SSE subscriber lists, and WebSocket stream registration must each be guarded by a mutex. Document the locking discipline at each entry point and use the `_locked` internal-variant pattern (caller holds lock) + public wrapper (locks) to avoid recursive-lock deadlocks with registration paths. +- All server-side shared state must be thread-safe. The XRPC server runs on a libmicrohttpd thread pool (auto-sized to CPU × 2 when `thread_count` is 0); route table mutations, rate-limit bucket access, SSE subscriber lists, and WebSocket stream registration must each be guarded by a mutex. Document the locking discipline at each entry point and use the `_locked` internal-variant pattern (caller holds lock) + public wrapper (locks) to avoid recursive-lock deadlocks with registration paths. ## Current state The SDK is broad and multi-layered, with extensive offline coverage. “Implemented” below means a concrete code path exists; it does not imply every optional build, live service, or console backend ran in the current validation. Known honest stubs and partial modules remain and must stay visible. Highlights: - `xrpc`: libcurl query/procedure calls, encoded scalar/repeated parameters, generic HTTP GET, bearer authentication, binary blob upload (incl. video), DPoP-bound OAuth client (`auth_client`), **thread-safe transport with async client SDK** (`wf_xrpc_query_async`/`wf_xrpc_procedure_async` via `wf_xrpc_pending`). Tested. -- `xrpc_server`: optional `libmicrohttpd`-backed XRPC server (`WOLFRAM_BUILD_SERVER`) with **thread-pool support** (`thread_count`, default 4, via `MHD_OPTION_THREAD_POOL_SIZE`), SSE streaming, WebSocket subscription endpoints, per-route token-bucket rate limiting. Route table and rate-limit entries are guarded by mutexes; route lookups use `_locked` + public-wrapper pattern. Tested offline, including `test_xrpc_server_parallel` for concurrent-request integrity. +- `xrpc_server`: optional `libmicrohttpd`-backed XRPC server (`WOLFRAM_BUILD_SERVER`) with **thread-pool support** (`thread_count`, auto-sized to CPU count × 2 when 0), SSE streaming, WebSocket subscription endpoints, per-route token-bucket rate limiting. Route table and rate-limit entries are guarded by mutexes; route lookups use `_locked` + public-wrapper pattern. Tested offline, including `test_xrpc_server_parallel` for concurrent-request integrity. - `session` / `server`: PDS login, resume, refresh, logout, and full `com.atproto.server` account lifecycle (createAccount, app passwords, deactivate, email/account-delete requests, session refresh). The `server_typed` agent wrappers implement the parameterless `com.atproto.server` procedures (`requestAccountDelete`, `requestEmailUpdate`, `requestEmailConfirmation`, `refreshSession`). Tested. - `identity` / `identity_typed` / `plc`: did:plc, did:web, handle DNS TXT (c-ares/POSIX `libresolv`/well-known fallback), `com.atproto.identity` wrappers, and DID PLC operation build/sign/submit helpers. `wf_agent_identity_rotate_handle` now wires the full handle-rotation flow: it builds the rotation operation locally (validation gate) and, given the out-of-band `requestPlcOperationSignature` token, signs it server-side via `signPlcOperation` and submits it via `submitPlcOperation`. Tested. - `crypto`: secp256k1 (libsecp256k1) + P-256 (OpenSSL), `did:key`/multikey verification. Tested. diff --git a/CMakeLists.txt b/CMakeLists.txt index e7d35af..69948ea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ if(POLICY CMP0156) endif() project( wolfram - VERSION 0.11.0 + VERSION 0.12.0 DESCRIPTION "A C/C++ SDK for the AT Protocol" LANGUAGES C CXX)