@vellumai/assistant 0.4.53 → 0.4.54
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/bun.lock +62 -349
- package/docs/architecture/integrations.md +1 -1
- package/docs/architecture/keychain-broker.md +94 -29
- package/docs/architecture/security.md +2 -2
- package/knip.json +7 -29
- package/package.json +2 -9
- package/src/__tests__/agent-loop.test.ts +1 -1
- package/src/__tests__/app-git-history.test.ts +0 -2
- package/src/__tests__/app-git-service.test.ts +1 -6
- package/src/__tests__/approval-cascade.test.ts +0 -1
- package/src/__tests__/avatar-e2e.test.ts +0 -1
- package/src/__tests__/browser-fill-credential.test.ts +1 -6
- package/src/__tests__/call-domain.test.ts +0 -1
- package/src/__tests__/call-routes-http.test.ts +0 -1
- package/src/__tests__/channel-guardian.test.ts +4 -4
- package/src/__tests__/channel-readiness-routes.test.ts +0 -1
- package/src/__tests__/channel-readiness-service.test.ts +0 -1
- package/src/__tests__/checker.test.ts +13 -11
- package/src/__tests__/claude-code-skill-regression.test.ts +0 -1
- package/src/__tests__/claude-code-tool-profiles.test.ts +1 -2
- package/src/__tests__/config-loader-backfill.test.ts +0 -3
- package/src/__tests__/config-schema.test.ts +3 -9
- package/src/__tests__/config-watcher.test.ts +11 -3
- package/src/__tests__/credential-broker-browser-fill.test.ts +27 -24
- package/src/__tests__/credential-broker-server-use.test.ts +60 -24
- package/src/__tests__/credential-security-e2e.test.ts +1 -6
- package/src/__tests__/credential-security-invariants.test.ts +13 -8
- package/src/__tests__/credential-vault-unit.test.ts +28 -12
- package/src/__tests__/credential-vault.test.ts +40 -28
- package/src/__tests__/credentials-cli.test.ts +1 -21
- package/src/__tests__/email-invite-adapter.test.ts +0 -1
- package/src/__tests__/fixtures/credential-security-fixtures.ts +3 -3
- package/src/__tests__/fixtures/media-reuse-fixtures.ts +3 -79
- package/src/__tests__/gateway-only-enforcement.test.ts +1 -21
- package/src/__tests__/guardian-action-conversation-turn.test.ts +8 -8
- package/src/__tests__/guardian-action-late-reply.test.ts +13 -14
- package/src/__tests__/guardian-action-store.test.ts +0 -57
- package/src/__tests__/guardian-outbound-http.test.ts +1 -1
- package/src/__tests__/guardian-verification-voice-binding.test.ts +1 -3
- package/src/__tests__/hooks-blocking.test.ts +1 -1
- package/src/__tests__/hooks-config.test.ts +5 -29
- package/src/__tests__/hooks-discovery.test.ts +1 -1
- package/src/__tests__/hooks-integration.test.ts +1 -1
- package/src/__tests__/hooks-manager.test.ts +1 -1
- package/src/__tests__/hooks-runner.test.ts +1 -23
- package/src/__tests__/hooks-settings.test.ts +1 -1
- package/src/__tests__/hooks-templates.test.ts +1 -1
- package/src/__tests__/integration-status.test.ts +0 -1
- package/src/__tests__/invite-routes-http.test.ts +0 -3
- package/src/__tests__/llm-usage-store.test.ts +50 -0
- package/src/__tests__/managed-proxy-context.test.ts +41 -41
- package/src/__tests__/media-generate-image.test.ts +2 -2
- package/src/__tests__/media-reuse-story.e2e.test.ts +1 -6
- package/src/__tests__/memory-regressions.experimental.test.ts +4 -4
- package/src/__tests__/memory-regressions.test.ts +27 -27
- package/src/__tests__/memory-retrieval.benchmark.test.ts +1 -1
- package/src/__tests__/memory-upsert-concurrency.test.ts +4 -4
- package/src/__tests__/notification-decision-fallback.test.ts +1 -1
- package/src/__tests__/oauth-cli.test.ts +1 -4
- package/src/__tests__/oauth-store.test.ts +1 -3
- package/src/__tests__/openai-provider.test.ts +7 -7
- package/src/__tests__/platform.test.ts +14 -4
- package/src/__tests__/pricing.test.ts +0 -223
- package/src/__tests__/provider-commit-message-generator.test.ts +1 -4
- package/src/__tests__/provider-fail-open-selection.test.ts +58 -54
- package/src/__tests__/provider-managed-proxy-integration.test.ts +63 -63
- package/src/__tests__/provider-registry-ollama.test.ts +3 -3
- package/src/__tests__/public-ingress-urls.test.ts +1 -1
- package/src/__tests__/registry.test.ts +3 -103
- package/src/__tests__/script-proxy-injection-runtime.test.ts +2 -7
- package/src/__tests__/secret-onetime-send.test.ts +1 -6
- package/src/__tests__/secret-routes-managed-proxy.test.ts +6 -13
- package/src/__tests__/secure-keys.test.ts +241 -229
- package/src/__tests__/session-abort-tool-results.test.ts +0 -1
- package/src/__tests__/session-confirmation-signals.test.ts +0 -1
- package/src/__tests__/session-messaging-secret-redirect.test.ts +1 -7
- package/src/__tests__/session-pre-run-repair.test.ts +0 -1
- package/src/__tests__/session-provider-retry-repair.test.ts +0 -1
- package/src/__tests__/session-queue.test.ts +2 -4
- package/src/__tests__/session-slash-known.test.ts +0 -1
- package/src/__tests__/session-slash-queue.test.ts +0 -1
- package/src/__tests__/session-slash-unknown.test.ts +0 -1
- package/src/__tests__/session-workspace-injection.test.ts +0 -1
- package/src/__tests__/session-workspace-tool-tracking.test.ts +0 -1
- package/src/__tests__/skill-projection-feature-flag.test.ts +0 -1
- package/src/__tests__/slack-channel-config.test.ts +1 -7
- package/src/__tests__/swarm-recursion.test.ts +0 -1
- package/src/__tests__/swarm-session-integration.test.ts +0 -1
- package/src/__tests__/swarm-tool.test.ts +0 -1
- package/src/__tests__/task-compiler.test.ts +1 -1
- package/src/__tests__/test-support/browser-skill-harness.ts +0 -18
- package/src/__tests__/test-support/computer-use-skill-harness.ts +0 -23
- package/src/__tests__/tool-executor.test.ts +1 -1
- package/src/__tests__/trust-store.test.ts +3 -82
- package/src/__tests__/twilio-config.test.ts +0 -1
- package/src/__tests__/twilio-provider.test.ts +0 -5
- package/src/__tests__/twilio-routes.test.ts +0 -1
- package/src/__tests__/usage-cache-backfill-migration.test.ts +10 -10
- package/src/calls/guardian-question-copy.ts +1 -1
- package/src/cli/commands/doctor.ts +10 -34
- package/src/cli/commands/memory.ts +3 -5
- package/src/cli/commands/sessions.ts +1 -1
- package/src/cli/commands/usage.ts +359 -0
- package/src/cli/http-client.ts +22 -12
- package/src/cli/program.ts +2 -0
- package/src/cli/reference.ts +1 -0
- package/src/cli.ts +251 -181
- package/src/config/assistant-feature-flags.ts +0 -7
- package/src/config/bundled-skills/chatgpt-import/tools/chatgpt-import.ts +1 -1
- package/src/config/bundled-skills/claude-code/SKILL.md +1 -1
- package/src/config/bundled-skills/claude-code/TOOLS.json +1 -1
- package/src/config/bundled-skills/gmail/SKILL.md +0 -1
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +2 -2
- package/src/config/bundled-skills/media-processing/services/reduce.ts +1 -1
- package/src/config/bundled-skills/messaging/SKILL.md +0 -1
- package/src/config/bundled-skills/sequences/SKILL.md +0 -1
- package/src/config/env.ts +13 -0
- package/src/config/feature-flag-registry.json +9 -41
- package/src/config/schemas/security.ts +1 -2
- package/src/config/skills.ts +1 -1
- package/src/contacts/contact-store.ts +0 -50
- package/src/daemon/approved-devices-store.ts +0 -44
- package/src/daemon/classifier.ts +1 -1
- package/src/daemon/config-watcher.ts +12 -6
- package/src/daemon/handlers/config-model.ts +1 -1
- package/src/daemon/handlers/sessions.ts +4 -116
- package/src/daemon/handlers/skills.ts +1 -1
- package/src/daemon/lifecycle.ts +13 -15
- package/src/daemon/providers-setup.ts +1 -1
- package/src/daemon/server.ts +19 -3
- package/src/daemon/session-slash.ts +2 -2
- package/src/daemon/shutdown-handlers.ts +15 -0
- package/src/daemon/watch-handler.ts +2 -2
- package/src/email/guardrails.ts +1 -1
- package/src/email/service.ts +0 -5
- package/src/hooks/templates.ts +1 -1
- package/src/media/app-icon-generator.ts +2 -2
- package/src/media/avatar-router.ts +2 -2
- package/src/media/gemini-image-service.ts +5 -5
- package/src/memory/admin.ts +2 -2
- package/src/memory/app-git-service.ts +0 -7
- package/src/memory/conversation-crud.ts +1 -1
- package/src/memory/conversation-title-service.ts +2 -2
- package/src/memory/embedding-backend.ts +30 -26
- package/src/memory/external-conversation-store.ts +0 -30
- package/src/memory/guardian-action-store.ts +0 -31
- package/src/memory/guardian-approvals.ts +1 -56
- package/src/memory/indexer.ts +4 -3
- package/src/memory/items-extractor.ts +1 -1
- package/src/memory/job-handlers/backfill.ts +5 -2
- package/src/memory/job-handlers/index-maintenance.ts +2 -2
- package/src/memory/job-handlers/media-processing.ts +2 -2
- package/src/memory/job-handlers/summarization.ts +1 -1
- package/src/memory/job-utils.ts +1 -2
- package/src/memory/jobs-worker.ts +2 -2
- package/src/memory/llm-usage-store.ts +57 -11
- package/src/memory/media-store.ts +4 -535
- package/src/memory/migrations/032-guardian-delivery-conversation-index.ts +2 -2
- package/src/memory/migrations/110-channel-guardian.ts +0 -1
- package/src/memory/published-pages-store.ts +0 -83
- package/src/memory/qdrant-circuit-breaker.ts +0 -8
- package/src/memory/retriever.ts +1 -1
- package/src/memory/search/semantic.ts +1 -8
- package/src/memory/shared-app-links-store.ts +0 -15
- package/src/messaging/registry.ts +0 -5
- package/src/messaging/style-analyzer.ts +1 -1
- package/src/notifications/copy-composer.ts +5 -13
- package/src/notifications/decision-engine.ts +2 -2
- package/src/notifications/deliveries-store.ts +0 -39
- package/src/notifications/guardian-question-mode.ts +6 -10
- package/src/notifications/preference-extractor.ts +1 -1
- package/src/oauth/byo-connection.test.ts +29 -20
- package/src/oauth/provider-behaviors.ts +1 -1
- package/src/permissions/checker.ts +1 -1
- package/src/permissions/shell-identity.ts +0 -5
- package/src/permissions/trust-store.ts +0 -37
- package/src/prompts/system-prompt.ts +3 -3
- package/src/providers/managed-proxy/constants.ts +8 -10
- package/src/providers/managed-proxy/context.ts +14 -9
- package/src/providers/provider-send-message.ts +4 -52
- package/src/providers/registry.ts +16 -50
- package/src/runtime/actor-token-store.ts +0 -23
- package/src/runtime/http-router.ts +5 -1
- package/src/runtime/http-server.ts +101 -4
- package/src/runtime/invite-instruction-generator.ts +25 -51
- package/src/runtime/invite-service.ts +0 -20
- package/src/runtime/routes/attachment-routes.ts +1 -1
- package/src/runtime/routes/brain-graph-routes.ts +1 -1
- package/src/runtime/routes/call-routes.ts +1 -1
- package/src/runtime/routes/conversation-routes.ts +32 -11
- package/src/runtime/routes/debug-routes.ts +1 -1
- package/src/runtime/routes/diagnostics-routes.ts +2 -2
- package/src/runtime/routes/documents-routes.ts +3 -3
- package/src/runtime/routes/global-search-routes.ts +1 -1
- package/src/runtime/routes/guardian-bootstrap-routes.ts +0 -20
- package/src/runtime/routes/guardian-refresh-routes.ts +0 -20
- package/src/runtime/routes/secret-routes.ts +4 -4
- package/src/runtime/routes/trust-rules-routes.ts +1 -1
- package/src/security/credential-backend.ts +148 -0
- package/src/security/oauth2.ts +1 -1
- package/src/security/secret-allowlist.ts +1 -1
- package/src/security/secure-keys.ts +98 -160
- package/src/security/token-manager.ts +0 -7
- package/src/sequence/guardrails.ts +0 -4
- package/src/sequence/store.ts +1 -20
- package/src/sequence/types.ts +1 -36
- package/src/signals/cancel.ts +69 -0
- package/src/signals/conversation-undo.ts +127 -0
- package/src/signals/trust-rule.ts +174 -0
- package/src/skills/clawhub.ts +5 -5
- package/src/skills/managed-store.ts +4 -4
- package/src/telemetry/usage-telemetry-reporter.test.ts +366 -0
- package/src/telemetry/usage-telemetry-reporter.ts +181 -0
- package/src/tools/claude-code/claude-code.ts +2 -2
- package/src/tools/credentials/vault.ts +8 -4
- package/src/tools/memory/handlers.test.ts +24 -26
- package/src/tools/memory/handlers.ts +1 -13
- package/src/tools/registry.ts +5 -100
- package/src/tools/terminal/parser.ts +34 -4
- package/src/tools/tool-manifest.ts +0 -10
- package/src/usage/actors.ts +0 -12
- package/src/util/canonicalize-identity.ts +0 -9
- package/src/util/errors.ts +0 -3
- package/src/util/platform.ts +24 -7
- package/src/util/pricing.ts +0 -38
- package/src/watcher/constants.ts +0 -7
- package/src/watcher/providers/linear.ts +1 -1
- package/src/work-items/work-item-store.ts +4 -4
- package/src/workspace/commit-message-provider.ts +1 -1
- package/src/workspace/git-service.ts +44 -1
- package/src/workspace/provider-commit-message-generator.ts +1 -1
- package/src/__tests__/fixtures/proxy-fixtures.ts +0 -147
- package/src/browser-extension-relay/client.ts +0 -155
- package/src/contacts/index.ts +0 -18
- package/src/daemon/tls-certs.ts +0 -270
- package/src/errors.ts +0 -41
- package/src/events/index.ts +0 -18
- package/src/followups/index.ts +0 -10
- package/src/playbooks/index.ts +0 -10
- package/src/runtime/auth/index.ts +0 -44
- package/src/tasks/candidate-store.ts +0 -95
- package/src/tools/browser/api-map.ts +0 -313
- package/src/tools/browser/auto-navigate.ts +0 -469
- package/src/tools/browser/headless-browser.ts +0 -590
- package/src/tools/browser/recording-store.ts +0 -75
- package/src/tools/computer-use/registry.ts +0 -21
- package/src/tools/tasks/index.ts +0 -27
package/src/daemon/tls-certs.ts
DELETED
|
@@ -1,270 +0,0 @@
|
|
|
1
|
-
import { createPrivateKey, X509Certificate } from "node:crypto";
|
|
2
|
-
import { chmod, mkdir, readFile, stat, writeFile } from "node:fs/promises";
|
|
3
|
-
import { join } from "node:path";
|
|
4
|
-
|
|
5
|
-
import { getLogger } from "../util/logger.js";
|
|
6
|
-
import { getRootDir } from "../util/platform.js";
|
|
7
|
-
|
|
8
|
-
const log = getLogger("tls-certs");
|
|
9
|
-
|
|
10
|
-
const TLS_DIR = "tls";
|
|
11
|
-
const CERT_FILENAME = "cert.pem";
|
|
12
|
-
const KEY_FILENAME = "key.pem";
|
|
13
|
-
const FINGERPRINT_FILENAME = "fingerprint";
|
|
14
|
-
|
|
15
|
-
/** Returns the TLS directory path (~/.vellum/tls/). */
|
|
16
|
-
export function getTlsDir(): string {
|
|
17
|
-
return join(getRootDir(), TLS_DIR);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/** Returns the path to the TLS certificate. */
|
|
21
|
-
export function getTlsCertPath(): string {
|
|
22
|
-
return join(getTlsDir(), CERT_FILENAME);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/** Returns the path to the TLS private key. */
|
|
26
|
-
export function getTlsKeyPath(): string {
|
|
27
|
-
return join(getTlsDir(), KEY_FILENAME);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/** Returns the path to the certificate fingerprint file. */
|
|
31
|
-
export function getTlsFingerprintPath(): string {
|
|
32
|
-
return join(getTlsDir(), FINGERPRINT_FILENAME);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Compute the SHA-256 fingerprint of a DER-encoded certificate.
|
|
37
|
-
* Returns hex lowercase, no colons.
|
|
38
|
-
*/
|
|
39
|
-
function computeFingerprint(cert: X509Certificate): string {
|
|
40
|
-
// X509Certificate.fingerprint256 returns colon-separated uppercase hex.
|
|
41
|
-
// Normalize to lowercase without colons for compact storage and comparison.
|
|
42
|
-
return cert.fingerprint256.replace(/:/g, "").toLowerCase();
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
type CertStatus = "valid" | "approaching_expiry" | "invalid";
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Check whether an existing cert+key pair is valid:
|
|
49
|
-
* - All three files exist (cert, key, fingerprint)
|
|
50
|
-
* - Cert is parseable as X509
|
|
51
|
-
* - Cert is not expired
|
|
52
|
-
* - Fingerprint file exists and matches the cert
|
|
53
|
-
* - Private key is valid and matches the certificate
|
|
54
|
-
*
|
|
55
|
-
* Returns 'valid' if the cert is good, 'approaching_expiry' if it's still usable
|
|
56
|
-
* but expires within 30 days (renewal should be attempted), or 'invalid' if the
|
|
57
|
-
* cert cannot be used at all.
|
|
58
|
-
*/
|
|
59
|
-
async function checkCertStatus(): Promise<CertStatus> {
|
|
60
|
-
const certPath = getTlsCertPath();
|
|
61
|
-
const keyPath = getTlsKeyPath();
|
|
62
|
-
const fpPath = getTlsFingerprintPath();
|
|
63
|
-
|
|
64
|
-
// Check all three files exist
|
|
65
|
-
const [certExists, keyExists, fpExists] = await Promise.all([
|
|
66
|
-
stat(certPath).then(
|
|
67
|
-
() => true,
|
|
68
|
-
() => false,
|
|
69
|
-
),
|
|
70
|
-
stat(keyPath).then(
|
|
71
|
-
() => true,
|
|
72
|
-
() => false,
|
|
73
|
-
),
|
|
74
|
-
stat(fpPath).then(
|
|
75
|
-
() => true,
|
|
76
|
-
() => false,
|
|
77
|
-
),
|
|
78
|
-
]);
|
|
79
|
-
|
|
80
|
-
if (!certExists || !keyExists || !fpExists) {
|
|
81
|
-
return "invalid";
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
try {
|
|
85
|
-
const [certPem, keyPem, storedFp] = await Promise.all([
|
|
86
|
-
readFile(certPath, "utf-8"),
|
|
87
|
-
readFile(keyPath, "utf-8"),
|
|
88
|
-
readFile(fpPath, "utf-8"),
|
|
89
|
-
]);
|
|
90
|
-
|
|
91
|
-
const x509 = new X509Certificate(certPem);
|
|
92
|
-
|
|
93
|
-
// Check expiration
|
|
94
|
-
const now = new Date();
|
|
95
|
-
const notAfter = new Date(x509.validTo);
|
|
96
|
-
if (notAfter <= now) {
|
|
97
|
-
log.info("Existing TLS certificate has expired, will regenerate");
|
|
98
|
-
return "invalid";
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// Check fingerprint matches
|
|
102
|
-
const actualFp = computeFingerprint(x509);
|
|
103
|
-
if (actualFp !== storedFp.trim()) {
|
|
104
|
-
log.info("TLS fingerprint mismatch, will regenerate");
|
|
105
|
-
return "invalid";
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// Verify the private key is valid and matches the certificate's public key.
|
|
109
|
-
// This catches corrupted key files or cert/key mismatches that would cause
|
|
110
|
-
// tls.createServer() to fail at runtime.
|
|
111
|
-
const privateKey = createPrivateKey(keyPem);
|
|
112
|
-
if (!x509.checkPrivateKey(privateKey)) {
|
|
113
|
-
log.info("TLS private key does not match certificate, will regenerate");
|
|
114
|
-
return "invalid";
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// Cert is structurally valid — check if it's approaching expiry
|
|
118
|
-
const thirtyDaysMs = 30 * 24 * 60 * 60 * 1000;
|
|
119
|
-
if (notAfter.getTime() - now.getTime() < thirtyDaysMs) {
|
|
120
|
-
log.info("TLS certificate approaching expiry, will attempt renewal");
|
|
121
|
-
return "approaching_expiry";
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
return "valid";
|
|
125
|
-
} catch (err) {
|
|
126
|
-
log.warn(
|
|
127
|
-
{ err },
|
|
128
|
-
"Failed to validate existing TLS certificate, will regenerate",
|
|
129
|
-
);
|
|
130
|
-
return "invalid";
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* Ensure a self-signed TLS certificate exists for the daemon.
|
|
136
|
-
*
|
|
137
|
-
* Stores files in `~/.vellum/tls/`:
|
|
138
|
-
* - `cert.pem` (0o644) — self-signed certificate
|
|
139
|
-
* - `key.pem` (0o600) — private key
|
|
140
|
-
* - `fingerprint` (0o644) — SHA-256 hex fingerprint (lowercase, no colons)
|
|
141
|
-
*
|
|
142
|
-
* Idempotent: skips generation if a valid cert already exists.
|
|
143
|
-
* Auto-regenerates if the cert is expired, fingerprint is missing/mismatched,
|
|
144
|
-
* or key/cert files are corrupt.
|
|
145
|
-
*
|
|
146
|
-
* Returns the cert, key (PEM strings), and fingerprint.
|
|
147
|
-
*/
|
|
148
|
-
export async function ensureTlsCert(): Promise<{
|
|
149
|
-
cert: string;
|
|
150
|
-
key: string;
|
|
151
|
-
fingerprint: string;
|
|
152
|
-
}> {
|
|
153
|
-
const tlsDir = getTlsDir();
|
|
154
|
-
const certPath = getTlsCertPath();
|
|
155
|
-
const keyPath = getTlsKeyPath();
|
|
156
|
-
const fpPath = getTlsFingerprintPath();
|
|
157
|
-
|
|
158
|
-
const status = await checkCertStatus();
|
|
159
|
-
|
|
160
|
-
if (status === "valid") {
|
|
161
|
-
const [cert, key, fingerprint] = await Promise.all([
|
|
162
|
-
readFile(certPath, "utf-8"),
|
|
163
|
-
readFile(keyPath, "utf-8"),
|
|
164
|
-
readFile(fpPath, "utf-8"),
|
|
165
|
-
]);
|
|
166
|
-
log.info("Using existing TLS certificate");
|
|
167
|
-
return { cert, key, fingerprint: fingerprint.trim() };
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
if (status === "approaching_expiry") {
|
|
171
|
-
try {
|
|
172
|
-
// Buffer existing cert/key/fingerprint before attempting renewal.
|
|
173
|
-
// generateNewCert() overwrites key.pem in-place, so if it fails mid-flight
|
|
174
|
-
// (e.g., key written but cert generation fails), reading from disk in the
|
|
175
|
-
// catch block would return a mismatched key/cert pair.
|
|
176
|
-
const [existingCert, existingKey, existingFp] = await Promise.all([
|
|
177
|
-
readFile(certPath, "utf-8"),
|
|
178
|
-
readFile(keyPath, "utf-8"),
|
|
179
|
-
readFile(fpPath, "utf-8"),
|
|
180
|
-
]);
|
|
181
|
-
try {
|
|
182
|
-
return await generateNewCert(tlsDir, certPath, keyPath, fpPath);
|
|
183
|
-
} catch (err) {
|
|
184
|
-
log.warn(
|
|
185
|
-
{ err },
|
|
186
|
-
"Proactive TLS renewal failed, continuing with existing certificate",
|
|
187
|
-
);
|
|
188
|
-
return {
|
|
189
|
-
cert: existingCert,
|
|
190
|
-
key: existingKey,
|
|
191
|
-
fingerprint: existingFp.trim(),
|
|
192
|
-
};
|
|
193
|
-
}
|
|
194
|
-
} catch (err) {
|
|
195
|
-
log.warn(
|
|
196
|
-
{ err },
|
|
197
|
-
"Failed to read existing TLS cert for buffering, attempting regeneration",
|
|
198
|
-
);
|
|
199
|
-
return await generateNewCert(tlsDir, certPath, keyPath, fpPath);
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
// status === 'invalid' — must regenerate, no fallback
|
|
204
|
-
return await generateNewCert(tlsDir, certPath, keyPath, fpPath);
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
async function generateNewCert(
|
|
208
|
-
tlsDir: string,
|
|
209
|
-
certPath: string,
|
|
210
|
-
keyPath: string,
|
|
211
|
-
fpPath: string,
|
|
212
|
-
): Promise<{ cert: string; key: string; fingerprint: string }> {
|
|
213
|
-
log.info("Generating new self-signed TLS certificate");
|
|
214
|
-
await mkdir(tlsDir, { recursive: true });
|
|
215
|
-
|
|
216
|
-
// Generate RSA 2048 key
|
|
217
|
-
const keyProc = Bun.spawn(["openssl", "genrsa", "-out", keyPath, "2048"], {
|
|
218
|
-
stdout: "pipe",
|
|
219
|
-
stderr: "pipe",
|
|
220
|
-
});
|
|
221
|
-
const keyExit = await keyProc.exited;
|
|
222
|
-
if (keyExit !== 0) {
|
|
223
|
-
const stderr = await new Response(keyProc.stderr).text();
|
|
224
|
-
throw new Error(`Failed to generate TLS key: ${stderr}`);
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
// Generate self-signed cert (1-year validity)
|
|
228
|
-
const certProc = Bun.spawn(
|
|
229
|
-
[
|
|
230
|
-
"openssl",
|
|
231
|
-
"req",
|
|
232
|
-
"-new",
|
|
233
|
-
"-x509",
|
|
234
|
-
"-key",
|
|
235
|
-
keyPath,
|
|
236
|
-
"-out",
|
|
237
|
-
certPath,
|
|
238
|
-
"-days",
|
|
239
|
-
"365",
|
|
240
|
-
"-subj",
|
|
241
|
-
"/CN=Vellum Daemon",
|
|
242
|
-
],
|
|
243
|
-
{ stdout: "pipe", stderr: "pipe" },
|
|
244
|
-
);
|
|
245
|
-
const certExit = await certProc.exited;
|
|
246
|
-
if (certExit !== 0) {
|
|
247
|
-
const stderr = await new Response(certProc.stderr).text();
|
|
248
|
-
throw new Error(`Failed to generate TLS certificate: ${stderr}`);
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
// Compute and write fingerprint
|
|
252
|
-
const certPem = await readFile(certPath, "utf-8");
|
|
253
|
-
const x509 = new X509Certificate(certPem);
|
|
254
|
-
const fingerprint = computeFingerprint(x509);
|
|
255
|
-
await writeFile(fpPath, fingerprint);
|
|
256
|
-
|
|
257
|
-
// Set permissions: key is private, cert and fingerprint are readable
|
|
258
|
-
await Promise.all([
|
|
259
|
-
chmod(keyPath, 0o600),
|
|
260
|
-
chmod(certPath, 0o644),
|
|
261
|
-
chmod(fpPath, 0o644),
|
|
262
|
-
]);
|
|
263
|
-
|
|
264
|
-
log.info({ fingerprint, certPath }, "TLS certificate generated");
|
|
265
|
-
return {
|
|
266
|
-
cert: certPem,
|
|
267
|
-
key: await readFile(keyPath, "utf-8"),
|
|
268
|
-
fingerprint,
|
|
269
|
-
};
|
|
270
|
-
}
|
package/src/errors.ts
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Central export point for the Vellum error hierarchy.
|
|
3
|
-
*
|
|
4
|
-
* Import from this module to access any named error class:
|
|
5
|
-
*
|
|
6
|
-
* import { VellumError, BackendUnavailableError, RateLimitError, ... } from '../errors.js';
|
|
7
|
-
*
|
|
8
|
-
* Full hierarchy (defined in util/errors.ts):
|
|
9
|
-
*
|
|
10
|
-
* VellumError — root base
|
|
11
|
-
* ├─ BackendError — infrastructure / external-service failures
|
|
12
|
-
* │ ├─ BackendUnavailableError — service not reachable or not configured
|
|
13
|
-
* │ └─ RateLimitError — request or token quota exceeded
|
|
14
|
-
* ├─ UserError — user input / policy violations
|
|
15
|
-
* └─ AssistantError — assistant-logic errors (carries ErrorCode)
|
|
16
|
-
* ├─ ProviderError
|
|
17
|
-
* ├─ ToolError
|
|
18
|
-
* ├─ PermissionDeniedError
|
|
19
|
-
* ├─ ConfigError
|
|
20
|
-
* ├─ DaemonError
|
|
21
|
-
* ├─ PlatformError
|
|
22
|
-
* ├─ IntegrityError
|
|
23
|
-
* └─ IngressBlockedError
|
|
24
|
-
*/
|
|
25
|
-
export {
|
|
26
|
-
AssistantError,
|
|
27
|
-
BackendError,
|
|
28
|
-
BackendUnavailableError,
|
|
29
|
-
ConfigError,
|
|
30
|
-
DaemonError,
|
|
31
|
-
ErrorCode,
|
|
32
|
-
IngressBlockedError,
|
|
33
|
-
IntegrityError,
|
|
34
|
-
PermissionDeniedError,
|
|
35
|
-
PlatformError,
|
|
36
|
-
ProviderError,
|
|
37
|
-
RateLimitError,
|
|
38
|
-
ToolError,
|
|
39
|
-
UserError,
|
|
40
|
-
VellumError,
|
|
41
|
-
} from "./util/errors.js";
|
package/src/events/index.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
export {
|
|
2
|
-
type AnyEventEnvelope,
|
|
3
|
-
type AnyEventListener,
|
|
4
|
-
EventBus,
|
|
5
|
-
EventBusDisposedError,
|
|
6
|
-
type EventListener,
|
|
7
|
-
type EventMap,
|
|
8
|
-
type Subscription,
|
|
9
|
-
} from "./bus.js";
|
|
10
|
-
export type {
|
|
11
|
-
AssistantDomainEvents,
|
|
12
|
-
DaemonDomainEvents,
|
|
13
|
-
ToolDomainEvents,
|
|
14
|
-
} from "./domain-events.js";
|
|
15
|
-
export { createToolDomainEventPublisher } from "./tool-domain-event-publisher.js";
|
|
16
|
-
export { registerToolMetricsLoggingListener } from "./tool-metrics-listener.js";
|
|
17
|
-
export { registerToolNotificationListener } from "./tool-notification-listener.js";
|
|
18
|
-
export { registerToolTraceListener } from "./tool-trace-listener.js";
|
package/src/followups/index.ts
DELETED
package/src/playbooks/index.ts
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Auth module barrel export.
|
|
3
|
-
*
|
|
4
|
-
* Re-exports all public types and functions from the auth subsystem
|
|
5
|
-
* so consumers can import from a single path.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
export type { BuildAuthContextResult } from "./context.js";
|
|
9
|
-
export { buildAuthContext } from "./context.js";
|
|
10
|
-
export type {
|
|
11
|
-
CredentialPairResult,
|
|
12
|
-
RefreshErrorCode,
|
|
13
|
-
RotateResult,
|
|
14
|
-
} from "./credential-service.js";
|
|
15
|
-
export { mintCredentialPair, rotateCredentials } from "./credential-service.js";
|
|
16
|
-
export {
|
|
17
|
-
getExternalAssistantId,
|
|
18
|
-
resetExternalAssistantIdCache,
|
|
19
|
-
} from "./external-assistant-id.js";
|
|
20
|
-
export type { AuthenticateResult } from "./middleware.js";
|
|
21
|
-
export { authenticateRequest } from "./middleware.js";
|
|
22
|
-
export { CURRENT_POLICY_EPOCH, isStaleEpoch } from "./policy.js";
|
|
23
|
-
export type { RoutePolicy } from "./route-policy.js";
|
|
24
|
-
export { enforcePolicy, getPolicy, registerPolicy } from "./route-policy.js";
|
|
25
|
-
export { hasAllScopes, hasScope, resolveScopeProfile } from "./scopes.js";
|
|
26
|
-
export type { ParseSubResult } from "./subject.js";
|
|
27
|
-
export { parseSub } from "./subject.js";
|
|
28
|
-
export type { VerifyResult } from "./token-service.js";
|
|
29
|
-
export {
|
|
30
|
-
hashToken,
|
|
31
|
-
initAuthSigningKey,
|
|
32
|
-
loadOrCreateSigningKey,
|
|
33
|
-
mintDaemonDeliveryToken,
|
|
34
|
-
mintToken,
|
|
35
|
-
verifyToken,
|
|
36
|
-
} from "./token-service.js";
|
|
37
|
-
export type {
|
|
38
|
-
AuthContext,
|
|
39
|
-
PrincipalType,
|
|
40
|
-
Scope,
|
|
41
|
-
ScopeProfile,
|
|
42
|
-
TokenAudience,
|
|
43
|
-
TokenClaims,
|
|
44
|
-
} from "./types.js";
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import { desc, eq, isNull } from "drizzle-orm";
|
|
2
|
-
|
|
3
|
-
import { getDb } from "../memory/db.js";
|
|
4
|
-
import { taskCandidates } from "../memory/schema.js";
|
|
5
|
-
|
|
6
|
-
// ── Types ────────────────────────────────────────────────────────────
|
|
7
|
-
|
|
8
|
-
export interface TaskCandidate {
|
|
9
|
-
id: string;
|
|
10
|
-
sourceConversationId: string;
|
|
11
|
-
compiledTemplate: string;
|
|
12
|
-
confidence: number | null;
|
|
13
|
-
requiredTools: string[] | null;
|
|
14
|
-
createdAt: number;
|
|
15
|
-
promotedTaskId: string | null;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
// ── Helpers ──────────────────────────────────────────────────────────
|
|
19
|
-
|
|
20
|
-
/** Convert a raw DB row to a TaskCandidate, deserializing the JSON requiredTools field. */
|
|
21
|
-
function rowToCandidate(
|
|
22
|
-
row: typeof taskCandidates.$inferSelect,
|
|
23
|
-
): TaskCandidate {
|
|
24
|
-
return {
|
|
25
|
-
id: row.id,
|
|
26
|
-
sourceConversationId: row.sourceConversationId,
|
|
27
|
-
compiledTemplate: row.compiledTemplate,
|
|
28
|
-
confidence: row.confidence,
|
|
29
|
-
requiredTools: row.requiredTools ? JSON.parse(row.requiredTools) : null,
|
|
30
|
-
createdAt: row.createdAt,
|
|
31
|
-
promotedTaskId: row.promotedTaskId,
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// ── CRUD ─────────────────────────────────────────────────────────────
|
|
36
|
-
|
|
37
|
-
/** Record a new task candidate from a conversation. */
|
|
38
|
-
export function createCandidate(opts: {
|
|
39
|
-
sourceConversationId: string;
|
|
40
|
-
compiledTemplate: string;
|
|
41
|
-
confidence?: number;
|
|
42
|
-
requiredTools?: string[];
|
|
43
|
-
}): TaskCandidate {
|
|
44
|
-
const db = getDb();
|
|
45
|
-
const now = Date.now();
|
|
46
|
-
const id = crypto.randomUUID();
|
|
47
|
-
const row = {
|
|
48
|
-
id,
|
|
49
|
-
sourceConversationId: opts.sourceConversationId,
|
|
50
|
-
compiledTemplate: opts.compiledTemplate,
|
|
51
|
-
confidence: opts.confidence ?? null,
|
|
52
|
-
requiredTools: opts.requiredTools
|
|
53
|
-
? JSON.stringify(opts.requiredTools)
|
|
54
|
-
: null,
|
|
55
|
-
createdAt: now,
|
|
56
|
-
promotedTaskId: null,
|
|
57
|
-
};
|
|
58
|
-
db.insert(taskCandidates).values(row).run();
|
|
59
|
-
return {
|
|
60
|
-
...row,
|
|
61
|
-
requiredTools: opts.requiredTools ?? null,
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/** List unpromoted candidates (most recent first). */
|
|
66
|
-
export function listUnpromotedCandidates(limit?: number): TaskCandidate[] {
|
|
67
|
-
const db = getDb();
|
|
68
|
-
const query = db
|
|
69
|
-
.select()
|
|
70
|
-
.from(taskCandidates)
|
|
71
|
-
.where(isNull(taskCandidates.promotedTaskId))
|
|
72
|
-
.orderBy(desc(taskCandidates.createdAt));
|
|
73
|
-
const rows = limit ? query.limit(limit).all() : query.all();
|
|
74
|
-
return rows.map(rowToCandidate);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/** Mark a candidate as promoted to a real task. */
|
|
78
|
-
export function promoteCandidate(candidateId: string, taskId: string): void {
|
|
79
|
-
const db = getDb();
|
|
80
|
-
db.update(taskCandidates)
|
|
81
|
-
.set({ promotedTaskId: taskId })
|
|
82
|
-
.where(eq(taskCandidates.id, candidateId))
|
|
83
|
-
.run();
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/** Get a candidate by ID. */
|
|
87
|
-
export function getCandidate(id: string): TaskCandidate | undefined {
|
|
88
|
-
const db = getDb();
|
|
89
|
-
const row = db
|
|
90
|
-
.select()
|
|
91
|
-
.from(taskCandidates)
|
|
92
|
-
.where(eq(taskCandidates.id, id))
|
|
93
|
-
.get();
|
|
94
|
-
return row ? rowToCandidate(row) : undefined;
|
|
95
|
-
}
|