diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index fb0f28ad..8124c85f 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -99,7 +99,7 @@ jobs: TAG: ${{ needs.release-please.outputs.tag_name }} run: | set -euo pipefail - cp "$BUNDLE" "dist/aptl-labs-${TAG}.intoto.jsonl" + cp "$BUNDLE" "dist/lilrae-${TAG}.intoto.jsonl" gh release upload "$TAG" dist/* sbom/* --clobber backmerge: @@ -119,13 +119,24 @@ jobs: # main is now ahead of dev. Auto-open a back-merge PR so dev stays # current. It's opened by GITHUB_TOKEN, so dev's required checks won't # run on it — admin-merge it (one click). + # + # TAG goes through the environment, so no workflow expression is parsed + # as shell. Only "dev already contains main" ends without a PR; any + # other failure (auth, network, API) fails the job. + env: + TAG: ${{ needs.release-please.outputs.tag_name }} run: | set -euo pipefail - if [ "$(gh pr list --base dev --head main --state open --json number --jq 'length')" != "0" ]; then + open_prs="$(gh pr list --base dev --head main --state open --json number --jq 'length')" + if [ "$open_prs" != "0" ]; then echo "back-merge PR main->dev already open; nothing to do." exit 0 fi + ahead="$(gh api "repos/${GH_REPO}/compare/dev...main" --jq '.ahead_by')" + if [ "$ahead" = "0" ]; then + echo "dev already contains main; no back-merge needed." + exit 0 + fi gh pr create --base dev --head main \ - --title "chore: back-merge ${{ needs.release-please.outputs.tag_name }} into dev" \ - --body "Automated back-merge of the release commit (version bump + CHANGELOG.md) from \`main\` into \`dev\` so dev stays current after the release. Admin-merge it — dev's required checks don't run on a bot-opened PR." \ - || echo "no back-merge needed (dev already up to date with main)." + --title "chore: back-merge ${TAG} into dev" \ + --body "Automated back-merge of the release commit (version bump + CHANGELOG.md) from \`main\` into \`dev\` so dev stays current after the release. Admin-merge it — dev's required checks don't run on a bot-opened PR." diff --git a/README.md b/README.md index dd37f6fc..87914276 100644 --- a/README.md +++ b/README.md @@ -5,21 +5,21 @@ # LilRAE (formerly APTL) -> **APTL is now LilRAE, and `aptl-labs` 7.0.0 is planned as the last -> `aptl-labs` release.** The Advanced Purple Team Lab (APTL) repository moved to +> **APTL is now LilRAE, and the package is now `lilrae`.** The Advanced Purple +> Team Lab (APTL) repository moved to > [github.com/OpenRAE/lilrae](https://github.com/OpenRAE/lilrae) and was > renamed. It is the same project, with the same source, history, features, -> and issue tracker. Later releases will publish to PyPI as -> [`lilrae`](https://pypi.org/project/lilrae/), starting at version 8.0.0. The -> import package is still `aptl`, the command is still `aptl`, and existing -> configuration, state directories, and runtime identifiers keep their `aptl` -> names. Where current pages still say APTL, they mean LilRAE. See +> and issue tracker. Releases publish to PyPI as +> [`lilrae`](https://pypi.org/project/lilrae/) from version 8.0.0. +> `aptl-labs` 7.0.0 was the last `aptl-labs` release. The import package is +> still `aptl`, the command is still `aptl`, and existing configuration, state +> directories, and runtime identifiers keep their `aptl` names. Where current +> pages still say APTL, they mean LilRAE. See > [ADR-062](https://github.com/OpenRAE/lilrae/blob/main/docs/adrs/adr-062-lilrae-name-and-naming-convention.md). > -> Do not change packages until `lilrae` 8.0.0 or later shows on its PyPI page. -> Until then, keep `aptl-labs`. The two distributions install the same `aptl` -> package and commands. Do not install `lilrae` over `aptl-labs`, because one -> installation overwrites the files of the other. Remove `aptl-labs` first, then install `lilrae` with the +> The two distributions install the same `aptl` package and commands. Do not +> install `lilrae` over `aptl-labs`, because one installation overwrites the +> files of the other. Remove `aptl-labs` first, then install `lilrae` with the > same extras. > > With pipx: @@ -37,15 +37,14 @@ > python -m pip install "lilrae[s3]" > ``` > -> To roll back after a migration, remove `lilrae`, then install the last legacy -> release: +> To roll back, remove `lilrae`, then install the last legacy release: > > ```shell > pipx uninstall lilrae > pipx install "aptl-labs==7.0.0" > ``` > -> The [installation guide](https://github.com/OpenRAE/lilrae/blob/main/docs/getting-started/installation.md#move-to-the-lilrae-package) +> The [installation guide](https://github.com/OpenRAE/lilrae/blob/main/docs/getting-started/installation.md#move-from-aptl-labs-to-lilrae) > has the full procedure. All earlier `aptl-labs` releases stay on PyPI. LilRAE is a local purple-team lab where human operators and AI agents exercise @@ -89,7 +88,7 @@ Install the released CLI and materialize its bundled lab assets. No source checkout is required: ```shell -pipx install aptl-labs +pipx install lilrae aptl lab init my-lab cd my-lab aptl lab start --scenario techvault diff --git a/appliance/guest/provision-offline.sh b/appliance/guest/provision-offline.sh index 52af7c35..4407fb8f 100755 --- a/appliance/guest/provision-offline.sh +++ b/appliance/guest/provision-offline.sh @@ -77,7 +77,7 @@ PYTHONPATH="$1" python3 -m pip install --no-index --only-binary=:all: \ # Keep the application wheel separate from the dependency closure. pip's # --target install does not merge an existing bin directory, so installing the # wheel into the dependency target would silently omit its aptl entrypoint. -set -- "$payload_dir"/wheelhouse/aptl_labs-*.whl +set -- "$payload_dir"/wheelhouse/lilrae-*.whl test "$#" -eq 1 test -f "$1" PYTHONPATH="$pip_wheel" python3 -m pip install \ diff --git a/docs/adrs/adr-062-lilrae-name-and-naming-convention.md b/docs/adrs/adr-062-lilrae-name-and-naming-convention.md index 5f03b688..403033d0 100644 --- a/docs/adrs/adr-062-lilrae-name-and-naming-convention.md +++ b/docs/adrs/adr-062-lilrae-name-and-naming-convention.md @@ -71,6 +71,26 @@ A future change to any of these needs its own compatibility and migration decision. No alias package, compatibility shim, second import root, duplicate configuration schema, or name toggle is introduced. +### Successor decision: distribution from 8.0.0 (#1367) + +Issue #1367 supersedes only the retained `aptl-labs` distribution clause and +current distribution-related install, upgrade, and recovery wording above. +`aptl-labs` 7.0.0 is the final legacy release; the successor distribution is +`lilrae` from 8.0.0. This decision authorizes the cutover; it does not assert +that 8.0.0 has published. Release-please continues to own version selection. + +The successor ships the same import packages, commands, entry points, extras, +and bundled asset contract. All other executable, configuration, runtime, +schema, and persisted identities remain unchanged. Installed-provider +provenance records the actual distribution; historical evidence, fixtures, +and the closed legacy startup-reset receipt classifier retain their names. +Migration removes the old distribution before installing the successor; +rollback removes the successor before restoring pinned `aptl-labs==7.0.0`. +No alias package or dual installation is supported. The +[#1367 preflight](../architecture/issue-1367-distribution-cutover-preflight.md) +records the release and consumer boundaries; #1234 owns post-release checks +and legacy archival. + ### Naming convention for new code Use `lilrae` as the naming convention for new code going forward. A new diff --git a/docs/architecture/issue-1367-distribution-cutover-preflight.md b/docs/architecture/issue-1367-distribution-cutover-preflight.md new file mode 100644 index 00000000..c78fcf3a --- /dev/null +++ b/docs/architecture/issue-1367-distribution-cutover-preflight.md @@ -0,0 +1,81 @@ +# Issue #1367: Distribution Cutover Preflight + +The supplied #1367 issue is the contract; no GRC workflow platform requirement is +attached. This note supplements the [parent preflight](issue-1234-pypi-transition-preflight.md), +whose cross-cutting guardrails remain applicable. It is design guidance, not +an implementation plan or evidence of publication. + +## Boundary and canonical owners + +Change the Python distribution to `lilrae` for the release following +`aptl-labs` 7.0.0. The issue identifies the unreleased breaking fix #1269 as +the reason that release is 8.0.0. Retain the single release-please version/tag +stream; do not manually bump versions or `CHANGELOG.md`, reset numbering, or +make a `build:` change trigger releases by inventing a functional commit. +ADR-062's successor clause is limited to distribution identity and its current +user-facing wording; it does not accept the proposed product split in ADR-054. + +| Layer | Required incumbent and passage | +| --- | --- | +| Package and build shape | `pyproject.toml` owns name, Python constraint, both `src/aptl` and `src/aptl_techvault` packages, scripts, extras, and `aptl.*` entry points. Preserve these contracts apart from name. `hatch_build.py`, `_asset_manifest.py`, and `core/assets.py` remain the shared build/materialization boundary, including tracked-file selection, secret/state exclusions, sanitized Git environment, full-build marker, and no-Git sdist fallback. Container builds also consume the bundled project metadata; retain their minimal-build behavior. | +| Lock and release shape | `.pre-commit-ci.yaml` owns the pinned UV lock/export hooks and hashed `requirements/*.txt`; use the specific hooks, not the whole-tree CI configuration locally. Avoid unrelated dependency upgrades. `release-please-config.json` must select the one renamed root lock package and retain the `src/aptl/__init__.py` updater. Its `package-name: aptl` is a release component identity, not the wheel's metadata name. `.release-please-manifest.json` and `docs/releasing.md` remain version/process authorities. | +| Installed version and evidence | CLI `--version` reads `aptl.__version__`, maintained by release-please; `core/snapshot.py` reads installed distribution metadata. They must agree in an installed artifact. Keep `SoftwareVersions.aptl_version`, catch only `PackageNotFoundError` for the existing source-only `dev` fallback, and never report `dev` when `lilrae` metadata exists. No legacy-name fallback chain, new version service, or renamed snapshot field. | +| Provider shapes and reset authority | Existing `backends/*_discovery.py`, `backends/scenario_startup.py`, and `validation/scenario_verification_discovery.py` validate installed providers and retain actual metadata provenance. Keep selectors and ambiguity rejection. `startup_reset_state.py`, `lifecycle_cleanup.py`, and `_scenario_startup_runtime.py` own canonical receipt parsing, hashes, safe persistence, and exact pack/reset authorization. Preserve the closed legacy classifier and historical bytes; a renamed distribution grants no new reset authority. An unavailable legacy reset stays a bounded diagnostic under existing rules. | +| Offline guest and host OS | `appliance/versioning.py:aptl_wheel_version(prefix=...)` and `is_appliance_version()` are the existing bounded parsing seam. `build-seat-image.sh` owns application wheel/hash requirement generation; `provision-offline.sh` owns archive shape/size/type admission and hash-enforced installation. Require exactly one matching wheel and matching name/version/hash requirement; zero, duplicate, or tampered inputs fail. Keep `--no-index`, `--no-deps` for the app, separate app/dependency targets, and fixed `/opt/aptl` launchers. `aptl-wheel-requirements.txt` is a payload interface filename, not distribution metadata. Preserve base/system-package pins and seat build-record/signature/trust gates; Python publishing stays independent of seat publishing. | +| Workflow auth and shell boundary | `.github/workflows/release-please.yml` retains pinned actions, `environment: pypi`, job-scoped OIDC/attestation permissions, hashed tooling, SBOM, and attest-before-publish ordering. Bind workflow outputs through `env:` and quoted expansions, including the complete back-merge title; environment binding prevents shell-code interpolation but does not replace metadata/path validation. Keep `GH_TOKEN` in the environment, never argv, shell tracing, logs, or artifacts; add no PyPI token fallback. Account-side `lilrae` trusted-publisher authorization requires external verification under the established release process. | +| Runtime config and auth shapes | `core/config.py:AptlConfig` and its strict nested models, `core/env.py:EnvVars`/placeholder validation, startup environment-binding contracts, and `api/deps.py:WebAuthSettings`/token checks retain their current shapes. No `LILRAE_*` aliases for existing `APTL_*`, new credentials, listeners, principals, config fields, or renamed Compose resources. Existing BFF/MCP validation and auth continue unchanged. | +| Error envelopes and observability | Reuse domain errors, startup reason codes/diagnostics, typed API/MCP envelopes, `utils/logging.py:get_logger()`, and `utils/redaction.py` (ADR-029). Change recovery prose to the installable distribution without changing error types, telemetry identities, or exposing raw validator values/backend stderr. Hash or selection failures remain fatal; no broad exception-to-`dev` conversion or migration exception hierarchy. | + +The extensibility seam is **distribution metadata separate from runtime +identity**. The host hash writer already reads `[project]`; derive its name and +normalized wheel prefix there, keeping filename normalization distinct from +the requirement's metadata name. Reuse the existing parser's prefix parameter +and explicit guest artifact selection. Release-please's declarative selector +must match the root metadata. No brand registry, configurable publication +destination, additional runtime config, or duplicated wheel/version parser is +needed for this single successor distribution. + +## Gotchas and verification boundaries + +The parent identified two existing release hazards still present in this +checkout: publish checkout follows a moving branch rather than the release +tag, and `gh pr create ... || echo` treats every back-merge failure as +"already up to date." Candidate provenance must bind to the release commit; +authentication/network failures must not count as successful workflow work. +Retain these as release review concerns, not a reason to add a second workflow. +Keep attestations outside the PyPI upload set and distinguish the new bundle +filename from stable labels such as `sbom/aptl.cdx.json`. + +Reuse `test_version_consistency.py`, `test_version.py`, `test_snapshot.py`, +`test_hashed_requirements.py`, `test_hatch_build_hook.py`, `test_assets.py`, +`test_seat_image_build.py`, `test_appliance_release_workflow.py`, installed +provider/cleanup tests, and `test_docs_user_journey.py`. Existing tests do not +prove all acceptance criteria: the seat test asserts the old glob, and +`aptl_wheel_version()` currently has no repository call sites. Update current +behavior assertions and cover the parser directly; leave historical fixtures +unchanged. Require meaningful zero/multiple-wheel and hash-mismatch cases, +wheel and sdist name/version/content contracts, and installed CLI/snapshot +agreement outside checkout/PYTHONPATH masking. Asset equivalence means the same +asset set and runtime contract, not byte identity of intentionally changed +bundled metadata or messages. Reuse the clean-wheel lifecycle job in +`checks.yml`; retain minimal-container and sdist-rebuild coverage. + +Current install/upgrade guidance includes README, docs home/installation, +secondary operator guides, asset recovery text, and `aptl_techvault` package +documentation. Preserve uninstall-first pip and pipx migration, pinned +rollback, extras/interpreter choice, and state. Do not advertise an unpublished +successor as verified, use `--force` to hide command collisions, or rewrite +old reviews, ADR history, evidence, and fixtures by global replacement. + +Local verification uses explicit tests through `tools/run-targeted-tests.sh` +and staged-file `pre-commit run`; full tests, prose/docs gates, and clean lab +checks remain CI/CD-owned. No requirement UID, status, or traceability is +fabricated. #1234 owns post-publication clean install, migration, rollback, +CLI smoke evidence and archival. Source inspection cannot verify PyPI account +state or publication, and this preflight authorizes no external mutation. + +## Non-goals + +No issue implementation, package/import/CLI aliases, runtime rename, schema +or persistence migration, feature extraction, dependency overhaul, alternate +build backend, second release pipeline, publishing, archival, or data transfer. diff --git a/docs/deployment.md b/docs/deployment.md index 88f65254..9306edc7 100644 --- a/docs/deployment.md +++ b/docs/deployment.md @@ -9,7 +9,7 @@ raw Compose commands are not an equivalent deployment path. Install the released package and materialize its lab assets: ```shell -pipx install aptl-labs +pipx install lilrae aptl lab init my-lab cd my-lab aptl lab start --scenario techvault diff --git a/docs/getting-started/installation.md b/docs/getting-started/installation.md index 7cda85fd..adc7b53a 100644 --- a/docs/getting-started/installation.md +++ b/docs/getting-started/installation.md @@ -7,20 +7,20 @@ pipx environment. Check the [prerequisites](prerequisites.md) first. Install pipx through your operating system or the [official pipx instructions](https://pipx.pypa.io/stable/installation/), then -install LilRAE. LilRAE was formerly named APTL; it is still published as the -`aptl-labs` package and provides the `aptl` command +install LilRAE. LilRAE was formerly named APTL. It is published as the +`lilrae` package and provides the `aptl` command ([ADR-062](../adrs/adr-062-lilrae-name-and-naming-convention.md)): ```shell -pipx install aptl-labs +pipx install lilrae aptl --version ``` -`aptl-labs` requires Python 3.12 or newer. On macOS, if pipx is bound to the +`lilrae` requires Python 3.12 or newer. On macOS, if pipx is bound to the Command Line Tools Python 3.9, ask pipx to fetch a supported interpreter: ```shell -pipx install --python 3.12 --fetch-missing-python aptl-labs +pipx install --python 3.12 --fetch-missing-python lilrae ``` pipx keeps the CLI outside the system Python environment, avoiding the PEP 668 @@ -52,20 +52,19 @@ Upgrade the isolated installation, then initialize a new project when you want the complete asset set from the new release: ```shell -pipx upgrade aptl-labs +pipx upgrade lilrae aptl lab init my-new-lab ``` Do not copy generated credentials or state between project directories. -## Move To The lilrae Package +## Move From aptl-labs To lilrae -`aptl-labs` 7.0.0 is planned as the last `aptl-labs` release. Later releases -will publish to PyPI as [`lilrae`](https://pypi.org/project/lilrae/), starting -at version 8.0.0. Do not start a migration until `lilrae` 8.0.0 or later shows -on its PyPI page. Until then, keep `aptl-labs` and upgrade it as usual. The import package, the `aptl` and `aptl-misp-suricata-sync` commands, -the configuration, and the project state do not change. `pipx upgrade -aptl-labs` does not move you to `lilrae`. +`aptl-labs` 7.0.0 was the last `aptl-labs` release. Releases publish to PyPI +as [`lilrae`](https://pypi.org/project/lilrae/) from version 8.0.0. The import +package, the `aptl` and `aptl-misp-suricata-sync` commands, the configuration, +and the project state do not change. `pipx upgrade aptl-labs` does not move +you to `lilrae`. Both distributions install the same `aptl` package and the same commands. If you install one over the other, the second installation overwrites the files of @@ -130,8 +129,8 @@ installation finds it. ### Roll Back -To return to the legacy package after a migration, remove `lilrae` first, then -install the last legacy release: +To return to the legacy package, remove `lilrae` first, then install the last +legacy release: ```shell pipx uninstall lilrae diff --git a/docs/getting-started/installing-packs.md b/docs/getting-started/installing-packs.md index 7c95dcf5..d7b13067 100644 --- a/docs/getting-started/installing-packs.md +++ b/docs/getting-started/installing-packs.md @@ -50,7 +50,7 @@ The adapter registers entry points in these groups, keyed by the pack identity: | `aptl.evidence_payload` | Evidence collectors | | `aptl.participant_mcp_smoke_plans` | Participant MCP smoke plans | -The TechVault adapter is `aptl_techvault`. It ships inside the `aptl-labs` +The TechVault adapter is `aptl_techvault`. It ships inside the `lilrae` (LilRAE) distribution, so a LilRAE install already has it. You do not install it separately. diff --git a/docs/getting-started/prerequisites.md b/docs/getting-started/prerequisites.md index 0becf2b2..fffc5966 100644 --- a/docs/getting-started/prerequisites.md +++ b/docs/getting-started/prerequisites.md @@ -33,7 +33,7 @@ - Node.js 20+ and npm (for the MCP servers, the AI-agent control plane that `aptl lab start` builds via `mcp/build-all-mcps.sh`; without them the lab still boots but reports `degraded` with MCP servers unavailable) -- Git (only for the from-source dev install; `pipx install aptl-labs` needs no clone) +- Git (only for the from-source dev install; `pipx install lilrae` needs no clone) ## Install Docker @@ -112,24 +112,24 @@ block system-wide `pip` under [PEP 668](https://peps.python.org/pep-0668/), so `pip install -e .` against the system Python fails with `error: externally-managed-environment`. -For released installs on any OS, prefer `pipx install aptl-labs`. +For released installs on any OS, prefer `pipx install lilrae`. -**macOS gotcha—pipx bound to the system Python 3.9.** `aptl-labs` requires +**macOS gotcha—pipx bound to the system Python 3.9.** `lilrae` requires Python 3.12+ (declared in `pyproject.toml`). If your `pipx` was installed against the Command Line Tools Python (`/usr/bin/python3`, which is 3.9), -`pipx install aptl-labs` fails with: +`pipx install lilrae` fails with: ``` -ERROR: Could not find a version that satisfies the requirement aptl-labs (from versions: none) +ERROR: Could not find a version that satisfies the requirement lilrae (from versions: none) ``` The real cause is the "Ignored the following versions that require a different python version" line further up in pip's output—every published -`aptl-labs` release is filtered out by the Python-version gate. Recover with +`lilrae` release is filtered out by the Python-version gate. Recover with a scoped standalone Python that pipx fetches just for this venv: ```bash -pipx install --python 3.12 --fetch-missing-python aptl-labs +pipx install --python 3.12 --fetch-missing-python lilrae ``` Alternatively, `brew install python@3.12` and use that interpreter. diff --git a/docs/index.md b/docs/index.md index b3948439..4cd30df3 100644 --- a/docs/index.md +++ b/docs/index.md @@ -5,16 +5,15 @@ The Advanced Purple Team Lab (APTL) repository moved to [OpenRAE/lilrae](https://github.com/OpenRAE/lilrae) and was renamed. It is the same project, with the same source, history, features, and issue - tracker. You still install the `aptl-labs` package and run the `aptl` - command, and existing configuration, state directories, and runtime + tracker. You install the `lilrae` package and run the `aptl` command, + and existing configuration, state directories, and runtime identifiers keep their `aptl` names. Where current pages still say APTL, they mean LilRAE. See [ADR-062](adrs/adr-062-lilrae-name-and-naming-convention.md). - `aptl-labs` 7.0.0 is planned as the last `aptl-labs` release. Later - releases will publish to PyPI as `lilrae`, starting at version 8.0.0. When - `lilrae` 8.0.0 shows on PyPI, follow - [Move to the lilrae package](getting-started/installation.md#move-to-the-lilrae-package). + `aptl-labs` 7.0.0 was the last `aptl-labs` release. Releases publish to + PyPI as `lilrae` from version 8.0.0. To change packages, follow + [Move from aptl-labs to lilrae](getting-started/installation.md#move-from-aptl-labs-to-lilrae). LilRAE is a local purple-team lab where human operators and AI agents exercise red- and blue-team workflows against an intentionally vulnerable enterprise @@ -57,7 +56,7 @@ require a source checkout or an architecture record. The shortest installation and start sequence is: ```shell -pipx install aptl-labs +pipx install lilrae aptl lab init my-lab cd my-lab aptl lab start --scenario techvault diff --git a/docs/raes/techvault-live-validation-gate.md b/docs/raes/techvault-live-validation-gate.md index d4f47413..3c1169be 100644 --- a/docs/raes/techvault-live-validation-gate.md +++ b/docs/raes/techvault-live-validation-gate.md @@ -135,7 +135,7 @@ The gate's framework holds no scenario knowledge: which node is the attacker and which nodes make up the defensive stack is knowledge about one scenario on one backend. That lives in a per-scenario adapter package, discovered through the `aptl.scenario_verifiers` entry-point group. For TechVault it is `aptl_techvault`, -which ships inside `aptl-labs`, so there is nothing extra to install. +which ships inside `lilrae`, so there is nothing extra to install. A scenario with no adapter of its own reports terminal `blocked` and the gate reaches no verdict. That is deliberate, and it is not a pass, a skip, or a diff --git a/docs/reference/experiment-runs.md b/docs/reference/experiment-runs.md index 11384678..e503dc6a 100644 --- a/docs/reference/experiment-runs.md +++ b/docs/reference/experiment-runs.md @@ -261,7 +261,7 @@ aptl runs path # Export run as tar.gz archive aptl runs export -# Export to S3 (requires pip install aptl-labs[s3]) +# Export to S3 (requires pip install lilrae[s3]) aptl runs export --s3-bucket my-bucket --s3-prefix runs/ # Build a portable evidence bundle (written to ./exports by default) diff --git a/docs/releasing.md b/docs/releasing.md index 169bd441..76ab606e 100644 --- a/docs/releasing.md +++ b/docs/releasing.md @@ -71,7 +71,7 @@ README badge do not update until a promotion lands. 4. Merging tags `vX.Y.Z` and cuts the GitHub Release; the `publish` job then builds the sdist + wheel, generates an SBOM, and publishes to PyPI via OIDC. Because the current workflow rebuilds at publish time, a later - `pip install aptl-labs==X.Y.Z` check is corroboration, not the pre-cut + `pip install lilrae==X.Y.Z` check is corroboration, not the pre-cut release gate or proof that the bytes are identical. If byte-for-byte promotion becomes required, publish the tested artifacts instead of rebuilding them. @@ -90,13 +90,16 @@ hand-edited. ## PyPI trusted publisher (one-time) -On pypi.org, open the project → Settings → Publishing. The trusted publisher -for project `aptl-labs` must have owner `OpenRAE`, repository `lilrae`, workflow -`release-please.yml`, and environment `pypi`. The repository moved from -`Brad-Edwards/aptl`, and PyPI matches the owner and repository names in the -OIDC token. A publisher with the old names rejects the upload. -`raes` must be on PyPI first (aptl depends on it). The distribution is named -`aptl-labs` because `aptl` is reserved on PyPI; the import package and CLI stay `aptl`. +On pypi.org, open the `lilrae` project → Settings → Publishing. The trusted +publisher must have owner `OpenRAE`, repository `lilrae`, workflow +`release-please.yml`, and environment `pypi`. PyPI matches these names in the +OIDC token, so a publisher with other names rejects the upload. Before the +first release of a new project, add the same values as a pending publisher +under Account → Publishing. The first upload then creates the project. +`raes` must be on PyPI first (the project depends on it). The distribution is +named `lilrae` because `aptl` is reserved on PyPI; the import package and CLI +stay `aptl`. Releases up to 7.0.0 published as `aptl-labs` +([ADR-062](adrs/adr-062-lilrae-name-and-naming-convention.md)). ## Seat image cuts diff --git a/docs/requirements/DEP-008/requirement.md b/docs/requirements/DEP-008/requirement.md index 18af9e23..fb8ae4c5 100644 --- a/docs/requirements/DEP-008/requirement.md +++ b/docs/requirements/DEP-008/requirement.md @@ -6,14 +6,14 @@ type: FUNCTIONAL priority: SHOULD wave: 2 created_at: 2026-07-06T08:00:25.969813Z -updated_at: 2026-09-04T00:00:00.000000Z +updated_at: 2026-10-13T00:00:00.000000Z --- # DEP-008: Self-Contained Distribution of Lab Assets from Installed Package ## Statement -The platform shall bundle all lab assets required to run a lab, comprising the Docker Compose definition (docker-compose.yml), scenario definitions (scenarios/), configuration files (config/: Wazuh/Suricata configs, cert templates, active-response lists), and container build contexts (all Dockerfiles and build contexts under containers/), as installed package data shipped in the aptl-labs wheel, and shall provide a materialization entry point (for example, `aptl lab init `) that copies those assets out of the installed package into a working directory. All src/aptl code that currently reads lab assets via current-working-directory-relative paths (including but not limited to core/certs.py, suricata_seed.py, credentials.py, env.py, continuity.py, docker_compose.py, snapshot.py, _soc_ca_io.py) shall instead resolve those assets against the materialized working directory or installed package data rather than assuming the current working directory is a repository checkout. As a result, `pipx install aptl-labs` followed by `aptl lab init` and `aptl lab start` shall produce a working lab without a git clone of the repository. +The platform shall bundle all lab assets required to run a lab, comprising the Docker Compose definition (docker-compose.yml), scenario definitions (scenarios/), configuration files (config/: Wazuh/Suricata configs, cert templates, active-response lists), and container build contexts (all Dockerfiles and build contexts under containers/), as installed package data shipped in the lilrae wheel, and shall provide a materialization entry point (for example, `aptl lab init `) that copies those assets out of the installed package into a working directory. All src/aptl code that currently reads lab assets via current-working-directory-relative paths (including but not limited to core/certs.py, suricata_seed.py, credentials.py, env.py, continuity.py, docker_compose.py, snapshot.py, _soc_ca_io.py) shall instead resolve those assets against the materialized working directory or installed package data rather than assuming the current working directory is a repository checkout. As a result, `pipx install aptl-labs` followed by `aptl lab init` and `aptl lab start` shall produce a working lab without a git clone of the repository. ## Rationale diff --git a/docs/reviews/962-lilrae-readiness/tracked-file-inventory.tsv b/docs/reviews/962-lilrae-readiness/tracked-file-inventory.tsv index 324a06e1..07c2f9b1 100644 --- a/docs/reviews/962-lilrae-readiness/tracked-file-inventory.tsv +++ b/docs/reviews/962-lilrae-readiness/tracked-file-inventory.tsv @@ -1872,6 +1872,7 @@ docs/reviews/1178-seat-desktop-diagnostic.md architecture-history Preserve VM se docs/specs/1178-vm-seat-access-preflight.md docs-follow-owner Keep VM seat implementation guidance with the appliance owner src/aptl/appliance/seat/namespace.py optional-delivery Keep VM seat delivery with the appliance owner tests/test_appliance_seat_namespace.py tests-follow-owner Retain VM seat regression coverage with the appliance owner +tests/test_appliance_versioning.py tests-follow-owner Retain appliance wheel-name parsing tests with migrated owner tests/test_seat_desktop.py tests-follow-owner Retain VM seat regression coverage with the appliance owner tests/test_seat_launch_descriptor.py tests-follow-owner Retain VM seat regression coverage with the appliance owner src/aptl/appliance/seat/private_vm.py optional-delivery Keep rootless VM network startup with the appliance owner @@ -1906,6 +1907,7 @@ containers/_host-identity/install.sh split-pack-delivery Inventory exact content docs/adrs/adr-062-lilrae-name-and-naming-convention.md architecture-history Preserve LilRAE name change and new-code naming decision docs/architecture/issue-1232-lilrae-naming-preflight.md architecture-history Preserve LilRAE public naming boundary and compatibility guardrails docs/architecture/issue-1234-pypi-transition-preflight.md architecture-history Preserve PyPI distribution transition and shared-file migration guardrails +docs/architecture/issue-1367-distribution-cutover-preflight.md architecture-history Preserve lilrae distribution cutover and consumer-boundary guardrails changelog.d/+install-scenario-packs-doc.added.md repository-metadata Inspect identity/content owner during #934; no runtime capability implied changelog.d/+proxy-addr-cve-2026-90711.fixed.md repository-metadata Inspect identity/content owner during #934; no runtime capability implied changelog.d/+techvault-env-packs-621-compat.fixed.md repository-metadata Inspect identity/content owner during #934; no runtime capability implied diff --git a/docs/workshop/emergency-rollout.md b/docs/workshop/emergency-rollout.md index 74a74ee5..fc6e615e 100644 --- a/docs/workshop/emergency-rollout.md +++ b/docs/workshop/emergency-rollout.md @@ -5,7 +5,7 @@ students cannot reliably run the lab on their own laptops. It is not the normal APTL delivery model. The normal model remains: ```bash -pipx install aptl-labs +pipx install lilrae aptl lab init workshop cd workshop aptl lab start --yes @@ -55,7 +55,7 @@ Minimum host contract: - supported student-like desktop access, usually RDP to an Ubuntu desktop; - Docker installed and usable by the student account; - `pipx`, Python, Node.js, and npm installed; -- `aptl-labs` installed from the intended release channel; +- `lilrae` installed from the intended release channel; - the workshop lab initialized and started; - Claude Code or the selected agent installed and authenticated; - MCP servers built and registered from the workshop directory. diff --git a/pyproject.toml b/pyproject.toml index 9aa0a646..2000a647 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,7 @@ requires = ["hatchling"] build-backend = "hatchling.build" [project] -name = "aptl-labs" +name = "lilrae" version = "7.0.0" description = "Advanced Purple Team Lab CLI" readme = "README.md" @@ -160,7 +160,7 @@ packages = ["src/aptl", "src/aptl_techvault"] # Bundle the git-tracked lab-asset tree (docker-compose.yml, config/, # containers/, web/, scripts/, and the source that container images -# build from) into the wheel under aptl/_labdata/ so `pipx install aptl-labs` +# build from) into the wheel under aptl/_labdata/ so `pipx install lilrae` # + `aptl lab init` runs a lab without a git clone (issue #659 / DEP-008). # The hook ships only git-tracked files, which keeps generated secrets and # local state out of the distribution. See hatch_build.py. diff --git a/release-please-config.json b/release-please-config.json index 9abe1200..80b7e070 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -10,7 +10,7 @@ { "type": "toml", "path": "uv.lock", - "jsonpath": "$.package[?(@.name.value=='aptl-labs')].version" + "jsonpath": "$.package[?(@.name.value=='lilrae')].version" } ] } diff --git a/requirements/dev.txt b/requirements/dev.txt index 47b49165..fd7badca 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -29,7 +29,7 @@ asyncssh==2.24.0 \ --hash=sha256:4064c590e59ce2e8d82a2f66d35f3120d765828b4df5e3dbfb07b4a8c24686c9 \ --hash=sha256:9abd46300adcb6d4b73269b34c53cd0d17a138b9a22b5b38008ce7d5808734b7 # via - # aptl-labs + # lilrae # raes attrs==26.1.0 \ --hash=sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309 \ @@ -93,12 +93,12 @@ blake3==1.0.9 \ --hash=sha256:f5c9d57f0dcb92243b6ae575c3065793edc9df9008d0ebd98d8245cdeb7c3f84 \ --hash=sha256:f65d77eb05331495485048f6804f53885b192b998acb7e6fe1487d941bf08435 # via - # aptl-labs + # lilrae # raes build==1.6.1 \ --hash=sha256:51cc11666391ab6f092070437ac747002ff46f3e4113a3622177ee6b488bfc53 \ --hash=sha256:ecd351a4be9d35a9eaaba244a7687143c9c7d4aea6ac964e7e7ddab20cbcf4e7 - # via aptl-labs + # via lilrae certifi==2026.7.22 \ --hash=sha256:62f22742b58a1a33014a2b6b706588a8d7e2a88ae7bd1a6ebe8c992928483775 \ --hash=sha256:741e2c3b351ddf169a738da9f2c048608ff7f2c5cc02f1ebc6b118bb090d5d55 @@ -316,7 +316,7 @@ coverage==7.15.2 \ --hash=sha256:eb6bcae8d1a9d305351ecb108232441d11c5cfe9de840a04388ba5d2db8d735c \ --hash=sha256:f653e5d7248c1191ec988a85c72edeab46c3ff44f90639a4ed4874ec0be90243 \ --hash=sha256:fe41909c9515c3bfdb5f02c4d1f857dba322d9a9a1178069b91eea77889df63a - # via aptl-labs + # via lilrae cryptography==50.0.2 \ --hash=sha256:0ddc924c04591c2811ca024d62ecad4f7f6f08af8939c211438f48a16bd23602 \ --hash=sha256:0ec5f09541743261e66e291b4a0cbf0fb2997aeaab6d9e9c740b9dba1b58d1c2 \ @@ -372,8 +372,8 @@ cryptography==50.0.2 \ --hash=sha256:fa8f5efb344d6908a1ce62f4a24e2e5780f825d6f53f5f50ec5ffacac72936cb \ --hash=sha256:fdd28f912fccfec1846a94e2e1e8f9b0012f557f0c46fe4f3eb0d7a87afcf90b # via - # aptl-labs # asyncssh + # lilrae # pyjwt # raes defusedxml==0.7.1 \ @@ -391,7 +391,7 @@ fastapi==0.140.0 \ --hash=sha256:e951c0a0d9540bf5d9a2a9e078fd415da2ab7e312d435139e7d9e2e7fe9f0b23 \ --hash=sha256:f338951b82fd74ca8f843163aec43ea1a1ce84d515415a50fa98fa25572a5544 # via - # aptl-labs + # lilrae # raes googleapis-common-protos==1.75.1 \ --hash=sha256:28a1934bcd33b9c9da66ac301a0a4227e3367f095a17d0375cb98f0a09d93b79 \ @@ -449,7 +449,7 @@ httptools==0.8.0 \ httpx==0.28.1 \ --hash=sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc \ --hash=sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad - # via aptl-labs + # via lilrae httpx2==2.12.0 \ --hash=sha256:7631fe9887a8a2275f4a2540e053aa670fcc50742864a9ae7c66e609fdcf12cf \ --hash=sha256:cc8b6eecb8661c146b8f89a60e97456ee086e91a784ed31ac450c3a9e613dd36 @@ -525,11 +525,11 @@ hypothesis==6.168.3 \ --hash=sha256:f59a3912858d0609c26054aa1c474847c797937f5e0e1c77f0d3f08032e50f09 \ --hash=sha256:f8122cfdd0bc0ba843063effa22ac310bdebdb3a1319bf1e63f14baa119c72ab \ --hash=sha256:fd81241f4cd76fb18d481e87b9688b30a0cb5c30841730513323ba1c7aba1837 - # via aptl-labs + # via lilrae icontract==2.7.3 \ --hash=sha256:8fb0f93f71211416f214f37c01b8017fdc8c079d70159f49f0ddcc10918c14d0 \ --hash=sha256:df37a43d86d532407bc6b84dea29dd9f7ece794b73211769fa8a33a76b8ed145 - # via aptl-labs + # via lilrae idna==3.20 \ --hash=sha256:a7db850025b95ded1eae8a46181a1a6c56c92c96f0e2b005d9ff8dc0210cab44 \ --hash=sha256:ab7ae7122974553370f0bdb919e1a960b2cd1bc1ef0276416d896db81c14582c @@ -563,7 +563,7 @@ mcp==2.2.0 \ --hash=sha256:2dc37ecb1974becdcebdbf7561e7c15a07dbbf20ba21ba16c3593b3038b3afbd \ --hash=sha256:bde982589473a060ae145e3406e9a5333fe538c97229ba841f5a7f92be004f81 # via - # aptl-labs + # lilrae # raes # raes-env-packs mcp-types==2.2.0 \ @@ -578,7 +578,7 @@ opentelemetry-api==1.44.0 \ --hash=sha256:67647e5e9566edcf421166fdf022b3537f818635daa852b289e34604dc6fb33a \ --hash=sha256:94b98c893a91b88657eaac1e3ba89618cdb85be6918196705354f34728b2cdef # via - # aptl-labs + # lilrae # mcp # opentelemetry-exporter-otlp-proto-http # opentelemetry-sdk @@ -590,7 +590,7 @@ opentelemetry-exporter-otlp-proto-common==1.44.0 \ opentelemetry-exporter-otlp-proto-http==1.44.0 \ --hash=sha256:838592fce774c1c8bb7b9a0a7facbfa82e17be5a8a4e94cef10cb84ae026bae3 \ --hash=sha256:c633d7270ad6b57cd4cfbe8b0007a9e2e7c0cb50bd6c50fe2a7b245f721a09d8 - # via aptl-labs + # via lilrae opentelemetry-proto==1.44.0 \ --hash=sha256:898b155a0e1557afd867478fb6158e8122a46329ca0bb8dc53cc55e98f017f56 \ --hash=sha256:c547a79c2f8c0c515d31509154682e5921c7cfd5ca67b70e1f9266e2c3e103f3 @@ -601,21 +601,21 @@ opentelemetry-sdk==1.44.0 \ --hash=sha256:cebe7f65dc12f26ead75c6064de12fd2a9052e5060c0272d402cfa203aae123b \ --hash=sha256:df081c4c6bcfdb1211e3e86140376792643128a25f8d72d1d27675936e7e96ad # via - # aptl-labs + # lilrae # opentelemetry-exporter-otlp-proto-http opentelemetry-semantic-conventions==0.65b0 \ --hash=sha256:1cacde7b0ad306f84c5ef08c3dbe1bbaf20165bba6f8bff43b670e555a086bcb \ --hash=sha256:f9b2b81e9d5b64f11bc952075e7e9c7fb0aab075c7fd1c46d597f1b919852d60 # via - # aptl-labs + # lilrae # opentelemetry-sdk packaging==26.3 \ --hash=sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79 \ --hash=sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c # via - # aptl-labs # build # hatchling + # lilrae # pytest # raes # univers @@ -674,7 +674,7 @@ pyarrow==25.0.1 \ --hash=sha256:df961f2e7ae9cf496459259d798652c70625f6c080650d6952f8c04053c58ee9 \ --hash=sha256:f3831aaa25c67a99f99dc8b05873cb9d64560390372e2aa197ce9dd4a3f06a44 \ --hash=sha256:f729cfdbd36fd99d543b67a914d2de044c84ebe45be8b34902b299b608c15c8f - # via aptl-labs + # via lilrae pycparser==3.0 ; implementation_name != 'PyPy' and platform_python_implementation != 'PyPy' \ --hash=sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29 \ --hash=sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992 @@ -683,8 +683,8 @@ pydantic==2.13.4 \ --hash=sha256:45a282cde31d808236fd7ea9d919b128653c8b38b393d1c4ab335c62924d9aba \ --hash=sha256:c40756b57adaa8b1efeeced5c196f3f3b7c435f90e84ea7f443901bec8099ef6 # via - # aptl-labs # fastapi + # lilrae # mcp # mcp-types # raes @@ -773,17 +773,17 @@ pytest==9.1.1 \ --hash=sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313 \ --hash=sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c # via - # aptl-labs + # lilrae # pytest-mock # pytest-xdist pytest-mock==3.16.0 \ --hash=sha256:007cfeb257801d88d9c0b2a7b5a15a15e73b71968dfd72e7bf8c4a2f8393aec8 \ --hash=sha256:5a8395528b8f498205f3718f575228d0edaed7425fff638f87d1a6c3e0383636 - # via aptl-labs + # via lilrae pytest-xdist==3.8.0 \ --hash=sha256:202ca578cfeb7370784a8c33d6d05bc6e13b4f25b5053c30a152269fd10f0b88 \ --hash=sha256:7e578125ec9bc6050861aa93f2d59f1d8d085595d6551c2c90b6f4fad8d3a9f1 - # via aptl-labs + # via lilrae python-dotenv==1.2.2 \ --hash=sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a \ --hash=sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3 @@ -847,7 +847,7 @@ pyyaml==6.0.3 \ --hash=sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6 \ --hash=sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0 # via - # aptl-labs + # lilrae # raes # raes-env-packs # uvicorn @@ -855,12 +855,12 @@ raes==6.0.1 \ --hash=sha256:3e97f42d42564acc1740757157ffd35a8c6373487845e987a314da54388a06c0 \ --hash=sha256:8ab156fb1b9c1f0b467c08d98c0695403224ad3c6f2b7835e30b570f8741e67f # via - # aptl-labs + # lilrae # raes-env-packs raes-env-packs==6.2.1 \ --hash=sha256:2144f4460cbcd8a2579820b6962fd59fb714c437b980a11ef4041017b22661b2 \ --hash=sha256:6a235e6c75697cb8a1afcb011b70b77e6bdc6fa302911aaa607f25856689b657 - # via aptl-labs + # via lilrae referencing==0.37.0 \ --hash=sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231 \ --hash=sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8 @@ -876,13 +876,13 @@ rfc8785==0.1.4 \ --hash=sha256:520d690b448ecf0703691c76e1a34a24ddcd4fc5bc41d589cb7c58ec651bcd48 \ --hash=sha256:e545841329fe0eee4f6a3b44e7034343100c12b4ec566dc06ca9735681deb4da # via - # aptl-labs + # lilrae # raes rich==15.0.0 \ --hash=sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb \ --hash=sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36 # via - # aptl-labs + # lilrae # raes # typer rpds-py==2026.6.3 \ @@ -997,7 +997,7 @@ ruff==0.16.8 \ --hash=sha256:a6b85621fd3c81e31fc5f5add09c9c078b430db3595ca632efafdec9e64ebfaa \ --hash=sha256:d075e820af612102ce217f07cc93e69f9490b10ec13ea85fa87bd03d996cef8a \ --hash=sha256:efa3e7a16d1baaa79957888dfdf8be9ef2e44db81cb032af06d76632ab59e773 - # via aptl-labs + # via lilrae semantic-version==2.10.0 \ --hash=sha256:bdabb6d336998cbb378d4b9db3a4b56a1e3235701dc05ea2690d9a997ed5041c \ --hash=sha256:de78a3b8e0feda74cabc54aab2da702113e33ac9d9eb9d2389bcf1f58b7d9177 @@ -1022,7 +1022,7 @@ sse-starlette==3.5.0 \ --hash=sha256:3e6e1070df3f0f5d9cea81496de92dbb72f6721871d99748ece67441dd8b7997 \ --hash=sha256:75de713aa8a9441513cc283220826da079d982770965b951e9437720e8bafdb2 # via - # aptl-labs + # lilrae # mcp # raes starlette==1.6.0 \ @@ -1046,7 +1046,7 @@ typer==0.27.0 \ --hash=sha256:629bd12ea5d13a17148125d9a264f949eb171fb3f120f9b04d85873cab054fa5 \ --hash=sha256:6f4b27631e47f077871b7dc30e933ec0131c1390fbe0e387ea5574b5bac9ccf1 # via - # aptl-labs + # lilrae # raes typing-extensions==4.16.0 \ --hash=sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8 \ @@ -1087,7 +1087,7 @@ uvicorn==0.51.0 \ --hash=sha256:5d38af6cd620f2ae3849fb44fd4879e0890aa1febe8d47eb355fb45d93fe6a5b \ --hash=sha256:f6f4b69b657c312f516dd2d268ab9ae6f254b11e4bac504f37b2ab58b24dd0b0 # via - # aptl-labs + # lilrae # mcp # raes uvloop==0.22.1 ; platform_python_implementation != 'PyPy' and sys_platform != 'cygwin' and sys_platform != 'win32' \ diff --git a/requirements/docs.txt b/requirements/docs.txt index 059ce2af..102a4c56 100644 --- a/requirements/docs.txt +++ b/requirements/docs.txt @@ -104,7 +104,7 @@ blake3==1.0.9 \ --hash=sha256:f5c9d57f0dcb92243b6ae575c3065793edc9df9008d0ebd98d8245cdeb7c3f84 \ --hash=sha256:f65d77eb05331495485048f6804f53885b192b998acb7e6fe1487d941bf08435 # via - # aptl-labs + # lilrae # raes certifi==2026.7.22 \ --hash=sha256:62f22742b58a1a33014a2b6b706588a8d7e2a88ae7bd1a6ebe8c992928483775 \ @@ -313,8 +313,8 @@ cryptography==50.0.2 \ --hash=sha256:fa8f5efb344d6908a1ce62f4a24e2e5780f825d6f53f5f50ec5ffacac72936cb \ --hash=sha256:fdd28f912fccfec1846a94e2e1e8f9b0012f557f0c46fe4f3eb0d7a87afcf90b # via - # aptl-labs # asyncssh + # lilrae # pyjwt # raes defusedxml==0.7.1 \ @@ -399,7 +399,7 @@ httpx2-jsfetch==1.0 ; sys_platform == 'emscripten' \ icontract==2.7.3 \ --hash=sha256:8fb0f93f71211416f214f37c01b8017fdc8c079d70159f49f0ddcc10918c14d0 \ --hash=sha256:df37a43d86d532407bc6b84dea29dd9f7ece794b73211769fa8a33a76b8ed145 - # via aptl-labs + # via lilrae idna==3.20 \ --hash=sha256:a7db850025b95ded1eae8a46181a1a6c56c92c96f0e2b005d9ff8dc0210cab44 \ --hash=sha256:ab7ae7122974553370f0bdb919e1a960b2cd1bc1ef0276416d896db81c14582c @@ -501,7 +501,7 @@ mcp==2.2.0 \ --hash=sha256:2dc37ecb1974becdcebdbf7561e7c15a07dbbf20ba21ba16c3593b3038b3afbd \ --hash=sha256:bde982589473a060ae145e3406e9a5333fe538c97229ba841f5a7f92be004f81 # via - # aptl-labs + # lilrae # raes # raes-env-packs mcp-types==2.2.0 \ @@ -531,11 +531,11 @@ mkdocs-get-deps==0.2.2 \ mkdocs-git-revision-date-localized-plugin==1.5.3 \ --hash=sha256:873444b54cab4d47c69bd6e85da05ef5fbe81fee27e64508114c46a0e4f81e37 \ --hash=sha256:cd96e432de6a7e59b31c7041574b22f84179c8636835419ff458877ecfaaaf05 - # via aptl-labs + # via lilrae mkdocs-material==9.7.7 \ --hash=sha256:8ea9bb1737a5b524a5f9dcf2e1b4ebda8274ae3008aa7845720a97083bef708f \ --hash=sha256:c0649c065b1b0512d60aad8c10f947f8e455284475239b364b610f2deb4d0855 - # via aptl-labs + # via lilrae mkdocs-material-extensions==1.3.1 \ --hash=sha256:10c9511cea88f568257f960358a467d12b970e1f7b2c0e5fb2bb48cab1928443 \ --hash=sha256:adff8b62700b25cb77b53358dad940f3ef973dd6db797907c49e3c2ef3ab4e31 @@ -544,7 +544,7 @@ opentelemetry-api==1.44.0 \ --hash=sha256:67647e5e9566edcf421166fdf022b3537f818635daa852b289e34604dc6fb33a \ --hash=sha256:94b98c893a91b88657eaac1e3ba89618cdb85be6918196705354f34728b2cdef # via - # aptl-labs + # lilrae # mcp # opentelemetry-exporter-otlp-proto-http # opentelemetry-sdk @@ -556,7 +556,7 @@ opentelemetry-exporter-otlp-proto-common==1.44.0 \ opentelemetry-exporter-otlp-proto-http==1.44.0 \ --hash=sha256:838592fce774c1c8bb7b9a0a7facbfa82e17be5a8a4e94cef10cb84ae026bae3 \ --hash=sha256:c633d7270ad6b57cd4cfbe8b0007a9e2e7c0cb50bd6c50fe2a7b245f721a09d8 - # via aptl-labs + # via lilrae opentelemetry-proto==1.44.0 \ --hash=sha256:898b155a0e1557afd867478fb6158e8122a46329ca0bb8dc53cc55e98f017f56 \ --hash=sha256:c547a79c2f8c0c515d31509154682e5921c7cfd5ca67b70e1f9266e2c3e103f3 @@ -567,20 +567,20 @@ opentelemetry-sdk==1.44.0 \ --hash=sha256:cebe7f65dc12f26ead75c6064de12fd2a9052e5060c0272d402cfa203aae123b \ --hash=sha256:df081c4c6bcfdb1211e3e86140376792643128a25f8d72d1d27675936e7e96ad # via - # aptl-labs + # lilrae # opentelemetry-exporter-otlp-proto-http opentelemetry-semantic-conventions==0.65b0 \ --hash=sha256:1cacde7b0ad306f84c5ef08c3dbe1bbaf20165bba6f8bff43b670e555a086bcb \ --hash=sha256:f9b2b81e9d5b64f11bc952075e7e9c7fb0aab075c7fd1c46d597f1b919852d60 # via - # aptl-labs + # lilrae # opentelemetry-sdk packaging==26.3 \ --hash=sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79 \ --hash=sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c # via - # aptl-labs # hatchling + # lilrae # mkdocs # raes # univers @@ -625,8 +625,8 @@ pydantic==2.13.4 \ --hash=sha256:45a282cde31d808236fd7ea9d919b128653c8b38b393d1c4ab335c62924d9aba \ --hash=sha256:c40756b57adaa8b1efeeced5c196f3f3b7c435f90e84ea7f443901bec8099ef6 # via - # aptl-labs # fastapi + # lilrae # mcp # mcp-types # raes @@ -778,7 +778,7 @@ pyyaml==6.0.3 \ --hash=sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6 \ --hash=sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0 # via - # aptl-labs + # lilrae # mkdocs # mkdocs-get-deps # pymdown-extensions @@ -794,12 +794,12 @@ raes==6.0.1 \ --hash=sha256:3e97f42d42564acc1740757157ffd35a8c6373487845e987a314da54388a06c0 \ --hash=sha256:8ab156fb1b9c1f0b467c08d98c0695403224ad3c6f2b7835e30b570f8741e67f # via - # aptl-labs + # lilrae # raes-env-packs raes-env-packs==6.2.1 \ --hash=sha256:2144f4460cbcd8a2579820b6962fd59fb714c437b980a11ef4041017b22661b2 \ --hash=sha256:6a235e6c75697cb8a1afcb011b70b77e6bdc6fa302911aaa607f25856689b657 - # via aptl-labs + # via lilrae referencing==0.37.0 \ --hash=sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231 \ --hash=sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8 @@ -817,13 +817,13 @@ rfc8785==0.1.4 \ --hash=sha256:520d690b448ecf0703691c76e1a34a24ddcd4fc5bc41d589cb7c58ec651bcd48 \ --hash=sha256:e545841329fe0eee4f6a3b44e7034343100c12b4ec566dc06ca9735681deb4da # via - # aptl-labs + # lilrae # raes rich==15.0.0 \ --hash=sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb \ --hash=sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36 # via - # aptl-labs + # lilrae # raes # typer rpds-py==2026.6.3 \ @@ -968,7 +968,7 @@ typer==0.27.0 \ --hash=sha256:629bd12ea5d13a17148125d9a264f949eb171fb3f120f9b04d85873cab054fa5 \ --hash=sha256:6f4b27631e47f077871b7dc30e933ec0131c1390fbe0e387ea5574b5bac9ccf1 # via - # aptl-labs + # lilrae # raes typing-extensions==4.16.0 \ --hash=sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8 \ diff --git a/requirements/runtime.txt b/requirements/runtime.txt index 1fbc08e6..de3806de 100644 --- a/requirements/runtime.txt +++ b/requirements/runtime.txt @@ -90,7 +90,7 @@ blake3==1.0.9 \ --hash=sha256:f5c9d57f0dcb92243b6ae575c3065793edc9df9008d0ebd98d8245cdeb7c3f84 \ --hash=sha256:f65d77eb05331495485048f6804f53885b192b998acb7e6fe1487d941bf08435 # via - # aptl-labs + # lilrae # raes certifi==2026.7.22 \ --hash=sha256:62f22742b58a1a33014a2b6b706588a8d7e2a88ae7bd1a6ebe8c992928483775 \ @@ -296,8 +296,8 @@ cryptography==50.0.2 \ --hash=sha256:fa8f5efb344d6908a1ce62f4a24e2e5780f825d6f53f5f50ec5ffacac72936cb \ --hash=sha256:fdd28f912fccfec1846a94e2e1e8f9b0012f557f0c46fe4f3eb0d7a87afcf90b # via - # aptl-labs # asyncssh + # lilrae # pyjwt # raes defusedxml==0.7.1 \ @@ -370,7 +370,7 @@ httpx2-jsfetch==1.0 ; sys_platform == 'emscripten' \ icontract==2.7.3 \ --hash=sha256:8fb0f93f71211416f214f37c01b8017fdc8c079d70159f49f0ddcc10918c14d0 \ --hash=sha256:df37a43d86d532407bc6b84dea29dd9f7ece794b73211769fa8a33a76b8ed145 - # via aptl-labs + # via lilrae idna==3.20 \ --hash=sha256:a7db850025b95ded1eae8a46181a1a6c56c92c96f0e2b005d9ff8dc0210cab44 \ --hash=sha256:ab7ae7122974553370f0bdb919e1a960b2cd1bc1ef0276416d896db81c14582c @@ -399,7 +399,7 @@ mcp==2.2.0 \ --hash=sha256:2dc37ecb1974becdcebdbf7561e7c15a07dbbf20ba21ba16c3593b3038b3afbd \ --hash=sha256:bde982589473a060ae145e3406e9a5333fe538c97229ba841f5a7f92be004f81 # via - # aptl-labs + # lilrae # raes # raes-env-packs mcp-types==2.2.0 \ @@ -414,7 +414,7 @@ opentelemetry-api==1.44.0 \ --hash=sha256:67647e5e9566edcf421166fdf022b3537f818635daa852b289e34604dc6fb33a \ --hash=sha256:94b98c893a91b88657eaac1e3ba89618cdb85be6918196705354f34728b2cdef # via - # aptl-labs + # lilrae # mcp # opentelemetry-exporter-otlp-proto-http # opentelemetry-sdk @@ -426,7 +426,7 @@ opentelemetry-exporter-otlp-proto-common==1.44.0 \ opentelemetry-exporter-otlp-proto-http==1.44.0 \ --hash=sha256:838592fce774c1c8bb7b9a0a7facbfa82e17be5a8a4e94cef10cb84ae026bae3 \ --hash=sha256:c633d7270ad6b57cd4cfbe8b0007a9e2e7c0cb50bd6c50fe2a7b245f721a09d8 - # via aptl-labs + # via lilrae opentelemetry-proto==1.44.0 \ --hash=sha256:898b155a0e1557afd867478fb6158e8122a46329ca0bb8dc53cc55e98f017f56 \ --hash=sha256:c547a79c2f8c0c515d31509154682e5921c7cfd5ca67b70e1f9266e2c3e103f3 @@ -437,20 +437,20 @@ opentelemetry-sdk==1.44.0 \ --hash=sha256:cebe7f65dc12f26ead75c6064de12fd2a9052e5060c0272d402cfa203aae123b \ --hash=sha256:df081c4c6bcfdb1211e3e86140376792643128a25f8d72d1d27675936e7e96ad # via - # aptl-labs + # lilrae # opentelemetry-exporter-otlp-proto-http opentelemetry-semantic-conventions==0.65b0 \ --hash=sha256:1cacde7b0ad306f84c5ef08c3dbe1bbaf20165bba6f8bff43b670e555a086bcb \ --hash=sha256:f9b2b81e9d5b64f11bc952075e7e9c7fb0aab075c7fd1c46d597f1b919852d60 # via - # aptl-labs + # lilrae # opentelemetry-sdk packaging==26.3 \ --hash=sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79 \ --hash=sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c # via - # aptl-labs # hatchling + # lilrae # raes # univers pathspec==1.1.1 \ @@ -484,8 +484,8 @@ pydantic==2.13.4 \ --hash=sha256:45a282cde31d808236fd7ea9d919b128653c8b38b393d1c4ab335c62924d9aba \ --hash=sha256:c40756b57adaa8b1efeeced5c196f3f3b7c435f90e84ea7f443901bec8099ef6 # via - # aptl-labs # fastapi + # lilrae # mcp # mcp-types # raes @@ -627,7 +627,7 @@ pyyaml==6.0.3 \ --hash=sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6 \ --hash=sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0 # via - # aptl-labs + # lilrae # raes # raes-env-packs # uvicorn @@ -635,12 +635,12 @@ raes==6.0.1 \ --hash=sha256:3e97f42d42564acc1740757157ffd35a8c6373487845e987a314da54388a06c0 \ --hash=sha256:8ab156fb1b9c1f0b467c08d98c0695403224ad3c6f2b7835e30b570f8741e67f # via - # aptl-labs + # lilrae # raes-env-packs raes-env-packs==6.2.1 \ --hash=sha256:2144f4460cbcd8a2579820b6962fd59fb714c437b980a11ef4041017b22661b2 \ --hash=sha256:6a235e6c75697cb8a1afcb011b70b77e6bdc6fa302911aaa607f25856689b657 - # via aptl-labs + # via lilrae referencing==0.37.0 \ --hash=sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231 \ --hash=sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8 @@ -656,13 +656,13 @@ rfc8785==0.1.4 \ --hash=sha256:520d690b448ecf0703691c76e1a34a24ddcd4fc5bc41d589cb7c58ec651bcd48 \ --hash=sha256:e545841329fe0eee4f6a3b44e7034343100c12b4ec566dc06ca9735681deb4da # via - # aptl-labs + # lilrae # raes rich==15.0.0 \ --hash=sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb \ --hash=sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36 # via - # aptl-labs + # lilrae # raes # typer rpds-py==2026.6.3 \ @@ -801,7 +801,7 @@ typer==0.27.0 \ --hash=sha256:629bd12ea5d13a17148125d9a264f949eb171fb3f120f9b04d85873cab054fa5 \ --hash=sha256:6f4b27631e47f077871b7dc30e933ec0131c1390fbe0e387ea5574b5bac9ccf1 # via - # aptl-labs + # lilrae # raes typing-extensions==4.16.0 \ --hash=sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8 \ diff --git a/requirements/web.txt b/requirements/web.txt index 138adf74..90934458 100644 --- a/requirements/web.txt +++ b/requirements/web.txt @@ -29,7 +29,7 @@ asyncssh==2.24.0 \ --hash=sha256:4064c590e59ce2e8d82a2f66d35f3120d765828b4df5e3dbfb07b4a8c24686c9 \ --hash=sha256:9abd46300adcb6d4b73269b34c53cd0d17a138b9a22b5b38008ce7d5808734b7 # via - # aptl-labs + # lilrae # raes attrs==26.1.0 \ --hash=sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309 \ @@ -93,7 +93,7 @@ blake3==1.0.9 \ --hash=sha256:f5c9d57f0dcb92243b6ae575c3065793edc9df9008d0ebd98d8245cdeb7c3f84 \ --hash=sha256:f65d77eb05331495485048f6804f53885b192b998acb7e6fe1487d941bf08435 # via - # aptl-labs + # lilrae # raes certifi==2026.7.22 \ --hash=sha256:62f22742b58a1a33014a2b6b706588a8d7e2a88ae7bd1a6ebe8c992928483775 \ @@ -302,8 +302,8 @@ cryptography==50.0.2 \ --hash=sha256:fa8f5efb344d6908a1ce62f4a24e2e5780f825d6f53f5f50ec5ffacac72936cb \ --hash=sha256:fdd28f912fccfec1846a94e2e1e8f9b0012f557f0c46fe4f3eb0d7a87afcf90b # via - # aptl-labs # asyncssh + # lilrae # pyjwt # raes defusedxml==0.7.1 \ @@ -317,7 +317,7 @@ fastapi==0.140.0 \ --hash=sha256:e951c0a0d9540bf5d9a2a9e078fd415da2ab7e312d435139e7d9e2e7fe9f0b23 \ --hash=sha256:f338951b82fd74ca8f843163aec43ea1a1ce84d515415a50fa98fa25572a5544 # via - # aptl-labs + # lilrae # raes googleapis-common-protos==1.75.1 \ --hash=sha256:28a1934bcd33b9c9da66ac301a0a4227e3367f095a17d0375cb98f0a09d93b79 \ @@ -375,7 +375,7 @@ httptools==0.8.0 \ httpx==0.28.1 \ --hash=sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc \ --hash=sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad - # via aptl-labs + # via lilrae httpx2==2.12.0 \ --hash=sha256:7631fe9887a8a2275f4a2540e053aa670fcc50742864a9ae7c66e609fdcf12cf \ --hash=sha256:cc8b6eecb8661c146b8f89a60e97456ee086e91a784ed31ac450c3a9e613dd36 @@ -387,7 +387,7 @@ httpx2-jsfetch==1.0 ; sys_platform == 'emscripten' \ icontract==2.7.3 \ --hash=sha256:8fb0f93f71211416f214f37c01b8017fdc8c079d70159f49f0ddcc10918c14d0 \ --hash=sha256:df37a43d86d532407bc6b84dea29dd9f7ece794b73211769fa8a33a76b8ed145 - # via aptl-labs + # via lilrae idna==3.20 \ --hash=sha256:a7db850025b95ded1eae8a46181a1a6c56c92c96f0e2b005d9ff8dc0210cab44 \ --hash=sha256:ab7ae7122974553370f0bdb919e1a960b2cd1bc1ef0276416d896db81c14582c @@ -417,7 +417,7 @@ mcp==2.2.0 \ --hash=sha256:2dc37ecb1974becdcebdbf7561e7c15a07dbbf20ba21ba16c3593b3038b3afbd \ --hash=sha256:bde982589473a060ae145e3406e9a5333fe538c97229ba841f5a7f92be004f81 # via - # aptl-labs + # lilrae # raes # raes-env-packs mcp-types==2.2.0 \ @@ -432,7 +432,7 @@ opentelemetry-api==1.44.0 \ --hash=sha256:67647e5e9566edcf421166fdf022b3537f818635daa852b289e34604dc6fb33a \ --hash=sha256:94b98c893a91b88657eaac1e3ba89618cdb85be6918196705354f34728b2cdef # via - # aptl-labs + # lilrae # mcp # opentelemetry-exporter-otlp-proto-http # opentelemetry-sdk @@ -444,7 +444,7 @@ opentelemetry-exporter-otlp-proto-common==1.44.0 \ opentelemetry-exporter-otlp-proto-http==1.44.0 \ --hash=sha256:838592fce774c1c8bb7b9a0a7facbfa82e17be5a8a4e94cef10cb84ae026bae3 \ --hash=sha256:c633d7270ad6b57cd4cfbe8b0007a9e2e7c0cb50bd6c50fe2a7b245f721a09d8 - # via aptl-labs + # via lilrae opentelemetry-proto==1.44.0 \ --hash=sha256:898b155a0e1557afd867478fb6158e8122a46329ca0bb8dc53cc55e98f017f56 \ --hash=sha256:c547a79c2f8c0c515d31509154682e5921c7cfd5ca67b70e1f9266e2c3e103f3 @@ -455,20 +455,20 @@ opentelemetry-sdk==1.44.0 \ --hash=sha256:cebe7f65dc12f26ead75c6064de12fd2a9052e5060c0272d402cfa203aae123b \ --hash=sha256:df081c4c6bcfdb1211e3e86140376792643128a25f8d72d1d27675936e7e96ad # via - # aptl-labs + # lilrae # opentelemetry-exporter-otlp-proto-http opentelemetry-semantic-conventions==0.65b0 \ --hash=sha256:1cacde7b0ad306f84c5ef08c3dbe1bbaf20165bba6f8bff43b670e555a086bcb \ --hash=sha256:f9b2b81e9d5b64f11bc952075e7e9c7fb0aab075c7fd1c46d597f1b919852d60 # via - # aptl-labs + # lilrae # opentelemetry-sdk packaging==26.3 \ --hash=sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79 \ --hash=sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c # via - # aptl-labs # hatchling + # lilrae # raes # univers pathspec==1.1.1 \ @@ -502,8 +502,8 @@ pydantic==2.13.4 \ --hash=sha256:45a282cde31d808236fd7ea9d919b128653c8b38b393d1c4ab335c62924d9aba \ --hash=sha256:c40756b57adaa8b1efeeced5c196f3f3b7c435f90e84ea7f443901bec8099ef6 # via - # aptl-labs # fastapi + # lilrae # mcp # mcp-types # raes @@ -645,7 +645,7 @@ pyyaml==6.0.3 \ --hash=sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6 \ --hash=sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0 # via - # aptl-labs + # lilrae # raes # raes-env-packs # uvicorn @@ -653,12 +653,12 @@ raes==6.0.1 \ --hash=sha256:3e97f42d42564acc1740757157ffd35a8c6373487845e987a314da54388a06c0 \ --hash=sha256:8ab156fb1b9c1f0b467c08d98c0695403224ad3c6f2b7835e30b570f8741e67f # via - # aptl-labs + # lilrae # raes-env-packs raes-env-packs==6.2.1 \ --hash=sha256:2144f4460cbcd8a2579820b6962fd59fb714c437b980a11ef4041017b22661b2 \ --hash=sha256:6a235e6c75697cb8a1afcb011b70b77e6bdc6fa302911aaa607f25856689b657 - # via aptl-labs + # via lilrae referencing==0.37.0 \ --hash=sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231 \ --hash=sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8 @@ -674,13 +674,13 @@ rfc8785==0.1.4 \ --hash=sha256:520d690b448ecf0703691c76e1a34a24ddcd4fc5bc41d589cb7c58ec651bcd48 \ --hash=sha256:e545841329fe0eee4f6a3b44e7034343100c12b4ec566dc06ca9735681deb4da # via - # aptl-labs + # lilrae # raes rich==15.0.0 \ --hash=sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb \ --hash=sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36 # via - # aptl-labs + # lilrae # raes # typer rpds-py==2026.6.3 \ @@ -796,7 +796,7 @@ sse-starlette==3.5.0 \ --hash=sha256:3e6e1070df3f0f5d9cea81496de92dbb72f6721871d99748ece67441dd8b7997 \ --hash=sha256:75de713aa8a9441513cc283220826da079d982770965b951e9437720e8bafdb2 # via - # aptl-labs + # lilrae # mcp # raes starlette==1.6.0 \ @@ -820,7 +820,7 @@ typer==0.27.0 \ --hash=sha256:629bd12ea5d13a17148125d9a264f949eb171fb3f120f9b04d85873cab054fa5 \ --hash=sha256:6f4b27631e47f077871b7dc30e933ec0131c1390fbe0e387ea5574b5bac9ccf1 # via - # aptl-labs + # lilrae # raes typing-extensions==4.16.0 \ --hash=sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8 \ @@ -861,7 +861,7 @@ uvicorn==0.51.0 \ --hash=sha256:5d38af6cd620f2ae3849fb44fd4879e0890aa1febe8d47eb355fb45d93fe6a5b \ --hash=sha256:f6f4b69b657c312f516dd2d268ab9ae6f254b11e4bac504f37b2ab58b24dd0b0 # via - # aptl-labs + # lilrae # mcp # raes uvloop==0.22.1 ; platform_python_implementation != 'PyPy' and sys_platform != 'cygwin' and sys_platform != 'win32' \ diff --git a/scripts/appliance/build-seat-image.sh b/scripts/appliance/build-seat-image.sh index fbb52496..3573802c 100755 --- a/scripts/appliance/build-seat-image.sh +++ b/scripts/appliance/build-seat-image.sh @@ -116,17 +116,22 @@ python3 - "$source_root/pyproject.toml" "$payload/wheelhouse" \ "$payload/aptl-wheel-requirements.txt" <<'PYTHON' import hashlib import pathlib +import re import sys import tomllib project = tomllib.loads(pathlib.Path(sys.argv[1]).read_text(encoding="utf-8")) +name = project["project"]["name"] version = project["project"]["version"] -wheels = list(pathlib.Path(sys.argv[2]).glob(f"aptl_labs-{version}-*.whl")) +# Wheel filenames use the normalized name (PEP 427); the requirement keeps the +# metadata name. +wheel_prefix = re.sub(r"[-_.]+", "_", name).lower() +wheels = list(pathlib.Path(sys.argv[2]).glob(f"{wheel_prefix}-{version}-*.whl")) if len(wheels) != 1: - raise SystemExit("bake must produce exactly one APTL application wheel") + raise SystemExit("bake must produce exactly one application wheel") digest = hashlib.sha256(wheels[0].read_bytes()).hexdigest() pathlib.Path(sys.argv[3]).write_text( - f"aptl-labs=={version} --hash=sha256:{digest}\n", encoding="utf-8" + f"{name}=={version} --hash=sha256:{digest}\n", encoding="utf-8" ) PYTHON diff --git a/src/aptl/appliance/versioning.py b/src/aptl/appliance/versioning.py index 910f3abc..0cff068f 100644 --- a/src/aptl/appliance/versioning.py +++ b/src/aptl/appliance/versioning.py @@ -22,7 +22,7 @@ def is_appliance_version(value: str) -> bool: return bool(patch) and all(character in _VERSION_SUFFIX for character in suffix) -def aptl_wheel_version(name: str, *, prefix: str = "aptl_labs-") -> str | None: +def aptl_wheel_version(name: str, *, prefix: str = "lilrae-") -> str | None: """Extract a validated normalized APTL version from one wheel path.""" filename = name.rsplit("/", 1)[-1] diff --git a/src/aptl/cli/lab_init.py b/src/aptl/cli/lab_init.py index a9859dfe..a46a96ea 100644 --- a/src/aptl/cli/lab_init.py +++ b/src/aptl/cli/lab_init.py @@ -29,7 +29,7 @@ def init( Copies the bundled lab assets (docker-compose.yml, scenarios, config, containers, web, scripts, and the source that container images build - from) and writes a default aptl.json, so a `pipx install aptl-labs` + from) and writes a default aptl.json, so a `pipx install lilrae` can run a lab without cloning the repository (DEP-008). After it finishes, run `aptl lab start` from the initialized directory. """ diff --git a/src/aptl/core/assets.py b/src/aptl/core/assets.py index d3f59530..67cde480 100644 --- a/src/aptl/core/assets.py +++ b/src/aptl/core/assets.py @@ -111,7 +111,7 @@ def resolve_asset_source() -> tuple[Path, bool]: return root, False raise AssetError( "Lab assets not found: the installed package has no bundled " - "_labdata and this is not a source checkout. Reinstall aptl-labs." + "_labdata and this is not a source checkout. Reinstall lilrae." ) diff --git a/src/aptl/core/snapshot.py b/src/aptl/core/snapshot.py index 7d484bfd..4b04df6b 100644 --- a/src/aptl/core/snapshot.py +++ b/src/aptl/core/snapshot.py @@ -121,7 +121,7 @@ def _get_software_versions( try: from importlib.metadata import PackageNotFoundError, version - versions.aptl_version = version("aptl-labs") + versions.aptl_version = version("lilrae") except PackageNotFoundError: versions.aptl_version = "dev" diff --git a/src/aptl_techvault/README.md b/src/aptl_techvault/README.md index 1fac74b8..d836bee2 100644 --- a/src/aptl_techvault/README.md +++ b/src/aptl_techvault/README.md @@ -24,8 +24,8 @@ backends are private, so they never could. A scenario declares the capability profile it needs and a backend declares conformance to it; the adapter answers the separate question of whether the scenario's expectations actually held. -It ships inside the `aptl-labs` distribution and releases with it, so `pipx -install aptl-labs` gives an operator every extension surface TechVault owns with +It ships inside the `lilrae` distribution and releases with it, so `pipx +install lilrae` gives an operator every extension surface TechVault owns with nothing further to install. The materialization boundary is in the code, not the packaging: generic materialization consumes the admitted RAES model without branching on TechVault names, while runtime parameters, startup diff --git a/src/aptl_techvault/__init__.py b/src/aptl_techvault/__init__.py index d26cfbf8..3ff7b2ad 100644 --- a/src/aptl_techvault/__init__.py +++ b/src/aptl_techvault/__init__.py @@ -13,7 +13,7 @@ the backend rather than to the scenario author: an author cannot write the adapter for a backend they have never seen, and many backends are private. -It ships inside the ``aptl-labs`` distribution and releases with it, so one +It ships inside the ``lilrae`` distribution and releases with it, so one install gives an operator every extension surface the scenario owns. What stays true is the separation, not the packaging: no module under ``aptl.`` holds scenario knowledge, and a second scenario adds a package like this one rather diff --git a/tests/test_appliance_release_workflow.py b/tests/test_appliance_release_workflow.py index 9d9bdfe7..6ef014df 100644 --- a/tests/test_appliance_release_workflow.py +++ b/tests/test_appliance_release_workflow.py @@ -29,6 +29,83 @@ def test_package_release_only_publishes_python_artifacts() -> None: assert set(jobs["backmerge"]["needs"]) == {"release-please", "publish"} +def test_backmerge_binds_values_and_fails_closed() -> None: + """The back-merge reaches shell values only through env and reports failures. + + The step once interpolated the tag into its script and ended with + ``|| echo``, so an auth or network failure read as "dev already up to date". + """ + (step,) = _jobs()["backmerge"]["steps"] + run = step["run"] + assert "${{" not in run + assert step["env"]["TAG"] == "${{ needs.release-please.outputs.tag_name }}" + assert "|| echo" not in run + assert "|| true" not in run + assert "compare/dev...main" in run + assert '--title "chore: back-merge ${TAG} into dev"' in run + + +_GH_STUB = """#!/bin/sh +echo "$*" >> "$GH_CALLS" +case "$1 $2" in + "pr list") [ -n "$GH_LIST_FAIL" ] && exit 1; echo "${GH_OPEN:-0}" ;; + "api repos/OpenRAE/lilrae/compare/dev...main") echo "${GH_AHEAD:-0}" ;; + "pr create") exit 0 ;; + *) exit 2 ;; +esac +""" + + +def _run_backmerge(tmp_path: Path, **stub_env: str) -> tuple[int, list[str]]: + """Run the back-merge step's script against a stub ``gh``.""" + + (step,) = _jobs()["backmerge"]["steps"] + bin_dir = tmp_path / "bin" + bin_dir.mkdir() + stub = bin_dir / "gh" + stub.write_text(_GH_STUB) + stub.chmod(0o755) + calls = tmp_path / "calls" + calls.touch() + environment = { + "PATH": f"{bin_dir}{os.pathsep}{os.environ['PATH']}", + "GH_REPO": "OpenRAE/lilrae", + "TAG": "v8.0.0", + "GH_CALLS": str(calls), + **stub_env, + } + completed = subprocess.run( + ["bash", "-c", step["run"]], env=environment, capture_output=True, text=True + ) + return completed.returncode, calls.read_text().splitlines() + + +@pytest.mark.parametrize( + ("stub_env", "expected_status", "creates_pr"), + [ + pytest.param({"GH_LIST_FAIL": "1"}, "fail", False, id="list-fails"), + pytest.param({"GH_OPEN": "1"}, "ok", False, id="already-open"), + pytest.param({"GH_AHEAD": "0"}, "ok", False, id="dev-current"), + pytest.param({"GH_AHEAD": "2"}, "ok", True, id="creates-pr"), + ], +) +def test_backmerge_script_outcomes( + tmp_path: Path, stub_env: dict[str, str], expected_status: str, creates_pr: bool +) -> None: + status, calls = _run_backmerge(tmp_path, **stub_env) + assert (status == 0) is (expected_status == "ok") + created = [call for call in calls if call.startswith("pr create")] + assert bool(created) is creates_pr + if creates_pr: + assert "--title chore: back-merge v8.0.0 into dev" in created[0] + + +def test_release_attestation_bundle_is_named_for_the_distribution() -> None: + publish = _jobs()["publish"] + upload = next(s for s in publish["steps"] if "gh release upload" in s.get("run", "")) + assert 'cp "$BUNDLE" "dist/lilrae-${TAG}.intoto.jsonl"' in upload["run"] + + def test_every_project_owned_image_is_still_published() -> None: # The seat image is what a participant boots, but the lab's own container # images are still published; deleting the golden pipeline must not have diff --git a/tests/test_appliance_versioning.py b/tests/test_appliance_versioning.py new file mode 100644 index 00000000..07e519a3 --- /dev/null +++ b/tests/test_appliance_versioning.py @@ -0,0 +1,37 @@ +"""Bounded wheel-name parsing for the appliance application wheel.""" + +from __future__ import annotations + +import pytest + +from aptl.appliance.versioning import aptl_wheel_version, is_appliance_version + + +@pytest.mark.parametrize( + ("name", "expected"), + [ + ("lilrae-8.0.0-py3-none-any.whl", "8.0.0"), + ("wheelhouse/lilrae-8.1.2rc1-py3-none-any.whl", "8.1.2rc1"), + ("lilrae-8.0.0_dev1-py3-none-any.whl", "8.0.0-dev1"), + # The legacy distribution's wheels are not the application wheel. + ("aptl_labs-7.0.0-py3-none-any.whl", None), + ("lilrae-8.0.0.whl", None), + ("lilrae-8.0-py3-none-any.whl", None), + ("lilrae-8.0.0-py3-none-any.tar.gz", None), + ("lilrae-8.0.0;x-py3-none-any.whl", None), + ], +) +def test_wheel_version_accepts_only_the_lilrae_application_wheel(name, expected): + assert aptl_wheel_version(name) == expected + + +def test_wheel_version_prefix_stays_a_parameter(): + assert aptl_wheel_version("other-1.2.3-py3-none-any.whl", prefix="other-") == "1.2.3" + + +@pytest.mark.parametrize( + ("value", "expected"), + [("8.0.0", True), ("10.20.30+local.1", True), ("8.0", False), ("8.x.0", False)], +) +def test_appliance_version_shape(value, expected): + assert is_appliance_version(value) is expected diff --git a/tests/test_env_pack_realization.py b/tests/test_env_pack_realization.py index b350b166..1eb81025 100644 --- a/tests/test_env_pack_realization.py +++ b/tests/test_env_pack_realization.py @@ -52,7 +52,7 @@ def test_techvault_pack_realizes_without_provisioner_diagnostics( # The adapter ships inside the one distribution, so host-observed # provenance names it. What the seam still proves is that the provenance # comes from installed metadata rather than the provider's own claim. - assert evidence["provider"]["distribution"] == "aptl-labs" + assert evidence["provider"]["distribution"] == "lilrae" assert evidence["provider"]["entry_point"] == "techvault.aptl" assert evidence["provider"]["mapping_digest"].startswith("sha256:") diff --git a/tests/test_scenario_verification_artifacts.py b/tests/test_scenario_verification_artifacts.py index 67f7ffc5..ccf9060d 100644 --- a/tests/test_scenario_verification_artifacts.py +++ b/tests/test_scenario_verification_artifacts.py @@ -11,7 +11,7 @@ Second, the install: one install of one distribution is enough for semantic verification to reach a verdict. That is the point of the adapter shipping with the backend, and it is what an operator on the packaged path (DEP-008, -``pipx install aptl-labs``, no git clone) actually gets. +``pipx install lilrae``, no git clone) actually gets. Every compatibility context is derived from the pack ``env_pack_bundle()`` admits (#879). A digest copied into this file would let the test agree with a @@ -251,7 +251,7 @@ def test_one_install_reaches_a_verdict_and_records_its_provenance( ) assert report.status is VerificationStatus.PASSED, report.diagnostics assert report.plugin_id == "techvault" -assert report.distribution == "aptl-labs" +assert report.distribution == "lilrae" assert report.distribution_version, "the version comes from installed metadata" assert report.entry_point == "techvault.aptl" """, diff --git a/tests/test_scenario_verification_seam.py b/tests/test_scenario_verification_seam.py index a35effe7..5ddc4989 100644 --- a/tests/test_scenario_verification_seam.py +++ b/tests/test_scenario_verification_seam.py @@ -597,7 +597,7 @@ def test_the_techvault_adapter_is_its_own_package_in_the_one_distribution(): core = tomllib.loads((root / "pyproject.toml").read_text(encoding="utf-8")) entry_points = core["project"]["entry-points"] - assert core["project"]["name"] == "aptl-labs" + assert core["project"]["name"] == "lilrae" assert entry_points[ENTRY_POINT_GROUP] == { "techvault.aptl": "aptl_techvault.verification:verifier", "techvault-participant-study.aptl": "aptl_techvault.study:verifier", diff --git a/tests/test_seat_image_build.py b/tests/test_seat_image_build.py index f8d68cb1..78f5c4ab 100644 --- a/tests/test_seat_image_build.py +++ b/tests/test_seat_image_build.py @@ -178,7 +178,8 @@ def test_bake_uses_the_proven_offline_guest_provisioning() -> None: assert "system-packages.sha256" in provision assert "policy-rc.d" in provision assert "systemctl enable docker.service" in provision - assert "aptl_labs-*.whl" in provision + assert "lilrae-*.whl" in provision + assert "aptl_labs" not in provision assert "aptl-wheel-requirements.txt" in bake assert "aptl-wheel-requirements.txt" in provision assert "--require-hashes --find-links" in provision @@ -256,3 +257,45 @@ def test_bake_uses_checkout_config_writer_and_configured_disk_scan() -> None: scan = (ROOT / "appliance/guest/scan-golden.sh").read_text() assert 'expected_disk_gib=${APTL_SEAT_DISK_GIB:-128}' in scan assert 'expected_disk_gib * 1024 * 1024 * 1024 * 19 / 20' in scan + + +def _wheel_requirement_writer() -> str: + """Return the bake's embedded application-wheel requirement writer.""" + + bake = BAKE.read_text() + start = bake.index("<<'PYTHON'\n") + len("<<'PYTHON'\n") + return bake[start : bake.index("\nPYTHON\n", start)] + + +@pytest.mark.parametrize("wheel_count", [0, 1, 2]) +def test_bake_pins_exactly_one_application_wheel_by_metadata_name( + tmp_path: Path, wheel_count: int +) -> None: + import hashlib + import subprocess + + project = tmp_path / "pyproject.toml" + project.write_text('[project]\nname = "lilrae"\nversion = "8.0.0"\n') + wheelhouse = tmp_path / "wheelhouse" + wheelhouse.mkdir() + # A legacy-named wheel in the wheelhouse is never the application wheel. + (wheelhouse / "aptl_labs-8.0.0-py3-none-any.whl").write_bytes(b"legacy") + for tag in ["py3-none-any", "py312-none-any"][:wheel_count]: + (wheelhouse / f"lilrae-8.0.0-{tag}.whl").write_bytes(tag.encode()) + output = tmp_path / "aptl-wheel-requirements.txt" + + completed = subprocess.run( + [sys.executable, "-", str(project), str(wheelhouse), str(output)], + input=_wheel_requirement_writer(), + capture_output=True, + text=True, + ) + + if wheel_count != 1: + assert completed.returncode != 0 + assert "exactly one application wheel" in completed.stderr + assert not output.exists() + return + assert completed.returncode == 0, completed.stderr + digest = hashlib.sha256(b"py3-none-any").hexdigest() + assert output.read_text() == f"lilrae==8.0.0 --hash=sha256:{digest}\n" diff --git a/tests/test_snapshot.py b/tests/test_snapshot.py index 553d06bd..8b04dc97 100644 --- a/tests/test_snapshot.py +++ b/tests/test_snapshot.py @@ -267,6 +267,38 @@ def test_handles_empty_docker_output(self): assert sv.python_version # still set + def test_reads_the_installed_lilrae_version(self, monkeypatch): + import importlib.metadata as metadata + + installed = {"lilrae": "8.0.0", "raes": "6.0.1"} + + def _version(name): + if name not in installed: + raise metadata.PackageNotFoundError(name) + return installed[name] + + monkeypatch.setattr(metadata, "version", _version) + backend = MagicMock() + backend.host_versions.return_value = {} + sv = _get_software_versions(backend, active_services=set()) + assert sv.aptl_version == "8.0.0" + assert sv.raes_version == "6.0.1" + + def test_reports_dev_only_when_lilrae_is_not_installed(self, monkeypatch): + import importlib.metadata as metadata + + def _version(name): + if name == "aptl-labs": + return "7.0.0" + raise metadata.PackageNotFoundError(name) + + monkeypatch.setattr(metadata, "version", _version) + backend = MagicMock() + backend.host_versions.return_value = {} + sv = _get_software_versions(backend, active_services=set()) + assert sv.aptl_version == "dev" + + class TestGetContainerSnapshots: """Tests for ``_get_container_snapshots`` driven by typed backend methods.""" diff --git a/tests/test_supply_chain_pinning.py b/tests/test_supply_chain_pinning.py index fe1f8d80..40f07445 100644 --- a/tests/test_supply_chain_pinning.py +++ b/tests/test_supply_chain_pinning.py @@ -421,23 +421,3 @@ def test_source_builds_do_not_re_open_an_unhashed_resolver(source: Path) -> None f"{source.relative_to(REPO_ROOT)} builds from source with PEP 517 isolation " f"enabled, which resolves the build backend unpinned: {offenders}" ) - - -def test_scenario_fixture_scripts_are_out_of_scope() -> None: - """The lab's fake corporate content is not part of APTL's supply chain. - - ``scenarios/fixtures/techvault-content/`` holds the files a red-team agent - discovers on a compromised TechVault host. Its ``deploy.sh`` is a prop: it is - never executed by a build, and hash-pinning it would make the artifact read - as machine-generated rather than as something a developer checked in. It is - excluded here by evidence, not by convenience - and this test fails if the - file stops being a fixture, so the exclusion cannot quietly widen. - """ - fixture = ( - REPO_ROOT - / "scenarios/fixtures/techvault-content/dev-user-home/projects/techvault-portal/deploy.sh" - ) - if not fixture.is_file(): - pytest.skip("fixture removed or relocated") - assert fixture not in _pinning_sources() - assert "scenarios/fixtures/" in str(fixture.relative_to(REPO_ROOT)) diff --git a/uv.lock b/uv.lock index 1342ca49..8953085b 100644 --- a/uv.lock +++ b/uv.lock @@ -37,124 +37,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/da/35/f2287558c17e29fafc8ef3daf819bb9834061cfa43bff8014f7df7f63bdc/anyio-4.14.2-py3-none-any.whl", hash = "sha256:9f505dda5ac9f0c8309b5e8bd445a8c2bf7246f3ce950121e45ea15bc41d1494", size = 125813, upload-time = "2026-07-12T20:29:05.763Z" }, ] -[[package]] -name = "aptl-labs" -version = "7.0.0" -source = { editable = "." } -dependencies = [ - { name = "blake3" }, - { name = "cryptography" }, - { name = "icontract" }, - { name = "mcp" }, - { name = "opentelemetry-api" }, - { name = "opentelemetry-exporter-otlp-proto-http" }, - { name = "opentelemetry-sdk" }, - { name = "opentelemetry-semantic-conventions" }, - { name = "packaging" }, - { name = "pydantic" }, - { name = "pyyaml" }, - { name = "raes" }, - { name = "raes-env-packs" }, - { name = "rfc8785" }, - { name = "rich" }, - { name = "typer" }, -] - -[package.optional-dependencies] -dev = [ - { name = "build" }, - { name = "coverage" }, - { name = "httpx" }, - { name = "hypothesis" }, - { name = "pyarrow" }, - { name = "pytest" }, - { name = "pytest-mock" }, - { name = "pytest-xdist" }, - { name = "ruff" }, -] -docs = [ - { name = "mkdocs-git-revision-date-localized-plugin" }, - { name = "mkdocs-material" }, -] -parquet = [ - { name = "pyarrow" }, -] -s3 = [ - { name = "boto3" }, -] -web = [ - { name = "asyncssh" }, - { name = "fastapi" }, - { name = "httpx" }, - { name = "sse-starlette" }, - { name = "uvicorn", extra = ["standard"] }, -] - -[package.dev-dependencies] -build = [ - { name = "editables" }, - { name = "hatchling" }, - { name = "pip" }, -] -ci = [ - { name = "build" }, - { name = "cyclonedx-bom" }, - { name = "pip-audit" }, - { name = "pre-commit" }, -] - -[package.metadata] -requires-dist = [ - { name = "asyncssh", marker = "extra == 'web'", specifier = ">=2.17.0" }, - { name = "blake3", specifier = ">=1.0.8,<2" }, - { name = "boto3", marker = "extra == 's3'", specifier = ">=1.28.0" }, - { name = "build", marker = "extra == 'dev'", specifier = ">=1.2.0" }, - { name = "coverage", marker = "extra == 'dev'", specifier = ">=7.0.0" }, - { name = "cryptography", specifier = ">=50.0.0" }, - { name = "fastapi", marker = "extra == 'web'", specifier = ">=0.115.0" }, - { name = "httpx", marker = "extra == 'dev'", specifier = ">=0.27.0" }, - { name = "httpx", marker = "extra == 'web'", specifier = ">=0.28.1" }, - { name = "hypothesis", marker = "extra == 'dev'", specifier = ">=6.0.0" }, - { name = "icontract", specifier = ">=2.6.0,<3.0" }, - { name = "mcp", specifier = ">=2,<3" }, - { name = "mkdocs-git-revision-date-localized-plugin", marker = "extra == 'docs'", specifier = ">=1.2.0" }, - { name = "mkdocs-material", marker = "extra == 'docs'", specifier = ">=9.5.0" }, - { name = "opentelemetry-api", specifier = ">=1.33.0" }, - { name = "opentelemetry-exporter-otlp-proto-http", specifier = ">=1.33.0" }, - { name = "opentelemetry-sdk", specifier = ">=1.33.0" }, - { name = "opentelemetry-semantic-conventions", specifier = ">=0.54b0" }, - { name = "packaging", specifier = ">=24.2" }, - { name = "pyarrow", marker = "extra == 'dev'", specifier = ">=17.0.0" }, - { name = "pyarrow", marker = "extra == 'parquet'", specifier = ">=17.0.0" }, - { name = "pydantic", specifier = ">=2.0.0" }, - { name = "pytest", marker = "extra == 'dev'", specifier = ">=8.0.0" }, - { name = "pytest-mock", marker = "extra == 'dev'", specifier = ">=3.12.0" }, - { name = "pytest-xdist", marker = "extra == 'dev'", specifier = ">=3.6.0" }, - { name = "pyyaml", specifier = ">=6.0" }, - { name = "raes", specifier = "==6.0.1" }, - { name = "raes-env-packs", specifier = "==6.2.1" }, - { name = "rfc8785", specifier = ">=0.1.4,<0.2.0" }, - { name = "rich", specifier = ">=13.0.0" }, - { name = "ruff", marker = "extra == 'dev'", specifier = ">=0.15.0" }, - { name = "sse-starlette", marker = "extra == 'web'", specifier = ">=2.0.0" }, - { name = "typer", specifier = ">=0.12.0" }, - { name = "uvicorn", extras = ["standard"], marker = "extra == 'web'", specifier = ">=0.34.0" }, -] -provides-extras = ["s3", "parquet", "web", "dev", "docs"] - -[package.metadata.requires-dev] -build = [ - { name = "editables", specifier = ">=0.5" }, - { name = "hatchling", specifier = ">=1.27.0" }, - { name = "pip", specifier = ">=26.2.1" }, -] -ci = [ - { name = "build", specifier = ">=1.2.0" }, - { name = "cyclonedx-bom", specifier = ">=6.0.0" }, - { name = "pip-audit", specifier = ">=2.7.0" }, - { name = "pre-commit", specifier = ">=4.0.0" }, -] - [[package]] name = "arrow" version = "1.4.0" @@ -1182,6 +1064,124 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/af/40/791891d4c0c4dab4c5e187c17261cedc26285fd41541577f900470a45a4d/license_expression-30.4.4-py3-none-any.whl", hash = "sha256:421788fdcadb41f049d2dc934ce666626265aeccefddd25e162a26f23bcbf8a4", size = 120615, upload-time = "2025-07-22T11:13:31.217Z" }, ] +[[package]] +name = "lilrae" +version = "7.0.0" +source = { editable = "." } +dependencies = [ + { name = "blake3" }, + { name = "cryptography" }, + { name = "icontract" }, + { name = "mcp" }, + { name = "opentelemetry-api" }, + { name = "opentelemetry-exporter-otlp-proto-http" }, + { name = "opentelemetry-sdk" }, + { name = "opentelemetry-semantic-conventions" }, + { name = "packaging" }, + { name = "pydantic" }, + { name = "pyyaml" }, + { name = "raes" }, + { name = "raes-env-packs" }, + { name = "rfc8785" }, + { name = "rich" }, + { name = "typer" }, +] + +[package.optional-dependencies] +dev = [ + { name = "build" }, + { name = "coverage" }, + { name = "httpx" }, + { name = "hypothesis" }, + { name = "pyarrow" }, + { name = "pytest" }, + { name = "pytest-mock" }, + { name = "pytest-xdist" }, + { name = "ruff" }, +] +docs = [ + { name = "mkdocs-git-revision-date-localized-plugin" }, + { name = "mkdocs-material" }, +] +parquet = [ + { name = "pyarrow" }, +] +s3 = [ + { name = "boto3" }, +] +web = [ + { name = "asyncssh" }, + { name = "fastapi" }, + { name = "httpx" }, + { name = "sse-starlette" }, + { name = "uvicorn", extra = ["standard"] }, +] + +[package.dev-dependencies] +build = [ + { name = "editables" }, + { name = "hatchling" }, + { name = "pip" }, +] +ci = [ + { name = "build" }, + { name = "cyclonedx-bom" }, + { name = "pip-audit" }, + { name = "pre-commit" }, +] + +[package.metadata] +requires-dist = [ + { name = "asyncssh", marker = "extra == 'web'", specifier = ">=2.17.0" }, + { name = "blake3", specifier = ">=1.0.8,<2" }, + { name = "boto3", marker = "extra == 's3'", specifier = ">=1.28.0" }, + { name = "build", marker = "extra == 'dev'", specifier = ">=1.2.0" }, + { name = "coverage", marker = "extra == 'dev'", specifier = ">=7.0.0" }, + { name = "cryptography", specifier = ">=50.0.0" }, + { name = "fastapi", marker = "extra == 'web'", specifier = ">=0.115.0" }, + { name = "httpx", marker = "extra == 'dev'", specifier = ">=0.27.0" }, + { name = "httpx", marker = "extra == 'web'", specifier = ">=0.28.1" }, + { name = "hypothesis", marker = "extra == 'dev'", specifier = ">=6.0.0" }, + { name = "icontract", specifier = ">=2.6.0,<3.0" }, + { name = "mcp", specifier = ">=2,<3" }, + { name = "mkdocs-git-revision-date-localized-plugin", marker = "extra == 'docs'", specifier = ">=1.2.0" }, + { name = "mkdocs-material", marker = "extra == 'docs'", specifier = ">=9.5.0" }, + { name = "opentelemetry-api", specifier = ">=1.33.0" }, + { name = "opentelemetry-exporter-otlp-proto-http", specifier = ">=1.33.0" }, + { name = "opentelemetry-sdk", specifier = ">=1.33.0" }, + { name = "opentelemetry-semantic-conventions", specifier = ">=0.54b0" }, + { name = "packaging", specifier = ">=24.2" }, + { name = "pyarrow", marker = "extra == 'dev'", specifier = ">=17.0.0" }, + { name = "pyarrow", marker = "extra == 'parquet'", specifier = ">=17.0.0" }, + { name = "pydantic", specifier = ">=2.0.0" }, + { name = "pytest", marker = "extra == 'dev'", specifier = ">=8.0.0" }, + { name = "pytest-mock", marker = "extra == 'dev'", specifier = ">=3.12.0" }, + { name = "pytest-xdist", marker = "extra == 'dev'", specifier = ">=3.6.0" }, + { name = "pyyaml", specifier = ">=6.0" }, + { name = "raes", specifier = "==6.0.1" }, + { name = "raes-env-packs", specifier = "==6.2.1" }, + { name = "rfc8785", specifier = ">=0.1.4,<0.2.0" }, + { name = "rich", specifier = ">=13.0.0" }, + { name = "ruff", marker = "extra == 'dev'", specifier = ">=0.15.0" }, + { name = "sse-starlette", marker = "extra == 'web'", specifier = ">=2.0.0" }, + { name = "typer", specifier = ">=0.12.0" }, + { name = "uvicorn", extras = ["standard"], marker = "extra == 'web'", specifier = ">=0.34.0" }, +] +provides-extras = ["s3", "parquet", "web", "dev", "docs"] + +[package.metadata.requires-dev] +build = [ + { name = "editables", specifier = ">=0.5" }, + { name = "hatchling", specifier = ">=1.27.0" }, + { name = "pip", specifier = ">=26.2.1" }, +] +ci = [ + { name = "build", specifier = ">=1.2.0" }, + { name = "cyclonedx-bom", specifier = ">=6.0.0" }, + { name = "pip-audit", specifier = ">=2.7.0" }, + { name = "pre-commit", specifier = ">=4.0.0" }, +] + [[package]] name = "lxml" version = "6.1.1"