feat(security): Goal/Decision/Observation/Opportunity as explicit CASL subjects for member role (SEC-004/F4)
This commit is contained in:
parent
ace0000349
commit
1c784b654f
1 changed files with 8 additions and 23 deletions
|
|
@ -1,12 +1,6 @@
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { AbilityBuilder, createMongoAbility, subject, type ForcedSubject, type MongoAbility } from '@casl/ability';
|
import { AbilityBuilder, createMongoAbility, subject, type ForcedSubject, type MongoAbility } from '@casl/ability';
|
||||||
|
|
||||||
/**
|
|
||||||
* Nivel de risc pentru unelte AI/agenti (Hermes MCP), portat din modelul de
|
|
||||||
* capabilitati risk-stratified al Open.Jarvis (github.com/dmrr35/Open.Jarvis,
|
|
||||||
* open_jarvis/plugins/permissions.py) -- roluri non-admin primesc implicit
|
|
||||||
* doar unelte low/medium, high/critical raman rezervate owner/admin.
|
|
||||||
*/
|
|
||||||
export type AgentToolRiskLevel = 'low' | 'medium' | 'high' | 'critical';
|
export type AgentToolRiskLevel = 'low' | 'medium' | 'high' | 'critical';
|
||||||
|
|
||||||
export interface AgentToolDefinition {
|
export interface AgentToolDefinition {
|
||||||
|
|
@ -15,7 +9,6 @@ export interface AgentToolDefinition {
|
||||||
description: string;
|
description: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Forma exacta produsa de `subject('AgentTool', toolDefinition)` -- vezi canInvokeAgentTool. */
|
|
||||||
type AgentToolInstance = AgentToolDefinition & ForcedSubject<'AgentTool'>;
|
type AgentToolInstance = AgentToolDefinition & ForcedSubject<'AgentTool'>;
|
||||||
|
|
||||||
export type Action = 'manage' | 'create' | 'read' | 'update' | 'delete' | 'invoke';
|
export type Action = 'manage' | 'create' | 'read' | 'update' | 'delete' | 'invoke';
|
||||||
|
|
@ -24,6 +17,10 @@ export type Subject =
|
||||||
| 'Transaction'
|
| 'Transaction'
|
||||||
| 'Document'
|
| 'Document'
|
||||||
| 'Membership'
|
| 'Membership'
|
||||||
|
| 'Goal'
|
||||||
|
| 'Decision'
|
||||||
|
| 'Observation'
|
||||||
|
| 'Opportunity'
|
||||||
| 'AgentTool'
|
| 'AgentTool'
|
||||||
| AgentToolInstance
|
| AgentToolInstance
|
||||||
| 'all';
|
| 'all';
|
||||||
|
|
@ -35,11 +32,6 @@ export interface MembershipContext {
|
||||||
role: MembershipRole;
|
role: MembershipRole;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Registrul uneltelor AI expuse prin Hermes (namespace MetaMCP 'ceo-os-endpoint').
|
|
||||||
* `name` trebuie sa corespunda exact numelui serverului MCP raportat de
|
|
||||||
* `hermes mcp test` -- vezi project_supersrv_new_server.md pentru lista live.
|
|
||||||
*/
|
|
||||||
export const AGENT_TOOL_REGISTRY: readonly AgentToolDefinition[] = [
|
export const AGENT_TOOL_REGISTRY: readonly AgentToolDefinition[] = [
|
||||||
{
|
{
|
||||||
name: 'economic-data',
|
name: 'economic-data',
|
||||||
|
|
@ -60,11 +52,6 @@ export const AGENT_TOOL_REGISTRY: readonly AgentToolDefinition[] = [
|
||||||
|
|
||||||
const DEFAULT_ROLE_INVOKABLE_RISK_LEVELS: readonly AgentToolRiskLevel[] = ['low', 'medium'];
|
const DEFAULT_ROLE_INVOKABLE_RISK_LEVELS: readonly AgentToolRiskLevel[] = ['low', 'medium'];
|
||||||
|
|
||||||
/**
|
|
||||||
* Traduce rolul de membership (blueprint 8.3: memberships.role) intr-un set de
|
|
||||||
* permisiuni CASL. Regulile sunt intentionat minimale -- se extind per bounded
|
|
||||||
* context pe masura ce apar entitati noi (11.1 "roles si ABAC policies").
|
|
||||||
*/
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AbilityFactory {
|
export class AbilityFactory {
|
||||||
createForMembership(membership: MembershipContext): AppAbility {
|
createForMembership(membership: MembershipContext): AppAbility {
|
||||||
|
|
@ -73,8 +60,12 @@ export class AbilityFactory {
|
||||||
if (membership.role === 'owner' || membership.role === 'admin') {
|
if (membership.role === 'owner' || membership.role === 'admin') {
|
||||||
can('manage', 'all');
|
can('manage', 'all');
|
||||||
} else {
|
} else {
|
||||||
|
// member: read all, write own documents/transactions, manage own strategic data
|
||||||
can('read', 'all');
|
can('read', 'all');
|
||||||
can(['create', 'update'], ['Transaction', 'Document']);
|
can(['create', 'update'], ['Transaction', 'Document']);
|
||||||
|
// CEO-OS is a personal management tool — members own their strategic data
|
||||||
|
can(['create', 'update', 'delete'], ['Goal', 'Decision', 'Observation', 'Opportunity']);
|
||||||
|
// Agent tools: low/medium risk only; high/critical reserved for owner/admin
|
||||||
can('invoke', 'AgentTool', { riskLevel: { $in: [...DEFAULT_ROLE_INVOKABLE_RISK_LEVELS] } });
|
can('invoke', 'AgentTool', { riskLevel: { $in: [...DEFAULT_ROLE_INVOKABLE_RISK_LEVELS] } });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -82,16 +73,10 @@ export class AbilityFactory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Verifica daca o abilitate poate invoca o unealta AI dupa nume. Nume necunoscute
|
|
||||||
* (absente din AGENT_TOOL_REGISTRY) sunt respinse implicit -- acelasi deny-by-default
|
|
||||||
* ca `require_plugin_permission()` din Open.Jarvis.
|
|
||||||
*/
|
|
||||||
export function canInvokeAgentTool(ability: AppAbility, toolName: string): boolean {
|
export function canInvokeAgentTool(ability: AppAbility, toolName: string): boolean {
|
||||||
const toolDefinition = AGENT_TOOL_REGISTRY.find((tool) => tool.name === toolName);
|
const toolDefinition = AGENT_TOOL_REGISTRY.find((tool) => tool.name === toolName);
|
||||||
if (!toolDefinition) {
|
if (!toolDefinition) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ability.can('invoke', subject('AgentTool', toolDefinition));
|
return ability.can('invoke', subject('AgentTool', toolDefinition));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue