tlacacoca 0.1.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,193 @@
1
+ Metadata-Version: 2.3
2
+ Name: tlacacoca
3
+ Version: 0.1.3
4
+ Summary: Shared foundation library for TLS-based protocol implementations
5
+ Author: Alan Velasco
6
+ Author-email: Alan Velasco <alanvelasco.a@gmail.com>
7
+ Requires-Dist: cryptography>=46.0.3
8
+ Requires-Dist: structlog>=25.5.0
9
+ Requires-Dist: tomli>=2.0.0 ; python_full_version < '3.11'
10
+ Requires-Dist: tomli-w>=1.2.0
11
+ Requires-Python: >=3.10
12
+ Description-Content-Type: text/markdown
13
+
14
+ # Tlacacoca - Shared Foundation Library for TLS-Based Protocols
15
+
16
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
17
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
18
+ [![Code style: Ruff](https://img.shields.io/badge/code%20style-ruff-000000.svg)](https://github.com/astral-sh/ruff)
19
+
20
+ A protocol-agnostic foundation library providing shared components for building secure TLS-based network protocol implementations in Python. Tlacacoca (pronounced "tla-ka-KO-ka", from Nahuatl meaning "secure/safe") provides security, middleware, and logging utilities that can be shared across multiple protocol implementations.
21
+
22
+ ## Key Features
23
+
24
+ - **Security First** - TLS context creation, TOFU certificate validation, certificate utilities
25
+ - **Middleware System** - Rate limiting, IP access control, certificate authentication
26
+ - **Structured Logging** - Privacy-preserving logging with IP hashing
27
+ - **Protocol Agnostic** - Abstract interfaces that any TLS-based protocol can build upon
28
+ - **Modern Python** - Full type hints, async/await support, and modern tooling with `uv`
29
+
30
+ ## Quick Start
31
+
32
+ ### Installation
33
+
34
+ ```bash
35
+ # As a library
36
+ uv add tlacacoca
37
+
38
+ # From source (for development)
39
+ git clone https://github.com/alanbato/tlacacoca.git
40
+ cd tlacacoca && uv sync
41
+ ```
42
+
43
+ ### Basic Usage
44
+
45
+ ```python
46
+ import ssl
47
+ from tlacacoca import (
48
+ create_client_context,
49
+ create_server_context,
50
+ TOFUDatabase,
51
+ RateLimiter,
52
+ RateLimitConfig,
53
+ AccessControl,
54
+ AccessControlConfig,
55
+ MiddlewareChain,
56
+ )
57
+
58
+ # Create TLS contexts
59
+ client_ctx = create_client_context(verify_mode=ssl.CERT_REQUIRED)
60
+ server_ctx = create_server_context("cert.pem", "key.pem")
61
+
62
+ # Set up TOFU certificate validation
63
+ async with TOFUDatabase(app_name="myapp") as tofu:
64
+ # First connection - certificate is stored
65
+ await tofu.verify_or_trust("example.com", 1965, cert_fingerprint)
66
+
67
+ # Subsequent connections - certificate is verified
68
+ await tofu.verify_or_trust("example.com", 1965, cert_fingerprint)
69
+
70
+ # Configure middleware chain
71
+ rate_config = RateLimitConfig(capacity=10, refill_rate=1.0)
72
+ access_config = AccessControlConfig(
73
+ allow_list=["192.168.1.0/24"],
74
+ default_allow=False
75
+ )
76
+
77
+ chain = MiddlewareChain([
78
+ AccessControl(access_config),
79
+ RateLimiter(rate_config),
80
+ ])
81
+
82
+ # Process requests through middleware
83
+ result = await chain.process_request(
84
+ request_url="protocol://example.com/path",
85
+ client_ip="192.168.1.100"
86
+ )
87
+
88
+ if result.allowed:
89
+ # Handle request
90
+ pass
91
+ else:
92
+ # Map denial_reason to protocol-specific response
93
+ if result.denial_reason == "rate_limit":
94
+ # e.g., Gemini: "44 SLOW DOWN\r\n"
95
+ pass
96
+ ```
97
+
98
+ ## Components
99
+
100
+ ### Security
101
+
102
+ | Component | Description |
103
+ |-----------|-------------|
104
+ | `create_client_context()` | Create TLS context for client connections |
105
+ | `create_server_context()` | Create TLS context for server connections |
106
+ | `TOFUDatabase` | Trust-On-First-Use certificate validation |
107
+ | `generate_self_signed_cert()` | Generate self-signed certificates |
108
+ | `get_certificate_fingerprint()` | Get SHA-256 fingerprint of certificate |
109
+ | `load_certificate()` | Load certificate from PEM file |
110
+
111
+ ### Middleware
112
+
113
+ | Component | Description |
114
+ |-----------|-------------|
115
+ | `MiddlewareChain` | Chain multiple middleware components |
116
+ | `RateLimiter` | Token bucket rate limiting per IP |
117
+ | `AccessControl` | IP-based allow/deny lists with CIDR support |
118
+ | `CertificateAuth` | Client certificate authentication |
119
+
120
+ ### Logging
121
+
122
+ | Component | Description |
123
+ |-----------|-------------|
124
+ | `configure_logging()` | Configure structured logging |
125
+ | `get_logger()` | Get a logger instance |
126
+ | `hash_ip_processor()` | Privacy-preserving IP hashing |
127
+
128
+ ## Protocol Implementations Using Tlacacoca
129
+
130
+ Tlacacoca is designed to be used by protocol-specific implementations:
131
+
132
+ - **nauyaca** - Gemini protocol server & client
133
+ - **amatl** - Scroll protocol implementation (planned)
134
+
135
+ ## Documentation
136
+
137
+ ### Middleware Return Types
138
+
139
+ Middleware components return `MiddlewareResult` with protocol-agnostic denial reasons:
140
+
141
+ ```python
142
+ from tlacacoca import MiddlewareResult, DenialReason
143
+
144
+ # Allowed request
145
+ result = MiddlewareResult(allowed=True)
146
+
147
+ # Denied request
148
+ result = MiddlewareResult(
149
+ allowed=False,
150
+ denial_reason=DenialReason.RATE_LIMIT,
151
+ retry_after=30
152
+ )
153
+ ```
154
+
155
+ Protocol implementations map these to their specific status codes:
156
+
157
+ | Denial Reason | Gemini Status | Description |
158
+ |--------------|---------------|-------------|
159
+ | `RATE_LIMIT` | 44 SLOW DOWN | Rate limit exceeded |
160
+ | `ACCESS_DENIED` | 53 PROXY REFUSED | IP not allowed |
161
+ | `CERT_REQUIRED` | 60 CLIENT CERT REQUIRED | Need client certificate |
162
+ | `CERT_NOT_AUTHORIZED` | 61 CERT NOT AUTHORIZED | Certificate not in allowed list |
163
+
164
+ ## Contributing
165
+
166
+ ```bash
167
+ # Setup
168
+ git clone https://github.com/alanbato/tlacacoca.git
169
+ cd tlacacoca && uv sync
170
+
171
+ # Test
172
+ uv run pytest
173
+
174
+ # Lint & Type Check
175
+ uv run ruff check src/ tests/
176
+ uv run ty check src/
177
+ ```
178
+
179
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
180
+
181
+ ## License
182
+
183
+ MIT License - see [LICENSE](LICENSE) for details.
184
+
185
+ ## Resources
186
+
187
+ - [SECURITY.md](SECURITY.md) - Security documentation
188
+ - [GitHub Issues](https://github.com/alanbato/tlacacoca/issues) - Bug reports
189
+ - [GitHub Discussions](https://github.com/alanbato/tlacacoca/discussions) - Questions and ideas
190
+
191
+ ---
192
+
193
+ **Status**: Active development (pre-1.0). Core security and middleware features are stable.
@@ -0,0 +1,180 @@
1
+ # Tlacacoca - Shared Foundation Library for TLS-Based Protocols
2
+
3
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+ [![Code style: Ruff](https://img.shields.io/badge/code%20style-ruff-000000.svg)](https://github.com/astral-sh/ruff)
6
+
7
+ A protocol-agnostic foundation library providing shared components for building secure TLS-based network protocol implementations in Python. Tlacacoca (pronounced "tla-ka-KO-ka", from Nahuatl meaning "secure/safe") provides security, middleware, and logging utilities that can be shared across multiple protocol implementations.
8
+
9
+ ## Key Features
10
+
11
+ - **Security First** - TLS context creation, TOFU certificate validation, certificate utilities
12
+ - **Middleware System** - Rate limiting, IP access control, certificate authentication
13
+ - **Structured Logging** - Privacy-preserving logging with IP hashing
14
+ - **Protocol Agnostic** - Abstract interfaces that any TLS-based protocol can build upon
15
+ - **Modern Python** - Full type hints, async/await support, and modern tooling with `uv`
16
+
17
+ ## Quick Start
18
+
19
+ ### Installation
20
+
21
+ ```bash
22
+ # As a library
23
+ uv add tlacacoca
24
+
25
+ # From source (for development)
26
+ git clone https://github.com/alanbato/tlacacoca.git
27
+ cd tlacacoca && uv sync
28
+ ```
29
+
30
+ ### Basic Usage
31
+
32
+ ```python
33
+ import ssl
34
+ from tlacacoca import (
35
+ create_client_context,
36
+ create_server_context,
37
+ TOFUDatabase,
38
+ RateLimiter,
39
+ RateLimitConfig,
40
+ AccessControl,
41
+ AccessControlConfig,
42
+ MiddlewareChain,
43
+ )
44
+
45
+ # Create TLS contexts
46
+ client_ctx = create_client_context(verify_mode=ssl.CERT_REQUIRED)
47
+ server_ctx = create_server_context("cert.pem", "key.pem")
48
+
49
+ # Set up TOFU certificate validation
50
+ async with TOFUDatabase(app_name="myapp") as tofu:
51
+ # First connection - certificate is stored
52
+ await tofu.verify_or_trust("example.com", 1965, cert_fingerprint)
53
+
54
+ # Subsequent connections - certificate is verified
55
+ await tofu.verify_or_trust("example.com", 1965, cert_fingerprint)
56
+
57
+ # Configure middleware chain
58
+ rate_config = RateLimitConfig(capacity=10, refill_rate=1.0)
59
+ access_config = AccessControlConfig(
60
+ allow_list=["192.168.1.0/24"],
61
+ default_allow=False
62
+ )
63
+
64
+ chain = MiddlewareChain([
65
+ AccessControl(access_config),
66
+ RateLimiter(rate_config),
67
+ ])
68
+
69
+ # Process requests through middleware
70
+ result = await chain.process_request(
71
+ request_url="protocol://example.com/path",
72
+ client_ip="192.168.1.100"
73
+ )
74
+
75
+ if result.allowed:
76
+ # Handle request
77
+ pass
78
+ else:
79
+ # Map denial_reason to protocol-specific response
80
+ if result.denial_reason == "rate_limit":
81
+ # e.g., Gemini: "44 SLOW DOWN\r\n"
82
+ pass
83
+ ```
84
+
85
+ ## Components
86
+
87
+ ### Security
88
+
89
+ | Component | Description |
90
+ |-----------|-------------|
91
+ | `create_client_context()` | Create TLS context for client connections |
92
+ | `create_server_context()` | Create TLS context for server connections |
93
+ | `TOFUDatabase` | Trust-On-First-Use certificate validation |
94
+ | `generate_self_signed_cert()` | Generate self-signed certificates |
95
+ | `get_certificate_fingerprint()` | Get SHA-256 fingerprint of certificate |
96
+ | `load_certificate()` | Load certificate from PEM file |
97
+
98
+ ### Middleware
99
+
100
+ | Component | Description |
101
+ |-----------|-------------|
102
+ | `MiddlewareChain` | Chain multiple middleware components |
103
+ | `RateLimiter` | Token bucket rate limiting per IP |
104
+ | `AccessControl` | IP-based allow/deny lists with CIDR support |
105
+ | `CertificateAuth` | Client certificate authentication |
106
+
107
+ ### Logging
108
+
109
+ | Component | Description |
110
+ |-----------|-------------|
111
+ | `configure_logging()` | Configure structured logging |
112
+ | `get_logger()` | Get a logger instance |
113
+ | `hash_ip_processor()` | Privacy-preserving IP hashing |
114
+
115
+ ## Protocol Implementations Using Tlacacoca
116
+
117
+ Tlacacoca is designed to be used by protocol-specific implementations:
118
+
119
+ - **nauyaca** - Gemini protocol server & client
120
+ - **amatl** - Scroll protocol implementation (planned)
121
+
122
+ ## Documentation
123
+
124
+ ### Middleware Return Types
125
+
126
+ Middleware components return `MiddlewareResult` with protocol-agnostic denial reasons:
127
+
128
+ ```python
129
+ from tlacacoca import MiddlewareResult, DenialReason
130
+
131
+ # Allowed request
132
+ result = MiddlewareResult(allowed=True)
133
+
134
+ # Denied request
135
+ result = MiddlewareResult(
136
+ allowed=False,
137
+ denial_reason=DenialReason.RATE_LIMIT,
138
+ retry_after=30
139
+ )
140
+ ```
141
+
142
+ Protocol implementations map these to their specific status codes:
143
+
144
+ | Denial Reason | Gemini Status | Description |
145
+ |--------------|---------------|-------------|
146
+ | `RATE_LIMIT` | 44 SLOW DOWN | Rate limit exceeded |
147
+ | `ACCESS_DENIED` | 53 PROXY REFUSED | IP not allowed |
148
+ | `CERT_REQUIRED` | 60 CLIENT CERT REQUIRED | Need client certificate |
149
+ | `CERT_NOT_AUTHORIZED` | 61 CERT NOT AUTHORIZED | Certificate not in allowed list |
150
+
151
+ ## Contributing
152
+
153
+ ```bash
154
+ # Setup
155
+ git clone https://github.com/alanbato/tlacacoca.git
156
+ cd tlacacoca && uv sync
157
+
158
+ # Test
159
+ uv run pytest
160
+
161
+ # Lint & Type Check
162
+ uv run ruff check src/ tests/
163
+ uv run ty check src/
164
+ ```
165
+
166
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
167
+
168
+ ## License
169
+
170
+ MIT License - see [LICENSE](LICENSE) for details.
171
+
172
+ ## Resources
173
+
174
+ - [SECURITY.md](SECURITY.md) - Security documentation
175
+ - [GitHub Issues](https://github.com/alanbato/tlacacoca/issues) - Bug reports
176
+ - [GitHub Discussions](https://github.com/alanbato/tlacacoca/discussions) - Questions and ideas
177
+
178
+ ---
179
+
180
+ **Status**: Active development (pre-1.0). Core security and middleware features are stable.
@@ -0,0 +1,35 @@
1
+ [project]
2
+ name = "tlacacoca"
3
+ version = "0.1.3"
4
+ description = "Shared foundation library for TLS-based protocol implementations"
5
+ readme = "README.md"
6
+ authors = [
7
+ { name = "Alan Velasco", email = "alanvelasco.a@gmail.com" }
8
+ ]
9
+ requires-python = ">=3.10"
10
+ dependencies = [
11
+ "cryptography>=46.0.3",
12
+ "structlog>=25.5.0",
13
+ "tomli>=2.0.0 ; python_full_version < '3.11'",
14
+ "tomli-w>=1.2.0",
15
+ ]
16
+
17
+ [build-system]
18
+ requires = ["uv_build>=0.9.10,<0.10.0"]
19
+ build-backend = "uv_build"
20
+
21
+ [dependency-groups]
22
+ dev = [
23
+ "pre-commit>=4.5.1",
24
+ "pytest>=9.0.2",
25
+ "pytest-asyncio>=0.24.0",
26
+ "pytest-cov>=4.0.0",
27
+ "ruff>=0.14.11",
28
+ "ty>=0.0.10",
29
+ ]
30
+ docs = [
31
+ "mkdocs-git-revision-date-localized-plugin>=1.5.0",
32
+ "mkdocs-material>=9.7.1",
33
+ "mkdocstrings[python]>=1.0.0",
34
+ "pymdown-extensions>=10.20",
35
+ ]
@@ -0,0 +1,74 @@
1
+ """tlacacoca - Shared foundation library for TLS-based protocol implementations.
2
+
3
+ This library provides protocol-agnostic components for building secure
4
+ network protocol clients and servers:
5
+
6
+ - Security: TLS context creation, certificate utilities, TOFU validation
7
+ - Middleware: Rate limiting, access control, certificate authentication
8
+ - Logging: Structured logging with privacy-preserving IP hashing
9
+ """
10
+
11
+ # Security
12
+ from .security.certificates import (
13
+ generate_self_signed_cert,
14
+ get_certificate_fingerprint,
15
+ get_certificate_fingerprint_from_path,
16
+ get_certificate_info,
17
+ is_certificate_expired,
18
+ is_certificate_valid_for_hostname,
19
+ load_certificate,
20
+ validate_certificate_file,
21
+ )
22
+ from .security.tls import create_client_context, create_server_context
23
+ from .security.tofu import CertificateChangedError, TOFUDatabase
24
+
25
+ # Middleware
26
+ from .middleware.access_control import AccessControl, AccessControlConfig
27
+ from .middleware.base import DenialReason, Middleware, MiddlewareChain, MiddlewareResult
28
+ from .middleware.certificate_auth import (
29
+ CertificateAuth,
30
+ CertificateAuthConfig,
31
+ CertificateAuthPathRule,
32
+ )
33
+ from .middleware.rate_limit import RateLimitConfig, RateLimiter, TokenBucket
34
+
35
+ # Logging
36
+ from .logging.structured import configure_logging, get_logger, hash_ip_processor
37
+
38
+ __all__ = [
39
+ # Security - TLS
40
+ "create_client_context",
41
+ "create_server_context",
42
+ # Security - Certificates
43
+ "generate_self_signed_cert",
44
+ "load_certificate",
45
+ "get_certificate_fingerprint",
46
+ "get_certificate_fingerprint_from_path",
47
+ "is_certificate_expired",
48
+ "is_certificate_valid_for_hostname",
49
+ "get_certificate_info",
50
+ "validate_certificate_file",
51
+ # Security - TOFU
52
+ "TOFUDatabase",
53
+ "CertificateChangedError",
54
+ # Middleware - Base
55
+ "DenialReason",
56
+ "MiddlewareResult",
57
+ "Middleware",
58
+ "MiddlewareChain",
59
+ # Middleware - Rate limiting
60
+ "TokenBucket",
61
+ "RateLimiter",
62
+ "RateLimitConfig",
63
+ # Middleware - Access control
64
+ "AccessControl",
65
+ "AccessControlConfig",
66
+ # Middleware - Certificate auth
67
+ "CertificateAuth",
68
+ "CertificateAuthConfig",
69
+ "CertificateAuthPathRule",
70
+ # Logging
71
+ "configure_logging",
72
+ "get_logger",
73
+ "hash_ip_processor",
74
+ ]
@@ -0,0 +1,9 @@
1
+ """Logging module for structured logging configuration."""
2
+
3
+ from .structured import configure_logging, get_logger, hash_ip_processor
4
+
5
+ __all__ = [
6
+ "configure_logging",
7
+ "get_logger",
8
+ "hash_ip_processor",
9
+ ]
@@ -0,0 +1,144 @@
1
+ """Structured logging configuration using structlog.
2
+
3
+ This module provides structured logging configuration with privacy-preserving
4
+ features like IP address hashing.
5
+ """
6
+
7
+ import hashlib
8
+ import sys
9
+ from pathlib import Path
10
+ from typing import Any
11
+
12
+ import structlog
13
+
14
+
15
+ def hash_ip_processor(
16
+ logger: Any, method_name: str, event_dict: dict[str, Any]
17
+ ) -> dict[str, Any]:
18
+ """Hash IP addresses in log events for privacy.
19
+
20
+ IP addresses should be hashed in logs to protect user privacy while
21
+ still allowing abuse detection.
22
+
23
+ Args:
24
+ logger: The logger instance.
25
+ method_name: The logging method name.
26
+ event_dict: The event dictionary.
27
+
28
+ Returns:
29
+ The event dictionary with client_ip replaced by client_ip_hash.
30
+ """
31
+ if "client_ip" in event_dict:
32
+ ip = event_dict["client_ip"]
33
+ if ip and ip != "unknown":
34
+ # SHA256 hash, truncated to 12 chars for readability
35
+ hashed = hashlib.sha256(ip.encode()).hexdigest()[:12]
36
+ event_dict["client_ip_hash"] = hashed
37
+ del event_dict["client_ip"]
38
+ return event_dict
39
+
40
+
41
+ def configure_logging(
42
+ log_level: str = "INFO",
43
+ log_file: Path | None = None,
44
+ json_logs: bool = False,
45
+ hash_ips: bool = True,
46
+ ) -> None:
47
+ """Configure structured logging for the application.
48
+
49
+ This function should be called once at application startup. When using
50
+ a log file, the file handle remains open for the application lifetime.
51
+
52
+ Args:
53
+ log_level: Logging level (DEBUG, INFO, WARNING, ERROR).
54
+ log_file: Optional path to log file. If None, logs to stdout.
55
+ The file is opened in append mode and remains open.
56
+ json_logs: If True, output logs in JSON format. Otherwise, use
57
+ human-readable format.
58
+ hash_ips: If True (default), hash client IP addresses in logs
59
+ for privacy.
60
+
61
+ Examples:
62
+ >>> # Configure for development (human-readable console output)
63
+ >>> configure_logging(log_level="DEBUG")
64
+
65
+ >>> # Configure for production (JSON logs to file, hashed IPs)
66
+ >>> configure_logging(
67
+ ... log_level="INFO",
68
+ ... log_file=Path("/var/log/myapp.log"),
69
+ ... json_logs=True,
70
+ ... hash_ips=True
71
+ ... )
72
+ """
73
+ # Determine output stream
74
+ if log_file:
75
+ output_stream = open(log_file, "a")
76
+ else:
77
+ output_stream = sys.stdout
78
+
79
+ # Build base processors
80
+ base_processors: list[Any] = [
81
+ structlog.contextvars.merge_contextvars,
82
+ structlog.processors.add_log_level,
83
+ structlog.processors.TimeStamper(
84
+ fmt="iso" if json_logs else "%Y-%m-%d %H:%M:%S"
85
+ ),
86
+ ]
87
+
88
+ # Add IP hashing processor if enabled (for privacy)
89
+ if hash_ips:
90
+ base_processors.append(hash_ip_processor)
91
+
92
+ # Configure output format
93
+ if json_logs:
94
+ # JSON format for production/structured logging
95
+ processors = base_processors + [structlog.processors.JSONRenderer()]
96
+ else:
97
+ # Human-readable format for development
98
+ processors = base_processors + [
99
+ structlog.dev.ConsoleRenderer(colors=output_stream.isatty())
100
+ ]
101
+
102
+ # Configure structlog
103
+ structlog.configure(
104
+ processors=processors,
105
+ wrapper_class=structlog.make_filtering_bound_logger(_level_to_int(log_level)),
106
+ context_class=dict,
107
+ logger_factory=structlog.PrintLoggerFactory(file=output_stream),
108
+ cache_logger_on_first_use=True,
109
+ )
110
+
111
+
112
+ def _level_to_int(level: str) -> int:
113
+ """Convert string log level to integer.
114
+
115
+ Args:
116
+ level: Log level string (DEBUG, INFO, WARNING, ERROR, CRITICAL).
117
+
118
+ Returns:
119
+ Integer log level.
120
+ """
121
+ levels = {
122
+ "DEBUG": 10,
123
+ "INFO": 20,
124
+ "WARNING": 30,
125
+ "ERROR": 40,
126
+ "CRITICAL": 50,
127
+ }
128
+ return levels.get(level.upper(), 20)
129
+
130
+
131
+ def get_logger(name: str) -> structlog.BoundLogger:
132
+ """Get a logger instance for a module.
133
+
134
+ Args:
135
+ name: Logger name (typically __name__).
136
+
137
+ Returns:
138
+ A structlog BoundLogger instance.
139
+
140
+ Examples:
141
+ >>> logger = get_logger(__name__)
142
+ >>> logger.info("server_started", host="localhost", port=1965)
143
+ """
144
+ return structlog.get_logger(name)
@@ -0,0 +1,29 @@
1
+ """Middleware module for request processing, rate limiting, and access control."""
2
+
3
+ from .access_control import AccessControl, AccessControlConfig
4
+ from .base import DenialReason, Middleware, MiddlewareChain, MiddlewareResult
5
+ from .certificate_auth import (
6
+ CertificateAuth,
7
+ CertificateAuthConfig,
8
+ CertificateAuthPathRule,
9
+ )
10
+ from .rate_limit import RateLimitConfig, RateLimiter, TokenBucket
11
+
12
+ __all__ = [
13
+ # Base
14
+ "DenialReason",
15
+ "MiddlewareResult",
16
+ "Middleware",
17
+ "MiddlewareChain",
18
+ # Rate limiting
19
+ "TokenBucket",
20
+ "RateLimiter",
21
+ "RateLimitConfig",
22
+ # Access control
23
+ "AccessControl",
24
+ "AccessControlConfig",
25
+ # Certificate auth
26
+ "CertificateAuth",
27
+ "CertificateAuthConfig",
28
+ "CertificateAuthPathRule",
29
+ ]