aetherius 0.2.0__tar.gz → 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- aetherius-0.3.0/.dockerignore +11 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/.env.example +8 -0
- aetherius-0.3.0/.github/workflows/release.yml +92 -0
- aetherius-0.3.0/CHANGELOG.md +189 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/PKG-INFO +98 -9
- {aetherius-0.2.0 → aetherius-0.3.0}/README.md +90 -8
- {aetherius-0.2.0/src/aetherius/_contracts → aetherius-0.3.0/contracts}/blueprint.schema.json +50 -2
- {aetherius-0.2.0 → aetherius-0.3.0}/contracts/events.schema.json +1 -1
- aetherius-0.3.0/contracts/openapi.yaml +308 -0
- aetherius-0.3.0/deploy/.env.example +17 -0
- aetherius-0.3.0/deploy/Dockerfile +63 -0
- aetherius-0.3.0/deploy/aetherius.service +29 -0
- aetherius-0.3.0/deploy/docker-compose.yml +28 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/pyproject.toml +9 -1
- {aetherius-0.2.0/contracts → aetherius-0.3.0/src/aetherius/_contracts}/blueprint.schema.json +50 -2
- aetherius-0.3.0/src/aetherius/acts/_shared.py +116 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/acts/continuum/browser.py +103 -13
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/acts/continuum/driver.py +18 -0
- aetherius-0.3.0/src/aetherius/acts/vector/client.py +216 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/acts/vector/driver.py +54 -5
- aetherius-0.3.0/src/aetherius/acts/vector/impersonate.py +81 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/builder/catalog.py +4 -1
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/builder/factory.py +4 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/builder/validation.py +16 -13
- aetherius-0.2.0/src/aetherius/cli.py → aetherius-0.3.0/src/aetherius/cli/__init__.py +27 -31
- aetherius-0.3.0/src/aetherius/cli/_shared.py +20 -0
- aetherius-0.3.0/src/aetherius/cli/schedule.py +245 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/config/settings.py +17 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/console/app.py +2 -2
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/console/console.tcss +40 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/console/screens/builder/options_editor.py +8 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/console/screens/home.py +5 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/console/screens/library.py +17 -0
- aetherius-0.3.0/src/aetherius/console/screens/schedules/__init__.py +12 -0
- aetherius-0.3.0/src/aetherius/console/screens/schedules/_common.py +44 -0
- aetherius-0.3.0/src/aetherius/console/screens/schedules/detail.py +269 -0
- aetherius-0.3.0/src/aetherius/console/screens/schedules/form.py +350 -0
- aetherius-0.3.0/src/aetherius/console/screens/schedules/screen.py +182 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/console/screenshots.py +134 -4
- aetherius-0.3.0/src/aetherius/console/widgets/confirm.py +52 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/console/widgets/form.py +6 -2
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/console/widgets/run_summary.py +2 -1
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/core/actions/base.py +19 -7
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/core/actions/flow.py +20 -13
- aetherius-0.3.0/src/aetherius/core/actions/notification.py +59 -0
- aetherius-0.3.0/src/aetherius/core/actions/registry.py +117 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/core/blueprint/models.py +6 -0
- aetherius-0.3.0/src/aetherius/core/blueprint/validator.py +83 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/core/errors.py +22 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/core/events/models.py +5 -1
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/core/extraction/json_extractor.py +12 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/core/runtime/context.py +5 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/core/runtime/engine.py +7 -57
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/core/runtime/result.py +2 -0
- aetherius-0.3.0/src/aetherius/core/runtime/steps.py +289 -0
- aetherius-0.3.0/src/aetherius/models/store/.gitkeep +0 -0
- aetherius-0.3.0/src/aetherius/network/__init__.py +35 -0
- aetherius-0.3.0/src/aetherius/network/geo.py +63 -0
- aetherius-0.3.0/src/aetherius/network/identity.py +104 -0
- aetherius-0.3.0/src/aetherius/network/pool.py +64 -0
- aetherius-0.3.0/src/aetherius/network/proxy.py +90 -0
- aetherius-0.3.0/src/aetherius/network/transport.py +33 -0
- aetherius-0.3.0/src/aetherius/notify/__init__.py +48 -0
- aetherius-0.3.0/src/aetherius/notify/base.py +18 -0
- aetherius-0.3.0/src/aetherius/notify/channels/__init__.py +19 -0
- aetherius-0.3.0/src/aetherius/notify/channels/_http.py +31 -0
- aetherius-0.3.0/src/aetherius/notify/channels/discord.py +52 -0
- aetherius-0.3.0/src/aetherius/notify/channels/ntfy.py +66 -0
- aetherius-0.3.0/src/aetherius/notify/channels/telegram.py +48 -0
- aetherius-0.3.0/src/aetherius/notify/channels/webhook.py +32 -0
- aetherius-0.3.0/src/aetherius/notify/message.py +26 -0
- aetherius-0.3.0/src/aetherius/notify/registry.py +98 -0
- aetherius-0.3.0/src/aetherius/notify/sink.py +51 -0
- aetherius-0.3.0/src/aetherius/plugins.py +88 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/recorder/_transform.py +21 -1
- aetherius-0.3.0/src/aetherius/server/app.py +68 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/server/config.py +18 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/server/deps.py +14 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/server/jobs.py +63 -4
- aetherius-0.3.0/src/aetherius/server/routes/schedules.py +142 -0
- aetherius-0.3.0/src/aetherius/server/scheduler/__init__.py +32 -0
- aetherius-0.3.0/src/aetherius/server/scheduler/alerts.py +140 -0
- aetherius-0.3.0/src/aetherius/server/scheduler/manual.py +82 -0
- aetherius-0.3.0/src/aetherius/server/scheduler/misfire.py +71 -0
- aetherius-0.3.0/src/aetherius/server/scheduler/service.py +198 -0
- aetherius-0.3.0/src/aetherius/server/scheduler/triggers.py +115 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/server/schemas.py +35 -0
- aetherius-0.3.0/src/aetherius/stealth/fingerprint/hardening.py +193 -0
- aetherius-0.3.0/src/aetherius/stealth/fingerprint/headers.py +46 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/stealth/fingerprint/profile.py +48 -7
- aetherius-0.3.0/src/aetherius/stealth/fingerprint/webrtc.py +64 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/stealth/humanizer/timing.py +15 -8
- aetherius-0.3.0/src/aetherius/store/__init__.py +28 -0
- aetherius-0.3.0/src/aetherius/store/engine.py +71 -0
- aetherius-0.3.0/src/aetherius/store/models.py +48 -0
- aetherius-0.3.0/src/aetherius/store/runs.py +91 -0
- aetherius-0.3.0/src/aetherius/store/schedules.py +118 -0
- aetherius-0.3.0/src/aetherius/store/schema.py +78 -0
- aetherius-0.3.0/src/aetherius/store/state.py +51 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/version.py +1 -1
- aetherius-0.2.0/CHANGELOG.md +0 -39
- aetherius-0.2.0/RELEASING.md +0 -49
- aetherius-0.2.0/contracts/openapi.yaml +0 -152
- aetherius-0.2.0/src/aetherius/acts/_shared.py +0 -61
- aetherius-0.2.0/src/aetherius/acts/vector/client.py +0 -129
- aetherius-0.2.0/src/aetherius/core/actions/registry.py +0 -70
- aetherius-0.2.0/src/aetherius/core/blueprint/validator.py +0 -45
- aetherius-0.2.0/src/aetherius/server/app.py +0 -37
- {aetherius-0.2.0 → aetherius-0.3.0}/.github/workflows/ci.yml +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/.gitignore +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/CONTRIBUTING.md +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/LICENSE +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/Makefile +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/blueprints/UKIT.king.blueprint.json +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/blueprints/direct.linkaetherius.blueprint.json +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/blueprints/github.aetherius.blueprint.json +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/blueprints/github.github.blueprint.json +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/blueprints/github.zeb.blueprint.json +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/blueprints/licence.aetherius.blueprint.json +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/blueprints/record.aetherius.blueprint.json +0 -0
- {aetherius-0.2.0/src/aetherius/models/store → aetherius-0.3.0/deploy/blueprints}/.gitkeep +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/__init__.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/__main__.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/_contracts/__init__.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/acts/__init__.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/acts/continuum/__init__.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/acts/continuum/actions.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/acts/continuum/bridge.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/acts/continuum/debug_overlay.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/acts/continuum/human_actions.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/acts/oracle/__init__.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/acts/oracle/driver.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/acts/oracle/locator.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/acts/oracle/model.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/acts/oracle/perception.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/acts/phantom/__init__.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/acts/phantom/driver.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/acts/phantom/loop.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/acts/phantom/memory.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/acts/phantom/perception.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/acts/phantom/planner.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/acts/vector/__init__.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/acts/vector/auth.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/builder/__init__.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/builder/templates.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/config/__init__.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/config/secrets.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/console/__init__.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/console/daemon_control.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/console/run_bridge.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/console/screens/__init__.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/console/screens/_pending.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/console/screens/builder/__init__.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/console/screens/builder/act_picker.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/console/screens/builder/io_editor.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/console/screens/builder/preview.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/console/screens/builder/screen.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/console/screens/builder/step_editor.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/console/screens/catalog.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/console/screens/library_scan.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/console/screens/recorder.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/console/screens/runs.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/console/screens/sessions.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/console/screens/settings.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/console/theme.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/console/widgets/__init__.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/console/widgets/event_log.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/console/widgets/json_preview.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/core/__init__.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/core/actions/__init__.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/core/actions/data.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/core/actions/interaction.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/core/actions/navigation.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/core/actions/spec.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/core/blueprint/__init__.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/core/blueprint/loader.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/core/blueprint/template.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/core/driver.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/core/events/__init__.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/core/events/bus.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/core/events/sinks.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/core/extraction/__init__.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/core/extraction/html_extractor.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/core/runtime/__init__.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/core/runtime/selector.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/models/__init__.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/models/registry.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/recorder/__init__.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/recorder/_capture_js.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/recorder/_gesture_js.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/recorder/_names.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/recorder/_overlay_js.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/recorder/_playwright.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/recorder/_selector_js.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/recorder/_vector_js.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/recorder/base.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/recorder/blueprint_recorder.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/recorder/capture.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/recorder/continuum_backend.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/recorder/gesture_recorder.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/recorder/selector_synth.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/recorder/session.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/recorder/vector_backend.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/server/__init__.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/server/routes/__init__.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/server/routes/blueprints.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/server/routes/recorder.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/server/routes/runs.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/server/routes/stream.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/stealth/__init__.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/stealth/fingerprint/__init__.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/stealth/fingerprint/patch.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/stealth/gestures/__init__.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/stealth/gestures/data/human_library.json +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/stealth/gestures/library.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/stealth/gestures/seed.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/stealth/humanizer/__init__.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/stealth/humanizer/input.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/stealth/humanizer/keyboard.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/stealth/humanizer/mouse.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/stealth/humanizer/scroll.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/stealth/ml/__init__.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/stealth/ml/fingerprint_model.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/stealth/ml/motion_model.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/stealth/policy.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/stealth/session/__init__.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/stealth/session/store.py +0 -0
- {aetherius-0.2.0 → aetherius-0.3.0}/src/aetherius/stealth/session/warmup.py +0 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Contexte de build Docker (deploy/Dockerfile, contexte = racine du depot).
|
|
2
|
+
# Allowlist : seul ce que le Dockerfile copie entre dans le contexte — le reste (dont .env et
|
|
3
|
+
# tout secret local) est exclu par construction.
|
|
4
|
+
*
|
|
5
|
+
!pyproject.toml
|
|
6
|
+
!README.md
|
|
7
|
+
!LICENSE
|
|
8
|
+
!src
|
|
9
|
+
!examples
|
|
10
|
+
**/__pycache__
|
|
11
|
+
**/*.pyc
|
|
@@ -18,3 +18,11 @@ AETHERIUS_SECRET_QUOTES_PASS=demo
|
|
|
18
18
|
# Universite de Bordeaux ENT/CAS.
|
|
19
19
|
AETHERIUS_SECRET_BORDEAUX_USER=your-username
|
|
20
20
|
AETHERIUS_SECRET_BORDEAUX_PASS='your-password'
|
|
21
|
+
|
|
22
|
+
# Notification targets (see docs/notifications.md) — uncomment the channels you use.
|
|
23
|
+
# A channel address grants write (and for ntfy, read) access: keep them out of Blueprints.
|
|
24
|
+
# AETHERIUS_SECRET_WEBHOOK_URL=https://webhook.site/<your-uuid>
|
|
25
|
+
# AETHERIUS_SECRET_DISCORD_WEBHOOK=https://discord.com/api/webhooks/<id>/<token>
|
|
26
|
+
# AETHERIUS_SECRET_TELEGRAM_BOT_TOKEN=123456:bot-token
|
|
27
|
+
# AETHERIUS_SECRET_TELEGRAM_CHAT_ID=123456789
|
|
28
|
+
# AETHERIUS_SECRET_NTFY_TOPIC=my-private-topic
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Automated release. Publishing lives here (as infra), not in a doc to remember.
|
|
2
|
+
#
|
|
3
|
+
# To cut a release:
|
|
4
|
+
# 1. Bump the version in BOTH src/aetherius/version.py and sdks/typescript/package.json (same X.Y.Z).
|
|
5
|
+
# 2. Add a "## [X.Y.Z] - <date>" section at the top of CHANGELOG.md (becomes the release notes).
|
|
6
|
+
# 3. Commit, then: git tag vX.Y.Z && git push && git push --tags
|
|
7
|
+
#
|
|
8
|
+
# Pushing the tag triggers this workflow, which — after checking the tag matches the versions —
|
|
9
|
+
# publishes to PyPI and npm and creates the GitHub Release. Nothing else to run by hand.
|
|
10
|
+
#
|
|
11
|
+
# One-time setup (see the pinned note): a PyPI "trusted publisher" for this repo (no token), and an
|
|
12
|
+
# NPM_TOKEN repository secret (npm automation token).
|
|
13
|
+
|
|
14
|
+
name: Release
|
|
15
|
+
|
|
16
|
+
on:
|
|
17
|
+
push:
|
|
18
|
+
tags: ["v*"]
|
|
19
|
+
|
|
20
|
+
permissions:
|
|
21
|
+
contents: read
|
|
22
|
+
|
|
23
|
+
jobs:
|
|
24
|
+
check-version:
|
|
25
|
+
name: Tag matches package versions
|
|
26
|
+
runs-on: ubuntu-latest
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/checkout@v4
|
|
29
|
+
- name: Verify tag == version.py == package.json
|
|
30
|
+
run: |
|
|
31
|
+
tag="${GITHUB_REF_NAME#v}"
|
|
32
|
+
py=$(python3 -c "import re,pathlib; print(re.search(r'__version__\s*=\s*\"([^\"]+)\"', pathlib.Path('src/aetherius/version.py').read_text()).group(1))")
|
|
33
|
+
ts=$(node -p "require('./sdks/typescript/package.json').version")
|
|
34
|
+
echo "tag=$tag python=$py npm=$ts"
|
|
35
|
+
test "$tag" = "$py" || { echo "::error::Tag $tag != Python version $py (bump src/aetherius/version.py)"; exit 1; }
|
|
36
|
+
test "$tag" = "$ts" || { echo "::error::Tag $tag != npm version $ts (bump sdks/typescript/package.json)"; exit 1; }
|
|
37
|
+
|
|
38
|
+
pypi:
|
|
39
|
+
name: Publish to PyPI
|
|
40
|
+
needs: check-version
|
|
41
|
+
runs-on: ubuntu-latest
|
|
42
|
+
permissions:
|
|
43
|
+
id-token: write # OIDC for PyPI trusted publishing (no token stored)
|
|
44
|
+
steps:
|
|
45
|
+
- uses: actions/checkout@v4
|
|
46
|
+
- uses: actions/setup-python@v5
|
|
47
|
+
with:
|
|
48
|
+
python-version: "3.12"
|
|
49
|
+
- run: python3 -m pip install build
|
|
50
|
+
- run: python3 -m build
|
|
51
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
52
|
+
|
|
53
|
+
npm:
|
|
54
|
+
name: Publish to npm
|
|
55
|
+
needs: check-version
|
|
56
|
+
runs-on: ubuntu-latest
|
|
57
|
+
steps:
|
|
58
|
+
- uses: actions/checkout@v4
|
|
59
|
+
- uses: actions/setup-node@v4
|
|
60
|
+
with:
|
|
61
|
+
node-version: "20"
|
|
62
|
+
registry-url: "https://registry.npmjs.org"
|
|
63
|
+
- run: npm install --no-audit --no-fund
|
|
64
|
+
working-directory: sdks/typescript
|
|
65
|
+
- run: npm run build
|
|
66
|
+
working-directory: sdks/typescript
|
|
67
|
+
- run: npm publish --access public
|
|
68
|
+
working-directory: sdks/typescript
|
|
69
|
+
env:
|
|
70
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
71
|
+
|
|
72
|
+
github-release:
|
|
73
|
+
name: GitHub Release
|
|
74
|
+
needs: [pypi, npm]
|
|
75
|
+
runs-on: ubuntu-latest
|
|
76
|
+
permissions:
|
|
77
|
+
contents: write
|
|
78
|
+
steps:
|
|
79
|
+
- uses: actions/checkout@v4
|
|
80
|
+
- name: Extract the CHANGELOG section for this version
|
|
81
|
+
run: |
|
|
82
|
+
version="${GITHUB_REF_NAME#v}"
|
|
83
|
+
awk -v ver="$version" '
|
|
84
|
+
$0 ~ "^## \\[" ver "\\]" { f=1; next }
|
|
85
|
+
/^## \[/ { if (f) exit }
|
|
86
|
+
f { print }
|
|
87
|
+
' CHANGELOG.md > release-notes.md
|
|
88
|
+
[ -s release-notes.md ] || echo "Release ${GITHUB_REF_NAME}." > release-notes.md
|
|
89
|
+
- name: Create the release
|
|
90
|
+
env:
|
|
91
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
92
|
+
run: gh release create "$GITHUB_REF_NAME" --title "$GITHUB_REF_NAME" --notes-file release-notes.md
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Toutes les évolutions notables du projet sont consignées ici. Le format s'inspire de
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/fr/1.1.0/) et le versionnage suit
|
|
5
|
+
[SemVer](https://semver.org/lang/fr/). Tant que la version reste en `0.x`, l'API publique peut encore
|
|
6
|
+
évoluer entre deux versions mineures (durcissement de la Phase 1 en conditions réelles).
|
|
7
|
+
|
|
8
|
+
## [Non publié]
|
|
9
|
+
|
|
10
|
+
## [0.3.0] - 2026-07-17
|
|
11
|
+
|
|
12
|
+
Phase 1.5 : le socle devient **opérationnel** (planification, alertes, réactivité, furtivité réseau
|
|
13
|
+
et empreinte), et durcissement du socle Phase 1 avant d'entamer la Phase 2 (audit croisé de la doc).
|
|
14
|
+
|
|
15
|
+
### Ajouté
|
|
16
|
+
- **Durcissement de l'empreinte (Jalon 1.5-H)** — les signaux à forte valeur que le profil laissait à
|
|
17
|
+
découvert sont fermés **de façon cohérente avec le profil actif** (un signal masqué mais incohérent
|
|
18
|
+
est un tell pire que l'absence de masque). Côté navigateur,
|
|
19
|
+
[`stealth/fingerprint/hardening.py`](src/aetherius/stealth/fingerprint/hardening.py) injecte, après
|
|
20
|
+
le script de cohérence du profil, un init script masquant : **Canvas** (`toDataURL`/`toBlob`/
|
|
21
|
+
`getImageData`) et **AudioContext** avec un bruit **déterministe par profil** (seed calculé côté
|
|
22
|
+
Python, hachage JS — stable entre deux lectures d'un même run, différent d'un profil à l'autre, lu
|
|
23
|
+
depuis une copie offscreen pour ne pas s'accumuler), **polices** (`measureText`), **client hints**
|
|
24
|
+
(`navigator.userAgentData`), **écran** (`screen.*` + `devicePixelRatio`) et **WebGL2**
|
|
25
|
+
(`getParameter`). Côté **Vector** (Act I, sans discrétion jusqu'ici),
|
|
26
|
+
[`stealth/fingerprint/headers.py`](src/aetherius/stealth/fingerprint/headers.py) donne une identité
|
|
27
|
+
d'en-têtes par défaut (`User-Agent`, `Sec-CH-UA`/`-Mobile`/`-Platform`, `Accept`, `Accept-Language`
|
|
28
|
+
aligné sur la géo) supprimant la signature « client HTTP nu » — **opt-in** (injectée seulement quand
|
|
29
|
+
`options.stealth` nomme un profil, un run sans stealth reste inchangé), les en-têtes explicites du
|
|
30
|
+
Blueprint gardant la priorité (fusion insensible à la casse) ; l'impersonation TLS `curl_cffi` garde
|
|
31
|
+
ses propres en-têtes. Le `FingerprintProfile` gagne les champs `screen`/`device_pixel_ratio`/
|
|
32
|
+
`ua_platform`/`ua_full_version` et dérive `Sec-CH-UA` de sa propre version d'UA : la limite « UA-CH
|
|
33
|
+
drift » est **levée**. Exemples exécutables zéro config
|
|
34
|
+
`examples/continuum/fingerprint-hardening.blueprint.json` et
|
|
35
|
+
`examples/vector/http-headers-identity.blueprint.json`. Voir [docs/stealth.md](docs/stealth.md).
|
|
36
|
+
- **Identité réseau (Jalon 1.5-G)** — option `options.proxy` de premier niveau qui rend le bot
|
|
37
|
+
invisible **au niveau réseau**, pour les **deux** moteurs (la couche stealth ne touche que le
|
|
38
|
+
navigateur). Le module `aetherius.network` est activé : `parse_proxy`/`ProxySpec` (rendu httpx et
|
|
39
|
+
Playwright, credentials masqués dans les logs), `ProxyPool` (rotation `per_run`/`round_robin`/
|
|
40
|
+
`random`/`sticky` — l'IP change d'un run à l'autre, ou reste stable par clé), `geo_hint` (cohérence
|
|
41
|
+
timezone/locale/langues avec le pays de l'IP), `resolve_identity` (option du Blueprint > défaut
|
|
42
|
+
d'environnement `AETHERIUS_PROXY_*` > aucun). Vector route par `httpx.Client(proxy=...)`
|
|
43
|
+
(HTTP/HTTPS, plus SOCKS5 via l'extra `[network]` avec garde typée si absent) et peut imiter la
|
|
44
|
+
poignée de main TLS d'un vrai navigateur (JA3/JA4) via un transport `curl_cffi` isolé
|
|
45
|
+
(`acts/vector/impersonate.py`, extra `[network]`, `DependencyError` claire sinon). Continuum lie le
|
|
46
|
+
proxy au lancement du contexte, force l'anti-fuite WebRTC (flag Chromium `disable_non_proxied_udp`
|
|
47
|
+
+ init-script filtrant les candidats ICE locaux — indispensable, sinon le proxy laisse fuir l'IP
|
|
48
|
+
réelle) et dérive le profil d'empreinte pour coller à la géo (timezone/locale/`navigator.languages`
|
|
49
|
+
alignés sur l'IP, vérifiés sur Chromium réel). Identifiants **jamais** stockés dans le Blueprint
|
|
50
|
+
(`{{ secrets.x }}`). Le Studio préserve `options.proxy` verbatim (aucune régression à l'édition).
|
|
51
|
+
Exemple exécutable `examples/vector/ip-echo-proxy.blueprint.json` (nécessite un proxy via `.env`).
|
|
52
|
+
Voir [docs/network.md](docs/network.md).
|
|
53
|
+
- **Déploiement always-on (Jalon 1.5-F)** — recette 24/7 vérifiée de bout en bout pour héberger le
|
|
54
|
+
daemon (et donc le scheduler) sur un hôte toujours allumé : VPS, Raspberry Pi, NAS. Les brouillons
|
|
55
|
+
`deploy/` sont finalisés : image Docker multi-stage (wheel construit à part, image finale sans
|
|
56
|
+
sources ni outils de build), utilisateur non-root, `HEALTHCHECK` sur `/health`, exemples embarqués
|
|
57
|
+
comme sondes zéro config, variante Act II exécutable (`--build-arg BROWSER=1` : extra `[browser]` +
|
|
58
|
+
Chromium sous `PLAYWRIGHT_BROWSERS_PATH` partagé) ; `docker-compose.yml` (volume persistant unique
|
|
59
|
+
`/data`, port publié sur la loopback de l'hôte, `env_file` + `.env.example`, montage lecture seule
|
|
60
|
+
`blueprints/` — les schedules résolvent des chemins côté conteneur) ; service systemd utilisateur
|
|
61
|
+
(`enable-linger`, `EnvironmentFile` optionnel, redémarrage automatique) ; `.dockerignore` racine en
|
|
62
|
+
allowlist (l'ancien `deploy/.dockerignore` était inopérant, le contexte de build étant la racine).
|
|
63
|
+
Durcissement afférent : un `AETHERIUS_DAEMON_TOKEN` vide vaut absence de token — l'interpolation
|
|
64
|
+
compose (`${VAR:-}`) n'active plus l'auth par accident (`server/config.py`, test miroir). Doc
|
|
65
|
+
complète (recettes, persistance, sauvegarde SQLite, sécurité : loopback par défaut, exposer =
|
|
66
|
+
token + reverse proxy TLS) : voir [docs/deployment.md](docs/deployment.md).
|
|
67
|
+
- **Actions custom / plugins (Jalon 1.5-E)** — points d'extension activés : un paquet tiers ajoute
|
|
68
|
+
des actions de Blueprint et des canaux de notification sans forker le cœur. Découverte par
|
|
69
|
+
entry-points (`aetherius.actions`, `aetherius.notify_channels`) dans le nouveau module
|
|
70
|
+
`aetherius.plugins` (`load_plugins()` idempotent, appelé au démarrage par la CLI, le lifespan du
|
|
71
|
+
daemon et `RunEngine.run` ; surface d'import unique pour les auteurs de plugins). Le registre
|
|
72
|
+
d'actions dormant est activé : une action plugin embarque son `ActionSpec` (visible du Studio et
|
|
73
|
+
des validators, invariant « registre = source, catalogue = projection » préservé), est
|
|
74
|
+
**act-agnostique** (hors capability-table, validée dynamiquement) et dispatchée par les drivers
|
|
75
|
+
en repli après leur `match` built-in. Gardes de collision sur les deux registres (les built-ins
|
|
76
|
+
restent prioritaires, un conflit est un échec de chargement explicite) et pannes isolées (un
|
|
77
|
+
plugin qui lève à l'import est loggé et sauté, jamais fatal). Plugin d'exemple exécutable
|
|
78
|
+
(`examples/plugins/` : action `demo.slugify` + canal `logfile` + Blueprint zéro réseau), chargé
|
|
79
|
+
par de vrais entry-points dans les tests. Voir [docs/plugins.md](docs/plugins.md).
|
|
80
|
+
- **Écran Console « Schedules »** — l'UI du scheduler (Jalon 1.5-D) dans la Console : liste des
|
|
81
|
+
schedules (trigger, politique d'alerte, statut, prochains/derniers tirs en heure locale, sonde
|
|
82
|
+
d'honnêteté « daemon actif ou non »), pause/reprise (`p`, la reprise recale la cadence),
|
|
83
|
+
suppression confirmée (`d`, nouveau `ConfirmModal` réutilisable), **détail** avec l'historique
|
|
84
|
+
des runs du schedule et un **tir manuel** aux événements streamés en direct (même brique
|
|
85
|
+
in-process que `aetherius schedule run`, extraite dans `server/scheduler/manual.py::fire_schedule`
|
|
86
|
+
et partagée CLI/Console), et **formulaire guidé** de création/édition (inputs du Blueprint en
|
|
87
|
+
champs, secrets jamais saisis — état `.env` affiché, trigger/misfire/notify validés à la
|
|
88
|
+
sauvegarde). Raccourci `s` dans Library pour planifier le Blueprint surligné. Captures SVG
|
|
89
|
+
déterministes (fuseau épinglé, store de démo figé) et neutralisation renforcée des chemins
|
|
90
|
+
(le home ne fuit plus, même tronqué dans une colonne). Voir [docs/console.md](docs/console.md).
|
|
91
|
+
- **Scheduler intégré au daemon (Jalon 1.5-D)** — rejeu persistant d'un Blueprint à heure fixe
|
|
92
|
+
(cron à 5 champs, évalué dans le fuseau local, DST gérés via `tzlocal`), par intervalle ou en tir
|
|
93
|
+
unique (`at`). Boucle de tick dans le lifespan du daemon (30 s, `AETHERIUS_DAEMON_SCHEDULER_TICK_SECONDS`) ;
|
|
94
|
+
un run planifié passe par `RunManager.submit` — mêmes événements, même historique, plus le lien
|
|
95
|
+
`schedule_id`. Rattrapage des tirs manqués par politique `misfire` (`skip`/`run_once`/`run_all`,
|
|
96
|
+
portée par le trigger, résolue par le tick au-delà d'une fenêtre de grâce) et politique d'alerte
|
|
97
|
+
par schedule (`failure`/`success`/`always`/`change` — la dédup au changement d'état s'appuie sur
|
|
98
|
+
`state.compare_and_set`, cibles `{{ secrets.x }}` rendues au tir, jamais persistées). CLI
|
|
99
|
+
`aetherius schedule add|list|rm|pause|resume|run` (écrit directement dans le store : marche daemon
|
|
100
|
+
éteint ; `cli.py` devient le package `cli/`) et API `/v1/schedules` (CRUD + tir immédiat,
|
|
101
|
+
contrat OpenAPI à jour). Exemple zéro config : `examples/vector/quotes-watch.blueprint.json`.
|
|
102
|
+
Dépendances : `croniter` (déjà déclarée) + `tzlocal`. Voir [docs/scheduler.md](docs/scheduler.md).
|
|
103
|
+
- **Notifications natives (Jalon 1.5-C)** — couche d'alerte sans dépendance nouvelle (`notify/`) :
|
|
104
|
+
quatre canaux built-in en un POST `httpx` chacun (webhook générique, Discord, Telegram, ntfy pour
|
|
105
|
+
la push téléphone, en mode JSON publishing), action `notify` Act-agnostique (handler partagé, se
|
|
106
|
+
combine à `when`), `NotifySink` de fin de run (`failure`/`success`/`always`) et registre de canaux
|
|
107
|
+
prêt pour les plugins (Jalon E). Échec d'envoi contenu : jamais fatal au run, `delivered` exposé
|
|
108
|
+
dans les outputs du step. Exemple zéro config :
|
|
109
|
+
`examples/vector/books-restock-notify.blueprint.json`. Voir
|
|
110
|
+
[docs/notifications.md](docs/notifications.md).
|
|
111
|
+
- **Réactivité et flux conditionnel (Jalon 1.5-B)** — garde d'étape `when` universelle (évaluée
|
|
112
|
+
avant dispatch, même règle de véracité que `assert` ; step sauté = statut `skipped` + événement
|
|
113
|
+
`step_skipped`, contrats et SDK TypeScript à jour) et actions `if`/`repeat`/`for_each` exécutées
|
|
114
|
+
par un **exécuteur récursif** dans le moteur (`core/runtime/steps.py`), en amont des drivers —
|
|
115
|
+
tous les Acts en héritent sans câblage, `repeat` rejoint les capacités Vector. Variable de boucle
|
|
116
|
+
`as` (défaut `item`) exposée au template le temps de l'itération, validation sémantique récursive
|
|
117
|
+
des branches, identifiants de steps imbriqués traçables (`loop[2].fetch`), schéma des steps
|
|
118
|
+
formalisé (`when`, `then`/`else`/`steps`). Deux exemples zéro config dans `examples/vector/`.
|
|
119
|
+
Voir [docs/blueprint-schema.md](docs/blueprint-schema.md).
|
|
120
|
+
- **Persistance durable (Jalon 1.5-A)** — socle de stockage SQLite (stdlib `sqlite3`, mode WAL, zéro
|
|
121
|
+
dépendance) sous `~/.aetherius/aetherius.db`, avec migrations versionnées (`PRAGMA user_version`) et
|
|
122
|
+
trois dépôts typés : schedules, historique des runs, état clé/valeur inter-run (`compare_and_set`
|
|
123
|
+
pour la déduplication d'alertes). Le daemon persiste désormais le résultat de ses runs dans le store
|
|
124
|
+
(migration douce, sans régression). Voir [docs/store.md](docs/store.md).
|
|
125
|
+
- **Cadrage Phase 1.5** — squelette (stubs, interfaces, contrats) et spécifications par jalon pour
|
|
126
|
+
rendre le socle **récurrent, réactif et furtif** : persistance SQLite (`store/`), notifications
|
|
127
|
+
natives (`notify/`), scheduler du daemon, flux conditionnel (`when`, `if`/`repeat`/`for_each`),
|
|
128
|
+
plugins, déploiement 24/7, **identité réseau** (`network/` : proxy, rotation d'IP, anti-fuite
|
|
129
|
+
WebRTC, cohérence géo, impersonation TLS) et **durcissement de l'empreinte**
|
|
130
|
+
(`stealth/fingerprint/` : canvas/audio/UA-CH/écran/WebGL2 + identité d'en-têtes pour Vector).
|
|
131
|
+
Aucune capacité n'est encore activée (jalons en attente : l'action `notify` est déclarée mais
|
|
132
|
+
marquée `PENDING`, les modules lèvent une erreur « jalon en attente ») ; `make check` reste vert.
|
|
133
|
+
Nouvel extra optionnel `[network]` (SOCKS5 + `curl_cffi`). Voir [docs/phase-1.5/](docs/phase-1.5/README.md).
|
|
134
|
+
- **Suivi des nouveaux onglets (Act II — Continuum)** : un clic ouvrant un onglet (`target="_blank"`,
|
|
135
|
+
`window.open`) rend la nouvelle page active pour les steps suivants, avec retombée sur une page
|
|
136
|
+
survivante si l'onglet actif se referme. Auparavant les steps restaient bloqués sur l'onglet initial.
|
|
137
|
+
- **Recorder « Make input »** : le `type`/`format` de l'input produit est inféré du type HTML du champ
|
|
138
|
+
(`number`, `date`+`format`, `email`/`url`, …) au lieu d'un `string` générique.
|
|
139
|
+
|
|
140
|
+
### Sécurité
|
|
141
|
+
- **Évaluateur `where` (Act I — Vector)** : rejet explicite des attributs magiques (`__class__`,
|
|
142
|
+
`__globals__`, tout nom en `__`) dans l'AST-walk. L'allowlist de nœuds bloquait déjà l'exécution de
|
|
143
|
+
code, mais la traversée d'attributs dunder combinée à une comparaison restait un oracle booléen sur
|
|
144
|
+
le graphe d'objets Python — la garde ferme cette évasion de sandbox sans dépendre de l'absence
|
|
145
|
+
d'appels/indexation.
|
|
146
|
+
|
|
147
|
+
### Corrigé
|
|
148
|
+
- **`precise_sleep` (stealth/humanizer)** : le busy-wait pur sous 20 ms saturait un cœur CPU à 100 %
|
|
149
|
+
(chaque point de geste souris), risque de privation de ressources sur le daemon en multi-run.
|
|
150
|
+
Désormais `time.sleep` cède le CPU pour le gros du délai et le busy-wait ne couvre que la queue
|
|
151
|
+
(~1,5 ms) — précision de timing inchangée, CPU au repos (~9 %).
|
|
152
|
+
- **Debug (Act II — Continuum)** : quand les entrées sont humanisées, `slow_mo` est à 0 et les actions
|
|
153
|
+
brutes (`select`, `upload`, `navigate`, …) défilaient instantanément, illisibles en debug. Elles
|
|
154
|
+
reçoivent maintenant un délai manuel équivalent.
|
|
155
|
+
|
|
156
|
+
## [0.2.0] - 2026-07-10
|
|
157
|
+
|
|
158
|
+
Première release publique. Elle clôt la **Phase 1** : le socle d'Aetherius, utilisable comme
|
|
159
|
+
**bibliothèque** (in-process Python) et comme **service** (daemon local + SDK), avec sa Console.
|
|
160
|
+
|
|
161
|
+
### Ajouté
|
|
162
|
+
- **Daemon local (FastAPI)** — passerelle HTTP + WebSocket exposant le moteur à tout langage
|
|
163
|
+
(`aetherius serve`, bind loopback, token bearer optionnel) : `POST /v1/runs`, `GET /v1/runs/{id}`,
|
|
164
|
+
`WS /v1/runs/{id}/events` (rejeu bufferisé + flux live jusqu'à `done`), `POST /v1/blueprints/validate`,
|
|
165
|
+
`GET /v1/schema`, `GET /health`. L'enregistrement reste host-local (`POST /v1/recorder/sessions` → 501).
|
|
166
|
+
Voir [docs/daemon.md](docs/daemon.md).
|
|
167
|
+
- **SDK TypeScript** `@aetherius/client` (Node 20+) — spawn du daemon (ou `baseUrl`),
|
|
168
|
+
`client.run(blueprint, { inputs, secrets, onEvent })`, streaming d'événements typé.
|
|
169
|
+
- **Console : écran Settings** — démarrer/arrêter le daemon et voir son statut, sans quitter le terminal.
|
|
170
|
+
- **Act I — Vector** : client HTTP/API (requêtes, retries/backoff, 5 stratégies d'auth, extraction
|
|
171
|
+
JSONPath et CSS/XPath, moteur de templates Jinja2).
|
|
172
|
+
- **Act II — Continuum** : automatisation d'un vrai navigateur (Playwright, extra `[browser]`) —
|
|
173
|
+
navigation, interactions, extraction DOM, `wait_for` avec échec nommé, sessions persistantes, debug.
|
|
174
|
+
- **Système de discrétion (stealth)** : couche transverse (`options.stealth`) — souris humaine par
|
|
175
|
+
rejeu géométrique de gestes, clavier/scroll/timing humains, fingerprint, warmup de profil.
|
|
176
|
+
- **Recorder** : création de Blueprint par démonstration (Continuum et Vector) + gesture recorder.
|
|
177
|
+
- **Builder headless + Blueprint Studio** : construction guidée de Blueprints sans JSON, avec aperçu
|
|
178
|
+
validé en direct, réutilisable par la Console, le daemon et les SDKs.
|
|
179
|
+
- **Console (Textual)** : Library, Runs, Catalog, Recorder, Blueprint Studio, Settings.
|
|
180
|
+
- **Contrats** langage-agnostiques (`contracts/`) : schéma Blueprint, OpenAPI du daemon, schéma
|
|
181
|
+
d'événements — source de vérité, gardés par des tests.
|
|
182
|
+
|
|
183
|
+
### Notes
|
|
184
|
+
- SemVer `0.x` : l'API peut évoluer pendant le durcissement de la Phase 1.
|
|
185
|
+
- La **Phase 2** ajoutera Act III (Oracle, vision) et Act IV (Phantom, agent autonome).
|
|
186
|
+
|
|
187
|
+
[Non publié]: https://github.com/kln-mltre/Aetherius/compare/v0.3.0...HEAD
|
|
188
|
+
[0.3.0]: https://github.com/kln-mltre/Aetherius/releases/tag/v0.3.0
|
|
189
|
+
[0.2.0]: https://github.com/kln-mltre/Aetherius/releases/tag/v0.2.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aetherius
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: A fixed, robust web-bot engine driven by declarative instruction files (Blueprints).
|
|
5
5
|
Project-URL: Repository, https://github.com/kln-mltre/Aetherius
|
|
6
6
|
Author: Kylian Malartre
|
|
@@ -18,6 +18,7 @@ License: Aetherius
|
|
|
18
18
|
License-File: LICENSE
|
|
19
19
|
Keywords: agent,automation,bot,browser,playwright,scraping,stealth
|
|
20
20
|
Requires-Python: >=3.11
|
|
21
|
+
Requires-Dist: croniter>=2.0
|
|
21
22
|
Requires-Dist: fastapi>=0.110
|
|
22
23
|
Requires-Dist: httpx>=0.27
|
|
23
24
|
Requires-Dist: jinja2>=3.1
|
|
@@ -33,17 +34,20 @@ Requires-Dist: rich>=13.7
|
|
|
33
34
|
Requires-Dist: tenacity>=8.2
|
|
34
35
|
Requires-Dist: textual>=0.60
|
|
35
36
|
Requires-Dist: typer>=0.12
|
|
37
|
+
Requires-Dist: tzlocal>=5.0
|
|
36
38
|
Requires-Dist: uvicorn[standard]>=0.29
|
|
37
39
|
Requires-Dist: websockets>=12.0
|
|
38
40
|
Provides-Extra: agent
|
|
39
41
|
Requires-Dist: anthropic>=0.25; extra == 'agent'
|
|
40
42
|
Provides-Extra: all
|
|
41
43
|
Requires-Dist: anthropic>=0.25; extra == 'all'
|
|
44
|
+
Requires-Dist: curl-cffi>=0.6; extra == 'all'
|
|
42
45
|
Requires-Dist: numpy>=1.26; extra == 'all'
|
|
43
46
|
Requires-Dist: onnxruntime>=1.17; extra == 'all'
|
|
44
47
|
Requires-Dist: opencv-python-headless>=4.9; extra == 'all'
|
|
45
48
|
Requires-Dist: pillow>=10.3; extra == 'all'
|
|
46
49
|
Requires-Dist: playwright>=1.44; extra == 'all'
|
|
50
|
+
Requires-Dist: socksio>=1.0; extra == 'all'
|
|
47
51
|
Provides-Extra: browser
|
|
48
52
|
Requires-Dist: playwright>=1.44; extra == 'browser'
|
|
49
53
|
Provides-Extra: dev
|
|
@@ -54,6 +58,9 @@ Requires-Dist: pytest-cov>=5.0; extra == 'dev'
|
|
|
54
58
|
Requires-Dist: pytest>=8.1; extra == 'dev'
|
|
55
59
|
Requires-Dist: ruff>=0.4; extra == 'dev'
|
|
56
60
|
Requires-Dist: twine>=5.0; extra == 'dev'
|
|
61
|
+
Provides-Extra: network
|
|
62
|
+
Requires-Dist: curl-cffi>=0.6; extra == 'network'
|
|
63
|
+
Requires-Dist: socksio>=1.0; extra == 'network'
|
|
57
64
|
Provides-Extra: stealth
|
|
58
65
|
Requires-Dist: numpy>=1.26; extra == 'stealth'
|
|
59
66
|
Provides-Extra: vision
|
|
@@ -315,8 +322,9 @@ aetherius # ouvre la Console
|
|
|
315
322
|
|
|
316
323
|

|
|
317
324
|
|
|
318
|
-
> **État actuel** : la Console est navigable de bout en bout. Library, Runs,
|
|
319
|
-
>
|
|
325
|
+
> **État actuel** : la Console est navigable de bout en bout. Library, Runs, **Schedules** (runs
|
|
326
|
+
> récurrents : liste, tir manuel, historique, création guidée), Catalog, le **Recorder**, le
|
|
327
|
+
> **Blueprint Studio** et **Settings** (démarrer/arrêter le daemon) sont pleinement fonctionnels
|
|
320
328
|
> pour Act I (Vector) et Act II (Continuum, avec l'extra `[browser]`) ; seul **Sessions** affiche
|
|
321
329
|
> honnêtement son jalon en attente (stealth/session). Détails : [docs/console.md](docs/console.md).
|
|
322
330
|
|
|
@@ -456,20 +464,25 @@ console.log(result.outputs.events);
|
|
|
456
464
|
```
|
|
457
465
|
src/aetherius/
|
|
458
466
|
core/ blueprint (models/loader/validator/template), actions (le dictionnaire),
|
|
459
|
-
runtime (engine/context/selector/result), extraction, events, errors, driver
|
|
467
|
+
runtime (engine/context/steps/selector/result), extraction, events, errors, driver
|
|
460
468
|
acts/ vector (I), continuum (II), oracle (III), phantom (IV)
|
|
461
469
|
stealth/ policy, humanizer (mouse/keyboard/scroll/timing), gestures, fingerprint,
|
|
462
470
|
session (store/warmup), ml (optionnel)
|
|
463
471
|
recorder/ blueprint_recorder, gesture_recorder, capture, selector_synth
|
|
464
472
|
builder/ construction headless de Blueprint (factory, catalog, templates)
|
|
465
|
-
console/ interface terminale globale (Textual) : Blueprint Studio, runs,
|
|
466
|
-
sessions, settings — la porte d'entrée de l'outil
|
|
473
|
+
console/ interface terminale globale (Textual) : Blueprint Studio, runs, schedules,
|
|
474
|
+
catalogue, sessions, settings — la porte d'entrée de l'outil
|
|
475
|
+
notify/ canaux d'alerte natifs (webhook/discord/telegram/ntfy) + registre ouvert aux plugins
|
|
476
|
+
store/ état durable SQLite sous ~/.aetherius : schedules, historique des runs, état inter-run
|
|
477
|
+
plugins.py découverte des extensions tierces par entry-points (actions + canaux)
|
|
467
478
|
models/ registry + cache des assets ML runtime
|
|
468
|
-
server/ daemon FastAPI (routes/jobs/schemas)
|
|
479
|
+
server/ daemon FastAPI (routes/jobs/schemas) + scheduler (triggers/misfire/alerts)
|
|
480
|
+
cli/ commandes scriptables (run/validate/serve/record, groupe schedule)
|
|
469
481
|
config/ settings
|
|
470
482
|
contracts/ blueprint.schema.json, openapi.yaml, events.schema.json (source de vérité)
|
|
483
|
+
deploy/ recette always-on : Dockerfile, docker-compose.yml, service systemd
|
|
471
484
|
sdks/ typescript (@aetherius/client), python
|
|
472
|
-
examples/ Blueprints de démonstration
|
|
485
|
+
examples/ Blueprints de démonstration (par Act + plugins/)
|
|
473
486
|
training/ entraînement des modèles Oracle (hors runtime)
|
|
474
487
|
legacy_examples/ code de référence des projets d'origine (UKit, TikTok) + carte de provenance
|
|
475
488
|
```
|
|
@@ -521,7 +534,8 @@ Conventions de contribution (discipline de test, invariants, structure des tests
|
|
|
521
534
|
Le projet avance en deux grandes phases. La **Phase 1** — le socle, utilisable comme **bibliothèque**
|
|
522
535
|
(in-process Python) et comme **service** (daemon + SDK) — est **terminée avec ce jalon** : un premier
|
|
523
536
|
point de contrôle, à éprouver en conditions réelles avant d'attaquer la **Phase 2** (les deux Acts les
|
|
524
|
-
plus lourds).
|
|
537
|
+
plus lourds). Entre les deux, une **Phase 1.5** durcit ce socle pour les workflows **récurrents et
|
|
538
|
+
réactifs** (planification, alertes, réactivité) — voir ci-dessous.
|
|
525
539
|
|
|
526
540
|
### Phase 1 — le socle réutilisable (terminée)
|
|
527
541
|
|
|
@@ -589,6 +603,81 @@ plus lourds).
|
|
|
589
603
|
**Phase 1 terminée.** Aetherius est utilisable comme bibliothèque et comme service ; c'est le point de
|
|
590
604
|
contrôle prévu pour l'éprouver en conditions réelles et corriger avant la suite.
|
|
591
605
|
|
|
606
|
+
### Phase 1.5 — socle opérationnel (en cours)
|
|
607
|
+
|
|
608
|
+
Un palier intermédiaire, dans l'esprit du durcissement du socle : rendre Aetherius capable de porter
|
|
609
|
+
des workflows **récurrents et réactifs** (planifier un Blueprint, réagir aux données extraites,
|
|
610
|
+
alerter au bon moment) avant les Acts autonomes. Le cas fil rouge : surveiller un produit en rupture,
|
|
611
|
+
vérifier plusieurs fois par jour, alerter au retour en stock. Et, dans la même veine furtive que la
|
|
612
|
+
couche stealth, le rendre invisible **au niveau réseau** (proxy, rotation d'IP). Cadrage complet et
|
|
613
|
+
**spécifications par jalon** : [docs/phase-1.5/](docs/phase-1.5/README.md).
|
|
614
|
+
|
|
615
|
+
- [x] **Persistance (`store/`)** : état durable SQLite (stdlib) sous `~/.aetherius` — schedules,
|
|
616
|
+
historique des runs, état inter-run. Fondation des autres jalons. Le daemon y persiste désormais
|
|
617
|
+
l'historique de ses runs. [docs/store.md](docs/store.md),
|
|
618
|
+
[docs/phase-1.5/a-store.md](docs/phase-1.5/a-store.md).
|
|
619
|
+
- [x] **Réactivité et flux conditionnel** : garde d'étape `when` universelle (step sauté = statut
|
|
620
|
+
`skipped` + événement `step_skipped`) et actions `if`/`repeat`/`for_each` exécutées récursivement
|
|
621
|
+
par le moteur sur tous les Acts (validation récursive des branches, variable de boucle `as`,
|
|
622
|
+
rend la réutilisation de session Continuum exprimable). Exemples zéro config dans
|
|
623
|
+
`examples/vector/`. [docs/blueprint-schema.md](docs/blueprint-schema.md),
|
|
624
|
+
[docs/phase-1.5/b-flow.md](docs/phase-1.5/b-flow.md).
|
|
625
|
+
- [x] **Notifications natives** : couche d'alerte sans dépendance nouvelle (webhook générique,
|
|
626
|
+
Discord, Telegram, **ntfy** pour la push téléphone — un POST `httpx` chacun), action `notify`
|
|
627
|
+
Act-agnostique (handler partagé, se combine à `when`) + `NotifySink` de fin de run
|
|
628
|
+
(`failure`/`success`/`always`), registre de canaux prêt pour les plugins (Jalon E), échec d'envoi
|
|
629
|
+
contenu (jamais fatal au run, `delivered` exposé). La dédup au changement d'état est désormais
|
|
630
|
+
portée par le scheduler (Jalon D, politique `change`). Exemple zéro config :
|
|
631
|
+
`examples/vector/books-restock-notify.blueprint.json`. [docs/notifications.md](docs/notifications.md),
|
|
632
|
+
[docs/phase-1.5/c-notifications.md](docs/phase-1.5/c-notifications.md).
|
|
633
|
+
- [x] **Scheduler (daemon)** : rejeu persistant d'un Blueprint à heure fixe (cron, fuseau local,
|
|
634
|
+
DST gérés) ou par intervalle, plus le tir unique (`at`). Intégré au daemon (lifespan FastAPI,
|
|
635
|
+
tick 30 s) ; un run planifié passe par `RunManager.submit` — indiscernable d'un run manuel, avec
|
|
636
|
+
le lien `schedule_id` dans l'historique. CLI `aetherius schedule add|list|rm|pause|resume|run`
|
|
637
|
+
(écrit directement dans le store : marche daemon éteint) et API `/v1/schedules` (CRUD + tir
|
|
638
|
+
immédiat). Rattrapage des tirs manqués par politique `misfire` (`skip`/`run_once`/`run_all`) et
|
|
639
|
+
politique d'alerte par schedule (`failure`/`success`/`always`/`change` — dédup au changement
|
|
640
|
+
d'état via le store). **Écran Console dédié** : liste, pause/reprise, suppression, détail avec
|
|
641
|
+
historique et tir manuel (événements en direct), formulaire de création/édition guidé, raccourci
|
|
642
|
+
`s` depuis Library. Exemple zéro config : `examples/vector/quotes-watch.blueprint.json`.
|
|
643
|
+
[docs/scheduler.md](docs/scheduler.md),
|
|
644
|
+
[docs/phase-1.5/d-scheduler.md](docs/phase-1.5/d-scheduler.md).
|
|
645
|
+
- [x] **Actions custom / plugins** : points d'extension activés — un paquet tiers ajoute des
|
|
646
|
+
**actions** et des **canaux de notification** sans forker le cœur. Découverte par entry-points
|
|
647
|
+
(`aetherius.actions`, `aetherius.notify_channels`) chargée au démarrage (CLI, daemon, moteur
|
|
648
|
+
in-process) ; une action plugin embarque sa spec (visible du Studio et du validator, act-agnostique,
|
|
649
|
+
dispatchée en repli après les built-ins) ; gardes de collision (les built-ins restent prioritaires)
|
|
650
|
+
et pannes isolées (un plugin cassé est loggé et sauté, jamais fatal au démarrage). Plugin d'exemple
|
|
651
|
+
exécutable : `examples/plugins/` (action `demo.slugify` + canal `logfile`).
|
|
652
|
+
[docs/plugins.md](docs/plugins.md), [docs/phase-1.5/e-plugins.md](docs/phase-1.5/e-plugins.md).
|
|
653
|
+
- [x] **Déploiement always-on** : recette 24/7 vérifiée de bout en bout pour héberger le daemon sur
|
|
654
|
+
une machine allumée (VPS, Raspberry Pi, NAS) — la réponse honnête au « hors machine ». Deux voies
|
|
655
|
+
dans [`deploy/`](deploy/) : image Docker durcie (multi-stage, non-root, healthcheck, variante Act
|
|
656
|
+
II via `--build-arg BROWSER=1`) + `docker-compose.yml` (volume persistant unique `/data`, port
|
|
657
|
+
publié sur la loopback de l'hôte, Blueprints utilisateur montés) et service systemd utilisateur
|
|
658
|
+
(`enable-linger`, redémarrage automatique). Tout l'état durable (schedules, historique, profils)
|
|
659
|
+
vit sous `AETHERIUS_DATA_DIR` et survit aux redémarrages ; sécurité par défaut : loopback, et
|
|
660
|
+
exposer exige token + reverse proxy TLS. [docs/deployment.md](docs/deployment.md),
|
|
661
|
+
[docs/phase-1.5/f-deployment.md](docs/phase-1.5/f-deployment.md).
|
|
662
|
+
- [x] **Identité réseau** : option `options.proxy` de premier niveau atteignant les **deux** moteurs
|
|
663
|
+
(Vector httpx/curl_cffi, Continuum Playwright ; HTTP/HTTPS/SOCKS5). Rotation de l'IP par run
|
|
664
|
+
(`per_run`/`round_robin`/`random`/`sticky`, pool inline ou défaut d'environnement `AETHERIUS_PROXY_*`),
|
|
665
|
+
prévention de la fuite WebRTC (flag de lancement + init-script, liée au proxy), cohérence géo
|
|
666
|
+
(timezone/locale/langues alignés sur le pays de l'IP, écrasant le profil d'empreinte) et
|
|
667
|
+
impersonation TLS (JA3/JA4) pour Vector via l'extra `[network]`. Identifiants jamais stockés
|
|
668
|
+
(`{{ secrets.x }}`). Exemple : `examples/vector/ip-echo-proxy.blueprint.json` (nécessite un proxy).
|
|
669
|
+
[docs/network.md](docs/network.md), [docs/phase-1.5/g-network.md](docs/phase-1.5/g-network.md).
|
|
670
|
+
- [x] **Durcissement de l'empreinte** : les signaux restants sont fermés **de façon cohérente avec le
|
|
671
|
+
profil** — Canvas et AudioContext (bruit déterministe par profil, stable entre deux lectures),
|
|
672
|
+
énumération des polices (`measureText`), client hints (`Sec-CH-UA` / `navigator.userAgentData`
|
|
673
|
+
dérivés de l'UA du profil, la limite « UA-CH drift » est levée), dimensions d'écran /
|
|
674
|
+
`devicePixelRatio` et WebGL2. Vector (Act I) gagne une **identité d'en-têtes par défaut** (UA +
|
|
675
|
+
client hints + `Accept-Language` alignés) quand `options.stealth` nomme un profil, sans écraser les
|
|
676
|
+
en-têtes explicites du Blueprint ni rien changer aux runs sans stealth. Exemples zéro config :
|
|
677
|
+
`examples/continuum/fingerprint-hardening.blueprint.json` et
|
|
678
|
+
`examples/vector/http-headers-identity.blueprint.json`. [docs/stealth.md](docs/stealth.md),
|
|
679
|
+
[docs/phase-1.5/h-fingerprint.md](docs/phase-1.5/h-fingerprint.md).
|
|
680
|
+
|
|
592
681
|
### Phase 2 — les Acts autonomes (à venir)
|
|
593
682
|
|
|
594
683
|
- [ ] Act III — Oracle (vision + entraînement).
|
|
@@ -250,8 +250,9 @@ aetherius # ouvre la Console
|
|
|
250
250
|
|
|
251
251
|

|
|
252
252
|
|
|
253
|
-
> **État actuel** : la Console est navigable de bout en bout. Library, Runs,
|
|
254
|
-
>
|
|
253
|
+
> **État actuel** : la Console est navigable de bout en bout. Library, Runs, **Schedules** (runs
|
|
254
|
+
> récurrents : liste, tir manuel, historique, création guidée), Catalog, le **Recorder**, le
|
|
255
|
+
> **Blueprint Studio** et **Settings** (démarrer/arrêter le daemon) sont pleinement fonctionnels
|
|
255
256
|
> pour Act I (Vector) et Act II (Continuum, avec l'extra `[browser]`) ; seul **Sessions** affiche
|
|
256
257
|
> honnêtement son jalon en attente (stealth/session). Détails : [docs/console.md](docs/console.md).
|
|
257
258
|
|
|
@@ -391,20 +392,25 @@ console.log(result.outputs.events);
|
|
|
391
392
|
```
|
|
392
393
|
src/aetherius/
|
|
393
394
|
core/ blueprint (models/loader/validator/template), actions (le dictionnaire),
|
|
394
|
-
runtime (engine/context/selector/result), extraction, events, errors, driver
|
|
395
|
+
runtime (engine/context/steps/selector/result), extraction, events, errors, driver
|
|
395
396
|
acts/ vector (I), continuum (II), oracle (III), phantom (IV)
|
|
396
397
|
stealth/ policy, humanizer (mouse/keyboard/scroll/timing), gestures, fingerprint,
|
|
397
398
|
session (store/warmup), ml (optionnel)
|
|
398
399
|
recorder/ blueprint_recorder, gesture_recorder, capture, selector_synth
|
|
399
400
|
builder/ construction headless de Blueprint (factory, catalog, templates)
|
|
400
|
-
console/ interface terminale globale (Textual) : Blueprint Studio, runs,
|
|
401
|
-
sessions, settings — la porte d'entrée de l'outil
|
|
401
|
+
console/ interface terminale globale (Textual) : Blueprint Studio, runs, schedules,
|
|
402
|
+
catalogue, sessions, settings — la porte d'entrée de l'outil
|
|
403
|
+
notify/ canaux d'alerte natifs (webhook/discord/telegram/ntfy) + registre ouvert aux plugins
|
|
404
|
+
store/ état durable SQLite sous ~/.aetherius : schedules, historique des runs, état inter-run
|
|
405
|
+
plugins.py découverte des extensions tierces par entry-points (actions + canaux)
|
|
402
406
|
models/ registry + cache des assets ML runtime
|
|
403
|
-
server/ daemon FastAPI (routes/jobs/schemas)
|
|
407
|
+
server/ daemon FastAPI (routes/jobs/schemas) + scheduler (triggers/misfire/alerts)
|
|
408
|
+
cli/ commandes scriptables (run/validate/serve/record, groupe schedule)
|
|
404
409
|
config/ settings
|
|
405
410
|
contracts/ blueprint.schema.json, openapi.yaml, events.schema.json (source de vérité)
|
|
411
|
+
deploy/ recette always-on : Dockerfile, docker-compose.yml, service systemd
|
|
406
412
|
sdks/ typescript (@aetherius/client), python
|
|
407
|
-
examples/ Blueprints de démonstration
|
|
413
|
+
examples/ Blueprints de démonstration (par Act + plugins/)
|
|
408
414
|
training/ entraînement des modèles Oracle (hors runtime)
|
|
409
415
|
legacy_examples/ code de référence des projets d'origine (UKit, TikTok) + carte de provenance
|
|
410
416
|
```
|
|
@@ -456,7 +462,8 @@ Conventions de contribution (discipline de test, invariants, structure des tests
|
|
|
456
462
|
Le projet avance en deux grandes phases. La **Phase 1** — le socle, utilisable comme **bibliothèque**
|
|
457
463
|
(in-process Python) et comme **service** (daemon + SDK) — est **terminée avec ce jalon** : un premier
|
|
458
464
|
point de contrôle, à éprouver en conditions réelles avant d'attaquer la **Phase 2** (les deux Acts les
|
|
459
|
-
plus lourds).
|
|
465
|
+
plus lourds). Entre les deux, une **Phase 1.5** durcit ce socle pour les workflows **récurrents et
|
|
466
|
+
réactifs** (planification, alertes, réactivité) — voir ci-dessous.
|
|
460
467
|
|
|
461
468
|
### Phase 1 — le socle réutilisable (terminée)
|
|
462
469
|
|
|
@@ -524,6 +531,81 @@ plus lourds).
|
|
|
524
531
|
**Phase 1 terminée.** Aetherius est utilisable comme bibliothèque et comme service ; c'est le point de
|
|
525
532
|
contrôle prévu pour l'éprouver en conditions réelles et corriger avant la suite.
|
|
526
533
|
|
|
534
|
+
### Phase 1.5 — socle opérationnel (en cours)
|
|
535
|
+
|
|
536
|
+
Un palier intermédiaire, dans l'esprit du durcissement du socle : rendre Aetherius capable de porter
|
|
537
|
+
des workflows **récurrents et réactifs** (planifier un Blueprint, réagir aux données extraites,
|
|
538
|
+
alerter au bon moment) avant les Acts autonomes. Le cas fil rouge : surveiller un produit en rupture,
|
|
539
|
+
vérifier plusieurs fois par jour, alerter au retour en stock. Et, dans la même veine furtive que la
|
|
540
|
+
couche stealth, le rendre invisible **au niveau réseau** (proxy, rotation d'IP). Cadrage complet et
|
|
541
|
+
**spécifications par jalon** : [docs/phase-1.5/](docs/phase-1.5/README.md).
|
|
542
|
+
|
|
543
|
+
- [x] **Persistance (`store/`)** : état durable SQLite (stdlib) sous `~/.aetherius` — schedules,
|
|
544
|
+
historique des runs, état inter-run. Fondation des autres jalons. Le daemon y persiste désormais
|
|
545
|
+
l'historique de ses runs. [docs/store.md](docs/store.md),
|
|
546
|
+
[docs/phase-1.5/a-store.md](docs/phase-1.5/a-store.md).
|
|
547
|
+
- [x] **Réactivité et flux conditionnel** : garde d'étape `when` universelle (step sauté = statut
|
|
548
|
+
`skipped` + événement `step_skipped`) et actions `if`/`repeat`/`for_each` exécutées récursivement
|
|
549
|
+
par le moteur sur tous les Acts (validation récursive des branches, variable de boucle `as`,
|
|
550
|
+
rend la réutilisation de session Continuum exprimable). Exemples zéro config dans
|
|
551
|
+
`examples/vector/`. [docs/blueprint-schema.md](docs/blueprint-schema.md),
|
|
552
|
+
[docs/phase-1.5/b-flow.md](docs/phase-1.5/b-flow.md).
|
|
553
|
+
- [x] **Notifications natives** : couche d'alerte sans dépendance nouvelle (webhook générique,
|
|
554
|
+
Discord, Telegram, **ntfy** pour la push téléphone — un POST `httpx` chacun), action `notify`
|
|
555
|
+
Act-agnostique (handler partagé, se combine à `when`) + `NotifySink` de fin de run
|
|
556
|
+
(`failure`/`success`/`always`), registre de canaux prêt pour les plugins (Jalon E), échec d'envoi
|
|
557
|
+
contenu (jamais fatal au run, `delivered` exposé). La dédup au changement d'état est désormais
|
|
558
|
+
portée par le scheduler (Jalon D, politique `change`). Exemple zéro config :
|
|
559
|
+
`examples/vector/books-restock-notify.blueprint.json`. [docs/notifications.md](docs/notifications.md),
|
|
560
|
+
[docs/phase-1.5/c-notifications.md](docs/phase-1.5/c-notifications.md).
|
|
561
|
+
- [x] **Scheduler (daemon)** : rejeu persistant d'un Blueprint à heure fixe (cron, fuseau local,
|
|
562
|
+
DST gérés) ou par intervalle, plus le tir unique (`at`). Intégré au daemon (lifespan FastAPI,
|
|
563
|
+
tick 30 s) ; un run planifié passe par `RunManager.submit` — indiscernable d'un run manuel, avec
|
|
564
|
+
le lien `schedule_id` dans l'historique. CLI `aetherius schedule add|list|rm|pause|resume|run`
|
|
565
|
+
(écrit directement dans le store : marche daemon éteint) et API `/v1/schedules` (CRUD + tir
|
|
566
|
+
immédiat). Rattrapage des tirs manqués par politique `misfire` (`skip`/`run_once`/`run_all`) et
|
|
567
|
+
politique d'alerte par schedule (`failure`/`success`/`always`/`change` — dédup au changement
|
|
568
|
+
d'état via le store). **Écran Console dédié** : liste, pause/reprise, suppression, détail avec
|
|
569
|
+
historique et tir manuel (événements en direct), formulaire de création/édition guidé, raccourci
|
|
570
|
+
`s` depuis Library. Exemple zéro config : `examples/vector/quotes-watch.blueprint.json`.
|
|
571
|
+
[docs/scheduler.md](docs/scheduler.md),
|
|
572
|
+
[docs/phase-1.5/d-scheduler.md](docs/phase-1.5/d-scheduler.md).
|
|
573
|
+
- [x] **Actions custom / plugins** : points d'extension activés — un paquet tiers ajoute des
|
|
574
|
+
**actions** et des **canaux de notification** sans forker le cœur. Découverte par entry-points
|
|
575
|
+
(`aetherius.actions`, `aetherius.notify_channels`) chargée au démarrage (CLI, daemon, moteur
|
|
576
|
+
in-process) ; une action plugin embarque sa spec (visible du Studio et du validator, act-agnostique,
|
|
577
|
+
dispatchée en repli après les built-ins) ; gardes de collision (les built-ins restent prioritaires)
|
|
578
|
+
et pannes isolées (un plugin cassé est loggé et sauté, jamais fatal au démarrage). Plugin d'exemple
|
|
579
|
+
exécutable : `examples/plugins/` (action `demo.slugify` + canal `logfile`).
|
|
580
|
+
[docs/plugins.md](docs/plugins.md), [docs/phase-1.5/e-plugins.md](docs/phase-1.5/e-plugins.md).
|
|
581
|
+
- [x] **Déploiement always-on** : recette 24/7 vérifiée de bout en bout pour héberger le daemon sur
|
|
582
|
+
une machine allumée (VPS, Raspberry Pi, NAS) — la réponse honnête au « hors machine ». Deux voies
|
|
583
|
+
dans [`deploy/`](deploy/) : image Docker durcie (multi-stage, non-root, healthcheck, variante Act
|
|
584
|
+
II via `--build-arg BROWSER=1`) + `docker-compose.yml` (volume persistant unique `/data`, port
|
|
585
|
+
publié sur la loopback de l'hôte, Blueprints utilisateur montés) et service systemd utilisateur
|
|
586
|
+
(`enable-linger`, redémarrage automatique). Tout l'état durable (schedules, historique, profils)
|
|
587
|
+
vit sous `AETHERIUS_DATA_DIR` et survit aux redémarrages ; sécurité par défaut : loopback, et
|
|
588
|
+
exposer exige token + reverse proxy TLS. [docs/deployment.md](docs/deployment.md),
|
|
589
|
+
[docs/phase-1.5/f-deployment.md](docs/phase-1.5/f-deployment.md).
|
|
590
|
+
- [x] **Identité réseau** : option `options.proxy` de premier niveau atteignant les **deux** moteurs
|
|
591
|
+
(Vector httpx/curl_cffi, Continuum Playwright ; HTTP/HTTPS/SOCKS5). Rotation de l'IP par run
|
|
592
|
+
(`per_run`/`round_robin`/`random`/`sticky`, pool inline ou défaut d'environnement `AETHERIUS_PROXY_*`),
|
|
593
|
+
prévention de la fuite WebRTC (flag de lancement + init-script, liée au proxy), cohérence géo
|
|
594
|
+
(timezone/locale/langues alignés sur le pays de l'IP, écrasant le profil d'empreinte) et
|
|
595
|
+
impersonation TLS (JA3/JA4) pour Vector via l'extra `[network]`. Identifiants jamais stockés
|
|
596
|
+
(`{{ secrets.x }}`). Exemple : `examples/vector/ip-echo-proxy.blueprint.json` (nécessite un proxy).
|
|
597
|
+
[docs/network.md](docs/network.md), [docs/phase-1.5/g-network.md](docs/phase-1.5/g-network.md).
|
|
598
|
+
- [x] **Durcissement de l'empreinte** : les signaux restants sont fermés **de façon cohérente avec le
|
|
599
|
+
profil** — Canvas et AudioContext (bruit déterministe par profil, stable entre deux lectures),
|
|
600
|
+
énumération des polices (`measureText`), client hints (`Sec-CH-UA` / `navigator.userAgentData`
|
|
601
|
+
dérivés de l'UA du profil, la limite « UA-CH drift » est levée), dimensions d'écran /
|
|
602
|
+
`devicePixelRatio` et WebGL2. Vector (Act I) gagne une **identité d'en-têtes par défaut** (UA +
|
|
603
|
+
client hints + `Accept-Language` alignés) quand `options.stealth` nomme un profil, sans écraser les
|
|
604
|
+
en-têtes explicites du Blueprint ni rien changer aux runs sans stealth. Exemples zéro config :
|
|
605
|
+
`examples/continuum/fingerprint-hardening.blueprint.json` et
|
|
606
|
+
`examples/vector/http-headers-identity.blueprint.json`. [docs/stealth.md](docs/stealth.md),
|
|
607
|
+
[docs/phase-1.5/h-fingerprint.md](docs/phase-1.5/h-fingerprint.md).
|
|
608
|
+
|
|
527
609
|
### Phase 2 — les Acts autonomes (à venir)
|
|
528
610
|
|
|
529
611
|
- [ ] Act III — Oracle (vision + entraînement).
|