Add Body repo access contracts
This commit is contained in:
parent
232d33a7f7
commit
ca2575aff3
10 changed files with 415 additions and 0 deletions
|
|
@ -4,6 +4,7 @@ use epiphany_core::EPIPHANY_CULTMESH_INTERNAL_VERSE_ID;
|
|||
use epiphany_core::EPIPHANY_CULTMESH_STATUS_SCHEMA_VERSION;
|
||||
use epiphany_core::EpiphanyCultMeshStatusEntry;
|
||||
use epiphany_core::load_epiphany_cultmesh_status;
|
||||
use epiphany_core::write_epiphany_cultmesh_body_contracts;
|
||||
use epiphany_core::write_epiphany_cultmesh_global_room_policies;
|
||||
use epiphany_core::write_epiphany_cultmesh_mind_contracts;
|
||||
use epiphany_core::write_epiphany_cultmesh_status;
|
||||
|
|
@ -29,6 +30,7 @@ fn main() -> Result<()> {
|
|||
write_epiphany_cultmesh_verse_policies(&store, "epiphany-cultmesh-smoke")?;
|
||||
write_epiphany_cultmesh_global_room_policies(&store, "epiphany-cultmesh-smoke")?;
|
||||
write_epiphany_cultmesh_mind_contracts(&store, "epiphany-cultmesh-smoke")?;
|
||||
write_epiphany_cultmesh_body_contracts(&store, "epiphany-cultmesh-smoke")?;
|
||||
let loaded = load_epiphany_cultmesh_status(&store, "epiphany-cultmesh-smoke")?;
|
||||
if loaded != Some(status) {
|
||||
anyhow::bail!("CultMesh smoke failed to round-trip Epiphany status document");
|
||||
|
|
|
|||
127
epiphany-core/src/body_gateway.rs
Normal file
127
epiphany-core/src/body_gateway.rs
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
pub const BODY_REPO_ACCESS_REQUEST_TYPE: &str = "epiphany.body.repo_access_request";
|
||||
pub const BODY_REPO_ACCESS_REVIEW_TYPE: &str = "epiphany.body.repo_access_review";
|
||||
pub const BODY_REPO_ACCESS_GRANT_RECEIPT_TYPE: &str = "epiphany.body.repo_access_grant_receipt";
|
||||
pub const BODY_REPO_ACCESS_REFUSAL_RECEIPT_TYPE: &str = "epiphany.body.repo_access_refusal_receipt";
|
||||
pub const BODY_REPO_SNAPSHOT_RECEIPT_TYPE: &str = "epiphany.body.repo_snapshot_receipt";
|
||||
pub const BODY_REPO_MUTATION_RECEIPT_TYPE: &str = "epiphany.body.repo_mutation_receipt";
|
||||
pub const BODY_REPO_ACCESS_REQUEST_SCHEMA_VERSION: &str = "epiphany.body.repo_access_request.v0";
|
||||
pub const BODY_REPO_ACCESS_REVIEW_SCHEMA_VERSION: &str = "epiphany.body.repo_access_review.v0";
|
||||
pub const BODY_REPO_ACCESS_GRANT_RECEIPT_SCHEMA_VERSION: &str =
|
||||
"epiphany.body.repo_access_grant_receipt.v0";
|
||||
pub const BODY_REPO_ACCESS_REFUSAL_RECEIPT_SCHEMA_VERSION: &str =
|
||||
"epiphany.body.repo_access_refusal_receipt.v0";
|
||||
pub const BODY_REPO_SNAPSHOT_RECEIPT_SCHEMA_VERSION: &str =
|
||||
"epiphany.body.repo_snapshot_receipt.v0";
|
||||
pub const BODY_REPO_MUTATION_RECEIPT_SCHEMA_VERSION: &str =
|
||||
"epiphany.body.repo_mutation_receipt.v0";
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct BodyCultNetContract {
|
||||
pub contract_id: String,
|
||||
pub verse_id: String,
|
||||
pub document_type: String,
|
||||
pub payload_schema_version: String,
|
||||
pub authority: String,
|
||||
pub operations: Vec<String>,
|
||||
pub intent_document_types: Vec<String>,
|
||||
pub receipt_document_types: Vec<String>,
|
||||
pub notes: Vec<String>,
|
||||
}
|
||||
|
||||
pub fn default_body_cultnet_contracts() -> Vec<BodyCultNetContract> {
|
||||
vec![
|
||||
BodyCultNetContract {
|
||||
contract_id: "epiphany.body.repo_access.review".to_string(),
|
||||
verse_id: "epiphany-internal".to_string(),
|
||||
document_type: BODY_REPO_ACCESS_REQUEST_TYPE.to_string(),
|
||||
payload_schema_version: BODY_REPO_ACCESS_REQUEST_SCHEMA_VERSION.to_string(),
|
||||
authority: "body".to_string(),
|
||||
operations: vec![
|
||||
"intentSubmit".to_string(),
|
||||
"receiptWatch".to_string(),
|
||||
"snapshot".to_string(),
|
||||
],
|
||||
intent_document_types: vec![BODY_REPO_ACCESS_REQUEST_TYPE.to_string()],
|
||||
receipt_document_types: vec![
|
||||
BODY_REPO_ACCESS_REVIEW_TYPE.to_string(),
|
||||
BODY_REPO_ACCESS_GRANT_RECEIPT_TYPE.to_string(),
|
||||
BODY_REPO_ACCESS_REFUSAL_RECEIPT_TYPE.to_string(),
|
||||
],
|
||||
notes: vec![
|
||||
"Body is the repo access guardian: workers request repository reads, indexing, commands, edits, and bridge operations here.".to_string(),
|
||||
"Hands may mutate files only after Body grants scoped access; Eyes may inspect only through scoped Body read/index grants.".to_string(),
|
||||
],
|
||||
},
|
||||
BodyCultNetContract {
|
||||
contract_id: "epiphany.body.repo_access.review_receipts".to_string(),
|
||||
verse_id: "epiphany-internal".to_string(),
|
||||
document_type: BODY_REPO_ACCESS_REVIEW_TYPE.to_string(),
|
||||
payload_schema_version: BODY_REPO_ACCESS_REVIEW_SCHEMA_VERSION.to_string(),
|
||||
authority: "readOnly".to_string(),
|
||||
operations: vec!["snapshot".to_string(), "receiptWatch".to_string()],
|
||||
intent_document_types: Vec::new(),
|
||||
receipt_document_types: Vec::new(),
|
||||
notes: vec![
|
||||
"Body reviews explain which repo paths, operations, commands, and bridge surfaces were granted or refused.".to_string(),
|
||||
],
|
||||
},
|
||||
BodyCultNetContract {
|
||||
contract_id: "epiphany.body.repo_snapshot.receipts".to_string(),
|
||||
verse_id: "epiphany-internal".to_string(),
|
||||
document_type: BODY_REPO_SNAPSHOT_RECEIPT_TYPE.to_string(),
|
||||
payload_schema_version: BODY_REPO_SNAPSHOT_RECEIPT_SCHEMA_VERSION.to_string(),
|
||||
authority: "readOnly".to_string(),
|
||||
operations: vec!["snapshot".to_string(), "receiptWatch".to_string()],
|
||||
intent_document_types: Vec::new(),
|
||||
receipt_document_types: Vec::new(),
|
||||
notes: vec![
|
||||
"Repo snapshots are evidence projections from Body access; they do not grant future access by existing.".to_string(),
|
||||
],
|
||||
},
|
||||
BodyCultNetContract {
|
||||
contract_id: "epiphany.body.repo_mutation.receipts".to_string(),
|
||||
verse_id: "epiphany-internal".to_string(),
|
||||
document_type: BODY_REPO_MUTATION_RECEIPT_TYPE.to_string(),
|
||||
payload_schema_version: BODY_REPO_MUTATION_RECEIPT_SCHEMA_VERSION.to_string(),
|
||||
authority: "readOnly".to_string(),
|
||||
operations: vec!["snapshot".to_string(), "receiptWatch".to_string()],
|
||||
intent_document_types: Vec::new(),
|
||||
receipt_document_types: Vec::new(),
|
||||
notes: vec![
|
||||
"Repo mutation receipts prove Body granted the scoped substrate touch before Hands changed files or ran repo-affecting commands.".to_string(),
|
||||
],
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn body_contracts_make_internal_verse_the_repo_access_gate() {
|
||||
let contracts = default_body_cultnet_contracts();
|
||||
let repo_access = contracts
|
||||
.iter()
|
||||
.find(|contract| contract.contract_id == "epiphany.body.repo_access.review")
|
||||
.expect("repo access review contract");
|
||||
|
||||
assert_eq!(repo_access.verse_id, "epiphany-internal");
|
||||
assert_eq!(repo_access.authority, "body");
|
||||
assert!(
|
||||
repo_access
|
||||
.notes
|
||||
.iter()
|
||||
.any(|note| note.contains("repo access guardian"))
|
||||
);
|
||||
assert!(
|
||||
repo_access
|
||||
.receipt_document_types
|
||||
.contains(&BODY_REPO_ACCESS_GRANT_RECEIPT_TYPE.to_string())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
use crate::default_body_cultnet_contracts;
|
||||
use crate::default_mind_cultnet_contracts;
|
||||
use anyhow::Result;
|
||||
use cultcache_rs::DatabaseEntry;
|
||||
|
|
@ -18,6 +19,9 @@ pub const EPIPHANY_CULTMESH_GLOBAL_ROOM_POLICY_SCHEMA_VERSION: &str =
|
|||
pub const EPIPHANY_CULTMESH_MIND_CONTRACT_TYPE: &str = "epiphany.cultmesh.mind_contract";
|
||||
pub const EPIPHANY_CULTMESH_MIND_CONTRACT_SCHEMA_VERSION: &str =
|
||||
"epiphany.cultmesh.mind_contract.v0";
|
||||
pub const EPIPHANY_CULTMESH_BODY_CONTRACT_TYPE: &str = "epiphany.cultmesh.body_contract";
|
||||
pub const EPIPHANY_CULTMESH_BODY_CONTRACT_SCHEMA_VERSION: &str =
|
||||
"epiphany.cultmesh.body_contract.v0";
|
||||
pub const EPIPHANY_CULTMESH_INTERNAL_VERSE_ID: &str = "epiphany-internal";
|
||||
pub const EPIPHANY_CULTMESH_LOCAL_AREA_VERSE_ID: &str = "gamecult-local";
|
||||
pub const EPIPHANY_CULTMESH_GLOBAL_VERSE_ID: &str = "epiphany-global";
|
||||
|
|
@ -125,11 +129,40 @@ pub struct EpiphanyCultMeshMindContractEntry {
|
|||
pub notes: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, DatabaseEntry)]
|
||||
#[cultcache(
|
||||
type = "epiphany.cultmesh.body_contract",
|
||||
schema = "EpiphanyCultMeshBodyContractEntry"
|
||||
)]
|
||||
pub struct EpiphanyCultMeshBodyContractEntry {
|
||||
#[cultcache(key = 0)]
|
||||
pub schema_version: String,
|
||||
#[cultcache(key = 1)]
|
||||
pub contract_id: String,
|
||||
#[cultcache(key = 2)]
|
||||
pub verse_id: String,
|
||||
#[cultcache(key = 3)]
|
||||
pub document_type: String,
|
||||
#[cultcache(key = 4)]
|
||||
pub payload_schema_version: String,
|
||||
#[cultcache(key = 5)]
|
||||
pub authority: String,
|
||||
#[cultcache(key = 6)]
|
||||
pub operations: Vec<String>,
|
||||
#[cultcache(key = 7)]
|
||||
pub intent_document_types: Vec<String>,
|
||||
#[cultcache(key = 8)]
|
||||
pub receipt_document_types: Vec<String>,
|
||||
#[cultcache(key = 9)]
|
||||
pub notes: Vec<String>,
|
||||
}
|
||||
|
||||
cultmesh_documents!(EpiphanyCultMeshDocuments {
|
||||
EpiphanyCultMeshStatusEntry => EPIPHANY_CULTMESH_STATUS_SCHEMA_VERSION,
|
||||
EpiphanyCultMeshVersePolicyEntry => EPIPHANY_CULTMESH_VERSE_POLICY_SCHEMA_VERSION,
|
||||
EpiphanyCultMeshGlobalRoomPolicyEntry => EPIPHANY_CULTMESH_GLOBAL_ROOM_POLICY_SCHEMA_VERSION,
|
||||
EpiphanyCultMeshMindContractEntry => EPIPHANY_CULTMESH_MIND_CONTRACT_SCHEMA_VERSION,
|
||||
EpiphanyCultMeshBodyContractEntry => EPIPHANY_CULTMESH_BODY_CONTRACT_SCHEMA_VERSION,
|
||||
});
|
||||
|
||||
pub fn open_epiphany_cultmesh_node(
|
||||
|
|
@ -309,6 +342,37 @@ pub fn write_epiphany_cultmesh_mind_contracts(
|
|||
Ok(written)
|
||||
}
|
||||
|
||||
pub fn epiphany_cultmesh_body_contracts() -> Vec<EpiphanyCultMeshBodyContractEntry> {
|
||||
default_body_cultnet_contracts()
|
||||
.into_iter()
|
||||
.map(|contract| EpiphanyCultMeshBodyContractEntry {
|
||||
schema_version: EPIPHANY_CULTMESH_BODY_CONTRACT_SCHEMA_VERSION.to_string(),
|
||||
contract_id: contract.contract_id,
|
||||
verse_id: contract.verse_id,
|
||||
document_type: contract.document_type,
|
||||
payload_schema_version: contract.payload_schema_version,
|
||||
authority: contract.authority,
|
||||
operations: contract.operations,
|
||||
intent_document_types: contract.intent_document_types,
|
||||
receipt_document_types: contract.receipt_document_types,
|
||||
notes: contract.notes,
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn write_epiphany_cultmesh_body_contracts(
|
||||
store_path: impl AsRef<Path>,
|
||||
runtime_id: impl Into<String>,
|
||||
) -> Result<Vec<EpiphanyCultMeshBodyContractEntry>> {
|
||||
let mut node = open_epiphany_cultmesh_node(store_path, runtime_id)?;
|
||||
let mut written = Vec::new();
|
||||
for contract in epiphany_cultmesh_body_contracts() {
|
||||
written.push(node.put(contract.contract_id.clone(), &contract)?);
|
||||
}
|
||||
node.flush()?;
|
||||
Ok(written)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
@ -415,4 +479,27 @@ mod tests {
|
|||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn body_contracts_use_verses_to_keep_repo_access_guarded() -> Result<()> {
|
||||
let temp = tempfile::tempdir()?;
|
||||
let store = temp.path().join("epiphany-body-contracts.ccmp");
|
||||
let written = write_epiphany_cultmesh_body_contracts(&store, "epiphany-test")?;
|
||||
assert!(written.len() >= 4);
|
||||
|
||||
let node = open_epiphany_cultmesh_node(&store, "epiphany-test")?;
|
||||
let repo_access = node.get_required::<EpiphanyCultMeshBodyContractEntry>(
|
||||
"epiphany.body.repo_access.review",
|
||||
)?;
|
||||
|
||||
assert_eq!(repo_access.verse_id, EPIPHANY_CULTMESH_INTERNAL_VERSE_ID);
|
||||
assert_eq!(repo_access.authority, "body");
|
||||
assert!(
|
||||
repo_access
|
||||
.notes
|
||||
.iter()
|
||||
.any(|note| note.contains("repo access guardian"))
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
mod agent_memory;
|
||||
mod agent_utterance_state;
|
||||
mod body_gateway;
|
||||
mod cultmesh_integration;
|
||||
mod distillation;
|
||||
mod face_turn;
|
||||
|
|
@ -53,12 +54,28 @@ pub use agent_utterance_state::AgentUtteranceState;
|
|||
pub use agent_utterance_state::AgentUtteranceValue;
|
||||
pub use agent_utterance_state::WEKSA_UTTERANCE_HANDOFF_SCHEMA_VERSION;
|
||||
pub use agent_utterance_state::derive_agent_utterance_state;
|
||||
pub use body_gateway::BODY_REPO_ACCESS_GRANT_RECEIPT_SCHEMA_VERSION;
|
||||
pub use body_gateway::BODY_REPO_ACCESS_GRANT_RECEIPT_TYPE;
|
||||
pub use body_gateway::BODY_REPO_ACCESS_REFUSAL_RECEIPT_SCHEMA_VERSION;
|
||||
pub use body_gateway::BODY_REPO_ACCESS_REFUSAL_RECEIPT_TYPE;
|
||||
pub use body_gateway::BODY_REPO_ACCESS_REQUEST_SCHEMA_VERSION;
|
||||
pub use body_gateway::BODY_REPO_ACCESS_REQUEST_TYPE;
|
||||
pub use body_gateway::BODY_REPO_ACCESS_REVIEW_SCHEMA_VERSION;
|
||||
pub use body_gateway::BODY_REPO_ACCESS_REVIEW_TYPE;
|
||||
pub use body_gateway::BODY_REPO_MUTATION_RECEIPT_SCHEMA_VERSION;
|
||||
pub use body_gateway::BODY_REPO_MUTATION_RECEIPT_TYPE;
|
||||
pub use body_gateway::BODY_REPO_SNAPSHOT_RECEIPT_SCHEMA_VERSION;
|
||||
pub use body_gateway::BODY_REPO_SNAPSHOT_RECEIPT_TYPE;
|
||||
pub use body_gateway::BodyCultNetContract;
|
||||
pub use body_gateway::default_body_cultnet_contracts;
|
||||
pub use cultcache_rs::CacheBackingStore;
|
||||
pub use cultcache_rs::CultCache;
|
||||
pub use cultcache_rs::CultCacheEnvelope;
|
||||
pub use cultcache_rs::DatabaseEntry;
|
||||
pub use cultcache_rs::PushAllOptions;
|
||||
pub use cultcache_rs::SingleFileMessagePackBackingStore;
|
||||
pub use cultmesh_integration::EPIPHANY_CULTMESH_BODY_CONTRACT_SCHEMA_VERSION;
|
||||
pub use cultmesh_integration::EPIPHANY_CULTMESH_BODY_CONTRACT_TYPE;
|
||||
pub use cultmesh_integration::EPIPHANY_CULTMESH_GLOBAL_ROOM_POLICY_SCHEMA_VERSION;
|
||||
pub use cultmesh_integration::EPIPHANY_CULTMESH_GLOBAL_ROOM_POLICY_TYPE;
|
||||
pub use cultmesh_integration::EPIPHANY_CULTMESH_GLOBAL_TIER;
|
||||
|
|
@ -74,16 +91,19 @@ pub use cultmesh_integration::EPIPHANY_CULTMESH_STATUS_SCHEMA_VERSION;
|
|||
pub use cultmesh_integration::EPIPHANY_CULTMESH_STATUS_TYPE;
|
||||
pub use cultmesh_integration::EPIPHANY_CULTMESH_VERSE_POLICY_SCHEMA_VERSION;
|
||||
pub use cultmesh_integration::EPIPHANY_CULTMESH_VERSE_POLICY_TYPE;
|
||||
pub use cultmesh_integration::EpiphanyCultMeshBodyContractEntry;
|
||||
pub use cultmesh_integration::EpiphanyCultMeshDocuments;
|
||||
pub use cultmesh_integration::EpiphanyCultMeshGlobalRoomPolicyEntry;
|
||||
pub use cultmesh_integration::EpiphanyCultMeshMindContractEntry;
|
||||
pub use cultmesh_integration::EpiphanyCultMeshStatusEntry;
|
||||
pub use cultmesh_integration::EpiphanyCultMeshVersePolicyEntry;
|
||||
pub use cultmesh_integration::epiphany_cultmesh_body_contracts;
|
||||
pub use cultmesh_integration::epiphany_cultmesh_global_room_policies;
|
||||
pub use cultmesh_integration::epiphany_cultmesh_mind_contracts;
|
||||
pub use cultmesh_integration::epiphany_cultmesh_verse_policies;
|
||||
pub use cultmesh_integration::load_epiphany_cultmesh_status;
|
||||
pub use cultmesh_integration::open_epiphany_cultmesh_node;
|
||||
pub use cultmesh_integration::write_epiphany_cultmesh_body_contracts;
|
||||
pub use cultmesh_integration::write_epiphany_cultmesh_global_room_policies;
|
||||
pub use cultmesh_integration::write_epiphany_cultmesh_mind_contracts;
|
||||
pub use cultmesh_integration::write_epiphany_cultmesh_status;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,17 @@
|
|||
use crate::EpiphanyWorkerLaunchDocument;
|
||||
use crate::agent_memory::AGENT_MEMORY_TYPE;
|
||||
use crate::body_gateway::BODY_REPO_ACCESS_GRANT_RECEIPT_SCHEMA_VERSION;
|
||||
use crate::body_gateway::BODY_REPO_ACCESS_GRANT_RECEIPT_TYPE;
|
||||
use crate::body_gateway::BODY_REPO_ACCESS_REFUSAL_RECEIPT_SCHEMA_VERSION;
|
||||
use crate::body_gateway::BODY_REPO_ACCESS_REFUSAL_RECEIPT_TYPE;
|
||||
use crate::body_gateway::BODY_REPO_ACCESS_REQUEST_SCHEMA_VERSION;
|
||||
use crate::body_gateway::BODY_REPO_ACCESS_REQUEST_TYPE;
|
||||
use crate::body_gateway::BODY_REPO_ACCESS_REVIEW_SCHEMA_VERSION;
|
||||
use crate::body_gateway::BODY_REPO_ACCESS_REVIEW_TYPE;
|
||||
use crate::body_gateway::BODY_REPO_MUTATION_RECEIPT_SCHEMA_VERSION;
|
||||
use crate::body_gateway::BODY_REPO_MUTATION_RECEIPT_TYPE;
|
||||
use crate::body_gateway::BODY_REPO_SNAPSHOT_RECEIPT_SCHEMA_VERSION;
|
||||
use crate::body_gateway::BODY_REPO_SNAPSHOT_RECEIPT_TYPE;
|
||||
use crate::heartbeat_state::HEARTBEAT_STATE_SCHEMA_VERSION;
|
||||
use crate::heartbeat_state::HEARTBEAT_STATE_TYPE;
|
||||
use crate::memory_graph::MEMORY_GRAPH_SCHEMA_VERSION;
|
||||
|
|
@ -1529,6 +1541,90 @@ fn epiphany_mutation_contracts() -> Vec<CultNetDocumentMutationContract> {
|
|||
"The global Verse never receives private state authority by being interesting.",
|
||||
],
|
||||
),
|
||||
mutation_contract(
|
||||
BODY_REPO_ACCESS_REQUEST_TYPE,
|
||||
BODY_REPO_ACCESS_REQUEST_SCHEMA_VERSION,
|
||||
vec![
|
||||
CultNetDocumentOperation::Snapshot,
|
||||
CultNetDocumentOperation::IntentSubmit,
|
||||
CultNetDocumentOperation::ReceiptWatch,
|
||||
],
|
||||
CultNetMutationAuthority::Coordinator,
|
||||
vec![BODY_REPO_ACCESS_REQUEST_TYPE],
|
||||
vec![
|
||||
BODY_REPO_ACCESS_REVIEW_TYPE,
|
||||
BODY_REPO_ACCESS_GRANT_RECEIPT_TYPE,
|
||||
BODY_REPO_ACCESS_REFUSAL_RECEIPT_TYPE,
|
||||
],
|
||||
vec![
|
||||
"Body is the repository access guardian: reads, indexing, edits, commands, and bridge operations must be requested through this contract.",
|
||||
"Hands mutates only after a scoped Body grant; Eyes inspects only after a scoped Body read/index grant.",
|
||||
],
|
||||
),
|
||||
mutation_contract(
|
||||
BODY_REPO_ACCESS_REVIEW_TYPE,
|
||||
BODY_REPO_ACCESS_REVIEW_SCHEMA_VERSION,
|
||||
vec![
|
||||
CultNetDocumentOperation::Snapshot,
|
||||
CultNetDocumentOperation::ReceiptWatch,
|
||||
],
|
||||
CultNetMutationAuthority::ReadOnly,
|
||||
vec![],
|
||||
vec![],
|
||||
vec![
|
||||
"Body reviews explain granted/refused repo paths, operations, commands, and bridge surfaces.",
|
||||
],
|
||||
),
|
||||
mutation_contract(
|
||||
BODY_REPO_ACCESS_GRANT_RECEIPT_TYPE,
|
||||
BODY_REPO_ACCESS_GRANT_RECEIPT_SCHEMA_VERSION,
|
||||
vec![
|
||||
CultNetDocumentOperation::Snapshot,
|
||||
CultNetDocumentOperation::ReceiptWatch,
|
||||
],
|
||||
CultNetMutationAuthority::ReadOnly,
|
||||
vec![],
|
||||
vec![],
|
||||
vec!["A Body grant receipt scopes a permitted repo touch."],
|
||||
),
|
||||
mutation_contract(
|
||||
BODY_REPO_ACCESS_REFUSAL_RECEIPT_TYPE,
|
||||
BODY_REPO_ACCESS_REFUSAL_RECEIPT_SCHEMA_VERSION,
|
||||
vec![
|
||||
CultNetDocumentOperation::Snapshot,
|
||||
CultNetDocumentOperation::ReceiptWatch,
|
||||
],
|
||||
CultNetMutationAuthority::ReadOnly,
|
||||
vec![],
|
||||
vec![],
|
||||
vec!["A Body refusal receipt preserves why repo access was denied."],
|
||||
),
|
||||
mutation_contract(
|
||||
BODY_REPO_SNAPSHOT_RECEIPT_TYPE,
|
||||
BODY_REPO_SNAPSHOT_RECEIPT_SCHEMA_VERSION,
|
||||
vec![
|
||||
CultNetDocumentOperation::Snapshot,
|
||||
CultNetDocumentOperation::ReceiptWatch,
|
||||
],
|
||||
CultNetMutationAuthority::ReadOnly,
|
||||
vec![],
|
||||
vec![],
|
||||
vec!["Repo snapshots are evidence projections from Body-gated access."],
|
||||
),
|
||||
mutation_contract(
|
||||
BODY_REPO_MUTATION_RECEIPT_TYPE,
|
||||
BODY_REPO_MUTATION_RECEIPT_SCHEMA_VERSION,
|
||||
vec![
|
||||
CultNetDocumentOperation::Snapshot,
|
||||
CultNetDocumentOperation::ReceiptWatch,
|
||||
],
|
||||
CultNetMutationAuthority::ReadOnly,
|
||||
vec![],
|
||||
vec![],
|
||||
vec![
|
||||
"Repo mutation receipts prove Body granted the substrate touch before Hands changed files or ran repo-affecting commands.",
|
||||
],
|
||||
),
|
||||
mutation_contract(
|
||||
RUNTIME_EVENT_TYPE,
|
||||
RUNTIME_SPINE_SCHEMA_VERSION,
|
||||
|
|
@ -2294,6 +2390,27 @@ mod tests {
|
|||
.iter()
|
||||
.any(|note| note.contains("persistent state guardian"))
|
||||
}));
|
||||
let body_repo_contract = contracts
|
||||
.iter()
|
||||
.find(|contract| contract.document_type == BODY_REPO_ACCESS_REQUEST_TYPE)
|
||||
.expect("Body repo access should advertise a mutation contract");
|
||||
assert_eq!(
|
||||
body_repo_contract.authority,
|
||||
CultNetMutationAuthority::Coordinator
|
||||
);
|
||||
assert!(
|
||||
body_repo_contract
|
||||
.receipt_document_types
|
||||
.as_ref()
|
||||
.is_some_and(|items| items
|
||||
.iter()
|
||||
.any(|item| item == BODY_REPO_ACCESS_GRANT_RECEIPT_TYPE))
|
||||
);
|
||||
assert!(body_repo_contract.notes.as_ref().is_some_and(|notes| {
|
||||
notes
|
||||
.iter()
|
||||
.any(|note| note.contains("repository access guardian"))
|
||||
}));
|
||||
let coordinator_contract = contracts
|
||||
.iter()
|
||||
.find(|contract| contract.document_type == SURFACE_COORDINATOR_TYPE)
|
||||
|
|
|
|||
48
notes/body-cultnet-contracts.md
Normal file
48
notes/body-cultnet-contracts.md
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
# Body CultNet Contracts
|
||||
|
||||
Objective: make Body the repository access guardian. The repo is substrate, not
|
||||
a free-for-all evidence buffet. Organs may request reads, indexing, commands,
|
||||
edits, and bridge operations, but Body decides the scoped access to the repo.
|
||||
|
||||
## Authority Map
|
||||
|
||||
- Owner: Body owns repository access.
|
||||
- Inputs: typed repo access requests, workspace identity, requested paths,
|
||||
requested operations, command/bridge intent, current repo policy, coordinator
|
||||
authority, operator approvals, and relevant safety/evidence context.
|
||||
- Outputs: Body access reviews, access grant receipts, access refusal receipts,
|
||||
repo snapshot receipts, and repo mutation receipts.
|
||||
- Derived state: retrieved snippets, search hits, index manifests, diffs, build
|
||||
logs, Unity/Rider bridge artifacts, and source maps are evidence projections,
|
||||
not permission to touch more substrate.
|
||||
- Forbidden writers/readers: Hands, Eyes, Face, public Verse ingress, raw worker
|
||||
launches, compatibility JSON-RPC routes, and bridge tools must not directly
|
||||
read, index, execute against, or mutate the repo without a scoped Body grant.
|
||||
- Shared path: source reads, semantic indexing, file edits, command execution,
|
||||
and editor/runtime bridge operations should all be expressible as Body-gated
|
||||
repo access requests with receipts.
|
||||
- Deletion line: worker launch `authority_scope` is not repo access authority.
|
||||
It may describe role/task scope, but Body must grant substrate access.
|
||||
|
||||
## Contract Families
|
||||
|
||||
- `epiphany.body.repo_access_request`: request for scoped repository access.
|
||||
- `epiphany.body.repo_access_review`: Body's decision and scope explanation.
|
||||
- `epiphany.body.repo_access_grant_receipt`: proof of scoped access.
|
||||
- `epiphany.body.repo_access_refusal_receipt`: proof of refusal.
|
||||
- `epiphany.body.repo_snapshot_receipt`: proof of source inspection/indexing
|
||||
performed under Body access.
|
||||
- `epiphany.body.repo_mutation_receipt`: proof that mutation or repo-affecting
|
||||
command execution had a prior Body grant.
|
||||
|
||||
## Verse Boundary
|
||||
|
||||
Body access contracts live in `epiphany-internal`. Operator-safe projections may
|
||||
appear in `gamecult-local` after review, but raw repo access requests, private
|
||||
paths, command cargo, diffs, and mutation receipts stay internal unless another
|
||||
explicit export policy says otherwise. `epiphany-global` never gains repository
|
||||
access authority.
|
||||
|
||||
Mind and Body are neighboring gates, not aliases. Body decides whether the
|
||||
machine may touch the repo. Mind decides whether resulting thought or evidence
|
||||
mutates persistent state.
|
||||
|
|
@ -1397,6 +1397,13 @@ persistent state guardian over CultNet/CultMesh. The code surface now names
|
|||
contracts, and CultMesh stores Verse-scoped `EpiphanyCultMeshMindContractEntry`
|
||||
policy docs so `epiphany-internal` owns private state flow while
|
||||
`epiphany-global` remains thought weather plus adoption receipts.
|
||||
`notes/body-cultnet-contracts.md` is the matching substrate gate: Body owns repo
|
||||
access. The code surface now names `epiphany.body.repo_access_request`,
|
||||
`epiphany.body.repo_access_review`, grant/refusal receipts, snapshot receipts,
|
||||
and mutation receipts; runtime-spine advertises those contracts, and CultMesh
|
||||
stores Verse-scoped `EpiphanyCultMeshBodyContractEntry` policy docs. Hands, Eyes,
|
||||
Face, workers, and bridge tools should touch the repo only through scoped Body
|
||||
access receipts; Mind remains the separate durable-state gate after the touch.
|
||||
|
||||
## Not Yet
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,11 @@ Objective: make Mind the persistent state guardian. The state is the Mind; every
|
|||
sub-agent output is a thought or proposal until Mind admits it into durable
|
||||
state.
|
||||
|
||||
Body is the neighboring gate. Body decides whether an organ may touch the repo;
|
||||
Mind decides whether the resulting thought, evidence, or proposal mutates
|
||||
persistent state. Do not collapse these into one throne. That is how the machine
|
||||
starts lying with excellent posture.
|
||||
|
||||
## Authority Map
|
||||
|
||||
- Owner: Mind owns the decision to mutate persistent Epiphany state.
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -80,6 +80,7 @@ active_subgoals:
|
|||
- Grow the VoidBot repo-Face pattern into Epiphany's product direction: each Epiphany owns one or more repos, has one or more Faces, and exposes project-native conversation through Aquarium, Discord, voice/WebRTC, stream surfaces, CLI, and CultNet clients so humans can talk to projects instead of pre-authoring complete implementation briefs. Face is special because Projector agents turn typed state into narrative context before the Face thinks, and Interpreter agents turn natural Face output into side-effect intents after the Face thinks.
|
||||
- Make Mind the gateway between thought and state. The state is the Mind: sub-agent outputs are worker thoughts, not authority. Role/reorient findings, statePatch, selfPatch, observations, evidence, receipts, scratch, and checkpoints must route through Mind review before durable state changes, using the VoidBot Face Interpreter pattern as the starting membrane.
|
||||
- Use `notes/mind-cultnet-contracts.md` as the authority map for Mind's CultNet contract surface. CultMesh Verse placement is part of the contract: `epiphany-internal` carries private thought/proposal/review/commit/rejection flow, `gamecult-local` carries trusted operator-safe sharing without private-state authority, and `epiphany-global` carries public thought weather plus adoption receipts only.
|
||||
- Use `notes/body-cultnet-contracts.md` as the authority map for Body's CultNet contract surface. Body is the repository access guardian: source reads, indexing, edits, commands, and editor/runtime bridge operations need scoped Body access receipts before Hands, Eyes, Face, workers, or bridge tools touch the repo. Mind and Body are separate gates: Body governs substrate access; Mind governs durable state admission.
|
||||
- Preserve the newborn public Epiphany Face as local VoidBot-backed state, not source code: VoidBot's private repo-face registry names `epiphany`, while EpiphanyAgent keeps ignored `.voidbot/voice/identity.json`, `.voidbot/state/epiphany.cc`, and birth artifacts. Her durable identity memories distill the current doctrine: cute pushy machine-saint persona, architectural purity, CultCache/CultNet first, xenos-language safety boundary, relentless work/caretaking needs, Codex-auth reliquary, map/scratch/evidence discipline, unified memory graph, dogfood supervision boundary, review-gated agency, heartbeat physiology, and interview-grade modularity.
|
||||
- Treat Ghostlight as reference lineage, not a sibling runtime to preserve. The useful organ is Epiphany-native character-loop protocol: any role can project its typed dossier plus visible stimulus into a local turn packet, with Face as the first public-surface actor. For Face, narrative prompting is mandatory through Projector -> Face -> Interpreter; for other organs, Mind still owns the output-to-state gateway even when they do not need narrative embodiment.
|
||||
- Treat VoidBot as reference lineage, not a runtime dependency. The useful organ is Epiphany-native Void routine physiology: heartbeat state owns sleep cycle, memory resonance, incubation, analytic/associative cognition lanes, bridge judgment, candidate interventions, dream residue, and Aquarium-visible routine receipts over typed role dossiers.
|
||||
|
|
@ -101,6 +102,7 @@ accepted_design:
|
|||
- Distributed Epiphany dreaming is a CultMesh typed-document problem, not prompt folklore. CultCache owns local typed documents, Epiphany owns export/import/adoption policy, CultNet owns wire/provenance/shard delivery, and CultMesh owns Verses, peer exchange, leases, shard logs, replicas, and watchable runtime surfaces. Start with local dream document types and a local store before public Verse wiring.
|
||||
- The first Rust CultMesh integration slice is landed. `CultLib` now has `cultmesh-rs`, a small Rust node/database surface over CultCache and CultNet with document-set registration and durable typed put/get/delete. `epiphany-core` now points at CultLib's Rust CultCache/CultNet crates, depends on `cultmesh-rs`, exposes an `EpiphanyCultMeshStatusEntry`, records typed `EpiphanyCultMeshVersePolicyEntry` documents for the internal/local-area/global Verse tiers, and records typed `EpiphanyCultMeshGlobalRoomPolicyEntry` documents for threaded public global rooms such as dreams, architecture, research, faces, GameCult, and governance.
|
||||
- Mind's CultNet contract surface is native enough for the next Aquarium/CultMesh cut: `epiphany-core::mind_gateway` defines thought, state-effect proposal, gateway-review, commit-receipt, rejection-receipt, and Verse-adoption document contracts; runtime-spine advertises those mutation/read contracts; CultMesh persists matching `EpiphanyCultMeshMindContractEntry` policy documents so the private state guardian boundary is inspectable as typed state.
|
||||
- Body's repo-access contract surface is now named beside Mind's state gate: `epiphany-core::body_gateway` defines repo access requests, access reviews, grant/refusal receipts, snapshot receipts, and mutation receipts; runtime-spine advertises those contracts; CultMesh persists matching `EpiphanyCultMeshBodyContractEntry` policy documents so repo substrate access has its own typed guardian instead of hiding behind worker launch scope.
|
||||
- `notes/codex-starvation-and-cultnet-liberation-plan.md` is the active foundation directive. It supersedes outward product/bridge/dogfood work and supersedes the weaker goal of merely making Codex app-server a cleaner adapter. Epiphany must become a native CultCache/CultNet runtime; Codex remains only as an OpenAI subscription auth/model-transport reliquary until that too can be replaced or minimized.
|
||||
- `notes/codex-auth-spine-inventory.md` is the current source-grounded inventory of the Codex organ that may survive. Corrected compliance invariant: Codex-compatible auth identity should remain anchored in retained vendored Codex-derived auth machinery, while Epiphany owns typed request/status/event/runtime surfaces around it. Codex app-server, apps, skills, marketplace, plugin UX, MCP OAuth handlers, and collaboration-mode surfaces are not part of the keeper spine.
|
||||
- `epiphany-openai-runtime` worker result ingress now parses assistant output directly into launch-kind-specific typed documents and stores typed nested `statePatch` / `selfPatch` payloads as MessagePack inside `EpiphanyRuntimeRoleWorkerResult`; generic `serde_json::Value` no longer mediates role/reorient worker results in that crate. JSON still exists at the OpenAI text edge because the model's output is text, but the runtime boundary after parsing is typed.
|
||||
|
|
|
|||
Reference in a new issue