blob: bd77b01f6e53c7088e3b384cf8041e92e45f833e [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
use maka_capabilities::storage::Namespace;
use maka_event_log::{EventLog, StoreError, sessions::PluginSession};
use maka_plugin_core::scope::Scope;
use serde_json::{Value, json};
#[tokio::test]
async fn plugin_creation_is_atomic_and_cannot_adopt_or_reassign_existing_sessions() {
let directory = tempfile::tempdir().unwrap();
let path = directory.path().join("events.sqlite");
let claim = PluginSession {
session_id: "example-inbox".into(),
creator: Namespace::new("example.workflow", Scope::Profile).unwrap(),
fingerprint: "owned-creation".into(),
managed: true,
authority_session_id: None,
};
let log = EventLog::open(&path).await.unwrap();
let configuration = json!({"name":"inbox"});
let record = log
.create_plugin_session(&claim, &configuration, 1)
.await
.unwrap();
assert_eq!(
log.create_plugin_session(&claim, &configuration, 2)
.await
.unwrap(),
record
);
assert!(matches!(
log.create_session(&claim.session_id, &claim.fingerprint, &configuration, 2)
.await,
Err(StoreError::SessionConflict)
));
for creator in [
Namespace::new("other.workflow", Scope::Profile).unwrap(),
Namespace::new("example.workflow", Scope::Session("other".into())).unwrap(),
] {
let wrong = PluginSession {
creator,
..claim.clone()
};
assert!(matches!(
log.create_plugin_session(&wrong, &configuration, 2).await,
Err(StoreError::SessionConflict)
));
}
let ordinary = PluginSession {
session_id: "ordinary".into(),
..claim.clone()
};
log.create_session("ordinary", &ordinary.fingerprint, &configuration, 1)
.await
.unwrap();
assert!(matches!(
log.create_plugin_session(&ordinary, &configuration, 2)
.await,
Err(StoreError::SessionConflict)
));
assert_eq!(log.session_manager("ordinary").await.unwrap(), None);
assert_eq!(log.session_creator("ordinary").await.unwrap(), None);
let delegated = PluginSession {
session_id: "delegated".into(),
managed: false,
..claim.clone()
};
log.create_plugin_session(&delegated, &configuration, 2)
.await
.unwrap();
for conflicting in [
PluginSession {
managed: true,
..delegated.clone()
},
PluginSession {
fingerprint: "changed".into(),
..delegated.clone()
},
PluginSession {
creator: Namespace::new("other", Scope::Profile).unwrap(),
..delegated.clone()
},
] {
assert!(matches!(
log.create_plugin_session(&conflicting, &configuration, 3)
.await,
Err(StoreError::SessionConflict)
));
}
let request = maka_agent_facts::session::CopyRequest {
source_session_id: claim.session_id.clone(),
target_session_id: "owned-copy".into(),
expected_source_revision: record.revision,
purpose: maka_agent_facts::session::CopyPurpose::EmptySideConversation,
};
let owner = PluginSession {
session_id: request.target_session_id.clone(),
fingerprint: "copy-with-settings".into(),
authority_session_id: Some(claim.session_id.clone()),
..claim.clone()
};
let other = PluginSession {
creator: Namespace::new("another.workflow", Scope::Profile).unwrap(),
..owner.clone()
};
assert!(
log.copy_plugin_session(request.clone(), &configuration, 4, other)
.await
.is_err(),
"reading a managed Session does not authorize escaping its owner lifecycle"
);
assert!(log.session_creator("owned-copy").await.unwrap().is_none());
let maka_event_log::sessions::SessionCopyResult::Committed(copied) = log
.copy_plugin_session(request.clone(), &configuration, 4, owner.clone())
.await
.unwrap()
else {
panic!("unexpected revision conflict")
};
assert!(
matches!(
log.copy_session(request.clone(), &configuration, 4).await,
Err(StoreError::SessionConflict)
),
"native copy retries cannot adopt a plugin's creation"
);
assert!(matches!(
log.copy_plugin_session(
request.clone(),
&configuration,
4,
PluginSession {
fingerprint: "changed-settings".into(),
..owner.clone()
}
)
.await,
Err(StoreError::SessionConflict)
));
log.close().await.unwrap();
let log = EventLog::open(&path).await.unwrap();
let maka_event_log::sessions::SessionCopyResult::Committed(replayed) = log
.copy_plugin_session(
request,
&json!({"ignored": "freshly resolved defaults"}),
5,
owner.clone(),
)
.await
.unwrap()
else {
panic!("exact copy was not replayed")
};
assert_eq!(replayed, copied);
assert_eq!(
log.session_manager("owned-copy").await.unwrap(),
Some(owner.creator)
);
assert_eq!(
log.session_manager(&claim.session_id).await.unwrap(),
Some(claim.creator.clone())
);
assert_eq!(log.session_manager("delegated").await.unwrap(), None);
assert_eq!(
log.session_creator("delegated").await.unwrap(),
Some(claim.creator)
);
assert_eq!(
log.get_session::<Value>(&claim.session_id).await.unwrap(),
Some(record)
);
log.close().await.unwrap();
}