diff --git a/skills/guanghu-feishu-glp/PROFILE.hldp b/skills/guanghu-feishu-glp/PROFILE.hldp new file mode 100644 index 0000000..0ab3b53 --- /dev/null +++ b/skills/guanghu-feishu-glp/PROFILE.hldp @@ -0,0 +1,12 @@ +HLDP://guanghu/feishu/glp-readonly-profile/v1 · 2026-10-19 +├── meta: {"id": "FEISHU-GLP-READONLY-PROFILE-001", "version": "1.0.0", "source_class": "ENGINEERING_PROFILE_NOT_NEW_WORLD_STANDARD"} +├── trigger: {"zh": "冰朔指定由京东承载运行,飞书晓通过技能工具递送协议消息;本次完成通信契约与接收器。", "en": "Bingshuo selects JD execution and protocol-message transport from Feishu Xiao; this delivery implements the contract and receiver."} +├── emergence: {"zh": "采用GLP/1.0标准信封;REQUEST调用零点原核只读ask,SYNC只查询公开规则发行版本。HTTP一次返回独立ACK、RESPONSE与可选RECEIPT,不是实时流式ACK。", "en": "Use GLP/1.0 envelopes. REQUEST asks Zero Core read-only; SYNC queries public release metadata only. One HTTP response contains distinct ACK, RESPONSE and optional RECEIPT, not a streamed immediate acknowledgement."} +├── lock: {"zh": "只问不喂;不调用say、不改脑、不直接执行命令。飞书个人身份与记忆仍属于晓,零点原核回答不冒充晓本人。", "en": "Read-only questions never feed, edit brains or execute commands. Xiao retains its identity and memory; Zero Core replies do not impersonate Xiao."} +├── why: {"zh": "复用已有常在线京东及零点问答,不需要飞书AI付费托管。技能说明与真实HTTP客户端一并交付,飞书适配器仍待接线。", "en": "Reuse existing always-on JD and Zero Core without a paid Feishu AI runtime. Deliver real HTTP client code with the skill; the Feishu adapter remains pending."} +├── rejected: {"zh": "协议格式、checksum、sender字段均不授予执行权或证明真人。身份范围来自独立传输凭据;不把问答写成本人直接原话或学习事件。", "en": "Protocol syntax, checksums and sender fields do not confer authority or prove a human. Independent transport credentials constrain sender scope; questions are not direct-human food or learning events."} +├── sources: {"zh": "冰朔本任务直接原话和已核通信协议来源。", "en": "Current owner language and verified communication standards.", "method_sha256": "6b6fb0efd7816dfc28ccf4acd0ae3d8aee04ac4400c6253d650e6b7d1a069789", "authorization_sha256": "4ccd2207a0ee63978b7e1ac8e488679038b9fbfd12c8d1066ca7e75f7dad1415", "protocol_pins": [{"id": "GLS-0300", "sha256": "9d02bb01a7f2ff7b9f7a4dbefe356cd823e71095aa1dcf0e9cc3c98cd3417be2"}, {"id": "GLS-0302", "sha256": "1e8b06ca9bcde879b0295226b9d55ed782db75266eab6a8f9bbdb3a6dedb655d"}, {"id": "GLS-0305", "sha256": "6b4ef3a9c79f9178e918bfb3109aea144f13ee7d94fe839f7ebd55b8d92fec4c"}, {"id": "GLS-0306", "sha256": "8469e8284a749315755d8f3992580c1612338ab041d7b542d321de9fdeaf99b0"}]} +├── interface: {"method": "POST", "path": "/v1/glp", "message_types": ["REQUEST", "SYNC"], "sender_scope": "AUTHENTICATED_CLIENT_PERSONAS", "receiver": "ICE-CH-ZC001", "auth": "BEARER_OVER_TLS_OR_LOOPBACK", "canonical_json": "OBJECT_KEYS_SORTED_RECURSIVELY_ARRAY_ORDER_PRESERVED_UTF8", "checksum": "SHA256_CANONICAL_MESSAGE_WITH_EMPTY_INTEGRITY_CHECKSUM_AND_SIGNATURE", "signature": "EMPTY_TRANSPORT_AUTH_PROFILE_NOT_ASYMMETRIC_SIGNATURE", "max_body_bytes": 24000, "max_question_bytes": 12000, "max_ttl_seconds": 300, "rate_per_client_per_minute": 12, "global_parallel_limit": 2, "replay_scope": "PROCESS_LIFETIME_UNTIL_MESSAGE_EXPIRY", "replay_cache_capacity": 256, "replay_restart_guarantee": false, "private_question_logs": "NONE_IN_RECEIVER", "sync_adopts_rules": false, "public_routing_installed": false} +├── errors: {"unauthenticated": 401, "invalid_envelope": 400, "message_id_rebound": 409, "body_too_large": 413, "rate_or_parallel_limit": 429, "upstream_withheld": 502, "cache_full_or_receiver_failure": 503} +├── relations: {"mother": "TCS", "communication": "GLP", "history": "HLDP", "standards": "GLS"} +└── writeback: {"zh": "交付代码、技能包、测试与京东隔离验证回执;正式常驻与飞书工具配置在后续环节验收。", "en": "Deliver source, skill, tests and an isolated JD verification receipt. Persistent production operation and Feishu tool configuration are later acceptance stages."} diff --git a/skills/guanghu-feishu-glp/SKILL.md b/skills/guanghu-feishu-glp/SKILL.md new file mode 100644 index 0000000..9e6e205 --- /dev/null +++ b/skills/guanghu-feishu-glp/SKILL.md @@ -0,0 +1,21 @@ +--- +name: guanghu-feishu-glp +description: 晓在飞书向京东零点原核递送只读问答或查询世界规则版本时使用;包含GLP信封、HTTP客户端与服务器接收器。普通文档编辑或现实执行任务不适用。 +--- + +先读同目录 PROFILE.hldp 和飞书办公室的原话瞄点。该目录是可单独复制的技能包,包含 contract.mjs、client.mjs、receiver.mjs 和测试;服务器部署来源是已核字节包。 + +从本技能目录运行: + + node client.mjs build 问题.txt 本任务原生会话号 本任务工单号 > request.json + node client.mjs send request.json https://本人配置的服务/v1/glp + +发送需在私有环境提供 GUANGHU_GLP_TOKEN,不能写入技能、仓库、文档或日志。服务地址必须由用户的部署配置明确给出;本包没有可自动使用的公网端点。当前只做京东隔离验证,飞书收发适配器尚未接通。飞书端若无执行本脚本的工具,需要后续桥接器提供等价HTTP调用;阅读技能本身不会产生工具能力。 + +REQUEST 表示只读问题;build 命令第四个参数 SYNC 表示只查询公开规则发行版本。SYNC返回可核验版本与哈希,不自动采纳规则,更不是完整人格脑同步。GLP请求只送入外部问题入口,不冒充冰朔本人语言,不写零点或晓的脑。 + +ACK-RECEIVED是收到;RESPONSE承载结果;ACK-EXECUTED是已完成本次只读查询。失败返回ACK-FAILED,不能把收到写成执行成功。一次HTTP返回这些独立阶段,不提供立即流式ACK。网络重试复用同一份 request.json 和 message_id;相同编号改内容会拒绝。过期后重新生成请求;进程重启不保证去重延续,禁止拿本包执行不可重复的现实动作。 + +checksum只证明字节一致,不是身份签名;发送主体范围由独立传输凭据约束。本工程剖面使用空signature。需要人类身份、学习、写入或现实动作时走相应系统的既有入口,不能扩展本问答接口。 + +本地验证:node --test receiver.test.mjs。服务器由操作者设置 GUANGHU_GLP_CONFIG 指向既有私有客户端哈希配置,并以 GUANGHU_GLP_PORT 指定空闲端口运行 node receiver.mjs;接收器始终只绑定127.0.0.1。默认后端固定为本机3931零点ask和3922公开规则manifest,不接受消息指定目标URL、文件路径或命令。 diff --git a/skills/guanghu-feishu-glp/client.mjs b/skills/guanghu-feishu-glp/client.mjs new file mode 100644 index 0000000..d81dd23 --- /dev/null +++ b/skills/guanghu-feishu-glp/client.mjs @@ -0,0 +1,7 @@ +import fs from 'node:fs';import {request} from './contract.mjs'; +const [mode,...a]=process.argv.slice(2); +try{ + if(mode==='build'){if(a.length<3||a.length>4)throw Error('QUESTION_FILE_SESSION_TASK_REQUIRED');console.log(JSON.stringify(request(fs.readFileSync(a[0],'utf8'),{session:a[1],task:a[2],type:a[3]||'REQUEST'}),null,2));} + else if(mode==='send'){if(a.length!==2||!process.env.GUANGHU_GLP_TOKEN)throw Error('MESSAGE_URL_AND_PRIVATE_TOKEN_REQUIRED');const u=new URL(a[1]);if(u.username||u.password||u.search||u.hash||u.pathname!=='/v1/glp'||!(u.protocol==='https:'||(u.protocol==='http:'&&['127.0.0.1','[::1]'].includes(u.hostname))))throw Error('GLP_ENDPOINT_INVALID');const r=await fetch(u,{method:'POST',redirect:'error',headers:{'content-type':'application/json',authorization:'Bearer '+process.env.GUANGHU_GLP_TOKEN},body:fs.readFileSync(a[0]),signal:AbortSignal.timeout(65000)});console.log(JSON.stringify(await r.json(),null,2));if(!r.ok)process.exitCode=2;} + else throw Error('COMMAND_NOT_SUPPORTED'); +}catch(e){console.log(JSON.stringify({error:/^[A-Z_]+$/.test(e.message)?e.message:'GLP_TRANSPORT_FAILED'}));process.exitCode=2;} diff --git a/skills/guanghu-feishu-glp/contract.mjs b/skills/guanghu-feishu-glp/contract.mjs new file mode 100644 index 0000000..c698b8f --- /dev/null +++ b/skills/guanghu-feishu-glp/contract.mjs @@ -0,0 +1,29 @@ +import crypto from 'node:crypto'; +export const ZERO='GLW-2.0-BRAIN-BINGSHUO-MASTER-0001', CHANNEL='ICE-CH-ZC001'; +export const canonical=x=>Array.isArray(x)?'['+x.map(canonical).join(',')+']':x&&typeof x==='object'?'{'+Object.keys(x).sort().map(k=>JSON.stringify(k)+':'+canonical(x[k])).join(',')+'}':JSON.stringify(x); +export const hash=x=>crypto.createHash('sha256').update(typeof x==='string'?x:canonical(x)).digest('hex'); +export function seal(m){const c=structuredClone(m);c.integrity={checksum:'',signature:''};c.integrity.checksum=hash(c);return {glp_message:c};} +export function request(question,{type='REQUEST',id=crypto.randomUUID(),sender='ICE-P-X1016',session,task,now=Date.now()}={}){ + return seal({protocol:'GLP/1.0',message_id:id,message_type:type,created_at:new Date(now).toISOString(),sender:{object_id:sender,object_type:'persona',world_path:'glw://GLW-2.0-0001/persona/'+sender},receiver:{object_id:CHANNEL,object_type:'channel',routing_mode:'direct'},context:{conversation_id:session,parent_message_id:'',relation_id:'',task_id:task,hldp_anchor:''},payload:{language:'zh-CN',content_type:'text',content:question,attachments:[]},control:{priority:'normal',ack_required:true,receipt_required:true,expires_at:new Date(now+300000).toISOString(),retry_policy:'safe'},integrity:{}}); +} +const need=(v,c)=>{if(!v)throw Error(c);}; +function keys(o,list){need(o&&typeof o==='object'&&!Array.isArray(o)&&Object.keys(o).length===list.length&&list.every(k=>Object.hasOwn(o,k)),'GLP_FIELDS_INVALID');} +export function validate(input,client,now=Date.now()){ + keys(input,['glp_message']);const m=input.glp_message; + keys(m,['protocol','message_id','message_type','created_at','sender','receiver','context','payload','control','integrity']); + need(m.protocol==='GLP/1.0'&&['REQUEST','SYNC'].includes(m.message_type),'GLP_TYPE_UNSUPPORTED'); + need(typeof m.message_id==='string'&&/^[-A-Za-z0-9._:]{1,160}$/.test(m.message_id),'GLP_ID_INVALID'); + keys(m.sender,['object_id','object_type','world_path']);need(m.sender.object_type==='persona'&&client.personas?.includes(m.sender.object_id),'GLP_SENDER_OUTSIDE_SCOPE'); + need(m.sender.world_path==='glw://GLW-2.0-0001/persona/'+m.sender.object_id,'GLP_WORLD_INVALID'); + keys(m.receiver,['object_id','object_type','routing_mode']);need(m.receiver.object_id===CHANNEL&&m.receiver.object_type==='channel'&&m.receiver.routing_mode==='direct','GLP_TARGET_INVALID'); + keys(m.context,['conversation_id','parent_message_id','relation_id','task_id','hldp_anchor']); + need(Object.values(m.context).every(x=>typeof x==='string'&&x.length<=300)&&m.context.conversation_id.trim()&&m.context.task_id.trim(),'GLP_CONTEXT_REQUIRED'); + keys(m.payload,['language','content_type','content','attachments']);need(m.payload.language==='zh-CN'&&m.payload.content_type==='text'&&typeof m.payload.content==='string'&&m.payload.content.trim()&&Buffer.byteLength(m.payload.content)<=12000&&Array.isArray(m.payload.attachments)&&m.payload.attachments.length===0,'GLP_PAYLOAD_INVALID'); + keys(m.control,['priority','ack_required','receipt_required','expires_at','retry_policy']); + const created=Date.parse(m.created_at),expires=Date.parse(m.control.expires_at); + need(Number.isFinite(created)&&Number.isFinite(expires)&&created<=now+30000&&expires>now&&expires>created&&expires-created<=300000,'GLP_EXPIRED_OR_TIME_INVALID'); + need(['normal','low'].includes(m.control.priority)&&m.control.ack_required===true&&typeof m.control.receipt_required==='boolean'&&['none','safe'].includes(m.control.retry_policy),'GLP_CONTROL_UNSUPPORTED'); + keys(m.integrity,['checksum','signature']);need(m.integrity.signature===''&&/^[a-f0-9]{64}$/.test(m.integrity.checksum),'GLP_INTEGRITY_INVALID'); + const clean=structuredClone(m);clean.integrity.checksum='';need(hash(clean)===m.integrity.checksum,'GLP_CHECKSUM_MISMATCH');return m; +} +export function reply(m,type,content){return seal({protocol:'GLP/1.0',message_id:crypto.randomUUID(),message_type:type,created_at:new Date().toISOString(),sender:{object_id:ZERO,object_type:'system',world_path:'glw://GLW-2.0-0001/channel/'+CHANNEL},receiver:{object_id:m.sender.object_id,object_type:m.sender.object_type,routing_mode:'direct'},context:{...m.context,parent_message_id:m.message_id},payload:{language:'zh-CN',content_type:'state',content,attachments:[]},control:{priority:'normal',ack_required:false,receipt_required:false,expires_at:m.control.expires_at,retry_policy:'none'},integrity:{}}).glp_message;} diff --git a/skills/guanghu-feishu-glp/receiver.mjs b/skills/guanghu-feishu-glp/receiver.mjs new file mode 100644 index 0000000..b5e293a --- /dev/null +++ b/skills/guanghu-feishu-glp/receiver.mjs @@ -0,0 +1,38 @@ +import http from 'node:http';import fs from 'node:fs';import crypto from 'node:crypto';import {pathToFileURL} from 'node:url'; +import {ZERO,hash,validate,reply} from './contract.mjs'; +const need=(v,c)=>{if(!v)throw Error(c);}; +export function authenticate(raw,config,now=Date.now()){ + if(typeof raw!=='string'||!raw.startsWith('Bearer '))return null;const digest=hash(raw.slice(7)); + return config.clients?.find(c=>/^[a-f0-9]{64}$/.test(c.key_sha256||'')&&crypto.timingSafeEqual(Buffer.from(digest,'hex'),Buffer.from(c.key_sha256,'hex'))&&Date.parse(c.expires_at)>now)||null; +} +async function json(url,options={}){const r=await fetch(url,{...options,redirect:'error',signal:AbortSignal.timeout(55000)});need(r.ok,'ZERO_UPSTREAM_UNAVAILABLE');return r.json();} +export async function zeroQuestion(text,{get=json}={}){ + const before=await get('http://127.0.0.1:3931/status');need(before.brain_id===ZERO&&before.integrity==='BRAIN_VERIFIED'&&before.node_role==='REPLICA_READ_ONLY'&&before.brain_write_allowed===false,'ZERO_IDENTITY_OR_ROLE_INVALID'); + const r=await get('http://127.0.0.1:3931/ask',{method:'POST',headers:{'content-type':'application/json'},body:JSON.stringify({text})}); + need(r.schema==='guanghu.zeropoint-channel-ask-receipt/v1'&&r.no_state_change===true&&r.brain_turn?.speaker?.brain_id===ZERO&&r.brain_turn.brain_revision===before.revision&&r.brain_turn.no_state_change===true&&r.brain_turn.input_sha256===hash(text)&&r.brain_turn.reply_sha256===hash(r.spoken)&&r.brain_turn.reply===r.spoken&&r.brain_turn?.outcome==='BRAIN_REPLY_ACCEPTED'&&typeof r.spoken==='string'&&r.spoken.trim(),'ZERO_REPLY_WITHHELD'); + const after=await get('http://127.0.0.1:3931/status');need(after.brain_id===before.brain_id&&after.integrity==='BRAIN_VERIFIED','ZERO_IDENTITY_CHANGED'); + need(after.node_role==='REPLICA_READ_ONLY'&&after.brain_write_allowed===false&&after.revision===before.revision,'ZERO_SOURCE_CHANGED'); + return {brain_id:ZERO,revision:before.revision,answer:r.spoken,no_state_change:true}; +} +export function createReceiver({config,ask=zeroQuestion,rules=async()=>{const r=await json('http://127.0.0.1:3922/v1/manifest');need(typeof r.version==='string'&&/^[a-f0-9]{64}$/.test(r.bundle_sha256),'RULE_RELEASE_INVALID');return {version:r.version,bundle_sha256:r.bundle_sha256,bundle_url:r.bundle_url,automatic_adoption:false};},now=Date.now,capacity=256}={}){ + const messages=new Map(),buckets=new Map();let active=0; + const send=(res,status,data)=>{res.writeHead(status,{'content-type':'application/json; charset=utf-8','cache-control':'no-store','x-content-type-options':'nosniff'});res.end(JSON.stringify(data));}; + const server=http.createServer(async(req,res)=>{try{ + if(req.method==='GET'&&req.url==='/health')return send(res,200,{state:'GLP_RECEIVER_READY',profile:'FEISHU_ZERO_READONLY_1',production_feishu_connected:false,no_execution_authority:true}); + if(req.method!=='POST'||req.url!=='/v1/glp')return send(res,404,{error:'ROUTE_NOT_REGISTERED'}); + const c=authenticate(req.headers.authorization,config);if(!c)return send(res,401,{error:'GLP_AUTH_REQUIRED'}); + if(!String(req.headers['content-type']||'').startsWith('application/json'))return send(res,415,{error:'JSON_REQUIRED'}); + const chunks=[];let size=0;for await(const b of req){size+=b.length;if(size>24000)return send(res,413,{error:'GLP_BODY_TOO_LARGE'});chunks.push(b);} + let input,m;try{input=JSON.parse(Buffer.concat(chunks));m=validate(input,c,now());}catch(e){return send(res,400,{error:/^[A-Z_]+$/.test(e.message)?e.message:'GLP_JSON_INVALID'});} + const k=c.id+':'+m.message_id,digest=hash(input),old=messages.get(k);if(old){if(old.digest!==digest)return send(res,409,{error:'GLP_MESSAGE_ID_REBOUND'});const r=await old.promise;return send(res,r.status,r.value);} + for(const [id,v] of messages)if(v.expires<=now())messages.delete(id); + const bucket=buckets.get(c.id)||{start:now(),count:0};if(now()-bucket.start>=60000){bucket.start=now();bucket.count=0;}if(bucket.count>=12||active>=2)return send(res,429,{error:'GLP_CAPACITY_LIMIT'});if(messages.size>=capacity)return send(res,503,{error:'GLP_REPLAY_CACHE_FULL'});bucket.count++;buckets.set(c.id,bucket);active++; + const ack=reply(m,'ACK',{status:'ACK-RECEIVED'});const promise=(async()=>{try{ + const result=m.message_type==='REQUEST'?await ask(m.payload.content):await rules(); + const response=reply(m,'RESPONSE',result),receipt=reply(m,'RECEIPT',{status:'ACK-EXECUTED',operation:m.message_type==='REQUEST'?'READ_ONLY_ZERO_QUESTION':'RULE_VERSION_QUERY',no_neural_state_write:true,no_execution_authority:true}); + return {status:200,value:{schema:'guanghu.glp-readonly-exchange/v1',request_id:m.message_id,ack,response,...(m.control.receipt_required?{receipt}:{}),no_execution_authority:true}}; + }catch{return {status:502,value:{error:'GLP_UPSTREAM_UNAVAILABLE',request_id:m.message_id,ack:reply(m,'ACK',{status:'ACK-RECEIVED'}),receipt:reply(m,'RECEIPT',{status:'ACK-FAILED',reply_withheld:true}),no_execution_authority:true}};}finally{active--;}})(); + messages.set(k,{digest,promise,expires:Date.parse(m.control.expires_at)});const r=await promise;send(res,r.status,r.value); + }catch{if(!res.headersSent)send(res,503,{error:'GLP_RECEIVER_UNAVAILABLE'});else res.destroy();}});server.requestTimeout=65000;server.headersTimeout=10000;return server; +} +if(process.argv[1]&&import.meta.url===pathToFileURL(process.argv[1]).href){const file=process.env.GUANGHU_GLP_CONFIG;need(file,'GLP_CONFIG_REQUIRED');createReceiver({config:JSON.parse(fs.readFileSync(file))}).listen(Number(process.env.GUANGHU_GLP_PORT||3926),'127.0.0.1');} diff --git a/skills/guanghu-feishu-glp/receiver.test.mjs b/skills/guanghu-feishu-glp/receiver.test.mjs new file mode 100644 index 0000000..8daaa82 --- /dev/null +++ b/skills/guanghu-feishu-glp/receiver.test.mjs @@ -0,0 +1,22 @@ +import test from 'node:test';import assert from 'node:assert/strict';import {request,seal,hash,ZERO,validate} from './contract.mjs';import {createReceiver,zeroQuestion} from './receiver.mjs'; +const token='fixture-not-real-secret',client={id:'fixture',key_sha256:hash(token),expires_at:'2099-01-01T00:00:00Z',personas:['ICE-P-X1016']}; +const native=(answer,revision=5,text='q')=>({schema:'guanghu.zeropoint-channel-ask-receipt/v1',no_state_change:true,spoken:answer,brain_turn:{speaker:{brain_id:ZERO},brain_revision:revision,no_state_change:true,input_sha256:hash(text),reply_sha256:hash(answer),reply:answer,outcome:'BRAIN_REPLY_ACCEPTED'}}); +const make=()=>request('请说明这次只读问答的边界。',{session:'fixture-session',task:'fixture-task'}); +async function fixture(t,extra={}){let calls=0;const server=createReceiver({config:{clients:[client]},ask:async()=>{calls++;return {brain_id:ZERO,answer:'只读测试回答',no_state_change:true};},rules:async()=>({version:'fixture',automatic_adoption:false}),...extra});await new Promise(r=>server.listen(0,'127.0.0.1',r));t.after(()=>{server.closeAllConnections();server.close();});return {calls:()=>calls,url:'http://127.0.0.1:'+server.address().port,post:async(b=make(),auth=token)=>fetch('http://127.0.0.1:'+server.address().port+'/v1/glp',{method:'POST',headers:{'content-type':'application/json',...(auth?{authorization:'Bearer '+auth}:{})},body:JSON.stringify(b)})};} +test('anonymous requests and wrong routes never invoke a brain',async t=>{const f=await fixture(t);assert.equal((await f.post(make(),null)).status,401);assert.equal((await fetch(f.url+'/say',{method:'POST'})).status,404);assert.equal(f.calls(),0);}); +test('valid GLP returns received, response and executed as separate stages',async t=>{const f=await fixture(t),m=make(),r=await f.post(m),j=await r.json();assert.equal(r.status,200);assert.equal(r.headers.get('cache-control'),'no-store');assert.equal(j.ack.message_type,'ACK');assert.equal(j.response.message_type,'RESPONSE');assert.equal(j.receipt.payload.content.status,'ACK-EXECUTED');assert.equal(j.response.context.parent_message_id,m.glp_message.message_id);assert.equal(j.no_execution_authority,true);}); +test('checksum, foreign persona, target, expiry and missing task are rejected',async t=>{const f=await fixture(t);for(const alter of [m=>m.payload.content+='变更',m=>m.sender.object_id='ICE-P-OTHER',m=>m.receiver.object_id='other',m=>m.control.expires_at='2000-01-01',m=>m.context.task_id='']){const m=make().glp_message;alter(m);const b=seal(m);if(m.payload.content.endsWith('变更'))b.glp_message.integrity.checksum='0'.repeat(64);assert.equal((await f.post(b)).status,400);}assert.equal(f.calls(),0);}); +test('extra execution fields and unsupported message types are rejected',async t=>{const f=await fixture(t);for(const alter of [m=>m.payload.command='rm',m=>m.message_type='BROADCAST',m=>m.integrity.signature='self-signed',m=>m.payload.attachments.push({url:'http://internal'})]){const m=make().glp_message;alter(m);const b=seal(m);if(m.integrity.signature)b.glp_message.integrity.signature='self-signed';assert.equal((await f.post(b)).status,400);}assert.equal(f.calls(),0);}); +test('exact replay returns one result; same id with new content conflicts',async t=>{const f=await fixture(t),m=make();const a=await(await f.post(m)).json(),b=await(await f.post(m)).json();assert.deepEqual(a,b);const changed=structuredClone(m.glp_message);changed.payload.content='另一问题';assert.equal((await f.post(seal(changed))).status,409);assert.equal(f.calls(),1);}); +test('concurrent retries share the same pending question',async t=>{let release,calls=0;const blocked=new Promise(r=>release=r),f=await fixture(t,{ask:async()=>{calls++;await blocked;return {answer:'ok'};}}),m=make();const a=f.post(m),b=f.post(m);await new Promise(r=>setTimeout(r,30));release();const [x,y]=await Promise.all([a,b]);assert.equal(x.status,200);assert.equal(y.status,200);assert.equal(calls,1);}); +test('SYNC queries release metadata without calling a brain or adopting rules',async t=>{const f=await fixture(t),j=await(await f.post(request('当前发行版本',{type:'SYNC',session:'s',task:'t'}))).json();assert.equal(j.response.payload.content.version,'fixture');assert.equal(j.response.payload.content.automatic_adoption,false);assert.equal(f.calls(),0);}); +test('upstream failure is withheld and cached with failed receipt',async t=>{let calls=0;const f=await fixture(t,{ask:async()=>{calls++;throw Error('secret /private/path');}}),m=make();for(let i=0;i<2;i++){const r=await f.post(m),j=await r.json();assert.equal(r.status,502);assert.equal(j.receipt.payload.content.status,'ACK-FAILED');assert.equal(JSON.stringify(j).includes('secret'),false);}assert.equal(calls,1);}); +test('a full replay cache refuses new requests instead of evicting live ids',async t=>{const f=await fixture(t,{capacity:1});assert.equal((await f.post()).status,200);assert.equal((await f.post()).status,503);assert.equal(f.calls(),1);}); +test('oversized messages do not reach a brain',async t=>{const f=await fixture(t);assert.equal((await f.post({padding:'x'.repeat(25000)})).status,413);const m=make();assert.throws(()=>validate(m,{personas:[]}),/SENDER/);}); +test('native Zero adapter checks own identity and read-only reply',async()=>{const status={brain_id:ZERO,revision:5,integrity:'BRAIN_VERIFIED',node_role:'REPLICA_READ_ONLY',brain_write_allowed:false};let urls=[];const get=async(u,o)=>{urls.push(u);if(u.endsWith('/status'))return status;assert.equal(JSON.parse(o.body).text,'q');return native('已核验回答');};assert.equal((await zeroQuestion('q',{get})).revision,5);assert.equal(urls.filter(x=>x.endsWith('/ask')).length,1);assert.equal(urls.some(x=>x.endsWith('/say')),false);}); +test('native adapter withholds wrong identity, rejected reply and changed source',async()=>{const status={brain_id:ZERO,revision:5,integrity:'BRAIN_VERIFIED',node_role:'REPLICA_READ_ONLY',brain_write_allowed:false};await assert.rejects(zeroQuestion('q',{get:async()=>({...status,brain_id:'other'})}),/IDENTITY/);await assert.rejects(zeroQuestion('q',{get:async u=>u.endsWith('/status')?status:{no_state_change:false}}),/WITHHELD/);let reads=0;await assert.rejects(zeroQuestion('q',{get:async u=>u.endsWith('/status')?{...status,revision:5+reads++}:native('x')}),/SOURCE_CHANGED/);}); + +test('expired credentials cannot enter the receiver',async t=>{const f=await fixture(t,{config:{clients:[{...client,expires_at:'2000-01-01T00:00:00Z'}]}});assert.equal((await f.post()).status,401);assert.equal(f.calls(),0);}); +test('new requests are rate limited while exact retries stay cached',async t=>{const f=await fixture(t);for(let i=0;i<12;i++)assert.equal((await f.post()).status,200);assert.equal((await f.post()).status,429);assert.equal(f.calls(),12);}); + +test('native reply speaker, input digest and reply digest must match',async()=>{const status={brain_id:ZERO,revision:5,integrity:'BRAIN_VERIFIED',node_role:'REPLICA_READ_ONLY',brain_write_allowed:false};for(const mutate of [r=>r.brain_turn.speaker.brain_id='foreign',r=>r.brain_turn.input_sha256='0'.repeat(64),r=>r.spoken='changed',r=>r.brain_turn.brain_revision=4]){const r=native('answer');mutate(r);await assert.rejects(zeroQuestion('q',{get:async u=>u.endsWith('/status')?status:r}),/WITHHELD/);}});