comisai 1.0.10 → 1.0.12
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 +3 -3
- package/node_modules/@comis/agent/dist/executor/pi-executor.d.ts +1 -4
- package/node_modules/@comis/agent/package.json +1 -1
- package/node_modules/@comis/channels/package.json +1 -1
- package/node_modules/@comis/cli/dist/wizard/steps/06-channels.js +88 -11
- package/node_modules/@comis/cli/dist/wizard/steps/10-write-config.js +4 -0
- package/node_modules/@comis/cli/dist/wizard/types.d.ts +1 -0
- package/node_modules/@comis/cli/package.json +1 -1
- package/node_modules/@comis/core/package.json +1 -1
- package/node_modules/@comis/daemon/package.json +1 -1
- package/node_modules/@comis/gateway/package.json +1 -1
- package/node_modules/@comis/infra/package.json +1 -1
- package/node_modules/@comis/memory/package.json +1 -1
- package/node_modules/@comis/scheduler/package.json +1 -1
- package/node_modules/@comis/shared/package.json +1 -1
- package/node_modules/@comis/skills/package.json +1 -1
- package/package.json +18 -18
- package/node_modules/@comis/core/dist/approval/approval-gate.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/approval/approval-gate.test.js +0 -1003
- package/node_modules/@comis/core/dist/bootstrap.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/bootstrap.test.js +0 -150
- package/node_modules/@comis/core/dist/config/backup.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/config/backup.test.js +0 -160
- package/node_modules/@comis/core/dist/config/env-substitution.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/config/env-substitution.test.js +0 -259
- package/node_modules/@comis/core/dist/config/field-metadata.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/config/field-metadata.test.js +0 -72
- package/node_modules/@comis/core/dist/config/git-manager.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/config/git-manager.test.js +0 -1042
- package/node_modules/@comis/core/dist/config/immutable-keys.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/config/immutable-keys.test.js +0 -283
- package/node_modules/@comis/core/dist/config/include-resolver.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/config/include-resolver.test.js +0 -292
- package/node_modules/@comis/core/dist/config/layered.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/config/layered.test.js +0 -211
- package/node_modules/@comis/core/dist/config/loader.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/config/loader.test.js +0 -300
- package/node_modules/@comis/core/dist/config/migrate.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/config/migrate.test.js +0 -244
- package/node_modules/@comis/core/dist/config/partial-validator.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/config/partial-validator.test.js +0 -98
- package/node_modules/@comis/core/dist/config/schema-agent-model.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/config/schema-agent-model.test.js +0 -279
- package/node_modules/@comis/core/dist/config/schema-agent-session.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/config/schema-agent-session.test.js +0 -242
- package/node_modules/@comis/core/dist/config/schema-agent.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/config/schema-agent.test.js +0 -645
- package/node_modules/@comis/core/dist/config/schema-channel.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/config/schema-channel.test.js +0 -341
- package/node_modules/@comis/core/dist/config/schema-coalescer.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/config/schema-coalescer.test.js +0 -51
- package/node_modules/@comis/core/dist/config/schema-context-engine.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/config/schema-context-engine.test.js +0 -797
- package/node_modules/@comis/core/dist/config/schema-context-guard.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/config/schema-context-guard.test.js +0 -111
- package/node_modules/@comis/core/dist/config/schema-daemon.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/config/schema-daemon.test.js +0 -107
- package/node_modules/@comis/core/dist/config/schema-delivery-timing.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/config/schema-delivery-timing.test.js +0 -51
- package/node_modules/@comis/core/dist/config/schema-documentation.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/config/schema-documentation.test.js +0 -63
- package/node_modules/@comis/core/dist/config/schema-gateway.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/config/schema-gateway.test.js +0 -219
- package/node_modules/@comis/core/dist/config/schema-gemini-cache.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/config/schema-gemini-cache.test.js +0 -41
- package/node_modules/@comis/core/dist/config/schema-integrations.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/config/schema-integrations.test.js +0 -92
- package/node_modules/@comis/core/dist/config/schema-lifecycle-reactions.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/config/schema-lifecycle-reactions.test.js +0 -61
- package/node_modules/@comis/core/dist/config/schema-misc.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/config/schema-misc.test.js +0 -394
- package/node_modules/@comis/core/dist/config/schema-observability.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/config/schema-observability.test.js +0 -76
- package/node_modules/@comis/core/dist/config/schema-providers.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/config/schema-providers.test.js +0 -294
- package/node_modules/@comis/core/dist/config/schema-queue.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/config/schema-queue.test.js +0 -234
- package/node_modules/@comis/core/dist/config/schema-response-prefix.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/config/schema-response-prefix.test.js +0 -36
- package/node_modules/@comis/core/dist/config/schema-security.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/config/schema-security.test.js +0 -54
- package/node_modules/@comis/core/dist/config/schema-sender-trust-display.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/config/schema-sender-trust-display.test.js +0 -60
- package/node_modules/@comis/core/dist/config/schema-serializer.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/config/schema-serializer.test.js +0 -73
- package/node_modules/@comis/core/dist/config/schema-telegram-file-guard.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/config/schema-telegram-file-guard.test.js +0 -39
- package/node_modules/@comis/core/dist/context/context.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/context/context.test.js +0 -276
- package/node_modules/@comis/core/dist/domain/agent-response.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/domain/agent-response.test.js +0 -159
- package/node_modules/@comis/core/dist/domain/credential-mapping.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/domain/credential-mapping.test.js +0 -135
- package/node_modules/@comis/core/dist/domain/delivery-origin.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/domain/delivery-origin.test.js +0 -68
- package/node_modules/@comis/core/dist/domain/execution-graph.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/domain/execution-graph.test.js +0 -441
- package/node_modules/@comis/core/dist/domain/memory-entry.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/domain/memory-entry.test.js +0 -193
- package/node_modules/@comis/core/dist/domain/normalized-message.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/domain/normalized-message.test.js +0 -255
- package/node_modules/@comis/core/dist/domain/session-key.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/domain/session-key.test.js +0 -291
- package/node_modules/@comis/core/dist/domain/subagent-context-config.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/domain/subagent-context-config.test.js +0 -131
- package/node_modules/@comis/core/dist/domain/subagent-context-types.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/domain/subagent-context-types.test.js +0 -182
- package/node_modules/@comis/core/dist/event-bus/bus.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/event-bus/bus.test.js +0 -152
- package/node_modules/@comis/core/dist/event-bus/events-agent.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/event-bus/events-agent.test.js +0 -409
- package/node_modules/@comis/core/dist/event-bus/events-channel.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/event-bus/events-channel.test.js +0 -240
- package/node_modules/@comis/core/dist/event-bus/events-infra.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/event-bus/events-infra.test.js +0 -416
- package/node_modules/@comis/core/dist/event-bus/events-messaging.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/event-bus/events-messaging.test.js +0 -433
- package/node_modules/@comis/core/dist/event-bus/events.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/event-bus/events.test.js +0 -93
- package/node_modules/@comis/core/dist/hooks/hook-runner-global.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/hooks/hook-runner-global.test.js +0 -29
- package/node_modules/@comis/core/dist/hooks/hook-runner.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/hooks/hook-runner.test.js +0 -490
- package/node_modules/@comis/core/dist/hooks/hook-strategies.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/hooks/hook-strategies.test.js +0 -209
- package/node_modules/@comis/core/dist/hooks/integration.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/hooks/integration.test.js +0 -235
- package/node_modules/@comis/core/dist/hooks/plugin-registry.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/hooks/plugin-registry.test.js +0 -470
- package/node_modules/@comis/core/dist/load-env.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/load-env.test.js +0 -21
- package/node_modules/@comis/core/dist/security/action-classifier.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/security/action-classifier.test.js +0 -298
- package/node_modules/@comis/core/dist/security/audit-aggregator.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/security/audit-aggregator.test.js +0 -128
- package/node_modules/@comis/core/dist/security/audit.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/security/audit.test.js +0 -154
- package/node_modules/@comis/core/dist/security/canary-token.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/security/canary-token.test.js +0 -45
- package/node_modules/@comis/core/dist/security/config-redaction.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/security/config-redaction.test.js +0 -107
- package/node_modules/@comis/core/dist/security/external-content.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/security/external-content.test.js +0 -210
- package/node_modules/@comis/core/dist/security/injection-patterns.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/security/injection-patterns.test.js +0 -213
- package/node_modules/@comis/core/dist/security/injection-rate-limiter.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/security/injection-rate-limiter.test.js +0 -194
- package/node_modules/@comis/core/dist/security/input-guard.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/security/input-guard.test.js +0 -215
- package/node_modules/@comis/core/dist/security/input-security-guard.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/security/input-security-guard.test.js +0 -215
- package/node_modules/@comis/core/dist/security/input-validator.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/security/input-validator.test.js +0 -133
- package/node_modules/@comis/core/dist/security/log-sanitizer.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/security/log-sanitizer.test.js +0 -260
- package/node_modules/@comis/core/dist/security/memory-write-validator.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/security/memory-write-validator.test.js +0 -62
- package/node_modules/@comis/core/dist/security/output-guard.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/security/output-guard.test.js +0 -397
- package/node_modules/@comis/core/dist/security/safe-path.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/security/safe-path.test.js +0 -95
- package/node_modules/@comis/core/dist/security/scoped-secret-manager.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/security/scoped-secret-manager.test.js +0 -231
- package/node_modules/@comis/core/dist/security/secret-access.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/security/secret-access.test.js +0 -41
- package/node_modules/@comis/core/dist/security/secret-crypto.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/security/secret-crypto.test.js +0 -113
- package/node_modules/@comis/core/dist/security/secret-manager.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/security/secret-manager.test.js +0 -394
- package/node_modules/@comis/core/dist/security/secret-ref-resolver.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/security/secret-ref-resolver.test.js +0 -268
- package/node_modules/@comis/core/dist/security/secrets-audit.test.d.ts +0 -10
- package/node_modules/@comis/core/dist/security/secrets-audit.test.js +0 -295
- package/node_modules/@comis/core/dist/security/ssrf-guard.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/security/ssrf-guard.test.js +0 -127
- package/node_modules/@comis/core/dist/security/token-generator.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/security/token-generator.test.js +0 -35
- package/node_modules/@comis/core/dist/tool-metadata.test.d.ts +0 -1
- package/node_modules/@comis/core/dist/tool-metadata.test.js +0 -112
- package/node_modules/@comis/memory/dist/compaction.test.d.ts +0 -1
- package/node_modules/@comis/memory/dist/compaction.test.js +0 -298
- package/node_modules/@comis/memory/dist/context-schema.test.d.ts +0 -1
- package/node_modules/@comis/memory/dist/context-schema.test.js +0 -246
- package/node_modules/@comis/memory/dist/context-store.test.d.ts +0 -1
- package/node_modules/@comis/memory/dist/context-store.test.js +0 -708
- package/node_modules/@comis/memory/dist/credential-mapping-schema.test.d.ts +0 -7
- package/node_modules/@comis/memory/dist/credential-mapping-schema.test.js +0 -73
- package/node_modules/@comis/memory/dist/credential-mapping-store.test.d.ts +0 -8
- package/node_modules/@comis/memory/dist/credential-mapping-store.test.js +0 -340
- package/node_modules/@comis/memory/dist/delivery-mirror-adapter.test.d.ts +0 -1
- package/node_modules/@comis/memory/dist/delivery-mirror-adapter.test.js +0 -165
- package/node_modules/@comis/memory/dist/delivery-queue-adapter.test.d.ts +0 -1
- package/node_modules/@comis/memory/dist/delivery-queue-adapter.test.js +0 -263
- package/node_modules/@comis/memory/dist/embedding-batch-indexer.test.d.ts +0 -1
- package/node_modules/@comis/memory/dist/embedding-batch-indexer.test.js +0 -202
- package/node_modules/@comis/memory/dist/embedding-cache-lru.test.d.ts +0 -1
- package/node_modules/@comis/memory/dist/embedding-cache-lru.test.js +0 -241
- package/node_modules/@comis/memory/dist/embedding-cache-sqlite.test.d.ts +0 -8
- package/node_modules/@comis/memory/dist/embedding-cache-sqlite.test.js +0 -678
- package/node_modules/@comis/memory/dist/embedding-cache.test.d.ts +0 -1
- package/node_modules/@comis/memory/dist/embedding-cache.test.js +0 -213
- package/node_modules/@comis/memory/dist/embedding-fingerprint.test.d.ts +0 -1
- package/node_modules/@comis/memory/dist/embedding-fingerprint.test.js +0 -87
- package/node_modules/@comis/memory/dist/embedding-hash.test.d.ts +0 -1
- package/node_modules/@comis/memory/dist/embedding-hash.test.js +0 -31
- package/node_modules/@comis/memory/dist/embedding-integration.test.d.ts +0 -8
- package/node_modules/@comis/memory/dist/embedding-integration.test.js +0 -232
- package/node_modules/@comis/memory/dist/embedding-provider-factory.test.d.ts +0 -1
- package/node_modules/@comis/memory/dist/embedding-provider-factory.test.js +0 -176
- package/node_modules/@comis/memory/dist/embedding-provider-local.test.d.ts +0 -8
- package/node_modules/@comis/memory/dist/embedding-provider-local.test.js +0 -76
- package/node_modules/@comis/memory/dist/embedding-provider-openai.test.d.ts +0 -8
- package/node_modules/@comis/memory/dist/embedding-provider-openai.test.js +0 -100
- package/node_modules/@comis/memory/dist/embedding-queue.test.d.ts +0 -1
- package/node_modules/@comis/memory/dist/embedding-queue.test.js +0 -236
- package/node_modules/@comis/memory/dist/hybrid-search.test.d.ts +0 -1
- package/node_modules/@comis/memory/dist/hybrid-search.test.js +0 -476
- package/node_modules/@comis/memory/dist/identity-link-store.test.d.ts +0 -1
- package/node_modules/@comis/memory/dist/identity-link-store.test.js +0 -88
- package/node_modules/@comis/memory/dist/memory-api.test.d.ts +0 -1
- package/node_modules/@comis/memory/dist/memory-api.test.js +0 -495
- package/node_modules/@comis/memory/dist/memory-concurrency.test.d.ts +0 -20
- package/node_modules/@comis/memory/dist/memory-concurrency.test.js +0 -222
- package/node_modules/@comis/memory/dist/named-graph-store.test.d.ts +0 -1
- package/node_modules/@comis/memory/dist/named-graph-store.test.js +0 -227
- package/node_modules/@comis/memory/dist/observability-store.test.d.ts +0 -1
- package/node_modules/@comis/memory/dist/observability-store.test.js +0 -704
- package/node_modules/@comis/memory/dist/row-mapper.test.d.ts +0 -1
- package/node_modules/@comis/memory/dist/row-mapper.test.js +0 -409
- package/node_modules/@comis/memory/dist/schema.test.d.ts +0 -1
- package/node_modules/@comis/memory/dist/schema.test.js +0 -240
- package/node_modules/@comis/memory/dist/secret-store-schema.test.d.ts +0 -7
- package/node_modules/@comis/memory/dist/secret-store-schema.test.js +0 -90
- package/node_modules/@comis/memory/dist/session-store.test.d.ts +0 -1
- package/node_modules/@comis/memory/dist/session-store.test.js +0 -262
- package/node_modules/@comis/memory/dist/setup-secrets.test.d.ts +0 -1
- package/node_modules/@comis/memory/dist/setup-secrets.test.js +0 -140
- package/node_modules/@comis/memory/dist/sqlite-memory-adapter.test.d.ts +0 -1
- package/node_modules/@comis/memory/dist/sqlite-memory-adapter.test.js +0 -888
- package/node_modules/@comis/memory/dist/sqlite-secret-store.test.d.ts +0 -8
- package/node_modules/@comis/memory/dist/sqlite-secret-store.test.js +0 -245
- package/node_modules/@comis/shared/dist/abort.test.d.ts +0 -1
- package/node_modules/@comis/shared/dist/abort.test.js +0 -71
- package/node_modules/@comis/shared/dist/result.test.d.ts +0 -1
- package/node_modules/@comis/shared/dist/result.test.js +0 -178
- package/node_modules/@comis/shared/dist/suppress-error.test.d.ts +0 -1
- package/node_modules/@comis/shared/dist/suppress-error.test.js +0 -50
- package/node_modules/@comis/shared/dist/timeout.test.d.ts +0 -1
- package/node_modules/@comis/shared/dist/timeout.test.js +0 -75
- package/node_modules/@comis/shared/dist/ttl-cache.test.d.ts +0 -1
- package/node_modules/@comis/shared/dist/ttl-cache.test.js +0 -81
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for credential mapping schema DDL.
|
|
3
|
-
*
|
|
4
|
-
* Uses in-memory SQLite databases with the secrets table as a prerequisite
|
|
5
|
-
* (credential_mappings has a foreign key to secrets(name)).
|
|
6
|
-
*/
|
|
7
|
-
import { describe, it, expect, beforeEach } from "vitest";
|
|
8
|
-
import Database from "better-sqlite3";
|
|
9
|
-
import { initSecretSchema } from "./secret-store-schema.js";
|
|
10
|
-
import { initCredentialMappingSchema } from "./credential-mapping-schema.js";
|
|
11
|
-
describe("initCredentialMappingSchema", () => {
|
|
12
|
-
let db;
|
|
13
|
-
beforeEach(() => {
|
|
14
|
-
db = new Database(":memory:");
|
|
15
|
-
db.pragma("foreign_keys = ON");
|
|
16
|
-
// Prerequisite: secrets table must exist for the foreign key
|
|
17
|
-
initSecretSchema(db);
|
|
18
|
-
});
|
|
19
|
-
it("creates credential_mappings table with expected columns", () => {
|
|
20
|
-
initCredentialMappingSchema(db);
|
|
21
|
-
const columns = db
|
|
22
|
-
.prepare("PRAGMA table_info(credential_mappings)")
|
|
23
|
-
.all();
|
|
24
|
-
const columnNames = columns.map((c) => c.name);
|
|
25
|
-
expect(columnNames).toContain("id");
|
|
26
|
-
expect(columnNames).toContain("secret_name");
|
|
27
|
-
expect(columnNames).toContain("injection_type");
|
|
28
|
-
expect(columnNames).toContain("injection_key");
|
|
29
|
-
expect(columnNames).toContain("url_pattern");
|
|
30
|
-
expect(columnNames).toContain("tool_name");
|
|
31
|
-
// Should have exactly 6 columns
|
|
32
|
-
expect(columns).toHaveLength(6);
|
|
33
|
-
// Verify id is primary key
|
|
34
|
-
const pkColumn = columns.find((c) => c.pk === 1);
|
|
35
|
-
expect(pkColumn?.name).toBe("id");
|
|
36
|
-
// Verify NOT NULL constraints
|
|
37
|
-
const notNullColumns = columns.filter((c) => c.notnull === 1).map((c) => c.name);
|
|
38
|
-
expect(notNullColumns).toContain("secret_name");
|
|
39
|
-
expect(notNullColumns).toContain("injection_type");
|
|
40
|
-
expect(notNullColumns).toContain("url_pattern");
|
|
41
|
-
});
|
|
42
|
-
it("is idempotent (safe to call multiple times)", () => {
|
|
43
|
-
initCredentialMappingSchema(db);
|
|
44
|
-
initCredentialMappingSchema(db);
|
|
45
|
-
const columns = db
|
|
46
|
-
.prepare("PRAGMA table_info(credential_mappings)")
|
|
47
|
-
.all();
|
|
48
|
-
expect(columns).toHaveLength(6);
|
|
49
|
-
});
|
|
50
|
-
it("rejects invalid injection_type via CHECK constraint", () => {
|
|
51
|
-
initCredentialMappingSchema(db);
|
|
52
|
-
// Insert a valid secret first (foreign key prerequisite)
|
|
53
|
-
db.prepare("INSERT INTO secrets (name, ciphertext, iv, auth_tag, salt, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?)").run("test-secret", Buffer.from("c"), Buffer.from("i"), Buffer.from("a"), Buffer.from("s"), Date.now(), Date.now());
|
|
54
|
-
expect(() => {
|
|
55
|
-
db.prepare("INSERT INTO credential_mappings (id, secret_name, injection_type, url_pattern) VALUES (?, ?, ?, ?)").run("map-1", "test-secret", "invalid", "https://api.example.com/*");
|
|
56
|
-
}).toThrow(/CHECK/);
|
|
57
|
-
});
|
|
58
|
-
it("rejects foreign key violation (non-existent secret)", () => {
|
|
59
|
-
initCredentialMappingSchema(db);
|
|
60
|
-
expect(() => {
|
|
61
|
-
db.prepare("INSERT INTO credential_mappings (id, secret_name, injection_type, url_pattern) VALUES (?, ?, ?, ?)").run("map-1", "nonexistent-secret", "bearer_header", "https://api.example.com/*");
|
|
62
|
-
}).toThrow(/FOREIGN KEY/);
|
|
63
|
-
});
|
|
64
|
-
it("creates indexes on secret_name and tool_name", () => {
|
|
65
|
-
initCredentialMappingSchema(db);
|
|
66
|
-
const indexes = db
|
|
67
|
-
.prepare("PRAGMA index_list(credential_mappings)")
|
|
68
|
-
.all();
|
|
69
|
-
const indexNames = indexes.map((i) => i.name);
|
|
70
|
-
expect(indexNames).toContain("idx_cred_map_secret");
|
|
71
|
-
expect(indexNames).toContain("idx_cred_map_tool");
|
|
72
|
-
});
|
|
73
|
-
});
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for CredentialMappingStore — CredentialMappingPort implementation
|
|
3
|
-
* with SQLite CRUD operations.
|
|
4
|
-
*
|
|
5
|
-
* Uses in-memory SQLite databases with foreign_keys enabled.
|
|
6
|
-
* Each test gets a fresh database with the secrets table and a dummy secret.
|
|
7
|
-
*/
|
|
8
|
-
export {};
|
|
@@ -1,340 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for CredentialMappingStore — CredentialMappingPort implementation
|
|
3
|
-
* with SQLite CRUD operations.
|
|
4
|
-
*
|
|
5
|
-
* Uses in-memory SQLite databases with foreign_keys enabled.
|
|
6
|
-
* Each test gets a fresh database with the secrets table and a dummy secret.
|
|
7
|
-
*/
|
|
8
|
-
import { describe, it, expect, beforeEach } from "vitest";
|
|
9
|
-
import Database from "better-sqlite3";
|
|
10
|
-
import { initSecretSchema } from "./secret-store-schema.js";
|
|
11
|
-
import { createCredentialMappingStore } from "./credential-mapping-store.js";
|
|
12
|
-
/** Unwrap a Result or fail the test. */
|
|
13
|
-
function unwrap(result) {
|
|
14
|
-
if (!result.ok) {
|
|
15
|
-
throw new Error(`Expected ok result, got error: ${result.error.message}`);
|
|
16
|
-
}
|
|
17
|
-
return result.value;
|
|
18
|
-
}
|
|
19
|
-
/** Insert a dummy secret into the secrets table (needed for foreign key). */
|
|
20
|
-
function insertDummySecret(db, name) {
|
|
21
|
-
db.prepare("INSERT INTO secrets (name, ciphertext, iv, auth_tag, salt, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?)").run(name, Buffer.from("c"), Buffer.from("i"), Buffer.from("a"), Buffer.from("s"), Date.now(), Date.now());
|
|
22
|
-
}
|
|
23
|
-
describe("createCredentialMappingStore", () => {
|
|
24
|
-
let db;
|
|
25
|
-
beforeEach(() => {
|
|
26
|
-
db = new Database(":memory:");
|
|
27
|
-
db.pragma("foreign_keys = ON");
|
|
28
|
-
initSecretSchema(db);
|
|
29
|
-
insertDummySecret(db, "OPENAI_API_KEY");
|
|
30
|
-
insertDummySecret(db, "BRAVE_API_KEY");
|
|
31
|
-
});
|
|
32
|
-
describe("set + get roundtrip", () => {
|
|
33
|
-
it("stores and retrieves a bearer_header mapping", () => {
|
|
34
|
-
const store = createCredentialMappingStore(db);
|
|
35
|
-
const mapping = {
|
|
36
|
-
id: "map-001",
|
|
37
|
-
secretName: "OPENAI_API_KEY",
|
|
38
|
-
injectionType: "bearer_header",
|
|
39
|
-
urlPattern: "https://api.openai.com/*",
|
|
40
|
-
};
|
|
41
|
-
const setResult = store.set(mapping);
|
|
42
|
-
expect(setResult.ok).toBe(true);
|
|
43
|
-
const retrieved = unwrap(store.get("map-001"));
|
|
44
|
-
expect(retrieved).toBeDefined();
|
|
45
|
-
expect(retrieved.id).toBe("map-001");
|
|
46
|
-
expect(retrieved.secretName).toBe("OPENAI_API_KEY");
|
|
47
|
-
expect(retrieved.injectionType).toBe("bearer_header");
|
|
48
|
-
expect(retrieved.urlPattern).toBe("https://api.openai.com/*");
|
|
49
|
-
expect(retrieved.injectionKey).toBeUndefined();
|
|
50
|
-
expect(retrieved.toolName).toBeUndefined();
|
|
51
|
-
});
|
|
52
|
-
it("stores and retrieves a custom_header mapping with injectionKey", () => {
|
|
53
|
-
const store = createCredentialMappingStore(db);
|
|
54
|
-
const mapping = {
|
|
55
|
-
id: "map-002",
|
|
56
|
-
secretName: "BRAVE_API_KEY",
|
|
57
|
-
injectionType: "custom_header",
|
|
58
|
-
injectionKey: "X-Subscription-Token",
|
|
59
|
-
urlPattern: "https://api.search.brave.com/*",
|
|
60
|
-
toolName: "brave_search",
|
|
61
|
-
};
|
|
62
|
-
unwrap(store.set(mapping));
|
|
63
|
-
const retrieved = unwrap(store.get("map-002"));
|
|
64
|
-
expect(retrieved).toBeDefined();
|
|
65
|
-
expect(retrieved.injectionType).toBe("custom_header");
|
|
66
|
-
expect(retrieved.injectionKey).toBe("X-Subscription-Token");
|
|
67
|
-
expect(retrieved.toolName).toBe("brave_search");
|
|
68
|
-
});
|
|
69
|
-
it("stores and retrieves a query_param mapping with injectionKey", () => {
|
|
70
|
-
const store = createCredentialMappingStore(db);
|
|
71
|
-
const mapping = {
|
|
72
|
-
id: "map-003",
|
|
73
|
-
secretName: "OPENAI_API_KEY",
|
|
74
|
-
injectionType: "query_param",
|
|
75
|
-
injectionKey: "api_key",
|
|
76
|
-
urlPattern: "https://api.example.com/*",
|
|
77
|
-
};
|
|
78
|
-
unwrap(store.set(mapping));
|
|
79
|
-
const retrieved = unwrap(store.get("map-003"));
|
|
80
|
-
expect(retrieved).toBeDefined();
|
|
81
|
-
expect(retrieved.injectionType).toBe("query_param");
|
|
82
|
-
expect(retrieved.injectionKey).toBe("api_key");
|
|
83
|
-
});
|
|
84
|
-
it("stores and retrieves a basic_auth mapping", () => {
|
|
85
|
-
const store = createCredentialMappingStore(db);
|
|
86
|
-
const mapping = {
|
|
87
|
-
id: "map-004",
|
|
88
|
-
secretName: "OPENAI_API_KEY",
|
|
89
|
-
injectionType: "basic_auth",
|
|
90
|
-
urlPattern: "https://internal.example.com/*",
|
|
91
|
-
};
|
|
92
|
-
unwrap(store.set(mapping));
|
|
93
|
-
const retrieved = unwrap(store.get("map-004"));
|
|
94
|
-
expect(retrieved).toBeDefined();
|
|
95
|
-
expect(retrieved.injectionType).toBe("basic_auth");
|
|
96
|
-
expect(retrieved.injectionKey).toBeUndefined();
|
|
97
|
-
});
|
|
98
|
-
});
|
|
99
|
-
describe("get", () => {
|
|
100
|
-
it("returns undefined for non-existent mapping", () => {
|
|
101
|
-
const store = createCredentialMappingStore(db);
|
|
102
|
-
const retrieved = unwrap(store.get("nonexistent"));
|
|
103
|
-
expect(retrieved).toBeUndefined();
|
|
104
|
-
});
|
|
105
|
-
});
|
|
106
|
-
describe("listAll", () => {
|
|
107
|
-
it("returns all inserted mappings", () => {
|
|
108
|
-
const store = createCredentialMappingStore(db);
|
|
109
|
-
unwrap(store.set({
|
|
110
|
-
id: "map-a",
|
|
111
|
-
secretName: "OPENAI_API_KEY",
|
|
112
|
-
injectionType: "bearer_header",
|
|
113
|
-
urlPattern: "https://api.openai.com/*",
|
|
114
|
-
}));
|
|
115
|
-
unwrap(store.set({
|
|
116
|
-
id: "map-b",
|
|
117
|
-
secretName: "BRAVE_API_KEY",
|
|
118
|
-
injectionType: "custom_header",
|
|
119
|
-
injectionKey: "X-Subscription-Token",
|
|
120
|
-
urlPattern: "https://api.search.brave.com/*",
|
|
121
|
-
toolName: "brave_search",
|
|
122
|
-
}));
|
|
123
|
-
const all = unwrap(store.listAll());
|
|
124
|
-
expect(all).toHaveLength(2);
|
|
125
|
-
const ids = all.map((m) => m.id).sort();
|
|
126
|
-
expect(ids).toEqual(["map-a", "map-b"]);
|
|
127
|
-
});
|
|
128
|
-
it("returns empty array when no mappings exist", () => {
|
|
129
|
-
const store = createCredentialMappingStore(db);
|
|
130
|
-
const all = unwrap(store.listAll());
|
|
131
|
-
expect(all).toEqual([]);
|
|
132
|
-
});
|
|
133
|
-
});
|
|
134
|
-
describe("listBySecret", () => {
|
|
135
|
-
it("filters by secret name", () => {
|
|
136
|
-
const store = createCredentialMappingStore(db);
|
|
137
|
-
unwrap(store.set({
|
|
138
|
-
id: "map-a",
|
|
139
|
-
secretName: "OPENAI_API_KEY",
|
|
140
|
-
injectionType: "bearer_header",
|
|
141
|
-
urlPattern: "https://api.openai.com/*",
|
|
142
|
-
}));
|
|
143
|
-
unwrap(store.set({
|
|
144
|
-
id: "map-b",
|
|
145
|
-
secretName: "BRAVE_API_KEY",
|
|
146
|
-
injectionType: "custom_header",
|
|
147
|
-
injectionKey: "X-Subscription-Token",
|
|
148
|
-
urlPattern: "https://api.search.brave.com/*",
|
|
149
|
-
}));
|
|
150
|
-
unwrap(store.set({
|
|
151
|
-
id: "map-c",
|
|
152
|
-
secretName: "OPENAI_API_KEY",
|
|
153
|
-
injectionType: "query_param",
|
|
154
|
-
injectionKey: "key",
|
|
155
|
-
urlPattern: "https://other.openai.com/*",
|
|
156
|
-
}));
|
|
157
|
-
const openaiMappings = unwrap(store.listBySecret("OPENAI_API_KEY"));
|
|
158
|
-
expect(openaiMappings).toHaveLength(2);
|
|
159
|
-
expect(openaiMappings.every((m) => m.secretName === "OPENAI_API_KEY")).toBe(true);
|
|
160
|
-
const braveMappings = unwrap(store.listBySecret("BRAVE_API_KEY"));
|
|
161
|
-
expect(braveMappings).toHaveLength(1);
|
|
162
|
-
expect(braveMappings[0].id).toBe("map-b");
|
|
163
|
-
});
|
|
164
|
-
it("returns empty array when no mappings match", () => {
|
|
165
|
-
const store = createCredentialMappingStore(db);
|
|
166
|
-
const result = unwrap(store.listBySecret("NONEXISTENT_KEY"));
|
|
167
|
-
expect(result).toEqual([]);
|
|
168
|
-
});
|
|
169
|
-
});
|
|
170
|
-
describe("listByTool", () => {
|
|
171
|
-
it("filters by tool name (excludes null tool_name)", () => {
|
|
172
|
-
const store = createCredentialMappingStore(db);
|
|
173
|
-
unwrap(store.set({
|
|
174
|
-
id: "map-a",
|
|
175
|
-
secretName: "OPENAI_API_KEY",
|
|
176
|
-
injectionType: "bearer_header",
|
|
177
|
-
urlPattern: "https://api.openai.com/*",
|
|
178
|
-
// no toolName -- should NOT appear in listByTool results
|
|
179
|
-
}));
|
|
180
|
-
unwrap(store.set({
|
|
181
|
-
id: "map-b",
|
|
182
|
-
secretName: "BRAVE_API_KEY",
|
|
183
|
-
injectionType: "custom_header",
|
|
184
|
-
injectionKey: "X-Subscription-Token",
|
|
185
|
-
urlPattern: "https://api.search.brave.com/*",
|
|
186
|
-
toolName: "brave_search",
|
|
187
|
-
}));
|
|
188
|
-
unwrap(store.set({
|
|
189
|
-
id: "map-c",
|
|
190
|
-
secretName: "OPENAI_API_KEY",
|
|
191
|
-
injectionType: "bearer_header",
|
|
192
|
-
urlPattern: "https://api.openai.com/v1/*",
|
|
193
|
-
toolName: "brave_search",
|
|
194
|
-
}));
|
|
195
|
-
const braveMappings = unwrap(store.listByTool("brave_search"));
|
|
196
|
-
expect(braveMappings).toHaveLength(2);
|
|
197
|
-
expect(braveMappings.every((m) => m.toolName === "brave_search")).toBe(true);
|
|
198
|
-
// Mapping without toolName should not appear
|
|
199
|
-
const ids = braveMappings.map((m) => m.id);
|
|
200
|
-
expect(ids).not.toContain("map-a");
|
|
201
|
-
});
|
|
202
|
-
it("returns empty array when no mappings match the tool", () => {
|
|
203
|
-
const store = createCredentialMappingStore(db);
|
|
204
|
-
const result = unwrap(store.listByTool("nonexistent_tool"));
|
|
205
|
-
expect(result).toEqual([]);
|
|
206
|
-
});
|
|
207
|
-
});
|
|
208
|
-
describe("delete", () => {
|
|
209
|
-
it("returns true when mapping exists and is deleted", () => {
|
|
210
|
-
const store = createCredentialMappingStore(db);
|
|
211
|
-
unwrap(store.set({
|
|
212
|
-
id: "map-to-delete",
|
|
213
|
-
secretName: "OPENAI_API_KEY",
|
|
214
|
-
injectionType: "bearer_header",
|
|
215
|
-
urlPattern: "https://api.openai.com/*",
|
|
216
|
-
}));
|
|
217
|
-
const deleted = unwrap(store.delete("map-to-delete"));
|
|
218
|
-
expect(deleted).toBe(true);
|
|
219
|
-
// Confirm deleted
|
|
220
|
-
const retrieved = unwrap(store.get("map-to-delete"));
|
|
221
|
-
expect(retrieved).toBeUndefined();
|
|
222
|
-
});
|
|
223
|
-
it("returns false when mapping does not exist", () => {
|
|
224
|
-
const store = createCredentialMappingStore(db);
|
|
225
|
-
const deleted = unwrap(store.delete("nonexistent"));
|
|
226
|
-
expect(deleted).toBe(false);
|
|
227
|
-
});
|
|
228
|
-
});
|
|
229
|
-
// ── DATA-08: URL pattern regex validation ────────────────────────
|
|
230
|
-
describe("urlPattern regex validation", () => {
|
|
231
|
-
it("accepts valid regex pattern", () => {
|
|
232
|
-
const store = createCredentialMappingStore(db);
|
|
233
|
-
const result = store.set({
|
|
234
|
-
id: "map-regex-valid",
|
|
235
|
-
secretName: "OPENAI_API_KEY",
|
|
236
|
-
injectionType: "bearer_header",
|
|
237
|
-
urlPattern: "https://api\\.example\\.com/.*",
|
|
238
|
-
});
|
|
239
|
-
expect(result.ok).toBe(true);
|
|
240
|
-
});
|
|
241
|
-
it("accepts broad wildcard pattern", () => {
|
|
242
|
-
const store = createCredentialMappingStore(db);
|
|
243
|
-
const result = store.set({
|
|
244
|
-
id: "map-regex-broad",
|
|
245
|
-
secretName: "OPENAI_API_KEY",
|
|
246
|
-
injectionType: "bearer_header",
|
|
247
|
-
urlPattern: ".*",
|
|
248
|
-
});
|
|
249
|
-
expect(result.ok).toBe(true);
|
|
250
|
-
});
|
|
251
|
-
it("returns err for unclosed parenthesis", () => {
|
|
252
|
-
const store = createCredentialMappingStore(db);
|
|
253
|
-
const result = store.set({
|
|
254
|
-
id: "map-regex-bad-paren",
|
|
255
|
-
secretName: "OPENAI_API_KEY",
|
|
256
|
-
injectionType: "bearer_header",
|
|
257
|
-
urlPattern: "(unclosed",
|
|
258
|
-
});
|
|
259
|
-
expect(result.ok).toBe(false);
|
|
260
|
-
if (!result.ok) {
|
|
261
|
-
expect(result.error.message).toContain("Invalid urlPattern");
|
|
262
|
-
expect(result.error.message).toContain("(unclosed");
|
|
263
|
-
}
|
|
264
|
-
});
|
|
265
|
-
it("returns err for unclosed bracket", () => {
|
|
266
|
-
const store = createCredentialMappingStore(db);
|
|
267
|
-
const result = store.set({
|
|
268
|
-
id: "map-regex-bad-bracket",
|
|
269
|
-
secretName: "OPENAI_API_KEY",
|
|
270
|
-
injectionType: "bearer_header",
|
|
271
|
-
urlPattern: "[invalid",
|
|
272
|
-
});
|
|
273
|
-
expect(result.ok).toBe(false);
|
|
274
|
-
if (!result.ok) {
|
|
275
|
-
expect(result.error.message).toContain("Invalid urlPattern");
|
|
276
|
-
}
|
|
277
|
-
});
|
|
278
|
-
});
|
|
279
|
-
describe("upsert behavior", () => {
|
|
280
|
-
it("updates existing mapping when same id is set twice", () => {
|
|
281
|
-
const store = createCredentialMappingStore(db);
|
|
282
|
-
unwrap(store.set({
|
|
283
|
-
id: "map-upsert",
|
|
284
|
-
secretName: "OPENAI_API_KEY",
|
|
285
|
-
injectionType: "bearer_header",
|
|
286
|
-
urlPattern: "https://api.openai.com/v1/*",
|
|
287
|
-
}));
|
|
288
|
-
// Update with different values
|
|
289
|
-
unwrap(store.set({
|
|
290
|
-
id: "map-upsert",
|
|
291
|
-
secretName: "BRAVE_API_KEY",
|
|
292
|
-
injectionType: "custom_header",
|
|
293
|
-
injectionKey: "X-Api-Key",
|
|
294
|
-
urlPattern: "https://api.search.brave.com/*",
|
|
295
|
-
toolName: "brave_search",
|
|
296
|
-
}));
|
|
297
|
-
const retrieved = unwrap(store.get("map-upsert"));
|
|
298
|
-
expect(retrieved).toBeDefined();
|
|
299
|
-
expect(retrieved.secretName).toBe("BRAVE_API_KEY");
|
|
300
|
-
expect(retrieved.injectionType).toBe("custom_header");
|
|
301
|
-
expect(retrieved.injectionKey).toBe("X-Api-Key");
|
|
302
|
-
expect(retrieved.urlPattern).toBe("https://api.search.brave.com/*");
|
|
303
|
-
expect(retrieved.toolName).toBe("brave_search");
|
|
304
|
-
// Should still be only one mapping
|
|
305
|
-
const all = unwrap(store.listAll());
|
|
306
|
-
expect(all).toHaveLength(1);
|
|
307
|
-
});
|
|
308
|
-
});
|
|
309
|
-
describe("ON DELETE CASCADE", () => {
|
|
310
|
-
it("deletes credential mappings when referenced secret is deleted", () => {
|
|
311
|
-
const store = createCredentialMappingStore(db);
|
|
312
|
-
unwrap(store.set({
|
|
313
|
-
id: "map-cascade-1",
|
|
314
|
-
secretName: "OPENAI_API_KEY",
|
|
315
|
-
injectionType: "bearer_header",
|
|
316
|
-
urlPattern: "https://api.openai.com/*",
|
|
317
|
-
}));
|
|
318
|
-
unwrap(store.set({
|
|
319
|
-
id: "map-cascade-2",
|
|
320
|
-
secretName: "OPENAI_API_KEY",
|
|
321
|
-
injectionType: "query_param",
|
|
322
|
-
injectionKey: "key",
|
|
323
|
-
urlPattern: "https://other.openai.com/*",
|
|
324
|
-
}));
|
|
325
|
-
// Verify mappings exist
|
|
326
|
-
const before = unwrap(store.listBySecret("OPENAI_API_KEY"));
|
|
327
|
-
expect(before).toHaveLength(2);
|
|
328
|
-
// Delete the referenced secret from the secrets table
|
|
329
|
-
db.prepare("DELETE FROM secrets WHERE name = ?").run("OPENAI_API_KEY");
|
|
330
|
-
// Mappings should be cascade-deleted
|
|
331
|
-
const after = unwrap(store.listBySecret("OPENAI_API_KEY"));
|
|
332
|
-
expect(after).toHaveLength(0);
|
|
333
|
-
// Verify via get too
|
|
334
|
-
const mapping1 = unwrap(store.get("map-cascade-1"));
|
|
335
|
-
expect(mapping1).toBeUndefined();
|
|
336
|
-
const mapping2 = unwrap(store.get("map-cascade-2"));
|
|
337
|
-
expect(mapping2).toBeUndefined();
|
|
338
|
-
});
|
|
339
|
-
});
|
|
340
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
2
|
-
import Database from "better-sqlite3";
|
|
3
|
-
import { createSqliteDeliveryMirror } from "./delivery-mirror-adapter.js";
|
|
4
|
-
import { createNoOpDeliveryMirror } from "@comis/core";
|
|
5
|
-
import { initSchema } from "./schema.js";
|
|
6
|
-
describe("createSqliteDeliveryMirror", () => {
|
|
7
|
-
let db;
|
|
8
|
-
let mirror;
|
|
9
|
-
beforeEach(() => {
|
|
10
|
-
db = new Database(":memory:");
|
|
11
|
-
initSchema(db, 128);
|
|
12
|
-
mirror = createSqliteDeliveryMirror(db);
|
|
13
|
-
});
|
|
14
|
-
afterEach(() => {
|
|
15
|
-
db.close();
|
|
16
|
-
});
|
|
17
|
-
function makeInput(overrides = {}) {
|
|
18
|
-
return {
|
|
19
|
-
sessionKey: "telegram:dm:user123",
|
|
20
|
-
text: "Hello from agent",
|
|
21
|
-
mediaUrls: [],
|
|
22
|
-
channelType: "telegram",
|
|
23
|
-
channelId: "chat-001",
|
|
24
|
-
origin: "agent",
|
|
25
|
-
idempotencyKey: `key-${Date.now()}-${Math.random()}`,
|
|
26
|
-
...overrides,
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
it("record() inserts a mirror entry and returns an id", async () => {
|
|
30
|
-
const result = await mirror.record(makeInput());
|
|
31
|
-
expect(result.ok).toBe(true);
|
|
32
|
-
if (!result.ok)
|
|
33
|
-
return;
|
|
34
|
-
expect(typeof result.value).toBe("string");
|
|
35
|
-
expect(result.value.length).toBeGreaterThan(0);
|
|
36
|
-
const pending = await mirror.pending("telegram:dm:user123");
|
|
37
|
-
expect(pending.ok).toBe(true);
|
|
38
|
-
if (!pending.ok)
|
|
39
|
-
return;
|
|
40
|
-
expect(pending.value).toHaveLength(1);
|
|
41
|
-
expect(pending.value[0].text).toBe("Hello from agent");
|
|
42
|
-
});
|
|
43
|
-
it("record() with duplicate idempotency key is silently ignored", async () => {
|
|
44
|
-
const input = makeInput({ idempotencyKey: "dup-key-001" });
|
|
45
|
-
const r1 = await mirror.record(input);
|
|
46
|
-
expect(r1.ok).toBe(true);
|
|
47
|
-
const r2 = await mirror.record({ ...input, text: "Different text" });
|
|
48
|
-
expect(r2.ok).toBe(true);
|
|
49
|
-
const pending = await mirror.pending("telegram:dm:user123");
|
|
50
|
-
expect(pending.ok).toBe(true);
|
|
51
|
-
if (!pending.ok)
|
|
52
|
-
return;
|
|
53
|
-
expect(pending.value).toHaveLength(1);
|
|
54
|
-
expect(pending.value[0].text).toBe("Hello from agent");
|
|
55
|
-
});
|
|
56
|
-
it("pending() returns entries ordered by created_at ASC", async () => {
|
|
57
|
-
// Insert directly with controlled timestamps to ensure ordering
|
|
58
|
-
db.exec(`
|
|
59
|
-
INSERT INTO delivery_mirror (id, session_key, text, media_urls, channel_type, channel_id, origin, idempotency_key, status, created_at)
|
|
60
|
-
VALUES ('id-3', 'sess-a', 'Third', '[]', 'telegram', 'ch1', 'agent', 'k3', 'pending', 3000);
|
|
61
|
-
`);
|
|
62
|
-
db.exec(`
|
|
63
|
-
INSERT INTO delivery_mirror (id, session_key, text, media_urls, channel_type, channel_id, origin, idempotency_key, status, created_at)
|
|
64
|
-
VALUES ('id-1', 'sess-a', 'First', '[]', 'telegram', 'ch1', 'agent', 'k1', 'pending', 1000);
|
|
65
|
-
`);
|
|
66
|
-
db.exec(`
|
|
67
|
-
INSERT INTO delivery_mirror (id, session_key, text, media_urls, channel_type, channel_id, origin, idempotency_key, status, created_at)
|
|
68
|
-
VALUES ('id-2', 'sess-a', 'Second', '[]', 'telegram', 'ch1', 'agent', 'k2', 'pending', 2000);
|
|
69
|
-
`);
|
|
70
|
-
const pending = await mirror.pending("sess-a");
|
|
71
|
-
expect(pending.ok).toBe(true);
|
|
72
|
-
if (!pending.ok)
|
|
73
|
-
return;
|
|
74
|
-
expect(pending.value).toHaveLength(3);
|
|
75
|
-
expect(pending.value[0].text).toBe("First");
|
|
76
|
-
expect(pending.value[1].text).toBe("Second");
|
|
77
|
-
expect(pending.value[2].text).toBe("Third");
|
|
78
|
-
});
|
|
79
|
-
it("pending() returns only entries for the given sessionKey", async () => {
|
|
80
|
-
await mirror.record(makeInput({ sessionKey: "sess-a", idempotencyKey: "ka" }));
|
|
81
|
-
await mirror.record(makeInput({ sessionKey: "sess-b", idempotencyKey: "kb" }));
|
|
82
|
-
const pendingA = await mirror.pending("sess-a");
|
|
83
|
-
expect(pendingA.ok).toBe(true);
|
|
84
|
-
if (!pendingA.ok)
|
|
85
|
-
return;
|
|
86
|
-
expect(pendingA.value).toHaveLength(1);
|
|
87
|
-
const pendingB = await mirror.pending("sess-b");
|
|
88
|
-
expect(pendingB.ok).toBe(true);
|
|
89
|
-
if (!pendingB.ok)
|
|
90
|
-
return;
|
|
91
|
-
expect(pendingB.value).toHaveLength(1);
|
|
92
|
-
});
|
|
93
|
-
it("acknowledge() marks entries as acknowledged", async () => {
|
|
94
|
-
const r1 = await mirror.record(makeInput({ idempotencyKey: "ack-1" }));
|
|
95
|
-
const r2 = await mirror.record(makeInput({ idempotencyKey: "ack-2" }));
|
|
96
|
-
expect(r1.ok).toBe(true);
|
|
97
|
-
expect(r2.ok).toBe(true);
|
|
98
|
-
if (!r1.ok || !r2.ok)
|
|
99
|
-
return;
|
|
100
|
-
const ackResult = await mirror.acknowledge([r1.value, r2.value]);
|
|
101
|
-
expect(ackResult.ok).toBe(true);
|
|
102
|
-
const pending = await mirror.pending("telegram:dm:user123");
|
|
103
|
-
expect(pending.ok).toBe(true);
|
|
104
|
-
if (!pending.ok)
|
|
105
|
-
return;
|
|
106
|
-
expect(pending.value).toHaveLength(0);
|
|
107
|
-
});
|
|
108
|
-
it("pruneOld() removes entries older than maxAgeMs", async () => {
|
|
109
|
-
const now = Date.now();
|
|
110
|
-
// Insert old entry via direct SQL
|
|
111
|
-
db.exec(`
|
|
112
|
-
INSERT INTO delivery_mirror (id, session_key, text, media_urls, channel_type, channel_id, origin, idempotency_key, status, created_at)
|
|
113
|
-
VALUES ('old-1', 'sess-a', 'Old', '[]', 'telegram', 'ch1', 'agent', 'prune-old', 'pending', ${now - 100_000});
|
|
114
|
-
`);
|
|
115
|
-
// Insert recent entry via adapter
|
|
116
|
-
await mirror.record(makeInput({ sessionKey: "sess-a", idempotencyKey: "prune-new" }));
|
|
117
|
-
const pruned = await mirror.pruneOld(50_000);
|
|
118
|
-
expect(pruned.ok).toBe(true);
|
|
119
|
-
if (!pruned.ok)
|
|
120
|
-
return;
|
|
121
|
-
expect(pruned.value).toBe(1);
|
|
122
|
-
const pending = await mirror.pending("sess-a");
|
|
123
|
-
expect(pending.ok).toBe(true);
|
|
124
|
-
if (!pending.ok)
|
|
125
|
-
return;
|
|
126
|
-
expect(pending.value).toHaveLength(1);
|
|
127
|
-
expect(pending.value[0].idempotencyKey).toBe("prune-new");
|
|
128
|
-
});
|
|
129
|
-
it("record() stores mediaUrls as JSON", async () => {
|
|
130
|
-
const urls = ["https://example.com/a.png", "https://example.com/b.jpg"];
|
|
131
|
-
await mirror.record(makeInput({ mediaUrls: urls, idempotencyKey: "media-1" }));
|
|
132
|
-
const pending = await mirror.pending("telegram:dm:user123");
|
|
133
|
-
expect(pending.ok).toBe(true);
|
|
134
|
-
if (!pending.ok)
|
|
135
|
-
return;
|
|
136
|
-
expect(pending.value[0].mediaUrls).toEqual(urls);
|
|
137
|
-
});
|
|
138
|
-
});
|
|
139
|
-
describe("createNoOpDeliveryMirror", () => {
|
|
140
|
-
it("returns success for all operations", async () => {
|
|
141
|
-
const noop = createNoOpDeliveryMirror();
|
|
142
|
-
const recordResult = await noop.record({
|
|
143
|
-
sessionKey: "s",
|
|
144
|
-
text: "t",
|
|
145
|
-
mediaUrls: [],
|
|
146
|
-
channelType: "echo",
|
|
147
|
-
channelId: "c",
|
|
148
|
-
origin: "agent",
|
|
149
|
-
idempotencyKey: "k",
|
|
150
|
-
});
|
|
151
|
-
expect(recordResult.ok).toBe(true);
|
|
152
|
-
if (recordResult.ok)
|
|
153
|
-
expect(typeof recordResult.value).toBe("string");
|
|
154
|
-
const pendingResult = await noop.pending("s");
|
|
155
|
-
expect(pendingResult.ok).toBe(true);
|
|
156
|
-
if (pendingResult.ok)
|
|
157
|
-
expect(pendingResult.value).toEqual([]);
|
|
158
|
-
const ackResult = await noop.acknowledge(["id1"]);
|
|
159
|
-
expect(ackResult.ok).toBe(true);
|
|
160
|
-
const pruneResult = await noop.pruneOld(1000);
|
|
161
|
-
expect(pruneResult.ok).toBe(true);
|
|
162
|
-
if (pruneResult.ok)
|
|
163
|
-
expect(pruneResult.value).toBe(0);
|
|
164
|
-
});
|
|
165
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|