Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions .github/workflows/validate-heller-transport-admission.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: validate-heller-transport-admission

on:
pull_request:
paths:
- "docs/heller-v1-transport-admission-v0.1.md"
- "fixtures/descriptors/heller/v1/transport_admission_manifest_v0.1.json"
- "fixtures/descriptors/heller/v1/encoded_payload_manifest_v8.json"
- "tools/verify_heller_transport_admission.py"
- ".github/workflows/validate-heller-transport-admission.yml"
push:
branches: [ main ]
paths:
- "docs/heller-v1-transport-admission-v0.1.md"
- "fixtures/descriptors/heller/v1/transport_admission_manifest_v0.1.json"
- "fixtures/descriptors/heller/v1/encoded_payload_manifest_v8.json"
- "tools/verify_heller_transport_admission.py"
- ".github/workflows/validate-heller-transport-admission.yml"
workflow_dispatch:

permissions:
contents: read

jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Validate Heller transport admission manifest
run: python tools/verify_heller_transport_admission.py
71 changes: 71 additions & 0 deletions docs/heller-v1-transport-admission-v0.1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Heller v1 transport admission v0.1

## Purpose

This note promotes the existing Heller transport seed from descriptor/payload visibility toward transport admission.

It does not claim final canonical TritRPC frame vectors yet. It defines the first stable binding layer needed before canonical vectors can be emitted and verified.

## Existing seed artifacts

The current Heller seed already includes:

- `fixtures/descriptors/heller/v1/heller_wire_v1.proto`
- `fixtures/descriptors/heller/v1/encoded_payload_manifest_v8.json`

The seed manifest includes two payload families:

1. `event_envelope`
- protobuf message: `socioprophet.heller.v1.HellerEventEnvelope`
- Avro binary sample: `sample_event_envelope_v1.avro.bin`
- Protobuf binary sample: `sample_event_envelope_v1.protobuf.bin`

2. `state_snapshot`
- protobuf message: `socioprophet.heller.v1.HellerStateSnapshot`
- Avro binary sample: `sample_state_snapshot_v1.avro.bin`
- Protobuf binary sample: `sample_state_snapshot_v1.protobuf.bin`

## Admission rule

TriTRPC remains the transport authority. Heller semantics are not redefined here.

This repository may define:

- service and method names for Heller carriage
- payload codec labels
- schema/context id derivation policy
- canonical frame-vector generation requirements
- Rust/Go verifier expectations

This repository must not redefine the canonical economics, state-machine, or semantic meaning of Heller objects.

## Initial service and method bindings

The v0.1 admission surface uses one transport service:

- `heller.v1.Transport`

With four method surfaces:

- `EventEnvelope.Avro`
- `EventEnvelope.Protobuf`
- `StateSnapshot.Avro`
- `StateSnapshot.Protobuf`

These are transport-level names. They are not semantic ownership claims.

## Frame-vector readiness gates

A Heller payload family is ready for canonical frame-vector emission when all of the following are true:

1. the descriptor or schema reference is stable
2. the payload hash is recorded in a manifest
3. the service and method binding is recorded
4. the schema id derivation rule is recorded
5. the context id derivation rule is recorded
6. a deterministic nonce strategy is selected for fixture generation
7. Rust and Go verifier expectations are recorded

## Follow-on implementation

The next PR should add a small generator or fixture-emission helper that reads `transport_admission_manifest_v0.1.json`, emits canonical frame vectors for at least one binding, and verifies decode/repack parity in the existing Rust/Go fixture path.
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
{
"profile": "tritrpc.heller.transport_admission.v0.1",
"transport_authority": "SocioProphet/TriTRPC",
"semantic_authority": "external",
"descriptor_refs": {
"protobuf": "fixtures/descriptors/heller/v1/heller_wire_v1.proto",
"payload_manifest": "fixtures/descriptors/heller/v1/encoded_payload_manifest_v8.json"
},
"service": "heller.v1.Transport",
"bindings": [
{
"binding_id": "heller.event_envelope.avro.v1",
"payload_family": "event_envelope",
"method": "EventEnvelope.Avro",
"payload_codec": "avro-binary",
"message_ref": "heller_event_envelope.avsc#HellerEventEnvelope",
"sample_payload_file": "sample_event_envelope_v1.avro.bin",
"sample_payload_sha256": "fba232ba000ff2d26ba47d11a7ca60b780520d52c5f25a1f06218f3272087443",
"schema_id_policy": "derive-sha256-32:message_ref+payload_codec+profile",
"context_id_policy": "derive-sha256-32:service+method+binding_id"
},
{
"binding_id": "heller.event_envelope.protobuf.v1",
"payload_family": "event_envelope",
"method": "EventEnvelope.Protobuf",
"payload_codec": "protobuf-binary",
"message_ref": "socioprophet.heller.v1.HellerEventEnvelope",
"sample_payload_file": "sample_event_envelope_v1.protobuf.bin",
"sample_payload_sha256": "4c7faf0e8ce2b71d2d71c238872d1cb057e76c02382976cdcdd436cb442fd261",
"schema_id_policy": "derive-sha256-32:message_ref+payload_codec+profile",
"context_id_policy": "derive-sha256-32:service+method+binding_id"
},
{
"binding_id": "heller.state_snapshot.avro.v1",
"payload_family": "state_snapshot",
"method": "StateSnapshot.Avro",
"payload_codec": "avro-binary",
"message_ref": "heller_state_snapshot.avsc#HellerStateSnapshot",
"sample_payload_file": "sample_state_snapshot_v1.avro.bin",
"sample_payload_sha256": "7fbf1b4c51f7edfdfeb1c0513e8d9b6342542a19127338f1abe3c2bb1f2700c4",
"schema_id_policy": "derive-sha256-32:message_ref+payload_codec+profile",
"context_id_policy": "derive-sha256-32:service+method+binding_id"
},
{
"binding_id": "heller.state_snapshot.protobuf.v1",
"payload_family": "state_snapshot",
"method": "StateSnapshot.Protobuf",
"payload_codec": "protobuf-binary",
"message_ref": "socioprophet.heller.v1.HellerStateSnapshot",
"sample_payload_file": "sample_state_snapshot_v1.protobuf.bin",
"sample_payload_sha256": "3d75baf61e92c3fc141450022ec243ce749d0ccf976ff049a5509fe61ec6df27",
"schema_id_policy": "derive-sha256-32:message_ref+payload_codec+profile",
"context_id_policy": "derive-sha256-32:service+method+binding_id"
}
],
"canonical_frame_vectors": {
"status": "not-yet-emitted",
"next_step": "generate deterministic TritRPC frames from these bindings and sample payloads"
},
"verifier_expectations": {
"rust_go_decode_repack_parity_required": true,
"payload_hash_check_required": true,
"fixture_nonce_strategy": "pending"
}
}
99 changes: 99 additions & 0 deletions tools/verify_heller_transport_admission.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#!/usr/bin/env python3
"""Validate the Heller transport admission manifest against the encoded payload manifest.

This is a repository-local readiness gate. It does not emit canonical TritRPC frames yet.
"""
from __future__ import annotations

import json
import sys
from pathlib import Path

ROOT = Path(__file__).resolve().parents[1]
ADMISSION = ROOT / "fixtures" / "descriptors" / "heller" / "v1" / "transport_admission_manifest_v0.1.json"
PAYLOADS = ROOT / "fixtures" / "descriptors" / "heller" / "v1" / "encoded_payload_manifest_v8.json"

REQUIRED_BINDING_KEYS = {
"binding_id",
"payload_family",
"method",
"payload_codec",
"message_ref",
"sample_payload_file",
"sample_payload_sha256",
"schema_id_policy",
"context_id_policy",
}


def fail(msg: str, code: int = 2) -> None:
print(f"[FAIL] {msg}", file=sys.stderr)
raise SystemExit(code)


def load_json(path: Path):
if not path.exists():
fail(f"missing file: {path}")
return json.loads(path.read_text(encoding="utf-8"))


def expected_hash_key(codec: str) -> str:
if codec == "avro-binary":
return "avro_sha256"
if codec == "protobuf-binary":
return "protobuf_sha256"
fail(f"unsupported payload codec: {codec}")


def expected_file_key(codec: str) -> str:
if codec == "avro-binary":
return "avro_binary_file"
if codec == "protobuf-binary":
return "protobuf_binary_file"
fail(f"unsupported payload codec: {codec}")


def main() -> None:
admission = load_json(ADMISSION)
payloads = load_json(PAYLOADS)

if admission.get("profile") != "tritrpc.heller.transport_admission.v0.1":
fail("unexpected admission profile")
if admission.get("service") != "heller.v1.Transport":
fail("unexpected Heller transport service")

bindings = admission.get("bindings")
if not isinstance(bindings, list) or not bindings:
fail("bindings must be a non-empty array")

seen = set()
for binding in bindings:
if not isinstance(binding, dict):
fail("binding entries must be objects")
missing = REQUIRED_BINDING_KEYS - set(binding)
if missing:
fail(f"{binding.get('binding_id', '<unknown>')}: missing keys {sorted(missing)}")
binding_id = binding["binding_id"]
if binding_id in seen:
fail(f"duplicate binding_id: {binding_id}")
seen.add(binding_id)

family = binding["payload_family"]
if family not in payloads:
fail(f"{binding_id}: unknown payload family {family}")
payload_info = payloads[family]
codec = binding["payload_codec"]
hash_key = expected_hash_key(codec)
file_key = expected_file_key(codec)
if binding["sample_payload_sha256"] != payload_info.get(hash_key):
fail(f"{binding_id}: sample payload sha256 mismatch")
if binding["sample_payload_file"] != payload_info.get(file_key):
fail(f"{binding_id}: sample payload file mismatch")
if not binding["method"].count(".") == 1:
fail(f"{binding_id}: method should use Family.Codec shape")

print(f"[OK] Heller transport admission manifest validated: {len(bindings)} bindings")


if __name__ == "__main__":
main()
Loading