@skillsmith/core 0.4.13 → 0.4.15
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/README.md +2 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/src/analytics/storage.d.ts +8 -2
- package/dist/src/analytics/storage.d.ts.map +1 -1
- package/dist/src/analytics/storage.js +16 -5
- package/dist/src/analytics/storage.js.map +1 -1
- package/dist/src/analytics/usage-tracker.d.ts +8 -2
- package/dist/src/analytics/usage-tracker.d.ts.map +1 -1
- package/dist/src/analytics/usage-tracker.js +24 -11
- package/dist/src/analytics/usage-tracker.js.map +1 -1
- package/dist/src/api/client.d.ts +1 -0
- package/dist/src/api/client.d.ts.map +1 -1
- package/dist/src/api/client.health.d.ts +26 -0
- package/dist/src/api/client.health.d.ts.map +1 -0
- package/dist/src/api/client.health.js +74 -0
- package/dist/src/api/client.health.js.map +1 -0
- package/dist/src/api/client.js +3 -51
- package/dist/src/api/client.js.map +1 -1
- package/dist/src/benchmarks/IndexBenchmark.js +2 -2
- package/dist/src/benchmarks/IndexBenchmark.js.map +1 -1
- package/dist/src/benchmarks/SearchBenchmark.js +2 -2
- package/dist/src/benchmarks/SearchBenchmark.js.map +1 -1
- package/dist/src/benchmarks/cacheBenchmark.js +2 -2
- package/dist/src/benchmarks/cacheBenchmark.js.map +1 -1
- package/dist/src/benchmarks/embeddingBenchmark.js +1 -1
- package/dist/src/benchmarks/embeddingBenchmark.js.map +1 -1
- package/dist/src/cache/CacheManager.d.ts +13 -2
- package/dist/src/cache/CacheManager.d.ts.map +1 -1
- package/dist/src/cache/CacheManager.js +27 -6
- package/dist/src/cache/CacheManager.js.map +1 -1
- package/dist/src/cache/TieredCache.d.ts +15 -2
- package/dist/src/cache/TieredCache.d.ts.map +1 -1
- package/dist/src/cache/TieredCache.js +52 -70
- package/dist/src/cache/TieredCache.js.map +1 -1
- package/dist/src/cache/index.d.ts +12 -0
- package/dist/src/cache/index.d.ts.map +1 -1
- package/dist/src/cache/index.js +20 -1
- package/dist/src/cache/index.js.map +1 -1
- package/dist/src/cache/sqlite.d.ts +15 -1
- package/dist/src/cache/sqlite.d.ts.map +1 -1
- package/dist/src/cache/sqlite.js +22 -4
- package/dist/src/cache/sqlite.js.map +1 -1
- package/dist/src/db/createDatabase.d.ts +9 -1
- package/dist/src/db/createDatabase.d.ts.map +1 -1
- package/dist/src/db/createDatabase.js +21 -1
- package/dist/src/db/createDatabase.js.map +1 -1
- package/dist/src/db/drivers/sqljsDriver.d.ts.map +1 -1
- package/dist/src/db/drivers/sqljsDriver.js +5 -2
- package/dist/src/db/drivers/sqljsDriver.js.map +1 -1
- package/dist/src/db/migrations/v5-skill-versions.d.ts +30 -0
- package/dist/src/db/migrations/v5-skill-versions.d.ts.map +1 -0
- package/dist/src/db/migrations/v5-skill-versions.js +45 -0
- package/dist/src/db/migrations/v5-skill-versions.js.map +1 -0
- package/dist/src/db/migrations/v5b-change-type.d.ts +19 -0
- package/dist/src/db/migrations/v5b-change-type.d.ts.map +1 -0
- package/dist/src/db/migrations/v5b-change-type.js +22 -0
- package/dist/src/db/migrations/v5b-change-type.js.map +1 -0
- package/dist/src/db/migrations/v6-advisories.d.ts +32 -0
- package/dist/src/db/migrations/v6-advisories.d.ts.map +1 -0
- package/dist/src/db/migrations/v6-advisories.js +53 -0
- package/dist/src/db/migrations/v6-advisories.js.map +1 -0
- package/dist/src/db/migrations/v7-compatibility.d.ts +21 -0
- package/dist/src/db/migrations/v7-compatibility.d.ts.map +1 -0
- package/dist/src/db/migrations/v7-compatibility.js +23 -0
- package/dist/src/db/migrations/v7-compatibility.js.map +1 -0
- package/dist/src/db/migrations/v8-co-installs.d.ts +21 -0
- package/dist/src/db/migrations/v8-co-installs.d.ts.map +1 -0
- package/dist/src/db/migrations/v8-co-installs.js +33 -0
- package/dist/src/db/migrations/v8-co-installs.js.map +1 -0
- package/dist/src/db/schema.d.ts +6 -11
- package/dist/src/db/schema.d.ts.map +1 -1
- package/dist/src/db/schema.js +38 -17
- package/dist/src/db/schema.js.map +1 -1
- package/dist/src/embeddings/hnsw-store.d.ts +14 -0
- package/dist/src/embeddings/hnsw-store.d.ts.map +1 -1
- package/dist/src/embeddings/hnsw-store.helpers.d.ts +4 -4
- package/dist/src/embeddings/hnsw-store.helpers.d.ts.map +1 -1
- package/dist/src/embeddings/hnsw-store.helpers.js +5 -5
- package/dist/src/embeddings/hnsw-store.helpers.js.map +1 -1
- package/dist/src/embeddings/hnsw-store.js +32 -4
- package/dist/src/embeddings/hnsw-store.js.map +1 -1
- package/dist/src/embeddings/index.d.ts +15 -1
- package/dist/src/embeddings/index.d.ts.map +1 -1
- package/dist/src/embeddings/index.js +24 -4
- package/dist/src/embeddings/index.js.map +1 -1
- package/dist/src/exports/repositories.d.ts +5 -0
- package/dist/src/exports/repositories.d.ts.map +1 -1
- package/dist/src/exports/repositories.js +17 -0
- package/dist/src/exports/repositories.js.map +1 -1
- package/dist/src/exports/types.d.ts +1 -1
- package/dist/src/exports/types.d.ts.map +1 -1
- package/dist/src/exports/types.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/indexer/SkillParser.d.ts +2 -0
- package/dist/src/indexer/SkillParser.d.ts.map +1 -1
- package/dist/src/indexer/SkillParser.js.map +1 -1
- package/dist/src/learning/PatternStore.d.ts +8 -2
- package/dist/src/learning/PatternStore.d.ts.map +1 -1
- package/dist/src/learning/PatternStore.helpers.d.ts +19 -1
- package/dist/src/learning/PatternStore.helpers.d.ts.map +1 -1
- package/dist/src/learning/PatternStore.helpers.js +51 -0
- package/dist/src/learning/PatternStore.helpers.js.map +1 -1
- package/dist/src/learning/PatternStore.js +19 -39
- package/dist/src/learning/PatternStore.js.map +1 -1
- package/dist/src/repositories/AdvisoryRepository.d.ts +80 -0
- package/dist/src/repositories/AdvisoryRepository.d.ts.map +1 -0
- package/dist/src/repositories/AdvisoryRepository.js +128 -0
- package/dist/src/repositories/AdvisoryRepository.js.map +1 -0
- package/dist/src/repositories/AdvisoryRepository.test.d.ts +6 -0
- package/dist/src/repositories/AdvisoryRepository.test.d.ts.map +1 -0
- package/dist/src/repositories/AdvisoryRepository.test.js +149 -0
- package/dist/src/repositories/AdvisoryRepository.test.js.map +1 -0
- package/dist/src/repositories/CoInstallRepository.d.ts +68 -0
- package/dist/src/repositories/CoInstallRepository.d.ts.map +1 -0
- package/dist/src/repositories/CoInstallRepository.js +122 -0
- package/dist/src/repositories/CoInstallRepository.js.map +1 -0
- package/dist/src/repositories/SkillRepository.d.ts.map +1 -1
- package/dist/src/repositories/SkillRepository.js +16 -5
- package/dist/src/repositories/SkillRepository.js.map +1 -1
- package/dist/src/repositories/SkillVersionRepository.d.ts +82 -0
- package/dist/src/repositories/SkillVersionRepository.d.ts.map +1 -0
- package/dist/src/repositories/SkillVersionRepository.js +118 -0
- package/dist/src/repositories/SkillVersionRepository.js.map +1 -0
- package/dist/src/search/hybrid.d.ts +15 -4
- package/dist/src/search/hybrid.d.ts.map +1 -1
- package/dist/src/search/hybrid.js +25 -9
- package/dist/src/search/hybrid.js.map +1 -1
- package/dist/src/services/SearchService.helpers.d.ts.map +1 -1
- package/dist/src/services/SearchService.helpers.js +4 -0
- package/dist/src/services/SearchService.helpers.js.map +1 -1
- package/dist/src/services/SearchService.types.d.ts +1 -0
- package/dist/src/services/SearchService.types.d.ts.map +1 -1
- package/dist/src/services/TaskRunner.d.ts +5 -81
- package/dist/src/services/TaskRunner.d.ts.map +1 -1
- package/dist/src/services/TaskRunner.js +7 -68
- package/dist/src/services/TaskRunner.js.map +1 -1
- package/dist/src/services/TaskRunner.process.d.ts +33 -0
- package/dist/src/services/TaskRunner.process.d.ts.map +1 -0
- package/dist/src/services/TaskRunner.process.js +70 -0
- package/dist/src/services/TaskRunner.process.js.map +1 -0
- package/dist/src/services/TaskRunner.types.d.ts +76 -0
- package/dist/src/services/TaskRunner.types.d.ts.map +1 -0
- package/dist/src/services/TaskRunner.types.js +22 -0
- package/dist/src/services/TaskRunner.types.js.map +1 -0
- package/dist/src/services/__tests__/TaskRunner.process.test.d.ts +13 -0
- package/dist/src/services/__tests__/TaskRunner.process.test.d.ts.map +1 -0
- package/dist/src/services/__tests__/TaskRunner.process.test.js +91 -0
- package/dist/src/services/__tests__/TaskRunner.process.test.js.map +1 -0
- package/dist/src/services/quarantine/QuarantineService.d.ts +3 -24
- package/dist/src/services/quarantine/QuarantineService.d.ts.map +1 -1
- package/dist/src/services/quarantine/QuarantineService.js +8 -205
- package/dist/src/services/quarantine/QuarantineService.js.map +1 -1
- package/dist/src/services/quarantine/QuarantineService.multiapproval.d.ts +57 -0
- package/dist/src/services/quarantine/QuarantineService.multiapproval.d.ts.map +1 -0
- package/dist/src/services/quarantine/QuarantineService.multiapproval.js +211 -0
- package/dist/src/services/quarantine/QuarantineService.multiapproval.js.map +1 -0
- package/dist/src/session/SessionManager.d.ts +2 -33
- package/dist/src/session/SessionManager.d.ts.map +1 -1
- package/dist/src/session/SessionManager.js +14 -238
- package/dist/src/session/SessionManager.js.map +1 -1
- package/dist/src/session/SessionManager.memory.d.ts +67 -0
- package/dist/src/session/SessionManager.memory.d.ts.map +1 -0
- package/dist/src/session/SessionManager.memory.js +262 -0
- package/dist/src/session/SessionManager.memory.js.map +1 -0
- package/dist/src/sync/SyncEngine.d.ts +13 -1
- package/dist/src/sync/SyncEngine.d.ts.map +1 -1
- package/dist/src/sync/SyncEngine.js +50 -1
- package/dist/src/sync/SyncEngine.js.map +1 -1
- package/dist/src/testing/MultiLLMProvider.d.ts +5 -6
- package/dist/src/testing/MultiLLMProvider.d.ts.map +1 -1
- package/dist/src/testing/MultiLLMProvider.js +18 -130
- package/dist/src/testing/MultiLLMProvider.js.map +1 -1
- package/dist/src/testing/MultiLLMProvider.metrics.d.ts +33 -0
- package/dist/src/testing/MultiLLMProvider.metrics.d.ts.map +1 -0
- package/dist/src/testing/MultiLLMProvider.metrics.js +87 -0
- package/dist/src/testing/MultiLLMProvider.metrics.js.map +1 -0
- package/dist/src/testing/MultiLLMProvider.selection.d.ts +77 -0
- package/dist/src/testing/MultiLLMProvider.selection.d.ts.map +1 -0
- package/dist/src/testing/MultiLLMProvider.selection.js +151 -0
- package/dist/src/testing/MultiLLMProvider.selection.js.map +1 -0
- package/dist/src/types/skill.d.ts +10 -0
- package/dist/src/types/skill.d.ts.map +1 -1
- package/dist/src/types.d.ts +34 -0
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/versioning/change-classifier.d.ts +38 -0
- package/dist/src/versioning/change-classifier.d.ts.map +1 -0
- package/dist/src/versioning/change-classifier.js +187 -0
- package/dist/src/versioning/change-classifier.js.map +1 -0
- package/dist/src/versioning/change-classifier.test.d.ts +6 -0
- package/dist/src/versioning/change-classifier.test.d.ts.map +1 -0
- package/dist/src/versioning/change-classifier.test.js +275 -0
- package/dist/src/versioning/change-classifier.test.js.map +1 -0
- package/dist/src/versioning/update-risk.d.ts +50 -0
- package/dist/src/versioning/update-risk.d.ts.map +1 -0
- package/dist/src/versioning/update-risk.js +80 -0
- package/dist/src/versioning/update-risk.js.map +1 -0
- package/dist/src/versioning/update-risk.test.d.ts +6 -0
- package/dist/src/versioning/update-risk.test.d.ts.map +1 -0
- package/dist/src/versioning/update-risk.test.js +200 -0
- package/dist/src/versioning/update-risk.test.js.map +1 -0
- package/dist/tests/AnalyticsStorage.test.js +2 -2
- package/dist/tests/AnalyticsStorage.test.js.map +1 -1
- package/dist/tests/AuditLogger.edge-cases.test.d.ts +10 -0
- package/dist/tests/AuditLogger.edge-cases.test.d.ts.map +1 -0
- package/dist/tests/AuditLogger.edge-cases.test.js +183 -0
- package/dist/tests/AuditLogger.edge-cases.test.js.map +1 -0
- package/dist/tests/CacheManager.test.d.ts +9 -0
- package/dist/tests/CacheManager.test.d.ts.map +1 -0
- package/dist/tests/CacheManager.test.js +163 -0
- package/dist/tests/CacheManager.test.js.map +1 -0
- package/dist/tests/CacheSecurity.test.js +4 -4
- package/dist/tests/CacheSecurity.test.js.map +1 -1
- package/dist/tests/EmbeddingService.test.js +11 -12
- package/dist/tests/EmbeddingService.test.js.map +1 -1
- package/dist/tests/GitHubIndexer.edge-cases.test.d.ts +10 -0
- package/dist/tests/GitHubIndexer.edge-cases.test.d.ts.map +1 -0
- package/dist/tests/GitHubIndexer.edge-cases.test.js +255 -0
- package/dist/tests/GitHubIndexer.edge-cases.test.js.map +1 -0
- package/dist/tests/HybridSearch.test.d.ts +8 -0
- package/dist/tests/HybridSearch.test.d.ts.map +1 -0
- package/dist/tests/HybridSearch.test.js +48 -0
- package/dist/tests/HybridSearch.test.js.map +1 -0
- package/dist/tests/SearchService.test.js +71 -0
- package/dist/tests/SearchService.test.js.map +1 -1
- package/dist/tests/SkillVersionRepository.test.d.ts +2 -0
- package/dist/tests/SkillVersionRepository.test.d.ts.map +1 -0
- package/dist/tests/SkillVersionRepository.test.js +168 -0
- package/dist/tests/SkillVersionRepository.test.js.map +1 -0
- package/dist/tests/TieredCache.test.js +10 -10
- package/dist/tests/TieredCache.test.js.map +1 -1
- package/dist/tests/UsageTracker.test.js +6 -6
- package/dist/tests/UsageTracker.test.js.map +1 -1
- package/dist/tests/analytics/usage-tracker.test.js +8 -8
- package/dist/tests/analytics/usage-tracker.test.js.map +1 -1
- package/dist/tests/api/client.health.test.d.ts +15 -0
- package/dist/tests/api/client.health.test.d.ts.map +1 -0
- package/dist/tests/api/client.health.test.js +111 -0
- package/dist/tests/api/client.health.test.js.map +1 -0
- package/dist/tests/cache.test.js +7 -9
- package/dist/tests/cache.test.js.map +1 -1
- package/dist/tests/db/betterSqlite3Driver.test.d.ts +8 -0
- package/dist/tests/db/betterSqlite3Driver.test.d.ts.map +1 -0
- package/dist/tests/db/betterSqlite3Driver.test.js +88 -0
- package/dist/tests/db/betterSqlite3Driver.test.js.map +1 -0
- package/dist/tests/db/database-abstraction.test.js +48 -0
- package/dist/tests/db/database-abstraction.test.js.map +1 -1
- package/dist/tests/db/schema-migrations.test.d.ts +10 -0
- package/dist/tests/db/schema-migrations.test.d.ts.map +1 -0
- package/dist/tests/db/schema-migrations.test.js +134 -0
- package/dist/tests/db/schema-migrations.test.js.map +1 -0
- package/dist/tests/db/sqljsDriver.test.d.ts +9 -0
- package/dist/tests/db/sqljsDriver.test.d.ts.map +1 -0
- package/dist/tests/db/sqljsDriver.test.js +75 -0
- package/dist/tests/db/sqljsDriver.test.js.map +1 -0
- package/dist/tests/embeddings/hnsw-store.test.js +27 -24
- package/dist/tests/embeddings/hnsw-store.test.js.map +1 -1
- package/dist/tests/helpers/database.d.ts +32 -0
- package/dist/tests/helpers/database.d.ts.map +1 -0
- package/dist/tests/helpers/database.js +54 -0
- package/dist/tests/helpers/database.js.map +1 -0
- package/dist/tests/learning/PatternStore.helpers.test.d.ts +17 -0
- package/dist/tests/learning/PatternStore.helpers.test.d.ts.map +1 -0
- package/dist/tests/learning/PatternStore.helpers.test.js +301 -0
- package/dist/tests/learning/PatternStore.helpers.test.js.map +1 -0
- package/dist/tests/learning/PatternStore.test.js +9 -0
- package/dist/tests/learning/PatternStore.test.js.map +1 -1
- package/dist/tests/repositories/CoInstallRepository.test.d.ts +9 -0
- package/dist/tests/repositories/CoInstallRepository.test.d.ts.map +1 -0
- package/dist/tests/repositories/CoInstallRepository.test.js +126 -0
- package/dist/tests/repositories/CoInstallRepository.test.js.map +1 -0
- package/dist/tests/routing/LanguageRouter.test.d.ts +9 -0
- package/dist/tests/routing/LanguageRouter.test.d.ts.map +1 -0
- package/dist/tests/routing/LanguageRouter.test.js +150 -0
- package/dist/tests/routing/LanguageRouter.test.js.map +1 -0
- package/dist/tests/session/SessionManager.memory.test.d.ts +11 -0
- package/dist/tests/session/SessionManager.memory.test.d.ts.map +1 -0
- package/dist/tests/session/SessionManager.memory.test.js +219 -0
- package/dist/tests/session/SessionManager.memory.test.js.map +1 -0
- package/dist/tests/sync/SyncEngine.test.js +32 -18
- package/dist/tests/sync/SyncEngine.test.js.map +1 -1
- package/dist/tests/testing/MultiLLMProvider.metrics.test.d.ts +13 -0
- package/dist/tests/testing/MultiLLMProvider.metrics.test.d.ts.map +1 -0
- package/dist/tests/testing/MultiLLMProvider.metrics.test.js +149 -0
- package/dist/tests/testing/MultiLLMProvider.metrics.test.js.map +1 -0
- package/dist/tests/testing/MultiLLMProvider.selection.test.d.ts +15 -0
- package/dist/tests/testing/MultiLLMProvider.selection.test.d.ts.map +1 -0
- package/dist/tests/testing/MultiLLMProvider.selection.test.js +249 -0
- package/dist/tests/testing/MultiLLMProvider.selection.test.js.map +1 -0
- package/dist/tests/unit/quarantine-query-builder.test.d.ts +10 -0
- package/dist/tests/unit/quarantine-query-builder.test.d.ts.map +1 -0
- package/dist/tests/unit/quarantine-query-builder.test.js +157 -0
- package/dist/tests/unit/quarantine-query-builder.test.js.map +1 -0
- package/package.json +1 -3
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* SMI-2269: Quarantine Service with Authentication
|
|
3
3
|
* SMI-2277: Persist multi-approval state to database
|
|
4
|
+
* @see SMI-2741: Multi-approval workflow split to QuarantineService.multiapproval.ts
|
|
4
5
|
*
|
|
5
6
|
* Service layer for quarantine operations that enforces authentication
|
|
6
7
|
* and authorization. Wraps QuarantineRepository with security controls.
|
|
@@ -19,17 +20,10 @@
|
|
|
19
20
|
* @module @skillsmith/core/services/quarantine/QuarantineService
|
|
20
21
|
*/
|
|
21
22
|
import { QuarantineServiceError, requirePermission } from './types.js';
|
|
22
|
-
|
|
23
|
-
//
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
* Number of approvals required for MALICIOUS severity reviews
|
|
27
|
-
*/
|
|
28
|
-
const MALICIOUS_APPROVAL_COUNT = 2;
|
|
29
|
-
/**
|
|
30
|
-
* Multi-approval timeout in milliseconds (24 hours)
|
|
31
|
-
*/
|
|
32
|
-
const MULTI_APPROVAL_TIMEOUT_MS = 24 * 60 * 60 * 1000;
|
|
23
|
+
import { handleMaliciousApproval, buildMultiApprovalStatus, } from './QuarantineService.multiapproval.js';
|
|
24
|
+
// Re-export multi-approval functions for public API
|
|
25
|
+
export { handleMaliciousApproval, buildMultiApprovalStatus, } from './QuarantineService.multiapproval.js';
|
|
26
|
+
export { MALICIOUS_APPROVAL_COUNT, MULTI_APPROVAL_TIMEOUT_MS, } from './QuarantineService.multiapproval.js';
|
|
33
27
|
// ============================================================================
|
|
34
28
|
// Service Implementation
|
|
35
29
|
// ============================================================================
|
|
@@ -145,7 +139,7 @@ export class QuarantineService {
|
|
|
145
139
|
}
|
|
146
140
|
// For MALICIOUS severity, require multi-approval workflow
|
|
147
141
|
if (entry.severity === 'MALICIOUS' && input.reviewStatus === 'approved') {
|
|
148
|
-
return
|
|
142
|
+
return handleMaliciousApproval(session, quarantineId, entry.skillId, input, this.repository, this.approvalRepository, this.auditLogger);
|
|
149
143
|
}
|
|
150
144
|
// For MALICIOUS severity rejection or non-MALICIOUS, check elevated permission
|
|
151
145
|
if (entry.severity === 'MALICIOUS') {
|
|
@@ -197,171 +191,8 @@ export class QuarantineService {
|
|
|
197
191
|
};
|
|
198
192
|
}
|
|
199
193
|
// ==========================================================================
|
|
200
|
-
// Multi-Approval
|
|
194
|
+
// Multi-Approval Status Operations
|
|
201
195
|
// ==========================================================================
|
|
202
|
-
/**
|
|
203
|
-
* Handle approval for MALICIOUS severity skills
|
|
204
|
-
*
|
|
205
|
-
* MALICIOUS severity requires multiple reviewers to approve
|
|
206
|
-
* before a skill can be unquarantined. This prevents single
|
|
207
|
-
* reviewer compromise from allowing malicious skills.
|
|
208
|
-
*
|
|
209
|
-
* Approval state is persisted to the database (SMI-2277) so
|
|
210
|
-
* pending approvals survive service restarts.
|
|
211
|
-
*
|
|
212
|
-
* @param session - Authenticated session
|
|
213
|
-
* @param quarantineId - Quarantine entry ID
|
|
214
|
-
* @param skillId - Skill ID
|
|
215
|
-
* @param input - Review input
|
|
216
|
-
* @returns Review result with multi-approval status
|
|
217
|
-
*/
|
|
218
|
-
handleMaliciousApproval(session, quarantineId, skillId, input) {
|
|
219
|
-
// Require elevated permission for MALICIOUS review
|
|
220
|
-
requirePermission(session, 'quarantine:review_malicious');
|
|
221
|
-
// Check if this reviewer already approved (database-backed)
|
|
222
|
-
if (this.approvalRepository.hasReviewerApproved(quarantineId, session.userId)) {
|
|
223
|
-
// Retrieve existing approval for error details
|
|
224
|
-
const existingApprovals = this.approvalRepository.getPendingApprovals(quarantineId);
|
|
225
|
-
const existing = existingApprovals.find((a) => a.reviewerId === session.userId);
|
|
226
|
-
throw new QuarantineServiceError('You have already approved this entry', 'ALREADY_REVIEWED', {
|
|
227
|
-
quarantineId,
|
|
228
|
-
previousApprovalAt: existing?.createdAt ?? 'unknown',
|
|
229
|
-
});
|
|
230
|
-
}
|
|
231
|
-
// Check for approval timeout
|
|
232
|
-
const startTime = this.approvalRepository.getWorkflowStartTime(quarantineId);
|
|
233
|
-
if (startTime) {
|
|
234
|
-
const timeSinceStart = Date.now() - new Date(startTime).getTime();
|
|
235
|
-
if (timeSinceStart > MULTI_APPROVAL_TIMEOUT_MS) {
|
|
236
|
-
// Capture existing approvals before clearing for audit
|
|
237
|
-
const expiredApprovals = this.approvalRepository.getPendingApprovals(quarantineId);
|
|
238
|
-
// Reset approval workflow
|
|
239
|
-
this.approvalRepository.clearApprovals(quarantineId);
|
|
240
|
-
// Log timeout event so cleared reviewer work is auditable
|
|
241
|
-
this.auditLogger.log({
|
|
242
|
-
event_type: 'quarantine_multi_approval_timeout',
|
|
243
|
-
actor: 'system',
|
|
244
|
-
resource: skillId,
|
|
245
|
-
action: 'timeout',
|
|
246
|
-
result: 'success',
|
|
247
|
-
metadata: {
|
|
248
|
-
quarantineId,
|
|
249
|
-
timeoutMs: MULTI_APPROVAL_TIMEOUT_MS,
|
|
250
|
-
expiredApprovals: expiredApprovals.map((a) => ({
|
|
251
|
-
reviewerId: a.reviewerId,
|
|
252
|
-
email: a.reviewerEmail,
|
|
253
|
-
approvedAt: a.createdAt,
|
|
254
|
-
})),
|
|
255
|
-
triggeredBy: {
|
|
256
|
-
userId: session.userId,
|
|
257
|
-
email: session.email,
|
|
258
|
-
},
|
|
259
|
-
},
|
|
260
|
-
});
|
|
261
|
-
throw new QuarantineServiceError('Multi-approval workflow timed out. Please start again.', 'INVALID_INPUT', { quarantineId, timeoutMs: MULTI_APPROVAL_TIMEOUT_MS });
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
// Record this approval in the database
|
|
265
|
-
this.approvalRepository.recordApproval({
|
|
266
|
-
skillId: quarantineId,
|
|
267
|
-
reviewerId: session.userId,
|
|
268
|
-
reviewerEmail: session.email,
|
|
269
|
-
decision: 'approved',
|
|
270
|
-
reason: input.reviewNotes,
|
|
271
|
-
requiredApprovals: MALICIOUS_APPROVAL_COUNT,
|
|
272
|
-
});
|
|
273
|
-
// Get current approval count and all pending approvals
|
|
274
|
-
const pendingApprovals = this.approvalRepository.getPendingApprovals(quarantineId);
|
|
275
|
-
const approvalCount = pendingApprovals.filter((a) => a.decision === 'approved').length;
|
|
276
|
-
// Build the multi-approval status from database state
|
|
277
|
-
const approvalStatus = this.buildMultiApprovalStatus(quarantineId, pendingApprovals);
|
|
278
|
-
// Log the approval
|
|
279
|
-
this.auditLogger.log({
|
|
280
|
-
event_type: 'quarantine_multi_approval',
|
|
281
|
-
actor: 'reviewer',
|
|
282
|
-
resource: skillId,
|
|
283
|
-
action: 'approve',
|
|
284
|
-
result: 'success',
|
|
285
|
-
metadata: {
|
|
286
|
-
quarantineId,
|
|
287
|
-
approvalNumber: approvalCount,
|
|
288
|
-
requiredApprovals: MALICIOUS_APPROVAL_COUNT,
|
|
289
|
-
reviewer: {
|
|
290
|
-
userId: session.userId,
|
|
291
|
-
email: session.email,
|
|
292
|
-
},
|
|
293
|
-
},
|
|
294
|
-
});
|
|
295
|
-
// Check if we have enough approvals
|
|
296
|
-
if (approvalCount >= MALICIOUS_APPROVAL_COUNT) {
|
|
297
|
-
// Mark approvals as complete in database
|
|
298
|
-
this.approvalRepository.markComplete(quarantineId);
|
|
299
|
-
approvalStatus.isComplete = true;
|
|
300
|
-
approvalStatus.completedAt = new Date();
|
|
301
|
-
// Perform the actual review
|
|
302
|
-
const approverEmails = pendingApprovals
|
|
303
|
-
.filter((a) => a.decision === 'approved')
|
|
304
|
-
.map((a) => a.reviewerEmail);
|
|
305
|
-
const reviewResult = this.repository.review(quarantineId, {
|
|
306
|
-
reviewedBy: approverEmails.join(', '),
|
|
307
|
-
reviewStatus: 'approved',
|
|
308
|
-
reviewNotes: `Multi-approval complete: ${approvalCount} reviewers approved. ${input.reviewNotes || ''}`,
|
|
309
|
-
});
|
|
310
|
-
// Log completion
|
|
311
|
-
this.auditLogger.log({
|
|
312
|
-
event_type: 'quarantine_multi_approval_complete',
|
|
313
|
-
actor: 'reviewer',
|
|
314
|
-
resource: skillId,
|
|
315
|
-
action: 'complete',
|
|
316
|
-
result: 'success',
|
|
317
|
-
metadata: {
|
|
318
|
-
quarantineId,
|
|
319
|
-
approvals: pendingApprovals
|
|
320
|
-
.filter((a) => a.decision === 'approved')
|
|
321
|
-
.map((a) => ({
|
|
322
|
-
reviewerId: a.reviewerId,
|
|
323
|
-
email: a.reviewerEmail,
|
|
324
|
-
approvedAt: a.createdAt,
|
|
325
|
-
})),
|
|
326
|
-
},
|
|
327
|
-
});
|
|
328
|
-
return {
|
|
329
|
-
success: true,
|
|
330
|
-
approved: true,
|
|
331
|
-
skillId,
|
|
332
|
-
severity: 'MALICIOUS',
|
|
333
|
-
canImport: reviewResult?.canImport ?? false,
|
|
334
|
-
warnings: [
|
|
335
|
-
'MALICIOUS skill approved through multi-approval workflow',
|
|
336
|
-
`Approved by: ${approverEmails.join(', ')}`,
|
|
337
|
-
],
|
|
338
|
-
reviewedBy: {
|
|
339
|
-
userId: session.userId,
|
|
340
|
-
email: session.email,
|
|
341
|
-
displayName: session.displayName,
|
|
342
|
-
},
|
|
343
|
-
multiApprovalStatus: approvalStatus,
|
|
344
|
-
};
|
|
345
|
-
}
|
|
346
|
-
// Need more approvals
|
|
347
|
-
return {
|
|
348
|
-
success: true,
|
|
349
|
-
approved: false,
|
|
350
|
-
skillId,
|
|
351
|
-
severity: 'MALICIOUS',
|
|
352
|
-
canImport: false,
|
|
353
|
-
warnings: [
|
|
354
|
-
`Multi-approval in progress: ${approvalCount}/${MALICIOUS_APPROVAL_COUNT} approvals received`,
|
|
355
|
-
`Requires ${MALICIOUS_APPROVAL_COUNT - approvalCount} more approval(s)`,
|
|
356
|
-
],
|
|
357
|
-
reviewedBy: {
|
|
358
|
-
userId: session.userId,
|
|
359
|
-
email: session.email,
|
|
360
|
-
displayName: session.displayName,
|
|
361
|
-
},
|
|
362
|
-
multiApprovalStatus: approvalStatus,
|
|
363
|
-
};
|
|
364
|
-
}
|
|
365
196
|
/**
|
|
366
197
|
* Get pending multi-approval status for a quarantine entry
|
|
367
198
|
*
|
|
@@ -375,7 +206,7 @@ export class QuarantineService {
|
|
|
375
206
|
if (pendingApprovals.length === 0) {
|
|
376
207
|
return null;
|
|
377
208
|
}
|
|
378
|
-
return
|
|
209
|
+
return buildMultiApprovalStatus(quarantineId, pendingApprovals);
|
|
379
210
|
}
|
|
380
211
|
/**
|
|
381
212
|
* Cancel a pending multi-approval workflow
|
|
@@ -432,33 +263,5 @@ export class QuarantineService {
|
|
|
432
263
|
this.approvalRepository.clearApprovals(id);
|
|
433
264
|
return this.repository.delete(id);
|
|
434
265
|
}
|
|
435
|
-
// ==========================================================================
|
|
436
|
-
// Private Helpers
|
|
437
|
-
// ==========================================================================
|
|
438
|
-
/**
|
|
439
|
-
* Build a MultiApprovalStatus from database rows
|
|
440
|
-
*
|
|
441
|
-
* Converts persisted approval entries into the MultiApprovalStatus
|
|
442
|
-
* interface expected by consumers.
|
|
443
|
-
*/
|
|
444
|
-
buildMultiApprovalStatus(quarantineId, approvals) {
|
|
445
|
-
const currentApprovals = approvals.map((a) => ({
|
|
446
|
-
reviewerId: a.reviewerId,
|
|
447
|
-
reviewerEmail: a.reviewerEmail,
|
|
448
|
-
approvedAt: new Date(a.createdAt),
|
|
449
|
-
notes: a.reason ?? undefined,
|
|
450
|
-
}));
|
|
451
|
-
const startedAt = approvals.length > 0 ? new Date(approvals[0].createdAt) : new Date();
|
|
452
|
-
const isComplete = approvals.some((a) => a.isComplete);
|
|
453
|
-
const completedEntry = approvals.find((a) => a.completedAt);
|
|
454
|
-
return {
|
|
455
|
-
quarantineId,
|
|
456
|
-
requiredApprovals: MALICIOUS_APPROVAL_COUNT,
|
|
457
|
-
currentApprovals,
|
|
458
|
-
isComplete,
|
|
459
|
-
startedAt,
|
|
460
|
-
completedAt: completedEntry ? new Date(completedEntry.completedAt) : undefined,
|
|
461
|
-
};
|
|
462
|
-
}
|
|
463
266
|
}
|
|
464
267
|
//# sourceMappingURL=QuarantineService.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QuarantineService.js","sourceRoot":"","sources":["../../../../src/services/quarantine/QuarantineService.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"QuarantineService.js","sourceRoot":"","sources":["../../../../src/services/quarantine/QuarantineService.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Multi-Approval Workflow for MALICIOUS Severity Quarantine
|
|
3
|
+
* @module @skillsmith/core/services/quarantine/QuarantineService.multiapproval
|
|
4
|
+
* @see SMI-2277: Persist multi-approval state to database
|
|
5
|
+
* @see SMI-2741: Split from QuarantineService.ts to meet 500-line standard
|
|
6
|
+
*
|
|
7
|
+
* Handles the multi-approval workflow required for MALICIOUS severity skills.
|
|
8
|
+
* MALICIOUS severity requires multiple independent reviewers to approve before
|
|
9
|
+
* a skill can be unquarantined, preventing single-reviewer compromise.
|
|
10
|
+
*/
|
|
11
|
+
import type { QuarantineRepository } from '../../repositories/quarantine/index.js';
|
|
12
|
+
import type { ApprovalRepository } from '../../repositories/quarantine/ApprovalRepository.js';
|
|
13
|
+
import type { AuditLogger } from '../../security/AuditLogger.js';
|
|
14
|
+
import type { AuthenticatedSession, AuthenticatedReviewInput, AuthenticatedReviewResult, MultiApprovalStatus } from './types.js';
|
|
15
|
+
/**
|
|
16
|
+
* Number of approvals required for MALICIOUS severity reviews
|
|
17
|
+
*/
|
|
18
|
+
export declare const MALICIOUS_APPROVAL_COUNT = 2;
|
|
19
|
+
/**
|
|
20
|
+
* Multi-approval timeout in milliseconds (24 hours)
|
|
21
|
+
*/
|
|
22
|
+
export declare const MULTI_APPROVAL_TIMEOUT_MS: number;
|
|
23
|
+
/**
|
|
24
|
+
* Handle approval for MALICIOUS severity skills
|
|
25
|
+
*
|
|
26
|
+
* MALICIOUS severity requires multiple reviewers to approve
|
|
27
|
+
* before a skill can be unquarantined. This prevents single
|
|
28
|
+
* reviewer compromise from allowing malicious skills.
|
|
29
|
+
*
|
|
30
|
+
* Approval state is persisted to the database (SMI-2277) so
|
|
31
|
+
* pending approvals survive service restarts.
|
|
32
|
+
*
|
|
33
|
+
* @param session - Authenticated session
|
|
34
|
+
* @param quarantineId - Quarantine entry ID
|
|
35
|
+
* @param skillId - Skill ID
|
|
36
|
+
* @param input - Review input
|
|
37
|
+
* @param repository - Quarantine repository
|
|
38
|
+
* @param approvalRepository - Approval repository
|
|
39
|
+
* @param auditLogger - Audit logger
|
|
40
|
+
* @returns Review result with multi-approval status
|
|
41
|
+
*/
|
|
42
|
+
export declare function handleMaliciousApproval(session: AuthenticatedSession, quarantineId: string, skillId: string, input: AuthenticatedReviewInput, repository: QuarantineRepository, approvalRepository: ApprovalRepository, auditLogger: AuditLogger): AuthenticatedReviewResult;
|
|
43
|
+
/**
|
|
44
|
+
* Build a MultiApprovalStatus from database rows
|
|
45
|
+
*
|
|
46
|
+
* Converts persisted approval entries into the MultiApprovalStatus
|
|
47
|
+
* interface expected by consumers.
|
|
48
|
+
*/
|
|
49
|
+
export declare function buildMultiApprovalStatus(quarantineId: string, approvals: Array<{
|
|
50
|
+
reviewerId: string;
|
|
51
|
+
reviewerEmail: string;
|
|
52
|
+
createdAt: string;
|
|
53
|
+
completedAt: string | null;
|
|
54
|
+
reason: string | null;
|
|
55
|
+
isComplete: boolean;
|
|
56
|
+
}>): MultiApprovalStatus;
|
|
57
|
+
//# sourceMappingURL=QuarantineService.multiapproval.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QuarantineService.multiapproval.d.ts","sourceRoot":"","sources":["../../../../src/services/quarantine/QuarantineService.multiapproval.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wCAAwC,CAAA;AAClF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qDAAqD,CAAA;AAC7F,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAA;AAChE,OAAO,KAAK,EACV,oBAAoB,EACpB,wBAAwB,EACxB,yBAAyB,EACzB,mBAAmB,EAEpB,MAAM,YAAY,CAAA;AAGnB;;GAEG;AACH,eAAO,MAAM,wBAAwB,IAAI,CAAA;AAEzC;;GAEG;AACH,eAAO,MAAM,yBAAyB,QAAsB,CAAA;AAE5D;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,oBAAoB,EAC7B,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,wBAAwB,EAC/B,UAAU,EAAE,oBAAoB,EAChC,kBAAkB,EAAE,kBAAkB,EACtC,WAAW,EAAE,WAAW,GACvB,yBAAyB,CAoK3B;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,KAAK,CAAC;IACf,UAAU,EAAE,MAAM,CAAA;IAClB,aAAa,EAAE,MAAM,CAAA;IACrB,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,UAAU,EAAE,OAAO,CAAA;CACpB,CAAC,GACD,mBAAmB,CAoBrB"}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Multi-Approval Workflow for MALICIOUS Severity Quarantine
|
|
3
|
+
* @module @skillsmith/core/services/quarantine/QuarantineService.multiapproval
|
|
4
|
+
* @see SMI-2277: Persist multi-approval state to database
|
|
5
|
+
* @see SMI-2741: Split from QuarantineService.ts to meet 500-line standard
|
|
6
|
+
*
|
|
7
|
+
* Handles the multi-approval workflow required for MALICIOUS severity skills.
|
|
8
|
+
* MALICIOUS severity requires multiple independent reviewers to approve before
|
|
9
|
+
* a skill can be unquarantined, preventing single-reviewer compromise.
|
|
10
|
+
*/
|
|
11
|
+
import { QuarantineServiceError, requirePermission } from './types.js';
|
|
12
|
+
/**
|
|
13
|
+
* Number of approvals required for MALICIOUS severity reviews
|
|
14
|
+
*/
|
|
15
|
+
export const MALICIOUS_APPROVAL_COUNT = 2;
|
|
16
|
+
/**
|
|
17
|
+
* Multi-approval timeout in milliseconds (24 hours)
|
|
18
|
+
*/
|
|
19
|
+
export const MULTI_APPROVAL_TIMEOUT_MS = 24 * 60 * 60 * 1000;
|
|
20
|
+
/**
|
|
21
|
+
* Handle approval for MALICIOUS severity skills
|
|
22
|
+
*
|
|
23
|
+
* MALICIOUS severity requires multiple reviewers to approve
|
|
24
|
+
* before a skill can be unquarantined. This prevents single
|
|
25
|
+
* reviewer compromise from allowing malicious skills.
|
|
26
|
+
*
|
|
27
|
+
* Approval state is persisted to the database (SMI-2277) so
|
|
28
|
+
* pending approvals survive service restarts.
|
|
29
|
+
*
|
|
30
|
+
* @param session - Authenticated session
|
|
31
|
+
* @param quarantineId - Quarantine entry ID
|
|
32
|
+
* @param skillId - Skill ID
|
|
33
|
+
* @param input - Review input
|
|
34
|
+
* @param repository - Quarantine repository
|
|
35
|
+
* @param approvalRepository - Approval repository
|
|
36
|
+
* @param auditLogger - Audit logger
|
|
37
|
+
* @returns Review result with multi-approval status
|
|
38
|
+
*/
|
|
39
|
+
export function handleMaliciousApproval(session, quarantineId, skillId, input, repository, approvalRepository, auditLogger) {
|
|
40
|
+
// Require elevated permission for MALICIOUS review
|
|
41
|
+
requirePermission(session, 'quarantine:review_malicious');
|
|
42
|
+
// Check if this reviewer already approved (database-backed)
|
|
43
|
+
if (approvalRepository.hasReviewerApproved(quarantineId, session.userId)) {
|
|
44
|
+
// Retrieve existing approval for error details
|
|
45
|
+
const existingApprovals = approvalRepository.getPendingApprovals(quarantineId);
|
|
46
|
+
const existing = existingApprovals.find((a) => a.reviewerId === session.userId);
|
|
47
|
+
throw new QuarantineServiceError('You have already approved this entry', 'ALREADY_REVIEWED', {
|
|
48
|
+
quarantineId,
|
|
49
|
+
previousApprovalAt: existing?.createdAt ?? 'unknown',
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
// Check for approval timeout
|
|
53
|
+
const startTime = approvalRepository.getWorkflowStartTime(quarantineId);
|
|
54
|
+
if (startTime) {
|
|
55
|
+
const timeSinceStart = Date.now() - new Date(startTime).getTime();
|
|
56
|
+
if (timeSinceStart > MULTI_APPROVAL_TIMEOUT_MS) {
|
|
57
|
+
// Capture existing approvals before clearing for audit
|
|
58
|
+
const expiredApprovals = approvalRepository.getPendingApprovals(quarantineId);
|
|
59
|
+
// Reset approval workflow
|
|
60
|
+
approvalRepository.clearApprovals(quarantineId);
|
|
61
|
+
// Log timeout event so cleared reviewer work is auditable
|
|
62
|
+
auditLogger.log({
|
|
63
|
+
event_type: 'quarantine_multi_approval_timeout',
|
|
64
|
+
actor: 'system',
|
|
65
|
+
resource: skillId,
|
|
66
|
+
action: 'timeout',
|
|
67
|
+
result: 'success',
|
|
68
|
+
metadata: {
|
|
69
|
+
quarantineId,
|
|
70
|
+
timeoutMs: MULTI_APPROVAL_TIMEOUT_MS,
|
|
71
|
+
expiredApprovals: expiredApprovals.map((a) => ({
|
|
72
|
+
reviewerId: a.reviewerId,
|
|
73
|
+
email: a.reviewerEmail,
|
|
74
|
+
approvedAt: a.createdAt,
|
|
75
|
+
})),
|
|
76
|
+
triggeredBy: {
|
|
77
|
+
userId: session.userId,
|
|
78
|
+
email: session.email,
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
throw new QuarantineServiceError('Multi-approval workflow timed out. Please start again.', 'INVALID_INPUT', { quarantineId, timeoutMs: MULTI_APPROVAL_TIMEOUT_MS });
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// Record this approval in the database
|
|
86
|
+
approvalRepository.recordApproval({
|
|
87
|
+
skillId: quarantineId,
|
|
88
|
+
reviewerId: session.userId,
|
|
89
|
+
reviewerEmail: session.email,
|
|
90
|
+
decision: 'approved',
|
|
91
|
+
reason: input.reviewNotes,
|
|
92
|
+
requiredApprovals: MALICIOUS_APPROVAL_COUNT,
|
|
93
|
+
});
|
|
94
|
+
// Get current approval count and all pending approvals
|
|
95
|
+
const pendingApprovals = approvalRepository.getPendingApprovals(quarantineId);
|
|
96
|
+
const approvalCount = pendingApprovals.filter((a) => a.decision === 'approved').length;
|
|
97
|
+
// Build the multi-approval status from database state
|
|
98
|
+
const approvalStatus = buildMultiApprovalStatus(quarantineId, pendingApprovals);
|
|
99
|
+
// Log the approval
|
|
100
|
+
auditLogger.log({
|
|
101
|
+
event_type: 'quarantine_multi_approval',
|
|
102
|
+
actor: 'reviewer',
|
|
103
|
+
resource: skillId,
|
|
104
|
+
action: 'approve',
|
|
105
|
+
result: 'success',
|
|
106
|
+
metadata: {
|
|
107
|
+
quarantineId,
|
|
108
|
+
approvalNumber: approvalCount,
|
|
109
|
+
requiredApprovals: MALICIOUS_APPROVAL_COUNT,
|
|
110
|
+
reviewer: {
|
|
111
|
+
userId: session.userId,
|
|
112
|
+
email: session.email,
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
});
|
|
116
|
+
// Check if we have enough approvals
|
|
117
|
+
if (approvalCount >= MALICIOUS_APPROVAL_COUNT) {
|
|
118
|
+
// Mark approvals as complete in database
|
|
119
|
+
approvalRepository.markComplete(quarantineId);
|
|
120
|
+
approvalStatus.isComplete = true;
|
|
121
|
+
approvalStatus.completedAt = new Date();
|
|
122
|
+
// Perform the actual review
|
|
123
|
+
const approverEmails = pendingApprovals
|
|
124
|
+
.filter((a) => a.decision === 'approved')
|
|
125
|
+
.map((a) => a.reviewerEmail);
|
|
126
|
+
const reviewResult = repository.review(quarantineId, {
|
|
127
|
+
reviewedBy: approverEmails.join(', '),
|
|
128
|
+
reviewStatus: 'approved',
|
|
129
|
+
reviewNotes: `Multi-approval complete: ${approvalCount} reviewers approved. ${input.reviewNotes || ''}`,
|
|
130
|
+
});
|
|
131
|
+
// Log completion
|
|
132
|
+
auditLogger.log({
|
|
133
|
+
event_type: 'quarantine_multi_approval_complete',
|
|
134
|
+
actor: 'reviewer',
|
|
135
|
+
resource: skillId,
|
|
136
|
+
action: 'complete',
|
|
137
|
+
result: 'success',
|
|
138
|
+
metadata: {
|
|
139
|
+
quarantineId,
|
|
140
|
+
approvals: pendingApprovals
|
|
141
|
+
.filter((a) => a.decision === 'approved')
|
|
142
|
+
.map((a) => ({
|
|
143
|
+
reviewerId: a.reviewerId,
|
|
144
|
+
email: a.reviewerEmail,
|
|
145
|
+
approvedAt: a.createdAt,
|
|
146
|
+
})),
|
|
147
|
+
},
|
|
148
|
+
});
|
|
149
|
+
return {
|
|
150
|
+
success: true,
|
|
151
|
+
approved: true,
|
|
152
|
+
skillId,
|
|
153
|
+
severity: 'MALICIOUS',
|
|
154
|
+
canImport: reviewResult?.canImport ?? false,
|
|
155
|
+
warnings: [
|
|
156
|
+
'MALICIOUS skill approved through multi-approval workflow',
|
|
157
|
+
`Approved by: ${approverEmails.join(', ')}`,
|
|
158
|
+
],
|
|
159
|
+
reviewedBy: {
|
|
160
|
+
userId: session.userId,
|
|
161
|
+
email: session.email,
|
|
162
|
+
displayName: session.displayName,
|
|
163
|
+
},
|
|
164
|
+
multiApprovalStatus: approvalStatus,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
// Need more approvals
|
|
168
|
+
return {
|
|
169
|
+
success: true,
|
|
170
|
+
approved: false,
|
|
171
|
+
skillId,
|
|
172
|
+
severity: 'MALICIOUS',
|
|
173
|
+
canImport: false,
|
|
174
|
+
warnings: [
|
|
175
|
+
`Multi-approval in progress: ${approvalCount}/${MALICIOUS_APPROVAL_COUNT} approvals received`,
|
|
176
|
+
`Requires ${MALICIOUS_APPROVAL_COUNT - approvalCount} more approval(s)`,
|
|
177
|
+
],
|
|
178
|
+
reviewedBy: {
|
|
179
|
+
userId: session.userId,
|
|
180
|
+
email: session.email,
|
|
181
|
+
displayName: session.displayName,
|
|
182
|
+
},
|
|
183
|
+
multiApprovalStatus: approvalStatus,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Build a MultiApprovalStatus from database rows
|
|
188
|
+
*
|
|
189
|
+
* Converts persisted approval entries into the MultiApprovalStatus
|
|
190
|
+
* interface expected by consumers.
|
|
191
|
+
*/
|
|
192
|
+
export function buildMultiApprovalStatus(quarantineId, approvals) {
|
|
193
|
+
const currentApprovals = approvals.map((a) => ({
|
|
194
|
+
reviewerId: a.reviewerId,
|
|
195
|
+
reviewerEmail: a.reviewerEmail,
|
|
196
|
+
approvedAt: new Date(a.createdAt),
|
|
197
|
+
notes: a.reason ?? undefined,
|
|
198
|
+
}));
|
|
199
|
+
const startedAt = approvals.length > 0 ? new Date(approvals[0].createdAt) : new Date();
|
|
200
|
+
const isComplete = approvals.some((a) => a.isComplete);
|
|
201
|
+
const completedEntry = approvals.find((a) => a.completedAt);
|
|
202
|
+
return {
|
|
203
|
+
quarantineId,
|
|
204
|
+
requiredApprovals: MALICIOUS_APPROVAL_COUNT,
|
|
205
|
+
currentApprovals,
|
|
206
|
+
isComplete,
|
|
207
|
+
startedAt,
|
|
208
|
+
completedAt: completedEntry ? new Date(completedEntry.completedAt) : undefined,
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
//# sourceMappingURL=QuarantineService.multiapproval.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QuarantineService.multiapproval.js","sourceRoot":"","sources":["../../../../src/services/quarantine/QuarantineService.multiapproval.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Session Manager for Claude-Flow Memory Integration
|
|
3
3
|
* SMI-641: Session ID Storage in Claude-Flow Memory
|
|
4
4
|
* SMI-1518: V3 API Migration - Use direct API calls instead of spawn
|
|
5
|
+
* SMI-2741: Split to meet 500-line standard
|
|
5
6
|
*
|
|
6
7
|
* Manages session lifecycle with persistent storage in claude-flow memory
|
|
7
8
|
* to enable context restoration across sessions.
|
|
@@ -10,6 +11,7 @@ import type { SessionData, Checkpoint } from './SessionContext.js';
|
|
|
10
11
|
import type { CommandExecutor, SessionOptions } from './SessionManager.types.js';
|
|
11
12
|
export type { CommandExecutor, MemoryResult, SessionOptions } from './SessionManager.types.js';
|
|
12
13
|
export { DefaultCommandExecutor } from './SessionManager.helpers.js';
|
|
14
|
+
export { storeMemoryEntry, retrieveMemoryEntry, deleteMemoryEntry, runPreTaskHook, runPostTaskHook, } from './SessionManager.memory.js';
|
|
13
15
|
/**
|
|
14
16
|
* Session Manager for claude-flow memory integration
|
|
15
17
|
*
|
|
@@ -85,38 +87,5 @@ export declare class SessionManager {
|
|
|
85
87
|
* Clear the current session pointer
|
|
86
88
|
*/
|
|
87
89
|
private clearCurrentSession;
|
|
88
|
-
/**
|
|
89
|
-
* Store data in claude-flow memory
|
|
90
|
-
*
|
|
91
|
-
* SMI-674: Uses spawn() with argument array to prevent command injection
|
|
92
|
-
* SMI-1518: V3 API Migration - Use direct storeEntry() when available
|
|
93
|
-
*/
|
|
94
|
-
private storeMemory;
|
|
95
|
-
/**
|
|
96
|
-
* Retrieve data from claude-flow memory
|
|
97
|
-
*
|
|
98
|
-
* SMI-674: Uses spawn() with argument array to prevent command injection
|
|
99
|
-
* SMI-1518: V3 API Migration - Use direct getEntry() when available
|
|
100
|
-
*/
|
|
101
|
-
private retrieveMemory;
|
|
102
|
-
/**
|
|
103
|
-
* Delete data from claude-flow memory
|
|
104
|
-
*
|
|
105
|
-
* SMI-674: Uses spawn() with argument array to prevent command injection
|
|
106
|
-
* SMI-1518: V3 API Migration - Use callMCPTool('memory/delete') when available
|
|
107
|
-
*/
|
|
108
|
-
private deleteMemory;
|
|
109
|
-
/**
|
|
110
|
-
* Run pre-task hook
|
|
111
|
-
* SMI-674: Uses spawn() with argument array to prevent command injection
|
|
112
|
-
* SMI-1518: V3 API Migration - Use callMCPTool('hooks/pre-task') when available
|
|
113
|
-
*/
|
|
114
|
-
private runPreTaskHook;
|
|
115
|
-
/**
|
|
116
|
-
* Run post-task hook
|
|
117
|
-
* SMI-674: Uses spawn() with argument array to prevent command injection
|
|
118
|
-
* SMI-1518: V3 API Migration - Use callMCPTool('hooks/post-task') when available
|
|
119
|
-
*/
|
|
120
|
-
private runPostTaskHook;
|
|
121
90
|
}
|
|
122
91
|
//# sourceMappingURL=SessionManager.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionManager.d.ts","sourceRoot":"","sources":["../../../src/session/SessionManager.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"SessionManager.d.ts","sourceRoot":"","sources":["../../../src/session/SessionManager.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAGlE,OAAO,KAAK,EAAE,eAAe,EAAgB,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAgB9F,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAC9F,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAA;AACpE,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,iBAAiB,EACjB,cAAc,EACd,eAAe,GAChB,MAAM,4BAA4B,CAAA;AAEnC;;;;;;;;;;;;GAYG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAiB;IACjC,OAAO,CAAC,cAAc,CAA2B;IAEjD;;;OAGG;IACH,OAAO,CAAC,WAAW,CAAmC;gBAE1C,QAAQ,CAAC,EAAE,eAAe;IAItC;;;OAGG;YACW,QAAQ;IAiBtB;;OAEG;IACH,iBAAiB,IAAI,MAAM;IAI3B;;OAEG;IACG,YAAY,CAAC,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,WAAW,CAAC;IA6BtE;;;;;OAKG;IACG,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAqDhE;;;OAGG;IACG,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAezD;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAiBjC;;OAEG;IACH,iBAAiB,IAAI,WAAW,GAAG,IAAI;IAIvC;;OAEG;IACG,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAehE;;OAEG;IACG,mBAAmB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAenD;;OAEG;YACW,YAAY;IAM1B;;OAEG;YACW,iBAAiB;IAI/B;;OAEG;YACW,mBAAmB;CAGlC"}
|