Coding Standards¶
Document type: Engineering Standard
Scope: Application services, APIs, AI orchestration, integrations, tests, and supporting infrastructure
Status: Baseline engineering policy
This document defines the coding practices expected across WhiteLotusAI. Its purpose is to keep the codebase maintainable, secure, testable, and consistent as the platform evolves.
These standards complement the repository's existing dependency constraints, configuration, and CI workflows. Where a tool or convention has not yet been formally adopted, follow the existing project implementation rather than introducing an unapproved requirement.
Readable and maintainable
Prefer explicit interfaces, focused functions, meaningful names, and clear error handling.
Secure by default
Validate inputs, enforce authorization server-side, and treat external content as untrusted.
Testable by design
Cover regressions, edge cases, failure paths, and provider integrations with deterministic tests.
Review-ready changes
Keep changes scoped, document important decisions, and verify compatibility before merging.
Start with the existing project configuration
Before changing formatting, linting, typing, or testing conventions, inspect the dependency files, tool configuration, and CI workflow. The engineering setup guide should remain the source of truth for the exact commands used by the project.
Engineering Setup Repository Structure
1. Core engineering principles¶
All contributions should follow these principles.
| Principle | Expected practice |
|---|---|
| Clarity | Prefer descriptive names, explicit control flow, and typed interfaces over implicit state or clever abstractions. |
| Separation of concerns | Keep API handling, orchestration, policy enforcement, provider adapters, and persistence responsibilities distinct. |
| Boundary validation | Validate external inputs before they enter application logic. |
| Focused implementation | Keep functions and classes cohesive, with clearly defined responsibilities. |
| Centralized authorization | Apply access-control decisions consistently in trusted application code. |
| Explicit failure handling | Propagate or handle exceptions deliberately; never disguise failures as successful operations. |
| Reproducibility | Keep dependency versions, configuration, and test behavior consistent across development and CI. |
| Data protection | Never commit secrets, credentials, unnecessary personal data, or local environment files. |
Do not hide failures
Avoid broad exception handlers that silently discard errors. If an exception is handled, the code must have a deliberate recovery or failure response, with appropriate diagnostics and without exposing sensitive information.
2. Code ownership and separation of responsibilities¶
WhiteLotusAI includes application services, AI orchestration, external integrations, and persistence. Keep responsibilities explicit so that changes remain independently testable.
flowchart TD
INPUT["External Input"]
API["API and Boundary Validation"]
POLICY["Authorization and Policy"]
ORCH["Application Logic and AI Orchestration"]
ADAPTER["Provider and Service Adapters"]
DATA["Persistence Layer"]
RESPONSE["Validated Response"]
INPUT --> API
API --> POLICY
POLICY --> ORCH
ORCH --> ADAPTER
ADAPTER --> DATA
DATA --> ADAPTER
ADAPTER --> ORCH
ORCH --> RESPONSE
classDef boundary fill:#dbeafe,stroke:#2563eb,color:#172554
classDef security fill:#ffedd5,stroke:#ea580c,color:#7c2d12
classDef logic fill:#dcfce7,stroke:#16a34a,color:#14532d
classDef storage fill:#f3e8ff,stroke:#9333ea,color:#581c87
class INPUT,API,RESPONSE boundary
class POLICY security
class ORCH,ADAPTER logic
class DATA storage
The diagram illustrates a recommended separation of responsibilities, not a claim about the exact runtime call sequence of every service.
| Component | Primary responsibility | Avoid |
|---|---|---|
| API and boundary layer | Parse requests, validate inputs, and shape responses. | Embedding provider-specific logic in route handlers. |
| Policy and authorization | Enforce permissions, access boundaries, and operation restrictions. | Trusting model-generated authorization decisions. |
| Orchestration | Coordinate application workflows, model calls, and approved tools. | Duplicating security policy across individual tools. |
| Provider adapters | Encapsulate external API requests, response mapping, and provider-specific failures. | Leaking provider-specific assumptions into unrelated services. |
| Persistence | Store and retrieve data under established ownership and access rules. | Bypassing access controls or mixing unrelated persistence concerns. |
| Tests | Verify behavior, failure handling, and cross-component contracts. | Depending on production accounts or uncontrolled external state. |
3. Python coding standards¶
Follow PEP 8 unless an approved project configuration establishes different conventions. Use the existing Python version, dependencies, and type-checking practices.
3.1 Naming and structure¶
- Use
snake_casefor functions, variables, and modules. - Use
PascalCasefor classes. - Use descriptive names that communicate intent.
- Keep functions focused and avoid unnecessary nesting.
- Extract repeated logic only when doing so improves clarity and maintainability.
- Prefer explicit parameters and return types for public or nontrivial interfaces.
- Keep configuration separate from business logic.
- Avoid mutable global state unless its lifecycle and synchronization are deliberate.
3.2 Type annotations and validation¶
Use type annotations to make interfaces easier to understand and maintain. Validate untrusted external data with Pydantic or the validation mechanism already established in the project.
from pydantic import BaseModel, ConfigDict, Field
class SearchRequest(BaseModel):
model_config = ConfigDict(extra="forbid")
query: str = Field(min_length=1, max_length=500)
limit: int = Field(default=10, ge=1, le=100)
def normalize_query(request: SearchRequest) -> str:
return request.query.strip()
This example demonstrates a strict request schema with bounded fields. Adapt the validation rules to the actual API contract and domain requirements.
Validation is not authorization
A structurally valid request is not necessarily permitted. Validate the schema first, then enforce the relevant identity, ownership, permissions, and operation policy.
3.3 Asynchronous operations and network requests¶
- Use asynchronous I/O consistently within asynchronous request paths.
- Avoid blocking network, file, or database operations on the event loop.
- Set explicit timeouts for network requests.
- Bound retries and use backoff where appropriate.
- Retry only operations whose semantics make retrying safe.
- Respect provider rate limits and cancellation.
- Avoid creating unbounded concurrent tasks.
For example, use the HTTP client's configured timeout mechanism rather than allowing requests to wait indefinitely.
import httpx
async def fetch_resource(url: str) -> dict[str, object]:
timeout = httpx.Timeout(10.0)
async with httpx.AsyncClient(timeout=timeout) as client:
response = await client.get(url)
response.raise_for_status()
return response.json()
This is an illustrative pattern. Use the HTTP client and timeout conventions already adopted by the repository, and validate the response schema before relying on external fields.
3.4 Exception handling and logging¶
- Catch specific exceptions when recovery is possible.
- Preserve exception causes with
raise ... from excwhen translating errors. - Return safe, consistent public errors.
- Keep diagnostic details in appropriately protected logs.
- Never log access tokens, passwords, API keys, or sensitive payloads.
- Avoid logging complete emails, chat histories, or retrieved documents unless explicitly justified and appropriately protected.
try:
result = await provider.fetch_resource()
except TimeoutError as exc:
logger.warning("Provider request timed out")
raise ProviderUnavailableError(
"The requested service is temporarily unavailable."
) from exc
The exception type and logger are illustrative. Match the actual provider client, error taxonomy, and logging conventions used in the project.
4. AI orchestration and tool safety¶
AI-generated plans and external content must never replace deterministic application controls.
Security boundaries must remain in trusted code
Model output, retrieved documents, emails, chat messages, issue descriptions, and provider responses are untrusted input. Instructions contained in that content must not override system policy, access controls, or tool restrictions.
4.1 Required safeguards¶
- Validate planner and model outputs against explicit schemas.
- Reject unknown, prohibited, or unsupported fields where appropriate.
- Authorize every protected operation using trusted application state.
- Enforce tool allowlists and read-only restrictions in server-side code.
- Require genuine user confirmation for actions that need it; never infer confirmation from an LLM-generated flag.
- Verify resource ownership and access permissions before returning or modifying data.
- Apply appropriate limits to tool arguments, execution time, retries, and returned content.
- Test prompt injection, malicious documents, malformed tool arguments, and unauthorized requests.
- Keep deterministic security policy separate from model-based recommendations.
4.2 Safe tool-execution lifecycle¶
flowchart TD
REQUEST["Incoming Request"]
PARSE["Validate Input and Context"]
PLAN["Generate Proposed Plan"]
SCHEMA["Validate Plan Schema"]
AUTH["Authorize Requested Operation"]
CONFIRM{"Confirmation Required?"}
APPROVE["Verify Explicit User Confirmation"]
EXEC["Execute Approved Operation"]
RESULT["Validate and Filter Result"]
ERROR["Reject or Return Safe Error"]
RESPONSE["Return Response"]
REQUEST --> PARSE
PARSE --> PLAN
PLAN --> SCHEMA
SCHEMA --> AUTH
AUTH --> CONFIRM
CONFIRM -- "No" --> EXEC
CONFIRM -- "Yes" --> APPROVE
APPROVE --> EXEC
EXEC --> RESULT
RESULT --> RESPONSE
PARSE -. "Invalid input" .-> ERROR
SCHEMA -. "Invalid plan" .-> ERROR
AUTH -. "Unauthorized" .-> ERROR
APPROVE -. "Not confirmed" .-> ERROR
classDef normal fill:#dbeafe,stroke:#2563eb,color:#172554
classDef security fill:#ffedd5,stroke:#ea580c,color:#7c2d12
classDef failure fill:#fee2e2,stroke:#dc2626,color:#7f1d1d
class REQUEST,PLAN,EXEC,RESULT,RESPONSE normal
class PARSE,SCHEMA,AUTH,CONFIRM,APPROVE security
class ERROR failure
The confirmation branch is illustrative. Apply confirmation only where required by the operation's risk and product policy. All operations must still pass the applicable authorization checks.
5. API, integration, and data handling¶
API design¶
- Validate request parameters and payloads at the API boundary.
- Use consistent status codes and documented response schemas.
- Keep internal exception messages, stack traces, and implementation details out of public responses.
- Apply authentication, authorization, and resource ownership checks to protected endpoints.
- Avoid breaking existing contracts without an explicit migration or compatibility plan.
- Document material changes to request and response behavior.
Provider integrations¶
- Isolate provider-specific behavior behind explicit adapter interfaces.
- Configure timeouts, retry policies, and rate-limit handling.
- Handle partial failures and malformed provider responses deliberately.
- Do not assume that a successful HTTP response guarantees a valid application-level result.
- Use mocks or fakes for routine unit tests.
- Reserve live-provider tests for controlled environments with appropriate credentials and safeguards.
Secrets and sensitive data¶
| Data category | Required handling |
|---|---|
| Credentials and API keys | Store through approved secret-management mechanisms; never commit them. |
| Environment configuration | Commit safe examples only; exclude real local environment files. |
| Personal and user content | Minimize collection, exposure, retention, and logging. |
| Authentication tokens | Protect in transit and at rest; never expose them in logs or responses. |
| Error diagnostics | Include useful operational context without leaking secrets or sensitive payloads. |
| Test fixtures | Use synthetic or appropriately sanitized data. |
Treat repository history as part of the security boundary
Removing a secret from the latest version of a file does not remove it from Git history. Follow the project's incident procedure for exposed credentials, including revocation and rotation where necessary.
6. Testing standards¶
Every meaningful behavior change should have tests appropriate to its risk and scope. Every fixed bug should have a regression test where practical.
| Test category | What to verify |
|---|---|
| Unit tests | Business logic, validation, transformations, and error handling. |
| Integration tests | Service boundaries, persistence interactions, and adapter contracts. |
| Authorization tests | Unauthorized access, ownership boundaries, and prohibited operations. |
| Negative tests | Malformed inputs, missing fields, invalid states, and provider failures. |
| Boundary tests | Minimum and maximum values, empty collections, limits, and edge conditions. |
| Regression tests | Previously observed bugs remain fixed. |
| AI safety tests | Prompt injection, hostile retrieved content, invalid plans, and unauthorized tool requests. |
Testing expectations¶
- Test success and failure paths.
- Mock external providers in unit tests.
- Avoid dependence on production accounts, real user data, or unstable external services.
- Make tests deterministic and isolate shared state.
- Clean up temporary resources and test-created records.
- Verify that retries, timeouts, and exceptions behave as intended.
- Update tests when API contracts or configuration behavior change.
async def test_user_cannot_access_another_users_resource(
client,
) -> None:
response = await client.get("/resources/another-users-resource")
assert response.status_code in (403, 404)
These examples are illustrative. Use the repository's actual fixtures, routes, authorization policy, and expected status-code conventions.
7. Formatting, linting, and static analysis¶
Use the tools already pinned or configured by the project. Do not introduce a new formatter, linter, type checker, or mandatory CI step without agreement on its configuration and adoption.
| Area | Standard |
|---|---|
| Formatting | Follow the configured formatter or existing repository conventions. |
| Linting | Use the linter and rules already adopted by the project. |
| Type checking | Follow the established typing policy and configured checks. |
| Tests | Run the applicable test suite for the change. |
| CI | Ensure required checks pass before merging. |
| Documentation | Keep examples, configuration references, and setup instructions current. |
Where to find exact commands
Refer to the Engineering Setup guide for verified installation steps and command examples. Do not assume a tool is installed simply because it is commonly used in Python projects.
8. Pull request and code review workflow¶
A pull request should make its purpose, risk, and verification straightforward for reviewers.
Author checklist¶
- The scope and purpose of the change are clearly described.
- Relevant tests cover new behavior and regressions.
- Invalid inputs, failure paths, and boundary cases are considered.
- Authorization and tool allowlists are enforced server-side.
- Secrets and sensitive data are excluded.
- Logging and public errors are safe and actionable.
- Documentation and configuration examples are updated.
- Compatibility and migration implications are documented.
- Required CI checks pass.
- Unrelated changes and generated build artifacts are excluded.
Reviewer checklist¶
- Responsibilities and interfaces remain clear.
- Security decisions do not depend on model output alone.
- Failure handling, timeouts, and retries are appropriate.
- Tests are meaningful, deterministic, and isolated.
- Public API and data-handling changes are compatible or documented.
- The implementation matches the stated purpose and risk.
9. Definition of done¶
A change is ready to merge when its implementation, verification, and operational impact have been reviewed.
-
Implementation
The code follows established conventions, preserves separation of concerns, and handles errors explicitly.
-
Security
Input validation, authorization, secret handling, and applicable tool restrictions are verified.
-
Verification
Relevant tests pass, regressions are covered, and required CI checks are successful.
-
Documentation
Relevant engineering guides, examples, and configuration references reflect the change.
10. Related engineering documentation¶
- Engineering Setup — Development environment, dependencies, and verified commands.
- Repository Structure — Code organization and component locations.
- Configuration — Application settings and configuration conventions.
Maintenance
Update this document when engineering conventions, security requirements, or the project's adopted tooling materially change. Keep normative requirements aligned with the actual repository and CI configuration.
-
Examples in this document illustrate recommended patterns. They are not evidence that a specific library, route, exception class, test fixture, or CI command is already implemented in WhiteLotusAI. ↩