diff --git a/.github/workflows/crates.yml b/.github/workflows/crates.yml
index cfa4d26b7..856e348d8 100644
--- a/.github/workflows/crates.yml
+++ b/.github/workflows/crates.yml
@@ -49,7 +49,7 @@ jobs:
set -o pipefail
actual="$(cargo metadata --no-deps --format-version 1 \
| jq -r '[.packages[] | select(.publish == null) | .name] | sort | join(" ")')"
- if [ "$actual" != "powerio powerio-cli powerio-core powerio-dist powerio-matrix powerio-prob powerio-synth powerio-tnd powerio-tx" ]; then
+ if [ "$actual" != "powerio powerio-archive powerio-cli powerio-core powerio-dist powerio-matrix powerio-prob powerio-synth powerio-tnd powerio-tx" ]; then
echo "publishable workspace members ($actual) do not match the publish list in crates.yml" >&2
exit 1
fi
@@ -61,7 +61,7 @@ jobs:
UA: powerio release workflow (https://github.com/eigenergy/powerio)
OWNER: samtalki
run: |
- for crate in powerio-core powerio-tx powerio-dist powerio-tnd powerio-prob powerio-synth powerio-matrix powerio powerio-cli; do
+ for crate in powerio-core powerio-archive powerio-tx powerio-dist powerio-tnd powerio-prob powerio-synth powerio-matrix powerio powerio-cli; do
resp="$RUNNER_TEMP/$crate-owners.json"
code="$(curl -sS -A "$UA" --max-time 30 -o "$resp" -w '%{http_code}' \
"https://crates.io/api/v1/crates/$crate/owners")" || code=unreachable
@@ -123,7 +123,7 @@ jobs:
# skip-existing), so a re-run after a partial publish only publishes
# what's missing.
run: |
- for crate in powerio-core powerio-tx powerio-dist powerio-tnd powerio-prob powerio-synth powerio-matrix powerio powerio-cli; do
+ for crate in powerio-core powerio-archive powerio-tx powerio-dist powerio-tnd powerio-prob powerio-synth powerio-matrix powerio powerio-cli; do
resp="$RUNNER_TEMP/$crate.json"
code="$(curl -sS -A "$UA" --max-time 30 -o "$resp" -w '%{http_code}' \
"https://crates.io/api/v1/crates/$crate/$VERSION")" || code=unreachable
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
index a9b7789fe..721c355cc 100644
--- a/.github/workflows/docs.yml
+++ b/.github/workflows/docs.yml
@@ -59,7 +59,7 @@ jobs:
- name: Build docs
env:
RUSTDOCFLAGS: "-D warnings"
- run: cargo doc --no-deps --all-features -p powerio-tnd -p powerio -p powerio-core -p powerio-tx -p powerio-synth -p powerio-matrix -p powerio-prob -p powerio-dist -p powerio-capi -p powerio-py -p powerio-wasm
+ run: cargo doc --no-deps --all-features -p powerio-tnd -p powerio -p powerio-core -p powerio-archive -p powerio-tx -p powerio-synth -p powerio-matrix -p powerio-prob -p powerio-dist -p powerio-capi -p powerio-py -p powerio-wasm
- name: Build Python API docs
run: |
python -m pip install --upgrade pip
@@ -143,6 +143,7 @@ jobs:
released / docs.rs
powerio
powerio-core
+ powerio-archive
powerio-tx
powerio-dist
powerio-prob
@@ -152,6 +153,7 @@ jobs:
development / main
powerio
powerio-core
+ powerio-archive
powerio-tx
powerio-dist
powerio-synth
diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml
index 37ae0e559..1dcdfba5c 100644
--- a/.github/workflows/rust.yml
+++ b/.github/workflows/rust.yml
@@ -182,7 +182,7 @@ jobs:
# Bare `cargo test` only covers the default-members; name the C ABI crate
# explicitly so its end-to-end ABI tests run in CI too.
- name: Run tests
- run: cargo test -p powerio -p powerio-tx -p powerio-core -p powerio-synth -p powerio-matrix -p powerio-prob -p powerio-cli -p powerio-capi -p powerio-dist -p powerio-tnd --verbose
+ run: cargo test -p powerio -p powerio-tx -p powerio-core -p powerio-archive -p powerio-synth -p powerio-matrix -p powerio-prob -p powerio-cli -p powerio-capi -p powerio-dist -p powerio-tnd --verbose
- name: Test problem matrix feature
run: cargo test -p powerio --features matrix --verbose
- name: Test gridfm reader feature
@@ -265,7 +265,7 @@ jobs:
- name: Check wasm32 component crates
run: |
cargo check --target wasm32-unknown-unknown -p powerio -p powerio-tx -p powerio-dist \
- -p powerio-core -p powerio-prob -p powerio-matrix
+ -p powerio-core -p powerio-archive -p powerio-prob -p powerio-matrix
cargo check --target wasm32-unknown-unknown -p powerio --features matrix
# A browser consumer that sets `default-features = false` builds with no C
# compiler: SQLite enters only through the default-on `sincal` feature.
diff --git a/AGENTS.md b/AGENTS.md
index a47ca1aa8..320eda3de 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -16,6 +16,9 @@ check the current source, tests, and release notes.
`Diagnostic`, `Error`, `PioModule`, common module records,
`TimeSeries`, `ScenarioSet`, and output destination types. It has no
electrical network, matrix, or solver dependencies.
+- **`powerio-archive`**: bounded in-memory ZIP transport over core, with explicit
+ limits, namespace validation, and lazy verified reads; no electrical types
+ or case discovery.
- **`powerio-tx`**: the format neutral `BalancedNetwork`, the balanced format
readers and writers, normalization, and derived indexed views.
- **`powerio-tnd`**: integrated transmission/distribution composition, explicit
@@ -161,8 +164,8 @@ release on its own.
its platform. Only then does it stage a **draft** GitHub release with the
five assets.
4. A human inspects and publishes the draft. Publishing starts `python.yml`
- (PyPI) and `crates.yml` (crates.io: `powerio-core`, `powerio-tx`, `powerio-dist`,
- `powerio-tnd`, `powerio-prob`, `powerio-matrix`, `powerio`, and
+ (PyPI) and `crates.yml` (crates.io: `powerio-core`, `powerio-archive`,
+ `powerio-tx`, `powerio-dist`, `powerio-tnd`, `powerio-prob`, `powerio-matrix`, `powerio`, and
`powerio-cli`, in dependency order). Both deploy through the `pypi` and
`crates-io` environments, which wait for the maintainer's approval. A
rerun skips files and versions already published. A crate's first
@@ -183,6 +186,7 @@ release on its own.
## Layout
```
+powerio-archive/src lib.rs (ZIP index/cache/limits), preflight.rs, local.rs
powerio-core/src module.rs (PioModule), source.rs, output.rs,
diagnostic.rs, codes.rs, error.rs, records.rs,
time_series.rs, scenario.rs, component_id.rs,
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 769750923..1bac64c14 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,9 @@
## Unreleased
+- Add `powerio-archive`: bounded ZIP indexing and verified member reads with
+ explicit limits and namespace checks, as shared infrastructure for #774.
+
## 0.11.7
**AC optimal transmission switching**
diff --git a/Cargo.lock b/Cargo.lock
index 5907f85ed..d6c035e1e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2431,6 +2431,14 @@ dependencies = [
"zip",
]
+[[package]]
+name = "powerio-archive"
+version = "0.11.7"
+dependencies = [
+ "powerio-core",
+ "zip",
+]
+
[[package]]
name = "powerio-capi"
version = "0.11.7"
diff --git a/Cargo.toml b/Cargo.toml
index f7717405e..901c2d492 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,6 +3,7 @@ members = [
"powerio",
"powerio-tx",
"powerio-core",
+ "powerio-archive",
"powerio-tnd",
"powerio-matrix",
"powerio-synth",
@@ -24,6 +25,7 @@ default-members = [
"powerio",
"powerio-tx",
"powerio-core",
+ "powerio-archive",
"powerio-tnd",
"powerio-matrix",
"powerio-synth",
@@ -55,6 +57,7 @@ powerio = { path = "powerio", version = "0.11.7" }
# Model crates remain independent; the facade enables optional format adapters.
powerio-tx = { path = "powerio-tx", version = "0.11.7", default-features = false }
powerio-core = { path = "powerio-core", version = "0.11.7" }
+powerio-archive = { path = "powerio-archive", version = "0.11.7" }
powerio-matrix = { path = "powerio-matrix", version = "0.11.7" }
powerio-synth = { path = "powerio-synth", version = "0.11.7" }
powerio-prob = { path = "powerio-prob", version = "0.11.7" }
diff --git a/README.md b/README.md
index 4588aaadd..4f6944ff9 100644
--- a/README.md
+++ b/README.md
@@ -179,6 +179,7 @@ depend on just the layer they use.
|---|---|
| `powerio` | `PioValue`, `parse`, `emit`, `serialize`, `deserialize` |
| `powerio-core` | `Source`, `PioModule`, diagnostics, collections, destinations |
+| `powerio-archive` | Bounded ZIP indexing and verified member reads |
| `powerio-tx` | `BalancedNetwork` and balanced format readers and writers |
| `powerio-dist` | `MulticonductorNetwork` and OpenDSS, PMD, BMOPF, CIM converters |
| `powerio-prob` | Operating points, updates, calculation instances and solutions |
diff --git a/docs/diagrams/architecture.dot b/docs/diagrams/architecture.dot
index 0c3c7c293..4f819cf60 100644
--- a/docs/diagrams/architecture.dot
+++ b/docs/diagrams/architecture.dot
@@ -36,6 +36,8 @@ digraph powerio_architecture {
"powerio-core" [label = "powerio-core\nSource, Diagnostic, Error,\nPioModule, series, output"];
"powerio-tnd" [label = "powerio-tnd\nIntegratedNetwork + transforms\nSINCAL adapters"];
+ "powerio-archive" [label = "powerio-archive\nbounded ZIP transport"];
+ "powerio-archive" -> "powerio-core";
"powerio-synth" -> "powerio-tx";
"powerio-tx" -> "powerio-core";
"powerio-tnd" -> "powerio-tx";
diff --git a/docs/src/assets/architecture.svg b/docs/src/assets/architecture.svg
index 7002ebfc7..ca4f029ba 100644
--- a/docs/src/assets/architecture.svg
+++ b/docs/src/assets/architecture.svg
@@ -1,238 +1,249 @@
-