Skip to content

Installation and Setup

This guide will walk you through installing the castlecraft-engineer library and configuring the necessary environment for its operation.

Package Installation

You can install castlecraft-engineer using your preferred Python package manager. If you are using uv (as recommended for projects using this library), you can add it to your pyproject.toml and run uv sync.

uv pip install castlecraft-engineer

Alternatively, using pip:

pip install castlecraft-engineer

This will also install its core dependencies, which include (as referenced in pyproject.toml):

  • punq: Used for dependency injection.
  • cryptography: For cryptographic operations like data encryption/decryption.
  • pyjwt[crypto]: For handling JSON Web Tokens (JWTs), particularly for OIDC authentication.
  • sqlmodel: For database interactions, defining data models, and ORM capabilities.

You can find the full list of dependencies and their versions in the pyproject.toml file of the library.

Environment Variable Configuration

castlecraft-engineer relies on several environment variables for its configuration. These variables control database connections, authentication mechanisms, caching, and security features.

It's recommended to use a .env file in your project root to manage these settings. An example structure can often be found in a file like examples/.env.example if provided by the project.

Here's a breakdown of essential environment variables:

Database Configuration

These variables are used by castlecraft_engineer.database.connection to establish database connections. You need to provide the complete database connection string.

  • SQL_CONNECTION_STRING: The full SQLAlchemy connection string for synchronous operations (this is the actual environment variable key to set).
    • Default if not set: "sqlite:///db.sqlite3"
  • SQL_ASYNC_CONNECTION_STRING: The full SQLAlchemy connection string for asynchronous operations, typically with an async driver (this is the actual environment variable key to set).
    • Default if not set: "sqlite+aiosqlite:///db.sqlite3"
  • ENABLE_SQL_LOG: (Optional) Set to true (or any non-empty string) to enable SQLAlchemy logging of SQL statements (this is the actual environment variable key to set). If not set or set to an empty string, logging is disabled.

Example for PostgreSQL:

# For PostgreSQL, you would define the full connection strings:
SQL_CONNECTION_STRING="postgresql://your_user:your_password@localhost:5432/your_db"
SQL_ASYNC_CONNECTION_STRING="postgresql+asyncpg://your_user:your_password@localhost:5432/your_db"
ENABLE_SQL_LOG="false"

Example for SQLite (local development):

SQL_CONNECTION_STRING="sqlite:///./my_app_sync.db"
SQL_ASYNC_CONNECTION_STRING="sqlite+aiosqlite:///./my_app_async.db"
ENABLE_SQL_LOG="true"

Authentication (OIDC) Configuration

These variables are used by castlecraft_engineer.application.auth for OpenID Connect (OIDC) based authentication. Set these exact keys in your environment:

  • CLIENT_ID: Your OIDC client ID (corresponds to ENV_CLIENT_ID in common.env).
  • CLIENT_SECRET: Your OIDC client secret (corresponds to ENV_CLIENT_SECRET in common.env).
  • JWKS_URL: The URL to your OIDC provider's JWKS endpoint (corresponds to ENV_JWKS_URL in common.env).
  • INTROSPECT_URL: (Optional) Direct URI to the token introspection endpoint (corresponds to ENV_INTROSPECT_URL in common.env).
  • USERINFO_URL: (Optional) Direct URI to the userinfo endpoint (corresponds to ENV_USERINFO_URL in common.env).
  • ALLOWED_AUD: (Optional) The audience claim for JWT validation (corresponds to ENV_ALLOWED_AUD in common.env).
  • ENABLE_VERIFY_ID_TOKEN: (Optional) Set to true to enable ID token verification. Defaults to true if not set (corresponds to ENV_ENABLE_VERIFY_ID_TOKEN in common.env).
  • ENABLE_INTROSPECT_TOKEN: (Optional) Set to true to enable token introspection. Defaults to false if not set (corresponds to ENV_ENABLE_INTROSPECT_TOKEN in common.env).
  • ENABLE_FETCH_USERINFO: (Optional) Set to true to enable fetching userinfo. Defaults to false if not set (corresponds to ENV_ENABLE_FETCH_USERINFO in common.env).
  • INTROSPECT_REQUIRES_AUTH: (Optional) Set to true if introspection endpoint requires client auth. Defaults to true if not set (corresponds to ENV_INTROSPECT_REQUIRES_AUTH in common.env).
  • INTROSPECT_TOKEN_KEY: (Optional) Key for the token in the introspection request. Defaults to token (corresponds to ENV_INTROSPECT_TOKEN_KEY in common.env).

Example:

CLIENT_ID="your_client_id"
CLIENT_SECRET="your_client_secret"
JWKS_URL="https://your-oidc-provider.com/jwks"
ALLOWED_AUD="your_api_audience"

Cryptography Configuration

Used by castlecraft_engineer.common.crypto for encrypting and decrypting data.

  • SECRETS_ENCRYPTION_KEY: A 32-byte (256-bit) AES key, base64 encoded (this is the actual environment variable key to set, corresponds to ENV_SECRETS_ENCRYPTION_KEY in common.env). This key is crucial for securing sensitive data. Ensure this is kept secret and is properly backed up.

Example (generate a new one for production):

SECRETS_ENCRYPTION_KEY="your_base64_encoded_32_byte_secret_key" # e.g., $(openssl rand -base64 32)

Redis Cache Configuration

Used by castlecraft_engineer.caching.cache and castlecraft_engineer.common.redis for caching.

  • CACHE_REDIS_URL: The connection URL for your Redis instance (e.g., redis://localhost:6379/0). Defaults to redis://localhost:6379 (corresponds to ENV_CACHE_REDIS_URL).
  • ENABLE_CACHE_REDIS_CLUSTER: Set to true if using Redis Sentinel/Cluster for high availability. Defaults to false (corresponds to ENV_ENABLE_CACHE_REDIS_CLUSTER).
  • CACHE_REDIS_SENTINELS: Comma-separated list of sentinel URIs if ENABLE_CACHE_REDIS_CLUSTER is true (e.g., redis://host1:port,redis://host2:port) (corresponds to ENV_CACHE_REDIS_SENTINELS).
  • CACHE_REDIS_MASTER_SERVICE: The name of the Redis master service in Sentinel configuration (corresponds to ENV_CACHE_REDIS_MASTER_SERVICE).
  • CACHE_REDIS_SENTINEL_USERNAME: (Optional) Username for Sentinel authentication (corresponds to ENV_CACHE_REDIS_SENTINEL_USERNAME).
  • CACHE_REDIS_SENTINEL_PASSWORD: (Optional) Password for Sentinel authentication (corresponds to ENV_CACHE_REDIS_SENTINEL_PASSWORD).
  • CACHE_REDIS_MASTER_USERNAME: (Optional) Username for Redis master authentication when using Sentinel (corresponds to ENV_CACHE_REDIS_MASTER_USERNAME).
  • CACHE_REDIS_MASTER_PASSWORD: (Optional) Password for Redis master authentication when using Sentinel (corresponds to ENV_CACHE_REDIS_MASTER_PASSWORD).

Example (Standard Redis):

CACHE_REDIS_URL="redis://localhost:6379/0"
ENABLE_CACHE_REDIS_CLUSTER="false"

Example (Redis Sentinel):

ENABLE_CACHE_REDIS_CLUSTER="true"
CACHE_REDIS_SENTINELS="sentinel1:26379,sentinel2:26379,sentinel3:26379"
CACHE_REDIS_MASTER_SERVICE="mymaster"
# Optional credentials
# CACHE_REDIS_SENTINEL_USERNAME="sentinel_user"
# CACHE_REDIS_SENTINEL_PASSWORD="sentinel_password"
# CACHE_REDIS_MASTER_USERNAME="redis_user"
# CACHE_REDIS_MASTER_PASSWORD="redis_password"

Example .env File (based on a typical examples/.env.example)

Create a .env file in your project root. It might look something like this:

# Database Configuration (provide full connection strings)
SQL_CONNECTION_STRING="sqlite:///./dev_sync.db"
SQL_ASYNC_CONNECTION_STRING="sqlite+aiosqlite:///./dev_async.db"
ENABLE_SQL_LOG="false"

# OIDC Configuration
CLIENT_ID="YOUR_CLIENT_ID"
CLIENT_SECRET="YOUR_CLIENT_SECRET"
JWKS_URL="YOUR_JWKS_URL"
ALLOWED_AUD="YOUR_API_AUDIENCE"
# INTROSPECT_URL=
# USERINFO_URL=
# ENABLE_VERIFY_ID_TOKEN=true
# ENABLE_INTROSPECT_TOKEN=false
# ENABLE_FETCH_USERINFO=false

# Cryptography
SECRETS_ENCRYPTION_KEY="generate_a_strong_base64_encoded_32_byte_key_here"

# Redis Cache
CACHE_REDIS_URL="redis://localhost:6379/0"
ENABLE_CACHE_REDIS_CLUSTER="false"
# CACHE_REDIS_SENTINELS=
# CACHE_REDIS_MASTER_SERVICE=
# CACHE_REDIS_SENTINEL_USERNAME=
# CACHE_REDIS_SENTINEL_PASSWORD=
# CACHE_REDIS_MASTER_USERNAME=
# CACHE_REDIS_MASTER_PASSWORD=
Important: For production, ensure all sensitive values (passwords, secret keys) are securely managed, potentially using a secrets management system rather than committing them directly into a .env file in your repository.

Initial Database Schema Setup

castlecraft-engineer provides a CLI command to help bootstrap your initial database schema based on your SQLModel definitions. This command is defined in castlecraft_engineer.database.commands and accessible via the main CLI entrypoint in castlecraft_engineer.commands.entrypoint.

To create the database tables:

  1. Ensure your environment variables for database connection are correctly set (e.g., in your .env file, which should be loaded by your application or the CLI environment).
  2. Make sure your SQLModel definitions are discoverable by the application (e.g., imported in a module that gets loaded when the application starts or when the CLI command runs).
  3. Run the bootstrap command from your project's root directory:

    python -m castlecraft_engineer.commands.entrypoint bootstrap
    

This command will connect to the database specified in your environment variables and create all tables defined by your SQLModels that have been registered with SQLModel.metadata.

After these steps, your castlecraft-engineer library should be installed and configured, ready for you to build your application. Refer to the Quickstart guide for the next steps.

CAUTION: Bootstrap of tables is for convenience of developers. In Production use alembic for migrations and bootstrap.