@maykonpaulo/maestro-core 0.3.0-next.0 → 0.3.0-next.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -70,6 +70,52 @@ var ConsoleLogger = class {
70
70
  }
71
71
  };
72
72
 
73
+ // src/logging/ConsoleStructuredLogger.ts
74
+ var ConsoleStructuredLogger = class {
75
+ constructor(minLevel = "info") {
76
+ this.minLevel = minLevel;
77
+ }
78
+ minLevel;
79
+ debug(entry) {
80
+ this.log("debug", entry);
81
+ }
82
+ info(entry) {
83
+ this.log("info", entry);
84
+ }
85
+ warn(entry) {
86
+ this.log("warn", entry);
87
+ }
88
+ error(entry) {
89
+ this.log("error", entry);
90
+ }
91
+ log(level, entry) {
92
+ if (LOG_LEVEL_PRIORITY[level] < LOG_LEVEL_PRIORITY[this.minLevel]) return;
93
+ const output = {
94
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
95
+ level
96
+ };
97
+ if (entry.correlationId !== void 0) output["correlationId"] = entry.correlationId;
98
+ if (entry.operation !== void 0) output["operation"] = entry.operation;
99
+ if (entry.entity !== void 0) output["entity"] = entry.entity;
100
+ if (entry.entityId !== void 0) output["entityId"] = entry.entityId;
101
+ if (entry.actor !== void 0) output["actor"] = entry.actor;
102
+ if (entry.durationMs !== void 0) output["durationMs"] = entry.durationMs;
103
+ if (entry.status !== void 0) output["status"] = entry.status;
104
+ if (entry.severity !== void 0) output["severity"] = entry.severity;
105
+ if (entry.message !== void 0) output["message"] = entry.message;
106
+ if (entry.metadata !== void 0) output["metadata"] = entry.metadata;
107
+ if (entry.error !== void 0) output["error"] = this.serializeError(entry.error);
108
+ const consoleFn = level === "error" ? console.error : level === "warn" ? console.warn : level === "debug" ? console.debug : console.info;
109
+ consoleFn(JSON.stringify(output));
110
+ }
111
+ serializeError(error) {
112
+ if (error instanceof Error) {
113
+ return { name: error.name, message: error.message };
114
+ }
115
+ return error;
116
+ }
117
+ };
118
+
73
119
  // src/audit/InMemoryAuditRepository.ts
74
120
  var InMemoryAuditRepository = class {
75
121
  store = /* @__PURE__ */ new Map();
@@ -85,6 +131,12 @@ var InMemoryAuditRepository = class {
85
131
  if (filter.action !== void 0) {
86
132
  events = events.filter((e) => e.action === filter.action);
87
133
  }
134
+ if (filter.entity !== void 0) {
135
+ events = events.filter((e) => e.entity === filter.entity);
136
+ }
137
+ if (filter.entityId !== void 0) {
138
+ events = events.filter((e) => e.entityId === filter.entityId);
139
+ }
88
140
  if (filter.resourceType !== void 0) {
89
141
  events = events.filter((e) => e.resource?.type === filter.resourceType);
90
142
  }
@@ -107,6 +159,9 @@ var InMemoryAuditRepository = class {
107
159
  }
108
160
  return events;
109
161
  }
162
+ async query(filter) {
163
+ return this.list(filter);
164
+ }
110
165
  };
111
166
 
112
167
  // src/audit/AuditRecorder.ts
@@ -124,6 +179,8 @@ var AuditRecorder = class {
124
179
  actor: input.actor,
125
180
  level: input.level ?? "info",
126
181
  resource: input.resource,
182
+ entity: input.entity,
183
+ entityId: input.entityId,
127
184
  before: input.before,
128
185
  after: input.after,
129
186
  metadata: input.metadata,
@@ -2303,25 +2360,297 @@ var IntrospectionRuntime = class {
2303
2360
  return engine.compare(previous.result, current);
2304
2361
  }
2305
2362
  };
2363
+
2364
+ // src/correlation/CorrelationId.ts
2365
+ import { randomUUID as randomUUID4 } from "crypto";
2366
+ function generateCorrelationId() {
2367
+ return randomUUID4();
2368
+ }
2369
+
2370
+ // src/risk/MetadataRiskClassifier.ts
2371
+ var MetadataRiskClassifier = class {
2372
+ constructor(operationRiskMap = {}, defaultRisk = "LOW") {
2373
+ this.operationRiskMap = operationRiskMap;
2374
+ this.defaultRisk = defaultRisk;
2375
+ }
2376
+ operationRiskMap;
2377
+ defaultRisk;
2378
+ classify(input) {
2379
+ const fromMetadata = input.metadata?.["riskLevel"];
2380
+ if (isOperationalRisk(fromMetadata)) return fromMetadata;
2381
+ return this.operationRiskMap[input.operation] ?? this.defaultRisk;
2382
+ }
2383
+ };
2384
+ var RISK_LEVELS = ["LOW", "MEDIUM", "HIGH", "CRITICAL"];
2385
+ function isOperationalRisk(value) {
2386
+ return typeof value === "string" && RISK_LEVELS.includes(value);
2387
+ }
2388
+
2389
+ // src/authorization/ContextualAuthorizationEngine.ts
2390
+ var ContextualAuthorizationEngine = class {
2391
+ constructor(policy, criticalOperations = /* @__PURE__ */ new Set()) {
2392
+ this.criticalOperations = criticalOperations;
2393
+ this.rbac = new RbacEngine(policy);
2394
+ }
2395
+ criticalOperations;
2396
+ rbac;
2397
+ async evaluate(context) {
2398
+ if (!this.rbac.can(context.actor, context.operation)) {
2399
+ return { decision: "DENY", reason: `Actor lacks permission for operation: ${context.operation}` };
2400
+ }
2401
+ const risk = context.riskLevel ?? "LOW";
2402
+ if (risk === "CRITICAL" || this.criticalOperations.has(context.operation)) {
2403
+ return { decision: "REQUIRES_CONFIRMATION", reason: `Operation requires confirmation due to risk level: ${risk}` };
2404
+ }
2405
+ return { decision: "ALLOW" };
2406
+ }
2407
+ };
2408
+
2409
+ // src/policy/PolicyEngine.ts
2410
+ var DECISION_PRIORITY = {
2411
+ ALLOW: 0,
2412
+ REQUIRES_CONFIRMATION: 1,
2413
+ DENY: 2
2414
+ };
2415
+ var PolicyEngine = class {
2416
+ constructor(provider) {
2417
+ this.provider = provider;
2418
+ }
2419
+ provider;
2420
+ evaluate(context) {
2421
+ const violations = [];
2422
+ let decision = "ALLOW";
2423
+ let reason;
2424
+ for (const rule of this.provider.rules()) {
2425
+ const result = rule.evaluate(context);
2426
+ if (result === null) continue;
2427
+ if (DECISION_PRIORITY[result.decision] > DECISION_PRIORITY[decision]) {
2428
+ decision = result.decision;
2429
+ reason = result.reason;
2430
+ }
2431
+ if (result.decision === "DENY" || result.decision === "REQUIRES_CONFIRMATION") {
2432
+ violations.push({
2433
+ ruleId: rule.id,
2434
+ reason: result.reason,
2435
+ context,
2436
+ occurredAt: /* @__PURE__ */ new Date()
2437
+ });
2438
+ }
2439
+ }
2440
+ return { decision, violations, reason };
2441
+ }
2442
+ };
2443
+
2444
+ // src/policy/InMemoryPolicyProvider.ts
2445
+ var InMemoryPolicyProvider = class {
2446
+ _rules;
2447
+ constructor(rules = []) {
2448
+ this._rules = rules;
2449
+ }
2450
+ rules() {
2451
+ return this._rules;
2452
+ }
2453
+ };
2454
+
2455
+ // src/confirmation/ConfirmationEngine.ts
2456
+ import { randomUUID as randomUUID5 } from "crypto";
2457
+ var ConfirmationEngine = class {
2458
+ constructor(repository) {
2459
+ this.repository = repository;
2460
+ }
2461
+ repository;
2462
+ async request(input) {
2463
+ const requiredApprovals = input.requiredApprovals ?? 1;
2464
+ const request = {
2465
+ id: randomUUID5(),
2466
+ operation: input.operation,
2467
+ actor: input.actor,
2468
+ resource: input.resource,
2469
+ status: requiredApprovals > 1 ? "AWAITING_CONFIRMATION" : "REQUESTED",
2470
+ requiredApprovals,
2471
+ approvals: [],
2472
+ rejections: [],
2473
+ requestedAt: /* @__PURE__ */ new Date(),
2474
+ expiresAt: input.expiresAt,
2475
+ metadata: input.metadata,
2476
+ correlationId: input.correlationId
2477
+ };
2478
+ await this.repository.save(request);
2479
+ return request;
2480
+ }
2481
+ async approve(requestId, approver, comment) {
2482
+ const request = await this.findOrThrow(requestId);
2483
+ this.assertActive(request);
2484
+ const updated = {
2485
+ ...request,
2486
+ approvals: [...request.approvals, { approver, approvedAt: /* @__PURE__ */ new Date(), comment }]
2487
+ };
2488
+ const fullyApproved = updated.approvals.length >= updated.requiredApprovals;
2489
+ updated.status = fullyApproved ? "APPROVED" : "AWAITING_CONFIRMATION";
2490
+ await this.repository.save(updated);
2491
+ return updated;
2492
+ }
2493
+ async reject(requestId, approver, comment) {
2494
+ const request = await this.findOrThrow(requestId);
2495
+ this.assertActive(request);
2496
+ const updated = {
2497
+ ...request,
2498
+ status: "REJECTED",
2499
+ rejections: [...request.rejections, { approver, approvedAt: /* @__PURE__ */ new Date(), comment }]
2500
+ };
2501
+ await this.repository.save(updated);
2502
+ return updated;
2503
+ }
2504
+ async execute(requestId) {
2505
+ const request = await this.findOrThrow(requestId);
2506
+ if (request.status !== "APPROVED") {
2507
+ throw new MaestroError(
2508
+ "VALIDATION_ERROR" /* VALIDATION_ERROR */,
2509
+ `Cannot execute confirmation request in status: ${request.status}`
2510
+ );
2511
+ }
2512
+ const updated = {
2513
+ ...request,
2514
+ status: "EXECUTED",
2515
+ executedAt: /* @__PURE__ */ new Date()
2516
+ };
2517
+ await this.repository.save(updated);
2518
+ return updated;
2519
+ }
2520
+ async getPending() {
2521
+ return this.repository.listPending();
2522
+ }
2523
+ async findOrThrow(requestId) {
2524
+ const request = await this.repository.findById(requestId);
2525
+ if (!request) {
2526
+ throw new MaestroError(
2527
+ "NOT_FOUND" /* NOT_FOUND */,
2528
+ `Confirmation request not found: ${requestId}`
2529
+ );
2530
+ }
2531
+ return request;
2532
+ }
2533
+ assertActive(request) {
2534
+ const terminal = ["APPROVED", "REJECTED", "EXECUTED", "EXPIRED"];
2535
+ if (terminal.includes(request.status)) {
2536
+ throw new MaestroError(
2537
+ "VALIDATION_ERROR" /* VALIDATION_ERROR */,
2538
+ `Confirmation request is already in terminal status: ${request.status}`
2539
+ );
2540
+ }
2541
+ }
2542
+ };
2543
+
2544
+ // src/confirmation/InMemoryConfirmationRepository.ts
2545
+ var InMemoryConfirmationRepository = class {
2546
+ store = /* @__PURE__ */ new Map();
2547
+ async save(request) {
2548
+ this.store.set(request.id, request);
2549
+ }
2550
+ async findById(id) {
2551
+ return this.store.get(id);
2552
+ }
2553
+ async listPending() {
2554
+ return Array.from(this.store.values()).filter(
2555
+ (r) => r.status === "REQUESTED" || r.status === "AWAITING_CONFIRMATION"
2556
+ );
2557
+ }
2558
+ };
2559
+
2560
+ // src/governance/GovernanceEventType.ts
2561
+ var GOVERNANCE_EVENT_TYPES = {
2562
+ OPERATION_EXECUTED: "governance.operation.executed",
2563
+ AUTHORIZATION_DENIED: "governance.authorization.denied",
2564
+ POLICY_TRIGGERED: "governance.policy.triggered",
2565
+ CONFIRMATION_REQUESTED: "governance.confirmation.requested",
2566
+ CONFIRMATION_APPROVED: "governance.confirmation.approved",
2567
+ CONFIRMATION_REJECTED: "governance.confirmation.rejected",
2568
+ AUDIT_RECORDED: "governance.audit.recorded"
2569
+ };
2570
+
2571
+ // src/governance/InMemoryGovernanceEventBus.ts
2572
+ import { randomUUID as randomUUID6 } from "crypto";
2573
+ var InMemoryGovernanceEventBus = class extends InMemoryEventBus {
2574
+ async publishGovernance(type, payload, correlationId) {
2575
+ const event = {
2576
+ id: randomUUID6(),
2577
+ type,
2578
+ occurredAt: /* @__PURE__ */ new Date(),
2579
+ payload,
2580
+ correlationId
2581
+ };
2582
+ await this.publish(event);
2583
+ return event;
2584
+ }
2585
+ };
2586
+
2587
+ // src/governance/DefaultGovernanceApi.ts
2588
+ var DefaultGovernanceApi = class {
2589
+ constructor(auditRepository, confirmationRepository, violationLog = []) {
2590
+ this.auditRepository = auditRepository;
2591
+ this.confirmationRepository = confirmationRepository;
2592
+ this.violationLog = violationLog;
2593
+ }
2594
+ auditRepository;
2595
+ confirmationRepository;
2596
+ violationLog;
2597
+ async getAuditTimeline(filter) {
2598
+ return this.auditRepository.list(filter);
2599
+ }
2600
+ async getCorrelationTrace(correlationId) {
2601
+ return this.auditRepository.list({ correlationId });
2602
+ }
2603
+ async getPendingConfirmations() {
2604
+ return this.confirmationRepository.listPending();
2605
+ }
2606
+ async getPolicyViolations(filter) {
2607
+ let violations = [...this.violationLog];
2608
+ if (filter?.ruleId !== void 0) {
2609
+ violations = violations.filter((v) => v.ruleId === filter.ruleId);
2610
+ }
2611
+ if (filter?.correlationId !== void 0) {
2612
+ violations = violations.filter((v) => v.context.correlationId === filter.correlationId);
2613
+ }
2614
+ if (filter?.from !== void 0) {
2615
+ const from = filter.from;
2616
+ violations = violations.filter((v) => v.occurredAt >= from);
2617
+ }
2618
+ if (filter?.to !== void 0) {
2619
+ const to = filter.to;
2620
+ violations = violations.filter((v) => v.occurredAt <= to);
2621
+ }
2622
+ return violations;
2623
+ }
2624
+ };
2306
2625
  export {
2307
2626
  AuditRecorder,
2627
+ ConfirmationEngine,
2308
2628
  ConsoleLogger,
2629
+ ConsoleStructuredLogger,
2630
+ ContextualAuthorizationEngine,
2309
2631
  CsvExportProvider,
2310
2632
  DEFAULT_CAPABILITIES,
2311
2633
  DatasourceRegistry,
2634
+ DefaultGovernanceApi,
2312
2635
  DiffEngine,
2313
2636
  ErrorCode,
2637
+ GOVERNANCE_EVENT_TYPES,
2314
2638
  InMemoryAuditRepository,
2315
2639
  InMemoryConfigProvider,
2640
+ InMemoryConfirmationRepository,
2316
2641
  InMemoryDatasourceProvider,
2317
2642
  InMemoryEventBus,
2318
2643
  InMemoryFeatureFlagProvider,
2644
+ InMemoryGovernanceEventBus,
2645
+ InMemoryPolicyProvider,
2319
2646
  InMemorySnapshotRepository,
2320
2647
  IntrospectionRuntime,
2321
2648
  MaestroEngine,
2322
2649
  MaestroError,
2323
2650
  MetadataEngine,
2651
+ MetadataRiskClassifier,
2324
2652
  OperationRegistry,
2653
+ PolicyEngine,
2325
2654
  RbacEngine,
2326
2655
  ReportGenerator,
2327
2656
  createMaestro,
@@ -2329,6 +2658,7 @@ export {
2329
2658
  createMaestroHttpHandlers,
2330
2659
  detectDisplayField,
2331
2660
  generateAllConfigs,
2661
+ generateCorrelationId,
2332
2662
  generateEntityConfig,
2333
2663
  generateRelationConfig,
2334
2664
  humanizeFieldName,