Skip to content

Commit 3119006

Browse files
Merge branch 'main' into feat/issue-255-result-schema-migration-guard
2 parents 0629c62 + 0c8e4fe commit 3119006

60 files changed

Lines changed: 10119 additions & 186 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.devcontainer/README.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# Devcontainer Setup
2+
3+
> Reproducible development environment for ApexChainx smart contracts.
4+
> Works with GitHub Codespaces and VS Code Dev Containers.
5+
6+
## What's Included
7+
8+
| Tool | Purpose |
9+
|------|---------|
10+
| Rust (latest) | Contract compilation and testing |
11+
| `wasm32-unknown-unknown` target | Soroban WASM builds |
12+
| `just` command runner | One-command dev workflows |
13+
| Node.js LTS | TypeScript tooling scripts |
14+
| `cargo clippy` | Linting on save |
15+
| `rust-analyzer` | IDE support |
16+
17+
## Getting Started
18+
19+
### GitHub Codespaces
20+
21+
1. Click **Code****Codespaces****Create codespace on main**
22+
2. Wait for the environment to build (~3–5 minutes first time)
23+
3. The post-create script runs `just bootstrap` automatically
24+
4. Run `just ci` to verify everything works
25+
26+
### VS Code (Local)
27+
28+
1. Install [Dev Containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers)
29+
2. Open the repo folder in VS Code
30+
3. Click **Reopen in Container** when prompted
31+
4. Run `just ci` to verify
32+
33+
## Daily Workflow
34+
35+
```bash
36+
# Before committing
37+
just fmt # Auto-format code
38+
just lint # Run clippy
39+
just check # Type-check
40+
41+
# Before opening a PR
42+
just ci # Full CI pipeline locally
43+
44+
# Fast release validation
45+
just release-replay # Minimal validation (fast)
46+
47+
# Generate a release summary
48+
just release-summary # From [Unreleased] in CHANGELOG
49+
```
50+
51+
## CI Parity
52+
53+
The devcontainer mirrors the CI environment (`ubuntu-latest`, Rust stable,
54+
`wasm32-unknown-unknown` target). Run `just ci` to reproduce the exact
55+
sequence that CI gates on before opening a PR.
56+
57+
## Troubleshooting
58+
59+
| Problem | Solution |
60+
|---------|----------|
61+
| `cargo: command not found` | Rebuild the devcontainer |
62+
| WASM target missing | Run `just bootstrap` |
63+
| `npx` not found | Ensure Node.js feature was installed |
64+
| Build errors after pull | Run `cargo clean && just ci` |

.devcontainer/devcontainer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
}
2929
}
3030
},
31-
"postCreateCommand": "rustup target add wasm32-unknown-unknown && cargo install just && just --list",
31+
"postCreateCommand": "cargo install just && just bootstrap && just --list",
3232
"remoteUser": "vscode",
3333
"containerEnv": {
3434
"CARGO_TERM_COLOR": "always",

.github/workflows/ci.yml

Lines changed: 48 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,45 @@ jobs:
167167
run: cargo test --lib fuzz_tests::
168168

169169

170+
parity-check:
171+
name: Parity Check (canonical baseline)
172+
runs-on: ubuntu-latest
173+
# This job is a release gate: it verifies that the current compute_result
174+
# implementation produces identical outputs to the locked-in historical
175+
# golden vectors in test_snapshots/tests/parity_baseline.json.
176+
# A failure here means a calculation regression has been introduced and
177+
# must be reviewed before merging or cutting a release.
178+
179+
steps:
180+
- name: Checkout code
181+
uses: actions/checkout@v4
182+
183+
- name: Install Rust toolchain
184+
uses: dtolnay/rust-toolchain@1.94.1
185+
186+
- name: Cache cargo registry
187+
uses: actions/cache@v4
188+
with:
189+
path: |
190+
~/.cargo/registry
191+
~/.cargo/git
192+
apexchainx_calculator/target
193+
key: parity-${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
194+
restore-keys: |
195+
parity-${{ runner.os }}-cargo-
196+
197+
- name: Run parity checker against canonical baseline
198+
working-directory: apexchainx_calculator
199+
run: cargo test --lib parity_tests::
200+
201+
- name: Upload parity baseline as artifact (for release traceability)
202+
uses: actions/upload-artifact@v4
203+
with:
204+
name: parity-baseline
205+
path: apexchainx_calculator/test_snapshots/tests/parity_baseline.json
206+
retention-days: 90
207+
208+
170209
provenance-hashes:
171210
name: Provenance & Hashes
172211
runs-on: ubuntu-latest
@@ -180,25 +219,19 @@ jobs:
180219
with:
181220
targets: wasm32-unknown-unknown
182221

183-
- name: Build WASM release
184-
working-directory: apexchainx_calculator
185-
run: cargo build --target wasm32-unknown-unknown --release
222+
- name: Install just
223+
run: cargo install just
186224

187-
- name: Generate hash
188-
run: |
189-
WASM=target/wasm32-unknown-unknown/release/apexchainx_calculator.wasm
190-
if [ -f "$WASM" ]; then
191-
sha256sum "$WASM" | awk '{print $1 " apexchainx_calculator.wasm"}' > provenance.sha256
192-
echo "Hash generated successfully"
193-
cat provenance.sha256
194-
else
195-
echo "WASM file not found at $WASM"
196-
exit 1
197-
fi
225+
- name: Generate and save hash
226+
run: just hash-save
227+
228+
- name: Verify hash against committed file
229+
run: just hash-verify
230+
continue-on-error: true
198231

199232
- name: Upload artifact
200233
uses: actions/upload-artifact@v4
201234
with:
202235
name: pr-provenance-hash
203-
path: provenance.sha256
236+
path: artifacts/apexchainx_calculator.wasm.sha256
204237
retention-days: 30

.gitignore

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,12 @@ apexchainx_calculator/fuzz/artifacts/
1010

1111

1212
# Soroban
13-
test_snapshots/
13+
# Exclude volatile CI-generated snapshots but keep the committed parity baseline.
14+
# Note: git negation cannot un-exclude files inside an excluded directory, so we
15+
# exclude individual subdirectories/patterns rather than the whole test_snapshots/ tree.
16+
apexchainx_calculator/test_snapshots/tests/*.snap
17+
apexchainx_calculator/test_snapshots/tests/*.json.tmp
18+
# Keep parity_baseline.json tracked (no rule excludes it).
1419
*.wasm
1520

1621
# IDE
@@ -30,6 +35,9 @@ Thumbs.db
3035
*.tmp
3136
*.temp
3237

38+
# Node tooling
39+
node_modules/
40+
3341
# Environment secrets
3442
.env
3543
.env.*

CHANGELOG.md

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,38 @@
88

99
## [Unreleased]
1010

11+
### Changed
12+
- `test_storage_key_namespace_symbols_are_distinct` now covers all 17 on-chain storage key constants (previously omitted `SEVERITY_CALC_COUNTS_KEY`, `SEVERITY_VIOL_COUNTS_KEY`, `LAST_CALCULATION_LEDGER_KEY`, `LAST_VIOLATION_LEDGER_KEY`, and `LAST_CFG_UPDATE_KEY`). The assertion now includes the colliding indices in its error message for faster diagnosis. A maintenance comment listing every key and a pointer to this test was added to both the storage-key block in `lib.rs` and the test itself so future contributors know to update both locations when adding a new key.
13+
### Fixed
14+
- Replaced stale `test_zero_threshold_always_violated` test in `threshold_config.rs`
15+
with two correct tests that verify `set_config` rejects `threshold_minutes = 0`
16+
with `InvalidThreshold` (code 8). The previous test incorrectly assumed a
17+
zero-threshold write would succeed and then tested calculation behaviour on an
18+
impossible stored state.
19+
- Hardened `validate_cross_severity_penalty_ordering` in `lib.rs` to use
20+
`.ok_or(SLAError::InvalidSeverity)?` instead of `.unwrap()` when indexing
21+
into the canonical severity list. The function is now panic-free: if the
22+
internal severity list invariant is ever broken the call surfaces a
23+
deterministic `InvalidSeverity` error rather than an unrecoverable host trap.
1124
### Added
25+
- `docs/CONTRACT_SHAPE_CHANGE_CHECKLIST.md` — release-readiness checklist for PRs that touch storage keys, `STORAGE_VERSION`, event topic constants, or event payload fields; cross-referenced from `CONTRIBUTING.md` as SC-100
26+
- **[SC-509] SLAError Addition Workflow** (#253) — comprehensive contributor guide for adding, deprecating, or reviewing `SLAError` variants without breaking backend adapter logic. See `docs/sla-error-additions-guide.md`.
27+
- `error_responses::is_severity_not_in_set` — typed helper predicate for `SLAError::SeverityNotInSet` (#253)
28+
- `docs/sla-error-additions-guide.md` — step-by-step guide covering SLAError enum management, the typed helper layer, compatibility expectations, and testing requirements (#253)- `docs/CONTRACT_MAINTENANCE_POLICY.md` — comprehensive maintenance policy covering `#[contracttype]` compatibility notes (#279), response-shape stability (#283), version negotiation (#284), API archetypes (#285), event payload size checks (#286), event drift review (#287), history write audit (#288), telemetry counters (#289), and role-change incident review (#290)
29+
- `docs/CONTRACT_LIFECYCLE.md` — Mermaid state-transition diagrams for the `apexchainx_calculator` contract lifecycle: top-level lifecycle, pause/unpause, storage migration, config-freeze, admin transfer (two-step), and operator handoff flows; plus the combined orthogonal state matrix and invariants table (closes #256)- `docs/CONTRACT_MAINTENANCE_POLICY.md` — comprehensive maintenance policy covering `#[contracttype]` compatibility notes (#279), response-shape stability (#283), version negotiation (#284), API archetypes (#285), event payload size checks (#286), event drift review (#287), history write audit (#288), telemetry counters (#289), and role-change incident review (#290)- `tooling/release-summary.ts` — release summary generator for maintainers (#280)
30+
- `.devcontainer/` — reproducible dev container workspace with Rust + WASM target + just + Node.js (#281)
31+
- `just bootstrap` target — session-safe, idempotent one-command local bootstrap for the Rust WASM contract workflow: verifies rustup, installs the pinned `1.94.1` toolchain with `rustfmt` + `clippy` components, adds `wasm32-unknown-unknown` target, and verifies `cargo` is on `PATH` (closes #257)
1232
- `docs/CONTRACT_MAINTENANCE_POLICY.md` — comprehensive maintenance policy covering `#[contracttype]` compatibility notes (#279), response-shape stability (#283), version negotiation (#284), API archetypes (#285), event payload size checks (#286), event drift review (#287), history write audit (#288), telemetry counters (#289), and role-change incident review (#290)
1333
- `RESULT_SCHEMA_FIELD_COUNT` constant — compile-time sentinel recording the number of named fields in `SLAResult`; must be updated alongside `RESULT_SCHEMA_VERSION` when the result layout changes (#255)
1434
- `SLAResultSchema::result_field_count` — exposes `RESULT_SCHEMA_FIELD_COUNT` to backend consumers via `get_result_schema()` so they can detect layout drift at runtime (#255)
1535
- `schema_migration_tests.rs` — CI-backed guardrail tests for `get_result_schema()`: exhaustive `SLAResult` destructure (compile-time gate), field count sentinel, symbol stability, deprecated-symbols invariant, and `get_config_bundle` consistency (closes #255)
1636
- `docs/result-schema-migration-guard.md` — documentation for the result schema migration process, describing the two-level guardrail, step-by-step change process, and backend consumer guidance (closes #255)
37+
- `docs/EVENT_DRIFT_CHECKLIST.md` — standalone quick-reference event drift review checklist for everyday maintainer use (#287)
1738
- `tooling/release-summary.ts` — release summary generator for maintainers (#280)
18-
- `.devcontainer/` — reproducible dev container workspace with Rust + WASM target + just + Node.js (#281)
19-
- `just bootstrap` target — one-command local environment setup (#281)
20-
- Historical parity checker test (`test_historical_parity_golden_results`) — validates current contract behavior against known golden results for release regression detection (#282)
39+
- `scripts/release-replay.ts` — minimal release candidate validation command for fast pre-release checks (#270)
40+
- `just release-replay` and `just release-replay-full` targets — fast and full release validation (#270)
41+
- `.devcontainer/` — reproducible dev container workspace with Rust + WASM target + just + Node.js, including setup README (#281)
42+
- `just bootstrap` target — one-command local environment setup (#281)- Historical parity checker test (`test_historical_parity_golden_results`) — validates current contract behavior against known golden results for release regression detection (#282)
2143
- `get_config_version_hash` — deterministic hash of the current config snapshot for backend parity validation
2244
- `get_result_schema` — explicit schema descriptor for SLA result encoding (status, payment type, rating symbols)
2345
- `calculate_sla_view` — read-only simulation of SLA calculation without state mutation or auth requirement
@@ -46,6 +68,9 @@
4668
- Event Correlation IDs — cross-contract tracing via deterministic correlation IDs generated by `generate_correlation_id` from ledger sequence and formatted with `correlation_event_topics` (SC-W5-079)
4769
- Settlement Intent Event (`set_int`) — Published on every `calculate_sla` call alongside `sla_calc` event for backend reconciliation. It uses topics `(set_int, v1, severity)` and payload `(outage_id: Symbol, status: Symbol, payment_type: Symbol, amount: i128, config_version_hash: u64, recorded_at: u64)` (SC-W5-041)
4870
- `docs/AUDIT_TRAIL.md` — human-readable one-pager cataloguing every event topic, payload field, emission site, and backend recovery implication, sourced directly from `event_schema.rs` and the `EVENT_*` constants in `lib.rs` (closes #106)
71+
- `docs/PUBLIC_FUNCTION_DOC_POLICY.md` (SC-102) — repository-level policy enforcing doc comments on all public items with compile-time enforcement via `#![deny(missing_docs)]` (closes #214)
72+
- `docs/UPGRADE_REVIEW_CHECKLIST.md` (SC-103) — admin-facing checklist for safely reviewing contract upgrade proposals (closes #212)
73+
- `docs/SECURITY_REVIEW_TEMPLATE.md` (SC-104) — standardised security review template for new contract modules (closes #210)
4974

5075
### Changed
5176
- `pause` now requires a `reason: String` parameter, records pause metadata (reason, timestamp, initiator), and emits an event payload with the paused status (breaking)

0 commit comments

Comments
 (0)