Skip to main content

Secure and extensible credential management SDK for Python applications.

Project description

infra-core-sdk

Version Python License

infra-core-sdk is a small infrastructure SDK for Python projects that need:

  • predictable project root resolution
  • centralized path configuration
  • encrypted credential setup and loading
  • typed, reusable runtime filesystem operations

Current published version: 0.3.0


Why this SDK exists

Most internal Python projects eventually reinvent the same infrastructure code:

  • hardcoded paths scattered across modules
  • inconsistent root discovery between local runs, scripts, CI, and installed packages
  • ad-hoc secret files and manual key handling
  • duplicated filesystem setup logic

infra-core-sdk turns those concerns into explicit, reusable building blocks.

Instead of solving paths and credentials separately in every project, you define them once and consume them through a consistent API.


What the SDK gives you

Root-aware path resolution

Resolve paths relative to the real project root instead of relying on fragile cwd assumptions.

The SDK supports:

  • marker-based root discovery
  • explicit start_path configuration
  • installed-package fallback for consumer scripts

Centralized path management

Define your important paths once and resolve or create them anywhere in your codebase.

Typical examples:

  • secrets directory
  • key file
  • credentials files
  • logs
  • cache directories
  • external absolute paths

Secure credentials flow

Store credentials as typed objects, encrypt them with Fernet, and load them back through a predictable setup/load flow.

Better reuse across projects

This SDK is designed to be installed and consumed by other Python projects, not just used from inside this repository.


Installation

Latest published version:

pip install infra-core-sdk==0.3.0

Or install the latest available release:

pip install infra-core-sdk

Python support policy:

  • package metadata allows Python >=3.12
  • practical validation has been executed on Python 3.14
  • versions above 3.12 other than 3.14 have not yet been explicitly tested

Quick Example

This is the simplest end-to-end flow:

from dataclasses import dataclass

from infra_core import (
    CredentialsLoader,
    CredentialsSetupService,
    FernetEncryption,
    PathConfig,
    RootConfig,
    RootConfigProvider,
)
from infra_core.core.path.path_config_provider import PathConfigProvider
from infra_core.core.path.path_definition import PathDefinition
from infra_core.credentials.models.base_credentials import BaseCredentials


@dataclass(frozen=True)
class MyCredentials(BaseCredentials):
    api_token: str


RootConfigProvider.set(
    RootConfig(
        markers=(".git", "pyproject.toml"),
    )
)

path_config = PathConfig()
path_config = path_config.addPath("secrets", PathDefinition("secrets"))
path_config = path_config.addPath("secret_key", PathDefinition("secrets/key.key"))
path_config = path_config.addPath(
    "credentials",
    PathDefinition("secrets/{name}.json"),
)

PathConfigProvider.set(path_config)

setup = CredentialsSetupService(FernetEncryption)
setup.setup(MyCredentials(api_token="123"), name="default")

creds = CredentialsLoader.load(
    MyCredentials,
    FernetEncryption,
    name="default",
)

print(creds.api_token)

Generated structure:

project_root/
├── secrets/
│   ├── key.key
│   └── default.json

If you want a runnable example from this repository, see:


Core Concepts

1. Root resolution

The SDK resolves the consumer project's root using markers such as:

.git
pyproject.toml
requirements.txt

You can also provide an explicit start_path:

from pathlib import Path

from infra_core import RootConfig, RootConfigProvider

RootConfigProvider.set(
    RootConfig(
        markers=(".git", "pyproject.toml"),
        start_path=Path(__file__).resolve().parent,
    )
)

This is especially useful when your application may run from a different cwd.

2. Path definitions

Each path is registered as a PathDefinition:

PathDefinition(path: str, use_root: bool = True)

Behavior:

Mode Meaning
use_root=True path is relative to the resolved project root
use_root=False path must be absolute

Template variables are supported:

PathDefinition("secrets/{name}.json")

3. Credentials lifecycle

The default flow is:

SETUP
  -> ensure key exists
  -> encrypt typed credentials
  -> save encrypted file

LOAD
  -> try environment variables first
  -> fallback to encrypted file
  -> return typed credentials object

Step-by-Step Usage

1. Define a credentials model

from dataclasses import dataclass

from infra_core.credentials.models.base_credentials import BaseCredentials


@dataclass(frozen=True)
class MyCredentials(BaseCredentials):
    api_token: str
    client_id: str

2. Configure root behavior

from infra_core import RootConfig, RootConfigProvider

RootConfigProvider.set(
    RootConfig(
        markers=(".git", "pyproject.toml"),
    )
)

3. Configure paths

from pathlib import Path

from infra_core import PathConfig
from infra_core.core.path.path_config_provider import PathConfigProvider
from infra_core.core.path.path_definition import PathDefinition

config = PathConfig()

config = config.addPath("secrets", PathDefinition("secrets"))
config = config.addPath("secret_key", PathDefinition("secrets/key.key"))
config = config.addPath("credentials", PathDefinition("secrets/{name}.json"))

absolute_logs = str(Path.cwd() / "logs" / "app")
config = config.addPath(
    "logs",
    PathDefinition(absolute_logs, use_root=False),
)

PathConfigProvider.set(config)

4. Setup encrypted credentials

from infra_core import CredentialsSetupService, FernetEncryption

setup = CredentialsSetupService(FernetEncryption)

setup.setup(
    MyCredentials(
        api_token="123",
        client_id="abc",
    ),
    name="default",
)

5. Load credentials

from infra_core import CredentialsLoader, FernetEncryption

creds = CredentialsLoader.load(
    MyCredentials,
    FernetEncryption,
    name="default",
)

print(creds.api_token)
print(creds.client_id)

Public API Highlights

Top-level imports currently supported:

from infra_core import (
    CredentialsLoader,
    CredentialsService,
    CredentialsSetupService,
    FernetEncryption,
    PathConfig,
    PathManager,
    RootConfig,
    RootConfigProvider,
    RootResolver,
)

Useful subpackage imports:

from infra_core.core.root import RootConfig, RootConfigProvider, RootResolver
from infra_core.exceptions import SDKError
from infra_core.credentials.exceptions import CredentialsError

Path Management

Resolve paths:

from infra_core import PathManager

manager = PathManager()

print(manager.getPath("secrets"))
print(manager.getPath("credentials", name="default"))

Ensure resources exist:

manager.ensurePathExists("secrets")
manager.ensurePathExists(
    "credentials",
    variables={"name": "default"},
    is_file=True,
)

Delete files or directories:

manager.deleteResource("credentials", name="default")
manager.deleteResource("secrets")

Multiple Credential Profiles

The same key can be reused for multiple profiles:

setup.setup(..., name="aws")
setup.setup(..., name="stripe")
setup.setup(..., name="internal")

Then load the profile you need:

aws = CredentialsLoader.load(MyCredentials, FernetEncryption, name="aws")

Custom Encryption

Fernet is the default recommendation:

from infra_core import FernetEncryption

You can also inject a custom encryption class:

class CustomEncryption:
    def __init__(self, key: bytes) -> None:
        self._key = key

    def encrypt(self, value: str) -> str:
        return value

    def decrypt(self, value: str) -> str:
        return value

Use it the same way:

setup = CredentialsSetupService(CustomEncryption)
creds = CredentialsLoader.load(MyCredentials, CustomEncryption, name="default")

Important Rules

Do not manually manage keys in your application flow.

Use:

CredentialsSetupService(...)

Do not use relative paths with use_root=False.

Invalid:

PathDefinition("logs", use_root=False)

Valid:

from pathlib import Path

PathDefinition(str(Path.cwd() / "logs"), use_root=False)

Development

pip install -e .[dev]
python -m pytest
python -m mypy src
python -m black .
python -m build
python -m twine check dist/*

Architecture Overview

infra_core/
  core/
    path/
    root/
  credentials/
    models/
    services/
    setup/
  exceptions/
  security/

Responsibility split:

  • core.root: project root discovery
  • core.path: path definitions, configuration, and runtime operations
  • credentials.models: typed credential objects
  • credentials.services: save/load flows
  • credentials.setup: initial setup and key lifecycle
  • security: encryption implementations

License

MIT


Author

Rafael Cavalcante

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

infra_core_sdk-0.3.0.tar.gz (28.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

infra_core_sdk-0.3.0-py3-none-any.whl (36.6 kB view details)

Uploaded Python 3

File details

Details for the file infra_core_sdk-0.3.0.tar.gz.

File metadata

  • Download URL: infra_core_sdk-0.3.0.tar.gz
  • Upload date:
  • Size: 28.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for infra_core_sdk-0.3.0.tar.gz
Algorithm Hash digest
SHA256 f513c162c043048a67a6bf443b80076b7a9073374a28fdff3bab4c53748ad677
MD5 f227272da4821f70633a2956773dc7a2
BLAKE2b-256 2665ac60cdbb697e45ae17765530cc7417b7a4320e884aea6d83c6519916abd8

See more details on using hashes here.

File details

Details for the file infra_core_sdk-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: infra_core_sdk-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 36.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for infra_core_sdk-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 16f82445de3dc3b7da19558d19a6f5ab2afb808fd5056d586efd7c21f905ee8e
MD5 fe273c84bf980795e6a0e77236996ce1
BLAKE2b-256 93c4c99185d2e447e4be4754359b9516357f29039dfd28df51b23d3c34e85995

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page