diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index 66f46f8..0000000 --- a/CLAUDE.md +++ /dev/null @@ -1,135 +0,0 @@ -# CLAUDE.md - -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. - -## Project Overview - -aproxy is an Activity Pub Reverse Proxy Framework built on OpenResty (NGINX + LuaJIT). It provides a modular script system to add filtering and protection capabilities in front of ActivityPub implementations. - -## Development Commands - -### Testing -```sh -# Install test dependencies (only needed once) -make testdeps -eval (luarocks-5.1 path --bin) - -# Run test suite -make test -``` - -The test suite uses luajit and luaunit for testing. Tests are located in the `tests/` directory. - -## Architecture - -### Core Components - -- **main.lua**: Entry point with two hooks: - - `init()`: Validates configuration at startup - - `access()`: Called on every request to execute the filter chain - -- **config.lua**: Configuration system - - Searches for `conf.lua` in paths: `.;/etc/aproxy` (or `$APROXY_CONFIG_PATH`) - - Provides schema validation framework - - Schema supports types: `string`, `number`, `table`, `list` (array of values) - -- **ctx.lua**: Request context and filter chain executor - - Loads scripts from config and builds `compiled_chain` - - Matches request URIs against script PCRE regexes - - Executes matching callbacks sequentially - - If any callback returns a status code, request is terminated with that response - -- **util.lua**: Lua standard library extensions - - `table.readonly()`: Create read-only table wrapper - - `table.pprint()`: Pretty-print nested tables - - `string.split()`: Split strings by separator - -### Script Module Structure - -Scripts live in `scripts/` and must export: - -```lua -return { - name = 'ModuleName', - author = 'email', - title = 'Short Title', - description = [[Long description]], - version = 1, - - -- Called once at startup with config - -- Return value becomes module state - init = function(cfg) - return state - end, - - -- Map of PCRE regex patterns to callback functions - callbacks = { - ['/api/path'] = function(cfg, state) - -- Return nil to allow request - -- Return status_code, body to block request - return nil - end - }, - - -- Schema for validating this module's config - config = { - ['field_name'] = { - type = 'string|number|table|list', - schema = {...}, -- for table/list types - description = 'field description' - } - } -} -``` - -**Important**: Module configs are made read-only via `table.readonly()` before being passed to callbacks. Attempting to modify them will error. - -### Request Flow - -1. OpenResty calls `aproxy.main.access()` on each request -2. `ctx:onRequest()` iterates through `compiled_chain` -3. For each script, check if request URI matches any callback regex -4. Execute matching callbacks with their config and state -5. If callback returns `(status_code, body)`, terminate request with that response -6. If callback returns `nil`, continue to next callback -7. If no callbacks block the request, pass through to backend - -### Testing Framework - -Tests use a mock `ngx` object (created by `createNgx()` in test.lua) that simulates OpenResty's API: -- `ngx.var.uri`: Request URI -- `ngx.req.get_uri_args()`: Query parameters -- `ngx.req.get_headers()`: Request headers -- `ngx.status`, `ngx.say()`, `ngx.exit()`: Response control -- `ngx.re.match()`: PCRE regex matching via rex_pcre2 - -Use `setupTest(module_path, config)` to initialize a module for testing and `setupFakeRequest(path, options)` to simulate requests. - -To run the test suite: -```sh -# needed only once ever to setup the environment -make testdeps - -# run once on any new shell -eval (luarocks-5.1 path --bin) - -# actually run suite -make test -``` - -## Configuration - -The default config file (`conf.lua`) structure: - -```lua -return { - version = 1, - wantedScripts = { - ['script_name'] = { - -- script-specific config matching its schema - } - } -} -``` - -Scripts are loaded from `scripts/{script_name}.lua` based on keys in `wantedScripts`.