Skip to content

Commit c40c99e

Browse files
committed
docs: update README.md
1 parent b018e3c commit c40c99e

2 files changed

Lines changed: 130 additions & 38 deletions

File tree

ATTRIBUTIONS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ SOFTWARE.
360360

361361
```
362362

363-
## aignostics-foundry-core (0.11.0) - MIT License
363+
## aignostics-foundry-core (0.12.0) - MIT License
364364

365365
🏭 Foundational infrastructure for Foundry components.
366366

README.md

Lines changed: 129 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,13 @@ Or follow the [installation guide](https://mise.jdx.dev/getting-started.html) fo
2828

2929
## Usage
3030

31-
### Initialise the context at application startup
31+
### Quickstart
3232

33-
Call `set_context()` once, before any library code runs, then call `boot()` to
34-
initialise logging, the SSL trust chain, and optional Sentry integration:
33+
`FoundryContext` is the single source of truth for all project-specific values. One call at
34+
application startup makes everything available library-wide — logging, Sentry, database settings,
35+
and more all derive from it automatically.
36+
37+
#### Initialise and boot
3538

3639
```python
3740
# main.py
@@ -42,32 +45,43 @@ set_context(FoundryContext.from_package("myproject"))
4245
boot()
4346
```
4447

45-
`FoundryContext.from_package()` derives everything from package metadata and
46-
environment variables:
48+
`FoundryContext.from_package("myproject")` reads package metadata and environment variables to
49+
populate every field:
4750

4851
- `name`, `version`, `version_full` — from `importlib.metadata`
49-
- `environment` — from `MYPROJECT_ENVIRONMENT``ENV``VERCEL_ENV`
50-
`RAILWAY_ENVIRONMENT``"local"`
52+
- `environment`resolved from env vars in priority order (see [Configuration reference](#configuration-reference) below)
53+
- `env_prefix` (`"MYPROJECT_"`) — used by every settings class; all env vars for this project share this prefix
5154
- `is_container`, `is_cli`, `is_test`, `is_library` — detected automatically
52-
- `env_prefix` (`"MYPROJECT_"`) — used by every settings class in the library
5355

54-
### Access the context from any module
56+
`boot()` initialises logging (loguru), amends the SSL trust chain (truststore + certifi), and
57+
optionally starts Sentry — all in one call.
58+
59+
#### Env file search order
60+
61+
Settings are loaded from the environment **and** from env files. Highest priority first:
62+
63+
1. `.env.{environment}`
64+
2. `.env`
65+
3. `{MYPROJECT_ENV_FILE}` (optional extra file; when the variable is set)
66+
4. `~/.myproject/.env.{environment}`
67+
5. `~/.myproject/.env`
68+
69+
#### Access the context from any module
5570

5671
```python
5772
from aignostics_foundry_core.foundry import get_context
5873

5974
ctx = get_context()
6075
print(f"Running {ctx.name} v{ctx.version_full} in {ctx.environment}")
61-
# → Running myproject v1.2.3+main---run.12345 in staging
76+
# → Running myproject v1.2.3+main-abc1234---run.12345---build.42 in staging
6277
```
6378

64-
`get_context()` raises `RuntimeError` with a clear message if `set_context()`
65-
was never called.
79+
`get_context()` raises `RuntimeError` with a clear message if `set_context()` was never called.
6680

67-
### Pass context explicitly in tests
81+
#### Testing pattern
6882

69-
Never call `set_context()` in tests. Pass a `FoundryContext` directly to each
70-
function via its optional `context` parameter instead:
83+
Never call `set_context()` in tests. Pass a `FoundryContext` directly to functions via their
84+
optional `context` parameter:
7185

7286
```python
7387
from aignostics_foundry_core.foundry import FoundryContext
@@ -77,14 +91,93 @@ ctx = FoundryContext(name="myproject", version="0.0.0", version_full="0.0.0", en
7791
logging_initialize(context=ctx)
7892
```
7993

80-
All public library functions (`logging_initialize`, `sentry_initialize`, `boot`,
81-
`load_modules`, etc.) accept an optional `context` keyword argument and fall
82-
back to `get_context()` when it is `None`.
94+
All public library functions (`logging_initialize`, `sentry_initialize`, `boot`, `load_modules`,
95+
etc.) accept an optional `context` keyword argument and fall back to `get_context()` when it is
96+
`None`.
97+
98+
---
99+
100+
### Configuration reference
101+
102+
All settings classes read from environment variables prefixed with `{PREFIX}` where
103+
`{PREFIX}` = `MYPROJECT_` for a package named `myproject`.
104+
105+
#### Context & deployment environment
83106

84-
### Database
107+
Read directly by `FoundryContext.from_package()` — no settings class.
85108

86-
Once a context is configured via `set_context()`, all database functions work
87-
with no arguments — the URL and pool settings are read from the context:
109+
| Variable | Default | Description |
110+
|---|---|---|
111+
| `{PREFIX}ENVIRONMENT` | `"local"` | Deployment environment name. Highest priority. |
112+
| `ENV` || Fallback environment (lower priority than `{PREFIX}ENVIRONMENT`). |
113+
| `VERCEL_ENV` || Vercel deployment environment (lower priority). |
114+
| `RAILWAY_ENVIRONMENT` || Railway deployment environment (lower priority). |
115+
| `{PREFIX}RUNNING_IN_CONTAINER` | unset | Set to any non-empty value to mark `is_container = True`. |
116+
| `{PREFIX}ENV_FILE` | unset | Path to an additional env file, inserted between the home-dir files and the local `.env`. |
117+
118+
#### Build metadata
119+
120+
Read by `FoundryContext.from_package()` to build `version_full` and `version_with_vcs_ref`. All
121+
optional; most useful in CI.
122+
123+
| Variable | Default | Description |
124+
|---|---|---|
125+
| `VCS_REF` | read from `.git/HEAD` | Branch name or commit SHA. Falls back to reading `.git/HEAD` when project path is found. |
126+
| `COMMIT_SHA` | `"unknown"` | Full commit SHA; first 7 chars used. |
127+
| `BUILD_DATE` | `"unknown"` | Build date string. |
128+
| `CI_RUN_ID` | `"unknown"` | CI system run ID. |
129+
| `CI_RUN_NUMBER` | `"unknown"` | CI system build number. |
130+
| `BUILDER` | `"uv"` | Build tool name. |
131+
132+
When any of these variables is set, `version_full` gains a `+…` suffix, e.g.
133+
`1.2.3+main-abc1234---run.12345---build.42`.
134+
135+
#### Logging (`{PREFIX}LOG_`)
136+
137+
Settings class: `LogSettings`
138+
139+
| Variable | Default | Description |
140+
|---|---|---|
141+
| `{PREFIX}LOG_LEVEL` | `INFO` | Log level: `CRITICAL`, `ERROR`, `WARNING`, `SUCCESS`, `INFO`, `DEBUG`, or `TRACE`. |
142+
| `{PREFIX}LOG_STDERR_ENABLED` | `true` | Enable logging to stderr. |
143+
| `{PREFIX}LOG_FILE_ENABLED` | `false` | Enable logging to a file. |
144+
| `{PREFIX}LOG_FILE_NAME` | platform log dir | Path to the log file (validated on startup when `FILE_ENABLED` is true). |
145+
| `{PREFIX}LOG_REDIRECT_LOGGING` | `true` | Redirect stdlib `logging` to loguru via `InterceptHandler`. |
146+
147+
#### Sentry (`{PREFIX}SENTRY_`)
148+
149+
Settings class: `SentrySettings`. Sentry is only initialised when `ENABLED=true` **and** `DSN` is
150+
set.
151+
152+
| Variable | Default | Description |
153+
|---|---|---|
154+
| `{PREFIX}SENTRY_ENABLED` | `false` | Enable Sentry error and performance monitoring. |
155+
| `{PREFIX}SENTRY_DSN` | unset | Sentry DSN (must be an HTTPS URL with a valid `ingest.*.sentry.io` domain). |
156+
| `{PREFIX}SENTRY_DEBUG` | `false` | Enable Sentry SDK debug mode. |
157+
| `{PREFIX}SENTRY_SEND_DEFAULT_PII` | `false` | Include personally-identifiable information in events. |
158+
| `{PREFIX}SENTRY_MAX_BREADCRUMBS` | `50` | Maximum breadcrumbs stored per event. |
159+
| `{PREFIX}SENTRY_SAMPLE_RATE` | `1.0` | Error event sample rate (0.0–1.0). |
160+
| `{PREFIX}SENTRY_TRACES_SAMPLE_RATE` | `0.1` | Transaction/trace sample rate. |
161+
| `{PREFIX}SENTRY_PROFILES_SAMPLE_RATE` | `0.1` | Profiler sample rate. |
162+
| `{PREFIX}SENTRY_PROFILE_SESSION_SAMPLE_RATE` | `0.1` | Profile session sample rate. |
163+
| `{PREFIX}SENTRY_PROFILE_LIFECYCLE` | `"trace"` | Profile lifecycle mode: `"trace"` or `"manual"`. |
164+
| `{PREFIX}SENTRY_ENABLE_LOGS` | `true` | Forward log records to Sentry. |
165+
166+
#### Database (`{PREFIX}DB_`)
167+
168+
Settings class: `DatabaseSettings`. Database configuration is only activated when `{PREFIX}DB_URL`
169+
is present (in the environment or in an env file).
170+
171+
| Variable | Required | Default | Description |
172+
|---|---|---|---|
173+
| `{PREFIX}DB_URL` | to activate || Full async database connection URL (e.g. `postgresql+asyncpg://user:pass@host/db`). Always access via `DatabaseSettings.get_url()`. |
174+
| `{PREFIX}DB_POOL_SIZE` | no | `10` | SQLAlchemy connection pool size. |
175+
| `{PREFIX}DB_POOL_MAX_OVERFLOW` | no | `10` | Max connections above pool size. |
176+
| `{PREFIX}DB_POOL_TIMEOUT` | no | `30.0` | Seconds to wait for a pool connection. |
177+
| `{PREFIX}DB_NAME` | no | unset | Override the database name in the URL path at runtime. |
178+
179+
Once a context is configured via `set_context()`, all database functions work with no arguments —
180+
the URL and pool settings are read from the context:
88181

89182
```python
90183
from aignostics_foundry_core.database import init_engine, cli_run_with_db, with_engine
@@ -106,17 +199,6 @@ async def my_job(): ...
106199
async def my_other_job(): ...
107200
```
108201

109-
`FoundryContext.from_package()` activates database configuration automatically
110-
when the following environment variables are present:
111-
112-
| Variable | Required | Description |
113-
|---|---|---|
114-
| `{PREFIX}DB_URL` | yes (to activate) | Full database connection URL |
115-
| `{PREFIX}DB_POOL_SIZE` | no | Connection pool size (default `10`) |
116-
| `{PREFIX}DB_MAX_OVERFLOW` | no | Max pool overflow (default `10`) |
117-
| `{PREFIX}DB_POOL_TIMEOUT` | no | Pool wait timeout in seconds (default `30.0`) |
118-
| `{PREFIX}DB_NAME` | no | Override database name in the URL path |
119-
120202
In tests, construct `DatabaseSettings` directly instead of setting env vars:
121203

122204
```python
@@ -126,13 +208,23 @@ from tests.conftest import make_context
126208
ctx = make_context(database=DatabaseSettings(_env_prefix="TEST_DB_", url="sqlite+aiosqlite:///test.db"))
127209
```
128210

129-
### Health API
211+
#### Authentication (`{PREFIX}AUTH_`)
130212

131-
```python
132-
from aignostics_foundry_core.health import Health, HealthStatus
213+
Settings class: `AuthSettings`. Both fields are required — no defaults. Only needed when using
214+
`aignostics_foundry_core.api.auth` dependencies.
133215

134-
health = Health(status=HealthStatus.UP)
135-
```
216+
| Variable | Required | Description |
217+
|---|---|---|
218+
| `{PREFIX}AUTH_INTERNAL_ORG_ID` | yes | Auth0 organization ID identifying the internal org (used by `require_internal`). |
219+
| `{PREFIX}AUTH_AUTH0_ROLE_CLAIM` | yes | JWT claim name containing the user's role (e.g. `https://myapp.example.com/roles`). |
220+
221+
#### Console
222+
223+
Read directly from the environment — no settings class.
224+
225+
| Variable | Default | Description |
226+
|---|---|---|
227+
| `{PREFIX}CONSOLE_WIDTH` | auto-detect | Override Rich console width (integer, characters). Defaults to terminal width or 80 in non-TTY environments. |
136228

137229
## Further Reading
138230

0 commit comments

Comments
 (0)