feat(wave): #119/#122/#131/#132 verts + sprint plugins ESM/persistance #135/#136/#139
État d'intégration confiné à la branche batch. Les tickets #119 (skills → capacités agent découvrables), #122 (override permissions par défaut), #131 (effort par agent/presets) et #132 (outil MCP d'édition du contexte projet) sont verts en périmètre. Le sprint plugins multi-fichiers ESM / persistance plugin-owned (#135/#136/#139) est co-implémenté dans les MÊMES fichiers de câblage (frontend/src/ports/index.ts, backend/src/lib.rs, domain/ports.rs, backend/dto.rs), inséparable sans staging interactif (indisponible ici). Commit unique volontaire : préserve l'état vert QA sans découpe hunk risquée. NON mergé vers develop tant que #137 (QA e2e plugins) n'est pas vert. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -9,7 +9,10 @@ use domain::ids::{AgentId, ProjectId};
|
||||
use domain::ports::{PermissionStore, StoreError};
|
||||
use domain::project::{Project, ProjectPath};
|
||||
use domain::remote::RemoteRef;
|
||||
use domain::{PermissionSet, Posture, ProjectPermissions};
|
||||
use domain::{
|
||||
Capability, Effect, PermissionRule, PermissionSet, PermissionShadowReport, Posture,
|
||||
ProjectPermissions,
|
||||
};
|
||||
|
||||
#[derive(Default)]
|
||||
struct FakePermissionStore {
|
||||
@ -125,4 +128,69 @@ async fn resolve_agent_permissions_returns_effective_policy() {
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(out.effective.unwrap().fallback(), Posture::Ask);
|
||||
assert_eq!(out.shadowed, PermissionShadowReport::default());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn resolve_agent_permissions_reports_shadowed_alongside_unchanged_effective() {
|
||||
let agent = AgentId::new_random();
|
||||
let store = Arc::new(FakePermissionStore {
|
||||
doc: Mutex::new(ProjectPermissions::new(
|
||||
Some(PermissionSet::new(
|
||||
vec![PermissionRule::bash(Effect::Deny, vec![])],
|
||||
Posture::Ask,
|
||||
)),
|
||||
vec![domain::AgentPermissionOverride::new(
|
||||
agent,
|
||||
PermissionSet::new(
|
||||
vec![PermissionRule::bash(Effect::Allow, vec![])],
|
||||
Posture::Ask,
|
||||
),
|
||||
)],
|
||||
)),
|
||||
saves: Mutex::new(0),
|
||||
});
|
||||
let use_case = ResolveAgentPermissions::new(store);
|
||||
|
||||
let out = use_case
|
||||
.execute(ResolveAgentPermissionsInput {
|
||||
project: project(),
|
||||
agent_id: agent,
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert!(out.shadowed.execute_bash);
|
||||
assert_eq!(out.effective.unwrap().decide_bash("ls"), Posture::Deny);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn resolve_agent_permissions_shadowed_defaults_when_no_agent_override() {
|
||||
let agent = AgentId::new_random();
|
||||
let store = Arc::new(FakePermissionStore {
|
||||
doc: Mutex::new(ProjectPermissions::new(
|
||||
Some(PermissionSet::new(
|
||||
vec![PermissionRule::file(
|
||||
Capability::Read,
|
||||
Effect::Deny,
|
||||
domain::PathScope::new(["**".to_owned()]).unwrap(),
|
||||
)
|
||||
.unwrap()],
|
||||
Posture::Deny,
|
||||
)),
|
||||
vec![],
|
||||
)),
|
||||
saves: Mutex::new(0),
|
||||
});
|
||||
let use_case = ResolveAgentPermissions::new(store);
|
||||
|
||||
let out = use_case
|
||||
.execute(ResolveAgentPermissionsInput {
|
||||
project: project(),
|
||||
agent_id: agent,
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(out.shadowed, PermissionShadowReport::default());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user