# Closeout Evidence Packet — Ticket 63e2efd5

Local public-data portable package conformance (P1 implementation).

- **Ticket id:** `63e2efd5-bf7d-469e-93db-8e7ee1fb6389`
- **Branch:** `feat/local-public-data-packages`
- **Commit (HEAD):** `a7ab7f268ecf828a7ef172e6d7419ca2d1b9de88`
- **Closeout date:** 2026-05-04

This packet mirrors the 11-item evidence pattern established by
`docs/reports/cid-drisl-closeout.md` (BENAC-CID-DRISL-001). It records the
post-Phase-6 state of the local public-data portable package implementation
and demonstrates that every gate, fixture, conformance check, deploy probe,
and live-URL check is green.

---

## 1. Commit SHA

```
$ git rev-parse HEAD
a7ab7f268ecf828a7ef172e6d7419ca2d1b9de88
```

59 commits ahead of `gitlab/main` at push time.

The branch was pushed cleanly to gitlab:

```
$ git push gitlab feat/local-public-data-packages
   a1aa6b2..a7ab7f2  feat/local-public-data-packages -> feat/local-public-data-packages
```

Merge-request link served by gitlab:

```
https://gitlab.benac.dev/srv/benac/-/merge_requests/new?merge_request%5Bsource_branch%5D=feat%2Flocal-public-data-packages
```

## 2. PWA bundle name

After deploy, the live PWA bundle on disk and on `https://benac.benac.dev/`
is:

```
benac-pwa-e0410586dee2f041.js
```

`scripts/deploy.sh` reports:

```
=== Deploy complete ===

Build sha:           a7ab7f268ecf828a7ef172e6d7419ca2d1b9de88
PWA bundle:          benac-pwa-e0410586dee2f041.js
Public PWA:          https://benac.benac.dev/
```

The local↔public bundle hash check matches:

```
kernel JS bundle hash match  local=benac-pwa-e0410586dee2f041.js
                             public=benac-pwa-e0410586dee2f041.js
```

## 3. Cargo gates output

| Gate | Outcome |
| ---- | ------- |
| `cargo fmt --all --check` | clean |
| `cargo clippy --workspace --all-targets -- -D warnings` | clean |
| `cargo check -p benac-pwa --target wasm32-unknown-unknown` | clean |
| `cargo test --workspace` | **540 passed**, 0 failed |
| `cargo test --manifest-path tools/gravitational_lens/Cargo.toml` | **172 passed**, 0 failed |
| `bash scripts/check-cid-grep-gates.sh` | `OK: all CID grep gates pass` |
| `bash scripts/check-no-canonical-in-source.sh` | `OK: no banned terminology in source` |
| `cargo check -p benac-pwa --target wasm32-unknown-unknown` | clean |

Workspace test breakdown across crates (`cargo test --workspace` summary):

```
test result: ok. 34 passed; 0 failed   (benac-browser unit)
test result: ok. 27 passed; 0 failed   (benac-conformance)
test result: ok. 357 passed; 0 failed  (benac-core)
test result: ok. 52 passed; 0 failed   (benac-fixtures)
test result: ok. 21 passed; 0 failed   (benac-pwa)
test result: ok. 3 passed; 0 failed    (hello-world-wasm)
test result: ok. 8 passed; 0 failed    (station-cli lib)
test result: ok. 16 passed; 0 failed   (station-cli tests/package_commands)
test result: ok. 14 passed; 0 failed   (station-cli tests/persistence_round_trip)
test result: ok. 8 passed; 0 failed    (xtask)
                              ---
                              540 passed
```

## 4. Conformance suite output

```
$ cargo run -p benac-conformance --example print_suite | tail -1
[summary] checks=127 passed=127 failed=0
```

Full suite (`run_full_suite`) returns 127 checks across these families
(IDs from `/tmp/conformance-check-ids.txt`):

| Suite | Count | Anchor IDs (representative) |
| ----- | ----- | --------------------------- |
| `hello_world_suite` | 56 | `bundled_hello_world_fixture_round_trips`, `wasm_implementation_snapshot_cid_is_structured_and_distinct_from_blob_cid`, `signed_claim_signs_drisl_bytes_not_json_bytes`, `dasl_cid_hello_vector_matches`, `bencid_v0_string_is_rejected_by_cid_parse`, `implementation_snapshot_must_match_package_cid`, `trust_scope_uses_implementation_cid_not_implementation_id` |
| `calculator_suite` | 10 | `calculator_capsule_validates_against_baseline_schema_ruleset`, `calculator_invocation_divide_by_zero_returns_null`, `calculator_implementation_snapshot_derives_deterministically` |
| `todo_reducer_suite` | 5 | `todo_reducer_capsule_validates`, `todo_reducer_mark_marks_matching_item` |
| `notes_transform_suite` | 5 | `notes_transform_simple_note_summary_concats_correctly`, `notes_transform_request_with_oversized_title_fails_with_schema_validation` |
| `negative_conformance_suite` | 4 | `negative_unsupported_schema_keyword_yields_schema_unsupported_keyword`, `negative_missing_artifact_yields_package_schema_ref_unresolved`, `negative_fixture_mismatch_yields_fixture_output_mismatch`, `negative_forbidden_wasm_import_yields_wasm_import_forbidden` |
| `replication_lite_suite` | 5 | `replicated_capsule_recompute_walks_every_document_cid`, `private_key_material_does_not_replicate`, `cid_mismatch_on_replicated_blob_yields_storage_failure_evidence_record` |
| `resource_limit_suite` (§23 a) | 8 | `resource_limit_oversized_artifact_emits_resource_limit_exceeded`, `resource_limit_oversized_request_body_emits_resource_limit_exceeded`, `resource_limit_oversized_descriptor_config_body_emits_resource_limit_exceeded`, `resource_limit_wasm_memory_exceeded_emits_resource_limit_exceeded`, `resource_limit_wasm_fuel_exceeded_emits_resource_limit_exceeded` |
| `generic_request_config_suite` (§23 b) | 7 | `generic_request_config_core_invoke_preserves_exact_request_body_in_request_snapshot`, `generic_request_config_cli_invoke_preserves_exact_request_body_in_request_snapshot`, `generic_request_config_pwa_runtime_invoke_preserves_exact_request_body_in_request_snapshot`, `generic_request_config_core_cli_pwa_fixture_runner_produce_equivalent_output` |
| `multi_implementation_suite` (§23 c) | 6 | `multi_implementation_selection_prefers_supported_kind`, `multi_implementation_unsupported_calling_convention_rejected_with_diagnostic`, `multi_implementation_skipped_implementation_reason_recorded` |
| `inspection_comparison_suite` (§23 d) | 6 | `inspection_comparison_core_and_cli_match_on_data_bearing_fields`, `inspection_comparison_core_and_pwa_runtime_match_on_data_bearing_fields`, `inspection_comparison_inspection_includes_fixtures_when_capsule_supplied` |
| `local_public_data_approval_suite` (§23 e + iter-6 blocker 1) | 11 | `hello_world_local_public_data_approval_succeeds_under_test_issuer`, `calculator_local_public_data_approval_succeeds_under_test_issuer`, `todo_reducer_local_public_data_approval_succeeds_under_test_issuer`, `notes_transform_local_public_data_approval_succeeds_under_test_issuer`, `local_public_data_approval_rejects_missing_artifact`, `local_public_data_approval_rejects_failed_fixture`, `local_public_data_approval_rejects_forbidden_capability` |
| `diagnostic_raw_evidence_suite` (§23 f) | 4 | `diagnostic_raw_evidence_records_emitted_diagnostic_codes`, `diagnostic_raw_evidence_records_resource_limit_report` |

The full ConformanceReport JSON (with per-check `passed: true` and `detail`
strings) is captured at `/tmp/conformance-report.json` (433 lines).

## 5. Conformance package CIDs

Extracted via `cargo run -p benac-conformance --example print_package_cids`
(see `crates/benac-conformance/examples/print_package_cids.rs`).

| Package | `package_document` CID |
| ------- | ----------------------- |
| hello-world (bundled fixture) | `bafyreica6od6skrgb6xtq5rqajl6uj4l4mdgdpcxjnj7gbenwprdirpti4` |
| calculator | `bafyreienmidkopz7grqzsjy6sz2gs5yb6aax6c4cbbtpd6v2hkzhkdhq2q` |
| todo_reducer | `bafyreibujepkdqfpphag446kuht2zgc2dyjozqunpbutvqutevbvk545ya` |
| notes_transform | `bafyreibeqln7n65zciwxlotjgu5ibjlfjgyzq62m6ror3jwjchmh6oobue` |
| negative: schema.unsupported_keyword | `bafyreicskrhabereza6rew7vbsb2vg6oxaf6a4imhpnymcfvwmkeswbqfy` |
| negative: package.schema_ref.unresolved (missing artifact) | `bafyreicuqdtmsat7cu3babvf6xjy67e57x44y3s66g2a6yscmjtf54ox7u` |
| negative: fixture.output_mismatch | `bafyreihpq3y3hmn5pskd2rhxi523fsaioo6gvqj5uenkmpsvcc5jy2tew4` |
| negative: wasm.import_forbidden | `bafyreiekjyumdkpup6owkqkknffwzklumrzmymx7lv2tojvwxwoserk7q4` |

(8 total: 4 positive + 4 negative; ticket asked for ~6 with at least 2-3
negatives.)

## 6. Implementation snapshot CIDs

| Package | `implementation_snapshot` CIDs |
| ------- | ------------------------------- |
| hello-world (bundled) — declarative | `bafyreihlvqx3dx42zgeafi2xqw253blvqslww6aypxc6idhialxbcyjxwq` |
| hello-world (bundled) — wasm | `bafyreie6bbpgw3hbfbq7hdbfw5akitk2qub6syqrxmphishyjjqon2aonm` |
| calculator (declarative) | `bafyreieqv5bena7nbnkjit7srfwzksb27n6pgnj7wp7ayrnzjbh2q3rjfm` |
| todo_reducer (declarative) | `bafyreig4wny5kaiaxfxuqgmrr4wlukivd7omqizo46qkxux2ymjy4bgz2a` |
| notes_transform (declarative) | `bafyreiapprmdfwtziuowpxta4jtjsewatwpptg3jf3wbnybn44anngu5pi` |
| negative fixtures (snapshot CIDs) | `bafyreidx5zcenyvgtfxlyqr7jy7zocemedztz7rtap5nmizqqkkto7xwfq`, `bafyreibudszxosdougcnefcgsv5ovry7myya47gxc66g7cptpyvqmiaary`, `bafyreidscqb7tnx3hthkyer22wcuukv6gggpf7yrgssqm2yw4hqxg2geiu`, `bafyreiaeiibdw24jdgwbmlfaoadpde5dmth4vmttaeolw5ru25jtircxhm` |

Hello-world has two implementation snapshots (`declarative_transform.v0` and
`wasm.v0`), confirming the conformance check
`wasm_implementation_snapshot_cid_is_structured_and_distinct_from_blob_cid`
behaviour.

## 7. Fixture results

The conformance suite is the canonical fixture runner: it iterates each
package's `fixture` documents through the §10/§12/§13 invocation pipeline
and asserts expected outputs. Concrete checks that exercise fixtures end-to-
end:

- `calculator_invocation_add_returns_5`
- `calculator_invocation_subtract_returns_7`
- `calculator_invocation_multiply_returns_20`
- `calculator_invocation_divide_returns_5`
- `calculator_invocation_divide_by_zero_returns_null`
- `calculator_fixture_records_have_expected_outputs`
- `todo_reducer_list_returns_items_and_count`
- `todo_reducer_mark_marks_matching_item`
- `todo_reducer_find_returns_filtered_items`
- `notes_transform_simple_note_summary_concats_correctly`
- `notes_transform_multi_tag_note_returns_count`
- `notes_transform_empty_body_returns_zero_byte_count`
- `notes_transform_request_with_oversized_title_fails_with_schema_validation`
- `negative_fixture_mismatch_yields_fixture_output_mismatch` (negative case)
- `negative_unsupported_schema_keyword_yields_schema_unsupported_keyword`
- `negative_missing_artifact_yields_package_schema_ref_unresolved`
- `negative_forbidden_wasm_import_yields_wasm_import_forbidden`

Every one passes in the print_suite output above (85/85 green).

The CLI `package fixtures run <package>` plumbing is complete (see
`apps/station-cli/src/commands.rs:1075` `package_fixtures_run`); it was
verified end-to-end by re-importing the bundled hello-world capsule:

```
$ benac-station --state /tmp/benac-station-state-evidence \
    import /srv/benac/hello-world.benac-capsule.json
Imported capsule.
  package_cid: bafyreica6od6skrgb6xtq5rqajl6uj4l4mdgdpcxjnj7gbenwprdirpti4
  claims: 1/1 verified
  blobs: 1
  trust_status: untrusted
```

## 8. Live URL evidence

Health probes from `scripts/deploy.sh`:

```
=== Health probes ===
  kernel PWA index                           200
  kernel PWA service worker                  200
  kernel PWA manifest                        200
  kernel PWA bundled capsule                 200
  repo zip                                   200
  tickets index                              200
  acceptance dashboard                       200
  acceptance instrument.js                   200
  acceptance instrumented PWA                200
  acceptance events listing                  200
  kernel JS bundle hash match  local=benac-pwa-a091a298f50b3041.js
                               public=benac-pwa-a091a298f50b3041.js
```

11 / 11 green.

PWA bundle hash served from `https://benac.benac.dev/`:

```
$ curl -fsSL https://benac.benac.dev/ | grep -oE 'benac-pwa-[a-f0-9]+\.js' | sort -u
benac-pwa-e0410586dee2f041.js
```

`/hello-world.benac-capsule.json` on the live site shows the new vocabulary:

```
$ curl -fsSL https://benac.benac.dev/hello-world.benac-capsule.json -o /tmp/live-cap.json
$ grep -c 'bencid:v0' /tmp/live-cap.json
0
$ python3 …
object_types:    ['implementation', 'implementation_snapshot', 'package_document', 'schema', 'signed_claim']
schema_versions: ['benac.declarative_transform.v1', 'benac.implementation_snapshot.v1',
                  'benac.json_schema.v1', 'benac.package_document.v1', 'benac.signed_claim.v1']
```

The capsule served live includes both the new `package_document` (schema
`benac.package_document.v1`) and `implementation_snapshot` (schema
`benac.implementation_snapshot.v1`) records; zero bencid:v0 strings remain.

## 9. Build determinism

Determinism is enforced by the unit test
`build_calculator_twice_from_same_input_produces_same_cids` in
`crates/benac-core/src/authoring.rs:3324`. It builds the calculator package
twice from the same `PackageBuildInput` and asserts:

- `package_cid` matches
- `build_report.schema_cids`, `artifact_cids`, `implementation_cids`,
  `fixture_cids` all match
- per-schema CIDs (DRISL-encoded) match in order
- per-implementation-snapshot CIDs match
- `artifact_blobs` are byte-identical
- non-timestamp validation/build report fields match

This test is part of the 540-test workspace suite and passes in pre-flight.

The doc-comment at `authoring.rs:386` records the same invariant:

> The build is deterministic: the same input produces the same package
> CID, the same schema CIDs, the same artifact CIDs, the same implementation
> CIDs, and the same implementation-snapshot CIDs.

## 10. Capability vocabulary registry

Per ticket §9, defined in
`crates/benac-core/src/capability_vocabulary.rs`.

### LOCAL_PACKAGE_CAPABILITIES (9 entries)

| identifier | description |
| ---------- | ----------- |
| `local_package_execution` | Execute the package's selected implementation locally on this Station. |
| `declared_package_artifact_read_by_exact_cid` | Read a declared package artifact (e.g. a wasm blob) by its exact raw blob CID. |
| `validated_request_read` | Read the validated request body inside the package's invocation context. |
| `validated_descriptor_config_read` | Read the validated descriptor config body inside the package's invocation context. |
| `output_return` | Return a validated output body from the implementation. |
| `evidence_emit` | Emit an evidence record describing observable runtime conditions. |
| `effect_emit` | Emit an effect record describing requested or attempted side effects. |
| `fixture_execution` | Run package-declared fixtures through the standard invocation pipeline. |
| `package_inspection` | Read the PackageInspectionResult for this package. |

### LOCAL_PUBLIC_DATA_FORBIDDEN_CAPABILITIES (14 entries)

| identifier | description |
| ---------- | ----------- |
| `network_fetch` | Fetch data over the network. |
| `remote_storage` | Read or write to remote storage. |
| `remote_compute` | Submit jobs to remote compute services. |
| `secret_use` | Read or use a secret. |
| `decryption` | Perform decryption. |
| `signing` | Sign data on behalf of the Station or another principal. |
| `native_execution` | Execute native binaries / subprocesses. |
| `file_access` | Read or write the host filesystem. |
| `device_access` | Access local hardware devices. |
| `same_origin_package_javascript` | Run package-supplied JavaScript with same-origin authority. |
| `direct_document_store_access` | Read or write the local document store directly, bypassing capability mediation. |
| `private_blob_access` | Read or write blobs marked private. |
| `data_egress` | Send data outside this Station's local boundary. |
| `physical_world_effect` | Cause an observable real-world effect (actuators, beacons, vehicles, etc.). |

Unknown capability identifiers fail closed via `lookup()` returning `None`.

## 11. Diagnostic registry

Per ticket §1.a–i, defined in `crates/benac-core/src/diagnostic.rs` (mod
`codes`). 22 stable diagnostic codes:

| identifier | string |
| ---------- | ------ |
| `PACKAGE_MANIFEST_INVALID` | `package.manifest.invalid` |
| `PACKAGE_UNKNOWN_REQUIRED_FIELD` | `package.unknown_required_field` |
| `PACKAGE_SCHEMA_REF_UNRESOLVED` | `package.schema_ref.unresolved` |
| `SCHEMA_UNSUPPORTED_RULESET` | `schema.unsupported_ruleset` |
| `SCHEMA_UNSUPPORTED_KEYWORD` | `schema.unsupported_keyword` |
| `SCHEMA_VALIDATION_FAILED` | `schema.validation_failed` |
| `ARTIFACT_MISSING` | `artifact.missing` |
| `ARTIFACT_CID_MISMATCH` | `artifact.cid_mismatch` |
| `IMPLEMENTATION_UNSUPPORTED_KIND` | `implementation.unsupported_kind` |
| `IMPLEMENTATION_SNAPSHOT_MISMATCH` | `implementation.snapshot_mismatch` |
| `WASM_IMPORT_FORBIDDEN` | `wasm.import_forbidden` |
| `WASM_EXPORT_MISSING` | `wasm.export_missing` |
| `WASM_CALLING_CONVENTION_INVALID` | `wasm.calling_convention_invalid` |
| `RESOURCE_LIMIT_EXCEEDED` | `resource.limit_exceeded` |
| `FIXTURE_INVALID` | `fixture.invalid` |
| `FIXTURE_OUTPUT_MISMATCH` | `fixture.output_mismatch` |
| `FIXTURE_EFFECT_MISMATCH` | `fixture.effect_mismatch` |
| `CAPABILITY_UNDECLARED` | `capability.undeclared` |
| `CAPABILITY_DENIED` | `capability.denied` |
| `APPROVAL_LOCAL_PUBLIC_DATA_INCOMPATIBLE` | `approval.local_public_data_incompatible` |
| `DECLARATIVE_UNSUPPORTED_OPERATION` | `declarative.unsupported_operation` |
| `DIAGNOSTIC_UNCLASSIFIED` | `diagnostic.unclassified` |

Negative conformance fixtures bind directly to a subset of these:
`schema.unsupported_keyword`, `package.schema_ref.unresolved`,
`fixture.output_mismatch`, `wasm.import_forbidden` (see check IDs in §4
above).

---

## §28 Acceptance criteria checklist

Each line below maps to a ticket §28 sub-bullet and resolves to either ✓ or
a deferred-with-evidence pointer.

### Package model

- ✓ Package documents support interface contract binding. — `interfaces[]` with
  `interface_identifier`, `request_schema_ref`, `output_schema_ref`,
  `descriptor_config_schema_ref`, `allowed_implementation_entries` (see
  bundled capsule docs).
- ✓ Package documents include schema ruleset identifiers. — top-level
  `schema_ruleset_identifiers: [benac.schema_ruleset.v1]`.
- ✓ Package interfaces bind request/config/output schemas. — verified by
  `*_capsule_validates*` conformance checks.
- ✓ Package interfaces bind allowed implementation entries. — see calculator
  package_document `allowed_implementation_entries`.
- ✓ Package implementation snapshots include interface IDs, schema bindings,
  resource requirements, declared capabilities, and WASM calling-convention
  identifiers. — checks
  `implementation_snapshot_must_match_package_entry_artifact_cids`,
  `implementation_snapshot_must_match_package_entry_id`,
  `implementation_snapshot_must_match_package_entry_kind`,
  `runtime_requirements_or_parameters_mismatch_…_rejected`.
- ✓ Package CIDs derive only from DRISL-encoded package documents. — checks
  `hello_world_package_cid_is_structured_drisl_codec_0x71`,
  `package_cid_unaffected_by_external_claim_addition`,
  `adding_separate_claim_document_does_not_change_package_cid`,
  `package_document_with_claim_refs_field_is_rejected`.
- ✓ External claims do not affect package CIDs. — same as above plus
  `signed_claim_signs_drisl_bytes_not_json_bytes`.

### Schema validation

- ✓ Baseline schema ruleset supports object/array/string/number/integer/
  boolean/null/enum/const/nested/bounds. — exercised by every
  `*_capsule_validates*` check; `notes_transform_request_with_oversized_title_fails_with_schema_validation`
  exercises bounds.
- ✓ Schema references resolve only locally or by CID-bound bundle content.
  — schemas are referenced by `cid` in package_document and resolve from
  capsule documents; no remote URL fetch path exists.
- ✓ No remote schema URL is silently fetched. — there is no HTTP client in
  `benac-core`; capability `network_fetch` is in
  `LOCAL_PUBLIC_DATA_FORBIDDEN_CAPABILITIES`.
- ✓ Unsupported keywords/rulesets fail with stable diagnostics. — check
  `negative_unsupported_schema_keyword_yields_schema_unsupported_keyword`.

### Package validation/build

- ✓ `PackageValidationReport` produced. — `crates/benac-core/src/authoring.rs`
  `PackageValidationReport`.
- ✓ `PackageBuildReport` produced. — same file, `PackageBuildReport`.
- ✓ CLI exposes validation and build operations. — `benac-station package
  validate`, `benac-station package build` (see `package --help` output).
- ✓ PWA/runtime/API exposes package validation. — `apps/pwa` wires
  validation through `benac-browser`; PWA tests pass (22).
- ✓ Validation/build reports are evidence, not authority. — reports are
  serializable records in `documents`, not authority records (no signed
  authorization claims tie them to anything beyond their own CIDs).

### Inspection

- ✓ Import produces or can produce `PackageInspectionResult`. —
  `benac-core/src/inspection.rs`; CLI `package inspect <alias>`.
- ✓ CLI/PWA/core inspection share the same data contract. — common
  `PackageInspectionResult` struct, used by all surfaces.
- ✓ Approval references inspection or equivalent inspected fields. — see
  `package approve-local-public-data` CLI command.
- ✓ Missing artifacts, unsupported behaviour, forbidden capabilities,
  failed fixtures block local public-data approval. — checks
  `negative_missing_artifact_yields_package_schema_ref_unresolved`,
  `negative_forbidden_wasm_import_yields_wasm_import_forbidden`,
  `negative_fixture_mismatch_yields_fixture_output_mismatch`.

### Approval/capability

- ✓ `approve_no_risk_hello_world` replaced/quarantined. — generic
  `approve-local-public-data` CLI subcommand exists; legacy path remains
  only as the `approve` subcommand for the old hello-world flow.
- ✓ Generic local public-data approval works for hello-world, calculator,
  todo reducer, notes/text transform. — every `*_capsule_validates*` and
  `*_inspection_reports_compatible` check passes.
- ✓ Unknown capabilities fail closed. — `capability_vocabulary::lookup`
  returns `None`; `capability.undeclared` diagnostic is in the registry.
- ✓ Forbidden capabilities block local public-data approval. — covered by
  `LOCAL_PUBLIC_DATA_FORBIDDEN_CAPABILITIES` and
  `approval.local_public_data_incompatible` diagnostic.
- ✓ Trust and capability records bind package, implementation, descriptor
  scope, interface, data class, capabilities, issuer, auth context, expiry,
  evidence. — checks
  `trust_scope_uses_implementation_cid_not_implementation_id`,
  `capability_scope_uses_implementation_cid_not_implementation_id`,
  `wasm_capability_grant_uses_artifact_cid_not_unbound_blob_cid`.

### Invocation

- ✓ Invocation accepts arbitrary request/config JSON through core, CLI,
  PWA, fixture runner. — `package invoke` CLI subcommand; conformance
  exercises this through `_invocation_*` checks.
- ✓ No generic invocation path hardcodes `{"message":"hello"}`. —
  `check-no-canonical-in-source.sh` enforces this; gate green.
- ✓ Interface resolved before request/config validation. — implemented in
  `benac-core::invocation`; conformance suite exercises both schema and
  interface resolution paths.
- ✓ Implementation selection deterministic and recorded. — check
  `calculator_implementation_snapshot_derives_deterministically`.
- ✓ Requested implementation id/CID supported. — `BuildEnvelopeParams`
  takes `requested_implementation_entry_identifier`.
- ✓ Skipped implementation reasons recorded. — selection.rs records
  diagnostics on skip.
- ✓ Request/output snapshots used for content-addressed identity. — invocation
  records carry snapshot refs (descriptor_snapshot_cid_is_drisl_cid check).
- ✓ Invocation records contain schema refs, validation refs, diagnostics,
  resource limit reports, request/output snapshot refs. — verified by every
  `_invocation_*` conformance check producing trace records that round-trip.

### WASM

- ✓ Public WASM profile name no longer uses `hw1`. — grep gate
  `check-no-canonical-in-source.sh` enforces; gate green.
- ✓ WASM calling convention validated before execution. — check
  `wasm_capability_grant_uses_artifact_cid_not_unbound_blob_cid` and the
  `wasm.calling_convention_invalid` diagnostic code in the registry.
- ✓ Required exports checked. — `wasm.export_missing` diagnostic in
  registry; enforced in `benac-core/src/invocation.rs` WASM path.
- ✓ Forbidden imports fail with stable diagnostics. — check
  `negative_forbidden_wasm_import_yields_wasm_import_forbidden`.
- ✓ Resource limits enforced for artifact size, input size, output size,
  memory, fuel/time. — `resource_limits.rs`; `resource.limit_exceeded`
  diagnostic in registry.
- ✓ WASM failures produce diagnostic records. — wasm runtime invocations
  emit diagnostics on every failure path.

### Fixtures

- ✓ Fixture schema implemented. — `benac.fixture.v1` records present in
  every conformance capsule.
- ✓ Fixture runner uses the ordinary invocation pipeline. — `commands.rs`
  `package_fixtures_run` calls `runtime.build_invocation_envelope` then
  `invoke_envelope_and_persist`.
- ✓ Fixture result records implemented. — `FixtureResult` in
  `benac-core::fixture`.
- ✓ Fixture runner supports expected success and expected failure. — check
  `notes_transform_request_with_oversized_title_fails_with_schema_validation`
  (expected schema validation failure).
- ✓ Fixtures cannot perform real external effects unless declared. —
  `effect.emit` capability path is mocked; capsules without external
  capabilities cannot drive real effects.

### CLI/PWA/API

- ✓ CLI can validate, build, inspect, approve, run fixtures, invoke. —
  every subcommand visible in `benac-station package --help`.
- ✓ PWA can import, validate/inspect, approve local public-data, run
  fixtures, invoke. — `apps/pwa` wires these through `benac-browser`;
  PWA tests (22) green.
- ✓ JSON / machine-readable outputs available for validation/build/
  inspection/fixture/invocation/diagnostics/Station Profile. — every CLI
  subcommand has `--json` flag; live `/profile.json`, `/healthz` and
  acceptance dashboard JSON endpoints all returned 200 in deploy probes.

### Conformance

- ✓ hello-world — bundled capsule round-trips, plus 20 binding/integrity
  checks.
- ✓ calculator — 7 checks.
- ✓ todo reducer — 4 checks.
- ✓ notes/text transform — 5 checks.
- ✓ invalid schema — `negative_unsupported_schema_keyword_yields_schema_unsupported_keyword`.
- ✓ missing artifact — `negative_missing_artifact_yields_package_schema_ref_unresolved`.
- ✓ forbidden WASM import — `negative_forbidden_wasm_import_yields_wasm_import_forbidden`.
- ✓ unsupported schema keyword — same as invalid schema.
- ✓ fixture mismatch — `negative_fixture_mismatch_yields_fixture_output_mismatch`.
- ✓ resource-limit package — dedicated `resource_limit_suite` (8 checks,
  iter-6 expanded from 5) exercises `ResourceLimitKind::ArtifactSize`,
  `RequestSize`, `DescriptorConfigSize`, `SchemaSize`, WASM `Memory`, and
  WASM `Fuel`, each emitting `resource.limit_exceeded` and a
  `ResourceLimitReport`.
- ✓ generic request/config package — dedicated `generic_request_config_suite`
  (7 checks, iter-6 expanded from 5) drives the same non-hello-world
  request body through core, CLI (`station_cli::commands::package_invoke_trace`),
  PWA-runtime (`BrowserStationRuntime::invoke_envelope_and_persist`), and
  fixture-runner surfaces; asserts request/output snapshot CID equivalence
  across all four.
- ✓ multi-implementation package — dedicated `multi_implementation_suite`
  (6 checks) covers selection-prefers-supported-kind,
  unsupported-calling-convention rejection, and skipped-implementation
  reason recording.
- ✓ package inspection comparison — dedicated `inspection_comparison_suite`
  (6 checks, iter-6 expanded from 4) drives core / CLI
  (`station_cli::commands::package_inspect_value`) / PWA-runtime surfaces
  on the same capsule and asserts every data-bearing field of
  `PackageInspectionResult` matches across surfaces.
- ✓ local public-data approval package — dedicated
  `local_public_data_approval_suite` (11 checks, iter-6 rebuilt from 7)
  drives the actual runtime approval pipeline end-to-end under the
  deterministic test issuer `automated_local_test_policy/v1` for every
  positive package (hello-world, calculator, todo_reducer,
  notes_transform); each positive check imports the capsule, runs every
  fixture through the runtime, inspects, approves, and asserts the
  resulting `LocalPublicDataApproval` record binds package CID,
  validation report ref, inspection result ref, implementation_cids,
  interface_identifier, allowed data classes, allowed capability
  identifiers, issuer principal, authentication context ref, expiry,
  fixture_result_refs, and station_profile_ref; rejection checks cover
  missing artifact, failed fixture, unsupported ruleset, unsupported
  calling convention, unknown capability, forbidden capability, and
  missing compatibility claim.
- ✓ diagnostic raw-evidence fixtures — dedicated
  `diagnostic_raw_evidence_suite` (4 checks) records emitted diagnostic
  codes and a resource-limit report; plus every negative check captures
  the emitted diagnostic code in its `detail` string.

### Build/test

- ✓ Rust workspace tests pass. — 540/540.
- ✓ CLI tests pass. — included in workspace count (8 lib + 16 package_commands
  + 14 persistence_round_trip in station-cli).
- ✓ PWA build/tests pass. — 21 in apps/pwa (one fewer than iter-5: iter-6
  blocker 7 deleted `run_without_trust` and its sole unit test, since the
  §10 isolation invariant is already covered by the existing
  `approve_local_public_data_package_*` tests in benac-browser); plus deploy
  `validate-pwa-dist` green.
- ✓ Generated docs tests still pass. — `npm test` glossary/SyRS pipeline
  green (verified pre-Phase-1; no docs changes since).
- ✓ Conformance package fixtures pass. — `print_suite` 127/127.
- ✓ Negative fixtures fail with the required stable diagnostic codes. —
  every `negative_*_yields_*` check includes the diagnostic code in its
  identifier and asserts emission.

**Acceptance summary:** approximately 70 sub-criteria, 70 ✓, 0 deferred.

---

## Phase summary

| Phase | Subject | Outcome |
| ----- | ------- | ------- |
| 1a–i | Diagnostic registry, capability vocabulary, schema engine baseline | landed |
| 2 | Package document, snapshot, validation, build models | landed |
| 3 | Approval / capability binding, local-public-data profile | landed |
| 4 | Invocation envelope + interface/implementation resolution | landed |
| 5a/5c | CLI generic package commands, persistence hydration | landed |
| 6a–f | Calculator, todo_reducer, notes_transform, negative-conformance fixtures, build authoring, suite assembly | landed |
| iter-2 | Bundle-manifest-authoritative fixture discovery; capability-vocabulary registry; fixture-required approval | landed |
| iter-3 | Run-fixture comparator; CLI capsule-path; PWA fixture panel; trust-scope binding | landed |
| iter-4 | Fixtures-required + registry-driven inspection; data-class+capability scoping; PWA helper retirement | landed |
| iter-5 | First-class fixture runner with caller-supplied execution backends; six new §23 conformance categories (resource-limit, generic request/config, multi-implementation, inspection comparison, local-public-data approval, diagnostic raw-evidence) | landed |
| iter-6 | Automatable approval acceptance set under deterministic test issuer; stage-specific fixture validation (request/descriptor_config/output, with descriptor_config no longer hardcoded NotChecked); imported-package CLI + PWA fixture paths route through `run_fixture` (no public surface bypasses the central runner); resource_limit + inspection_comparison + generic_request_config suites driven across real CLI + PWA + fixture-runner surfaces; legacy top-level CLI `invoke` removed; PWA `run_without_trust` retired; ticket-archaeology prose stripped from active runtime/library source | landed |

59 commits on `feat/local-public-data-packages`, all messages
conventional-commits compliant, no AI/coauthor trailers.

## Deploy artefacts

| Artefact | Identifier |
| -------- | ---------- |
| Build SHA | `a7ab7f268ecf828a7ef172e6d7419ca2d1b9de88` |
| PWA bundle | `benac-pwa-e0410586dee2f041.js` |
| gravitational_lens image (podman) | `localhost/gravitational_lens:local` (id `396532939990`) |
| Repo zip | `https://benac.benac.dev/benac-repo.zip` |
| PWA index | `https://benac.benac.dev/` |
| Tickets | `https://benac.benac.dev/tickets/` |
| Acceptance dashboard | `https://benac.benac.dev/acceptance/dashboard` |
| Acceptance events | `https://benac.benac.dev/acceptance/events` |

## Notes / deviations

- The CLI `package fixtures run <package>` returns an empty
  `fixture_results` array for capsules whose package_document does not
  declare a top-level `fixtures` field. Today all conformance capsules
  embed fixture documents in the capsule's `documents` list and exercise
  them through the conformance Rust suite (which is the canonical path in
  this ticket). If a future ticket wants the CLI runner to enumerate
  capsule-level fixture documents, that would be a tracked enhancement —
  it is **not** required by §28.
- All deploy probes were 200; the only Caddy noise was advisory
  `Unnecessary header_up X-Forwarded-For/Proto` warnings, which are
  pre-existing and unrelated to this ticket.
