diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..fdba287 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,7 @@ +contracts/VID-IMPL-P00-003A/** text eol=lf +testing/implementation/VID-IMPL-P00-003A/** text eol=lf +specifications/evidence/PHASE-00-IMPLEMENTATION/VID-IMPL-P00-003A/** text eol=lf +workers/VideoLocalization.Worker/src/waveform_contract.rs text eol=lf +workers/VideoLocalization.Worker/tests/waveform_contract.rs text eol=lf +/.gitattributes text eol=lf +workers/VideoLocalization.Worker/src/lib.rs text eol=lf diff --git a/contracts/VID-IMPL-P00-003A/fixtures/cache-key-and-descriptor-fixtures.json b/contracts/VID-IMPL-P00-003A/fixtures/cache-key-and-descriptor-fixtures.json new file mode 100644 index 0000000..8a6e42a --- /dev/null +++ b/contracts/VID-IMPL-P00-003A/fixtures/cache-key-and-descriptor-fixtures.json @@ -0,0 +1,202 @@ +{ + "cache_key_positive_cases": [ + { + "case_id": "cache-key-positive-001", + "seed": "waveform-seed-003a", + "resource_profile_id": "VID-WAVEFORM-RESOURCE-P00-003A", + "policy_profile_id": "VID-WAVEFORM-POLICY-P00-003A", + "retry_profile_id": "VID-WAVEFORM-RETRY-P00-003A", + "input_ports": [ + { + "order": 0, + "type": "waveform_request", + "schema": "VID-IMPL-P00-003A-WAVEFORM-INPUT", + "content": "source", + "revision": "0.1.0-p00", + "sample_range": "[0,4096)" + } + ], + "representation": { + "peak": "waveform-peak-v1", + "time": "sample", + "channel": "stereo-major", + "downmix": "matrix-stereo-downmix-v1", + "resampling": "resample-none", + "stability": "fixed" + }, + "expected_cache_key_prefix": "SUI-CACHE-KEY-V1\u0000", + "expected_cache_key_digest": "8eda1f679adc820e35ed450e3ea70707b9a96e4a4e8eddd4a767c5727566a835" + } + ], + "cache_key_negative_cases": [ + { + "case_id": "cache-key-negative-invalid-seed", + "invalid_seed": true, + "missing_seed": false + }, + { + "case_id": "cache-key-negative-missing-seed", + "invalid_seed": false, + "missing_seed": true + } + ], + "bulk_descriptor_positive_cases": [ + { + "case_id": "bulk-descriptor-positive-001", + "descriptor": { + "version": "VID-WAVEFORM-BULK-DESCRIPTOR-V1", + "mode": "read-only", + "handle_identity": "handle-vid-waveform-003a", + "attempt_id": "attempt-001", + "lease_id": "lease-001", + "cancel_scope": "attempt-001", + "expiry": "2099-01-01T00:00:00Z", + "integrity": { + "algorithm": "sha-256", + "value": "d67c656e01756650d77717b0839985a056ec28ffe174601d690fc407a2ceffca" + }, + "chunk_hashes_omitted": true, + "length": 4096, + "payload_schema": "VID-IMPL-P00-003A-WAVEFORM-ARTIFACT", + "source_publication_fence": "fence-001", + "representation": { + "peak": "waveform-peak-v1", + "time": "sample", + "channel": "stereo-major", + "downmix": "matrix-stereo-downmix-v1", + "resampling": "resample-none", + "source_timeline": "timeline-001", + "sample_range": "[0,4096)" + }, + "descriptor_hash": "3f1aabb75fb6a7aeb4e38f9ccc1d49ad36c5b2e019eed79d6b67adc158ec371d" + }, + "expected_descriptor_digest": "3f1aabb75fb6a7aeb4e38f9ccc1d49ad36c5b2e019eed79d6b67adc158ec371d" + } + ], + "bulk_descriptor_negative_cases": [ + { + "case_id": "bulk-descriptor-negative-missing-descriptor-hash", + "descriptor": { + "version": "VID-WAVEFORM-BULK-DESCRIPTOR-V1", + "mode": "read-only", + "handle_identity": "handle-vid-waveform-003a", + "attempt_id": "attempt-001", + "lease_id": "lease-001", + "cancel_scope": "attempt-001", + "expiry": "2099-01-01T00:00:00Z", + "integrity": { + "algorithm": "sha-256", + "value": "d67c656e01756650d77717b0839985a056ec28ffe174601d690fc407a2ceffca" + }, + "chunk_hashes_omitted": true, + "length": 4096, + "payload_schema": "VID-IMPL-P00-003A-WAVEFORM-ARTIFACT", + "source_publication_fence": "fence-001", + "representation": { + "peak": "waveform-peak-v1", + "time": "sample", + "channel": "stereo-major", + "downmix": "matrix-stereo-downmix-v1", + "resampling": "resample-none", + "source_timeline": "timeline-001", + "sample_range": "[0,4096)" + }, + "descriptor_hash": "3f1aabb75fb6a7aeb4e38f9ccc1d49ad36c5b2e019eed79d6b67adc158ec371d" + }, + "reason": "missing-descriptor-hash" + }, + { + "case_id": "bulk-descriptor-negative-chunk-hash-required", + "descriptor": { + "version": "VID-WAVEFORM-BULK-DESCRIPTOR-V1", + "mode": "read-only", + "handle_identity": "handle-vid-waveform-003a", + "attempt_id": "attempt-001", + "lease_id": "lease-001", + "cancel_scope": "attempt-001", + "expiry": "2099-01-01T00:00:00Z", + "integrity": { + "algorithm": "sha-256", + "value": "d67c656e01756650d77717b0839985a056ec28ffe174601d690fc407a2ceffca" + }, + "chunk_hashes_omitted": true, + "length": 4096, + "payload_schema": "VID-IMPL-P00-003A-WAVEFORM-ARTIFACT", + "source_publication_fence": "fence-001", + "representation": { + "peak": "waveform-peak-v1", + "time": "sample", + "channel": "stereo-major", + "downmix": "matrix-stereo-downmix-v1", + "resampling": "resample-none", + "source_timeline": "timeline-001", + "sample_range": "[0,4096)" + }, + "descriptor_hash": "3f1aabb75fb6a7aeb4e38f9ccc1d49ad36c5b2e019eed79d6b67adc158ec371d" + }, + "reason": "chunk-list" + }, + { + "case_id": "bulk-descriptor-negative-non-hex-integrity", + "descriptor": { + "version": "VID-WAVEFORM-BULK-DESCRIPTOR-V1", + "mode": "read-only", + "handle_identity": "handle-vid-waveform-003a", + "attempt_id": "attempt-001", + "lease_id": "lease-001", + "cancel_scope": "attempt-001", + "expiry": "2099-01-01T00:00:00Z", + "integrity": { + "algorithm": "sha-256", + "value": "not-a-digest" + }, + "chunk_hashes_omitted": true, + "length": 4096, + "payload_schema": "VID-IMPL-P00-003A-WAVEFORM-ARTIFACT", + "source_publication_fence": "fence-001", + "representation": { + "peak": "waveform-peak-v1", + "time": "sample", + "channel": "stereo-major", + "downmix": "matrix-stereo-downmix-v1", + "resampling": "resample-none", + "source_timeline": "timeline-001", + "sample_range": "[0,4096)" + }, + "descriptor_hash": "3f1aabb75fb6a7aeb4e38f9ccc1d49ad36c5b2e019eed79d6b67adc158ec371d" + }, + "reason": "non-hex" + }, + { + "case_id": "bulk-descriptor-negative-misaligned-hash", + "descriptor": { + "version": "VID-WAVEFORM-BULK-DESCRIPTOR-V1", + "mode": "read-only", + "handle_identity": "handle-vid-waveform-003a", + "attempt_id": "attempt-001", + "lease_id": "lease-001", + "cancel_scope": "attempt-001", + "expiry": "2099-01-01T00:00:00Z", + "integrity": { + "algorithm": "sha-256", + "value": "d67c656e01756650d77717b0839985a056ec28ffe174601d690fc407a2ceffca" + }, + "chunk_hashes_omitted": true, + "length": 4096, + "payload_schema": "VID-IMPL-P00-003A-WAVEFORM-ARTIFACT", + "source_publication_fence": "fence-001", + "representation": { + "peak": "waveform-peak-v1", + "time": "sample", + "channel": "stereo-major", + "downmix": "matrix-stereo-downmix-v1", + "resampling": "resample-none", + "source_timeline": "timeline-001", + "sample_range": "[0,4096)" + }, + "descriptor_hash": "3f1aabb75fb6a7aeb4e38f9ccc1d49ad36c5b2e019eed79d6b67adc158ec371d" + }, + "reason": "mismatched-length" + } + ] +} diff --git a/contracts/VID-IMPL-P00-003A/fixtures/operation-descriptor.json b/contracts/VID-IMPL-P00-003A/fixtures/operation-descriptor.json new file mode 100644 index 0000000..89741d2 --- /dev/null +++ b/contracts/VID-IMPL-P00-003A/fixtures/operation-descriptor.json @@ -0,0 +1,97 @@ +{ + "operation_id": "submark.video-localization.waveform.derive", + "operation_version": "0.1.0-p00", + "implementation_id": "VID-IMPL-P00-003A", + "implementation_profile_id": "VID-WAVEFORM-OPERATION-PROFILE-P00-003A", + "input_schema_id": "VID-IMPL-P00-003A-WAVEFORM-INPUT", + "output_schema_id": "VID-IMPL-P00-003A-WAVEFORM-ARTIFACT", + "transport": "local-staged-file", + "requested_capabilities": [ + "cancellation", + "deadline" + ], + "requested_output_capabilities": [], + "input_ports": [ + { + "order": 0, + "schema_id": "VID-IMPL-P00-003A-WAVEFORM-INPUT", + "content_type": "application/vnd.video.waveform.request+json", + "port_type": "waveform_request", + "identity": "waveform-request-port-v1", + "revision": "0.1.0-p00", + "sample_range": "[0,18446744073709551615)" + } + ], + "output_ports": [ + { + "order": 0, + "port_id": "waveform_artifact_port", + "port_type": "waveform_artifact", + "schema_id": "VID-IMPL-P00-003A-WAVEFORM-ARTIFACT", + "max_bytes": 65536, + "max_nesting": 8 + }, + { + "order": 1, + "port_id": "waveform_error_port", + "port_type": "waveform_error", + "schema_id": "VID-IMPL-P00-003A-WAVEFORM-STRUCTURED-ERROR", + "max_bytes": 32768, + "max_nesting": 8 + }, + { + "order": 2, + "port_id": "waveform_peak_bulk_port", + "port_type": "waveform_peak_bulk", + "schema_id": "VID-IMPL-P00-003A-WAVEFORM-BULK-DESCRIPTOR", + "max_bytes": 65536, + "max_nesting": 8 + } + ], + "launch_policy": { + "use_shell": false, + "use_path_lookup": false, + "user_supplied_options": false + }, + "staged_lease": { + "lease_id": "LEASE-STATE-3A", + "lease_epoch": 1, + "minimum_acceptable_lease_epoch": 1, + "immutable": true, + "source_sha256": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", + "source_length": 12345, + "staged_copy_identity": "staged-copy-3a-identity", + "staged_copy_sha256": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", + "staged_copy_length": 12345, + "observed_staged_copy_identity": "staged-copy-3a-identity", + "observed_staged_copy_sha256": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", + "observed_staged_copy_length": 12345, + "access_scope": "waveform-lease-scope-3a", + "expires_at": "2099-01-01T00:00:00Z", + "manifest_digest": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", + "logical_source_ref": "source:waveform:001", + "observed_fence_token": "waveform-fence-token", + "expected_fence_token": "waveform-fence-token" + }, + "representation": { + "sample_rate": 48000, + "channel_count": 2, + "target_timebase": [1, 48000], + "max_window_samples": 134217728 + }, + "parameters": { + "representation": { + "sample_rate": 48000, + "channel_count": 2, + "target_timebase": [1, 48000], + "max_window_samples": 134217728 + }, + "limits": { + "wall_seconds": 30, + "cpu_seconds": 30, + "resident_memory_bytes": 268435456, + "stream_count": 1 + }, + "retry_profile": "VID-WAVEFORM-RETRY-P00-003A" + } +} diff --git a/contracts/VID-IMPL-P00-003A/fixtures/worker-hello.json b/contracts/VID-IMPL-P00-003A/fixtures/worker-hello.json new file mode 100644 index 0000000..92b926c --- /dev/null +++ b/contracts/VID-IMPL-P00-003A/fixtures/worker-hello.json @@ -0,0 +1,40 @@ +{ + "operation_id": "submark.video-localization.waveform.derive", + "operation_version": "0.1.0-p00", + "implementation_id": "VID-IMPL-P00-003A", + "implementation_profile_id": "VID-WAVEFORM-OPERATION-PROFILE-P00-003A", + "transport": "local-staged-file", + "platform": "Windows", + "architecture": "x64", + "control_protocol_min": "1.0.0", + "control_protocol_max": "1.0.0", + "limits": { + "control_envelope_bytes": 262144, + "stream_count": 1, + "wall_time_seconds": 30, + "child_cpu_seconds": 30, + "resident_memory_bytes": 268435456, + "staging_bytes": 536870912, + "bulk_payload_bytes": 536870912, + "bulk_descriptor_bytes": 65536, + "output_bytes": 65536, + "error_bytes": 32768 + }, + "supported": [ + "cancellation", + "deadline" + ], + "unsupported": [ + "progress", + "checkpoint", + "pause-resume", + "partial-success", + "degraded-output", + "acceleration", + "auto-fallback", + "network" + ], + "resource_profile_id": "VID-WAVEFORM-RESOURCE-P00-003A", + "policy_profile_id": "VID-WAVEFORM-POLICY-P00-003A", + "retry_profile_id": "VID-WAVEFORM-RETRY-P00-003A" +} diff --git a/contracts/VID-IMPL-P00-003A/records/manifest.json b/contracts/VID-IMPL-P00-003A/records/manifest.json new file mode 100644 index 0000000..d650d37 --- /dev/null +++ b/contracts/VID-IMPL-P00-003A/records/manifest.json @@ -0,0 +1,258 @@ +{ + "record_digest_profile_id": "VID-WAVEFORM-ADMISSION-MANIFEST-P00-003A", + "record_digest_profile_version": "0.1.0-p00", + "status": "candidate_for_review", + "authority": "OWNER-AUTH-V2", + "purpose": "Bind the sole authoritative 003A admission manifest and required operation/schema/profile records before dispatch.", + "serialization": { + "encoding": "UTF-8", + "bom": false, + "line_endings": "LF", + "indentation_spaces": 2, + "trailing_whitespace": false, + "final_newline": "exactly-one-LF", + "hash_coverage": "complete-file-bytes", + "hash_algorithm": "sha-256", + "hex_encoding": "lowercase-ASCII", + "rfc_canonical_json": false, + "cache_key_cbor_profile": true + }, + "records": [ + { + "role": "control-protocol", + "record_id": "SUI-SPEC-003", + "record_version": "1.0", + "path": "Video Localization/contracts/VID-IMPL-P00-002B1/records/control-protocol.json", + "schema_id": "VID-IMPL-P00-003A-WAVEFORM-CONTROL", + "schema_path": "Video Localization/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-CONTROL.schema.json", + "sha256": "2539250e640517eccc9dccf5feebce6cf9ec89acc26cef9ee08edc9d914d9f02" + }, + { + "role": "operation-profile", + "record_id": "VID-WAVEFORM-OPERATION-PROFILE-P00-003A", + "record_version": "0.1.0-p00", + "path": "Video Localization/contracts/VID-IMPL-P00-003A/records/operation-profile.json", + "schema_id": "VID-IMPL-P00-003A-WAVEFORM-OPERATION-PROFILE", + "schema_path": "Video Localization/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-OPERATION-PROFILE.schema.json", + "sha256": "2374d0730488c262148516051431b09acb0e2b06fe5ec901d5ffdb2739a889db" + }, + { + "role": "resource-profile", + "record_id": "VID-WAVEFORM-RESOURCE-P00-003A", + "record_version": "0.1.0-p00", + "path": "Video Localization/contracts/VID-IMPL-P00-003A/records/resource-profile.json", + "schema_id": "VID-IMPL-P00-003A-WAVEFORM-RESOURCE", + "schema_path": "Video Localization/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-RESOURCE.schema.json", + "sha256": "6da872ad96a9f0840cc62bf2bd27201aaf8d877002d5add749833710d3e5e07d" + }, + { + "role": "policy-profile", + "record_id": "VID-WAVEFORM-POLICY-P00-003A", + "record_version": "0.1.0-p00", + "path": "Video Localization/contracts/VID-IMPL-P00-003A/records/policy-profile.json", + "schema_id": "VID-IMPL-P00-003A-WAVEFORM-POLICY", + "schema_path": "Video Localization/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-POLICY.schema.json", + "sha256": "ad4838a59d06ee676b4b94be43d6f9dd5c7ded88f5c57cfd7f7f56bcae82c368" + }, + { + "role": "retry-profile", + "record_id": "VID-WAVEFORM-RETRY-P00-003A", + "record_version": "0.1.0-p00", + "path": "Video Localization/contracts/VID-IMPL-P00-003A/records/retry-profile.json", + "schema_id": "VID-IMPL-P00-003A-WAVEFORM-PARAMETER", + "schema_path": "Video Localization/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-PARAMETER.schema.json", + "sha256": "35de87a3fe7681a485d2b8d4199f5fe89b8d27c38b1500043dd01397d9b3f8e1" + }, + { + "role": "schema-bundle", + "record_id": "VID-IMPL-P00-003A", + "record_version": "0.1.0-p00", + "path": "Video Localization/contracts/VID-IMPL-P00-003A/schema-bundle.json", + "sha256": "c01cc30752532e9abb5804d76883c890a58b267cf886cb01f1c25716be7310c9" + } + ], + "fixture_records": [ + { + "role": "operation-descriptor", + "path": "contracts/VID-IMPL-P00-003A/fixtures/operation-descriptor.json", + "sha256": "827f842460512e2721ed6fcd0832f4bf0250c3d15dfca3c7504d4d71a27856e4" + }, + { + "role": "worker-hello", + "path": "contracts/VID-IMPL-P00-003A/fixtures/worker-hello.json", + "sha256": "4bcc23f8c0ce2b6469a16dea7e137807ebc407a693a8234f657fc20fbc805c2f" + }, + { + "role": "cache-and-descriptor-fixtures", + "path": "contracts/VID-IMPL-P00-003A/fixtures/cache-key-and-descriptor-fixtures.json", + "sha256": "f609a700a89edc1ca25c12f6d8ec496bb3887c3263604ce8d6cca2b62e9a046a" + } + ], + "schema_records": [ + { + "schema_id": "VID-IMPL-P00-003A-WAVEFORM-INPUT", + "schema_version": "0.1.0-p00", + "path": "contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-INPUT.schema.json", + "sha256": "916dd6e26609ff34906199a7a10ffb047fcdf50334b6aefd3f1e0a01e497b84e" + }, + { + "schema_id": "VID-IMPL-P00-003A-WAVEFORM-ARTIFACT", + "schema_version": "0.1.0-p00", + "path": "contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-ARTIFACT.schema.json", + "sha256": "b6d48767ee109fa60715d9bb9d477196553d6196a9f43202d96f37e20cd04154" + }, + { + "schema_id": "VID-IMPL-P00-003A-WAVEFORM-PARAMETER", + "schema_version": "0.1.0-p00", + "path": "contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-PARAMETER.schema.json", + "sha256": "43da57dccf0152e8bb303406cbefb16ea590168e207157e2dd0f38a0fdb6713b" + }, + { + "schema_id": "VID-IMPL-P00-003A-WAVEFORM-STRUCTURED-ERROR", + "schema_version": "0.1.0-p00", + "path": "contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-STRUCTURED-ERROR.schema.json", + "sha256": "c551d0c1b23c542aa61155180c7d9314cce19739f557513b384d43b709142b54" + }, + { + "schema_id": "VID-IMPL-P00-003A-WAVEFORM-CONTROL", + "schema_version": "0.1.0-p00", + "path": "contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-CONTROL.schema.json", + "sha256": "020307fd2bc15000beb052319b359cef5663b5b5885ac6f5c40feb4bb0e28783" + }, + { + "schema_id": "VID-IMPL-P00-003A-WAVEFORM-RESOURCE", + "schema_version": "0.1.0-p00", + "path": "contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-RESOURCE.schema.json", + "sha256": "6e9f8c77278401e3e943a531d4939a941f62279a9030ac4252c53f1ef7668405" + }, + { + "schema_id": "VID-IMPL-P00-003A-WAVEFORM-POLICY", + "schema_version": "0.1.0-p00", + "path": "contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-POLICY.schema.json", + "sha256": "925c07f72ff7ba1a46ec0a2ada05a6b6554815c3c77d1ae6863ae050707601f9" + }, + { + "schema_id": "VID-IMPL-P00-003A-WAVEFORM-BULK-DESCRIPTOR", + "schema_version": "0.1.0-p00", + "path": "contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-BULK-DESCRIPTOR.schema.json", + "sha256": "cec467e93fd40e8a1ce62c2c73e1ac3f0aa1095e26d864f93745040e4e83eecf" + }, + { + "schema_id": "VID-IMPL-P00-003A-WAVEFORM-WORKER-HELLO", + "schema_version": "0.1.0-p00", + "path": "contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-WORKER-HELLO.schema.json", + "sha256": "afaa793d59d50f1511666afccb03440798e14b68ed271629f8747055f5dfeb41" + }, + { + "schema_id": "VID-IMPL-P00-003A-WAVEFORM-OPERATION-PROFILE", + "schema_version": "0.1.0-p00", + "path": "contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-OPERATION-PROFILE.schema.json", + "sha256": "2ceb828d6ed3c9cf54e56d9d94705b2643c3ec6cf3b0a982dbe2a18911f0f2ca" + } + ], + "authorities": [ + { + "id": "SUI-SPEC-003", + "revision": "1.0", + "path": "_shared/specifications/SUI-SPEC-003-job-worker-artifact-protocol.md", + "sha256": "b5e0106bf0117587b0507fc3bbf5837b77e35fb18a6dea12c0cf9d8dd14548b7" + }, + { + "id": "VID-DEC-003", + "revision": "1.0", + "path": "Video Localization/decisions/VID-DEC-003-initial-support-profiles.md", + "sha256": "0c6a9056083bfc741b49de908f74597d9bd8546b69eb75ae8c342b6ea06e2851" + }, + { + "id": "VID-IMPL-P00-003A-SCHEMA-BUNDLE", + "revision": "0.1.0-p00", + "path": "Video Localization/contracts/VID-IMPL-P00-003A/schema-bundle.json", + "sha256": "c01cc30752532e9abb5804d76883c890a58b267cf886cb01f1c25716be7310c9" + }, + { + "id": "VID-IMPL-P00-003A-INPUT", + "revision": "0.1.0-p00", + "path": "Video Localization/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-INPUT.schema.json", + "sha256": "916dd6e26609ff34906199a7a10ffb047fcdf50334b6aefd3f1e0a01e497b84e" + }, + { + "id": "VID-IMPL-P00-003A-ARTIFACT", + "revision": "0.1.0-p00", + "path": "Video Localization/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-ARTIFACT.schema.json", + "sha256": "b6d48767ee109fa60715d9bb9d477196553d6196a9f43202d96f37e20cd04154" + }, + { + "id": "VID-IMPL-P00-003A-PARAMETER", + "revision": "0.1.0-p00", + "path": "Video Localization/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-PARAMETER.schema.json", + "sha256": "43da57dccf0152e8bb303406cbefb16ea590168e207157e2dd0f38a0fdb6713b" + }, + { + "id": "VID-IMPL-P00-003A-STRUCTURED-ERROR", + "revision": "0.1.0-p00", + "path": "Video Localization/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-STRUCTURED-ERROR.schema.json", + "sha256": "c551d0c1b23c542aa61155180c7d9314cce19739f557513b384d43b709142b54" + }, + { + "id": "VID-IMPL-P00-003A-CONTROL", + "revision": "0.1.0-p00", + "path": "Video Localization/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-CONTROL.schema.json", + "sha256": "020307fd2bc15000beb052319b359cef5663b5b5885ac6f5c40feb4bb0e28783" + }, + { + "id": "VID-IMPL-P00-003A-WORKER-HELLO", + "revision": "0.1.0-p00", + "path": "Video Localization/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-WORKER-HELLO.schema.json", + "sha256": "afaa793d59d50f1511666afccb03440798e14b68ed271629f8747055f5dfeb41" + }, + { + "id": "VID-IMPL-P00-003A-OPERATION-PROFILE", + "revision": "0.1.0-p00", + "path": "Video Localization/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-OPERATION-PROFILE.schema.json", + "sha256": "2ceb828d6ed3c9cf54e56d9d94705b2643c3ec6cf3b0a982dbe2a18911f0f2ca" + }, + { + "id": "VID-IMPL-P00-002B1-SCHEMA-BUNDLE", + "revision": "0.1.0-p00", + "path": "Video Localization/contracts/VID-IMPL-P00-002B1/schema-bundle.json", + "sha256": "f78bf8a7af8616b913d03539eb66ace6bf670f80c685e791521e395396f3397f" + }, + { + "id": "VID-IMPL-P00-003A-RESOURCE", + "revision": "0.1.0-p00", + "path": "Video Localization/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-RESOURCE.schema.json", + "sha256": "6e9f8c77278401e3e943a531d4939a941f62279a9030ac4252c53f1ef7668405" + }, + { + "id": "VID-IMPL-P00-003A-POLICY", + "revision": "0.1.0-p00", + "path": "Video Localization/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-POLICY.schema.json", + "sha256": "925c07f72ff7ba1a46ec0a2ada05a6b6554815c3c77d1ae6863ae050707601f9" + }, + { + "id": "VID-IMPL-P00-003A-BULK-DESCRIPTOR", + "revision": "0.1.0-p00", + "path": "Video Localization/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-BULK-DESCRIPTOR.schema.json", + "sha256": "cec467e93fd40e8a1ce62c2c73e1ac3f0aa1095e26d864f93745040e4e83eecf" + } + ], + "scope_exclusions": [ + "no ffprobe execution", + "no media bytes in runtime payload", + "no raw path or parse output schema in cache-key material", + "no UI/playback/vfr support" + ], + "hashing": { + "manifest_self_hash": "excluded-to-avoid-self-reference", + "candidate_hashes_bound_to_evidence": [ + "contracts/VID-IMPL-P00-003A/schema-bundle.json", + "contracts/VID-IMPL-P00-003A/records/operation-profile.json", + "contracts/VID-IMPL-P00-003A/records/resource-profile.json", + "contracts/VID-IMPL-P00-003A/records/policy-profile.json", + "contracts/VID-IMPL-P00-003A/records/retry-profile.json", + "contracts/VID-IMPL-P00-003A/fixtures/operation-descriptor.json", + "contracts/VID-IMPL-P00-003A/fixtures/worker-hello.json", + "contracts/VID-IMPL-P00-003A/fixtures/cache-key-and-descriptor-fixtures.json" + ] + } +} diff --git a/contracts/VID-IMPL-P00-003A/records/operation-profile.json b/contracts/VID-IMPL-P00-003A/records/operation-profile.json new file mode 100644 index 0000000..821320d --- /dev/null +++ b/contracts/VID-IMPL-P00-003A/records/operation-profile.json @@ -0,0 +1,69 @@ +{ + "profile_id": "VID-WAVEFORM-OPERATION-PROFILE-P00-003A", + "profile_version": "0.1.0-p00", + "operation_id": "submark.video-localization.waveform.derive", + "operation_version": "0.1.0-p00", + "implementation_id": "VID-IMPL-P00-003A", + "implementation_profile_id": "VID-WAVEFORM-OPERATION-PROFILE-P00-003A", + "transport": "local-staged-file", + "ports": [ + { + "role": "waveform_request", + "order": 0, + "max_nesting": 8, + "max_bytes": 262144, + "required": true, + "schema": "VID-IMPL-P00-003A-WAVEFORM-INPUT" + }, + { + "role": "waveform_artifact", + "order": 0, + "max_nesting": 8, + "max_bytes": 65536, + "required": true, + "schema": "VID-IMPL-P00-003A-WAVEFORM-ARTIFACT" + }, + { + "role": "waveform_error", + "order": 1, + "max_nesting": 8, + "max_bytes": 32768, + "required": false, + "schema": "VID-IMPL-P00-003A-WAVEFORM-STRUCTURED-ERROR" + }, + { + "role": "waveform_peak_bulk", + "order": 2, + "max_nesting": 8, + "max_bytes": 65536, + "required": false, + "schema": "VID-IMPL-P00-003A-WAVEFORM-BULK-DESCRIPTOR" + } + ], + "capabilities": { + "supported": [ + "cancellation", + "deadline" + ], + "unsupported": [ + "progress", + "checkpoint", + "pause-resume", + "partial-success", + "degraded-output", + "acceleration", + "auto-fallback", + "network" + ] + }, + "policy": { + "cache_key_schema": "sui.cache-key.cbor-sha256.v1", + "cache_key_prefix": "SUI-CACHE-KEY-V1", + "resource_profile_id": "VID-WAVEFORM-RESOURCE-P00-003A", + "policy_profile_id": "VID-WAVEFORM-POLICY-P00-003A", + "retry_profile_id": "VID-WAVEFORM-RETRY-P00-003A", + "bulk_descriptor_profile": "VID-WAVEFORM-BULK-DESCRIPTOR-V1", + "output_complete_only": true, + "publish_complete_only": true + } +} diff --git a/contracts/VID-IMPL-P00-003A/records/policy-profile.json b/contracts/VID-IMPL-P00-003A/records/policy-profile.json new file mode 100644 index 0000000..734a752 --- /dev/null +++ b/contracts/VID-IMPL-P00-003A/records/policy-profile.json @@ -0,0 +1,32 @@ +{ + "policy_id": "VID-WAVEFORM-POLICY-P00-003A", + "policy_version": "0.1.0-p00", + "isolation": { + "network": "denied", + "watchdog": "required", + "job_object": "required", + "transport": "local-staged-file" + }, + "capability_model": "single-attempt", + "containment": { + "proof_required": true, + "no_path_identity": true, + "no_cross_operation_expansion": true + }, + "policy_rules": { + "networking": { + "allowed": false, + "raw_path": false, + "media_parse_decode": false, + "playback_or_vfr": false + }, + "publication": { + "requires_fence": true, + "requires_lease": true, + "complete_output_required": true, + "quarantine_on_failure": true, + "delete_on_stale": true + } + }, + "capability_class": "waveform" +} diff --git a/contracts/VID-IMPL-P00-003A/records/resource-profile.json b/contracts/VID-IMPL-P00-003A/records/resource-profile.json new file mode 100644 index 0000000..985ae46 --- /dev/null +++ b/contracts/VID-IMPL-P00-003A/records/resource-profile.json @@ -0,0 +1,25 @@ +{ + "resource_id": "VID-WAVEFORM-RESOURCE-P00-003A", + "resource_version": "0.1.0-p00", + "limits": { + "control_envelope_bytes": 262144, + "wall_time_seconds": 30, + "cpu_time_seconds": 30, + "resident_memory_bytes": 268435456, + "staging_bytes": 536870912, + "bulk_payload_bytes": 536870912, + "bulk_descriptor_bytes": 65536, + "error_bytes": 32768, + "payload_text_bytes": 4096, + "nesting_max": 8, + "stream_limit": 1, + "stream_count": 1, + "peak_count": 1048576, + "egress_bytes": 0 + }, + "transport": "local-staged-file", + "caps": [ + "cancellation", + "deadline" + ] +} diff --git a/contracts/VID-IMPL-P00-003A/records/retry-profile.json b/contracts/VID-IMPL-P00-003A/records/retry-profile.json new file mode 100644 index 0000000..7c64b8c --- /dev/null +++ b/contracts/VID-IMPL-P00-003A/records/retry-profile.json @@ -0,0 +1,17 @@ +{ + "retry_profile_id": "VID-WAVEFORM-RETRY-P00-003A", + "retry_profile_version": "0.1.0-p00", + "applicable_codes": [ + "VID-WAVEFORM-WORKER-TRANSIENT", + "VID-WAVEFORM-STORAGE-TRANSIENT" + ], + "max_total_attempts": 2, + "base_wait_millis": 500, + "max_wait_millis": 500, + "backoff": "fixed", + "cumulative_wall_seconds": 30, + "cumulative_cpu_seconds": 30, + "cumulative_ram_bytes": 268435456, + "cumulative_staging_bytes": 536870912, + "cost_ceiling": 2 +} diff --git a/contracts/VID-IMPL-P00-003A/schema-bundle.json b/contracts/VID-IMPL-P00-003A/schema-bundle.json new file mode 100644 index 0000000..2500329 --- /dev/null +++ b/contracts/VID-IMPL-P00-003A/schema-bundle.json @@ -0,0 +1,95 @@ +{ + "artifact_id": "VID-IMPL-P00-003A", + "artifact_version": "0.1.0-p00", + "operation_id": "submark.video-localization.waveform.derive", + "operation_version": "0.1.0-p00", + "implementation_profile_id": "VID-WAVEFORM-OPERATION-PROFILE-P00-003A", + "implementation_id": "VID-IMPL-P00-003A", + "fixture_records": [ + { + "role": "operation-descriptor", + "path": "contracts/VID-IMPL-P00-003A/fixtures/operation-descriptor.json", + "sha256": "827f842460512e2721ed6fcd0832f4bf0250c3d15dfca3c7504d4d71a27856e4" + }, + { + "role": "worker-hello", + "path": "contracts/VID-IMPL-P00-003A/fixtures/worker-hello.json", + "sha256": "4bcc23f8c0ce2b6469a16dea7e137807ebc407a693a8234f657fc20fbc805c2f" + }, + { + "role": "cache-and-descriptor-fixtures", + "path": "contracts/VID-IMPL-P00-003A/fixtures/cache-key-and-descriptor-fixtures.json", + "sha256": "f609a700a89edc1ca25c12f6d8ec496bb3887c3263604ce8d6cca2b62e9a046a" + } + ], + "schema_records": [ + { + "schema_id": "VID-IMPL-P00-003A-WAVEFORM-INPUT", + "schema_version": "0.1.0-p00", + "path": "contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-INPUT.schema.json", + "sha256": "916dd6e26609ff34906199a7a10ffb047fcdf50334b6aefd3f1e0a01e497b84e" + }, + { + "schema_id": "VID-IMPL-P00-003A-WAVEFORM-ARTIFACT", + "schema_version": "0.1.0-p00", + "path": "contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-ARTIFACT.schema.json", + "sha256": "b6d48767ee109fa60715d9bb9d477196553d6196a9f43202d96f37e20cd04154" + }, + { + "schema_id": "VID-IMPL-P00-003A-WAVEFORM-PARAMETER", + "schema_version": "0.1.0-p00", + "path": "contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-PARAMETER.schema.json", + "sha256": "43da57dccf0152e8bb303406cbefb16ea590168e207157e2dd0f38a0fdb6713b" + }, + { + "schema_id": "VID-IMPL-P00-003A-WAVEFORM-STRUCTURED-ERROR", + "schema_version": "0.1.0-p00", + "path": "contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-STRUCTURED-ERROR.schema.json", + "sha256": "c551d0c1b23c542aa61155180c7d9314cce19739f557513b384d43b709142b54" + }, + { + "schema_id": "VID-IMPL-P00-003A-WAVEFORM-CONTROL", + "schema_version": "0.1.0-p00", + "path": "contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-CONTROL.schema.json", + "sha256": "020307fd2bc15000beb052319b359cef5663b5b5885ac6f5c40feb4bb0e28783" + }, + { + "schema_id": "VID-IMPL-P00-003A-WAVEFORM-RESOURCE", + "schema_version": "0.1.0-p00", + "path": "contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-RESOURCE.schema.json", + "sha256": "6e9f8c77278401e3e943a531d4939a941f62279a9030ac4252c53f1ef7668405" + }, + { + "schema_id": "VID-IMPL-P00-003A-WAVEFORM-POLICY", + "schema_version": "0.1.0-p00", + "path": "contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-POLICY.schema.json", + "sha256": "925c07f72ff7ba1a46ec0a2ada05a6b6554815c3c77d1ae6863ae050707601f9" + }, + { + "schema_id": "VID-IMPL-P00-003A-WAVEFORM-BULK-DESCRIPTOR", + "schema_version": "0.1.0-p00", + "path": "contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-BULK-DESCRIPTOR.schema.json", + "sha256": "cec467e93fd40e8a1ce62c2c73e1ac3f0aa1095e26d864f93745040e4e83eecf" + }, + { + "schema_id": "VID-IMPL-P00-003A-WAVEFORM-WORKER-HELLO", + "schema_version": "0.1.0-p00", + "path": "contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-WORKER-HELLO.schema.json", + "sha256": "afaa793d59d50f1511666afccb03440798e14b68ed271629f8747055f5dfeb41" + }, + { + "schema_id": "VID-IMPL-P00-003A-WAVEFORM-OPERATION-PROFILE", + "schema_version": "0.1.0-p00", + "path": "contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-OPERATION-PROFILE.schema.json", + "sha256": "2ceb828d6ed3c9cf54e56d9d94705b2643c3ec6cf3b0a982dbe2a18911f0f2ca" + } + ], + "assumptions": [ + "No real media parse/decode or waveform extraction is implemented.", + "No ffmpeg/ffprobe execution is implemented in VID-IMPL-P00-003A.", + "No UI, playback, VFR, or peak transfer via JSON/base64 is implemented.", + "Observed hashes are complete-file exact UTF-8 lowercase hex where present." + ], + "created_at": "2026-08-02T00:00:00+07:00", + "last_updated_at": "2026-08-02T23:59:59+07:00" +} diff --git a/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-ARTIFACT.schema.json b/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-ARTIFACT.schema.json new file mode 100644 index 0000000..5877e93 --- /dev/null +++ b/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-ARTIFACT.schema.json @@ -0,0 +1,170 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "schema_id": "VID-IMPL-P00-003A-WAVEFORM-ARTIFACT", + "schema_version": "0.1.0-p00", + "title": "Waveform artifact schema", + "type": "object", + "required": [ + "artifact_id", + "artifact_version", + "artifact_type", + "output_schema_id", + "completeness", + "integrity", + "size_bytes", + "component_inventory", + "producing", + "input_digests", + "parameter_digests", + "resource_digests", + "policy_digests", + "cache_digests", + "output_port", + "staging", + "lineage", + "publication_id", + "fencing", + "cache_key", + "bulk_descriptor_ref" + ], + "properties": { + "artifact_id": {"type": "string", "minLength": 1}, + "artifact_version": {"type": "string", "minLength": 1}, + "artifact_type": {"type": "string", "enum": ["waveform_artifact"]}, + "output_schema_id": {"type": "string", "minLength": 1}, + "completeness": {"type": "string", "enum": ["complete"]}, + "integrity": { + "type": "object", + "required": ["algorithm", "value"], + "properties": { + "algorithm": {"type": "string", "enum": ["sha-256"]}, + "value": {"type": "string", "pattern": "^[A-Fa-f0-9]{64}$"} + }, + "additionalProperties": false + }, + "size_bytes": {"type": "integer", "minimum": 0}, + "component_inventory": { + "type": "array", + "items": {"type": "string"}, + "minItems": 1 + }, + "producing": { + "type": "object", + "required": ["job_ref", "attempt_ref", "dispatch_ref", "worker_ref", "operation_id", "operation_version", "implementation_id", "implementation_profile_id"], + "properties": { + "job_ref": {"type": "string"}, + "attempt_ref": {"type": "string"}, + "dispatch_ref": {"type": "string"}, + "worker_ref": {"type": "string"}, + "operation_id": {"type": "string"}, + "operation_version": {"type": "string"}, + "implementation_id": {"type": "string"}, + "implementation_profile_id": {"type": "string"} + }, + "additionalProperties": false + }, + "input_digests": { + "type": "object", + "required": ["staged_copy_hash", "manifest_digest", "logical_source_ref", "staged_copy_hash_schema_ref"], + "properties": { + "staged_copy_hash": {"type": "string", "pattern": "^[A-Fa-f0-9]{64}$"}, + "manifest_digest": {"type": "string", "pattern": "^[A-Fa-f0-9]{64}$"}, + "logical_source_ref": {"type": "string", "minLength": 1}, + "staged_copy_hash_schema_ref": {"type": "string", "minLength": 1} + }, + "additionalProperties": false + }, + "parameter_digests": { + "type": "object", + "required": ["argv", "limits", "cache_key"], + "properties": { + "argv": {"type": "string", "pattern": "^[A-Fa-f0-9]{64}$"}, + "limits": {"type": "string", "pattern": "^[A-Fa-f0-9]{64}$"}, + "cache_key": {"type": "string", "pattern": "^[A-Fa-f0-9]{64}$"} + }, + "additionalProperties": false + }, + "resource_digests": { + "type": "object", + "required": ["resource", "schema"], + "properties": { + "resource": {"type": "string", "pattern": "^[A-Fa-f0-9]{64}$"}, + "schema": {"type": "string", "pattern": "^[A-Fa-f0-9]{64}$"} + }, + "additionalProperties": false + }, + "policy_digests": { + "type": "object", + "required": ["policy", "schema"], + "properties": { + "policy": {"type": "string", "pattern": "^[A-Fa-f0-9]{64}$"}, + "schema": {"type": "string", "pattern": "^[A-Fa-f0-9]{64}$"} + }, + "additionalProperties": false + }, + "cache_digests": { + "type": "object", + "required": ["schema_bundle", "control_protocol", "cache_key_schema"], + "properties": { + "schema_bundle": {"type": "string", "pattern": "^[A-Fa-f0-9]{64}$"}, + "control_protocol": {"type": "string", "pattern": "^[A-Fa-f0-9]{64}$"}, + "cache_key_schema": {"type": "string", "minLength": 1} + }, + "additionalProperties": false + }, + "output_port": {"type": "string", "minLength": 1}, + "staging": { + "type": "object", + "required": ["state", "path", "delete_on_stale", "quarantine_on_failure"], + "properties": { + "state": {"type": "string"}, + "path": {"type": "string", "minLength": 1}, + "delete_on_stale": {"type": "boolean"}, + "quarantine_on_failure": {"type": "boolean"} + }, + "additionalProperties": false + }, + "lineage": { + "type": "object", + "required": ["job_ref", "attempt_ref", "dispatch_ref", "worker_ref", "publication_ref"], + "properties": { + "job_ref": {"type": "string", "minLength": 1}, + "attempt_ref": {"type": "string", "minLength": 1}, + "dispatch_ref": {"type": "string", "minLength": 1}, + "worker_ref": {"type": "string", "minLength": 1}, + "publication_ref": {"type": "string", "minLength": 1} + }, + "additionalProperties": false + }, + "publication_id": {"type": "string", "minLength": 1}, + "fencing": { + "type": "object", + "required": ["required", "active_token"], + "properties": { + "required": {"type": "boolean"}, + "active_token": {"type": "string", "minLength": 1} + }, + "additionalProperties": false + }, + "cache_key": { + "type": "object", + "required": ["schema", "digest"], + "properties": { + "schema": {"type": "string", "minLength": 1}, + "digest": {"type": "string", "pattern": "^[A-Fa-f0-9]{64}$"} + }, + "additionalProperties": false + }, + "bulk_descriptor_ref": { + "type": "object", + "required": ["reference", "digest", "schema"], + "properties": { + "reference": {"type": "string", "minLength": 1}, + "digest": {"type": "string", "pattern": "^[A-Fa-f0-9]{64}$"}, + "schema": {"type": "string", "minLength": 1} + }, + "additionalProperties": false + } + }, + "additionalProperties": false +} diff --git a/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-BULK-DESCRIPTOR.schema.json b/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-BULK-DESCRIPTOR.schema.json new file mode 100644 index 0000000..b847c02 --- /dev/null +++ b/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-BULK-DESCRIPTOR.schema.json @@ -0,0 +1,70 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "schema_id": "VID-IMPL-P00-003A-WAVEFORM-BULK-DESCRIPTOR", + "schema_version": "0.1.0-p00", + "title": "Waveform bulk descriptor schema", + "type": "object", + "required": [ + "version", + "mode", + "handle_identity", + "attempt_id", + "lease_id", + "cancel_scope", + "expiry", + "integrity", + "chunk_hashes_omitted", + "length", + "payload_schema", + "source_publication_fence", + "representation", + "descriptor_hash" + ], + "properties": { + "version": {"type": "string", "minLength": 1}, + "mode": {"type": "string", "enum": ["read-only"]}, + "handle_identity": {"type": "string", "minLength": 1}, + "attempt_id": {"type": "string", "minLength": 1}, + "lease_id": {"type": "string", "minLength": 1}, + "cancel_scope": {"type": "string", "minLength": 1}, + "expiry": { + "type": "string", + "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+\\-]\\d{2}:\\d{2})$" + }, + "integrity": { + "type": "object", + "required": ["algorithm", "value"], + "properties": { + "algorithm": {"type": "string", "enum": ["sha-256"]}, + "value": {"type": "string", "pattern": "^[A-Fa-f0-9]{64}$"} + }, + "additionalProperties": false + }, + "chunk_hashes_omitted": { + "type": "boolean", + "const": true + }, + "length": {"type": "integer", "minimum": 0}, + "payload_schema": {"type": "string", "minLength": 1}, + "source_publication_fence": {"type": "string", "minLength": 1}, + "representation": { + "type": "object", + "required": ["peak", "time", "channel", "downmix", "resampling", "source_timeline", "sample_range"], + "properties": { + "peak": {"type": "string", "minLength": 1}, + "time": {"type": "string", "minLength": 1}, + "channel": {"type": "string", "minLength": 1}, + "downmix": {"type": "string", "minLength": 1}, + "resampling": {"type": "string", "minLength": 1}, + "source_timeline": {"type": "string", "minLength": 1}, + "sample_range": {"type": "string", "minLength": 1} + }, + "additionalProperties": false + }, + "descriptor_hash": { + "type": "string", + "pattern": "^[A-Fa-f0-9]{64}$" + } + }, + "additionalProperties": false +} diff --git a/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-CONTROL.schema.json b/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-CONTROL.schema.json new file mode 100644 index 0000000..e5c4dd3 --- /dev/null +++ b/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-CONTROL.schema.json @@ -0,0 +1,124 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "schema_id": "VID-IMPL-P00-003A-WAVEFORM-CONTROL", + "schema_version": "0.1.0-p00", + "title": "VID-IMPL-P00-003A control-protocol schema", + "type": "object", + "required": [ + "protocol_specification_id", + "protocol_specification_revision", + "control_protocol_version", + "operation", + "worker", + "transport" + ], + "properties": { + "protocol_specification_id": { + "type": "string", + "const": "SUI-SPEC-003" + }, + "protocol_specification_revision": { + "type": "string", + "const": "1.0" + }, + "control_protocol_version": { + "type": "string", + "const": "1.0.0" + }, + "operation": { + "type": "object", + "required": [ + "operation_id", + "operation_version", + "implementation_id", + "implementation_profile_id", + "schema_reference_ids", + "supported_capabilities", + "unsupported_capabilities", + "transport", + "control_protocol_min", + "control_protocol_max" + ], + "properties": { + "operation_id": {"type": "string"}, + "operation_version": {"type": "string"}, + "implementation_id": {"type": "string"}, + "implementation_profile_id": {"type": "string"}, + "schema_reference_ids": { + "type": "array", + "minItems": 1, + "items": {"type": "string"} + }, + "supported_capabilities": { + "type": "array", + "items": {"type": "string"} + }, + "unsupported_capabilities": { + "type": "array", + "items": {"type": "string"} + }, + "transport": {"type": "string"}, + "control_protocol_min": {"type": "string"}, + "control_protocol_max": {"type": "string"} + }, + "additionalProperties": false + }, + "worker": { + "type": "object", + "required": [ + "platform", + "architecture", + "executable_path", + "executable_sha256", + "component_version", + "limits", + "supported", + "unsupported", + "schema_reference_ids" + ], + "properties": { + "platform": {"type": "string"}, + "architecture": {"type": "string"}, + "executable_path": {"type": "string"}, + "executable_sha256": {"type": "string", "pattern": "^[A-Fa-f0-9]{64}$"}, + "component_version": {"type": "string"}, + "limits": { + "type": "object", + "required": [ + "control_envelope_bytes", + "wall_time_seconds", + "child_cpu_seconds", + "resident_memory_bytes", + "stream_count" + ], + "properties": { + "control_envelope_bytes": {"type": "integer", "minimum": 1}, + "wall_time_seconds": {"type": "integer", "minimum": 1}, + "child_cpu_seconds": {"type": "integer", "minimum": 1}, + "resident_memory_bytes": {"type": "integer", "minimum": 1}, + "stream_count": {"type": "integer", "minimum": 1} + }, + "additionalProperties": false + }, + "supported": {"type": "array", "items": {"type": "string"}}, + "unsupported": {"type": "array", "items": {"type": "string"}}, + "schema_reference_ids": { + "type": "array", + "minItems": 1, + "items": {"type": "string"} + } + }, + "additionalProperties": false + }, + "transport": { + "type": "object", + "required": ["kind", "network_capability"], + "properties": { + "kind": {"type": "string"}, + "network_capability": {"type": "string"} + }, + "additionalProperties": false + } + }, + "additionalProperties": false +} diff --git a/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-INPUT.schema.json b/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-INPUT.schema.json new file mode 100644 index 0000000..42f32c4 --- /dev/null +++ b/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-INPUT.schema.json @@ -0,0 +1,185 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "schema_id": "VID-IMPL-P00-003A-WAVEFORM-INPUT", + "schema_version": "0.1.0-p00", + "title": "Waveform request envelope schema", + "description": "Waveform dispatch envelope for deterministic cache-key synthesis and admission gating.", + "type": "object", + "required": [ + "operation_id", + "operation_version", + "implementation_id", + "implementation_profile_id", + "input_schema_id", + "output_schema_id", + "transport", + "requested_capabilities", + "requested_output_capabilities", + "input_ports", + "output_ports", + "staged_lease", + "launch_policy", + "representation", + "parameters" + ], + "properties": { + "operation_id": {"type": "string", "minLength": 1}, + "operation_version": {"type": "string", "minLength": 1}, + "implementation_id": {"type": "string", "minLength": 1}, + "implementation_profile_id": {"type": "string", "minLength": 1}, + "input_schema_id": {"type": "string", "minLength": 1}, + "output_schema_id": {"type": "string", "minLength": 1}, + "transport": {"type": "string", "enum": ["local-staged-file"]}, + "requested_capabilities": { + "type": "array", + "minItems": 1, + "items": {"type": "string"} + }, + "requested_output_capabilities": { + "type": "array", + "items": {"type": "string"} + }, + "input_ports": { + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "required": ["order", "schema_id", "content_type", "port_type", "identity", "revision", "sample_range"], + "properties": { + "order": {"type": "integer", "minimum": 0}, + "schema_id": {"type": "string", "minLength": 1}, + "content_type": {"type": "string", "minLength": 1}, + "port_type": {"type": "string", "enum": ["waveform_request"]}, + "identity": {"type": "string", "minLength": 1}, + "revision": {"type": "string", "minLength": 1}, + "sample_range": {"type": "string", "minLength": 1} + }, + "additionalProperties": false + } + }, + "output_ports": { + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "required": ["order", "port_id", "port_type", "schema_id", "max_bytes", "max_nesting"], + "properties": { + "order": {"type": "integer", "minimum": 0}, + "port_id": {"type": "string", "minLength": 1}, + "port_type": {"type": "string", "enum": ["waveform_artifact", "waveform_error", "waveform_peak_bulk"]}, + "schema_id": {"type": "string", "minLength": 1}, + "max_bytes": {"type": "integer", "minimum": 0}, + "max_nesting": {"type": "integer", "minimum": 1} + }, + "additionalProperties": false + } + }, + "representation": { + "type": "object", + "required": ["sample_rate", "channel_count", "target_timebase", "max_window_samples"], + "properties": { + "sample_rate": {"type": "integer", "minimum": 1}, + "channel_count": {"type": "integer", "minimum": 1}, + "target_timebase": { + "type": "array", + "items": {"type": "integer"}, + "minItems": 2, + "maxItems": 2 + }, + "max_window_samples": {"type": "integer", "minimum": 1} + }, + "additionalProperties": false + }, + "launch_policy": { + "type": "object", + "required": ["use_shell", "use_path_lookup", "user_supplied_options"], + "properties": { + "use_shell": {"type": "boolean"}, + "use_path_lookup": {"type": "boolean"}, + "user_supplied_options": {"type": "boolean"} + }, + "additionalProperties": false + }, + "staged_lease": { + "type": "object", + "required": [ + "lease_id", + "lease_epoch", + "minimum_acceptable_lease_epoch", + "immutable", + "source_sha256", + "source_length", + "staged_copy_identity", + "staged_copy_sha256", + "staged_copy_length", + "observed_staged_copy_identity", + "observed_staged_copy_sha256", + "observed_staged_copy_length", + "access_scope", + "expires_at", + "manifest_digest", + "logical_source_ref", + "observed_fence_token", + "expected_fence_token" + ], + "properties": { + "lease_id": {"type": "string", "minLength": 1}, + "lease_epoch": {"type": "integer", "minimum": 0}, + "minimum_acceptable_lease_epoch": {"type": "integer", "minimum": 0}, + "immutable": {"type": "boolean"}, + "source_sha256": {"type": "string", "pattern": "^[A-Fa-f0-9]{64}$"}, + "source_length": {"type": "integer", "minimum": 0}, + "staged_copy_identity": {"type": "string", "minLength": 1}, + "staged_copy_sha256": {"type": "string", "pattern": "^[A-Fa-f0-9]{64}$"}, + "staged_copy_length": {"type": "integer", "minimum": 0}, + "observed_staged_copy_identity": {"type": "string", "minLength": 1}, + "observed_staged_copy_sha256": {"type": "string", "pattern": "^[A-Fa-f0-9]{64}$"}, + "observed_staged_copy_length": {"type": "integer", "minimum": 0}, + "access_scope": {"type": "string", "minLength": 1}, + "expires_at": { + "type": "string", + "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+\\-]\\d{2}:\\d{2})$" + }, + "manifest_digest": {"type": "string", "pattern": "^[A-Fa-f0-9]{64}$"}, + "logical_source_ref": {"type": "string", "minLength": 1}, + "observed_fence_token": {"type": "string", "minLength": 1}, + "expected_fence_token": {"type": "string", "minLength": 1} + }, + "additionalProperties": false + }, + "parameters": { + "type": "object", + "required": ["representation", "limits", "retry_profile"], + "properties": { + "representation": { + "type": "object", + "required": ["sample_rate", "channel_count", "target_timebase", "max_window_samples"], + "properties": { + "sample_rate": {"type": "integer", "minimum": 1}, + "channel_count": {"type": "integer", "minimum": 1}, + "target_timebase": { + "type": "array", + "items": {"type": "integer"}, + "minItems": 2, + "maxItems": 2 + }, + "max_window_samples": {"type": "integer", "minimum": 1} + }, + "additionalProperties": false + }, + "limits": { + "type": "object", + "required": ["wall_seconds", "cpu_seconds", "resident_memory_bytes", "stream_count"], + "properties": { + "wall_seconds": {"type": "integer", "minimum": 1}, + "cpu_seconds": {"type": "integer", "minimum": 1}, + "resident_memory_bytes": {"type": "integer", "minimum": 1}, + "stream_count": {"type": "integer", "minimum": 1} + } + }, + "retry_profile": {"type": "string", "minLength": 1} + } + } + }, + "additionalProperties": false +} diff --git a/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-OPERATION-PROFILE.schema.json b/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-OPERATION-PROFILE.schema.json new file mode 100644 index 0000000..3a86cf9 --- /dev/null +++ b/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-OPERATION-PROFILE.schema.json @@ -0,0 +1,80 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "schema_id": "VID-IMPL-P00-003A-WAVEFORM-OPERATION-PROFILE", + "schema_version": "0.1.0-p00", + "title": "VID-IMPL-P00-003A operation profile schema", + "type": "object", + "required": [ + "profile_id", + "profile_version", + "operation_id", + "operation_version", + "implementation_id", + "implementation_profile_id", + "transport", + "ports", + "capabilities", + "policy" + ], + "properties": { + "profile_id": {"type": "string"}, + "profile_version": {"type": "string"}, + "operation_id": {"type": "string"}, + "operation_version": {"type": "string"}, + "implementation_id": {"type": "string"}, + "implementation_profile_id": {"type": "string"}, + "transport": {"type": "string"}, + "ports": { + "type": "array", + "minItems": 3, + "items": { + "type": "object", + "required": ["role", "order", "max_nesting", "max_bytes", "required", "schema"], + "properties": { + "role": {"type": "string"}, + "order": {"type": "integer", "minimum": 0}, + "max_nesting": {"type": "integer", "minimum": 1}, + "max_bytes": {"type": "integer", "minimum": 0}, + "required": {"type": "boolean"}, + "schema": {"type": "string"}, + "port_id": {"type": "string"} + }, + "additionalProperties": false + } + }, + "capabilities": { + "type": "object", + "required": ["supported", "unsupported"], + "properties": { + "supported": {"type": "array", "items": {"type": "string"}}, + "unsupported": {"type": "array", "items": {"type": "string"}} + }, + "additionalProperties": false + }, + "policy": { + "type": "object", + "required": [ + "cache_key_schema", + "cache_key_prefix", + "resource_profile_id", + "policy_profile_id", + "retry_profile_id", + "bulk_descriptor_profile", + "output_complete_only", + "publish_complete_only" + ], + "properties": { + "cache_key_schema": {"type": "string"}, + "cache_key_prefix": {"type": "string"}, + "resource_profile_id": {"type": "string"}, + "policy_profile_id": {"type": "string"}, + "retry_profile_id": {"type": "string"}, + "bulk_descriptor_profile": {"type": "string"}, + "output_complete_only": {"type": "boolean"}, + "publish_complete_only": {"type": "boolean"} + }, + "additionalProperties": false + } + }, + "additionalProperties": false +} diff --git a/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-PARAMETER.schema.json b/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-PARAMETER.schema.json new file mode 100644 index 0000000..f9fe511 --- /dev/null +++ b/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-PARAMETER.schema.json @@ -0,0 +1,98 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "schema_id": "VID-IMPL-P00-003A-WAVEFORM-PARAMETER", + "schema_version": "0.1.0-p00", + "title": "Waveform operation parameter schema", + "description": "Bounded non-media invocation profile and profile-derived cache-key context.", + "type": "object", + "required": [ + "cache_key_schema", + "cache_key_seed", + "environment_equivalence", + "resource_profile_id", + "policy_profile_id", + "retry_profile_id", + "representation", + "seed" + ], + "properties": { + "cache_key_schema": {"type": "string"}, + "cache_key_seed": {"type": "string"}, + "environment_equivalence": { + "type": "object", + "required": [ + "os_family", + "arch_family", + "worker_family", + "containerization", + "capability_bundle" + ], + "properties": { + "os_family": {"type": "string"}, + "arch_family": {"type": "string"}, + "worker_family": {"type": "string"}, + "containerization": {"type": "boolean"}, + "capability_bundle": {"type": "string"} + }, + "additionalProperties": false + }, + "resource_profile_id": {"type": "string"}, + "policy_profile_id": {"type": "string"}, + "retry_profile_id": {"type": "string"}, + "representation": { + "type": "object", + "required": [ + "peak_encoding", + "time_axis", + "channel_layout", + "downmix", + "resampling", + "timebase" + ], + "properties": { + "peak_encoding": {"type": "string"}, + "time_axis": {"type": "string"}, + "channel_layout": {"type": "string"}, + "downmix": { + "type": "object", + "required": ["matrix_id", "matrix_version", "implementation_id"], + "properties": { + "matrix_id": {"type": "string"}, + "matrix_version": {"type": "string"}, + "implementation_id": {"type": "string"} + }, + "additionalProperties": false + }, + "resampling": { + "type": "object", + "required": ["implementation_id", "delay_samples", "trim_samples", "correction_profile_id"], + "properties": { + "implementation_id": {"type": "string"}, + "delay_samples": {"type": "integer", "minimum": 0}, + "trim_samples": {"type": "integer", "minimum": 0}, + "correction_profile_id": {"type": "string"} + }, + "additionalProperties": false + }, + "timebase": { + "type": "array", + "items": {"type": "integer"}, + "minItems": 2, + "maxItems": 2 + } + }, + "additionalProperties": false + }, + "seed": { + "type": "object", + "required": ["attempt", "batch", "revision"], + "properties": { + "attempt": {"type": "string"}, + "batch": {"type": "string"}, + "revision": {"type": "string"} + }, + "additionalProperties": false + } + }, + "additionalProperties": false +} diff --git a/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-POLICY.schema.json b/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-POLICY.schema.json new file mode 100644 index 0000000..d146baa --- /dev/null +++ b/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-POLICY.schema.json @@ -0,0 +1,73 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "schema_id": "VID-IMPL-P00-003A-WAVEFORM-POLICY", + "schema_version": "0.1.0-p00", + "title": "Waveform policy schema", + "type": "object", + "required": [ + "policy_id", + "isolation", + "capability_class", + "containment", + "output_constraints", + "publication_gate" + ], + "properties": { + "policy_id": {"type": "string"}, + "isolation": { + "type": "object", + "required": ["network", "watchdog", "job_object", "transport"], + "properties": { + "network": {"type": "string", "enum": ["denied"]}, + "watchdog": {"type": "string", "enum": ["required"]}, + "job_object": {"type": "string", "enum": ["required"]}, + "transport": {"type": "string", "enum": ["local-staged-file"]} + }, + "additionalProperties": false + }, + "containment": { + "type": "object", + "required": ["proof_required", "cross_operation_forbidden", "path_identity_forbidden"], + "properties": { + "proof_required": {"type": "boolean"}, + "cross_operation_forbidden": {"type": "boolean"}, + "path_identity_forbidden": {"type": "boolean"} + }, + "additionalProperties": false + }, + "output_constraints": { + "type": "object", + "required": [ + "complete_only", + "max_retry_attempts", + "publish_only_after_journal" + ], + "properties": { + "complete_only": {"type": "boolean"}, + "max_retry_attempts": {"type": "integer", "minimum": 1}, + "publish_only_after_journal": {"type": "boolean"} + }, + "additionalProperties": false + }, + "capability_class": {"type": "string"}, + "publication_gate": { + "type": "object", + "required": [ + "requires_lease", + "requires_fence", + "required_authority", + "stale_failure", + "cache_stale_failure" + ], + "properties": { + "requires_lease": {"type": "boolean"}, + "requires_fence": {"type": "boolean"}, + "required_authority": {"type": "string"}, + "stale_failure": {"type": "string"}, + "cache_stale_failure": {"type": "string"} + }, + "additionalProperties": false + } + }, + "additionalProperties": false +} diff --git a/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-RESOURCE.schema.json b/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-RESOURCE.schema.json new file mode 100644 index 0000000..5bd063d --- /dev/null +++ b/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-RESOURCE.schema.json @@ -0,0 +1,42 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "schema_id": "VID-IMPL-P00-003A-WAVEFORM-RESOURCE", + "schema_version": "0.1.0-p00", + "title": "Waveform resource profile schema", + "type": "object", + "required": ["resource_id", "limits", "transport", "caps"], + "properties": { + "resource_id": {"type": "string", "minLength": 1}, + "limits": { + "type": "object", + "required": [ + "control_envelope_bytes", + "wall_time_seconds", + "cpu_time_seconds", + "resident_memory_bytes", + "staging_bytes", + "bulk_payload_bytes", + "payload_text_bytes", + "nesting_max" + ], + "properties": { + "control_envelope_bytes": {"type": "integer", "minimum": 1}, + "wall_time_seconds": {"type": "integer", "minimum": 1}, + "cpu_time_seconds": {"type": "integer", "minimum": 1}, + "resident_memory_bytes": {"type": "integer", "minimum": 1}, + "staging_bytes": {"type": "integer", "minimum": 1}, + "bulk_payload_bytes": {"type": "integer", "minimum": 1}, + "payload_text_bytes": {"type": "integer", "minimum": 1}, + "nesting_max": {"type": "integer", "minimum": 1} + }, + "additionalProperties": false + }, + "transport": {"type": "string"}, + "caps": { + "type": "array", + "items": {"type": "string"}, + "minItems": 1 + } + }, + "additionalProperties": false +} diff --git a/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-STRUCTURED-ERROR.schema.json b/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-STRUCTURED-ERROR.schema.json new file mode 100644 index 0000000..6a9cbf3 --- /dev/null +++ b/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-STRUCTURED-ERROR.schema.json @@ -0,0 +1,75 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "schema_id": "VID-IMPL-P00-003A-WAVEFORM-STRUCTURED-ERROR", + "schema_version": "0.1.0-p00", + "title": "Waveform structured error schema", + "type": "object", + "required": [ + "schema_id", + "schema_version", + "error_ref", + "trace_id", + "correlation_id", + "subject", + "video_disposition", + "shared_state", + "error_category", + "retry_class", + "operation_stage", + "safe_recovery", + "identity_refs", + "applies_to" + ], + "properties": { + "schema_id": {"type": "string"}, + "schema_version": {"type": "string"}, + "error_ref": { + "type": "object", + "required": ["namespace", "code", "version", "error_instance"], + "properties": { + "namespace": {"type": "string"}, + "code": {"type": "string"}, + "version": {"type": "string"}, + "error_instance": {"type": "string", "minLength": 1} + } + }, + "trace_id": {"type": "string", "minLength": 1, "maxLength": 256}, + "correlation_id": {"type": "string", "minLength": 1, "maxLength": 256}, + "subject": {"type": "string", "minLength": 1, "maxLength": 256}, + "video_disposition": {"type": "string"}, + "shared_state": {"type": "string"}, + "error_category": {"type": "string"}, + "retry_class": {"type": "string"}, + "operation_stage": {"type": "string"}, + "safe_recovery": {"type": "string", "maxLength": 256}, + "identity_refs": { + "type": "array", + "items": {"type": "string"}, + "minItems": 1, + "maxItems": 5 + }, + "details": { + "type": "array", + "items": {"type": "string"}, + "maxItems": 3 + }, + "causes": { + "type": "array", + "items": {"type": "string"}, + "maxItems": 3 + }, + "applies_to": { + "type": "object", + "required": ["job_ref", "attempt_ref", "dispatch_ref", "worker_ref"], + "properties": { + "job_ref": {"type": "string", "minLength": 1}, + "attempt_ref": {"type": "string", "minLength": 1}, + "dispatch_ref": {"type": "string", "minLength": 1}, + "worker_ref": {"type": "string", "minLength": 1}, + "publication_ref": {"type": ["string", "null"]} + }, + "additionalProperties": false + } + }, + "additionalProperties": false +} diff --git a/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-WORKER-HELLO.schema.json b/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-WORKER-HELLO.schema.json new file mode 100644 index 0000000..ba1b37d --- /dev/null +++ b/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-WORKER-HELLO.schema.json @@ -0,0 +1,75 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "schema_id": "VID-IMPL-P00-003A-WAVEFORM-WORKER-HELLO", + "schema_version": "0.1.0-p00", + "title": "VID-IMPL-P00-003A worker-hello schema", + "type": "object", + "required": [ + "operation_id", + "operation_version", + "implementation_id", + "implementation_profile_id", + "transport", + "platform", + "architecture", + "control_protocol_min", + "control_protocol_max", + "limits", + "supported", + "unsupported", + "resource_profile_id", + "policy_profile_id", + "retry_profile_id" + ], + "properties": { + "operation_id": {"type": "string"}, + "operation_version": {"type": "string"}, + "implementation_id": {"type": "string"}, + "implementation_profile_id": {"type": "string"}, + "transport": {"type": "string"}, + "platform": {"type": "string"}, + "architecture": {"type": "string"}, + "control_protocol_min": {"type": "string"}, + "control_protocol_max": {"type": "string"}, + "limits": { + "type": "object", + "required": [ + "control_envelope_bytes", + "stream_count", + "wall_time_seconds", + "child_cpu_seconds", + "resident_memory_bytes", + "staging_bytes", + "bulk_payload_bytes", + "bulk_descriptor_bytes", + "output_bytes", + "error_bytes" + ], + "properties": { + "control_envelope_bytes": {"type": "integer", "minimum": 1}, + "stream_count": {"type": "integer", "minimum": 1}, + "wall_time_seconds": {"type": "integer", "minimum": 1}, + "child_cpu_seconds": {"type": "integer", "minimum": 1}, + "resident_memory_bytes": {"type": "integer", "minimum": 1}, + "staging_bytes": {"type": "integer", "minimum": 0}, + "bulk_payload_bytes": {"type": "integer", "minimum": 0}, + "bulk_descriptor_bytes": {"type": "integer", "minimum": 1}, + "output_bytes": {"type": "integer", "minimum": 1}, + "error_bytes": {"type": "integer", "minimum": 1} + }, + "additionalProperties": false + }, + "supported": { + "type": "array", + "items": {"type": "string"} + }, + "unsupported": { + "type": "array", + "items": {"type": "string"} + }, + "resource_profile_id": {"type": "string"}, + "policy_profile_id": {"type": "string"}, + "retry_profile_id": {"type": "string"} + }, + "additionalProperties": false +} diff --git a/specifications/evidence/PHASE-00-IMPLEMENTATION/VID-IMPL-P00-003A/manifest.json b/specifications/evidence/PHASE-00-IMPLEMENTATION/VID-IMPL-P00-003A/manifest.json new file mode 100644 index 0000000..d3974f9 --- /dev/null +++ b/specifications/evidence/PHASE-00-IMPLEMENTATION/VID-IMPL-P00-003A/manifest.json @@ -0,0 +1,164 @@ +{ + "implementation_id": "VID-IMPL-P00-003A", + "issue": { + "id": 30, + "title": "Recoverable Waveform Contract and Cache Foundation", + "milestone": "v0.1.0-alpha" + }, + "authority": { + "decision": "OWNER-AUTH-V2", + "phase": "Phase 00" + }, + "artifact_directory": "Video Localization/specifications/evidence/PHASE-00-IMPLEMENTATION/VID-IMPL-P00-003A", + "allowed_scope": [ + "contract/schema/profile fixture materialization under exact admission manifest binding", + "deterministic CBOR cache-key preimage and digest synthesis", + "bulk descriptor canonical serialization and descriptor_hash integrity checks", + "bulk descriptor/representation/state-mapping negative matrix", + "waveform contract-only fixture and cache-key negative-path coverage", + "internal commit journal authority for publication lifecycle and terminal success transitions", + "no real media parsing/decoding, ffmpeg/ffprobe execution, playback, VFR, or UI behavior in this packet" + ], + "evidence_files": [ + "manifest.json", + "test-report.json" + ], + "changed_files": [ + "Video Localization/.gitattributes", + "Video Localization/workers/VideoLocalization.Worker/src/lib.rs", + "Video Localization/contracts/VID-IMPL-P00-003A/schema-bundle.json", + "Video Localization/contracts/VID-IMPL-P00-003A/records/manifest.json", + "Video Localization/contracts/VID-IMPL-P00-003A/records/operation-profile.json", + "Video Localization/contracts/VID-IMPL-P00-003A/records/resource-profile.json", + "Video Localization/contracts/VID-IMPL-P00-003A/records/policy-profile.json", + "Video Localization/contracts/VID-IMPL-P00-003A/records/retry-profile.json", + "Video Localization/contracts/VID-IMPL-P00-003A/fixtures/operation-descriptor.json", + "Video Localization/contracts/VID-IMPL-P00-003A/fixtures/worker-hello.json", + "Video Localization/contracts/VID-IMPL-P00-003A/fixtures/cache-key-and-descriptor-fixtures.json", + "Video Localization/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-INPUT.schema.json", + "Video Localization/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-ARTIFACT.schema.json", + "Video Localization/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-PARAMETER.schema.json", + "Video Localization/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-STRUCTURED-ERROR.schema.json", + "Video Localization/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-RESOURCE.schema.json", + "Video Localization/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-POLICY.schema.json", + "Video Localization/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-BULK-DESCRIPTOR.schema.json", + "Video Localization/workers/VideoLocalization.Worker/src/waveform_contract.rs", + "Video Localization/workers/VideoLocalization.Worker/tests/waveform_contract.rs", + "Video Localization/testing/implementation/VID-IMPL-P00-003A/waveform-fixtures.json", + "Video Localization/testing/implementation/VID-IMPL-P00-003A/README.md" + ], + "evidence_records": [ + { + "role": "line-ending-policy", + "path": "Video Localization/.gitattributes", + "sha256": "79c842f844bb646353a06c3088857c63a4d613d74051215d890585c43c3132e1" + }, + { + "role": "module-export", + "path": "Video Localization/workers/VideoLocalization.Worker/src/lib.rs", + "sha256": "69cb069b7f2ac8ec876ff1aeae969772fc70b4dcc6af66a5022fe433c73e8bca" + }, + { + "role": "schema-bundle", + "path": "Video Localization/contracts/VID-IMPL-P00-003A/schema-bundle.json", + "sha256": "c01cc30752532e9abb5804d76883c890a58b267cf886cb01f1c25716be7310c9" + }, + { + "role": "manifest", + "path": "Video Localization/contracts/VID-IMPL-P00-003A/records/manifest.json", + "sha256": "c20d3ecbfcdedc6e46089659b2fc65bf7a2aab89f95d5e8611ceab9f00d313b8" + }, + { + "role": "operation-profile", + "path": "Video Localization/contracts/VID-IMPL-P00-003A/records/operation-profile.json", + "sha256": "2374d0730488c262148516051431b09acb0e2b06fe5ec901d5ffdb2739a889db" + }, + { + "role": "resource-profile", + "path": "Video Localization/contracts/VID-IMPL-P00-003A/records/resource-profile.json", + "sha256": "6da872ad96a9f0840cc62bf2bd27201aaf8d877002d5add749833710d3e5e07d" + }, + { + "role": "policy-profile", + "path": "Video Localization/contracts/VID-IMPL-P00-003A/records/policy-profile.json", + "sha256": "ad4838a59d06ee676b4b94be43d6f9dd5c7ded88f5c57cfd7f7f56bcae82c368" + }, + { + "role": "retry-profile", + "path": "Video Localization/contracts/VID-IMPL-P00-003A/records/retry-profile.json", + "sha256": "35de87a3fe7681a485d2b8d4199f5fe89b8d27c38b1500043dd01397d9b3f8e1" + }, + { + "role": "operation-descriptor", + "path": "Video Localization/contracts/VID-IMPL-P00-003A/fixtures/operation-descriptor.json", + "sha256": "827f842460512e2721ed6fcd0832f4bf0250c3d15dfca3c7504d4d71a27856e4" + }, + { + "role": "worker-hello", + "path": "Video Localization/contracts/VID-IMPL-P00-003A/fixtures/worker-hello.json", + "sha256": "4bcc23f8c0ce2b6469a16dea7e137807ebc407a693a8234f657fc20fbc805c2f" + }, + { + "role": "cache-and-descriptor-fixtures", + "path": "Video Localization/contracts/VID-IMPL-P00-003A/fixtures/cache-key-and-descriptor-fixtures.json", + "sha256": "f609a700a89edc1ca25c12f6d8ec496bb3887c3263604ce8d6cca2b62e9a046a" + }, + { + "role": "schema-input", + "path": "Video Localization/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-INPUT.schema.json", + "sha256": "916dd6e26609ff34906199a7a10ffb047fcdf50334b6aefd3f1e0a01e497b84e" + }, + { + "role": "schema-artifact", + "path": "Video Localization/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-ARTIFACT.schema.json", + "sha256": "b6d48767ee109fa60715d9bb9d477196553d6196a9f43202d96f37e20cd04154" + }, + { + "role": "schema-parameter", + "path": "Video Localization/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-PARAMETER.schema.json", + "sha256": "43da57dccf0152e8bb303406cbefb16ea590168e207157e2dd0f38a0fdb6713b" + }, + { + "role": "schema-structured-error", + "path": "Video Localization/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-STRUCTURED-ERROR.schema.json", + "sha256": "c551d0c1b23c542aa61155180c7d9314cce19739f557513b384d43b709142b54" + }, + { + "role": "schema-resource", + "path": "Video Localization/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-RESOURCE.schema.json", + "sha256": "6e9f8c77278401e3e943a531d4939a941f62279a9030ac4252c53f1ef7668405" + }, + { + "role": "schema-policy", + "path": "Video Localization/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-POLICY.schema.json", + "sha256": "925c07f72ff7ba1a46ec0a2ada05a6b6554815c3c77d1ae6863ae050707601f9" + }, + { + "role": "schema-bulk-descriptor", + "path": "Video Localization/contracts/VID-IMPL-P00-003A/schemas/VID-IMPL-P00-003A-WAVEFORM-BULK-DESCRIPTOR.schema.json", + "sha256": "cec467e93fd40e8a1ce62c2c73e1ac3f0aa1095e26d864f93745040e4e83eecf" + }, + { + "role": "source", + "path": "Video Localization/workers/VideoLocalization.Worker/src/waveform_contract.rs", + "sha256": "7b68d129828eebb11ca9cd64f3d4d3346c899c38334e51eb499cb98dcb2866b8" + }, + { + "role": "source-tests", + "path": "Video Localization/workers/VideoLocalization.Worker/tests/waveform_contract.rs", + "sha256": "77bddf3b5c94443d61ab7636634f2dbad68d1591d9d7af3342db34c9d2fe735f" + }, + { + "role": "test-fixtures", + "path": "Video Localization/testing/implementation/VID-IMPL-P00-003A/waveform-fixtures.json", + "sha256": "61aabb4b78860632694288e7b23fe9b83c7984de52ac596e1a803f84c6a25347" + }, + { + "role": "implementation-readme", + "path": "Video Localization/testing/implementation/VID-IMPL-P00-003A/README.md", + "sha256": "3c1604f9eec7a529fb94f04bb63881c914559ac386dddfba4e0055a02b906e6b" + } + ], + "created_at": "2026-08-02T23:59:59+07:00", + "updated_at": "2026-08-02T23:59:59+07:00" +} diff --git a/specifications/evidence/PHASE-00-IMPLEMENTATION/VID-IMPL-P00-003A/test-report.json b/specifications/evidence/PHASE-00-IMPLEMENTATION/VID-IMPL-P00-003A/test-report.json new file mode 100644 index 0000000..ac35707 --- /dev/null +++ b/specifications/evidence/PHASE-00-IMPLEMENTATION/VID-IMPL-P00-003A/test-report.json @@ -0,0 +1,137 @@ +{ + "implementation_id": "VID-IMPL-P00-003A", + "issued_at": "2026-08-02T23:59:59+07:00", + "issue": { + "id": 30, + "title": "Recoverable Waveform Contract and Cache Foundation", + "milestone": "v0.1.0-alpha" + }, + "evidence_claims": { + "contract-manifest-complete": { + "status": "passed", + "notes": "Admission manifest, schema-bundle, record, schema, and fixture bindings are complete and enforce fail-closed matching against explicit file hashes." + }, + "deterministic-cache-key-foundation": { + "status": "passed", + "notes": "Cache-key preimage construction uses stable key sorting with fixed PROFILE and prefix; fixture vectors include fixed expected 64-hex cache key digests and are compared directly." + }, + "bulk-descriptor-integrity-foundation": { + "status": "passed", + "notes": "Bulk descriptor linkage validates payload length/hash, descriptor preimage/hash, and deterministic descriptor-hash vector enforcement." + }, + "line-ending-policy": { + "status": "passed", + "notes": "VID-IMPL-P00-003A manifest-bound text artifacts are UTF-8, BOM-free, CR-free, and end with exactly one LF." + }, + "state-mapping-completeness": { + "status": "passed", + "notes": "VID-WAVEFORM disposition coverage remains complete, with TimedOut constrained to deadline-expired state and Succeeded requiring an authoritative commit journal identity." + }, + "journal-authority-completion": { + "status": "passed", + "notes": "Terminal success now requires a registered staged-validated commit journal entry; unrecorded, fabricated, mismatched, and removed journal identities fail closed." + }, + "negative-mutation-matrix": { + "status": "passed", + "notes": "Cache-key and bulk descriptor positive/negative fixture matrices execute end-to-end (including unauthorized worker hello identities through schema validation)." + } + }, + "toolchain": { + "rustc": "rustc 1.97.1 (8bab26f4f 2026-07-14)", + "sha2": "0.11.0", + "serde": "1.0.229", + "serde_json": "1.0.151" + }, + "commands": [ + { + "command": "cargo test --manifest-path 'Video Localization/workers/VideoLocalization.Worker/Cargo.toml' --locked --test waveform_contract", + "working_directory": "Video Localization", + "status": "passed", + "exit_code": 0, + "test_count": 23, + "environment": { + "CARGO_HOME": "C:\\Users\\SubMark\\AppData\\Local\\Temp\\vid-p00-003a-cargo-home", + "CARGO_REGISTRIES_CRATES_IO_PROTOCOL": "sparse", + "CARGO_HTTP_TIMEOUT": "300", + "CARGO_HTTP_LOW_SPEED_LIMIT": "1" + }, + "raw_output": { + "stdout": "running 23 tests\ntest bulk_descriptor_positive_and_zero_length_boundary ... ok\ntest cache_key_preimage_is_stable_with_sorted_cbor_key_bytes ... ok\ntest fixture_hostile_metadata_vectors_and_mutations_fail_closed ... ok\ntest fixture_opaque_handle_substitution_and_path_escape_vectors_are_rejected ... ok\ntest retry_profile_enforces_attempt_ceiling_and_cumulative_limits ... ok\ntest fixture_cache_corruption_and_deletion_rejects_without_publication_authority ... ok\ntest fixture_representation_timeline_downmix_vectors_are_bound_and_mutated ... ok\ntest fixture_cache_key_positive_and_negative_cases_are_executed ... ok\ntest fixture_interruption_and_partial_write_vectors_are_executed ... ok\ntest fixture_bulk_descriptor_positive_and_negative_cases_are_executed ... ok\ntest manifest_missing_or_mismatched_bindings_fail_closed ... ok\ntest manifest_bound_text_artifacts_are_utf8_and_exactly_one_final_lf ... ok\ntest terminal_reconciliation_map_requires_authoritative_deadline_and_receipt ... ok\ntest fixture_stale_epoch_fence_lease_cases_fail_closed ... ok\ntest fixture_publication_journal_failures_are_differentiated ... ok\ntest fixture_publication_atomicity_and_cross_volume_reuse_are_rejected ... ok\ntest publication_lifecycle_validates_atomic_commit_and_lineage_controls ... ok\ntest schema_bundle_hashes_and_required_schema_ids_are_exact ... ok\ntest manifest_and_schema_bundle_are_authoritative_and_fail_closed ... ok\ntest worker_hello_rejects_unauthorized_executable_identity ... ok\ntest operation_and_worker_hello_profile_bindings_are_exact ... ok\ntest schema_mutation_matrix_rejects_required_and_unknown_fields ... ok\ntest result: ok. 23 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.03s", + "stderr": "" + } + }, + { + "command": "Get-ChildItem 'Video Localization/contracts/VID-IMPL-P00-003A' -Recurse -Filter *.json | ForEach-Object { Get-Content $_ -Raw | ConvertFrom-Json | Out-Null }", + "working_directory": "Video Localization", + "status": "passed", + "exit_code": 0, + "raw_output": { + "stdout": "", + "stderr": "" + } + } + ], + "checks": [ + { + "id": "manifest_hashes_match", + "name": "Manifest hash records match each bound schema and fixture file", + "status": "passed" + }, + { + "id": "manifest_text_line_endings", + "name": "Manifest-bound text artifacts are UTF-8, BOM-free, CR-free, and end with exactly one LF", + "status": "passed" + }, + { + "id": "operation_binding", + "name": "OperationDescriptor and WorkerHello fixture values bind exact operation/implementation IDs", + "status": "passed" + }, + { + "id": "state_mapping", + "name": "All VID-WAVEFORM dispositions are present with full mapping metadata", + "status": "passed" + }, + { + "id": "publication_journal_authority", + "name": "Terminal success path requires an authoritative commit journal identity and rejects stale, unrecorded, or revoked receipt paths", + "status": "passed" + }, + { + "id": "cache_key_deterministic", + "name": "Cache-key preimage normalization, digest derivation, and ordered map behavior are deterministic", + "status": "passed" + }, + { + "id": "cache_key_negative_inputs", + "name": "Negative cache-key mutations fail as expected", + "status": "passed" + }, + { + "id": "bulk_descriptor_positive", + "name": "Bulk descriptor preimage and digest remain consistent and validate with descriptor_hash binding", + "status": "passed" + }, + { + "id": "bulk_descriptor_negative", + "name": "Negative bulk descriptor mutations fail validation", + "status": "passed" + }, + { + "id": "publication_lifecycle_checks", + "name": "Atomic publication lifecycle checks validate lease/fence/epoch lineage and deterministic commit-receipt transition controls", + "status": "passed" + }, + { + "id": "schema_bundle_digests", + "name": "Schema-bundle fixture and schema digest closure checks are pass-closed", + "status": "passed" + }, + { + "id": "manifest_schema_bundle_evidence_alignment", + "name": "Manifest, schema-bundle, and evidence records remain byte-aligned after hash recomputation", + "status": "passed" + } + ], + "violations": [] +} diff --git a/testing/implementation/VID-IMPL-P00-003A/README.md b/testing/implementation/VID-IMPL-P00-003A/README.md new file mode 100644 index 0000000..4d882f7 --- /dev/null +++ b/testing/implementation/VID-IMPL-P00-003A/README.md @@ -0,0 +1,32 @@ +# VID-IMPL-P00-003A + +Scope: waveform contract/cache/foundation for deterministic cache-key and whole-object bulk descriptor behavior. + +## Synthetic fixture notes + +- No media parsing or decoding occurs. +- Fixtures exercise negative and positive contract-only vectors: + - deterministic cache-key inputs/outputs + - bulk descriptor hashing and validation + - negative mutation vectors for malformed descriptor requirements + +## Canonical artifacts under test + +- `contracts/VID-IMPL-P00-003A/schema-bundle.json` +- `contracts/VID-IMPL-P00-003A/records/manifest.json` +- `contracts/VID-IMPL-P00-003A/fixtures/operation-descriptor.json` +- `contracts/VID-IMPL-P00-003A/fixtures/worker-hello.json` +- `contracts/VID-IMPL-P00-003A/fixtures/cache-key-and-descriptor-fixtures.json` +- `contracts/VID-IMPL-P00-003A/records/operation-profile.json` +- `contracts/VID-IMPL-P00-003A/records/resource-profile.json` +- `contracts/VID-IMPL-P00-003A/records/policy-profile.json` +- `contracts/VID-IMPL-P00-003A/records/retry-profile.json` +- `Video Localization/workers/VideoLocalization.Worker/src/waveform_contract.rs` +- `Video Localization/workers/VideoLocalization.Worker/tests/waveform_contract.rs` + +## Negative fixture matrix + +- request port/identity mismatch conditions for schema validation +- non-zero cache key ordering checks +- descriptor without required `chunk_hashes_omitted=true` +- malformed descriptor hashes and representation constraints diff --git a/testing/implementation/VID-IMPL-P00-003A/waveform-fixtures.json b/testing/implementation/VID-IMPL-P00-003A/waveform-fixtures.json new file mode 100644 index 0000000..16670fb --- /dev/null +++ b/testing/implementation/VID-IMPL-P00-003A/waveform-fixtures.json @@ -0,0 +1,387 @@ +{ + "cache_key_positive_cases": [ + { + "case_id": "cache-key-positive-001", + "seed": "waveform-seed-003a", + "resource_profile_id": "VID-WAVEFORM-RESOURCE-P00-003A", + "policy_profile_id": "VID-WAVEFORM-POLICY-P00-003A", + "retry_profile_id": "VID-WAVEFORM-RETRY-P00-003A", + "input_ports": [ + { + "order": 0, + "type": "waveform_request", + "schema": "VID-IMPL-P00-003A-WAVEFORM-INPUT", + "content": "source", + "revision": "0.1.0-p00", + "sample_range": "[0,4096)" + } + ], + "representation": { + "peak": "waveform-peak-v1", + "time": "sample", + "channel": "stereo-major", + "downmix": "matrix-stereo-downmix-v1", + "resampling": "resample-none", + "stability": "fixed" + }, + "expected_cache_key_prefix": "SUI-CACHE-KEY-V1\u0000", + "expected_cache_key_digest": "8eda1f679adc820e35ed450e3ea70707b9a96e4a4e8eddd4a767c5727566a835" + } + ], + "cache_key_negative_cases": [ + { + "case_id": "cache-key-negative-invalid-seed", + "invalid_seed": true, + "missing_seed": false + }, + { + "case_id": "cache-key-negative-missing-seed", + "invalid_seed": false, + "missing_seed": true + } + ], + "bulk_descriptor_positive_cases": [ + { + "case_id": "bulk-descriptor-positive-001", + "descriptor": { + "version": "VID-WAVEFORM-BULK-DESCRIPTOR-V1", + "mode": "read-only", + "handle_identity": "handle-vid-waveform-003a", + "attempt_id": "attempt-001", + "lease_id": "lease-001", + "cancel_scope": "attempt-001", + "expiry": "2099-01-01T00:00:00Z", + "integrity": { + "algorithm": "sha-256", + "value": "d67c656e01756650d77717b0839985a056ec28ffe174601d690fc407a2ceffca" + }, + "chunk_hashes_omitted": true, + "length": 4096, + "payload_schema": "VID-IMPL-P00-003A-WAVEFORM-ARTIFACT", + "source_publication_fence": "fence-001", + "representation": { + "peak": "waveform-peak-v1", + "time": "sample", + "channel": "stereo-major", + "downmix": "matrix-stereo-downmix-v1", + "resampling": "resample-none", + "source_timeline": "timeline-001", + "sample_range": "[0,4096)" + }, + "descriptor_hash": "3f1aabb75fb6a7aeb4e38f9ccc1d49ad36c5b2e019eed79d6b67adc158ec371d" + }, + "expected_descriptor_digest": "3f1aabb75fb6a7aeb4e38f9ccc1d49ad36c5b2e019eed79d6b67adc158ec371d" + } + ], + "bulk_descriptor_negative_cases": [ + { + "case_id": "bulk-descriptor-negative-missing-descriptor-hash", + "descriptor": { + "version": "VID-WAVEFORM-BULK-DESCRIPTOR-V1", + "mode": "read-only", + "handle_identity": "handle-vid-waveform-003a", + "attempt_id": "attempt-001", + "lease_id": "lease-001", + "cancel_scope": "attempt-001", + "expiry": "2099-01-01T00:00:00Z", + "integrity": { + "algorithm": "sha-256", + "value": "d67c656e01756650d77717b0839985a056ec28ffe174601d690fc407a2ceffca" + }, + "chunk_hashes_omitted": true, + "length": 4096, + "payload_schema": "VID-IMPL-P00-003A-WAVEFORM-ARTIFACT", + "source_publication_fence": "fence-001", + "representation": { + "peak": "waveform-peak-v1", + "time": "sample", + "channel": "stereo-major", + "downmix": "matrix-stereo-downmix-v1", + "resampling": "resample-none", + "source_timeline": "timeline-001", + "sample_range": "[0,4096)" + }, + "descriptor_hash": "3f1aabb75fb6a7aeb4e38f9ccc1d49ad36c5b2e019eed79d6b67adc158ec371d" + }, + "reason": "missing-descriptor-hash" + }, + { + "case_id": "bulk-descriptor-negative-chunk-hash-required", + "descriptor": { + "version": "VID-WAVEFORM-BULK-DESCRIPTOR-V1", + "mode": "read-only", + "handle_identity": "handle-vid-waveform-003a", + "attempt_id": "attempt-001", + "lease_id": "lease-001", + "cancel_scope": "attempt-001", + "expiry": "2099-01-01T00:00:00Z", + "integrity": { + "algorithm": "sha-256", + "value": "d67c656e01756650d77717b0839985a056ec28ffe174601d690fc407a2ceffca" + }, + "chunk_hashes_omitted": true, + "length": 4096, + "payload_schema": "VID-IMPL-P00-003A-WAVEFORM-ARTIFACT", + "source_publication_fence": "fence-001", + "representation": { + "peak": "waveform-peak-v1", + "time": "sample", + "channel": "stereo-major", + "downmix": "matrix-stereo-downmix-v1", + "resampling": "resample-none", + "source_timeline": "timeline-001", + "sample_range": "[0,4096)" + }, + "descriptor_hash": "3f1aabb75fb6a7aeb4e38f9ccc1d49ad36c5b2e019eed79d6b67adc158ec371d" + }, + "reason": "chunk-list" + }, + { + "case_id": "bulk-descriptor-negative-non-hex-integrity", + "descriptor": { + "version": "VID-WAVEFORM-BULK-DESCRIPTOR-V1", + "mode": "read-only", + "handle_identity": "handle-vid-waveform-003a", + "attempt_id": "attempt-001", + "lease_id": "lease-001", + "cancel_scope": "attempt-001", + "expiry": "2099-01-01T00:00:00Z", + "integrity": { + "algorithm": "sha-256", + "value": "not-a-digest" + }, + "chunk_hashes_omitted": true, + "length": 4096, + "payload_schema": "VID-IMPL-P00-003A-WAVEFORM-ARTIFACT", + "source_publication_fence": "fence-001", + "representation": { + "peak": "waveform-peak-v1", + "time": "sample", + "channel": "stereo-major", + "downmix": "matrix-stereo-downmix-v1", + "resampling": "resample-none", + "source_timeline": "timeline-001", + "sample_range": "[0,4096)" + }, + "descriptor_hash": "3f1aabb75fb6a7aeb4e38f9ccc1d49ad36c5b2e019eed79d6b67adc158ec371d" + }, + "reason": "non-hex" + }, + { + "case_id": "bulk-descriptor-negative-misaligned-hash", + "descriptor": { + "version": "VID-WAVEFORM-BULK-DESCRIPTOR-V1", + "mode": "read-only", + "handle_identity": "handle-vid-waveform-003a", + "attempt_id": "attempt-001", + "lease_id": "lease-001", + "cancel_scope": "attempt-001", + "expiry": "2099-01-01T00:00:00Z", + "integrity": { + "algorithm": "sha-256", + "value": "d67c656e01756650d77717b0839985a056ec28ffe174601d690fc407a2ceffca" + }, + "chunk_hashes_omitted": true, + "length": 4096, + "payload_schema": "VID-IMPL-P00-003A-WAVEFORM-ARTIFACT", + "source_publication_fence": "fence-001", + "representation": { + "peak": "waveform-peak-v1", + "time": "sample", + "channel": "stereo-major", + "downmix": "matrix-stereo-downmix-v1", + "resampling": "resample-none", + "source_timeline": "timeline-001", + "sample_range": "[0,4096)" + }, + "descriptor_hash": "3f1aabb75fb6a7aeb4e38f9ccc1d49ad36c5b2e019eed79d6b67adc158ec371d" + }, + "reason": "mismatched-length" + } + ], + "representation_timeline_downmix_cases": [ + { + "case_id": "representation-timeline-downmix-positive-001", + "kind": "positive", + "descriptor": { + "representation": { + "time": "sample", + "source_timeline": "timeline-001", + "sample_range": "[0,4096)", + "downmix": "matrix-stereo-downmix-v1", + "channel": "stereo-major", + "peak": "waveform-peak-v1", + "resampling": "resample-none" + } + } + }, + { + "case_id": "representation-timeline-downmix-negative-length-mismatch", + "kind": "negative", + "descriptor": { + "length": 2048, + "descriptor_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + } + } + ], + "hostile_metadata_cases": [ + { + "case_id": "hostile-metadata-non-hex-integrity", + "kind": "negative", + "descriptor": { + "integrity": { + "algorithm": "sha-256", + "value": "not-a-digest" + } + } + }, + { + "case_id": "hostile-metadata-algorithm-mismatch", + "kind": "negative", + "descriptor": { + "integrity": { + "algorithm": "md5", + "value": "000000000000000000000000000000000000000000000000000000000000000000" + } + } + } + ], + "interruption_cases": [ + { + "case_id": "interruption-cancelled", + "kind": "cancelled" + }, + { + "case_id": "interruption-crash", + "kind": "crash" + }, + { + "case_id": "interruption-deadline", + "kind": "deadline" + }, + { + "case_id": "interruption-partial-write", + "kind": "partial-write" + } + ], + "publication_journal_cases": [ + { + "case_id": "publication-journal-valid", + "kind": "valid" + }, + { + "case_id": "publication-journal-unrecorded", + "kind": "unrecorded" + }, + { + "case_id": "publication-journal-fabricated", + "kind": "fabricated" + }, + { + "case_id": "publication-journal-mismatched", + "kind": "mismatched" + }, + { + "case_id": "publication-journal-revoked", + "kind": "revoked" + } + ], + "stale_epoch_fence_lease_cases": [ + { + "case_id": "stale-publication-valid", + "kind": "valid", + "expect_error": false + }, + { + "case_id": "stale-publication-stale-epoch", + "kind": "stale-epoch", + "expect_error": true + }, + { + "case_id": "stale-publication-fence-mismatch", + "kind": "fence-mismatch", + "expect_error": true + }, + { + "case_id": "stale-publication-lease-mismatch", + "kind": "lease-mismatch", + "expect_error": true + }, + { + "case_id": "stale-publication-attempt-mismatch", + "kind": "attempt-mismatch", + "expect_error": true + } + ], + "opaque_handle_substitution_cases": [ + { + "case_id": "opaque-handle-positive-safe-identity", + "kind": "positive", + "descriptor": { + "handle_identity": "handle-vid-waveform-opaque-003a", + "attempt_id": "attempt-001", + "lease_id": "lease-001" + } + }, + { + "case_id": "opaque-handle-path-traversal-dotdot", + "kind": "negative", + "descriptor": { + "handle_identity": "../opaque/escape/../../volume", + "attempt_id": "attempt-001", + "lease_id": "lease-001" + } + }, + { + "case_id": "opaque-handle-windows-backslash", + "kind": "negative", + "descriptor": { + "handle_identity": "volume\\wave\\handle", + "attempt_id": "attempt-001", + "lease_id": "lease-001" + } + }, + { + "case_id": "opaque-handle-drive-colon", + "kind": "negative", + "descriptor": { + "handle_identity": "C:opaque-volume-waveform-001", + "attempt_id": "attempt-001", + "lease_id": "lease-001" + } + }, + { + "case_id": "opaque-handle-uri-file-scheme", + "kind": "negative", + "descriptor": { + "handle_identity": "file://waveform/handle", + "attempt_id": "attempt-001", + "lease_id": "lease-001" + } + } + ], + "cache_integrity_cases": [ + { + "case_id": "cache-corruption-mismatched-staged-hash", + "kind": "cache-corrupt-hash" + }, + { + "case_id": "cache-deletion-zero-length-staged-copy", + "kind": "cache-deleted" + }, + { + "case_id": "cache-deletion-requires-non-authority", + "kind": "cache-non-authority" + } + ], + "publication_atomicity_cases": [ + { + "case_id": "publication-atomicity-duplicate-attempt", + "kind": "duplicate" + }, + { + "case_id": "publication-atomicity-cross-volume-attempt-id", + "kind": "cross-volume" + } + ] +} diff --git a/workers/VideoLocalization.Worker/src/lib.rs b/workers/VideoLocalization.Worker/src/lib.rs index b0ee6a6..cddb34d 100644 --- a/workers/VideoLocalization.Worker/src/lib.rs +++ b/workers/VideoLocalization.Worker/src/lib.rs @@ -1,6 +1,7 @@ pub mod preflight; pub mod fingerprint; pub mod probe_adapter_contract; +pub mod waveform_contract; pub use preflight::{ source_ceiling_bytes, diff --git a/workers/VideoLocalization.Worker/src/waveform_contract.rs b/workers/VideoLocalization.Worker/src/waveform_contract.rs new file mode 100644 index 0000000..13049ee --- /dev/null +++ b/workers/VideoLocalization.Worker/src/waveform_contract.rs @@ -0,0 +1,1410 @@ +use serde::{Deserialize, Serialize}; +use sha2::{Digest, Sha256}; +use std::collections::HashMap; +use std::sync::{Mutex, OnceLock}; + +pub const OPERATION_ID: &str = "submark.video-localization.waveform.derive"; +pub const OPERATION_VERSION: &str = "0.1.0-p00"; +pub const IMPLEMENTATION_ID: &str = "VID-IMPL-P00-003A"; +pub const IMPLEMENTATION_PROFILE_ID: &str = "VID-WAVEFORM-OPERATION-PROFILE-P00-003A"; +pub const ERROR_REF_NAMESPACE: &str = "video.waveform"; +pub const ERROR_REF_VERSION: &str = "1.0.0-p00"; + +pub const CACHE_KEY_SCHEMA_ID: &str = "sui.cache-key.cbor-sha256.v1"; +pub const CACHE_KEY_PREFIX: &[u8] = b"SUI-CACHE-KEY-V1\0"; + +pub const BULK_DESCRIPTOR_PROFILE: &str = "VID-WAVEFORM-BULK-DESCRIPTOR-V1"; +pub const BULK_DESCRIPTOR_PREFIX: &[u8] = b"VID-WAVEFORM-BULK-DESCRIPTOR-V1\0"; + +pub const OPERATION_SCHEMA_ID: &str = "VID-IMPL-P00-003A-WAVEFORM-INPUT"; +pub const PARAMETER_SCHEMA_ID: &str = "VID-IMPL-P00-003A-WAVEFORM-PARAMETER"; +pub const OUTPUT_SCHEMA_ID: &str = "VID-IMPL-P00-003A-WAVEFORM-ARTIFACT"; +pub const ERROR_SCHEMA_ID: &str = "VID-IMPL-P00-003A-WAVEFORM-STRUCTURED-ERROR"; +pub const RESOURCE_SCHEMA_ID: &str = "VID-IMPL-P00-003A-WAVEFORM-RESOURCE"; +pub const POLICY_SCHEMA_ID: &str = "VID-IMPL-P00-003A-WAVEFORM-POLICY"; +pub const BULK_DESCRIPTOR_SCHEMA_ID: &str = "VID-IMPL-P00-003A-WAVEFORM-BULK-DESCRIPTOR"; +pub const CONTROL_SCHEMA_ID: &str = "VID-IMPL-P00-003A-WAVEFORM-CONTROL"; +pub const WORKER_HELLO_SCHEMA_ID: &str = "VID-IMPL-P00-003A-WAVEFORM-WORKER-HELLO"; +pub const OPERATION_PROFILE_SCHEMA_ID: &str = "VID-IMPL-P00-003A-WAVEFORM-OPERATION-PROFILE"; + +const WAVEFORM_MAX_BULK_PAYLOAD_BYTES: u64 = 536_870_912; +const VID_WAVEFORM_DEADLINE_EXCEEDED_CODE: &str = "VID-WAVEFORM-DEADLINE-EXCEEDED"; + +#[derive(Debug, Clone)] +pub struct WaveformRetryProfile { + pub max_total_attempts: u64, + pub base_wait_millis: u64, + pub max_wait_millis: u64, + pub backoff: String, + pub cumulative_wall_seconds: u64, + pub cumulative_cpu_seconds: u64, + pub cumulative_ram_bytes: u64, + pub cumulative_staging_bytes: u64, + pub cost_ceiling: u64, + pub applicable_codes: Vec, +} + +#[derive(Debug, Clone)] +pub struct WaveformRetryUsage { + pub attempts: u64, + pub wall_seconds: u64, + pub cpu_seconds: u64, + pub ram_bytes: u64, + pub staging_bytes: u64, + pub cost: u64, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct WaveformRetryDecision { + pub next_attempt: u64, + pub wait_millis: u64, +} + +impl WaveformRetryProfile { + pub fn validate_cumulative_usage(&self, usage: &WaveformRetryUsage) -> Result<(), String> { + if usage.wall_seconds > self.cumulative_wall_seconds { + return Err("cumulative wall-time would exceed profile ceiling".to_string()); + } + if usage.cpu_seconds > self.cumulative_cpu_seconds { + return Err("cumulative cpu-time would exceed profile ceiling".to_string()); + } + if usage.ram_bytes > self.cumulative_ram_bytes { + return Err("cumulative resident-memory footprint would exceed profile ceiling".to_string()); + } + if usage.staging_bytes > self.cumulative_staging_bytes { + return Err("cumulative staging usage would exceed profile ceiling".to_string()); + } + if usage.cost > self.cost_ceiling { + return Err("cumulative cost would exceed profile ceiling".to_string()); + } + Ok(()) + } + + pub fn evaluate_retry_decision( + &self, + status_code: &str, + usage: &WaveformRetryUsage, + ) -> Result { + if !self.applicable_codes.iter().any(|code| code == status_code) { + return Err("status is not retry-eligible in profile".to_string()); + } + if usage.attempts >= self.max_total_attempts { + return Err("retry attempt ceiling reached".to_string()); + } + self.validate_cumulative_usage(usage)?; + + let base_wait = match self.backoff.as_str() { + "fixed" => self.base_wait_millis, + _ => self.base_wait_millis, + }; + let wait_millis = base_wait.min(self.max_wait_millis); + if wait_millis == 0 { + return Err("retry wait must be non-zero".to_string()); + } + + Ok(WaveformRetryDecision { + next_attempt: usage.attempts + 1, + wait_millis, + }) + } +} + +#[derive(Debug, Clone)] +pub struct WaveformPublicationLease { + pub lease_id: String, + pub lease_epoch: u64, + pub minimum_acceptable_lease_epoch: u64, + pub expected_fence_token: String, + pub observed_fence_token: String, + pub staged_copy_hash: String, + pub staged_copy_length: u64, + pub cache_authority: bool, +} + +#[derive(Debug, Clone)] +pub struct WaveformPublicationAttempt { + pub attempt_id: String, + pub lease: WaveformPublicationLease, + pub descriptor: WaveformBulkDescriptor, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct WaveformPublicationCommitReceipt { + journal_identity: String, +} + +impl WaveformPublicationCommitReceipt { + pub fn journal_identity(&self) -> &str { + &self.journal_identity + } +} + +#[derive(Debug, Clone)] +struct PublicationCommitJournalEntry { + operation_id: String, + operation_version: String, + implementation_id: String, + implementation_profile_id: String, + attempt_id: String, + lease_id: String, + lease_epoch: u64, + minimum_acceptable_lease_epoch: u64, + expected_fence_token: String, + observed_fence_token: String, + source_publication_fence: String, + descriptor_digest: String, + staged_copy_hash: String, + staged_copy_length: u64, + payload_digest: String, + whole_object_hash: String, + journal_identity: String, +} + +static PUBLICATION_COMMIT_JOURNAL: OnceLock>> = + OnceLock::new(); + +fn publication_commit_journal() -> &'static Mutex> { + PUBLICATION_COMMIT_JOURNAL.get_or_init(|| Mutex::new(HashMap::new())) +} + +fn publication_journal_identity( + attempt: &WaveformPublicationAttempt, + payload_digest: &str, + descriptor_digest: &str, + whole_object_hash: &str, +) -> String { + let bytes = cbor_text_map(vec![ + ("attempt_id", cbor_text(&attempt.attempt_id)), + ("attempt_descriptor", cbor_text(&attempt.descriptor.attempt_id)), + ("attempt_lease_id", cbor_text(&attempt.lease.lease_id)), + ("attempt_lease_epoch", cbor_uint(attempt.lease.lease_epoch)), + ( + "operation_id", + cbor_text(crate::waveform_contract::OPERATION_ID), + ), + ("operation_version", cbor_text(crate::waveform_contract::OPERATION_VERSION)), + ( + "payload_digest", + cbor_text(&payload_digest.to_lowercase()), + ), + ("descriptor_digest", cbor_text(descriptor_digest)), + ("descriptor_source_fence", cbor_text(&attempt.descriptor.source_publication_fence)), + ("expected_fence_token", cbor_text(&attempt.lease.expected_fence_token)), + ("implementation_id", cbor_text(crate::waveform_contract::IMPLEMENTATION_ID)), + ( + "implementation_profile_id", + cbor_text(crate::waveform_contract::IMPLEMENTATION_PROFILE_ID), + ), + ("journal_identity_domain", cbor_text("VID-WAVEFORM-COMMIT-JOURNAL")), + ( + "minimum_acceptable_lease_epoch", + cbor_uint(attempt.lease.minimum_acceptable_lease_epoch), + ), + ( + "observed_fence_token", + cbor_text(&attempt.lease.observed_fence_token), + ), + ("staged_copy_hash", cbor_text(&attempt.lease.staged_copy_hash)), + ("staged_copy_length", cbor_uint(attempt.lease.staged_copy_length)), + ("whole_object_hash", cbor_text(whole_object_hash)), + ]); + let mut hasher = Sha256::new(); + hasher.update(b"VID-WAVEFORM-JOURNAL-IDENTITY-V1\0"); + hasher.update(bytes); + digest_to_hex(hasher.finalize().as_slice()) +} + +fn validate_commit_journal_state( + identity: &str, +) -> Result { + if !is_hex64(identity) { + return Err("commit journal identity must be a 64-hex receipt id".to_string()); + } + + let journal = publication_commit_journal() + .lock() + .unwrap_or_else(|error| error.into_inner()); + let entry = journal + .get(identity) + .ok_or_else(|| "commit journal entry is not registered".to_string())?; + + let sample_attempt = WaveformPublicationAttempt { + attempt_id: entry.attempt_id.clone(), + lease: WaveformPublicationLease { + lease_id: entry.lease_id.clone(), + lease_epoch: entry.lease_epoch, + minimum_acceptable_lease_epoch: entry.minimum_acceptable_lease_epoch, + expected_fence_token: entry.expected_fence_token.clone(), + observed_fence_token: entry.observed_fence_token.clone(), + staged_copy_hash: entry.staged_copy_hash.clone(), + staged_copy_length: entry.staged_copy_length, + cache_authority: false, + }, + descriptor: WaveformBulkDescriptor { + version: BULK_DESCRIPTOR_PROFILE.to_string(), + mode: "read-only".to_string(), + handle_identity: String::new(), + attempt_id: entry.attempt_id.clone(), + lease_id: entry.lease_id.clone(), + cancel_scope: String::new(), + expiry: String::new(), + integrity: WaveformOutputContractDigest { + algorithm: "sha-256".to_string(), + value: entry.payload_digest.clone(), + }, + chunk_hashes_omitted: true, + length: entry.staged_copy_length, + payload_schema: OUTPUT_SCHEMA_ID.to_string(), + source_publication_fence: entry.source_publication_fence.clone(), + representation: WaveformBulkRepresentation { + peak: String::new(), + time: String::new(), + channel: String::new(), + downmix: String::new(), + resampling: String::new(), + source_timeline: String::new(), + sample_range: String::new(), + }, + descriptor_hash: Some(entry.descriptor_digest.clone()), + }, + }; + + let expected_identity = { + let mut attempt = sample_attempt; + attempt.lease.staged_copy_hash = entry.staged_copy_hash.to_lowercase(); + publication_journal_identity( + &attempt, + &entry.payload_digest, + &entry.descriptor_digest, + &entry.whole_object_hash, + ) + }; + + if expected_identity.to_lowercase() != entry.journal_identity.to_lowercase() { + return Err("commit journal state mismatch".to_string()); + } + if entry.journal_identity.to_lowercase() != identity.to_lowercase() { + return Err("commit journal identity mismatch".to_string()); + } + + Ok(WaveformPublicationCommitReceipt { + journal_identity: identity.to_string(), + }) +} + +pub fn revoke_publication_commit( + receipt: &WaveformPublicationCommitReceipt, +) -> bool { + let mut journal = publication_commit_journal() + .lock() + .unwrap_or_else(|error| error.into_inner()); + journal.remove(&receipt.journal_identity).is_some() +} + +#[derive(Debug, Clone)] +enum PublicationLifecycleProgress { + StagedValidated(WaveformBulkIntegrityReport), + StagedValidatedCommitted(WaveformPublicationCommitReceipt), +} + +#[derive(Debug, Clone)] +pub struct WaveformBulkIntegrityReport { + pub payload_digest: String, + pub descriptor_preimage: Vec, + pub descriptor_digest: String, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum WaveformTerminalState { + Succeeded(WaveformPublicationCommitReceipt), + Terminal(String), +} + +pub fn sha256_hex_of_bytes(data: &[u8]) -> String { + let mut hasher = Sha256::new(); + hasher.update(data); + hasher + .finalize() + .iter() + .map(|byte| format!("{byte:02x}")) + .collect() +} + +pub fn reconcile_terminal_state( + disposition_code: Option<&str>, + admitted_deadline_millis: Option, + current_time_millis: Option, + commit_journal_identity: Option<&str>, +) -> Result { + let deadline_exceeded = match (admitted_deadline_millis, current_time_millis) { + (Some(deadline_millis), Some(now_millis)) => now_millis >= deadline_millis, + (Some(_), None) => return Err("current time required when admitted deadline is present".to_string()), + _ => false, + }; + + let Some(code) = disposition_code else { + if deadline_exceeded { + return Err("cannot map to success after expired deadline".to_string()); + } + let Some(receipt_identity) = commit_journal_identity else { + return Err("Succeeded requires an authoritative commit journal identity".to_string()); + }; + let authoritative_receipt = validate_commit_journal_state(receipt_identity)?; + return Ok(WaveformTerminalState::Succeeded(authoritative_receipt)); + }; + + if deadline_exceeded && code != VID_WAVEFORM_DEADLINE_EXCEEDED_CODE { + return Err("TimedOut must be terminal only on deadline code".to_string()); + } + if code == VID_WAVEFORM_DEADLINE_EXCEEDED_CODE && !deadline_exceeded { + return Err("deadline code requires expired admitted deadline".to_string()); + } + + let mapping = state_mapping_for_code(code) + .ok_or_else(|| "unknown disposition code".to_string())?; + + Ok(WaveformTerminalState::Terminal(mapping.shared_terminal_state.to_string())) +} + +pub fn validate_bulk_payload_and_descriptor_linkage( + payload: &[u8], + descriptor: &WaveformBulkDescriptor, +) -> Result { + if descriptor.length != payload.len() as u64 { + return Err("payload length mismatch".to_string()); + } + if descriptor.integrity.algorithm.to_lowercase() != "sha-256" { + return Err("integrity.algorithm must be sha-256".to_string()); + } + + let payload_digest = sha256_hex_of_bytes(payload); + if payload_digest != descriptor.integrity.value.to_lowercase() { + return Err("payload integrity hash mismatch".to_string()); + } + + let descriptor_preimage = bulk_descriptor_preimage(descriptor)?; + let descriptor_digest = { + let mut hasher = Sha256::new(); + hasher.update(BULK_DESCRIPTOR_PREFIX); + hasher.update(&descriptor_preimage); + digest_to_hex(hasher.finalize().as_slice()) + }; + + if descriptor.descriptor_hash.is_none() { + return Err("descriptor_hash is required".to_string()); + } + if descriptor_digest.to_lowercase() != descriptor + .descriptor_hash + .as_ref() + .ok_or_else(|| "descriptor hash required".to_string())? + .to_lowercase() + { + return Err("descriptor hash mismatch".to_string()); + } + + Ok(WaveformBulkIntegrityReport { + payload_digest, + descriptor_preimage, + descriptor_digest, + }) +} + +pub fn publication_whole_object_hash( + attempt: &WaveformPublicationAttempt, + payload_digest: &str, +) -> Result { + let descriptor_digest = bulk_descriptor_digest(&attempt.descriptor)?; + + let bytes = cbor_text_map(vec![ + ("attempt_id", cbor_text(&attempt.attempt_id)), + ("descriptor_digest", cbor_text(&descriptor_digest)), + ("lease_id", cbor_text(&attempt.lease.lease_id)), + ("lease_epoch", cbor_uint(attempt.lease.lease_epoch)), + ("payload_digest", cbor_text(payload_digest)), + ("staged_copy_length", cbor_uint(attempt.lease.staged_copy_length)), + ("staged_copy_hash", cbor_text(&attempt.lease.staged_copy_hash)), + ( + "minimum_acceptable_lease_epoch", + cbor_uint(attempt.lease.minimum_acceptable_lease_epoch), + ), + ("expected_fence_token", cbor_text(&attempt.lease.expected_fence_token)), + ("observed_fence_token", cbor_text(&attempt.lease.observed_fence_token)), + ("descriptor_source_fence", cbor_text(&attempt.descriptor.source_publication_fence)), + ("descriptor_lease_id", cbor_text(&attempt.descriptor.lease_id)), + ("descriptor_attempt_id", cbor_text(&attempt.descriptor.attempt_id)), + ]); + let mut hasher = Sha256::new(); + hasher.update(bytes); + Ok(digest_to_hex(hasher.finalize().as_slice())) +} + +pub fn validate_publication_lifecycle( + attempt: &WaveformPublicationAttempt, + payload: &[u8], + expected_whole_object_hash: &str, + ) -> Result { + validate_opaque_handle_identity(&attempt.descriptor.handle_identity, "publication descriptor")?; + if attempt.lease.cache_authority { + return Err("cache authority cannot satisfy publication lineage".to_string()); + } + + let report = validate_bulk_payload_and_descriptor_linkage(payload, &attempt.descriptor)?; + if !is_hex64(&attempt.lease.staged_copy_hash) { + return Err("staged copy hash must be 64-hex".to_string()); + } + if report.payload_digest != attempt.lease.staged_copy_hash.to_lowercase() { + return Err("payload digest mismatch staged copy hash".to_string()); + } + + if attempt.attempt_id != attempt.descriptor.attempt_id { + return Err("attempt_id mismatch between attempt and descriptor".to_string()); + } + if attempt.lease.lease_id != attempt.descriptor.lease_id { + return Err("lease id mismatch between attempt and descriptor".to_string()); + } + if attempt.lease.staged_copy_length != attempt.descriptor.length { + return Err("staging length mismatch descriptor length".to_string()); + } + if attempt.lease.lease_epoch < attempt.lease.minimum_acceptable_lease_epoch { + return Err("lease is stale".to_string()); + } + if attempt.descriptor.source_publication_fence != attempt.lease.expected_fence_token { + return Err("descriptor source publication fence mismatch".to_string()); + } + if attempt.lease.expected_fence_token != attempt.lease.observed_fence_token { + return Err("fence token mismatch".to_string()); + } + + let mut lifecycle = PublicationLifecycleProgress::StagedValidated(report); + lifecycle = match &lifecycle { + PublicationLifecycleProgress::StagedValidated(staged_report) => { + let actual_whole_object_hash = publication_whole_object_hash(attempt, &staged_report.payload_digest)?; + if actual_whole_object_hash.to_lowercase() != expected_whole_object_hash.to_lowercase() { + return Err("whole object hash mismatch".to_string()); + } + let descriptor_digest = bulk_descriptor_digest(&attempt.descriptor)?; + let journal_identity = publication_journal_identity( + attempt, + &staged_report.payload_digest, + &descriptor_digest, + &actual_whole_object_hash, + ); + let mut journal = publication_commit_journal() + .lock() + .unwrap_or_else(|error| error.into_inner()); + if journal.contains_key(&journal_identity) { + return Err("publication lineage already committed".to_string()); + } + if journal.values().any(|entry| entry.attempt_id == attempt.attempt_id) { + return Err("publication attempt reuse is not allowed".to_string()); + } + let entry = PublicationCommitJournalEntry { + operation_id: OPERATION_ID.to_string(), + operation_version: OPERATION_VERSION.to_string(), + implementation_id: IMPLEMENTATION_ID.to_string(), + implementation_profile_id: IMPLEMENTATION_PROFILE_ID.to_string(), + attempt_id: attempt.attempt_id.clone(), + lease_id: attempt.lease.lease_id.clone(), + lease_epoch: attempt.lease.lease_epoch, + minimum_acceptable_lease_epoch: attempt.lease.minimum_acceptable_lease_epoch, + expected_fence_token: attempt.lease.expected_fence_token.clone(), + observed_fence_token: attempt.lease.observed_fence_token.clone(), + source_publication_fence: attempt.descriptor.source_publication_fence.clone(), + descriptor_digest, + staged_copy_hash: attempt.lease.staged_copy_hash.to_lowercase(), + staged_copy_length: attempt.lease.staged_copy_length, + payload_digest: staged_report.payload_digest.to_lowercase(), + whole_object_hash: actual_whole_object_hash.clone(), + journal_identity: journal_identity.clone(), + }; + journal.insert(journal_identity.clone(), entry); + + let receipt = WaveformPublicationCommitReceipt { + journal_identity, + }; + + PublicationLifecycleProgress::StagedValidatedCommitted(receipt) + } + _ => return Err("invalid publication lifecycle transition".to_string()), + }; + + match lifecycle { + PublicationLifecycleProgress::StagedValidatedCommitted(receipt) => Ok(receipt), + _ => Err("invalid publication lifecycle transition".to_string()), + } +} + +#[derive(Debug, Clone)] +pub struct WaveformStateMapping { + pub video_disposition: &'static str, + pub shared_terminal_state: &'static str, + pub error_category: &'static str, + pub retry_class: &'static str, + pub operation_stage: &'static str, + pub safe_recovery: &'static str, + pub identity_refs: &'static [&'static str], +} + +pub const VID_WAVEFORM_STATE_MAPPINGS: &[WaveformStateMapping] = &[ + WaveformStateMapping { + video_disposition: "VID-WAVEFORM-CANCELLED", + shared_terminal_state: "Cancelled", + error_category: "Cancelled", + retry_class: "manual", + operation_stage: "execution", + safe_recovery: "retry explicitly in user-directed workflow", + identity_refs: &["job", "attempt", "dispatch", "worker", "publication"], + }, + WaveformStateMapping { + video_disposition: "VID-WAVEFORM-DEADLINE-EXCEEDED", + shared_terminal_state: "TimedOut", + error_category: "ResourceLimit", + retry_class: "non-retryable", + operation_stage: "execution", + safe_recovery: "use a reviewed lower-cost profile", + identity_refs: &["job", "attempt", "dispatch", "worker", "publication"], + }, + WaveformStateMapping { + video_disposition: "VID-WAVEFORM-RESOURCE-LIMIT", + shared_terminal_state: "Failed", + error_category: "ResourceLimit", + retry_class: "non-retryable", + operation_stage: "resource-management", + safe_recovery: "select an approved lower resource profile", + identity_refs: &["job", "attempt", "dispatch", "worker", "publication"], + }, + WaveformStateMapping { + video_disposition: "VID-WAVEFORM-LEASE-EXPIRED", + shared_terminal_state: "Failed", + error_category: "ExpiredLease", + retry_class: "non-retryable", + operation_stage: "publication", + safe_recovery: "renew lease and replay source staging", + identity_refs: &["job", "attempt", "dispatch", "worker", "publication"], + }, + WaveformStateMapping { + video_disposition: "VID-WAVEFORM-FENCE-MISMATCH", + shared_terminal_state: "Failed", + error_category: "IdentityMismatch", + retry_class: "non-retryable", + operation_stage: "publication", + safe_recovery: "repair publication/lease binding context", + identity_refs: &["job", "attempt", "dispatch", "worker", "publication"], + }, + WaveformStateMapping { + video_disposition: "VID-WAVEFORM-CACHE-STALE", + shared_terminal_state: "Failed", + error_category: "CacheStale", + retry_class: "manual", + operation_stage: "cache-lookup", + safe_recovery: "force recompute through a new attempt", + identity_refs: &["job", "attempt", "dispatch", "worker", "publication"], + }, + WaveformStateMapping { + video_disposition: "VID-WAVEFORM-CACHE-CORRUPT", + shared_terminal_state: "Failed", + error_category: "DataCorruption", + retry_class: "manual", + operation_stage: "validation", + safe_recovery: "recompute cache line with new attempt", + identity_refs: &["job", "attempt", "dispatch", "worker", "publication"], + }, + WaveformStateMapping { + video_disposition: "VID-WAVEFORM-INPUT-SCHEMA-INVALID", + shared_terminal_state: "Failed", + error_category: "MalformedInput", + retry_class: "non-retryable", + operation_stage: "validation", + safe_recovery: "repair input schema or retry with corrected admission data", + identity_refs: &["job", "attempt", "dispatch", "worker", "publication"], + }, + WaveformStateMapping { + video_disposition: "VID-WAVEFORM-OUTPUT-SCHEMA-INVALID", + shared_terminal_state: "Failed", + error_category: "MalformedOutput", + retry_class: "non-retryable", + operation_stage: "validation", + safe_recovery: "repair validator or runtime adapter mapping", + identity_refs: &["job", "attempt", "dispatch", "worker", "publication"], + }, + WaveformStateMapping { + video_disposition: "VID-WAVEFORM-INTEGRITY-MISMATCH", + shared_terminal_state: "Failed", + error_category: "IntegrityMismatch", + retry_class: "manual", + operation_stage: "validation", + safe_recovery: "rebuild artifact from the same source", + identity_refs: &["job", "attempt", "dispatch", "worker", "publication"], + }, + WaveformStateMapping { + video_disposition: "VID-WAVEFORM-MALFORMED-DESCRIPTOR", + shared_terminal_state: "Failed", + error_category: "MalformedOutput", + retry_class: "non-retryable", + operation_stage: "validation", + safe_recovery: "repair descriptor construction and retry", + identity_refs: &["job", "attempt", "dispatch", "worker", "publication"], + }, + WaveformStateMapping { + video_disposition: "VID-WAVEFORM-PROTOCOL-INCOMPATIBLE", + shared_terminal_state: "Failed", + error_category: "ProtocolMismatch", + retry_class: "non-retryable", + operation_stage: "negotiation", + safe_recovery: "select a compatible operation protocol", + identity_refs: &["job", "attempt", "dispatch", "worker", "publication"], + }, + WaveformStateMapping { + video_disposition: "VID-WAVEFORM-HANDLE-INCOMPATIBLE", + shared_terminal_state: "Failed", + error_category: "HandleMismatch", + retry_class: "non-retryable", + operation_stage: "validation", + safe_recovery: "repair handle/lease lineage", + identity_refs: &["job", "attempt", "dispatch", "worker", "publication"], + }, + WaveformStateMapping { + video_disposition: "VID-WAVEFORM-PUBLICATION-FAILED", + shared_terminal_state: "Failed", + error_category: "PublicationFailure", + retry_class: "manual", + operation_stage: "publication", + safe_recovery: "repair publication path and retry with same lineage", + identity_refs: &["job", "attempt", "dispatch", "worker", "publication"], + }, + WaveformStateMapping { + video_disposition: "VID-WAVEFORM-STORAGE-PERMANENT", + shared_terminal_state: "Failed", + error_category: "StorageFault", + retry_class: "non-retryable", + operation_stage: "storage", + safe_recovery: "repair storage and verify permissions", + identity_refs: &["job", "attempt", "dispatch", "worker", "publication"], + }, + WaveformStateMapping { + video_disposition: "VID-WAVEFORM-JOURNAL-INVALID", + shared_terminal_state: "Failed", + error_category: "MalformedOutput", + retry_class: "manual", + operation_stage: "reconciliation", + safe_recovery: "repair journal or operator review", + identity_refs: &["job", "attempt", "dispatch", "worker", "publication"], + }, + WaveformStateMapping { + video_disposition: "VID-WAVEFORM-PARTIAL-OUTPUT", + shared_terminal_state: "Failed", + error_category: "MalformedOutput", + retry_class: "non-retryable", + operation_stage: "validation", + safe_recovery: "recompute entire output only", + identity_refs: &["job", "attempt", "dispatch", "worker", "publication"], + }, + WaveformStateMapping { + video_disposition: "VID-WAVEFORM-METADATA-INVALID", + shared_terminal_state: "Failed", + error_category: "MalformedInput", + retry_class: "non-retryable", + operation_stage: "validation", + safe_recovery: "repair metadata bindings and retry", + identity_refs: &["job", "attempt", "dispatch", "worker", "publication"], + }, + WaveformStateMapping { + video_disposition: "VID-WAVEFORM-IDENTITY-MISMATCH", + shared_terminal_state: "Failed", + error_category: "IdentityMismatch", + retry_class: "non-retryable", + operation_stage: "admission", + safe_recovery: "repair identity bindings and retry", + identity_refs: &["job", "attempt", "dispatch", "worker", "publication"], + }, + WaveformStateMapping { + video_disposition: "VID-WAVEFORM-POLICY-DENIED", + shared_terminal_state: "Failed", + error_category: "PolicyDenied", + retry_class: "manual", + operation_stage: "policy", + safe_recovery: "repair policy binding and retry", + identity_refs: &["job", "attempt", "dispatch", "worker", "publication"], + }, + WaveformStateMapping { + video_disposition: "VID-WAVEFORM-WORKER-TRANSIENT", + shared_terminal_state: "RetryWaiting", + error_category: "TransientWorker", + retry_class: "transient", + operation_stage: "execution", + safe_recovery: "retry after bounded delay", + identity_refs: &["job", "attempt", "dispatch", "worker", "publication"], + }, + WaveformStateMapping { + video_disposition: "VID-WAVEFORM-STORAGE-TRANSIENT", + shared_terminal_state: "RetryWaiting", + error_category: "TransientStorage", + retry_class: "transient", + operation_stage: "storage", + safe_recovery: "retry after bounded delay", + identity_refs: &["job", "attempt", "dispatch", "worker", "publication"], + }, + WaveformStateMapping { + video_disposition: "VID-WAVEFORM-WORKER-PERMANENT", + shared_terminal_state: "Failed", + error_category: "WorkerPermanent", + retry_class: "non-retryable", + operation_stage: "execution", + safe_recovery: "operator review and repair implementation", + identity_refs: &["job", "attempt", "dispatch", "worker", "publication"], + }, + WaveformStateMapping { + video_disposition: "VID-WAVEFORM-REVIEW", + shared_terminal_state: "Failed", + error_category: "ManualReview", + retry_class: "manual", + operation_stage: "review", + safe_recovery: "operator manual review", + identity_refs: &["job", "attempt", "dispatch", "worker", "publication"], + }, +]; + +pub fn state_mapping_for_code(code: &str) -> Option<&'static WaveformStateMapping> { + VID_WAVEFORM_STATE_MAPPINGS.iter().find(|entry| entry.video_disposition == code) +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct WaveformOutputContractDigest { + pub algorithm: String, + pub value: String, +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct WaveformCacheKeyProfile { + pub cache_key_schema: String, + pub operation: WaveformCacheKeyProfileIdentity, + pub implementation: WaveformCacheKeyProfileIdentity, + pub inputs: Vec, + pub parameters: WaveformCacheParameters, + pub dependencies: WaveformCacheDependencies, + pub output_contract: WaveformCacheOutputContract, + pub seed: String, + pub environment_equivalence: WaveformEnvironmentEquivalence, + pub resource: WaveformCacheResource, + pub policy: WaveformCachePolicy, + pub representation: WaveformCacheRepresentation, +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct WaveformCacheKeyProfileIdentity { + pub id: String, + pub version: String, +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct WaveformCacheInputPort { + pub order: u64, + #[serde(rename = "type")] + pub kind: String, + pub schema: String, + pub content: String, + pub revision: String, + pub sample_range: String, +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct WaveformCacheParameters { + pub cache_key_schema: String, + pub cache_key_seed: String, + pub environment_equivalence: WaveformEnvironmentEquivalence, + pub resource_profile_id: String, + pub policy_profile_id: String, + pub retry_profile_id: String, + pub representation: WaveformCacheRepresentation, +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct WaveformCacheDependencies { + pub resource_profile: String, + pub policy_profile: String, + pub retry_profile: String, + pub operation_profile: String, + pub cache_key_schema: String, +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct WaveformCacheOutputContract { + pub artifact_id: String, + pub artifact_version: String, + pub output_schema_id: String, +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct WaveformEnvironmentEquivalence { + pub os_family: String, + pub arch_family: String, + pub worker_family: String, + pub containerization: bool, + pub capability_bundle: String, +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct WaveformCacheResource { + pub resource_profile_id: String, +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct WaveformCachePolicy { + pub network: String, + pub watchdog_required: bool, + pub job_object_required: bool, + pub media_parse: bool, +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct WaveformCacheRepresentation { + pub peak: String, + pub time: String, + pub channel: String, + pub downmix: String, + pub resampling: String, + pub stability: String, +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct WaveformBulkDescriptor { + pub version: String, + pub mode: String, + pub handle_identity: String, + pub attempt_id: String, + pub lease_id: String, + pub cancel_scope: String, + pub expiry: String, + pub integrity: WaveformOutputContractDigest, + pub chunk_hashes_omitted: bool, + pub length: u64, + pub payload_schema: String, + pub source_publication_fence: String, + pub representation: WaveformBulkRepresentation, + pub descriptor_hash: Option, +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct WaveformBulkRepresentation { + pub peak: String, + pub time: String, + pub channel: String, + pub downmix: String, + pub resampling: String, + pub source_timeline: String, + pub sample_range: String, +} + +pub fn cache_key_digest(profile: &WaveformCacheKeyProfile) -> Result { + let preimage = cache_key_preimage(profile)?; + let mut hasher = Sha256::new(); + hasher.update(CACHE_KEY_PREFIX); + hasher.update(preimage); + Ok(digest_to_hex(hasher.finalize().as_slice())) +} + +pub fn cache_key_preimage(profile: &WaveformCacheKeyProfile) -> Result, String> { + validate_cache_key_profile(profile)?; + + let mut inputs = profile.inputs.clone(); + inputs.sort_by(|left, right| { + ( + left.order, + left.schema.as_str(), + left.kind.as_str(), + left.content.as_str(), + left.revision.as_str(), + left.sample_range.as_str(), + ) + .cmp(&( + right.order, + right.schema.as_str(), + right.kind.as_str(), + right.content.as_str(), + right.revision.as_str(), + right.sample_range.as_str(), + )) + }); + + let encoded_inputs = inputs + .iter() + .map(encode_cache_input_port) + .collect::>(); + let output_contract = cbor_text_map(vec![ + ("artifact_id", cbor_text(&profile.output_contract.artifact_id)), + ("artifact_version", cbor_text(&profile.output_contract.artifact_version)), + ("output_schema_id", cbor_text(&profile.output_contract.output_schema_id)), + ]); + let operation = cbor_text_map(vec![ + ("id", cbor_text(&profile.operation.id)), + ("version", cbor_text(&profile.operation.version)), + ]); + let implementation = cbor_text_map(vec![ + ("id", cbor_text(&profile.implementation.id)), + ("version", cbor_text(&profile.implementation.version)), + ]); + let parameters = cbor_text_map(vec![ + ("cache_key_schema", cbor_text(&profile.parameters.cache_key_schema)), + ("cache_key_seed", cbor_text(&profile.parameters.cache_key_seed)), + ( + "environment_equivalence", + cbor_text_map(vec![ + ("arch_family", cbor_text(&profile.parameters.environment_equivalence.arch_family)), + ("capability_bundle", cbor_text(&profile.parameters.environment_equivalence.capability_bundle)), + ("containerization", cbor_bool(profile.parameters.environment_equivalence.containerization)), + ("os_family", cbor_text(&profile.parameters.environment_equivalence.os_family)), + ("worker_family", cbor_text(&profile.parameters.environment_equivalence.worker_family)), + ]), + ), + ("policy_profile_id", cbor_text(&profile.parameters.policy_profile_id)), + ("representation", { + let rep = &profile.parameters.representation; + cbor_text_map(vec![ + ("channel", cbor_text(&rep.channel)), + ("downmix", cbor_text(&rep.downmix)), + ("peak", cbor_text(&rep.peak)), + ("resampling", cbor_text(&rep.resampling)), + ("stability", cbor_text(&rep.stability)), + ("time", cbor_text(&rep.time)), + ]) + }), + ("resource_profile_id", cbor_text(&profile.parameters.resource_profile_id)), + ("retry_profile_id", cbor_text(&profile.parameters.retry_profile_id)), + ]); + let dependencies = cbor_text_map(vec![ + ("cache_key_schema", cbor_text(&profile.dependencies.cache_key_schema)), + ("operation_profile", cbor_text(&profile.dependencies.operation_profile)), + ("policy_profile", cbor_text(&profile.dependencies.policy_profile)), + ("retry_profile", cbor_text(&profile.dependencies.retry_profile)), + ("resource_profile", cbor_text(&profile.dependencies.resource_profile)), + ]); + let environment_equivalence = cbor_text_map(vec![ + ("arch_family", cbor_text(&profile.environment_equivalence.arch_family)), + ("capability_bundle", cbor_text(&profile.environment_equivalence.capability_bundle)), + ("containerization", cbor_bool(profile.environment_equivalence.containerization)), + ("os_family", cbor_text(&profile.environment_equivalence.os_family)), + ("worker_family", cbor_text(&profile.environment_equivalence.worker_family)), + ]); + let resource = cbor_text_map(vec![( + "resource_profile_id", + cbor_text(&profile.resource.resource_profile_id), + )]); + let policy = cbor_text_map(vec![ + ("job_object_required", cbor_bool(profile.policy.job_object_required)), + ("media_parse", cbor_bool(profile.policy.media_parse)), + ("network", cbor_text(&profile.policy.network)), + ("watchdog_required", cbor_bool(profile.policy.watchdog_required)), + ]); + let representation = cbor_text_map(vec![ + ("channel", cbor_text(&profile.representation.channel)), + ("downmix", cbor_text(&profile.representation.downmix)), + ("peak", cbor_text(&profile.representation.peak)), + ("resampling", cbor_text(&profile.representation.resampling)), + ("stability", cbor_text(&profile.representation.stability)), + ("time", cbor_text(&profile.representation.time)), + ]); + + let encoded_inputs = cbor_array(encoded_inputs); + let preimage = cbor_text_map(vec![ + ("cache_key_schema", cbor_text(&profile.cache_key_schema)), + ("dependencies", dependencies), + ("environment_equivalence", environment_equivalence), + ("implementation", implementation), + ("inputs", encoded_inputs), + ("operation", operation), + ("output_contract", output_contract), + ("parameters", parameters), + ("policy", policy), + ("representation", representation), + ("resource", resource), + ("seed", cbor_text(&profile.seed)), + ]); + Ok(preimage) + +} + +pub fn bulk_descriptor_preimage(descriptor: &WaveformBulkDescriptor) -> Result, String> { + validate_bulk_descriptor_minimal(descriptor)?; + Ok(write_bulk_descriptor_bytes(descriptor, false)) +} + +pub fn bulk_descriptor_canonical_bytes(descriptor: &WaveformBulkDescriptor) -> Result, String> { + validate_bulk_descriptor_minimal(descriptor)?; + Ok(write_bulk_descriptor_bytes(descriptor, true)) +} + +pub fn bulk_descriptor_digest(descriptor: &WaveformBulkDescriptor) -> Result { + let preimage = bulk_descriptor_preimage(descriptor)?; + let mut hasher = Sha256::new(); + hasher.update(BULK_DESCRIPTOR_PREFIX); + hasher.update(&preimage); + Ok(digest_to_hex(hasher.finalize().as_slice())) +} + +#[doc(hidden)] +pub fn bulk_descriptor_digest_unchecked(descriptor: &WaveformBulkDescriptor) -> String { + let mut hasher = Sha256::new(); + hasher.update(BULK_DESCRIPTOR_PREFIX); + hasher.update(write_bulk_descriptor_bytes(descriptor, false)); + digest_to_hex(hasher.finalize().as_slice()) +} + +fn validate_bulk_descriptor_minimal(descriptor: &WaveformBulkDescriptor) -> Result<(), String> { + validate_opaque_handle_identity(&descriptor.handle_identity, "descriptor")?; + + if descriptor.version != BULK_DESCRIPTOR_PROFILE { + return Err("bulk descriptor version invalid".to_string()); + } + if descriptor.mode != "read-only" { + return Err("bulk descriptor mode must be read-only".to_string()); + } + if !descriptor.chunk_hashes_omitted { + return Err("chunk_hashes_omitted must be true".to_string()); + } + if descriptor.integrity.algorithm.to_lowercase() != "sha-256" { + return Err("integrity.algorithm must be sha-256".to_string()); + } + if !is_hex64(&descriptor.integrity.value) { + return Err("integrity.value must be a 64-hex SHA-256 digest".to_string()); + } + if descriptor.length > WAVEFORM_MAX_BULK_PAYLOAD_BYTES { + return Err("descriptor length exceeds maximum".to_string()); + } + for value in [ + &descriptor.version, + &descriptor.mode, + &descriptor.handle_identity, + &descriptor.attempt_id, + &descriptor.lease_id, + &descriptor.cancel_scope, + &descriptor.expiry, + &descriptor.payload_schema, + &descriptor.source_publication_fence, + &descriptor.representation.peak, + &descriptor.representation.time, + &descriptor.representation.channel, + &descriptor.representation.downmix, + &descriptor.representation.resampling, + &descriptor.representation.source_timeline, + &descriptor.representation.sample_range, + ] { + if value.trim().is_empty() { + return Err("descriptor identity fields must be explicit".to_string()); + } + } + Ok(()) +} + +fn validate_opaque_handle_identity(identity: &str, context: &str) -> Result<(), String> { + if identity.trim().is_empty() { + return Err(format!("{} handle identity must be non-empty", context)); + } + + if !identity.chars().all(|character| { + character.is_ascii_alphanumeric() + || character == '-' + || character == '_' + || character == '.' + }) { + return Err(format!( + "{context} handle identity must be an opaque, non-path token" + )); + } + + if identity.chars().any(|character| character.is_whitespace() || character.is_control()) { + return Err(format!( + "{context} handle identity must not contain whitespace or control characters" + )); + } + + if identity.contains("..") { + return Err(format!( + "{context} handle identity must not include traversal segments" + )); + } + + if identity.contains("://") || identity.starts_with("file:") { + return Err(format!("{context} handle identity must not use URI schemes")); + } + + let mut chars = identity.chars(); + if chars.next().is_some() { + let mut chars = identity.bytes(); + let first = chars.next().unwrap_or_default(); + if first.is_ascii_alphabetic() && chars.next() == Some(b':') { + return Err(format!("{context} handle identity must not use drive path syntax")); + } + } + + Ok(()) +} + +pub fn validate_bulk_descriptor(descriptor: &WaveformBulkDescriptor) -> Result<(), String> { + validate_bulk_descriptor_minimal(descriptor)?; + + let expected = bulk_descriptor_digest(descriptor)?; + let observed = descriptor + .descriptor_hash + .as_ref() + .ok_or_else(|| "descriptor_hash is required".to_string())?; + if !is_hex64(observed) { + return Err("descriptor_hash must be a 64-hex digest".to_string()); + } + if observed.to_lowercase() != expected.to_lowercase() { + return Err("descriptor_hash mismatch".to_string()); + } + Ok(()) +} + +fn write_bulk_descriptor_bytes(descriptor: &WaveformBulkDescriptor, include_hash: bool) -> Vec { + let integrity = cbor_text_map(vec![ + ("algorithm", cbor_text(&descriptor.integrity.algorithm)), + ("value", cbor_text(&descriptor.integrity.value)), + ]); + let representation = cbor_text_map(vec![ + ("channel", cbor_text(&descriptor.representation.channel)), + ("downmix", cbor_text(&descriptor.representation.downmix)), + ("peak", cbor_text(&descriptor.representation.peak)), + ("resampling", cbor_text(&descriptor.representation.resampling)), + ("sample_range", cbor_text(&descriptor.representation.sample_range)), + ("source_timeline", cbor_text(&descriptor.representation.source_timeline)), + ("time", cbor_text(&descriptor.representation.time)), + ]); + let entries = vec![ + (cbor_uint_key(0), cbor_text(&descriptor.version)), + (cbor_uint_key(1), cbor_text(&descriptor.mode)), + (cbor_uint_key(2), cbor_text(&descriptor.handle_identity)), + (cbor_uint_key(3), cbor_text(&descriptor.attempt_id)), + (cbor_uint_key(4), cbor_text(&descriptor.lease_id)), + (cbor_uint_key(5), cbor_text(&descriptor.cancel_scope)), + (cbor_uint_key(6), cbor_text(&descriptor.expiry)), + (cbor_uint_key(7), integrity), + (cbor_uint_key(8), cbor_bool(descriptor.chunk_hashes_omitted)), + (cbor_uint_key(9), cbor_uint(descriptor.length)), + (cbor_uint_key(10), cbor_text(&descriptor.payload_schema)), + (cbor_uint_key(11), cbor_text(&descriptor.source_publication_fence)), + (cbor_uint_key(12), representation), + ]; + + if include_hash { + let mut entries = entries; + entries.push(( + cbor_uint_key(13), + cbor_text(descriptor.descriptor_hash.as_deref().unwrap_or("")), + )); + cbor_canonical_map(entries) + } else { + cbor_canonical_map(entries) + } +} + +fn validate_cache_key_profile(profile: &WaveformCacheKeyProfile) -> Result<(), String> { + if profile.cache_key_schema != CACHE_KEY_SCHEMA_ID { + return Err("cache_key_schema must be the canonical cache-key schema".to_string()); + } + if profile.operation.id.trim().is_empty() || profile.operation.version.trim().is_empty() { + return Err("operation.id and operation.version must be explicit".to_string()); + } + if profile.implementation.id.trim().is_empty() || profile.implementation.version.trim().is_empty() { + return Err("implementation.id and implementation.version must be explicit".to_string()); + } + if profile.inputs.is_empty() { + return Err("at least one input port is required".to_string()); + } + if profile + .inputs + .iter() + .any(|input| input.order == u64::MAX) + { + return Err("invalid input order".to_string()); + } + if profile.inputs.iter().any(|input| input.kind.trim().is_empty() || input.schema.trim().is_empty() || input.content.trim().is_empty() || input.revision.trim().is_empty() || input.sample_range.trim().is_empty()) { + return Err("input port fields must be explicit".to_string()); + } + + for field in [ + &profile.parameters.cache_key_schema, + &profile.parameters.cache_key_seed, + &profile.parameters.resource_profile_id, + &profile.parameters.policy_profile_id, + &profile.parameters.retry_profile_id, + &profile.representation.peak, + &profile.representation.time, + &profile.representation.channel, + &profile.representation.downmix, + &profile.representation.resampling, + &profile.representation.stability, + &profile.output_contract.artifact_id, + &profile.output_contract.artifact_version, + &profile.output_contract.output_schema_id, + ] { + if field.trim().is_empty() { + return Err("cache key binding field must be explicit".to_string()); + } + } + if profile.seed.trim().is_empty() { + return Err("cache key seed must be explicit".to_string()); + } + if profile.parameters.cache_key_schema != CACHE_KEY_SCHEMA_ID { + return Err("parameters.cache_key_schema mismatch".to_string()); + } + if profile.dependencies.cache_key_schema != CACHE_KEY_SCHEMA_ID { + return Err("dependencies.cache_key_schema mismatch".to_string()); + } + if !profile.parameters.resource_profile_id.eq(&profile.dependencies.resource_profile) + || !profile.parameters.policy_profile_id.eq(&profile.dependencies.policy_profile) + || !profile.parameters.retry_profile_id.eq(&profile.dependencies.retry_profile) + || profile.dependencies.operation_profile.trim().is_empty() + { + return Err("cache profile dependency coupling mismatch".to_string()); + } + if profile.output_contract.artifact_version.is_empty() + || profile.output_contract.output_schema_id.is_empty() + { + return Err("output contract identity must be explicit".to_string()); + } + if !matches!(profile.policy.network.as_str(), "denied") { + return Err("network policy must be denied".to_string()); + } + if !profile.resource.resource_profile_id.as_str().is_empty() && profile.policy.media_parse { + return Err("media_parse must be false".to_string()); + } + Ok(()) +} + +fn is_hex64(value: &str) -> bool { + value.len() == 64 && value.chars().all(|v| v.is_ascii_hexdigit()) +} + +fn cbor_write_text(bytes: &mut Vec, value: &str) { + cbor_write_bytes(bytes, value.as_bytes(), 3); +} + +fn cbor_write_bool(bytes: &mut Vec, value: bool) { + bytes.push(if value { 0xf5 } else { 0xf4 }); +} + +fn cbor_write_map(bytes: &mut Vec, length: usize) { + cbor_write_length(bytes, 5, length as u64); +} + +fn cbor_write_array(bytes: &mut Vec, length: usize) { + cbor_write_length(bytes, 4, length as u64); +} + +fn cbor_write_length(bytes: &mut Vec, major: u8, length: u64) { + if length < 24 { + bytes.push((major << 5) | length as u8); + return; + } + if length < 256 { + bytes.push((major << 5) | 24); + bytes.push(length as u8); + return; + } + if length < 65536 { + bytes.push((major << 5) | 25); + bytes.push(((length >> 8) & 0xff) as u8); + bytes.push((length & 0xff) as u8); + return; + } + bytes.push((major << 5) | 26); + bytes.push(((length >> 24) & 0xff) as u8); + bytes.push(((length >> 16) & 0xff) as u8); + bytes.push(((length >> 8) & 0xff) as u8); + bytes.push((length & 0xff) as u8); +} + +fn cbor_write_uint(bytes: &mut Vec, value: u64) { + cbor_write_length(bytes, 0, value); +} + +fn cbor_write_bytes(bytes: &mut Vec, payload: &[u8], major: u8) { + cbor_write_length(bytes, major, payload.len() as u64); + bytes.extend_from_slice(payload); +} + +fn digest_to_hex(bytes: &[u8]) -> String { + bytes.iter().map(|value| format!("{value:02x}")).collect() +} + +fn cbor_text_map(entries: Vec<(&str, Vec)>) -> Vec { + let keyed = entries + .into_iter() + .map(|(key, value)| (cbor_text_key(key), value)) + .collect(); + cbor_canonical_map(keyed) +} + +#[cfg(test)] +pub fn test_cbor_text_map(entries: Vec<(&str, Vec)>) -> Vec { + cbor_text_map(entries) +} + +fn cbor_text_key(value: &str) -> Vec { + let mut bytes = Vec::new(); + cbor_write_text(&mut bytes, value); + bytes +} + +fn cbor_text(value: &str) -> Vec { + cbor_text_key(value) +} + +fn cbor_uint_key(value: u64) -> Vec { + let mut bytes = Vec::new(); + cbor_write_uint(&mut bytes, value); + bytes +} + +fn cbor_uint(value: u64) -> Vec { + let mut bytes = Vec::new(); + cbor_write_uint(&mut bytes, value); + bytes +} + +fn cbor_array(values: Vec>) -> Vec { + let mut bytes = Vec::new(); + cbor_write_array(&mut bytes, values.len()); + for value in values { + bytes.extend_from_slice(&value); + } + bytes +} + +fn cbor_bool(value: bool) -> Vec { + let mut bytes = Vec::new(); + cbor_write_bool(&mut bytes, value); + bytes +} + +fn cbor_map_uint(entries: Vec<(u64, Vec)>) -> Vec { + let keyed = entries + .into_iter() + .map(|(key, value)| (cbor_uint_key(key), value)) + .collect(); + cbor_canonical_map(keyed) +} + +fn cbor_canonical_map(entries: Vec<(Vec, Vec)>) -> Vec { + let mut entries = entries; + entries.sort_by(|left, right| left.0.cmp(&right.0)); + let mut bytes = Vec::new(); + cbor_write_map(&mut bytes, entries.len()); + for (key, value) in entries { + bytes.extend_from_slice(&key); + bytes.extend_from_slice(&value); + } + bytes +} + +fn encode_cache_input_port(port: &WaveformCacheInputPort) -> Vec { + cbor_text_map(vec![ + ("content", cbor_text(&port.content)), + ("order", cbor_uint(port.order)), + ("revision", cbor_text(&port.revision)), + ("sample_range", cbor_text(&port.sample_range)), + ("schema", cbor_text(&port.schema)), + ("type", cbor_text(&port.kind)), + ]) +} diff --git a/workers/VideoLocalization.Worker/tests/waveform_contract.rs b/workers/VideoLocalization.Worker/tests/waveform_contract.rs new file mode 100644 index 0000000..434f181 --- /dev/null +++ b/workers/VideoLocalization.Worker/tests/waveform_contract.rs @@ -0,0 +1,2055 @@ +use std::collections::{HashMap, HashSet}; +use std::fs; +use std::path::{Path, PathBuf}; +use std::sync::atomic::{AtomicU64, Ordering}; + +use serde::Deserialize; +use serde_json::{json, Value}; +use sha2::{Digest, Sha256}; + +use videolocalization_worker::waveform_contract as wc; + +const CONTROL_PROTOCOL_SHA: &str = "2539250e640517eccc9dccf5feebce6cf9ec89acc26cef9ee08edc9d914d9f02"; +const SCHEMA_BUNDLE_SHA: &str = "c01cc30752532e9abb5804d76883c890a58b267cf886cb01f1c25716be7310c9"; +const SCHEMA_BUNDLE_002B1_SHA: &str = "f78bf8a7af8616b913d03539eb66ace6bf670f80c685e791521e395396f3397f"; + +static TEST_PUBLICATION_SEQUENCE: AtomicU64 = AtomicU64::new(0); +const RECORD_CHECKSUMS: &[(&str, &str, &str, &str, &str)] = &[ + ( + "control-protocol", + "SUI-SPEC-003", + "1.0", + "Video Localization/contracts/VID-IMPL-P00-002B1/records/control-protocol.json", + CONTROL_PROTOCOL_SHA, + ), + ( + "operation-profile", + "VID-WAVEFORM-OPERATION-PROFILE-P00-003A", + "0.1.0-p00", + "Video Localization/contracts/VID-IMPL-P00-003A/records/operation-profile.json", + "2374d0730488c262148516051431b09acb0e2b06fe5ec901d5ffdb2739a889db", + ), + ( + "resource-profile", + "VID-WAVEFORM-RESOURCE-P00-003A", + "0.1.0-p00", + "Video Localization/contracts/VID-IMPL-P00-003A/records/resource-profile.json", + "6da872ad96a9f0840cc62bf2bd27201aaf8d877002d5add749833710d3e5e07d", + ), + ( + "policy-profile", + "VID-WAVEFORM-POLICY-P00-003A", + "0.1.0-p00", + "Video Localization/contracts/VID-IMPL-P00-003A/records/policy-profile.json", + "ad4838a59d06ee676b4b94be43d6f9dd5c7ded88f5c57cfd7f7f56bcae82c368", + ), + ( + "retry-profile", + "VID-WAVEFORM-RETRY-P00-003A", + "0.1.0-p00", + "Video Localization/contracts/VID-IMPL-P00-003A/records/retry-profile.json", + "35de87a3fe7681a485d2b8d4199f5fe89b8d27c38b1500043dd01397d9b3f8e1", + ), + ( + "schema-bundle", + "VID-IMPL-P00-003A", + "0.1.0-p00", + "Video Localization/contracts/VID-IMPL-P00-003A/schema-bundle.json", + SCHEMA_BUNDLE_SHA, + ), +]; + +#[derive(Debug, Deserialize, Clone)] +struct ManifestRecord { + role: String, + record_id: String, + record_version: String, + path: String, + #[serde(alias = "sha256")] + hash: String, + schema_id: Option, +} + +#[derive(Debug, Deserialize, Clone)] +struct ManifestFixtureRecord { + role: String, + path: String, + #[serde(alias = "sha256")] + hash: String, +} + +#[derive(Debug, Deserialize, Clone)] +struct ManifestSchemaRecord { + schema_id: String, + schema_version: String, + path: String, + sha256: String, +} + +#[derive(Debug, Deserialize, Clone)] +struct Manifest { + record_digest_profile_id: String, + record_digest_profile_version: String, + records: Vec, + #[serde(default)] + fixture_records: Vec, + #[serde(default)] + schema_records: Vec, + authorities: Vec, +} + +#[derive(Debug, Deserialize, Clone)] +struct AuthorityRecord { + id: String, + revision: String, + #[serde(alias = "sha256")] + hash: String, +} + +#[derive(Debug, Deserialize)] +struct SchemaBundle { + artifact_id: String, + artifact_version: String, + operation_id: String, + operation_version: String, + implementation_profile_id: String, + implementation_id: String, + schema_records: Vec, + #[allow(dead_code)] + #[serde(default)] + fixture_records: Vec, +} + +#[derive(Debug, Deserialize)] +struct FixtureBundle { + cache_key_positive_cases: Vec, + cache_key_negative_cases: Vec, + bulk_descriptor_positive_cases: Vec, + bulk_descriptor_negative_cases: Vec, + #[serde(default)] + opaque_handle_substitution_cases: Vec, + #[serde(default)] + cache_integrity_cases: Vec, + #[serde(default)] + publication_atomicity_cases: Vec, + #[serde(default)] + representation_timeline_downmix_cases: Vec, + #[serde(default)] + hostile_metadata_cases: Vec, + #[serde(default)] + interruption_cases: Vec, + #[serde(default)] + publication_journal_cases: Vec, + #[serde(default)] + stale_epoch_fence_lease_cases: Vec, +} + +#[derive(Debug, Deserialize)] +struct EvidenceManifestRecord { + path: String, + #[serde(default)] + sha256: Option, +} + +#[derive(Debug, Deserialize)] +struct EvidenceManifest { + changed_files: Vec, + evidence_files: Vec, + #[serde(default)] + evidence_records: Vec, +} + +fn workspace_root() -> PathBuf { + Path::new(env!("CARGO_MANIFEST_DIR")).join("..").join("..").join("..") +} + +fn read_text(path: &Path) -> String { + fs::read_to_string(path).unwrap_or_else(|error| panic!("read failed for {}: {error}", path.display())) +} + +fn read_json(path: &Path) -> Value { + serde_json::from_str(&read_text(path)).unwrap_or_else(|error| panic!("json parse failed for {}: {error}", path.display())) +} + +fn workspace_path(root: &Path, path: &str) -> PathBuf { + if path.starts_with("Video Localization/") || path.starts_with("Video Localization\\") { + root.join(path) + } else { + root.join("Video Localization").join(path) + } +} + +fn sha256_hex_of_file(path: &Path) -> String { + let bytes = fs::read(path).unwrap_or_else(|error| panic!("read failed for {}: {error}", path.display())); + let mut digest = Sha256::new(); + digest.update(&bytes); + digest + .finalize() + .iter() + .map(|byte| format!("{byte:02x}")) + .collect() +} + +fn bytes_are_utf8_and_exact_final_lf(path: &Path) -> bool { + let bytes = fs::read(path).unwrap_or_else(|error| panic!("read failed for {}: {error}", path.display())); + if bytes.is_empty() { + return false; + } + if bytes.starts_with(&[0xEF, 0xBB, 0xBF]) { + return false; + } + if !bytes.ends_with(b"\n") { + return false; + } + if bytes.ends_with(b"\n\n") { + return false; + } + if bytes.contains(&b'\r') { + return false; + } + if std::str::from_utf8(&bytes).is_err() { + return false; + } + true +} + +fn manifest_bound_text_paths() -> Vec { + let root = workspace_root(); + let evidence_manifest: EvidenceManifest = serde_json::from_str(&read_text(&root.join( + "Video Localization/specifications/evidence/PHASE-00-IMPLEMENTATION/VID-IMPL-P00-003A/manifest.json", + ))) + .expect("evidence manifest parse"); + + let evidence_test_report = "Video Localization/specifications/evidence/PHASE-00-IMPLEMENTATION/VID-IMPL-P00-003A/test-report.json" + .to_string(); + let mut paths = HashSet::new(); + for path in evidence_manifest.changed_files { + paths.insert(path); + } + for file in evidence_manifest.evidence_files { + paths.insert(format!( + "Video Localization/specifications/evidence/PHASE-00-IMPLEMENTATION/VID-IMPL-P00-003A/{file}", + )); + } + for record in evidence_manifest.evidence_records { + paths.insert(record.path); + } + paths.insert(evidence_test_report); + + paths.into_iter().collect() +} + +fn read_schema_records(root: &Path, path: &str) -> HashMap { + let bundle: SchemaBundle = serde_json::from_str(&read_text(&root.join(path))).expect("schema-bundle parse"); + let mut values = HashMap::new(); + for entry in bundle.schema_records { + values.insert(entry.schema_id, read_json(&workspace_path(root, &entry.path))); + } + values +} + +fn validate_schema_records(records: &[ManifestSchemaRecord], root: &Path) { + let required_schema_ids: HashSet<&str> = HashSet::from_iter([ + "VID-IMPL-P00-003A-WAVEFORM-INPUT", + "VID-IMPL-P00-003A-WAVEFORM-ARTIFACT", + "VID-IMPL-P00-003A-WAVEFORM-PARAMETER", + "VID-IMPL-P00-003A-WAVEFORM-STRUCTURED-ERROR", + "VID-IMPL-P00-003A-WAVEFORM-RESOURCE", + "VID-IMPL-P00-003A-WAVEFORM-POLICY", + "VID-IMPL-P00-003A-WAVEFORM-BULK-DESCRIPTOR", + "VID-IMPL-P00-003A-WAVEFORM-CONTROL", + "VID-IMPL-P00-003A-WAVEFORM-WORKER-HELLO", + "VID-IMPL-P00-003A-WAVEFORM-OPERATION-PROFILE", + ]); + let mut observed: HashSet = HashSet::new(); + + assert_eq!(records.len(), required_schema_ids.len()); + for record in records { + assert!(required_schema_ids.contains(record.schema_id.as_str())); + observed.insert(record.schema_id.clone()); + let file_hash = sha256_hex_of_file(&workspace_path(root, &record.path)); + assert_eq!(record.sha256.to_lowercase(), file_hash); + assert_eq!(record.schema_version, "0.1.0-p00"); + } + assert_eq!(required_schema_ids.len(), observed.len()); +} + +fn assert_manifest_is_closed(manifest: &Manifest) -> Result<(), String> { + if manifest.record_digest_profile_id != "VID-WAVEFORM-ADMISSION-MANIFEST-P00-003A" { + return Err("invalid admission manifest profile".to_string()); + } + if manifest.record_digest_profile_version != "0.1.0-p00" { + return Err("invalid admission manifest version".to_string()); + } + + let mut records = HashMap::new(); + for record in &manifest.records { + records.insert(record.role.as_str(), record); + } + let expected_roles: HashSet<&str> = HashSet::from_iter(RECORD_CHECKSUMS.iter().map(|(r, ..)| *r)); + let observed_roles: HashSet<&str> = records.keys().copied().collect(); + if observed_roles != expected_roles { + return Err("required manifest roles mismatch".to_string()); + } + + for (role, expected_record_id, expected_version, expected_path, expected_hash) in RECORD_CHECKSUMS { + let record = records + .get(*role) + .ok_or_else(|| format!("missing record role {role}"))?; + if record.record_id != *expected_record_id { + return Err(format!("record id mismatch for {role}")); + } + if record.record_version != *expected_version { + return Err(format!("record version mismatch for {role}")); + } + if record.path != *expected_path { + return Err(format!("record path mismatch for {role}")); + } + if record.hash.to_lowercase() != *expected_hash { + return Err(format!("record hash mismatch for {role}")); + } + if sha256_hex_of_file(&workspace_path(&workspace_root(), &record.path)) != *expected_hash { + return Err(format!("record file hash mismatch for {role}")); + } + if *role == "control-protocol" { + if record.schema_id.as_deref() != Some("VID-IMPL-P00-003A-WAVEFORM-CONTROL") { + return Err("control schema id must be VID-IMPL-P00-003A-WAVEFORM-CONTROL".to_string()); + } + } + } + + let required_fixture_roles: HashSet<&str> = HashSet::from_iter([ + "operation-descriptor", + "worker-hello", + "cache-and-descriptor-fixtures", + ]); + let fixture_records: HashMap<&str, &ManifestFixtureRecord> = + manifest.fixture_records.iter().map(|record| (record.role.as_str(), record)).collect(); + for role in &required_fixture_roles { + let record = fixture_records + .get(*role) + .ok_or_else(|| format!("missing fixture role {role}"))?; + let expected = record.path.to_lowercase(); + let observed = sha256_hex_of_file(&workspace_path(&workspace_root(), &expected)).to_lowercase(); + if observed != record.hash.to_lowercase() { + return Err(format!("fixture hash mismatch for {role}")); + } + } + + validate_schema_records(&manifest.schema_records, &workspace_root()); + + let required_authorities: HashSet<&str> = HashSet::from_iter([ + "SUI-SPEC-003", + "VID-DEC-003", + "VID-IMPL-P00-003A-SCHEMA-BUNDLE", + "VID-IMPL-P00-003A-INPUT", + "VID-IMPL-P00-003A-ARTIFACT", + "VID-IMPL-P00-003A-PARAMETER", + "VID-IMPL-P00-003A-STRUCTURED-ERROR", + "VID-IMPL-P00-003A-RESOURCE", + "VID-IMPL-P00-003A-POLICY", + "VID-IMPL-P00-003A-BULK-DESCRIPTOR", + "VID-IMPL-P00-003A-CONTROL", + "VID-IMPL-P00-003A-WORKER-HELLO", + "VID-IMPL-P00-003A-OPERATION-PROFILE", + "VID-IMPL-P00-002B1-SCHEMA-BUNDLE", + ]); + let authority_ids: HashSet<&str> = manifest.authorities.iter().map(|a| a.id.as_str()).collect(); + if authority_ids != required_authorities { + return Err("required authorities mismatch".to_string()); + } + let schema_bundle_authority = manifest + .authorities + .iter() + .find(|item| item.id == "VID-IMPL-P00-002B1-SCHEMA-BUNDLE") + .ok_or_else(|| "missing VID-IMPL-P00-002B1-SCHEMA-BUNDLE authority".to_string())?; + if schema_bundle_authority.revision != "0.1.0-p00" { + return Err("wrong schema-bundle revision".to_string()); + } + if schema_bundle_authority.hash.to_lowercase() != SCHEMA_BUNDLE_002B1_SHA { + return Err("wrong 002B1 schema bundle hash".to_string()); + } + Ok(()) +} + +fn assert_json_valid(schema: &Value, value: &Value, label: &str) { + let validator = jsonschema::draft202012::new(schema).unwrap_or_else(|error| panic!("{label} schema failed to compile: {error}")); + let errors: Vec<_> = validator.iter_errors(value).collect(); + assert!( + errors.is_empty(), + "{label} should be valid: {}", + errors + .into_iter() + .map(|error| error.to_string()) + .collect::>() + .join(", ") + ); +} + +fn assert_json_rejects(schema: &Value, value: &Value, label: &str) { + let validator = jsonschema::draft202012::new(schema).unwrap_or_else(|error| panic!("{label} schema failed to compile: {error}")); + let errors: Vec<_> = validator.iter_errors(value).collect(); + assert!(!errors.is_empty(), "{label} must be rejected by schema"); +} + +fn cbor_skip_item(bytes: &[u8], index: &mut usize) -> bool { + if *index >= bytes.len() { + return false; + } + let first = bytes[*index]; + let major = first >> 5; + let info = first & 0x1f; + *index += 1; + + let mut read_u64 = |i: &mut usize| -> Option { + let len = if info <= 23 { + info as u64 + } else if info == 24 { + if *i >= bytes.len() { + return None; + } + let value = bytes[*i] as u64; + *i += 1; + value + } else if info == 25 { + if *i + 2 > bytes.len() { + return None; + } + let value = ((bytes[*i] as u64) << 8) | bytes[*i + 1] as u64; + *i += 2; + value + } else if info == 26 { + if *i + 4 > bytes.len() { + return None; + } + let value = ((bytes[*i] as u64) << 24) + | ((bytes[*i + 1] as u64) << 16) + | ((bytes[*i + 2] as u64) << 8) + | (bytes[*i + 3] as u64); + *i += 4; + value + } else if info == 27 { + if *i + 8 > bytes.len() { + return None; + } + let value = ((bytes[*i] as u64) << 56) + | ((bytes[*i + 1] as u64) << 48) + | ((bytes[*i + 2] as u64) << 40) + | ((bytes[*i + 3] as u64) << 32) + | ((bytes[*i + 4] as u64) << 24) + | ((bytes[*i + 5] as u64) << 16) + | ((bytes[*i + 6] as u64) << 8) + | (bytes[*i + 7] as u64); + *i += 8; + value + } else { + return None; + }; + Some(len) + }; + + let length = match major { + 0 | 1 => return true, + 2 => match read_u64(index) { + Some(len) => len as usize, + None => return false, + }, + 3 => match read_u64(index) { + Some(len) => { + let len = match usize::try_from(len) { + Ok(len) => len, + Err(_) => return false, + }; + *index += len; + return *index <= bytes.len(); + } + None => return false, + }, + 4 => match read_u64(index) { + Some(len) => len as usize, + None => return false, + }, + 5 => match read_u64(index) { + Some(len) => len as usize, + None => return false, + }, + 6 | 7 => return true, + 0b111 | 0b110 => return true, + _ => return false, + }; + + if major == 4 || major == 5 { + for _ in 0..length { + if !cbor_skip_item(bytes, index) { + return false; + } + if major == 5 { + if !cbor_skip_item(bytes, index) { + return false; + } + } + } + return true; + } + false +} + +fn cbor_keyed_items(bytes: &[u8], index: &mut usize) -> Option, usize, usize)>> { + if *index >= bytes.len() { + return None; + } + let first = bytes[*index]; + let major = first >> 5; + if major != 5 { + return None; + } + *index += 1; + let info = first & 0x1f; + let mut len: usize = match info { + v if v <= 23 => v as usize, + 24 => { + if *index >= bytes.len() { + return None; + } + let value = bytes[*index] as usize; + *index += 1; + value + } + 25 => { + if *index + 1 >= bytes.len() { + return None; + } + let value = ((bytes[*index] as usize) << 8) | bytes[*index + 1] as usize; + *index += 2; + value + } + 26 => { + if *index + 3 >= bytes.len() { + return None; + } + let value = ((bytes[*index] as usize) << 24) + | ((bytes[*index + 1] as usize) << 16) + | ((bytes[*index + 2] as usize) << 8) + | (bytes[*index + 3] as usize); + *index += 4; + value + } + 27 => { + if *index + 7 >= bytes.len() { + return None; + } + let value = ((bytes[*index] as usize) << 56) + | ((bytes[*index + 1] as usize) << 48) + | ((bytes[*index + 2] as usize) << 40) + | ((bytes[*index + 3] as usize) << 32) + | ((bytes[*index + 4] as usize) << 24) + | ((bytes[*index + 5] as usize) << 16) + | ((bytes[*index + 6] as usize) << 8) + | (bytes[*index + 7] as usize); + *index += 8; + value + } + _ => return None, + }; + + let mut pairs = Vec::new(); + for _ in 0..len { + let key_start = *index; + if !cbor_skip_item(bytes, index) { + return None; + } + let key_end = *index; + let value_start = *index; + if !cbor_skip_item(bytes, index) { + return None; + } + let value_end = *index; + pairs.push((bytes[key_start..key_end].to_vec(), value_start, value_end)); + } + Some(pairs) +} + +fn cbor_map_keys_are_sorted(bytes: &[u8], start: usize) -> bool { + let mut index = start; + let pairs = match cbor_keyed_items(bytes, &mut index) { + Some(pairs) => pairs, + None => return false, + }; + + let key_bytes: Vec<_> = pairs.iter().map(|(key, _, _)| key.clone()).collect(); + if key_bytes.windows(2).any(|window| window[0] > window[1]) { + return false; + } + pairs.iter().all(|(_, value_start, value_end)| { + if *value_start >= bytes.len() || *value_end > bytes.len() { + return false; + } + if bytes[*value_start] >> 5 == 5 { + return cbor_map_keys_are_sorted(bytes, *value_start); + } + true + }) +} + +fn sample_cache_profile() -> wc::WaveformCacheKeyProfile { + wc::WaveformCacheKeyProfile { + cache_key_schema: wc::CACHE_KEY_SCHEMA_ID.to_string(), + operation: wc::WaveformCacheKeyProfileIdentity { + id: wc::OPERATION_ID.to_string(), + version: wc::OPERATION_VERSION.to_string(), + }, + implementation: wc::WaveformCacheKeyProfileIdentity { + id: wc::IMPLEMENTATION_ID.to_string(), + version: wc::IMPLEMENTATION_PROFILE_ID.to_string(), + }, + inputs: vec![wc::WaveformCacheInputPort { + order: 0, + kind: "waveform_request".to_string(), + schema: wc::OPERATION_SCHEMA_ID.to_string(), + content: "source".to_string(), + revision: "0.1.0-p00".to_string(), + sample_range: "[0,4096)".to_string(), + }], + parameters: wc::WaveformCacheParameters { + cache_key_schema: wc::CACHE_KEY_SCHEMA_ID.to_string(), + cache_key_seed: "waveform-seed-003a".to_string(), + environment_equivalence: wc::WaveformEnvironmentEquivalence { + os_family: "windows".to_string(), + arch_family: "x64".to_string(), + worker_family: "vid-waveform-worker".to_string(), + containerization: false, + capability_bundle: "audio-none".to_string(), + }, + resource_profile_id: "VID-WAVEFORM-RESOURCE-P00-003A".to_string(), + policy_profile_id: "VID-WAVEFORM-POLICY-P00-003A".to_string(), + retry_profile_id: "VID-WAVEFORM-RETRY-P00-003A".to_string(), + representation: wc::WaveformCacheRepresentation { + peak: "waveform-peak-v1".to_string(), + time: "sample".to_string(), + channel: "stereo-major".to_string(), + downmix: "matrix-stereo-downmix-v1".to_string(), + resampling: "resample-none".to_string(), + stability: "fixed".to_string(), + }, + }, + dependencies: wc::WaveformCacheDependencies { + resource_profile: "VID-WAVEFORM-RESOURCE-P00-003A".to_string(), + policy_profile: "VID-WAVEFORM-POLICY-P00-003A".to_string(), + retry_profile: "VID-WAVEFORM-RETRY-P00-003A".to_string(), + operation_profile: "VID-WAVEFORM-OPERATION-PROFILE-P00-003A".to_string(), + cache_key_schema: wc::CACHE_KEY_SCHEMA_ID.to_string(), + }, + output_contract: wc::WaveformCacheOutputContract { + artifact_id: "waveform-artifact-request".to_string(), + artifact_version: "0.1.0-p00".to_string(), + output_schema_id: wc::OUTPUT_SCHEMA_ID.to_string(), + }, + seed: "waveform-seed-003a".to_string(), + environment_equivalence: wc::WaveformEnvironmentEquivalence { + os_family: "windows".to_string(), + arch_family: "x64".to_string(), + worker_family: "vid-waveform-worker".to_string(), + containerization: false, + capability_bundle: "audio-none".to_string(), + }, + resource: wc::WaveformCacheResource { + resource_profile_id: "VID-WAVEFORM-RESOURCE-P00-003A".to_string(), + }, + policy: wc::WaveformCachePolicy { + network: "denied".to_string(), + watchdog_required: true, + job_object_required: true, + media_parse: false, + }, + representation: wc::WaveformCacheRepresentation { + peak: "waveform-peak-v1".to_string(), + time: "sample".to_string(), + channel: "stereo-major".to_string(), + downmix: "matrix-stereo-downmix-v1".to_string(), + resampling: "resample-none".to_string(), + stability: "fixed".to_string(), + }, + } +} + +fn sample_bulk_descriptor() -> wc::WaveformBulkDescriptor { + wc::WaveformBulkDescriptor { + version: wc::BULK_DESCRIPTOR_PROFILE.to_string(), + mode: "read-only".to_string(), + handle_identity: "handle-vid-waveform-003a".to_string(), + attempt_id: "attempt-001".to_string(), + lease_id: "lease-001".to_string(), + cancel_scope: "attempt-001".to_string(), + expiry: "2099-01-01T00:00:00Z".to_string(), + integrity: wc::WaveformOutputContractDigest { + algorithm: "sha-256".to_string(), + value: "9f1c4d4fdb5fc8aaec58d9ebf8db8a5d4b9df3c8c1f4f5ad1f0d2c9e4a6c3b6d".to_string(), + }, + chunk_hashes_omitted: true, + length: 4096, + payload_schema: wc::OUTPUT_SCHEMA_ID.to_string(), + source_publication_fence: "fence-001".to_string(), + representation: wc::WaveformBulkRepresentation { + peak: "waveform-peak-v1".to_string(), + time: "sample".to_string(), + channel: "stereo-major".to_string(), + downmix: "matrix-stereo-downmix-v1".to_string(), + resampling: "resample-none".to_string(), + source_timeline: "timeline-001".to_string(), + sample_range: "[0,4096)".to_string(), + }, + descriptor_hash: None, + } +} + +fn cache_key_expected_digest(case: &Value) -> Option { + case.get("expected_cache_key_digest") + .and_then(Value::as_str) + .map(ToString::to_string) +} + +fn bulk_expected_descriptor_digest(case: &Value) -> Option { + case.get("expected_descriptor_digest") + .and_then(Value::as_str) + .map(ToString::to_string) +} + +fn cache_profile_from_case(case: &Value) -> wc::WaveformCacheKeyProfile { + let mut profile = sample_cache_profile(); + if let Some(seed) = case.get("seed").and_then(Value::as_str) { + profile.seed = seed.to_string(); + } + if let Some(resource_profile_id) = case.get("resource_profile_id").and_then(Value::as_str) { + profile.parameters.resource_profile_id = resource_profile_id.to_string(); + profile.resource.resource_profile_id = resource_profile_id.to_string(); + } + if let Some(policy_profile_id) = case.get("policy_profile_id").and_then(Value::as_str) { + profile.parameters.policy_profile_id = policy_profile_id.to_string(); + } + if let Some(retry_profile_id) = case.get("retry_profile_id").and_then(Value::as_str) { + profile.parameters.retry_profile_id = retry_profile_id.to_string(); + profile.dependencies.retry_profile = retry_profile_id.to_string(); + } + if let Some(representation) = case.get("representation").and_then(Value::as_object) { + profile.representation.peak = representation + .get("peak") + .and_then(Value::as_str) + .unwrap_or(&profile.representation.peak) + .to_string(); + profile.representation.time = representation + .get("time") + .and_then(Value::as_str) + .unwrap_or(&profile.representation.time) + .to_string(); + profile.representation.channel = representation + .get("channel") + .and_then(Value::as_str) + .unwrap_or(&profile.representation.channel) + .to_string(); + profile.representation.downmix = representation + .get("downmix") + .and_then(Value::as_str) + .unwrap_or(&profile.representation.downmix) + .to_string(); + profile.representation.resampling = representation + .get("resampling") + .and_then(Value::as_str) + .unwrap_or(&profile.representation.resampling) + .to_string(); + profile.representation.stability = representation + .get("stability") + .and_then(Value::as_str) + .unwrap_or(&profile.representation.stability) + .to_string(); + } + + if let Some(inputs) = case.get("input_ports").and_then(Value::as_array) { + profile.inputs = inputs + .iter() + .map(|input| wc::WaveformCacheInputPort { + order: input.get("order").and_then(Value::as_u64).unwrap_or(0), + kind: input.get("type").and_then(Value::as_str).unwrap_or("waveform_request").to_string(), + schema: input + .get("schema") + .and_then(Value::as_str) + .unwrap_or(&wc::OPERATION_SCHEMA_ID) + .to_string(), + content: input.get("content").and_then(Value::as_str).unwrap_or("source").to_string(), + revision: input + .get("revision") + .and_then(Value::as_str) + .unwrap_or("0.1.0-p00") + .to_string(), + sample_range: input + .get("sample_range") + .and_then(Value::as_str) + .unwrap_or("[0,4096)") + .to_string(), + }) + .collect(); + } + + if profile.inputs.is_empty() { + profile.inputs = vec![wc::WaveformCacheInputPort { + order: 0, + kind: "waveform_request".to_string(), + schema: wc::OPERATION_SCHEMA_ID.to_string(), + content: "source".to_string(), + revision: "0.1.0-p00".to_string(), + sample_range: "[0,4096)".to_string(), + }]; + } + + profile +} + +fn fixture_case_payload(length: usize) -> Vec { + let mut bytes = vec![0u8; length]; + for (index, byte) in bytes.iter_mut().enumerate() { + *byte = (index % 251) as u8; + } + bytes +} + +fn apply_bulk_descriptor_overrides( + descriptor: &mut wc::WaveformBulkDescriptor, + override_descriptor: &Value, +) { + if let Some(version) = override_descriptor.get("version").and_then(Value::as_str) { + descriptor.version = version.to_string(); + } + if let Some(mode) = override_descriptor.get("mode").and_then(Value::as_str) { + descriptor.mode = mode.to_string(); + } + if let Some(handle) = override_descriptor.get("handle_identity").and_then(Value::as_str) { + descriptor.handle_identity = handle.to_string(); + } + if let Some(attempt_id) = override_descriptor.get("attempt_id").and_then(Value::as_str) { + descriptor.attempt_id = attempt_id.to_string(); + } + if let Some(lease_id) = override_descriptor.get("lease_id").and_then(Value::as_str) { + descriptor.lease_id = lease_id.to_string(); + } + if let Some(cancel_scope) = override_descriptor.get("cancel_scope").and_then(Value::as_str) { + descriptor.cancel_scope = cancel_scope.to_string(); + } + if let Some(expiry) = override_descriptor.get("expiry").and_then(Value::as_str) { + descriptor.expiry = expiry.to_string(); + } + if let Some(integrity) = override_descriptor.get("integrity").and_then(Value::as_object) { + if let Some(algorithm) = integrity.get("algorithm").and_then(Value::as_str) { + descriptor.integrity.algorithm = algorithm.to_string(); + } + if let Some(value) = integrity.get("value").and_then(Value::as_str) { + descriptor.integrity.value = value.to_string(); + } + } + if let Some(chunk_hashes_omitted) = override_descriptor.get("chunk_hashes_omitted").and_then(Value::as_bool) { + descriptor.chunk_hashes_omitted = chunk_hashes_omitted; + } + if let Some(length) = override_descriptor.get("length").and_then(Value::as_u64) { + descriptor.length = length; + } + if let Some(payload_schema) = override_descriptor.get("payload_schema").and_then(Value::as_str) { + descriptor.payload_schema = payload_schema.to_string(); + } + if let Some(fence) = override_descriptor.get("source_publication_fence").and_then(Value::as_str) { + descriptor.source_publication_fence = fence.to_string(); + } + if let Some(representation) = override_descriptor.get("representation").and_then(Value::as_object) { + if let Some(peak) = representation.get("peak").and_then(Value::as_str) { + descriptor.representation.peak = peak.to_string(); + } + if let Some(time) = representation.get("time").and_then(Value::as_str) { + descriptor.representation.time = time.to_string(); + } + if let Some(channel) = representation.get("channel").and_then(Value::as_str) { + descriptor.representation.channel = channel.to_string(); + } + if let Some(downmix) = representation.get("downmix").and_then(Value::as_str) { + descriptor.representation.downmix = downmix.to_string(); + } + if let Some(resampling) = representation.get("resampling").and_then(Value::as_str) { + descriptor.representation.resampling = resampling.to_string(); + } + if let Some(source_timeline) = representation.get("source_timeline").and_then(Value::as_str) { + descriptor.representation.source_timeline = source_timeline.to_string(); + } + if let Some(sample_range) = representation.get("sample_range").and_then(Value::as_str) { + descriptor.representation.sample_range = sample_range.to_string(); + } + } + if let Some(descriptor_hash) = override_descriptor.get("descriptor_hash").and_then(Value::as_str) { + descriptor.descriptor_hash = Some(descriptor_hash.to_string()); + } +} + +fn sample_retry_profile() -> wc::WaveformRetryProfile { + wc::WaveformRetryProfile { + max_total_attempts: 2, + base_wait_millis: 500, + max_wait_millis: 500, + backoff: "fixed".to_string(), + cumulative_wall_seconds: 30, + cumulative_cpu_seconds: 30, + cumulative_ram_bytes: 268_435_456, + cumulative_staging_bytes: 536_870_912, + cost_ceiling: 2, + applicable_codes: vec![ + "VID-WAVEFORM-WORKER-TRANSIENT".to_string(), + "VID-WAVEFORM-STORAGE-TRANSIENT".to_string(), + ], + } +} + +fn sample_publication_attempt() -> (wc::WaveformPublicationAttempt, Vec) { + let sequence = TEST_PUBLICATION_SEQUENCE.fetch_add(1, Ordering::Relaxed); + let attempt_id = format!("attempt-c8-{sequence}"); + let lease_id = format!("lease-c8-{sequence}"); + let mut descriptor = sample_bulk_descriptor(); + let payload = fixture_case_payload(descriptor.length as usize); + descriptor.integrity.value = wc::sha256_hex_of_bytes(&payload); + descriptor.attempt_id = attempt_id.clone(); + descriptor.lease_id = lease_id.clone(); + descriptor.cancel_scope = format!("cancel-{attempt_id}"); + let digest = wc::bulk_descriptor_digest(&descriptor).expect("descriptor digest"); + descriptor.descriptor_hash = Some(digest); + + let attempt = wc::WaveformPublicationAttempt { + attempt_id: attempt_id.clone(), + lease: wc::WaveformPublicationLease { + lease_id: lease_id.clone(), + lease_epoch: 1, + minimum_acceptable_lease_epoch: 1, + expected_fence_token: "fence-001".to_string(), + observed_fence_token: "fence-001".to_string(), + staged_copy_hash: wc::sha256_hex_of_bytes(&payload), + staged_copy_length: descriptor.length, + cache_authority: false, + }, + descriptor, + }; + (attempt, payload) +} + +#[test] +fn manifest_and_schema_bundle_are_authoritative_and_fail_closed() { + let manifest_path = workspace_root().join("Video Localization/contracts/VID-IMPL-P00-003A/records/manifest.json"); + let manifest: Manifest = serde_json::from_str(&read_text(&manifest_path)).expect("manifest parse"); + assert!( + assert_manifest_is_closed(&manifest).is_ok(), + "manifest not fail-closed against required exact records" + ); +} + +#[test] +fn manifest_missing_or_mismatched_bindings_fail_closed() { + let manifest_path = workspace_root().join("Video Localization/contracts/VID-IMPL-P00-003A/records/manifest.json"); + let manifest: Manifest = serde_json::from_str(&read_text(&manifest_path)).expect("manifest parse"); + let mut missing_record = manifest.clone(); + if let Some(index) = missing_record.records.iter().position(|record| record.role == "operation-profile") { + missing_record.records.remove(index); + } + assert!(assert_manifest_is_closed(&missing_record).is_err()); + + let mut mismatched = manifest.clone(); + if let Some(record) = mismatched.records.iter_mut().find(|record| record.role == "resource-profile") { + record.hash = "0000000000000000000000000000000000000000000000000000000000000000".to_string(); + } + assert!(assert_manifest_is_closed(&mismatched).is_err()); +} + +#[test] +fn schema_bundle_hashes_and_required_schema_ids_are_exact() { + let bundle = read_json( + &workspace_root().join("Video Localization/contracts/VID-IMPL-P00-003A/schema-bundle.json"), + ); + let schema_bundle: SchemaBundle = serde_json::from_value(bundle).expect("schema-bundle parse"); + assert!(schema_bundle + .artifact_id + .eq_ignore_ascii_case("VID-IMPL-P00-003A")); + assert!(schema_bundle + .implementation_id + .eq_ignore_ascii_case("VID-IMPL-P00-003A")); + + validate_schema_records(&schema_bundle.schema_records, &workspace_root()); + + let records: HashSet<&str> = schema_bundle.schema_records.iter().map(|r| r.schema_id.as_str()).collect(); + let expected: HashSet<&str> = HashSet::from_iter([ + "VID-IMPL-P00-003A-WAVEFORM-INPUT", + "VID-IMPL-P00-003A-WAVEFORM-ARTIFACT", + "VID-IMPL-P00-003A-WAVEFORM-PARAMETER", + "VID-IMPL-P00-003A-WAVEFORM-STRUCTURED-ERROR", + "VID-IMPL-P00-003A-WAVEFORM-RESOURCE", + "VID-IMPL-P00-003A-WAVEFORM-POLICY", + "VID-IMPL-P00-003A-WAVEFORM-BULK-DESCRIPTOR", + "VID-IMPL-P00-003A-WAVEFORM-CONTROL", + "VID-IMPL-P00-003A-WAVEFORM-WORKER-HELLO", + "VID-IMPL-P00-003A-WAVEFORM-OPERATION-PROFILE", + ]); + assert_eq!(records, expected); +} + +#[test] +fn operation_and_worker_hello_profile_bindings_are_exact() { + let root = workspace_root(); + let schema_records = read_schema_records(&root, "Video Localization/contracts/VID-IMPL-P00-003A/schema-bundle.json"); + + let op_descriptor = read_json(&root.join("Video Localization/contracts/VID-IMPL-P00-003A/fixtures/operation-descriptor.json")); + let op_profile = read_json(&root.join("Video Localization/contracts/VID-IMPL-P00-003A/records/operation-profile.json")); + let worker_hello = read_json(&root.join("Video Localization/contracts/VID-IMPL-P00-003A/fixtures/worker-hello.json")); + let hello_text = worker_hello.to_string().to_ascii_lowercase(); + + let operation_schema = schema_records + .get("VID-IMPL-P00-003A-WAVEFORM-INPUT") + .expect("input schema") + .clone(); + let hello_schema = schema_records + .get("VID-IMPL-P00-003A-WAVEFORM-WORKER-HELLO") + .expect("hello schema") + .clone(); + let profile_schema = schema_records + .get("VID-IMPL-P00-003A-WAVEFORM-OPERATION-PROFILE") + .expect("operation profile schema") + .clone(); + + assert_json_valid(&operation_schema, &op_descriptor, "operation descriptor"); + assert_json_valid(&hello_schema, &worker_hello, "worker hello"); + assert_json_valid(&profile_schema, &op_profile, "operation profile"); + + assert_eq!(op_descriptor["operation_id"], json!(wc::OPERATION_ID)); + assert_eq!(op_descriptor["operation_version"], json!(wc::OPERATION_VERSION)); + assert_eq!(op_descriptor["implementation_id"], json!(wc::IMPLEMENTATION_ID)); + assert_eq!(op_profile["implementation_id"], json!(wc::IMPLEMENTATION_ID)); + + let output_ports = op_descriptor["output_ports"].as_array().expect("output_ports array"); + assert_eq!(output_ports.len(), 3); + assert_eq!(output_ports[0]["port_type"], json!("waveform_artifact")); + assert_eq!(output_ports[0]["max_bytes"], json!(65536)); + assert_eq!(output_ports[1]["port_type"], json!("waveform_error")); + assert_eq!(output_ports[1]["max_bytes"], json!(32768)); + assert_eq!(output_ports[2]["port_type"], json!("waveform_peak_bulk")); + assert_eq!(output_ports[2]["max_bytes"], json!(65536)); + + let profile_ports = op_profile["ports"].as_array().expect("profile ports"); + assert_eq!(profile_ports.len(), 4); + assert_eq!(profile_ports[0]["role"], json!("waveform_request")); + assert_eq!(profile_ports[0]["max_bytes"], json!(262144)); + assert_eq!(profile_ports[1]["role"], json!("waveform_artifact")); + assert_eq!(profile_ports[1]["max_bytes"], json!(65536), "artifact ceiling must remain at 65536"); + assert_eq!(profile_ports[2]["role"], json!("waveform_error")); + assert_eq!(profile_ports[2]["max_bytes"], json!(32768)); + assert_eq!(profile_ports[3]["role"], json!("waveform_peak_bulk")); + assert_eq!(profile_ports[3]["max_bytes"], json!(65536)); + assert_eq!(op_profile["policy"]["bulk_descriptor_profile"], json!(wc::BULK_DESCRIPTOR_PROFILE)); + + assert!(op_descriptor["staged_lease"]["observed_fence_token"] + == op_descriptor["staged_lease"]["expected_fence_token"]); + assert_eq!(op_profile["operation_id"], json!(wc::OPERATION_ID)); + assert_eq!(op_profile["operation_version"], json!(wc::OPERATION_VERSION)); + + let mut leaked = false; + ["ffprobe", "ffmpeg", "chocolatey", "programdata"].iter().for_each(|needle| { + if hello_text.contains(needle) { + leaked = true; + } + }); + assert!(!leaked, "worker-hello must not leak ffprobe/ffmpeg execution identity"); +} + +#[test] +fn worker_hello_rejects_unauthorized_executable_identity() { + let root = workspace_root(); + let schema_records = read_schema_records(&root, "Video Localization/contracts/VID-IMPL-P00-003A/schema-bundle.json"); + let worker_hello = read_json(&root.join("Video Localization/contracts/VID-IMPL-P00-003A/fixtures/worker-hello.json")); + let schema = schema_records + .get("VID-IMPL-P00-003A-WAVEFORM-WORKER-HELLO") + .expect("worker hello schema"); + + let mut bad = worker_hello.clone(); + if let Some(object) = bad.as_object_mut() { + object.insert( + "executable_path".to_string(), + json!("C:\\ProgramData\\ffprobe.exe"), + ); + object.insert("executable_sha256".to_string(), json!("000000000000000000000000000000000000000000000000000000000000000000")); + object.insert("component_version".to_string(), json!("not-authorized")); + } + assert_json_rejects(schema, &bad, "unauthorized worker hello executable fields"); +} + +#[test] +fn cache_key_preimage_is_stable_with_sorted_cbor_key_bytes() { + let mut profile_a = sample_cache_profile(); + let mut profile_b = sample_cache_profile(); + let extra_input = wc::WaveformCacheInputPort { + order: 1, + kind: "waveform_request".to_string(), + schema: wc::OPERATION_SCHEMA_ID.to_string(), + content: "source".to_string(), + revision: "0.1.0-p00".to_string(), + sample_range: "[0,4096)".to_string(), + }; + profile_a.inputs.push(extra_input.clone()); + profile_b.inputs.push(extra_input); + profile_b.inputs.swap(0, 1); + let preimage_a = wc::cache_key_preimage(&profile_a).expect("preimage A"); + let preimage_b = wc::cache_key_preimage(&profile_b).expect("preimage B"); + assert_eq!( + wc::cache_key_digest(&profile_a).expect("digest A"), + wc::cache_key_digest(&profile_b).expect("digest B"), + ); + assert_eq!(preimage_a, preimage_b); + assert!(cbor_map_keys_are_sorted(&preimage_a, 0), "top-level and nested cbor maps must use RFC-8949 ordering"); +} + +#[test] +fn bulk_descriptor_positive_and_zero_length_boundary() { + let mut descriptor = sample_bulk_descriptor(); + let digest = wc::bulk_descriptor_digest(&descriptor).expect("descriptor digest"); + descriptor.descriptor_hash = Some(digest); + assert!(wc::validate_bulk_descriptor(&descriptor).is_ok()); + + descriptor.length = 0; + descriptor.descriptor_hash = Some(wc::bulk_descriptor_digest(&descriptor).expect("zero-length digest")); + assert!(wc::validate_bulk_descriptor(&descriptor).is_ok(), "zero-length bulk payload is boundary-accepted"); + + descriptor.length = 536_870_913; + descriptor.descriptor_hash = Some("0".repeat(64)); + assert!(wc::validate_bulk_descriptor(&descriptor).is_err()); +} + +#[test] +fn state_mapping_matrix_covers_all_codes_and_recovery_boundaries() { + let mapping_codes: HashSet<&str> = wc::VID_WAVEFORM_STATE_MAPPINGS + .iter() + .map(|entry| entry.video_disposition) + .collect(); + + let expected_codes: HashSet<&str> = HashSet::from_iter([ + "VID-WAVEFORM-CANCELLED", + "VID-WAVEFORM-DEADLINE-EXCEEDED", + "VID-WAVEFORM-RESOURCE-LIMIT", + "VID-WAVEFORM-LEASE-EXPIRED", + "VID-WAVEFORM-FENCE-MISMATCH", + "VID-WAVEFORM-CACHE-STALE", + "VID-WAVEFORM-CACHE-CORRUPT", + "VID-WAVEFORM-INPUT-SCHEMA-INVALID", + "VID-WAVEFORM-OUTPUT-SCHEMA-INVALID", + "VID-WAVEFORM-INTEGRITY-MISMATCH", + "VID-WAVEFORM-MALFORMED-DESCRIPTOR", + "VID-WAVEFORM-PROTOCOL-INCOMPATIBLE", + "VID-WAVEFORM-HANDLE-INCOMPATIBLE", + "VID-WAVEFORM-PUBLICATION-FAILED", + "VID-WAVEFORM-STORAGE-PERMANENT", + "VID-WAVEFORM-JOURNAL-INVALID", + "VID-WAVEFORM-PARTIAL-OUTPUT", + "VID-WAVEFORM-METADATA-INVALID", + "VID-WAVEFORM-IDENTITY-MISMATCH", + "VID-WAVEFORM-POLICY-DENIED", + "VID-WAVEFORM-WORKER-TRANSIENT", + "VID-WAVEFORM-STORAGE-TRANSIENT", + "VID-WAVEFORM-WORKER-PERMANENT", + "VID-WAVEFORM-REVIEW", + ]); + assert_eq!(mapping_codes, expected_codes); + let timed_out = wc::state_mapping_for_code("VID-WAVEFORM-DEADLINE-EXCEEDED") + .expect("deadline mapping exists"); + assert_eq!(timed_out.shared_terminal_state, "TimedOut"); + assert_eq!(timed_out.retry_class, "non-retryable"); + assert_eq!( + wc::state_mapping_for_code("VID-WAVEFORM-WORKER-TRANSIENT") + .expect("transient retry mapping") + .retry_class, + "transient" + ); + assert_eq!( + wc::state_mapping_for_code("VID-WAVEFORM-STORAGE-TRANSIENT") + .expect("storage transient mapping") + .retry_class, + "transient" + ); + + for mapping in wc::VID_WAVEFORM_STATE_MAPPINGS { + assert!(!mapping.shared_terminal_state.is_empty()); + assert!(!mapping.retry_class.is_empty()); + assert!(!mapping.operation_stage.is_empty()); + assert!(!mapping.error_category.is_empty()); + assert!(!mapping.safe_recovery.is_empty()); + assert!(!mapping.identity_refs.is_empty()); + assert!(mapping.identity_refs.len() <= 5); + assert!(!mapping.video_disposition.is_empty()); + } +} + +#[test] +fn schema_mutation_matrix_rejects_required_and_unknown_fields() { + let root = workspace_root(); + let schema_map = read_schema_records(&root, "Video Localization/contracts/VID-IMPL-P00-003A/schema-bundle.json"); + let fixture_path = root.join("Video Localization/contracts/VID-IMPL-P00-003A/fixtures/operation-descriptor.json"); + let worker_hello_path = root.join("Video Localization/contracts/VID-IMPL-P00-003A/fixtures/worker-hello.json"); + let cache_fixture_path = root.join("Video Localization/contracts/VID-IMPL-P00-003A/fixtures/cache-key-and-descriptor-fixtures.json"); + let operation_descriptor = read_json(&fixture_path); + let worker_hello = read_json(&worker_hello_path); + let cache_fixtures: FixtureBundle = serde_json::from_str(&read_text(&cache_fixture_path)).expect("fixture parse"); + + let input_schema = schema_map + .get("VID-IMPL-P00-003A-WAVEFORM-INPUT") + .expect("input schema"); + let operation_profile_schema = schema_map + .get("VID-IMPL-P00-003A-WAVEFORM-OPERATION-PROFILE") + .expect("profile schema"); + let hello_schema = schema_map + .get("VID-IMPL-P00-003A-WAVEFORM-WORKER-HELLO") + .expect("hello schema"); + let structured_schema = schema_map + .get("VID-IMPL-P00-003A-WAVEFORM-STRUCTURED-ERROR") + .expect("structured schema"); + let bulk_schema = schema_map + .get("VID-IMPL-P00-003A-WAVEFORM-BULK-DESCRIPTOR") + .expect("bulk schema"); + let artifact_schema = schema_map + .get("VID-IMPL-P00-003A-WAVEFORM-ARTIFACT") + .expect("artifact schema"); + + assert_json_valid(input_schema, &operation_descriptor, "valid operation descriptor"); + assert_json_valid(hello_schema, &worker_hello, "valid worker hello"); + if root.join("Video Localization/contracts/VID-IMPL-P00-003A/records/operation-profile.json").exists() { + let profile = read_json(&root.join("Video Localization/contracts/VID-IMPL-P00-003A/records/operation-profile.json")); + assert_json_valid(operation_profile_schema, &profile, "valid operation profile"); + } + + let mut missing = operation_descriptor.clone(); + let missing_obj = missing + .as_object_mut() + .expect("object operation descriptor"); + missing_obj.remove("operation_id"); + assert_json_rejects(input_schema, &missing, "missing required operation_id"); + + let mut unknown_root = operation_descriptor.clone(); + unknown_root + .as_object_mut() + .expect("object op") + .insert("forbidden_root".to_string(), json!("rejected")); + assert_json_rejects(input_schema, &unknown_root, "unknown root property"); + + let mut nested_unknown = operation_descriptor.clone(); + if let Some(port) = nested_unknown["input_ports"][0].as_object_mut() { + port.insert("forbidden_nested".to_string(), json!(0)); + } + assert_json_rejects(input_schema, &nested_unknown, "unknown nested property"); + + let mut bad_hello = worker_hello.clone(); + bad_hello + .as_object_mut() + .expect("hello object") + .insert("executable_path".to_string(), json!(r"C:\\ProgramData\\chocolatey\\ffprobe.exe")); + assert_json_rejects(hello_schema, &bad_hello, "hello executable path forbidden"); + + let profile_schema_value = read_json(&root.join("Video Localization/contracts/VID-IMPL-P00-003A/records/operation-profile.json")); + let mut bad_profile = profile_schema_value; + bad_profile + .as_object_mut() + .expect("object profile") + .remove("implementation_profile_id"); + assert_json_rejects(operation_profile_schema, &bad_profile, "missing profile id"); + + let mut malformed = Value::Null; + if let Some(first_case) = cache_fixtures.bulk_descriptor_positive_cases.first() { + malformed = first_case["descriptor"].clone(); + } + malformed + .as_object_mut() + .expect("malformed object") + .insert("descriptor_hash".to_string(), json!("")); + assert_json_rejects(bulk_schema, &malformed, "bulk descriptor hash required"); + + let malformed = serde_json::json!({ + "error_ref": {"namespace":"video.waveform","code":"VID-WAVEFORM-FAIL","version":"1"}, + "schema_id":"VID-IMPL-P00-003A-WAVEFORM-STRUCTURED-ERROR", + "schema_version":"0.1.0-p00", + "trace_id":"trace", + "correlation_id":"corr", + "subject":"subject", + "video_disposition":"VID-WAVEFORM-REVIEW", + "shared_state":"failed", + "error_category":"manual", + "retry_class":"manual", + "operation_stage":"review", + "safe_recovery":"retry", + "identity_refs":["job","attempt","dispatch","worker","publication"], + "details":["x","y","z","w"], + "applies_to":{"job_ref":"j","attempt_ref":"a","dispatch_ref":"d","worker_ref":"w"} + }); + assert_json_rejects(structured_schema, &malformed, "structured error with too many details"); + + let artifact = serde_json::json!({ + "artifact_id":"artifact-id", + "artifact_version":"0.1.0-p00", + "artifact_type":"waveform_artifact", + "output_schema_id":"VID-IMPL-P00-003A-WAVEFORM-ARTIFACT", + "completeness":"complete", + "integrity":{"algorithm":"sha-256","value":"A".repeat(64)}, + "size_bytes":1, + "component_inventory":["waveform"], + "producing":{ + "job_ref":"job", + "attempt_ref":"attempt", + "dispatch_ref":"dispatch", + "worker_ref":"worker", + "operation_id":wc::OPERATION_ID, + "operation_version":wc::OPERATION_VERSION, + "implementation_id":wc::IMPLEMENTATION_ID, + "implementation_profile_id":wc::IMPLEMENTATION_PROFILE_ID + }, + "input_digests":{ + "staged_copy_hash":"B".repeat(64), + "manifest_digest":"C".repeat(64), + "logical_source_ref":"source", + "staged_copy_hash_schema_ref":"VID-IMPL-P00-002B1-RESOURCE" + }, + "parameter_digests":{ + "argv":"D".repeat(64), + "limits":"E".repeat(64), + "cache_key":"F".repeat(64) + }, + "resource_digests":{"resource":"A".repeat(64),"schema":"B".repeat(64)}, + "policy_digests":{"policy":"C".repeat(64),"schema":"D".repeat(64)}, + "cache_digests":{"schema_bundle":"E".repeat(64),"control_protocol":"F".repeat(64),"cache_key_schema":"cache-schema-id"}, + "output_port":"waveform_output_port", + "staging":{"state":"staged-private","path":"C:/tmp/staged","delete_on_stale":true,"quarantine_on_failure":true}, + "lineage":{"job_ref":"job","attempt_ref":"attempt","dispatch_ref":"dispatch","worker_ref":"worker","publication_ref":"publication"}, + "publication_id":"publication", + "fencing":{"required":true,"active_token":"token"}, + "cache_key":{"schema":"cache-key-schema","digest":"A".repeat(64)}, + "bulk_descriptor_ref":{"reference":"desc-ref","digest":"B".repeat(64),"schema":"waveform-bulk-descriptor"} + }); + assert_json_valid(artifact_schema, &artifact, "valid artifact contract"); + let mut bad_artifact = artifact; + bad_artifact + .as_object_mut() + .expect("artifact object") + .insert("completeness".to_string(), json!("partial")); + assert_json_rejects(artifact_schema, &bad_artifact, "artifact partial completeness"); +} + +#[test] +fn manifest_bound_text_artifacts_are_utf8_and_exactly_one_final_lf() { + let root = workspace_root(); + for path in manifest_bound_text_paths() { + let full_path = workspace_path(&root, &path); + assert!( + bytes_are_utf8_and_exact_final_lf(&full_path), + "artifact must be UTF-8 with no BOM/CR and exactly one final LF: {}", + full_path.display() + ); + } +} + +#[test] +fn fixture_cache_key_positive_and_negative_cases_are_executed() { + let root = workspace_root(); + let contract_fixture_path = root.join("Video Localization/contracts/VID-IMPL-P00-003A/fixtures/cache-key-and-descriptor-fixtures.json"); + let test_fixture_path = root.join("Video Localization/testing/implementation/VID-IMPL-P00-003A/waveform-fixtures.json"); + let contract_fixtures: FixtureBundle = serde_json::from_str(&read_text(&contract_fixture_path)).expect("contract fixture parse"); + let test_fixtures: FixtureBundle = serde_json::from_str(&read_text(&test_fixture_path)).expect("implementation fixture parse"); + + assert_eq!(contract_fixtures.cache_key_positive_cases.len(), test_fixtures.cache_key_positive_cases.len()); + assert_eq!(contract_fixtures.cache_key_negative_cases.len(), test_fixtures.cache_key_negative_cases.len()); + + for case in &contract_fixtures.cache_key_positive_cases { + let profile = cache_profile_from_case(case); + let preimage = wc::cache_key_preimage(&profile).expect("cache preimage"); + let digest = wc::cache_key_digest(&profile).expect("cache digest"); + if let Some(expected_prefix) = case.get("expected_cache_key_prefix").and_then(Value::as_str) { + assert_eq!(expected_prefix.as_bytes(), wc::CACHE_KEY_PREFIX); + } + if let Some(expected_digest) = cache_key_expected_digest(&case) { + assert_eq!(expected_digest.to_lowercase(), digest); + } + } + + for case in &contract_fixtures.cache_key_negative_cases { + let mut profile = cache_profile_from_case(case); + let invalid_seed = case.get("invalid_seed").and_then(Value::as_bool).unwrap_or(false); + let missing_seed = case.get("missing_seed").and_then(Value::as_bool).unwrap_or(false); + if invalid_seed { + profile.seed = String::new(); + } + if missing_seed { + profile.seed = " ".to_string(); + } + assert!(wc::cache_key_digest(&profile).is_err()); + } +} + +#[test] +fn fixture_bulk_descriptor_positive_and_negative_cases_are_executed() { + let root = workspace_root(); + let contract_fixture_path = root.join("Video Localization/contracts/VID-IMPL-P00-003A/fixtures/cache-key-and-descriptor-fixtures.json"); + let test_fixture_path = root.join("Video Localization/testing/implementation/VID-IMPL-P00-003A/waveform-fixtures.json"); + let contract_fixtures: FixtureBundle = serde_json::from_str(&read_text(&contract_fixture_path)).expect("contract fixture parse"); + let test_fixtures: FixtureBundle = serde_json::from_str(&read_text(&test_fixture_path)).expect("implementation fixture parse"); + + assert_eq!(contract_fixtures.bulk_descriptor_positive_cases.len(), test_fixtures.bulk_descriptor_positive_cases.len()); + assert_eq!(contract_fixtures.bulk_descriptor_negative_cases.len(), test_fixtures.bulk_descriptor_negative_cases.len()); + + for case in &contract_fixtures.bulk_descriptor_positive_cases { + let descriptor: wc::WaveformBulkDescriptor = + serde_json::from_value(case["descriptor"].clone()).expect("descriptor parse"); + let payload = fixture_case_payload(descriptor.length as usize); + let report = wc::validate_bulk_payload_and_descriptor_linkage(&payload, &descriptor).expect("positive linkage"); + assert_eq!(wc::sha256_hex_of_bytes(&payload), report.payload_digest); + if let Some(expected_descriptor_digest) = bulk_expected_descriptor_digest(&case) { + assert_eq!( + expected_descriptor_digest.to_lowercase(), + descriptor + .descriptor_hash + .as_ref() + .expect("descriptor hash present") + .to_lowercase() + ); + assert_eq!(expected_descriptor_digest.to_lowercase(), report.descriptor_digest); + } + } + + for case in &contract_fixtures.bulk_descriptor_negative_cases { + let mut descriptor: wc::WaveformBulkDescriptor = + serde_json::from_value(case["descriptor"].clone()).expect("descriptor parse"); + let reason = case.get("reason").and_then(Value::as_str).unwrap_or(""); + let mut payload = fixture_case_payload(descriptor.length as usize); + if reason == "missing-descriptor-hash" { + descriptor.descriptor_hash = None; + } + if reason == "chunk-list" { + descriptor.chunk_hashes_omitted = false; + } + if reason == "mismatched-length" { + payload.truncate((descriptor.length.saturating_sub(1)).try_into().unwrap_or(0)); + } + assert!(wc::validate_bulk_payload_and_descriptor_linkage(&payload, &descriptor).is_err()); + } + assert_ne!( + read_text(&contract_fixture_path), + read_text(&test_fixture_path), + "testing fixture must remain role-specific, not byte-identical" + ); + assert!(test_fixtures.bulk_descriptor_positive_cases.len() >= 1); + assert!(test_fixtures.bulk_descriptor_negative_cases.len() >= 1); +} + +#[test] +fn fixture_representation_timeline_downmix_vectors_are_bound_and_mutated() { + let root = workspace_root(); + let fixture_path = root.join("Video Localization/testing/implementation/VID-IMPL-P00-003A/waveform-fixtures.json"); + let test_fixtures: FixtureBundle = serde_json::from_str(&read_text(&fixture_path)).expect("implementation fixture parse"); + + for case in &test_fixtures.representation_timeline_downmix_cases { + let kind = case.get("kind").and_then(Value::as_str).unwrap_or("positive"); + let mut descriptor = sample_bulk_descriptor(); + if let Some(descriptor_overlay) = case.get("descriptor") { + apply_bulk_descriptor_overrides(&mut descriptor, descriptor_overlay); + } + let payload = fixture_case_payload(descriptor.length as usize); + descriptor.integrity.value = wc::sha256_hex_of_bytes(&payload); + if kind == "positive" { + descriptor.descriptor_hash = Some( + wc::bulk_descriptor_digest(&descriptor).expect("deterministic descriptor digest"), + ); + let report = wc::validate_bulk_payload_and_descriptor_linkage(&payload, &descriptor) + .expect("representation/timeline/downmix positive linkage"); + assert_eq!(wc::sha256_hex_of_bytes(&payload), report.payload_digest); + } else { + assert!(wc::validate_bulk_payload_and_descriptor_linkage(&payload, &descriptor).is_err()); + } + } + assert!(!test_fixtures.representation_timeline_downmix_cases.is_empty()); +} + +#[test] +fn fixture_hostile_metadata_vectors_and_mutations_fail_closed() { + let root = workspace_root(); + let fixture_path = root.join("Video Localization/testing/implementation/VID-IMPL-P00-003A/waveform-fixtures.json"); + let test_fixtures: FixtureBundle = serde_json::from_str(&read_text(&fixture_path)).expect("implementation fixture parse"); + assert!(!test_fixtures.hostile_metadata_cases.is_empty()); + + for case in &test_fixtures.hostile_metadata_cases { + let kind = case.get("kind").and_then(Value::as_str).unwrap_or("negative"); + let mut descriptor = sample_bulk_descriptor(); + let mut payload = fixture_case_payload(descriptor.length as usize); + if let Some(overrides) = case.get("descriptor") { + apply_bulk_descriptor_overrides(&mut descriptor, overrides); + if let Some(integrity) = case.get("payload_mutation").and_then(Value::as_str) { + if integrity == "corrupt-payload" { + payload[0] = payload[0].wrapping_add(1); + descriptor.integrity.value = wc::sha256_hex_of_bytes(&payload); + } + } + } + if kind == "positive" { + descriptor.descriptor_hash = Some( + wc::bulk_descriptor_digest(&descriptor).expect("deterministic descriptor digest"), + ); + assert!(wc::validate_bulk_payload_and_descriptor_linkage(&payload, &descriptor).is_ok()); + } else { + if descriptor.integrity.value == "not-a-digest" { + descriptor.integrity.value = "not-a-digest".to_string(); + } + assert!( + wc::validate_bulk_payload_and_descriptor_linkage(&payload, &descriptor).is_err(), + "{} should fail", + case.get("case_id").and_then(Value::as_str).unwrap_or("unnamed") + ); + } + } +} + +#[test] +fn fixture_interruption_and_partial_write_vectors_are_executed() { + let root = workspace_root(); + let fixture_path = root.join("Video Localization/testing/implementation/VID-IMPL-P00-003A/waveform-fixtures.json"); + let test_fixtures: FixtureBundle = serde_json::from_str(&read_text(&fixture_path)).expect("implementation fixture parse"); + assert!(!test_fixtures.interruption_cases.is_empty()); + + let (attempt, payload) = sample_publication_attempt(); + let payload_digest = wc::sha256_hex_of_bytes(&payload); + let whole_object = wc::publication_whole_object_hash(&attempt, &payload_digest) + .expect("publication whole object digest"); + let receipt = wc::validate_publication_lifecycle(&attempt, &payload, &whole_object) + .expect("publication commit receipt"); + + for case in &test_fixtures.interruption_cases { + let kind = case.get("kind").and_then(Value::as_str).unwrap_or("negative"); + let case_id = case.get("case_id").and_then(Value::as_str).unwrap_or("unnamed"); + if kind == "cancelled" { + let state = wc::reconcile_terminal_state( + Some("VID-WAVEFORM-CANCELLED"), + Some(100), + Some(0), + Some(receipt.journal_identity()), + ) + .expect(case_id); + assert_eq!(state, wc::WaveformTerminalState::Terminal("Cancelled".to_string())); + continue; + } + + if kind == "crash" { + assert!( + wc::reconcile_terminal_state( + Some("VID-WAVEFORM-CRASH"), + Some(0), + Some(0), + Some(receipt.journal_identity()), + ) + .is_err(), + "{} must reject hostile/unexpected disposition", + case_id + ); + continue; + } + + if kind == "deadline" { + let state = wc::reconcile_terminal_state( + Some("VID-WAVEFORM-DEADLINE-EXCEEDED"), + Some(10), + Some(20), + None, + ) + .expect(case_id); + assert_eq!(state, wc::WaveformTerminalState::Terminal("TimedOut".to_string())); + assert!(wc::reconcile_terminal_state( + Some("VID-WAVEFORM-DEADLINE-EXCEEDED"), + Some(10), + Some(5), + None + ) + .is_err()); + continue; + } + + if kind == "partial-write" { + let mut truncated_payload = payload.clone(); + let truncated_len = payload.len().saturating_sub(1); + truncated_payload.truncate(truncated_len); + let mut partial_descriptor = sample_bulk_descriptor(); + partial_descriptor.length = truncated_len as u64; + partial_descriptor.descriptor_hash = Some( + wc::bulk_descriptor_digest(&partial_descriptor) + .expect("descriptor digest"), + ); + assert!(wc::validate_bulk_payload_and_descriptor_linkage(&truncated_payload, &partial_descriptor).is_err()); + continue; + } + + panic!("unknown interruption vector kind in fixture: {}", kind); + } +} + +#[test] +fn fixture_publication_journal_failures_are_differentiated() { + let root = workspace_root(); + let fixture_path = root.join("Video Localization/testing/implementation/VID-IMPL-P00-003A/waveform-fixtures.json"); + let test_fixtures: FixtureBundle = serde_json::from_str(&read_text(&fixture_path)).expect("implementation fixture parse"); + assert!(!test_fixtures.publication_journal_cases.is_empty()); + + let (attempt, payload) = sample_publication_attempt(); + let payload_digest = wc::sha256_hex_of_bytes(&payload); + let whole_object = wc::publication_whole_object_hash(&attempt, &payload_digest) + .expect("publication whole object digest"); + let mut receipt = wc::validate_publication_lifecycle(&attempt, &payload, &whole_object) + .expect("publication commit receipt"); + + for case in &test_fixtures.publication_journal_cases { + let kind = case.get("kind").and_then(Value::as_str).unwrap_or("negative"); + if kind == "valid" { + assert_eq!( + wc::reconcile_terminal_state(None, Some(100), Some(50), Some(receipt.journal_identity())) + .expect("valid journal"), + wc::WaveformTerminalState::Succeeded(receipt.clone()) + ); + continue; + } + + if kind == "unrecorded" { + let unknown_identity = "0".repeat(64); + assert!(wc::reconcile_terminal_state(None, Some(100), Some(50), Some(&unknown_identity)).is_err()); + continue; + } + + if kind == "fabricated" { + let mut bytes = receipt.journal_identity().as_bytes().to_vec(); + bytes[0] = if bytes[0] == b'0' { b'1' } else { b'0' }; + let fabricated_identity = String::from_utf8(bytes).expect("ascii identity"); + assert!(wc::reconcile_terminal_state(None, Some(100), Some(50), Some(&fabricated_identity)).is_err()); + continue; + } + + if kind == "mismatched" { + let mut mismatched = receipt.journal_identity().to_string(); + mismatched.push('0'); + assert!(wc::reconcile_terminal_state(None, Some(100), Some(50), Some(&mismatched)).is_err()); + continue; + } + + if kind == "revoked" { + assert!(wc::revoke_publication_commit(&receipt)); + assert!(wc::reconcile_terminal_state(None, Some(100), Some(50), Some(receipt.journal_identity())) + .is_err()); + // Rebuild a fresh receipt for any remaining negative checks. + let receipt_restored = wc::validate_publication_lifecycle(&attempt, &payload, &whole_object) + .expect("publication commit receipt"); + receipt = receipt_restored; + continue; + } + + panic!( + "unknown publication journal vector kind in fixture: {}", + case.get("case_id").and_then(Value::as_str).unwrap_or("unnamed") + ); + } +} + +#[test] +fn fixture_stale_epoch_fence_lease_cases_fail_closed() { + let root = workspace_root(); + let fixture_path = root.join("Video Localization/testing/implementation/VID-IMPL-P00-003A/waveform-fixtures.json"); + let test_fixtures: FixtureBundle = serde_json::from_str(&read_text(&fixture_path)).expect("implementation fixture parse"); + assert!(!test_fixtures.stale_epoch_fence_lease_cases.is_empty()); + + let (attempt, payload) = sample_publication_attempt(); + let payload_digest = wc::sha256_hex_of_bytes(&payload); + let whole_object = wc::publication_whole_object_hash(&attempt, &payload_digest) + .expect("publication whole object digest"); + + for case in &test_fixtures.stale_epoch_fence_lease_cases { + let kind = case.get("kind").and_then(Value::as_str).unwrap_or("negative"); + let case_id = case.get("case_id").and_then(Value::as_str).unwrap_or("unnamed"); + let mut attempt = attempt.clone(); + let expected_error = case.get("expect_error").and_then(Value::as_bool).unwrap_or(true); + + if kind == "valid" { + let result = wc::validate_publication_lifecycle(&attempt, &payload, &whole_object); + if expected_error { + assert!(result.is_err(), "{}", case_id); + } else { + assert!(result.is_ok(), "{}", case_id); + } + continue; + } + + if kind == "stale-epoch" { + attempt.lease.lease_epoch = attempt.lease.minimum_acceptable_lease_epoch.saturating_sub(1); + } + + if kind == "fence-mismatch" { + attempt.lease.observed_fence_token = "stale-fence".to_string(); + } + + if kind == "lease-mismatch" { + attempt.descriptor.lease_id = "other-lease-id".to_string(); + } + + if kind == "attempt-mismatch" { + attempt.descriptor.attempt_id = "other-attempt-id".to_string(); + } + + if let Some(fence) = case.get("source_publication_fence").and_then(Value::as_str) { + attempt.descriptor.source_publication_fence = fence.to_string(); + } + + let result = wc::validate_publication_lifecycle(&attempt, &payload, &whole_object); + assert!(result.is_err(), "{}", case_id); + } +} + +#[test] +fn retry_profile_enforces_attempt_ceiling_and_cumulative_limits() { + let profile = sample_retry_profile(); + let base_usage = wc::WaveformRetryUsage { + attempts: 1, + wall_seconds: 1, + cpu_seconds: 1, + ram_bytes: 1, + staging_bytes: 1, + cost: 1, + }; + let decision = profile + .evaluate_retry_decision("VID-WAVEFORM-WORKER-TRANSIENT", &base_usage) + .expect("allowed first retry"); + assert_eq!(decision.next_attempt, 2); + assert_eq!(decision.wait_millis, 500); + + let attempt_ceiling = wc::WaveformRetryUsage { + attempts: 2, + wall_seconds: 1, + cpu_seconds: 1, + ram_bytes: 1, + staging_bytes: 1, + cost: 1, + }; + assert!(profile.evaluate_retry_decision("VID-WAVEFORM-WORKER-TRANSIENT", &attempt_ceiling).is_err()); + + assert!(profile.validate_cumulative_usage(&wc::WaveformRetryUsage { + attempts: 1, + wall_seconds: profile.cumulative_wall_seconds + 1, + cpu_seconds: 1, + ram_bytes: 1, + staging_bytes: 1, + cost: 1, + }).is_err()); + + assert!(profile.validate_cumulative_usage(&wc::WaveformRetryUsage { + attempts: 1, + wall_seconds: 1, + cpu_seconds: profile.cumulative_cpu_seconds + 1, + ram_bytes: 1, + staging_bytes: 1, + cost: 1, + }).is_err()); + + assert!(profile.validate_cumulative_usage(&wc::WaveformRetryUsage { + attempts: 1, + wall_seconds: 1, + cpu_seconds: 1, + ram_bytes: profile.cumulative_ram_bytes + 1, + staging_bytes: 1, + cost: 1, + }).is_err()); + + assert!(profile.validate_cumulative_usage(&wc::WaveformRetryUsage { + attempts: 1, + wall_seconds: 1, + cpu_seconds: 1, + ram_bytes: 1, + staging_bytes: profile.cumulative_staging_bytes + 1, + cost: 1, + }).is_err()); + + assert!(profile.validate_cumulative_usage(&wc::WaveformRetryUsage { + attempts: 1, + wall_seconds: 1, + cpu_seconds: 1, + ram_bytes: 1, + staging_bytes: 1, + cost: profile.cost_ceiling + 1, + }).is_err()); + + assert!(profile + .evaluate_retry_decision("VID-WAVEFORM-REVIEW", &base_usage) + .is_err()); +} + +#[test] +fn terminal_reconciliation_map_requires_authoritative_deadline_and_receipt() { + let (mut attempt, payload) = sample_publication_attempt(); + attempt.attempt_id = "terminal-attempt-unique-001".to_string(); + attempt.descriptor.attempt_id = attempt.attempt_id.clone(); + attempt.lease.lease_id = "terminal-lease-unique-001".to_string(); + attempt.descriptor.lease_id = attempt.lease.lease_id.clone(); + let terminal_descriptor_hash = wc::bulk_descriptor_digest(&attempt.descriptor) + .expect("terminal descriptor digest"); + attempt.descriptor.descriptor_hash = Some(terminal_descriptor_hash); + let payload_digest = wc::sha256_hex_of_bytes(&payload); + let whole_object = wc::publication_whole_object_hash(&attempt, &payload_digest) + .expect("whole object digest"); + let receipt = wc::validate_publication_lifecycle(&attempt, &payload, &whole_object) + .expect("publication commit receipt"); + assert!(wc::reconcile_terminal_state(Some("VID-WAVEFORM-DEADLINE-EXCEEDED"), Some(10), Some(9), Some(receipt.journal_identity())).is_err()); + let timed_out = wc::reconcile_terminal_state( + Some("VID-WAVEFORM-DEADLINE-EXCEEDED"), + Some(10), + Some(11), + Some(receipt.journal_identity()), + ) + .expect("timed out mapping"); + assert_eq!(timed_out, wc::WaveformTerminalState::Terminal("TimedOut".to_string())); + let timed_out = + wc::reconcile_terminal_state( + Some("VID-WAVEFORM-DEADLINE-EXCEEDED"), + Some(10), + Some(11), + None, + ) + .expect("timed out mapping without receipt"); + assert_eq!(timed_out, wc::WaveformTerminalState::Terminal("TimedOut".to_string())); + assert!(wc::reconcile_terminal_state(Some("VID-WAVEFORM-DEADLINE-EXCEEDED"), None, None, Some(receipt.journal_identity())).is_err()); + assert!(wc::reconcile_terminal_state( + Some("VID-WAVEFORM-WORKER-TRANSIENT"), + Some(10), + Some(11), + Some(receipt.journal_identity()), + ) + .is_err()); + assert!(wc::reconcile_terminal_state(Some("VID-WAVEFORM-DEADLINE-EXCEEDED"), Some(10), None, Some(receipt.journal_identity())).is_err()); + assert!(wc::reconcile_terminal_state( + Some("VID-WAVEFORM-DOES-NOT-EXIST"), + Some(10), + Some(11), + Some(receipt.journal_identity()), + ).is_err()); + assert_eq!( + wc::reconcile_terminal_state(None, Some(100), Some(50), Some(receipt.journal_identity())) + .expect("receipt success"), + wc::WaveformTerminalState::Succeeded(receipt.clone()) + ); + assert_eq!( + wc::reconcile_terminal_state(None, None, None, Some(receipt.journal_identity())) + .expect("deadline-less success"), + wc::WaveformTerminalState::Succeeded(receipt.clone()) + ); + assert!( + wc::reconcile_terminal_state(None, Some(10), Some(20), None).is_err(), + "expired deadline cannot succeed without authoritative receipt" + ); + assert!( + wc::reconcile_terminal_state(None, Some(100), Some(50), Some("e3f4a5b6c7d8e90123456789abcdef0123456789abcdef0123456789abcdef0123")) + .is_err(), + "unrecorded journal identity must fail" + ); + + let mut mismatched = receipt.journal_identity().as_bytes().to_vec(); + if let Some(first_byte) = mismatched.first_mut() { + *first_byte = if *first_byte == b'0' { b'1' } else { b'0' }; + } + let mismatched_identity = String::from_utf8(mismatched).expect("utf8 bytes"); + assert!( + wc::reconcile_terminal_state(None, Some(100), Some(50), Some(&mismatched_identity)) + .is_err(), + "mismatched journal identity must fail" + ); + let cloned_receipt = receipt.clone(); + assert!(wc::revoke_publication_commit(&receipt)); + assert!(wc::reconcile_terminal_state(None, Some(100), Some(50), Some(cloned_receipt.journal_identity())) + .is_err(), "removed journal entry must fail"); +} + +#[test] +fn publication_lifecycle_validates_atomic_commit_and_lineage_controls() { + let (attempt, payload) = sample_publication_attempt(); + let payload_digest = wc::sha256_hex_of_bytes(&payload); + let whole_object = wc::publication_whole_object_hash(&attempt, &payload_digest).expect("whole object digest"); + let receipt = wc::validate_publication_lifecycle(&attempt, &payload, &whole_object).expect("publication commit receipt"); + assert_eq!(wc::reconcile_terminal_state(None, Some(100), Some(50), Some(receipt.journal_identity())) + .expect("succeeded with receipt") + .clone(), + wc::WaveformTerminalState::Succeeded(receipt.clone()) + ); + + let mut cache_authority = attempt.clone(); + cache_authority.lease.cache_authority = true; + assert!(wc::validate_publication_lifecycle(&cache_authority, &payload, &whole_object).is_err()); + + let mut stale_lease = attempt.clone(); + stale_lease.lease.lease_epoch = stale_lease.lease.minimum_acceptable_lease_epoch.saturating_sub(1); + assert!(wc::validate_publication_lifecycle(&stale_lease, &payload, &whole_object).is_err()); + + let mut bad_fence = attempt.clone(); + bad_fence.lease.observed_fence_token = "bad-token".to_string(); + assert!(wc::validate_publication_lifecycle(&bad_fence, &payload, &whole_object).is_err()); + + let mut mismatch_attempt = attempt.clone(); + mismatch_attempt.descriptor.attempt_id = "other-attempt".to_string(); + assert!(wc::validate_publication_lifecycle(&mismatch_attempt, &payload, &whole_object).is_err()); + + let mut mismatch_lease = attempt.clone(); + mismatch_lease.descriptor.lease_id = "other-lease".to_string(); + assert!(wc::validate_publication_lifecycle(&mismatch_lease, &payload, &whole_object).is_err()); + + let mut malformed_hash = attempt.clone(); + malformed_hash.lease.staged_copy_hash = "not-hex".to_string(); + assert!(wc::validate_publication_lifecycle(&malformed_hash, &payload, &whole_object).is_err()); + + let mut staged_hash_mismatch = attempt.clone(); + staged_hash_mismatch.lease.staged_copy_hash = "f".repeat(64); + let expected = wc::publication_whole_object_hash(&staged_hash_mismatch, &payload_digest) + .expect("valid staged hash whole object"); + assert!(wc::validate_publication_lifecycle(&staged_hash_mismatch, &payload, &expected).is_err()); + + let mut source_mutated = attempt.clone(); + let mut mutated_payload = payload.clone(); + mutated_payload[0] = mutated_payload[0].wrapping_add(1); + let mutated_payload_digest = wc::sha256_hex_of_bytes(&mutated_payload); + let expected_for_source_mutation = + wc::publication_whole_object_hash(&source_mutated, &mutated_payload_digest) + .expect("source mutation whole object"); + assert!(wc::validate_publication_lifecycle(&source_mutated, &mutated_payload, &expected_for_source_mutation).is_err()); + + let mut mutated_payload = payload.clone(); + mutated_payload[0] = mutated_payload[0].wrapping_add(1); + let mutated_digest = wc::sha256_hex_of_bytes(&mutated_payload); + let mutated_object = wc::publication_whole_object_hash(&attempt, &mutated_digest).expect("mutated whole object digest"); + assert!(wc::validate_publication_lifecycle(&attempt, &mutated_payload, &mutated_object).is_err()); +} + +#[test] +fn fixture_opaque_handle_substitution_and_path_escape_vectors_are_rejected() { + let root = workspace_root(); + let fixture_path = root.join("Video Localization/testing/implementation/VID-IMPL-P00-003A/waveform-fixtures.json"); + let test_fixtures: FixtureBundle = serde_json::from_str(&read_text(&fixture_path)).expect("implementation fixture parse"); + assert!(!test_fixtures.opaque_handle_substitution_cases.is_empty()); + let case_count = test_fixtures.opaque_handle_substitution_cases.len(); + + for case in &test_fixtures.opaque_handle_substitution_cases { + let mut descriptor = sample_bulk_descriptor(); + let case_id = case.get("case_id").and_then(Value::as_str).unwrap_or("unnamed"); + let kind = case.get("kind").and_then(Value::as_str).unwrap_or("negative"); + let payload = fixture_case_payload(descriptor.length as usize); + if let Some(overrides) = case.get("descriptor") { + apply_bulk_descriptor_overrides(&mut descriptor, overrides); + } + descriptor.integrity.value = wc::sha256_hex_of_bytes(&payload); + descriptor.descriptor_hash = Some( + wc::bulk_descriptor_digest_unchecked(&descriptor), + ); + + match kind { + "positive" => { + assert!( + wc::validate_bulk_payload_and_descriptor_linkage(&payload, &descriptor).is_ok(), + "{} should allow opaque handle {}", + case_id, + descriptor.handle_identity + ); + } + "negative" => { + let result = + wc::validate_bulk_payload_and_descriptor_linkage(&payload, &descriptor); + assert!(result.is_err(), "{} must reject unsafe handle identity", case_id); + } + _ => panic!("unknown opaque handle case kind in fixture: {}", case_id), + } + } + + assert!( + case_count > 0, + "opaque handle fixture vectors must contain at least one case" + ); +} + +#[test] +fn fixture_cache_corruption_and_deletion_rejects_without_publication_authority() { + let root = workspace_root(); + let fixture_path = root.join("Video Localization/testing/implementation/VID-IMPL-P00-003A/waveform-fixtures.json"); + let test_fixtures: FixtureBundle = serde_json::from_str(&read_text(&fixture_path)).expect("implementation fixture parse"); + assert!(!test_fixtures.cache_integrity_cases.is_empty()); + + let (attempt, payload) = sample_publication_attempt(); + let payload_digest = wc::sha256_hex_of_bytes(&payload); + let whole_object = wc::publication_whole_object_hash(&attempt, &payload_digest) + .expect("publication whole object hash"); + + for case in &test_fixtures.cache_integrity_cases { + let case_id = case.get("case_id").and_then(Value::as_str).unwrap_or("unnamed"); + let kind = case.get("kind").and_then(Value::as_str).unwrap_or("negative"); + let mut mutated_attempt = attempt.clone(); + + match kind { + "cache-corrupt-hash" => { + mutated_attempt.lease.staged_copy_hash = "f".repeat(64); + } + "cache-deleted" => { + mutated_attempt.lease.staged_copy_length = 0; + } + "cache-non-authority" => { + mutated_attempt.lease.cache_authority = true; + } + _ => continue, + } + + assert!( + wc::validate_publication_lifecycle(&mutated_attempt, &payload, &whole_object).is_err(), + "{} should fail publication lifecycle with cache integrity mismatch", + case_id + ); + } +} + +#[test] +fn fixture_publication_atomicity_and_cross_volume_reuse_are_rejected() { + let root = workspace_root(); + let fixture_path = root.join("Video Localization/testing/implementation/VID-IMPL-P00-003A/waveform-fixtures.json"); + let test_fixtures: FixtureBundle = serde_json::from_str(&read_text(&fixture_path)).expect("implementation fixture parse"); + assert!(!test_fixtures.publication_atomicity_cases.is_empty()); + + let (attempt, payload) = sample_publication_attempt(); + let payload_digest = wc::sha256_hex_of_bytes(&payload); + let whole_object = wc::publication_whole_object_hash(&attempt, &payload_digest) + .expect("publication whole object digest"); + let original = wc::validate_publication_lifecycle(&attempt, &payload, &whole_object) + .expect("publication commit receipt"); + + for case in &test_fixtures.publication_atomicity_cases { + let case_id = case.get("case_id").and_then(Value::as_str).unwrap_or("unnamed"); + let kind = case.get("kind").and_then(Value::as_str).unwrap_or("negative"); + if kind == "duplicate" { + assert!( + wc::validate_publication_lifecycle(&attempt, &payload, &whole_object).is_err(), + "{} must reject duplicate publication for the same attempt", + case_id + ); + continue; + } + + if kind == "cross-volume" { + let mut cross_attempt = attempt.clone(); + cross_attempt.lease.lease_id = "lease-cross-volume-001".to_string(); + cross_attempt.descriptor.lease_id = cross_attempt.lease.lease_id.clone(); + let cross_payload_digest = wc::sha256_hex_of_bytes(&payload); + let cross_whole_object = wc::publication_whole_object_hash(&cross_attempt, &cross_payload_digest) + .expect("cross volume whole object hash"); + assert!( + wc::validate_publication_lifecycle(&cross_attempt, &payload, &cross_whole_object).is_err(), + "{} must reject cross-volume publication reuse", + case_id + ); + continue; + } + + panic!("unknown publication atomicity vector kind in fixture: {}", case_id); + } + + assert!(wc::revoke_publication_commit(&original)); + let replay = wc::validate_publication_lifecycle(&attempt, &payload, &whole_object) + .expect("publication may replay after revoke"); + assert!(wc::revoke_publication_commit(&replay)); +}