Metadata-Version: 2.5
Name: beacon-otel
Version: 1.2.3
Summary: Beacon Python auto-instrumentation distribution
Project-URL: Homepage, https://github.com/beacon-observability/beacon-python/tree/main/beacon-otel
Project-URL: Repository, https://github.com/beacon-observability/beacon-python
Author: Beacon Observability
License-Expression: Apache-2.0
License-File: LICENSE
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Requires-Python: >=3.10
Requires-Dist: opentelemetry-api==1.45.1
Requires-Dist: opentelemetry-exporter-otlp==1.45.1
Requires-Dist: opentelemetry-instrumentation-threading==0.66b1
Requires-Dist: opentelemetry-instrumentation==0.66b1
Requires-Dist: opentelemetry-sdk==1.45.1
Requires-Dist: packaging>=24
Requires-Dist: wrapt<3,>=1.17
Provides-Extra: django
Requires-Dist: opentelemetry-instrumentation-django==0.66b1; extra == 'django'
Provides-Extra: fastapi
Requires-Dist: opentelemetry-instrumentation-fastapi==0.66b1; extra == 'fastapi'
Provides-Extra: flask
Requires-Dist: opentelemetry-instrumentation-flask==0.66b1; extra == 'flask'
Provides-Extra: profiling
Requires-Dist: beacon-profiling==1.2.3; extra == 'profiling'
Provides-Extra: requests
Requires-Dist: opentelemetry-instrumentation-requests==0.66b1; extra == 'requests'
Description-Content-Type: text/markdown

# Beacon Python

`beacon-otel` is the main Beacon Python installation package. This source tree
builds version `1.2.3`.

Install the main package together with the auto-instrumentation plugins required by your framework. For example, a FastAPI application can install the current stable version with:

```bash
pip install 'beacon-otel[fastapi]==1.2.3'
```

To enable profiling, install:

```bash
pip install 'beacon-otel[fastapi,profiling]==1.2.3'
```

Activate the virtual environment where Beacon is installed, configure the OTLP endpoint, and then start the application. You can also pass the full path of an executable in that virtual environment after `beacon`:

```bash
export OTEL_SERVICE_NAME=my-service
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
beacon uvicorn myapp:app
```

`beacon --version` displays the Beacon Python product version. Optional dependencies are currently provided for `requests`, `flask`, `fastapi`, and `django`; auto-instrumentation packages for other frameworks can be installed separately according to the official OpenTelemetry documentation. Package availability does not mean that every framework and runtime environment is supported by a stable Beacon release. Refer to the release notes and acceptance records for the supported scope of each version.

Optional dependencies install only the corresponding auto-instrumentation plugins; the application must install the framework itself. Do not install another profiling distribution that registers a conflicting auto-instrumentation entry point in the same Python environment.

By default, `beacon` selects the Beacon OpenTelemetry distro and configurator and uses the standard `OTEL_*` environment variables. Explicitly configured `OTEL_PYTHON_DISTRO` or `OTEL_PYTHON_CONFIGURATOR` values are not overwritten. Profiling is disabled by default; see the [profiling documentation](../sdk-extension/beacon-profiling/README.rst) to enable it.

## Beacon Security

Beacon Python `1.1.0` includes opt-in Beacon Security in the same `beacon-otel`
wheel and command. It does not require a second Security distribution or a
second version lifecycle.

Security currently supports standard-GIL CPython 3.11 through 3.14. The master
switch enables its lifecycle and runtime SBOM; an application-module prefix is
also required for modeled data-flow collection:

```bash
export BEACON_SECURITY_ENABLED=true
export BEACON_SECURITY_PYTHON_INCLUDE=orders
export OTEL_SERVICE_NAME=orders
export OTEL_RESOURCE_ATTRIBUTES=service.namespace=shop
export OTEL_LOGS_EXPORTER=otlp
export OTEL_EXPORTER_OTLP_PROTOCOL=grpc
export OTEL_EXPORTER_OTLP_ENDPOINT=http://127.0.0.1:4317

beacon uvicorn orders.asgi:application --host 0.0.0.0 --port 8000
```

`BEACON_SECURITY_PYTHON_INCLUDE` contains Python module prefixes, not file-system
paths. Without it, the enabled lifecycle can report the runtime SBOM but does
not transform application code or collect findings. The runtime transforms only
included application modules and excludes the standard library, OpenTelemetry,
Beacon Security itself, and explicitly configured prefixes. Findings are
bounded modeled-flow observations or candidate risks, not confirmed
vulnerability reports.

Call rewriting preserves the caller module for standard-library namedtuple,
typing and Enum factories. Standard logging and `warnings.warn` ignore Security
helper frames when interpreting `stacklevel`, including aliases and partials.
Custom frame-inspecting callables and exception tracebacks can still expose
the call observation helpers.

Collection eligibility (the enabled flag, include selector and runtime support)
is captured when a Security runtime starts; environment changes require a
restart. Control-file pause/resume and verification runs remain dynamic.

String and bytes `+=` propagation includes variable, attribute and subscript
targets. Target reads, right-hand expressions and writes retain native order;
setters can observe the propagated marks. Generator suspension in a right-hand
expression reports `generator_iadd_propagation`; marked inputs to custom
`__iadd__` implementations report `unmodeled_iadd`.

Runtime SBOM collection is enabled by default only after Security itself is
enabled. Findings and dependency inventories use the existing OpenTelemetry Logs
pipeline. Local files are off by default:

| Environment variable | Default | Purpose |
| --- | --- | --- |
| `BEACON_SECURITY_ENABLED` | `false` | Enable the Security lifecycle and its runtime SBOM. |
| `BEACON_SECURITY_PYTHON_INCLUDE` | empty | Comma-separated application module prefixes required for finding collection. |
| `BEACON_SECURITY_PYTHON_EXCLUDE` | empty | Comma-separated exclusions, which take precedence. |
| `BEACON_SECURITY_SBOM_ENABLED` | `true` | Enable runtime SBOM within an enabled lifecycle. |
| `BEACON_SECURITY_SBOM_REFRESH_SECONDS` | `300` | Delay after each completed inventory collection. |
| `BEACON_SECURITY_SBOM_CACHE_SECONDS` | `300` | Reuse unchanged artifact metadata. |
| `BEACON_SECURITY_LOCAL_OUTPUT_ENABLED` | `false` | Enable process-local diagnostic files. |
| `BEACON_SECURITY_OUTPUT` | `./beacon-security-output/<instance-id>` | Diagnostic snapshot directory. |
| `BEACON_SECURITY_EVIDENCE_FILE` | unset | Optional diagnostic JSONL file. |

For local inspection without an OTLP backend, additionally set
`BEACON_SECURITY_LOCAL_OUTPUT_ENABLED=true`, choose the output paths, and set
`OTEL_LOGS_EXPORTER=none`. Local files are diagnostic evidence, not durable or
cluster-wide delivery.
`BEACON_SECURITY_EVIDENCE_FILE` can be enabled independently of the other local
snapshots.

Gunicorn must initialize OpenTelemetry after each worker fork. Do not prefix
this command with `beacon` or `opentelemetry-instrument`, and do not enable
`preload_app`:

```bash
gunicorn -c python:beacon_security.gunicorn orders.wsgi:application
```

For Kubernetes, bake the `beacon-otel` release into the application
image and use the checked-in [Deployment example](examples/kubernetes/deployment.yaml).
The example needs only the normal application command, environment variables,
and an OTLP Collector endpoint; it deliberately leaves local output disabled.

The language-neutral event, identity, configuration, fingerprint, and runtime
SBOM contract is maintained in
[beacon-security-spec](https://github.com/beacon-observability/beacon-security-spec).
This wheel carries an immutable contract revision in
[`security-spec.properties`](src/beacon_security/security-spec.properties).

### Security telemetry v2

The OTel Logs output contains only two INFO events:

| `source` | `event_name` | Trigger |
| --- | --- | --- |
| `beacon_security` | `beacon.security.finding` | One matched finding per request and fingerprint. |
| `beacon_security_sbom` | `beacon.security.sbom.inventory` | Every successful dependency collection, including unchanged and empty lists. |

The inventory worker starts asynchronously and waits 300 seconds after each
collection by default (`BEACON_SECURITY_SBOM_REFRESH_SECONDS`). A failed or
incomplete collection emits nothing, leaving the last successful list intact.
Each event contains `instance_id`, `observed_at`, process `started_at`,
`uptime_ms`, and the complete current `dependencies` list. Each loaded library
is identified by `name`, `version`, and an MD5 identity key over the compact
JSON array `[name,version]`; the key is not a content digest. Large inventories
use `part_index` and `part_count` only when split. Consumers should replace the
previous list only after all parts for one `instance_id + observed_at` arrive.

Findings retain a stable `finding_id` (fingerprint v1), a per-request
`occurrence_id`, rule, sink, attack-evidence status and reason, request and Trace
correlation, and sampled propagation evidence. The normal full-evidence sample
interval is 300 seconds (`BEACON_SECURITY_FINDINGS_SAMPLE_SECONDS`). An
unsampled occurrence still reports the finding with `evidence_sampled=false`
and `evidence_sample_reason=interval`; this is not a real truncation. Only
actual capacity or serialization loss sets `truncated=true`.

The exported body omits service/runtime/code fields already in the OTel
Resource, empty optional fields, fixed placeholders, `evidence_id`, and online
`occurrences_total`. Resolved `component` data directly carries
`name`/`version`/`hash`; unresolved components are omitted. The backend can
deduplicate by `instance_id + occurrence_id` and group by `finding_id`.
Security does not send separate health, summary, collection-failure, dropped,
or truncated-record diagnostic events. Queues and rate budgets are bounded;
failed or oversized events can be dropped. Stronger attack evidence retains a
20% security-channel budget reserve. OTel API emission is not a backend ACK.
Full representative evidence and cumulative finding counters remain in memory
only when local diagnostic output is enabled. Local `control.json` exception
scopes match the stable `finding_id`, so a process restart does not invalidate
an exception. The local CycloneDX file is the current snapshot with version 1;
no SBOM history file is maintained.

### Request body tracking budgets

Raw request-body byte buffers have a separate reservation inside the existing
request/process tracking limits. By default they may use one quarter of the
request byte and object budgets, leaving capacity for parsed JSON/form fields.
Set `BEACON_SECURITY_MAX_BODY_BUFFER_BYTES` to adjust the raw byte reservation
(at most the request's total byte limit). Oversized/excess raw buffers are not
retained and produce a `raw_body_buffer_budget` collection gap; later parsed
fields can still be tracked and analyzed. Raw-body coverage is therefore
bounded explicitly, and unchanged request/process memory limits still apply.

### Request-specific attack evidence

A finding's `attack_evidence` status is `unknown` for unsupported or imprecise
analysis, `no_evidence` when supported analysis finds no exploitation evidence,
or `suspected` when tainted input controls supported syntax. Reasons are bounded
machine-readable values without captured request data. An invocation, normal
return, or HTTP status cannot establish
successful exploitation. `no_evidence` is not a safety verdict.

Set `BEACON_SECURITY_ANALYSIS_SQL_DIALECT=ansi` to enable the bounded ANSI lexical
subset; the default is `unknown`. It supports single/double quoted strings and
identifiers, doubled SQL quotes, numeric literals, and simple SQL operators and
comments. This is not a SQL parser or complete dialect implementation. Other
dialects, backslash/dollar quoting, unsupported syntax, imprecise ranges, and
inputs exceeding 8192 code points or 64 marks retain uncertainty. Fixed SQL
parameter binding remains separate from untrusted dynamic templates.
Within the supported subset, a tainted quote that closes a fixed quoted
region (or a fixed quote that closes a tainted region) is structural evidence.
Doubled quote escapes and ordinary values inside fixed quotes are not promoted
on that basis. Placeholder dialects such as `%s`, `%(name)s`, and `:name`
are currently outside this lexical subset and remain `unknown`; bound values
in a fixed SQL template remain separate from SQL-template pollution.

The shell subset supports simple POSIX `sh`, `bash`, `dash`, `ksh`, and `zsh`
commands, quoting, escapes, and control separators. Expansion, redirection,
compound syntax, and other shells remain `unknown`. Executable control requires
policy; ordinary argv and fixed-destination path/query input remain separate
observations. Network allowlist and filesystem-root policies are not implemented,
so related boundary decisions remain `unknown`. Normalization alone does not
prove safety. Byte strings are not interpreted as a known textual dialect.

Within a request, `suspected > unknown > no_evidence` selects the retained
occurrence without changing its ID or counting it twice. Stronger evidence
bypasses ordinary detail sampling. Each later request retains its own status;
a weaker request cannot replace a stronger representative.
`attack_evidence_counts` partitions process-local request occurrences by the
three statuses, and `strongest_attack_evidence` describes the strongest retained
status. These counters do not represent confirmed attacks or exploit successes.
