feat: add JD native read-only service surface
This commit is contained in:
parent
a5a1cdc185
commit
856a6c9ffb
8 changed files with 317 additions and 18 deletions
|
|
@ -0,0 +1,48 @@
|
||||||
|
---
|
||||||
|
type: ADR
|
||||||
|
id: "0179"
|
||||||
|
title: "JD native read-only service surface before public cutover"
|
||||||
|
status: accepted
|
||||||
|
date: 2026-08-15
|
||||||
|
supersedes: "0171-jd-native-service-equivalence-staging"
|
||||||
|
---
|
||||||
|
|
||||||
|
# 京东原生只读服务面先于公网切换
|
||||||
|
|
||||||
|
## 触发
|
||||||
|
|
||||||
|
京东物理机已经证明 GOSK/GHAL 原生常驻能力,但原生常驻时公网 `/code/` 与
|
||||||
|
`/api/ai/v1/anchor` 返回 `502`。本轮重新读取真实链路后确认,公网前门实际位于
|
||||||
|
`BS-GZ-006`:它通过反向 SSH 隧道进入京东 Linux 上的 Node 导航服务、应用代理和
|
||||||
|
Forgejo。原生启动会使整个 Linux 数据面与 SSH 一起消失。
|
||||||
|
|
||||||
|
## 为什么旧办法不成立
|
||||||
|
|
||||||
|
继续在 Ubuntu 宿主里增加守卫、进程或 Docker 服务,只能提高 Linux 宿主阶段的可用性,
|
||||||
|
不能让服务跨越原生启动。QEMU 回执也只能证明候选能力,不能替代物理公网读回。一个固定
|
||||||
|
JSON 快照不是 Forgejo,也不能把完整代码频道等价从 `0` 写成 `100`。
|
||||||
|
|
||||||
|
## 决定
|
||||||
|
|
||||||
|
原生候选先提供两个互相独立的只读接口:
|
||||||
|
|
||||||
|
- `GET /v1/anchor`:唯一公共导航锚点;
|
||||||
|
- `GET /v1/code-channel`:绑定 REPO-012 精确分支与提交的只读发现快照。
|
||||||
|
|
||||||
|
两者必须在同一次原生驻留 QEMU 生命周期里通过 TCP、校验和、正文精确读回以及受保护恢复
|
||||||
|
能力测试。公网等价仍需另一个门:为 `BS-GZ-006` 建立在 Linux 不在场时仍存在的受认证原生
|
||||||
|
传输,并分别验证公网导航与 `/code/` 产品契约。
|
||||||
|
|
||||||
|
## 当前边界
|
||||||
|
|
||||||
|
本轮只完成源码、契约与 QEMU 候选验证:
|
||||||
|
|
||||||
|
- 原生导航锚点 QEMU:`100`;
|
||||||
|
- 原生代码频道只读发现 QEMU:`100`;
|
||||||
|
- 京东物理机本轮启动:`0`;
|
||||||
|
- 公网原生导航:`0`;
|
||||||
|
- 公网原生代码频道:`0`;
|
||||||
|
- 完整 Forgejo 等价:`0`;
|
||||||
|
- 最终光湖 OS 主控:`0`。
|
||||||
|
|
||||||
|
没有修改默认启动、引导盘、服务器磁盘或公网前门。
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
schema: guanghu.jd-native-read-only-service-surface-qemu-receipt/v1
|
||||||
|
receipt_id: GH-OS-JD-FD-PRIMARY-NATIVE-READ-ONLY-SERVICE-SURFACE-QEMU-20260815-001
|
||||||
|
status: PASS_100
|
||||||
|
observed_at: 2026-08-15T18:47:43+08:00
|
||||||
|
node_id: JD-FD-PRIMARY
|
||||||
|
source:
|
||||||
|
repository_id: REPO-014
|
||||||
|
accepted_repo_012_commit: fb1096c5ecdcfb36015d51273f487c2f36d9c9cd
|
||||||
|
candidate:
|
||||||
|
sector_count: 29
|
||||||
|
sha256: 9807fa751616d4b421c103d60eecface1c5eb8013cbd89417ef9e027da281fb3
|
||||||
|
recovery_capability: QEMU_FIXTURE_ONLY_NOT_DEPLOYABLE
|
||||||
|
verified:
|
||||||
|
native_anchor_http_qemu: 100
|
||||||
|
native_code_channel_read_only_qemu: 100
|
||||||
|
tcp_checksums: 100
|
||||||
|
exact_response_bodies: 100
|
||||||
|
protected_recovery_capability: 100
|
||||||
|
wrong_recovery_capability_ignored: 100
|
||||||
|
truth_boundary:
|
||||||
|
native_physical_readback_this_cycle: 0
|
||||||
|
public_anchor_during_native_residency: 0
|
||||||
|
public_code_during_native_residency: 0
|
||||||
|
full_forgejo_equivalence: 0
|
||||||
|
default_boot_changed: false
|
||||||
|
bootloader_written: false
|
||||||
|
server_disk_written: false
|
||||||
|
server_rebooted: false
|
||||||
|
why:
|
||||||
|
trigger: Native residency removed the Linux-hosted SSH and service data plane, causing public 502 responses.
|
||||||
|
decision: Prove a bounded native read-only surface before designing the authenticated BS-GZ-006 relay and public mapping.
|
||||||
|
rejected: Treating a Linux-hosted guard, a QEMU result, or a JSON snapshot as production service equivalence.
|
||||||
|
next_action: IMPLEMENT_AUTHENTICATED_NATIVE_TO_BS_GZ_006_TRANSPORT_AND_SEPARATE_PUBLIC_ANCHOR_FROM_FULL_CODE_CHANNEL_ACCEPTANCE
|
||||||
|
|
@ -1333,13 +1333,47 @@ ghal_net_try_anchor_http:
|
||||||
sub eax, 4
|
sub eax, 4
|
||||||
cmp dword [VIRTIO_NET_RX_BUFFER + rax], 0x20544547
|
cmp dword [VIRTIO_NET_RX_BUFFER + rax], 0x20544547
|
||||||
jne .handled_without_reply
|
jne .handled_without_reply
|
||||||
mov byte [rel ghal_anchor_tcp_flags], 0x19
|
lea edx, [eax + 15]
|
||||||
|
cmp r14d, edx
|
||||||
|
jb .handled_without_reply
|
||||||
|
mov rdx, 0x2f31762f20544547
|
||||||
|
cmp qword [VIRTIO_NET_RX_BUFFER + rax], rdx
|
||||||
|
jne .handled_without_reply
|
||||||
|
mov rdx, 0x4820726f68636e61
|
||||||
|
cmp qword [VIRTIO_NET_RX_BUFFER + rax + 8], rdx
|
||||||
|
jne .try_code_channel
|
||||||
mov rsi, ghal_anchor_http_response
|
mov rsi, ghal_anchor_http_response
|
||||||
|
mov [rel ghal_http_response_pointer], rsi
|
||||||
mov word [rel ghal_anchor_tcp_payload_size], ghal_anchor_http_response_end - ghal_anchor_http_response
|
mov word [rel ghal_anchor_tcp_payload_size], ghal_anchor_http_response_end - ghal_anchor_http_response
|
||||||
|
jmp .send_http
|
||||||
|
.try_code_channel:
|
||||||
|
lea edx, [eax + 21]
|
||||||
|
cmp r14d, edx
|
||||||
|
jb .handled_without_reply
|
||||||
|
mov rdx, 0x6168632d65646f63
|
||||||
|
cmp qword [VIRTIO_NET_RX_BUFFER + rax + 8], rdx
|
||||||
|
jne .handled_without_reply
|
||||||
|
cmp dword [VIRTIO_NET_RX_BUFFER + rax + 16], 0x6c656e6e
|
||||||
|
jne .handled_without_reply
|
||||||
|
cmp byte [VIRTIO_NET_RX_BUFFER + rax + 20], 0x20
|
||||||
|
jne .handled_without_reply
|
||||||
|
mov rsi, ghal_code_channel_http_response
|
||||||
|
mov [rel ghal_http_response_pointer], rsi
|
||||||
|
mov word [rel ghal_anchor_tcp_payload_size], ghal_code_channel_http_response_end - ghal_code_channel_http_response
|
||||||
|
.send_http:
|
||||||
|
mov byte [rel ghal_anchor_tcp_flags], 0x19
|
||||||
call ghal_net_send_anchor_tcp
|
call ghal_net_send_anchor_tcp
|
||||||
jc .not_anchor
|
jc .not_anchor
|
||||||
mov byte [rel physical_proof_anchor_http_response_tx], 1
|
mov byte [rel physical_proof_anchor_http_response_tx], 1
|
||||||
|
mov rax, [rel ghal_http_response_pointer]
|
||||||
|
lea rdx, [rel ghal_code_channel_http_response]
|
||||||
|
cmp rax, rdx
|
||||||
|
jne .log_anchor_http
|
||||||
|
mov rsi, msg_ghal_code_channel_http_ready
|
||||||
|
jmp .log_http
|
||||||
|
.log_anchor_http:
|
||||||
mov rsi, msg_ghal_anchor_http_ready
|
mov rsi, msg_ghal_anchor_http_ready
|
||||||
|
.log_http:
|
||||||
call serial_write64
|
call serial_write64
|
||||||
clc
|
clc
|
||||||
ret
|
ret
|
||||||
|
|
@ -1432,7 +1466,7 @@ ghal_net_send_anchor_tcp:
|
||||||
movzx ecx, word [rel ghal_anchor_tcp_payload_size]
|
movzx ecx, word [rel ghal_anchor_tcp_payload_size]
|
||||||
test ecx, ecx
|
test ecx, ecx
|
||||||
jz .checksums
|
jz .checksums
|
||||||
mov rsi, ghal_anchor_http_response
|
mov rsi, [rel ghal_http_response_pointer]
|
||||||
mov rdi, VIRTIO_NET_TX_BUFFER + 64
|
mov rdi, VIRTIO_NET_TX_BUFFER + 64
|
||||||
rep movsb
|
rep movsb
|
||||||
.checksums:
|
.checksums:
|
||||||
|
|
@ -1557,6 +1591,7 @@ ghal_anchor_tcp_payload_size: dw 0
|
||||||
ghal_anchor_rx_ipv4_header_size: dw 0
|
ghal_anchor_rx_ipv4_header_size: dw 0
|
||||||
ghal_anchor_rx_tcp_offset: dw 0
|
ghal_anchor_rx_tcp_offset: dw 0
|
||||||
ghal_anchor_rx_tcp_header_size: dw 0
|
ghal_anchor_rx_tcp_header_size: dw 0
|
||||||
|
ghal_http_response_pointer: dq 0
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
msg_ghal_net_discovered: db "GHOS_GHAL_VIRTIO_NET=DISCOVERED", 13, 10, 0
|
msg_ghal_net_discovered: db "GHOS_GHAL_VIRTIO_NET=DISCOVERED", 13, 10, 0
|
||||||
|
|
@ -1575,6 +1610,15 @@ ghal_anchor_http_response:
|
||||||
db "Content-Length: 286", 13, 10, 13, 10
|
db "Content-Length: 286", 13, 10, 13, 10
|
||||||
db '{"schema":"guanghu.native-public-anchor/v1","anchor_id":"GLW-PUBLIC-NAV-ANCHOR-001","entry_path":"LL-CMPN-0001","world_node_id":"SYS-GLW-0001","repository_id":"REPO-012","branch":"main","code_entry":"https://guanghulab.com/code/bingshuo/guanghu-ice-heart","runtime":"GUANGHU_OS_NATIVE"}'
|
db '{"schema":"guanghu.native-public-anchor/v1","anchor_id":"GLW-PUBLIC-NAV-ANCHOR-001","entry_path":"LL-CMPN-0001","world_node_id":"SYS-GLW-0001","repository_id":"REPO-012","branch":"main","code_entry":"https://guanghulab.com/code/bingshuo/guanghu-ice-heart","runtime":"GUANGHU_OS_NATIVE"}'
|
||||||
ghal_anchor_http_response_end:
|
ghal_anchor_http_response_end:
|
||||||
|
msg_ghal_code_channel_http_ready: db "GHOS_NATIVE_CODE_CHANNEL_HTTP=RESPONSE_TX", 13, 10, 0
|
||||||
|
ghal_code_channel_http_response:
|
||||||
|
db "HTTP/1.1 200 OK", 13, 10
|
||||||
|
db "Content-Type: application/json", 13, 10
|
||||||
|
db "Cache-Control: no-store", 13, 10
|
||||||
|
db "Connection: close", 13, 10
|
||||||
|
db "Content-Length: 240", 13, 10, 13, 10
|
||||||
|
db '{"schema":"guanghu.native-code-channel-read-only/v1","repository_id":"REPO-012","branch":"main","commit":"fb1096c5ecdcfb36015d51273f487c2f36d9c9cd","mode":"READ_ONLY_DISCOVERY","runtime":"GUANGHU_OS_NATIVE","full_forgejo_equivalence":false}'
|
||||||
|
ghal_code_channel_http_response_end:
|
||||||
%endif
|
%endif
|
||||||
msg_ghal_world_store_ready: db "GHOS_HLDP_WORLD_STORE=WRITE_READ_VERIFIED", 13, 10, 0
|
msg_ghal_world_store_ready: db "GHOS_HLDP_WORLD_STORE=WRITE_READ_VERIFIED", 13, 10, 0
|
||||||
msg_ghal_code_channel_store_ready: db "GHOS_CODE_CHANNEL_STORE=WRITE_READ_VERIFIED", 13, 10, 0
|
msg_ghal_code_channel_store_ready: db "GHOS_CODE_CHANNEL_STORE=WRITE_READ_VERIFIED", 13, 10, 0
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@ NATIVE_ACK_MAGIC = b"HLDP-NATIVE-ACK!"
|
||||||
ANCHOR_PORT = 3922
|
ANCHOR_PORT = 3922
|
||||||
ANCHOR_CLIENT_PORT = 40392
|
ANCHOR_CLIENT_PORT = 40392
|
||||||
ANCHOR_CLIENT_SEQUENCE = 0x10203040
|
ANCHOR_CLIENT_SEQUENCE = 0x10203040
|
||||||
|
CODE_CLIENT_PORT = 40393
|
||||||
|
CODE_CLIENT_SEQUENCE = 0x20304050
|
||||||
ANCHOR_BODY = (
|
ANCHOR_BODY = (
|
||||||
b'{"schema":"guanghu.native-public-anchor/v1",'
|
b'{"schema":"guanghu.native-public-anchor/v1",'
|
||||||
b'"anchor_id":"GLW-PUBLIC-NAV-ANCHOR-001",'
|
b'"anchor_id":"GLW-PUBLIC-NAV-ANCHOR-001",'
|
||||||
|
|
@ -26,6 +28,13 @@ ANCHOR_BODY = (
|
||||||
b'"code_entry":"https://guanghulab.com/code/bingshuo/guanghu-ice-heart",'
|
b'"code_entry":"https://guanghulab.com/code/bingshuo/guanghu-ice-heart",'
|
||||||
b'"runtime":"GUANGHU_OS_NATIVE"}'
|
b'"runtime":"GUANGHU_OS_NATIVE"}'
|
||||||
)
|
)
|
||||||
|
CODE_BODY = (
|
||||||
|
b'{"schema":"guanghu.native-code-channel-read-only/v1",'
|
||||||
|
b'"repository_id":"REPO-012","branch":"main",'
|
||||||
|
b'"commit":"fb1096c5ecdcfb36015d51273f487c2f36d9c9cd",'
|
||||||
|
b'"mode":"READ_ONLY_DISCOVERY","runtime":"GUANGHU_OS_NATIVE",'
|
||||||
|
b'"full_forgejo_equivalence":false}'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def checksum(payload: bytes) -> int:
|
def checksum(payload: bytes) -> int:
|
||||||
|
|
@ -105,13 +114,14 @@ def tcp_frame(
|
||||||
acknowledgement: int,
|
acknowledgement: int,
|
||||||
payload: bytes = b"",
|
payload: bytes = b"",
|
||||||
options: bytes = b"",
|
options: bytes = b"",
|
||||||
|
client_port: int = ANCHOR_CLIENT_PORT,
|
||||||
) -> bytes:
|
) -> bytes:
|
||||||
if len(options) % 4 or len(options) > 40:
|
if len(options) % 4 or len(options) > 40:
|
||||||
raise ValueError("TCP options must be 32-bit aligned and no more than 40 bytes")
|
raise ValueError("TCP options must be 32-bit aligned and no more than 40 bytes")
|
||||||
tcp = bytearray(
|
tcp = bytearray(
|
||||||
struct.pack(
|
struct.pack(
|
||||||
"!HHIIBBHHH",
|
"!HHIIBBHHH",
|
||||||
ANCHOR_CLIENT_PORT,
|
client_port,
|
||||||
ANCHOR_PORT,
|
ANCHOR_PORT,
|
||||||
sequence,
|
sequence,
|
||||||
acknowledgement,
|
acknowledgement,
|
||||||
|
|
@ -137,7 +147,9 @@ def tcp_frame(
|
||||||
return GUEST_MAC + PEER_MAC + b"\x08\x00" + bytes(ip) + bytes(tcp)
|
return GUEST_MAC + PEER_MAC + b"\x08\x00" + bytes(ip) + bytes(tcp)
|
||||||
|
|
||||||
|
|
||||||
def verify_anchor_tcp(frame: bytes, expected_flags: int) -> tuple[int, int, bytes]:
|
def verify_anchor_tcp(
|
||||||
|
frame: bytes, expected_flags: int, client_port: int = ANCHOR_CLIENT_PORT
|
||||||
|
) -> tuple[int, int, bytes]:
|
||||||
assert frame[0:6] == PEER_MAC
|
assert frame[0:6] == PEER_MAC
|
||||||
assert frame[6:12] == GUEST_MAC
|
assert frame[6:12] == GUEST_MAC
|
||||||
assert frame[12:14] == b"\x08\x00"
|
assert frame[12:14] == b"\x08\x00"
|
||||||
|
|
@ -148,7 +160,7 @@ def verify_anchor_tcp(frame: bytes, expected_flags: int) -> tuple[int, int, byte
|
||||||
total_length = int.from_bytes(frame[16:18], "big")
|
total_length = int.from_bytes(frame[16:18], "big")
|
||||||
tcp = frame[34 : 14 + total_length]
|
tcp = frame[34 : 14 + total_length]
|
||||||
assert int.from_bytes(tcp[0:2], "big") == ANCHOR_PORT
|
assert int.from_bytes(tcp[0:2], "big") == ANCHOR_PORT
|
||||||
assert int.from_bytes(tcp[2:4], "big") == ANCHOR_CLIENT_PORT
|
assert int.from_bytes(tcp[2:4], "big") == client_port
|
||||||
assert tcp[13] == expected_flags
|
assert tcp[13] == expected_flags
|
||||||
pseudo = GUEST_IP + GATEWAY_IP + b"\0\x06" + struct.pack("!H", len(tcp))
|
pseudo = GUEST_IP + GATEWAY_IP + b"\0\x06" + struct.pack("!H", len(tcp))
|
||||||
assert checksum(pseudo + tcp) == 0
|
assert checksum(pseudo + tcp) == 0
|
||||||
|
|
@ -170,6 +182,7 @@ def main() -> None:
|
||||||
parser.add_argument("--recovery-token-file")
|
parser.add_argument("--recovery-token-file")
|
||||||
parser.add_argument("--login-only", action="store_true")
|
parser.add_argument("--login-only", action="store_true")
|
||||||
parser.add_argument("--anchor-http", action="store_true")
|
parser.add_argument("--anchor-http", action="store_true")
|
||||||
|
parser.add_argument("--service-equivalence", action="store_true")
|
||||||
parser.add_argument("--guest-ip", default="172.16.0.6")
|
parser.add_argument("--guest-ip", default="172.16.0.6")
|
||||||
parser.add_argument("--peer-ip", default="172.16.0.1")
|
parser.add_argument("--peer-ip", default="172.16.0.1")
|
||||||
parser.add_argument("--relay-ip", default="43.153.193.169")
|
parser.add_argument("--relay-ip", default="43.153.193.169")
|
||||||
|
|
@ -192,7 +205,7 @@ def main() -> None:
|
||||||
peer.bind(("127.0.0.1", args.listen_port))
|
peer.bind(("127.0.0.1", args.listen_port))
|
||||||
peer.settimeout(0.2)
|
peer.settimeout(0.2)
|
||||||
qemu = ("127.0.0.1", args.qemu_port)
|
qemu = ("127.0.0.1", args.qemu_port)
|
||||||
deadline = time.monotonic() + 15
|
deadline = time.monotonic() + (30 if args.service_equivalence else 15)
|
||||||
arp_verified = False
|
arp_verified = False
|
||||||
login_count = 0
|
login_count = 0
|
||||||
resident_login_count = 0
|
resident_login_count = 0
|
||||||
|
|
@ -204,6 +217,11 @@ def main() -> None:
|
||||||
anchor_server_sequence = None
|
anchor_server_sequence = None
|
||||||
anchor_get_sent = False
|
anchor_get_sent = False
|
||||||
anchor_http_verified = False
|
anchor_http_verified = False
|
||||||
|
code_syn_sent = False
|
||||||
|
code_syn_ack_verified = False
|
||||||
|
code_server_sequence = None
|
||||||
|
code_get_sent = False
|
||||||
|
code_http_verified = False
|
||||||
|
|
||||||
while time.monotonic() < deadline:
|
while time.monotonic() < deadline:
|
||||||
try:
|
try:
|
||||||
|
|
@ -217,6 +235,46 @@ def main() -> None:
|
||||||
if frame[12:14] != b"\x08\x00":
|
if frame[12:14] != b"\x08\x00":
|
||||||
continue
|
continue
|
||||||
if frame[23] == 6:
|
if frame[23] == 6:
|
||||||
|
response_client_port = int.from_bytes(frame[36:38], "big")
|
||||||
|
if response_client_port == CODE_CLIENT_PORT:
|
||||||
|
if not code_syn_ack_verified:
|
||||||
|
server_sequence, acknowledgement, payload = verify_anchor_tcp(
|
||||||
|
frame, 0x12, CODE_CLIENT_PORT
|
||||||
|
)
|
||||||
|
assert acknowledgement == CODE_CLIENT_SEQUENCE + 1
|
||||||
|
assert payload == b""
|
||||||
|
code_server_sequence = server_sequence
|
||||||
|
code_syn_ack_verified = True
|
||||||
|
request = (
|
||||||
|
b"GET /v1/code-channel HTTP/1.1\r\n"
|
||||||
|
b"Host: native.guanghulab.com\r\n"
|
||||||
|
b"Connection: close\r\n\r\n"
|
||||||
|
)
|
||||||
|
peer.sendto(
|
||||||
|
tcp_frame(
|
||||||
|
0x18,
|
||||||
|
CODE_CLIENT_SEQUENCE + 1,
|
||||||
|
server_sequence + 1,
|
||||||
|
request,
|
||||||
|
options=b"\x01\x01\x08\x0a\xd8\x8d\xec\x57\x00\x00\x00\x01",
|
||||||
|
client_port=CODE_CLIENT_PORT,
|
||||||
|
),
|
||||||
|
qemu,
|
||||||
|
)
|
||||||
|
code_get_sent = True
|
||||||
|
continue
|
||||||
|
server_sequence, acknowledgement, payload = verify_anchor_tcp(
|
||||||
|
frame, 0x19, CODE_CLIENT_PORT
|
||||||
|
)
|
||||||
|
assert code_server_sequence is not None
|
||||||
|
assert server_sequence == code_server_sequence + 1
|
||||||
|
assert acknowledgement > CODE_CLIENT_SEQUENCE + 1
|
||||||
|
header, body = payload.split(b"\r\n\r\n", 1)
|
||||||
|
assert b"HTTP/1.1 200 OK" in header
|
||||||
|
assert f"Content-Length: {len(CODE_BODY)}".encode() in header
|
||||||
|
assert body == CODE_BODY
|
||||||
|
code_http_verified = True
|
||||||
|
continue
|
||||||
if not anchor_syn_ack_verified:
|
if not anchor_syn_ack_verified:
|
||||||
server_sequence, acknowledgement, payload = verify_anchor_tcp(frame, 0x12)
|
server_sequence, acknowledgement, payload = verify_anchor_tcp(frame, 0x12)
|
||||||
assert acknowledgement == ANCHOR_CLIENT_SEQUENCE + 1
|
assert acknowledgement == ANCHOR_CLIENT_SEQUENCE + 1
|
||||||
|
|
@ -249,6 +307,21 @@ def main() -> None:
|
||||||
assert b"Content-Length: 286" in header
|
assert b"Content-Length: 286" in header
|
||||||
assert body == ANCHOR_BODY
|
assert body == ANCHOR_BODY
|
||||||
anchor_http_verified = True
|
anchor_http_verified = True
|
||||||
|
if args.service_equivalence and not code_syn_sent:
|
||||||
|
peer.sendto(
|
||||||
|
tcp_frame(
|
||||||
|
0x02,
|
||||||
|
CODE_CLIENT_SEQUENCE,
|
||||||
|
0,
|
||||||
|
options=(
|
||||||
|
b"\x02\x04\x05\x90\x04\x02\x08\x0a"
|
||||||
|
b"\xd8\x8d\xec\x57\x00\x00\x00\x00\x01\x03\x03\x07"
|
||||||
|
),
|
||||||
|
client_port=CODE_CLIENT_PORT,
|
||||||
|
),
|
||||||
|
qemu,
|
||||||
|
)
|
||||||
|
code_syn_sent = True
|
||||||
continue
|
continue
|
||||||
sequence = int.from_bytes(frame[40:42], "big")
|
sequence = int.from_bytes(frame[40:42], "big")
|
||||||
if sequence <= 3:
|
if sequence <= 3:
|
||||||
|
|
@ -273,12 +346,13 @@ def main() -> None:
|
||||||
raise AssertionError(f"unexpected native sequence {sequence}")
|
raise AssertionError(f"unexpected native sequence {sequence}")
|
||||||
verified_request(frame, sequence, magic)
|
verified_request(frame, sequence, magic)
|
||||||
peer.sendto(ordinary_reply(frame), qemu)
|
peer.sendto(ordinary_reply(frame), qemu)
|
||||||
time.sleep(0.05)
|
time.sleep(0.005 if args.service_equivalence else 0.05)
|
||||||
response_capability = NATIVE_ACK_MAGIC
|
response_capability = NATIVE_ACK_MAGIC
|
||||||
if (
|
if (
|
||||||
args.final_resident
|
args.final_resident
|
||||||
and resident_login_count >= 3
|
and resident_login_count >= 3
|
||||||
and (not args.anchor_http or anchor_http_verified)
|
and (not args.anchor_http or anchor_http_verified)
|
||||||
|
and (not args.service_equivalence or code_http_verified)
|
||||||
):
|
):
|
||||||
response_capability = recovery_capability
|
response_capability = recovery_capability
|
||||||
recovery_verified = True
|
recovery_verified = True
|
||||||
|
|
@ -286,9 +360,9 @@ def main() -> None:
|
||||||
for repetition in range(4):
|
for repetition in range(4):
|
||||||
peer.sendto(reply, qemu)
|
peer.sendto(reply, qemu)
|
||||||
if repetition < 3:
|
if repetition < 3:
|
||||||
time.sleep(0.01)
|
time.sleep(0.001 if args.service_equivalence else 0.01)
|
||||||
if (
|
if (
|
||||||
args.anchor_http
|
(args.anchor_http or args.service_equivalence)
|
||||||
and args.final_resident
|
and args.final_resident
|
||||||
and sequence == 6
|
and sequence == 6
|
||||||
and not anchor_syn_sent
|
and not anchor_syn_sent
|
||||||
|
|
@ -336,12 +410,24 @@ def main() -> None:
|
||||||
f"anchor_syn_sent: {str(anchor_syn_sent).lower()}\n"
|
f"anchor_syn_sent: {str(anchor_syn_sent).lower()}\n"
|
||||||
f"anchor_syn_ack_verified: {str(anchor_syn_ack_verified).lower()}\n"
|
f"anchor_syn_ack_verified: {str(anchor_syn_ack_verified).lower()}\n"
|
||||||
f"anchor_get_sent: {str(anchor_get_sent).lower()}\n"
|
f"anchor_get_sent: {str(anchor_get_sent).lower()}\n"
|
||||||
f"anchor_http_verified: {str(anchor_http_verified).lower()}\n"
|
f"anchor_http_verified: {str(anchor_http_verified).lower()}\n"
|
||||||
|
f"code_syn_sent: {str(code_syn_sent).lower()}\n"
|
||||||
|
f"code_syn_ack_verified: {str(code_syn_ack_verified).lower()}\n"
|
||||||
|
f"code_get_sent: {str(code_get_sent).lower()}\n"
|
||||||
|
f"code_http_verified: {str(code_http_verified).lower()}\n"
|
||||||
"recovery_selected_by_native: false\n"
|
"recovery_selected_by_native: false\n"
|
||||||
"login_magic: HLDP-GHOS-LOGIN!\n"
|
"login_magic: HLDP-GHOS-LOGIN!\n"
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
raise SystemExit("timed out waiting for native outbound ICMP exchange")
|
raise SystemExit(
|
||||||
|
"timed out waiting for native service equivalence: "
|
||||||
|
f"anchor_syn_sent={anchor_syn_sent}, "
|
||||||
|
f"anchor_syn_ack_verified={anchor_syn_ack_verified}, "
|
||||||
|
f"anchor_http_verified={anchor_http_verified}, "
|
||||||
|
f"code_syn_sent={code_syn_sent}, "
|
||||||
|
f"code_syn_ack_verified={code_syn_ack_verified}, "
|
||||||
|
f"code_http_verified={code_http_verified}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
||||||
|
|
@ -50,11 +50,11 @@ python3 "${source_root}/scripts/qemu-native-net-peer.py" \
|
||||||
--qemu-port "${qemu_port}" \
|
--qemu-port "${qemu_port}" \
|
||||||
--receipt "${test_root}/peer.hldp" \
|
--receipt "${test_root}/peer.hldp" \
|
||||||
--final-resident \
|
--final-resident \
|
||||||
--anchor-http \
|
--service-equivalence \
|
||||||
--recovery-token-file "${token_file}" >"${test_root}/peer.log" 2>&1 &
|
--recovery-token-file "${token_file}" >"${test_root}/peer.log" 2>&1 &
|
||||||
peer_pid=$!
|
peer_pid=$!
|
||||||
set +e
|
set +e
|
||||||
timeout 40 qemu-system-x86_64 \
|
timeout "${GHOS_QEMU_TIMEOUT_SECONDS:-40}" qemu-system-x86_64 \
|
||||||
-machine pc,accel=tcg \
|
-machine pc,accel=tcg \
|
||||||
-m 64M \
|
-m 64M \
|
||||||
-drive "if=none,id=ghboot,format=raw,file=${test_root}/disk.img" \
|
-drive "if=none,id=ghboot,format=raw,file=${test_root}/disk.img" \
|
||||||
|
|
@ -78,7 +78,10 @@ grep -q '^recovery_reply_verified: true$' "${test_root}/peer.hldp"
|
||||||
grep -q '^recovery_selected_by_native: false$' "${test_root}/peer.hldp"
|
grep -q '^recovery_selected_by_native: false$' "${test_root}/peer.hldp"
|
||||||
grep -q '^anchor_syn_ack_verified: true$' "${test_root}/peer.hldp"
|
grep -q '^anchor_syn_ack_verified: true$' "${test_root}/peer.hldp"
|
||||||
grep -q '^anchor_http_verified: true$' "${test_root}/peer.hldp"
|
grep -q '^anchor_http_verified: true$' "${test_root}/peer.hldp"
|
||||||
|
grep -q '^code_syn_ack_verified: true$' "${test_root}/peer.hldp"
|
||||||
|
grep -q '^code_http_verified: true$' "${test_root}/peer.hldp"
|
||||||
grep -q '^GHOS_NATIVE_ANCHOR_HTTP=RESPONSE_TX' "${test_root}/serial.log"
|
grep -q '^GHOS_NATIVE_ANCHOR_HTTP=RESPONSE_TX' "${test_root}/serial.log"
|
||||||
|
grep -q '^GHOS_NATIVE_CODE_CHANNEL_HTTP=RESPONSE_TX' "${test_root}/serial.log"
|
||||||
grep -q '^GHOS_NATIVE_RECOVERY_BEACON=WRITE_READ_VERIFIED' "${test_root}/serial.log"
|
grep -q '^GHOS_NATIVE_RECOVERY_BEACON=WRITE_READ_VERIFIED' "${test_root}/serial.log"
|
||||||
grep -q '^GHOS_DISK_PROOF_OBSERVED_AFTER_RESET=LBA134' "${test_root}/serial.log"
|
grep -q '^GHOS_DISK_PROOF_OBSERVED_AFTER_RESET=LBA134' "${test_root}/serial.log"
|
||||||
|
|
||||||
|
|
@ -172,6 +175,13 @@ native_anchor_service:
|
||||||
world_node_id: SYS-GLW-0001
|
world_node_id: SYS-GLW-0001
|
||||||
repository_id: REPO-012
|
repository_id: REPO-012
|
||||||
runtime: GUANGHU_OS_NATIVE
|
runtime: GUANGHU_OS_NATIVE
|
||||||
|
native_code_channel_read_only:
|
||||||
|
http_get_v1_code_channel: PASS_100
|
||||||
|
response_schema: guanghu.native-code-channel-read-only/v1
|
||||||
|
repository_id: REPO-012
|
||||||
|
branch: main
|
||||||
|
commit: fb1096c5ecdcfb36015d51273f487c2f36d9c9cd
|
||||||
|
full_forgejo_equivalence: false
|
||||||
recovery_control:
|
recovery_control:
|
||||||
selected_by_native_runtime: false
|
selected_by_native_runtime: false
|
||||||
per_deployment_capability_required: true
|
per_deployment_capability_required: true
|
||||||
|
|
@ -183,7 +193,8 @@ boundary:
|
||||||
physical_server_capability: 0
|
physical_server_capability: 0
|
||||||
native_anchor_http_qemu_capability: 100
|
native_anchor_http_qemu_capability: 100
|
||||||
native_anchor_http_physical_capability: 0
|
native_anchor_http_physical_capability: 0
|
||||||
code_channel_service_equivalence: 0
|
native_code_channel_read_only_qemu_capability: 100
|
||||||
|
public_code_channel_service_equivalence: 0
|
||||||
final_native_residency_proven: false
|
final_native_residency_proven: false
|
||||||
next_action: PHYSICAL_ONE_TIME_NATIVE_ANCHOR_HTTP_GATE_WITH_PROTECTED_RECOVERY
|
next_action: IMPLEMENT_AUTHENTICATED_NATIVE_TO_BS_GZ_006_TRANSPORT_AND_SEPARATE_PUBLIC_ANCHOR_FROM_FULL_CODE_CHANNEL_ACCEPTANCE
|
||||||
EOF
|
EOF
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
{
|
||||||
|
"schema": "guanghu.jd-native-service-equivalence-contract/v1",
|
||||||
|
"node_id": "JD-FD-PRIMARY",
|
||||||
|
"candidate_source": "GUANGHU_OS_NATIVE",
|
||||||
|
"accepted_repository": {
|
||||||
|
"repository_id": "REPO-012",
|
||||||
|
"branch": "main",
|
||||||
|
"commit": "fb1096c5ecdcfb36015d51273f487c2f36d9c9cd"
|
||||||
|
},
|
||||||
|
"native_read_only_surface": [
|
||||||
|
{
|
||||||
|
"path": "/v1/anchor",
|
||||||
|
"schema": "guanghu.native-public-anchor/v1",
|
||||||
|
"required_anchor_id": "GLW-PUBLIC-NAV-ANCHOR-001"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/v1/code-channel",
|
||||||
|
"schema": "guanghu.native-code-channel-read-only/v1",
|
||||||
|
"mode": "READ_ONLY_DISCOVERY",
|
||||||
|
"full_forgejo_equivalence": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"current_public_contract": {
|
||||||
|
"anchor_path": "/api/ai/v1/anchor",
|
||||||
|
"code_path": "/code/",
|
||||||
|
"front_door_node": "BS-GZ-006",
|
||||||
|
"transport_while_linux_hosted": "REVERSE_SSH_TUNNEL",
|
||||||
|
"survives_native_residency": false
|
||||||
|
},
|
||||||
|
"acceptance_gates": {
|
||||||
|
"native_anchor_qemu": 100,
|
||||||
|
"native_code_channel_read_only_qemu": 100,
|
||||||
|
"native_physical_readback": 0,
|
||||||
|
"public_anchor_during_native_residency": 0,
|
||||||
|
"public_code_during_native_residency": 0,
|
||||||
|
"full_forgejo_equivalence": 0,
|
||||||
|
"production_native_cutover": 0
|
||||||
|
},
|
||||||
|
"prohibited_claims": [
|
||||||
|
"A_READ_ONLY_SNAPSHOT_IS_FULL_FORGEJO",
|
||||||
|
"QEMU_IS_PHYSICAL_SERVER_READBACK",
|
||||||
|
"LINUX_HOSTED_TUNNEL_SURVIVES_NATIVE_BOOT",
|
||||||
|
"SOURCE_IMPLEMENTATION_IS_PRODUCTION_CUTOVER"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"schema": "guanghu.os-control-architecture/v1",
|
"schema": "guanghu.os-control-architecture/v1",
|
||||||
"record_id": "HLP-GUANGHU-OS-CONTROL-001",
|
"record_id": "HLP-GUANGHU-OS-CONTROL-001",
|
||||||
"version": "2026-08-15.3",
|
"version": "2026-08-15.4",
|
||||||
"state": "CURRENT_CANONICAL",
|
"state": "CURRENT_CANONICAL",
|
||||||
"final_topology": "GUANGHU_MASTER_WITH_ON_DEMAND_LINUX_SUBCONTROL_AND_RESCUE",
|
"final_topology": "GUANGHU_MASTER_WITH_ON_DEMAND_LINUX_SUBCONTROL_AND_RESCUE",
|
||||||
"control_ownership": {
|
"control_ownership": {
|
||||||
|
|
@ -39,7 +39,7 @@
|
||||||
"linux_on_demand_subcontrol": 0,
|
"linux_on_demand_subcontrol": 0,
|
||||||
"linux_rescue_preserved": 100,
|
"linux_rescue_preserved": 100,
|
||||||
"final_guanghu_os_master": 0,
|
"final_guanghu_os_master": 0,
|
||||||
"next_engineering_gate": "IMPLEMENT_EQUIVALENT_SERVICE_CONTRACT_AND_INDEPENDENT_GUANGHU_SUPERVISOR_OWNERSHIP_BEFORE_ANY_BOOT_CUTOVER"
|
"next_engineering_gate": "IMPLEMENT_AUTHENTICATED_NATIVE_TO_BS_GZ_006_TRANSPORT_AND_PUBLIC_READBACK_BEFORE_ANY_BOOT_CUTOVER"
|
||||||
},
|
},
|
||||||
"implementation": {
|
"implementation": {
|
||||||
"guanghu_supervisor_lifecycle_contract_source": 100,
|
"guanghu_supervisor_lifecycle_contract_source": 100,
|
||||||
|
|
@ -50,6 +50,12 @@
|
||||||
"linux_hosted_isolated_shadow_backend": 100,
|
"linux_hosted_isolated_shadow_backend": 100,
|
||||||
"real_isolated_linux_backend": 0,
|
"real_isolated_linux_backend": 0,
|
||||||
"jd_shadow_backend_physical_cycle": 100,
|
"jd_shadow_backend_physical_cycle": 100,
|
||||||
|
"native_service_equivalence_contract_source": 100,
|
||||||
|
"native_anchor_http_qemu_capability": 100,
|
||||||
|
"native_code_channel_read_only_qemu_capability": 100,
|
||||||
|
"public_native_anchor_equivalence": 0,
|
||||||
|
"public_native_code_channel_equivalence": 0,
|
||||||
|
"full_forgejo_equivalence": 0,
|
||||||
"independent_guanghu_first_boot_supervisor": 0,
|
"independent_guanghu_first_boot_supervisor": 0,
|
||||||
"jd_physical_deployment": 0
|
"jd_physical_deployment": 0
|
||||||
},
|
},
|
||||||
|
|
@ -66,6 +72,7 @@
|
||||||
"historical_linux_free_completion_formula_is_current": false,
|
"historical_linux_free_completion_formula_is_current": false,
|
||||||
"adr_0172_linux_hosted_control_is_transition_not_final_topology": true
|
"adr_0172_linux_hosted_control_is_transition_not_final_topology": true
|
||||||
},
|
},
|
||||||
|
"native_service_equivalence_contract": "product-source/hololake-platform/guanghu-os/standards/jd-native-service-equivalence-contract.json",
|
||||||
"architecture_page": "product-source/hololake-platform/architecture/HOLOLAKE-GUANGHU-OS-MASTER-AND-ON-DEMAND-LINUX-SUBCONTROL-20260810.md",
|
"architecture_page": "product-source/hololake-platform/architecture/HOLOLAKE-GUANGHU-OS-MASTER-AND-ON-DEMAND-LINUX-SUBCONTROL-20260810.md",
|
||||||
"adr": "product-source/hololake-platform/docs/adr/0175-guanghu-os-master-and-on-demand-linux-subcontrol.md",
|
"adr": "product-source/hololake-platform/docs/adr/0175-guanghu-os-master-and-on-demand-linux-subcontrol.md",
|
||||||
"development_id": "DEV-20260810-012"
|
"development_id": "DEV-20260810-012"
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,9 @@ const readJson = (relative) => JSON.parse(fs.readFileSync(path.join(root, relati
|
||||||
const contract = readJson("routing/guanghu-os-control-architecture.json");
|
const contract = readJson("routing/guanghu-os-control-architecture.json");
|
||||||
const architecture = readJson("routing/hololake-current-architecture.json");
|
const architecture = readJson("routing/hololake-current-architecture.json");
|
||||||
const rules = readJson("routing/hololake-engineering-rules.json");
|
const rules = readJson("routing/hololake-engineering-rules.json");
|
||||||
|
const serviceContract = readJson(
|
||||||
|
"product-source/hololake-platform/guanghu-os/standards/jd-native-service-equivalence-contract.json",
|
||||||
|
);
|
||||||
|
|
||||||
test("final topology makes Guanghu the master while preserving Linux as on-demand subcontrol and rescue", () => {
|
test("final topology makes Guanghu the master while preserving Linux as on-demand subcontrol and rescue", () => {
|
||||||
assert.equal(contract.final_topology, "GUANGHU_MASTER_WITH_ON_DEMAND_LINUX_SUBCONTROL_AND_RESCUE");
|
assert.equal(contract.final_topology, "GUANGHU_MASTER_WITH_ON_DEMAND_LINUX_SUBCONTROL_AND_RESCUE");
|
||||||
|
|
@ -32,7 +35,7 @@ test("current JD state stays transitional and cannot impersonate final master co
|
||||||
});
|
});
|
||||||
|
|
||||||
test("the physical shadow cycle is registered without impersonating Guanghu-owned boot control", () => {
|
test("the physical shadow cycle is registered without impersonating Guanghu-owned boot control", () => {
|
||||||
assert.equal(contract.version, "2026-08-15.3");
|
assert.equal(contract.version, "2026-08-15.4");
|
||||||
assert.equal(contract.implementation.guanghu_supervisor_lifecycle_contract_source, 100);
|
assert.equal(contract.implementation.guanghu_supervisor_lifecycle_contract_source, 100);
|
||||||
assert.equal(contract.implementation.target_readback_and_mandatory_reclaim_state_machine, 100);
|
assert.equal(contract.implementation.target_readback_and_mandatory_reclaim_state_machine, 100);
|
||||||
assert.equal(contract.implementation.declared_supervisor_core_line_and_function_coverage, 100);
|
assert.equal(contract.implementation.declared_supervisor_core_line_and_function_coverage, 100);
|
||||||
|
|
@ -40,6 +43,12 @@ test("the physical shadow cycle is registered without impersonating Guanghu-owne
|
||||||
assert.equal(contract.implementation.linux_hosted_isolated_shadow_backend, 100);
|
assert.equal(contract.implementation.linux_hosted_isolated_shadow_backend, 100);
|
||||||
assert.equal(contract.implementation.real_isolated_linux_backend, 0);
|
assert.equal(contract.implementation.real_isolated_linux_backend, 0);
|
||||||
assert.equal(contract.implementation.jd_shadow_backend_physical_cycle, 100);
|
assert.equal(contract.implementation.jd_shadow_backend_physical_cycle, 100);
|
||||||
|
assert.equal(contract.implementation.native_service_equivalence_contract_source, 100);
|
||||||
|
assert.equal(contract.implementation.native_anchor_http_qemu_capability, 100);
|
||||||
|
assert.equal(contract.implementation.native_code_channel_read_only_qemu_capability, 100);
|
||||||
|
assert.equal(contract.implementation.public_native_anchor_equivalence, 0);
|
||||||
|
assert.equal(contract.implementation.public_native_code_channel_equivalence, 0);
|
||||||
|
assert.equal(contract.implementation.full_forgejo_equivalence, 0);
|
||||||
assert.equal(contract.implementation.independent_guanghu_first_boot_supervisor, 0);
|
assert.equal(contract.implementation.independent_guanghu_first_boot_supervisor, 0);
|
||||||
assert.equal(contract.implementation.jd_physical_deployment, 0);
|
assert.equal(contract.implementation.jd_physical_deployment, 0);
|
||||||
assert.equal(contract.current_target_evidence.final_state, "DORMANT");
|
assert.equal(contract.current_target_evidence.final_state, "DORMANT");
|
||||||
|
|
@ -54,3 +63,19 @@ test("current architecture and global engineering rules project the same control
|
||||||
assert.equal(rules.server_os_control.linux_hosted_language_primary_is_final_master, false);
|
assert.equal(rules.server_os_control.linux_hosted_language_primary_is_final_master, false);
|
||||||
assert.equal(rules.server_os_control.live_readback_predicates_required, true);
|
assert.equal(rules.server_os_control.live_readback_predicates_required, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("native service surface is exact while every physical and public claim remains zero", () => {
|
||||||
|
assert.equal(serviceContract.node_id, "JD-FD-PRIMARY");
|
||||||
|
assert.deepEqual(
|
||||||
|
serviceContract.native_read_only_surface.map((endpoint) => endpoint.path),
|
||||||
|
["/v1/anchor", "/v1/code-channel"],
|
||||||
|
);
|
||||||
|
assert.equal(serviceContract.accepted_repository.commit, "fb1096c5ecdcfb36015d51273f487c2f36d9c9cd");
|
||||||
|
assert.equal(serviceContract.acceptance_gates.native_anchor_qemu, 100);
|
||||||
|
assert.equal(serviceContract.acceptance_gates.native_code_channel_read_only_qemu, 100);
|
||||||
|
assert.equal(serviceContract.acceptance_gates.native_physical_readback, 0);
|
||||||
|
assert.equal(serviceContract.acceptance_gates.public_anchor_during_native_residency, 0);
|
||||||
|
assert.equal(serviceContract.acceptance_gates.public_code_during_native_residency, 0);
|
||||||
|
assert.equal(serviceContract.acceptance_gates.full_forgejo_equivalence, 0);
|
||||||
|
assert.equal(serviceContract.acceptance_gates.production_native_cutover, 0);
|
||||||
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue