Unify Epiphany operator request v1
This commit is contained in:
parent
225859bd7e
commit
6491f449cf
10 changed files with 13 additions and 13 deletions
|
|
@ -196,9 +196,9 @@ The command is a dry-run shape probe for public surfaces that are real enough to
|
|||
|
||||
VoidBot remains the Discord observer and mention scheduler. A Face registry entry may opt into a remote `remotePersonaFeedbackTarget`; only then does VoidBot insert an immutable typed `voidbot.discord.persona_feedback_event.v0` observation into the dedicated `BIFROST_PERSONA_FEEDBACK_OBSERVATION_STORE_PATH`. This is an observation inbox, never an actuator queue. Insert collisions must contain exactly equal content. Its canonical path and physical file identity must differ from the outbound Discord-command provider store and all Bifrost-private state. Local Persona mention handling is committed first; observation export runs independently with three bounded idempotent attempts and cannot suppress the local response path.
|
||||
|
||||
Discord operator control is a separate authority. VoidBot may insert only a strict `voidbot.discord.epiphany_operator_request.v0` document containing one of `status`, `sleep`, `wake`, or `directive`, a fixed target runtime, Discord provenance, and a positive expiry of at most 60 seconds. Bifrost independently requires the exact configured Discord owner and the exact persisted guild/actor mapping from its private actor-link store. The actor link is the admitted mapping authority; its Heimdall reference remains provenance until a signed live Heimdall claim surface exists and is not represented as authorization. Bifrost derives the Rust field-order packet tuple, hashes its canonical MessagePack bytes, and signs the exact `BifrostOperatorCommandAdmission` tuple for purpose `bifrost.operator-command.delivery.v0` with a dedicated operator Ed25519 seed. The feedback seed is not reused.
|
||||
Discord operator control is a separate authority. VoidBot may insert only a strict `voidbot.discord.epiphany_operator_request.v1` document containing one of `status`, `sleep`, `wake`, `directive`, `reviews`, or `review`, a fixed target runtime, Discord provenance, and a positive expiry of at most 60 seconds. Bifrost independently requires the exact configured Discord owner and the exact persisted guild/actor mapping from its private actor-link store. The actor link is the admitted mapping authority; its Heimdall reference remains provenance until a signed live Heimdall claim surface exists and is not represented as authorization. Bifrost derives the Rust field-order packet tuple, hashes its canonical MessagePack bytes, and signs the exact `BifrostOperatorCommandAdmission` tuple for purpose `bifrost.operator-command.delivery.v1` with a dedicated operator Ed25519 seed. The feedback seed is not reused.
|
||||
|
||||
Bifrost does not mount an Epiphany store and has no argv or shell escape hatch. One supervised worker serializes requests across the CultNet RUDP boundary and requires the trusted Epiphany executor anchor. Success requires a host-signed `epiphany.operator_command.sealed_result.v0` whose payload digest, command id, packet digest, target runtime, completion time, and executor identity verify exactly; a transport acknowledgement is not success. Admissions and sealed results are persisted in the typed Bifrost operator ledger. Permanent pre-admission refusals are separately terminalized there, while transport failures remain retryable. An expired request cannot mint a new admission, but an exact admission already durably recorded before expiry may be retransmitted to recover Epiphany's one idempotent result without depending on mutable actor-link or signer state. The worker publishes a separate immutable Discord-delivery projection bound to the original request digest and interaction id; it exposes only bounded result/refusal fields and sealed-result fingerprints, never raw signatures or private state. VoidBot reads that outbox and owns Discord response/checkpoint state. Bifrost never manufactures success. Ordinary Persona messages remain `feedback_only` and cannot enter this path.
|
||||
Bifrost does not mount an Epiphany store and has no argv or shell escape hatch. One supervised worker serializes requests across the CultNet RUDP boundary and requires the trusted Epiphany executor anchor. Success requires a host-signed `epiphany.operator_command.sealed_result.v1` whose payload digest, command id, packet digest, target runtime, completion time, and executor identity verify exactly; a transport acknowledgement is not success. Admissions and sealed results are persisted in the typed Bifrost operator ledger. Permanent pre-admission refusals are separately terminalized there, while transport failures remain retryable. An expired request cannot mint a new admission, but an exact admission already durably recorded before expiry may be retransmitted to recover Epiphany's one idempotent result without depending on mutable actor-link or signer state. The worker publishes a separate immutable Discord-delivery projection bound to the original request digest and interaction id; it exposes only bounded result/refusal fields and sealed-result fingerprints, never raw signatures or private state. VoidBot reads that outbox and owns Discord response/checkpoint state. Bifrost never manufactures success. Ordinary Persona messages remain `feedback_only` and cannot enter this path. Durable v0 admissions/results are replay-only and cannot acquire the review vocabulary.
|
||||
|
||||
Bifrost admits an observation only when guild, channel, target runtime, canonical repository, Persona, producer, and producer runtime match a preconfigured `bifrost.persona_feedback.target_binding.v0` document in Bifrost's private provider store. That binding also owns source visibility, data classification, and the delivery-store target. Bifrost never infers public visibility from Discord identifiers. It classifies the author using its own `bifrost.discord.actor_link.v0` state: a match yields `linked_governance_feedback`; absence yields `unlinked_social_feedback`. Neither class grants adoption, work, release, or deployment authority.
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
- Owner: Bifrost alone authenticates a Discord operator request, resolves the
|
||||
persisted Discord-to-Bifrost actor link, and signs an expiring Epiphany
|
||||
admission. Epiphany alone decides and applies the named command.
|
||||
- Inputs: one strict `voidbot.discord.epiphany_operator_request.v0`, the exact
|
||||
- Inputs: one strict `voidbot.discord.epiphany_operator_request.v1`, the exact
|
||||
configured Discord owner, a persisted Bifrost actor link, the deployment's
|
||||
operator signing identity, and the configured Epiphany runtime/host trust
|
||||
anchor.
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ public sealed class ProviderAdvertisementTests
|
|||
AssertEndpoint(root, "crossing-receipts", "bifrost.crossing_receipt.v1", "bridge");
|
||||
AssertEndpoint(root, "patron-support-intake", "bifrost.patron_support_event.v0", "patronage");
|
||||
AssertEndpoint(root, "github-webhooks", "bifrost.work_item.v0", "github");
|
||||
AssertEndpoint(root, "epiphany-operator-requests", "voidbot.discord.epiphany_operator_request.v0", "operator");
|
||||
AssertEndpoint(root, "epiphany-operator-requests", "voidbot.discord.epiphany_operator_request.v1", "operator");
|
||||
AssertEndpoint(root, "epiphany-operator-results", "epiphany.operator_command.sealed_result.v1", "epiphany");
|
||||
Assert.Equal("asgard.yggdrasil.bifrost", root.GetProperty("locatedService").GetString());
|
||||
AssertSchemaPurpose(root, "bifrost.crossing_receipt.v1", "canonical Bifrost-owned public crossing receipt");
|
||||
|
|
|
|||
|
|
@ -4,14 +4,14 @@ import {admissionTuple,packetTuple,parseOperatorRequest} from "../tools/epiphany
|
|||
import {verifyPurpose} from "../tools/bifrost-signed-identity.mjs";
|
||||
const cultLibRoot=process.env.VOIDBOT_CULTLIB_ROOT||"E:/Projects/CultLib",requireCult=createRequire(resolve(cultLibRoot,"packages/cultnet-ts/package.json")),{encode}=requireCult("@msgpack/msgpack");
|
||||
const actorLink={guildId:"guild",discordAuthorId:"owner",bifrostActorId:"actor",heimdallActorRef:"heimdall:actor:1"};
|
||||
function request(command={kind:"status"}){return {schemaName:"voidbot.discord.epiphany_operator_request",schemaVersion:"voidbot.discord.epiphany_operator_request.v0",requestId:"interaction-1",commandId:"interaction-1",nonce:"interaction-1",sourceEventId:"interaction-1",sourceActorDiscordId:"owner",discordGuildId:"guild",discordChannelId:"channel",discordMessageId:"interaction-1",targetRuntimeId:"epiphany-yggdrasil",issuedAt:"2026-07-19T10:00:00.000Z",expiresAt:"2026-07-19T10:00:30.000Z",producerId:"voidbot",producerRuntimeId:"voidbot-yggdrasil",authorityClass:"operator_request_only",status:"pending",command};}
|
||||
function request(command={kind:"status"}){return {schemaName:"voidbot.discord.epiphany_operator_request",schemaVersion:"voidbot.discord.epiphany_operator_request.v1",requestId:"interaction-1",commandId:"interaction-1",nonce:"interaction-1",sourceEventId:"interaction-1",sourceActorDiscordId:"owner",discordGuildId:"guild",discordChannelId:"channel",discordMessageId:"interaction-1",targetRuntimeId:"epiphany-yggdrasil",issuedAt:"2026-07-19T10:00:00.000Z",expiresAt:"2026-07-19T10:00:30.000Z",producerId:"voidbot",producerRuntimeId:"voidbot-yggdrasil",authorityClass:"operator_request_only",status:"pending",command};}
|
||||
function result(admission){const value={schemaVersion:"epiphany.operator_command.result.v1",resultId:"result-1",commandId:admission.packet.commandId,packetSha256:admission.packetSha256,targetRuntimeId:admission.packet.targetRuntimeId,disposition:"observed",consequenceKind:"operator-snapshot",consequenceRef:"snapshot-1",completedAt:"2026-07-19T10:00:01.000Z",privateStateExposed:false,operatorStatus:"sleeping",stateStatus:"ready",coordinatorAction:"",brakeStatus:"engaged",detail:"bounded",reviews:[],reviewCandidateId:"",reviewDecision:""},receipt={schemaVersion:"epiphany.operator_command.sealed_result.v1",result:value,resultPayloadSha256:"sha256-result",commandId:value.commandId,packetSha256:value.packetSha256,targetRuntimeId:value.targetRuntimeId,completedAt:value.completedAt,providerIdentityId:"epiphany-host",privateStateExposed:false,executorSignature:new Uint8Array(64)};return {providerIdentityId:"epiphany-host",result:value,receipt};}
|
||||
const transport=(execute)=>({trustedIdentityId:"epiphany-host",execute,verifyReceipt:(_admission,receipt)=>receipt});
|
||||
class TestLedger{constructor(){this.requests=new Map();this.admissions=new Map();this.completions=new Map();this.terminals=new Map();}admit(id,request,value){const oldRequest=this.requests.get(id),old=this.admissions.get(id);if(oldRequest&&JSON.stringify(oldRequest)!==JSON.stringify(request)||old&&JSON.stringify(old)!==JSON.stringify(value))throw new Error("operator request identity collision");this.requests.set(id,request);this.admissions.set(id,value);}complete(_id,result,_provider,receipt){this.completions.set(result.commandId,receipt??{...result,result,providerIdentityId:"epiphany-host"});}getRequest(id){return this.requests.get(id);}getAdmission(id){return this.admissions.get(id);}getCompletion(id){return this.completions.get(id);}terminalize(value){this.terminals.set(value.requestId,value);}getTerminal(id){return this.terminals.get(id);}}
|
||||
async function identity(){const d=await mkdtemp(resolve(tmpdir(),"bifrost-operator-"));return enrollOperatorIdentity(resolve(d,"operator.seed"));}
|
||||
test("signs the exact Rust packet and admission tuples",async()=>{const id=await identity(),out=await admitOperatorRequest({request:request(),ownerDiscordId:"owner",actorLink,identity:id,encode,now:new Date("2026-07-19T10:00:01Z"),ledger:new TestLedger(),transport:transport(async a=>result(a))});assert.equal(out.admission.packetSha256,`sha256-${(await import("node:crypto")).createHash("sha256").update(encode(packetTuple(out.admission.packet))).digest("hex")}`);assert.ok(verifyPurpose(id.publicKey,OPERATOR_SIGNING_PURPOSE,encode(admissionTuple(out.admission)),out.admission.providerSignature));assert.equal(out.result.disposition,"observed");});
|
||||
test("requires exact owner and admitted Bifrost actor link",async()=>{const id=await identity();for(const args of [{ownerDiscordId:"other",actorLink},{ownerDiscordId:"owner",actorLink:null}])await assert.rejects(()=>admitOperatorRequest({request:request(),identity:id,encode,now:new Date("2026-07-19T10:00:01Z"),ledger:new TestLedger(),transport:transport(async a=>result(a)),...args}));const provenanceOnly={...actorLink,heimdallActorRef:""};assert.equal((await admitOperatorRequest({request:request(),ownerDiscordId:"owner",actorLink:provenanceOnly,identity:id,encode,now:new Date("2026-07-19T10:00:01Z"),ledger:new TestLedger(),transport:transport(async a=>result(a))})).result.disposition,"observed");});
|
||||
test("strict request, ttl, command bounds, and expiry fail closed",()=>{assert.throws(()=>parseOperatorRequest({...request(),extra:true}));assert.throws(()=>parseOperatorRequest({...request(),expiresAt:"2026-07-19T10:01:01Z"}));assert.throws(()=>parseOperatorRequest(request({kind:"argv",args:["whoami"]})));assert.throws(()=>parseOperatorRequest(request({kind:"sleep",reason:""})));});
|
||||
test("strict request, ttl, command bounds, and expiry fail closed",()=>{assert.throws(()=>parseOperatorRequest({...request(),schemaVersion:"voidbot.discord.epiphany_operator_request.v0"}));assert.throws(()=>parseOperatorRequest({...request(),extra:true}));assert.throws(()=>parseOperatorRequest({...request(),expiresAt:"2026-07-19T10:01:01Z"}));assert.throws(()=>parseOperatorRequest(request({kind:"argv",args:["whoami"]})));assert.throws(()=>parseOperatorRequest(request({kind:"sleep",reason:""})));});
|
||||
test("does not synthesize success without an authenticated transport result",async()=>{const id=await identity(),base={request:request(),ownerDiscordId:"owner",actorLink,identity:id,encode,now:new Date("2026-07-19T10:00:01Z"),ledger:new TestLedger()};await assert.rejects(()=>admitOperatorRequest(base),/authenticated Epiphany/);await assert.rejects(()=>admitOperatorRequest({...base,transport:transport(async a=>({...result(a),providerIdentityId:"impostor"}))}),/authenticated Epiphany/);await assert.rejects(()=>admitOperatorRequest({...base,transport:transport(async a=>({...result(a),result:{...result(a).result,packetSha256:"sha256-wrong"}}))}),/not bound/);});
|
||||
test("retransmits an exact durable admission after expiry without mutable actor or signer state",async()=>{const id=await identity(),ledger=new TestLedger(),r=request(),base={request:r,ownerDiscordId:"owner",actorLink,identity:id,encode,ledger};await assert.rejects(()=>admitOperatorRequest({...base,now:new Date("2026-07-19T10:00:01Z"),transport:transport(async()=>{throw new Error("lost result")})}),/lost result/);let calls=0;const recovered=await admitOperatorRequest({...base,ownerDiscordId:"rotated-owner",actorLink:null,identity:null,now:new Date("2026-07-19T10:02:00Z"),transport:transport(async a=>{calls++;return result(a)})});assert.equal(calls,1);assert.equal(recovered.recovered,true);const fresh={...r,requestId:"interaction-2",commandId:"interaction-2",nonce:"interaction-2",sourceEventId:"interaction-2",discordMessageId:"interaction-2"};await assert.rejects(()=>admitOperatorRequest({...base,request:fresh,ledger:new TestLedger(),now:new Date("2026-07-19T10:02:00Z"),transport:transport(async a=>result(a))}),error=>error.code==="expired-new-request");});
|
||||
test("does not hide command-id collisions behind an existing completion",async()=>{const id=await identity(),ledger=new TestLedger(),base={ownerDiscordId:"owner",actorLink,identity:id,encode,ledger,now:new Date("2026-07-19T10:00:01Z"),transport:transport(async a=>result(a))};await admitOperatorRequest({...base,request:request()});const collision={...request(),requestId:"interaction-alien",nonce:"alien",sourceEventId:"alien",discordMessageId:"alien"};await assert.rejects(()=>admitOperatorRequest({...base,request:collision}),error=>error.code==="command-id-collision");});
|
||||
|
|
|
|||
|
|
@ -10,6 +10,6 @@ import { resolve } from "node:path";
|
|||
import { EpiphanyOperatorDiscordOutbox } from "../tools/epiphany-operator-discord-outbox.mjs";
|
||||
|
||||
const cultLibRoot=process.env.VOIDBOT_CULTLIB_ROOT||"E:/Projects/CultLib",requireCache=createRequire(resolve(cultLibRoot,"packages/cultcache-ts/package.json")),requireNet=createRequire(resolve(cultLibRoot,"packages/cultnet-ts/package.json")),cache=requireCache("cultcache-ts"),{encode}=requireNet("@msgpack/msgpack");
|
||||
function request(id="request-1",command={kind:"status"}){return {schemaName:"voidbot.discord.epiphany_operator_request",schemaVersion:"voidbot.discord.epiphany_operator_request.v0",requestId:id,commandId:id,nonce:id,sourceEventId:id,sourceActorDiscordId:"owner",discordGuildId:"guild",discordChannelId:"ops",discordMessageId:id,targetRuntimeId:"epiphany-yggdrasil",issuedAt:"2026-07-19T12:00:00Z",expiresAt:"2026-07-19T12:01:00Z",producerId:"voidbot",producerRuntimeId:"voidbot-yggdrasil",authorityClass:"operator_request_only",status:"pending",command};}
|
||||
function request(id="request-1",command={kind:"status"}){return {schemaName:"voidbot.discord.epiphany_operator_request",schemaVersion:"voidbot.discord.epiphany_operator_request.v1",requestId:id,commandId:id,nonce:id,sourceEventId:id,sourceActorDiscordId:"owner",discordGuildId:"guild",discordChannelId:"ops",discordMessageId:id,targetRuntimeId:"epiphany-yggdrasil",issuedAt:"2026-07-19T12:00:00Z",expiresAt:"2026-07-19T12:01:00Z",producerId:"voidbot",producerRuntimeId:"voidbot-yggdrasil",authorityClass:"operator_request_only",status:"pending",command};}
|
||||
function receipt(id="request-1"){return {schemaVersion:"epiphany.operator_command.sealed_result.v1",result:{disposition:"observed",detail:"bounded",operatorStatus:"sleeping",stateStatus:"ready",coordinatorAction:"",brakeStatus:"engaged",reviews:[],reviewCandidateId:"candidate-1",reviewDecision:"hold"},resultPayloadSha256:`sha256-${"1".repeat(64)}`,providerIdentityId:"executor",executorSignature:new Uint8Array(64),completedAt:"2026-07-19T12:00:01Z",commandId:id};}
|
||||
test("Discord outbox publishes immutable request-bound completed and refused deliveries",async()=>{const root=await mkdtemp(resolve(tmpdir(),"operator-outbox-")),path=resolve(root,"deliveries.cc"),outbox=await EpiphanyOperatorDiscordOutbox.open(path,{cultcacheRuntime:cache,encode}),r=request("request-1",{kind:"review",mindRequestId:"mind-1",candidateId:"candidate-1",candidateSha256:"1".repeat(64),expectedModelRevision:41,expectedModelHash:"2".repeat(64),decision:"hold"}),completed=await outbox.publishCompleted(r,receipt());assert.equal(completed.deliveryId,r.requestId);assert.match(completed.requestPayloadSha256,/^sha256-[0-9a-f]{64}$/);assert.match(completed.executorSignatureSha256,/^sha256-[0-9a-f]{64}$/);assert.equal(completed.operatorStatus,"sleeping");assert.equal(completed.brakeStatus,"engaged");assert.equal(completed.schemaVersion,"bifrost.discord.epiphany_operator_delivery.v1");assert.equal(completed.commandId,r.commandId);assert.deepEqual(completed.reviews,[]);assert.equal(completed.reviewCandidateId,"candidate-1");assert.equal(completed.reviewDecision,"hold");assert.equal(outbox.isExactDelivery(r),true);assert.equal(outbox.isExactDelivery({...r,discordChannelId:"alien"}),false);assert.equal(completed.privateStateExposed,false);await outbox.publishCompleted(r,receipt());await assert.rejects(()=>outbox.publishCompleted({...r,command:{...r.command,candidateId:"alien"}},receipt()),/does not bind/);await assert.rejects(()=>outbox.publishCompleted(r,{...receipt(),result:{...receipt().result,disposition:"applied",detail:"changed"}}),/collision/);const refusedRequest=request("request-2"),refused=await outbox.publishRefused(refusedRequest,{failureCode:"foreign-owner",recordedAt:"2026-07-19T12:00:02Z"});assert.equal(refused.status,"refused");assert.equal(refused.failureCode,"foreign-owner");assert.equal(refused.sealedResultPayloadSha256,"");assert.deepEqual(refused.reviews,[]);assert.equal(refused.reviewCandidateId,"");assert.equal(refused.reviewDecision,"");const reopened=await EpiphanyOperatorDiscordOutbox.open(path,{cultcacheRuntime:cache,encode});assert.equal(reopened.get(r.requestId).status,"completed");assert.equal(reopened.get(refusedRequest.requestId).status,"refused");});
|
||||
|
|
|
|||
|
|
@ -9,4 +9,4 @@ import { DurableOperatorLedger } from "../tools/epiphany-operator-ledger.mjs";
|
|||
const cultLibRoot=process.env.VOIDBOT_CULTLIB_ROOT||"E:/Projects/CultLib",requireCult=createRequire(resolve(cultLibRoot,"packages/cultcache-ts/package.json")),runtime=requireCult("cultcache-ts");
|
||||
function admission(){return {schemaName:"bifrost.operator_command.delivery",schemaVersion:"bifrost.operator_command.delivery.v0",admissionId:"admission-1",packet:{commandId:"command-1",nonce:"nonce-1",sourceEventId:"event-1",sourceActorId:"actor",discordGuildId:"guild",discordChannelId:"ops",discordMessageId:"message-1",targetRuntimeId:"epiphany-yggdrasil",issuedAt:"2026-07-19T12:00:00Z",expiresAt:"2026-07-19T12:01:00Z",command:{kind:"status"}},packetSha256:"sha256-packet",sourceObserverId:"voidbot",sourceObserverRuntimeId:"voidbot-yggdrasil",provider:"bifrost",bifrostAdmissionReceiptId:"receipt-1",authority:"exact_operator_command_only",providerIdentityId:"bifrost",providerSignature:new Uint8Array(64)};}
|
||||
function receipt(){const result={schemaVersion:"epiphany.operator_command.result.v0",resultId:"result-1",commandId:"command-1",packetSha256:"sha256-packet",targetRuntimeId:"epiphany-yggdrasil",disposition:"observed",consequenceKind:"operator-snapshot",consequenceRef:"snapshot-1",completedAt:"2026-07-19T12:00:01Z",privateStateExposed:false,operatorStatus:"sleeping",stateStatus:"ready",coordinatorAction:"",brakeStatus:"engaged",detail:"bounded"};return {schemaVersion:"epiphany.operator_command.sealed_result.v0",result,resultPayloadSha256:"sha256-result",commandId:result.commandId,packetSha256:result.packetSha256,targetRuntimeId:result.targetRuntimeId,completedAt:result.completedAt,providerIdentityId:"epiphany",privateStateExposed:false,executorSignature:new Uint8Array(64)};}
|
||||
test("durable operator ledger survives restart and refuses admission/result collisions",async()=>{const root=await mkdtemp(resolve(tmpdir(),"operator-ledger-")),path=resolve(root,"ledger.cc"),first=await DurableOperatorLedger.open(path,{cultcacheRuntime:runtime}),a=admission(),request={schemaName:"voidbot.discord.epiphany_operator_request",schemaVersion:"voidbot.discord.epiphany_operator_request.v0",requestId:a.admissionId,commandId:a.packet.commandId,nonce:a.packet.nonce,sourceEventId:a.packet.sourceEventId,sourceActorDiscordId:"owner",discordGuildId:a.packet.discordGuildId,discordChannelId:a.packet.discordChannelId,discordMessageId:a.packet.discordMessageId,targetRuntimeId:a.packet.targetRuntimeId,issuedAt:a.packet.issuedAt,expiresAt:a.packet.expiresAt,producerId:"voidbot",producerRuntimeId:a.sourceObserverRuntimeId,authorityClass:"operator_request_only",status:"pending",command:a.packet.command},r=receipt(),terminal={schemaVersion:"bifrost.operator_command.terminal.v0",requestId:"rejected-1",commandId:"rejected-1",status:"refused",failureCode:"foreign-owner",recordedAt:"2026-07-19T12:00:00Z",retryable:false,privateStateExposed:false};await first.admit(a.admissionId,request,a);await first.complete(a.admissionId,r.result,r.providerIdentityId,r);await first.terminalize(terminal);const reopened=await DurableOperatorLedger.open(path,{cultcacheRuntime:runtime});assert.equal(reopened.getRequest(a.admissionId).sourceActorDiscordId,"owner");assert.equal(reopened.getAdmission(a.admissionId).packetSha256,a.packetSha256);assert.equal(reopened.getCompletion(r.commandId).result.resultId,r.result.resultId);assert.equal(reopened.getTerminal(terminal.requestId).failureCode,"foreign-owner");await reopened.admit(a.admissionId,request,a);await reopened.complete(a.admissionId,r.result,r.providerIdentityId,r);await reopened.terminalize(terminal);await assert.rejects(()=>reopened.admit(a.admissionId,{...request,sourceActorDiscordId:"alien"},a),/collision/);await assert.rejects(()=>reopened.admit(a.admissionId,request,{...a,packetSha256:"sha256-alien"}),/collision/);await assert.rejects(()=>reopened.complete(a.admissionId,{...r.result,detail:"alien"},r.providerIdentityId,{...r,result:{...r.result,detail:"alien"}}),/collision/);await assert.rejects(()=>reopened.complete(a.admissionId,{...r.result,packetSha256:"sha256-alien"},r.providerIdentityId,{...r,packetSha256:"sha256-alien",result:{...r.result,packetSha256:"sha256-alien"}}),/exact durable admission/);await assert.rejects(()=>reopened.terminalize({...terminal,failureCode:"alien"}),/collision/);});
|
||||
test("durable operator ledger survives restart and refuses admission/result collisions",async()=>{const root=await mkdtemp(resolve(tmpdir(),"operator-ledger-")),path=resolve(root,"ledger.cc"),first=await DurableOperatorLedger.open(path,{cultcacheRuntime:runtime}),a=admission(),request={schemaName:"voidbot.discord.epiphany_operator_request",schemaVersion:"voidbot.discord.epiphany_operator_request.v1",requestId:a.admissionId,commandId:a.packet.commandId,nonce:a.packet.nonce,sourceEventId:a.packet.sourceEventId,sourceActorDiscordId:"owner",discordGuildId:a.packet.discordGuildId,discordChannelId:a.packet.discordChannelId,discordMessageId:a.packet.discordMessageId,targetRuntimeId:a.packet.targetRuntimeId,issuedAt:a.packet.issuedAt,expiresAt:a.packet.expiresAt,producerId:"voidbot",producerRuntimeId:a.sourceObserverRuntimeId,authorityClass:"operator_request_only",status:"pending",command:a.packet.command},r=receipt(),terminal={schemaVersion:"bifrost.operator_command.terminal.v0",requestId:"rejected-1",commandId:"rejected-1",status:"refused",failureCode:"foreign-owner",recordedAt:"2026-07-19T12:00:00Z",retryable:false,privateStateExposed:false};await first.admit(a.admissionId,request,a);await first.complete(a.admissionId,r.result,r.providerIdentityId,r);await first.terminalize(terminal);const reopened=await DurableOperatorLedger.open(path,{cultcacheRuntime:runtime});assert.equal(reopened.getRequest(a.admissionId).sourceActorDiscordId,"owner");assert.equal(reopened.getAdmission(a.admissionId).packetSha256,a.packetSha256);assert.equal(reopened.getCompletion(r.commandId).result.resultId,r.result.resultId);assert.equal(reopened.getTerminal(terminal.requestId).failureCode,"foreign-owner");await reopened.admit(a.admissionId,request,a);await reopened.complete(a.admissionId,r.result,r.providerIdentityId,r);await reopened.terminalize(terminal);await assert.rejects(()=>reopened.admit(a.admissionId,{...request,sourceActorDiscordId:"alien"},a),/collision/);await assert.rejects(()=>reopened.admit(a.admissionId,request,{...a,packetSha256:"sha256-alien"}),/collision/);await assert.rejects(()=>reopened.complete(a.admissionId,{...r.result,detail:"alien"},r.providerIdentityId,{...r,result:{...r.result,detail:"alien"}}),/collision/);await assert.rejects(()=>reopened.complete(a.admissionId,{...r.result,packetSha256:"sha256-alien"},r.providerIdentityId,{...r,packetSha256:"sha256-alien",result:{...r.result,packetSha256:"sha256-alien"}}),/exact durable admission/);await assert.rejects(()=>reopened.terminalize({...terminal,failureCode:"alien"}),/collision/);});
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ const review = {
|
|||
function request(command) {
|
||||
return {
|
||||
schemaName: "voidbot.discord.epiphany_operator_request",
|
||||
schemaVersion: "voidbot.discord.epiphany_operator_request.v0",
|
||||
schemaVersion: "voidbot.discord.epiphany_operator_request.v1",
|
||||
requestId: "request-1",
|
||||
commandId: "command-1",
|
||||
nonce: "nonce-1",
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -1,5 +1,5 @@
|
|||
export const operatorRequestType="voidbot.discord.epiphany_operator_request";
|
||||
export const operatorRequestSchema="voidbot.discord.epiphany_operator_request.v0";
|
||||
export const operatorRequestSchema="voidbot.discord.epiphany_operator_request.v1";
|
||||
export const operatorAdmissionType="bifrost.operator_command.delivery";
|
||||
export const operatorAdmissionSchema="bifrost.operator_command.delivery.v1";
|
||||
export const legacyOperatorAdmissionSchema="bifrost.operator_command.delivery.v0";
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ const canonicalService = `${rootVerse}.bifrost`;
|
|||
const locatedService = `${rootVerse}.${currentMachine}.bifrost`;
|
||||
const motionSurfaceCultMeshUri = `cultmesh://${locatedService}/eve/governance/surface`;
|
||||
const motionCommandCultMeshUri = `cultmesh://${locatedService}/commands/motion`;
|
||||
const epiphanyOperatorRequestSchemaId = "voidbot.discord.epiphany_operator_request.v0";
|
||||
const epiphanyOperatorRequestSchemaId = "voidbot.discord.epiphany_operator_request.v1";
|
||||
const epiphanyOperatorAdmissionSchemaId = "bifrost.operator_command.delivery.v1";
|
||||
const epiphanyOperatorResultSchemaId = "epiphany.operator_command.result.v1";
|
||||
const epiphanyOperatorSealedResultSchemaId = "epiphany.operator_command.sealed_result.v1";
|
||||
|
|
@ -506,7 +506,7 @@ function buildAdvertisement(options) {
|
|||
"does not touch secrets in this advertisement",
|
||||
]),
|
||||
boundary("epiphany-operator", "Bifrost admission; Epiphany execution", [
|
||||
"admit exact owner-only status, sleep, wake, and directive requests",
|
||||
"admit exact owner-only status, sleep, wake, directive, reviews, and review requests",
|
||||
"require the exact configured Discord owner and persisted Bifrost actor-link mapping; Heimdall reference is provenance until signed claims are live",
|
||||
"sign Rust-compatible expiring operator admissions with a dedicated Ed25519 identity",
|
||||
"relay only Epiphany-origin results bound to the admitted command",
|
||||
|
|
|
|||
Loading…
Reference in a new issue