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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion evidence/compatibility-environment-v1.10.17.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
{
"id": "native-framing-draft",
"reference": "spec/v1.9/iicp-framing.md",
"sha256": "803a0a20620df53c8bbcc7534d05e8ddd391d0d3d55752541bc1478764e914cf"
"sha256": "75a11f6d5c75f2ee77827989d2180ff98add5c4b44ae979f8503a567e8fc1bf4"
}
],
"identity_and_security_profiles": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
{
"path": "native-framing-v1.json",
"fixture_version": "1.0.0-draft",
"sha256": "795516349af7b8b1167357f12add10e56b467b80d1441c898dd48c97f3da1672"
"sha256": "945c5086f0f7173beb7708478a36be74c0a4256ca4a4efd1a855e0e0057c3376"
}
]
}
100 changes: 99 additions & 1 deletion research/native-ai-infrastructure/fixtures/native-framing-v1.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"fixture_version": "1.0.0-draft",
"status": "implementation-backed-pre-ratification",
"purpose": "Cross-implementation native framing vectors for the current ordered-stream binding. They cover bounded frame decoding only; dispatch, TLS, lifecycle, experimental relay opcodes, logical fragmentation and unsupported QUIC behavior are outside this fixture.",
"purpose": "Cross-implementation native framing vectors for the current ordered-stream binding. They cover bounded frame decoding and the fail-closed stable task-session type boundary. Dispatch direction, TLS, lifecycle, dedicated experimental relay sessions, logical fragmentation and unsupported QUIC behavior remain outside this fixture.",
"frame": {
"framing_version": 1,
"header_bytes": 12,
Expand Down Expand Up @@ -48,6 +48,33 @@
"max_payload_bytes": 16777216,
"length_semantics": "payload_bytes_excluding_12_byte_header"
},
"stable_task_profile": {
"status": "implementation_backed_pre_ratification",
"accepted_message_types": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
13,
14
],
"conflicted_message_types": [
11,
12
],
"conflict": "0x0B/0x0C are CONTROL/ADVERTISE in the draft registry but RELAY_BIND/RELAY_ACK in maintained relay experiments; stable task sessions reject both bytes before proportional allocation.",
"relay_boundary": "Experimental relay sessions remain isolated on their dedicated transport and do not count as stable task-profile conformance.",
"extension_boundary": "0xF0-0xFE require negotiated extension state; the current stable task profile negotiates none and rejects them before proportional allocation.",
"production_security_disposition": "open_qualify_or_exclude",
"plaintext_scope": "development_only",
"stable_claim": "not_admitted"
},
"scenarios": [
{
"name": "ping_empty",
Expand Down Expand Up @@ -137,5 +164,76 @@
"reason": "payload_too_large"
}
}
],
"stable_task_type_scenarios": [
{
"name": "init_is_in_stable_task_profile",
"message_type": 1,
"expected": {
"outcome": "accept"
}
},
{
"name": "call_is_in_stable_task_profile",
"message_type": 5,
"expected": {
"outcome": "accept"
}
},
{
"name": "observe_is_in_stable_task_profile",
"message_type": 13,
"expected": {
"outcome": "accept"
}
},
{
"name": "zero_is_invalid",
"message_type": 0,
"expected": {
"outcome": "reject",
"reason": "invalid_type"
}
},
{
"name": "control_relay_bind_collision_is_rejected",
"message_type": 11,
"expected": {
"outcome": "reject",
"reason": "conflicted_type"
}
},
{
"name": "advertise_relay_ack_collision_is_rejected",
"message_type": 12,
"expected": {
"outcome": "reject",
"reason": "conflicted_type"
}
},
{
"name": "future_core_type_is_unknown",
"message_type": 15,
"expected": {
"outcome": "reject",
"reason": "unknown_type"
}
},
{
"name": "unnegotiated_private_extension_is_rejected",
"message_type": 240,
"expected": {
"outcome": "reject",
"reason": "unsupported_extension"
}
},
{
"name": "maximum_type_is_invalid",
"message_type": 255,
"expected": {
"outcome": "reject",
"reason": "invalid_type"
}
}
]
}
16 changes: 14 additions & 2 deletions spec/v1.9/iicp-framing.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# IICP Binary Framing Layer

**Document**: `spec/iicp-framing.md`
**Version**: 0.1.10-draft
**Version**: 0.1.11-draft
**Date**: 2026-08-28
**Status**: Draft — NOT YET RATIFIED (see §12)
**Authority**: Protocol Steward
Expand Down Expand Up @@ -81,6 +81,10 @@ Receivers that receive an unknown Type in the range 0x0F–0xEF MUST send a
`CLOSE` frame with error code `unknown_type` and close the connection. Receivers that
receive a Type in the CUSTOM range (0xF0–0xFE) and have not negotiated that type
via INIT MUST send a `CLOSE` frame with error code `unsupported_extension`.
The receiver MUST validate the Type after the fixed header and before allocating
or waiting for a buffer proportional to Length. The current stable task-session
profile accepts `0x01`–`0x0A` and `0x0D`–`0x0E`. It rejects `0x0B`/`0x0C` with
`conflicted_type` until the pre-ratification relay collision in §3 is resolved.

#### Flags (1 byte)

Expand Down Expand Up @@ -162,6 +166,12 @@ The 256-value type byte is partitioned as follows:
> support for any of these four messages on `0x0B`/`0x0C`. Existing relay use
> remains experimental and cannot count as stable framing conformance.

The maintained relay experiment uses a dedicated session implementation. Its
`RELAY_BIND`/`RELAY_ACK` frames MUST NOT enter the stable task-session decoder,
and rejection of `0x0B`/`0x0C` there does not alter the isolated experimental
relay behavior. Type direction and connection-state checks remain additional to
this header-level allowlist.

---

## 4. CBOR Payload Encoding
Expand Down Expand Up @@ -362,7 +372,7 @@ terminal RESPONSE requirement.
| 2 | message | tstr | MAY | Human-readable description |
| 3 | session_id | tstr | MAY | Session being closed |

Standard close reason codes: `graceful`, `unknown_type`, `unsupported_extension`,
Standard close reason codes: `graceful`, `unknown_type`, `unsupported_extension`, `conflicted_type`,
`frame_too_large`, `payload_too_large`, `version_mismatch`, `auth_failed`,
`idle_timeout`, `protocol_error`.

Expand Down Expand Up @@ -743,6 +753,7 @@ security principle: fail closed, fail cheap, fail loudly (log at warn level).
| Version unknown and peer rejected downgrade | Version negotiation §6 | Send CLOSE(version_mismatch); close connection | `version_mismatch` |
| Type = 0x00 (RESERVED) | Header parse | Send CLOSE(invalid_type); reject | `invalid_type` |
| Type = 0xFF (RESERVED) | Header parse | Send CLOSE(invalid_type); reject | `invalid_type` |
| Type = 0x0B or 0x0C in the stable task profile | Header parse | Reject before proportional allocation; dedicated experimental relay sessions remain separate | `conflicted_type` |
| Type in 0x0F–0xEF (future IICP reserved) | Header parse | Send CLOSE(unknown_type) if not forward-compat; MUST NOT process payload | `unknown_type` |
| Type in 0xF0–0xFE and no capability negotiated | Header parse | Send CLOSE(unsupported_extension); reject | `unsupported_extension` |
| Flags: unknown bits set | Header parse | MUST ignore unknown flag bits; process frame normally | — (extensibility rule) |
Expand Down Expand Up @@ -1150,3 +1161,4 @@ mechanisms are complementary.
| 0.1.8-draft | 2026-08-08 | Protocol Steward | Resolved the base-versus-profile RESPONSE contradiction: base CALLs remain buffered and single-terminal; negotiated service-lifecycle streaming uses incremental partials plus one terminal response. Clarified accounting, HTTP fallback, QUIC closure, sequence ownership and fragmentation terminology. No base-frame or required-field change. |
| 0.1.9-draft | 2026-08-08 | Protocol Steward | Specifies the negotiated lifecycle-envelope location in RESPONSE key 13 and OBSERVE `data`, including call/task correlation, status/finality mapping and native negative vectors. Key 13 remains profile-only; no base-frame or required-field change. |
| 0.1.10-draft | 2026-08-28 | Protocol Steward | Aligns the draft with the transport decision: native TCP remains optional, QUIC is research-only, Length is payload-only, 64 KiB is not a stream/datagram boundary, logical fragmentation is not stable, reassembly defaults are true maxima, deterministic-CBOR receive scope is explicit, and the unresolved `0x0B`/`0x0C` relay collision is recorded. |
| 0.1.11-draft | 2026-08-28 | Protocol Steward | Defines the finite stable task-session type allowlist, requires type rejection before proportional allocation, isolates dedicated experimental relay opcodes, and keeps production native TCP at the open qualify-or-exclude security gate. |
10 changes: 5 additions & 5 deletions spec/v1.9/release-integrity-manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
"ecosystem/repositories.json": "ab3565df543623420465a11f5284fe8ae64b554289be070fbcb480042deb0e9e",
"evidence/clean-room-interoperability-record-v1.json": "907a769090908ec1169c04f8e276396bb644765c0cb98bee735320467c449bc9",
"evidence/compatibility-environment-v1.10.16.json": "9571cefa0823d21433bc092bac4bb8c537d074bcf03c36be3c7f9704ddb5d994",
"evidence/compatibility-environment-v1.10.17.json": "e7b65bf9b93b976ec7a6e2f28e8f06b1e8857b862a5558b0eb485d21d3f28c0a",
"evidence/compatibility-environment-v1.10.17.json": "10abf903bcc011c86d0dd150150d178c60bf3c506dd3590c9a406267cdd9a112",
"evidence/external-participation-campaign-v1.json": "f19f85b4767b008c8754d82c959143426d3d502cb1b2e79b82e5d15cc80a2a9f",
"evidence/newcomer-validation-record-v1.json": "5fad1491f8c85a0517164b5aed0a13d7992747b2f211efd27bdec7e287ec5181",
"evidence/public-evidence-access-v1.json": "fc06068de5bb842e182cf22626abfb9f23bdc299d058cfed255d4828f5b37e8b",
Expand Down Expand Up @@ -93,8 +93,8 @@
"registry/schemas/translate-v1-input.json": "197067000ec2acfeba9ab463c61d733008a302a4a836bebc5ba02eec228823e4",
"registry/source-classification.json": "fe01d4cc22394fd74c1b734aaf469e5f6201b8229d792f30ca570c6a124f44b1",
"research/RESEARCH.md": "323dd757c9871aba21bf5933715ee746745fbecfc615d709f046deca7a6b58c5",
"research/native-ai-infrastructure/fixtures/native-framing-fixture-manifest-v1.json": "decfb39bb293877689197ba259f3c1b8a09ec290b6bb523edc119937ce3f3112",
"research/native-ai-infrastructure/fixtures/native-framing-v1.json": "795516349af7b8b1167357f12add10e56b467b80d1441c898dd48c97f3da1672",
"research/native-ai-infrastructure/fixtures/native-framing-fixture-manifest-v1.json": "d48cd3528563bec9796115289a6fe1391646a145cbc9b67dcdd3d84c1fda9c9b",
"research/native-ai-infrastructure/fixtures/native-framing-v1.json": "945c5086f0f7173beb7708478a36be74c0a4256ca4a4efd1a855e0e0057c3376",
"research/native-ai-infrastructure/fixtures/service-profiles-v1.json": "69fa2693d44a7d596cdabf433b284c07d27f4ab27433e2936c137de444cdaa9f",
"research/pre-normative-profiles/README.md": "5a25e689919e373bdd2cb9cd3fbf63ac1ed51b7a8729c9b5efcbc5ff3012a219",
"research/pre-normative-profiles/fixtures/README.md": "b69f8f0eb066d41f027798d012f00a8938d80e62a4a1b2797a53634cfc282185",
Expand Down Expand Up @@ -163,7 +163,7 @@
"spec/v1.9/iicp-dir.md": "3b626dea03ed7d4906cca12e766e9077a464eae319f461b0439deff41f8799ef",
"spec/v1.9/iicp-extensions.md": "c1e0443c2e365abe54c7503dcdeb59a1efdc25d48faafee4429e4aed13f87ce9",
"spec/v1.9/iicp-federated-directory.md": "ebb7c237111da0c3e5baa376426ea1b3720b33fe76bc894fda3fcbba5355f3f6",
"spec/v1.9/iicp-framing.md": "803a0a20620df53c8bbcc7534d05e8ddd391d0d3d55752541bc1478764e914cf",
"spec/v1.9/iicp-framing.md": "75a11f6d5c75f2ee77827989d2180ff98add5c4b44ae979f8503a567e8fc1bf4",
"spec/v1.9/iicp-identity-slot.md": "837342eb79ef6be07b93f1a6b8041accfa23fd6a9bf858cafd4470d97d70f14c",
"spec/v1.9/iicp-mcp-binding.md": "eac9dce25ab74ed7685a05b0c9dbb286e8c0b5fef96c80e51b10109d72fcf6c6",
"spec/v1.9/iicp-provider-admission-profile.md": "5ae8f4ff485fe939e7d61c405ea1209ea63125f9a3e048bda0440bd552e9f364",
Expand Down Expand Up @@ -206,7 +206,7 @@
"tools/check_identity_evidence_layering.py": "6ec6e752944db65559867490f7e7479875380692760356f7f585effa90526a07",
"tools/check_intent_registry.py": "58103bc020f2609ead76a4d52db7b6cebdabbba6a5f01ccb909c9b0dd154855f",
"tools/check_intent_registry_schema.py": "d868bb821d4dc278dbddefe8e449033d9f20c4e243c1843142e2047ab0429c8c",
"tools/check_native_framing_fixtures.py": "5c263e21d328fdfe9d116c2b64afc6bf39045ab03fdd34f7f382d700dfb5acb0",
"tools/check_native_framing_fixtures.py": "499e3b941be7ff373687443ae674e6804bbbd722437d20b2d47971c161365c3b",
"tools/check_newcomer_validation_record.py": "4cf42b3059a82066c7276f69be11b991994280d58e9799eebcddc0fc661cacd9",
"tools/check_operator_onboarding_recovery.py": "c7b8023b918a3ba936b4dbd7f41760b6d2f798daa399140b335ff0f63b0a5536",
"tools/check_profile_security_candidate.py": "505afe261598c302ebef4f743f0ba45eef6c7e401c5f80c1ce0c7f5239e3d9e9",
Expand Down
40 changes: 40 additions & 0 deletions tools/check_native_framing_fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,46 @@ def main() -> int:
errors.append(f"missing required negative vector: {name}")
elif scenario.get("expected", {}).get("reason") != reason:
errors.append(f"{name}: expected reason must be {reason}")
task_profile = data.get("stable_task_profile", {})
if task_profile.get("accepted_message_types") != [*range(1, 11), 13, 14]:
errors.append("stable task accepted types must be 0x01-0x0A and 0x0D-0x0E")
if task_profile.get("conflicted_message_types") != [11, 12]:
errors.append("stable task conflicted types must be 0x0B and 0x0C")
if task_profile.get("production_security_disposition") != "open_qualify_or_exclude":
errors.append("production security disposition must remain open qualify-or-exclude")
if task_profile.get("plaintext_scope") != "development_only":
errors.append("plaintext native TCP must remain development-only")
if task_profile.get("stable_claim") != "not_admitted":
errors.append("native TCP must not be admitted to the stable claim by this fixture")
type_scenarios = data.get("stable_task_type_scenarios", [])
type_names = [scenario.get("name") for scenario in type_scenarios]
if len(type_names) != len(set(type_names)):
errors.append("stable task type scenario names must be unique")
by_type = {scenario.get("message_type"): scenario for scenario in type_scenarios}
required_types = {
0: "invalid_type",
1: None,
5: None,
11: "conflicted_type",
12: "conflicted_type",
13: None,
15: "unknown_type",
240: "unsupported_extension",
255: "invalid_type",
}
for message_type, reason in required_types.items():
scenario = by_type.get(message_type)
if scenario is None:
errors.append(f"missing stable task type vector: 0x{message_type:02x}")
continue
expected_result = scenario.get("expected", {})
expected_outcome = "accept" if reason is None else "reject"
if expected_result.get("outcome") != expected_outcome:
errors.append(
f"type 0x{message_type:02x}: expected outcome must be {expected_outcome}"
)
if expected_result.get("reason") != reason:
errors.append(f"type 0x{message_type:02x}: expected reason must be {reason}")
for copy in args.copy:
if not copy.is_file():
errors.append(f"missing SDK fixture copy: {copy}")
Expand Down