HTTP (`http::*`):
- `HttpService` trait (picloud-shared) + reqwest-backed `HttpServiceImpl`
(manager-core), wired into the `Services` bundle.
- SSRF deny-list applied to the resolved IP via a custom reqwest
`dns_resolver` (covers every redirect hop + defeats DNS rebinding) plus
a literal-IP check at URL-parse time. Scheme/port restrictions, request
+ response body caps (stream-with-cap), layered timeout. Error reason is
a CIDR category, never the IP. `PICLOUD_HTTP_ALLOW_PRIVATE` dev override
(logs a startup warning).
- Rhai bridge with three-arg split `verb(url, body, opts)` (resolves the
brief's body-vs-opts contradiction; unknown opt keys throw). Body
dispatch by type; response `#{status,headers,body,body_raw}` with JSON
auto-parse; non-2xx does not throw.
- `Capability::AppHttpRequest` → existing `script:write` scope (no new
Scope variant). `SdkCallCx` gains `script_id` (attribution + User-Agent).
Cron triggers (4th trigger kind):
- Migration 0017 widens the kind/source_kind CHECKs and adds
`cron_trigger_details`. `cron`/`chrono-tz` parse + validate 6-field
schedules and IANA timezones.
- `spawn_cron_scheduler` polls due triggers and enqueues to the universal
outbox; the dispatcher delivers them (one-line match-arm extension).
Catch-up fires exactly once per trigger per tick, not once per missed
window. `ctx.event.cron` for handlers.
- `POST /api/v1/admin/apps/{id}/triggers/cron` reuses the v1.1.3
cross-app + kind!=module target check.
- Dashboard: admin-gated Triggers tab (cron create form + list).
Follow-ups: redact module backend errors at the resolver boundary (log
original at error level); pin `rhai = "=1.24"`; CHANGELOG incl. retroactive
v1.1.3 cross-app-trigger security note. Version bumps: workspace 1.1.4,
SDK 1.5, dashboard 0.10.0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
48 lines
1.5 KiB
TOML
48 lines
1.5 KiB
TOML
[package]
|
|
name = "picloud-executor-core"
|
|
version.workspace = true
|
|
edition.workspace = true
|
|
rust-version.workspace = true
|
|
license.workspace = true
|
|
|
|
[lints]
|
|
workspace = true
|
|
|
|
[dependencies]
|
|
picloud-shared.workspace = true
|
|
|
|
serde.workspace = true
|
|
serde_json.workspace = true
|
|
thiserror.workspace = true
|
|
tokio.workspace = true
|
|
tracing.workspace = true
|
|
uuid.workspace = true
|
|
chrono.workspace = true
|
|
async-trait.workspace = true
|
|
# `internals` feature surfaces `rhai::Stmt`, `rhai::Expr`, `ASTFlags`
|
|
# (used by the v1.1.3 module-shape validator to walk top-level
|
|
# statements and accept only `fn` / `const` / `import`). Pinned at
|
|
# the workspace level; bumping rhai is a deliberate, reviewed change.
|
|
rhai = { workspace = true, features = ["internals"] }
|
|
|
|
# v1.1.3 — per-module compiled-Module cache lives in this crate so the
|
|
# resolver can reuse compiled modules across invocations.
|
|
lru.workspace = true
|
|
|
|
# Stdlib utility modules — see crates/executor-core/src/sdk/stdlib/.
|
|
regex.workspace = true
|
|
rand.workspace = true
|
|
base64.workspace = true
|
|
hex.workspace = true
|
|
percent-encoding.workspace = true
|
|
# v1.1.4 — `http::post_form` uses `url::form_urlencoded` for correct
|
|
# application/x-www-form-urlencoded body encoding.
|
|
url.workspace = true
|
|
|
|
[dev-dependencies]
|
|
async-trait.workspace = true
|
|
# v1.1.4 §10a: capture tracing output to assert the original module
|
|
# backend error is logged at error level after being redacted from the
|
|
# script-visible message.
|
|
tracing-subscriber.workspace = true
|