thumbgate 1.35.0 → 1.37.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/skills/cyberstrike-compare-not-clone/SKILL.md +36 -0
- package/.agents/skills/gitlab-sandbox-allowlist-not-trust/SKILL.md +77 -0
- package/.agents/skills/jit-harness-compare-not-clone/SKILL.md +34 -0
- package/.agents/skills/openui-catalog-compose-honesty/SKILL.md +64 -0
- package/.agents/skills/zvec-grep-compare-not-clone/SKILL.md +34 -0
- package/.claude-plugin/plugin.json +1 -1
- package/.well-known/llms.txt +1 -0
- package/.well-known/mcp/server-card.json +1 -1
- package/CONTRIBUTING.md +95 -0
- package/README.md +195 -632
- package/THIRD_PARTY_NOTICES.md +89 -0
- package/adapters/claude/.mcp.json +2 -2
- package/adapters/forge/forge.yaml +3 -3
- package/adapters/future-agi/.mcp.json +8 -0
- package/adapters/future-agi/FUTURE_AGI.md +23 -0
- package/adapters/future-agi/config.toml +3 -0
- package/adapters/future-agi/future-agi-bridge.js +9 -0
- package/adapters/future-agi/opencode.json +8 -0
- package/adapters/herdr/herdr-plugin.toml +18 -0
- package/adapters/mcp/server-stdio.js +238 -25
- package/adapters/opencode/opencode.json +1 -1
- package/adapters/workos/WORKOS.md +52 -0
- package/bin/cli.js +336 -3
- package/bin/futureagi-bridge +9 -0
- package/config/gate-templates.json +581 -4
- package/config/gates/actor-critic-audit.json +34 -0
- package/config/gates/default.json +9 -3
- package/config/gates/five-walls-governance.json +34 -0
- package/config/gates/future-agi-guardrails.json +34 -0
- package/config/gates/radware-threat-defense-2026.json +61 -0
- package/config/gates/simatree-data-governance.json +33 -0
- package/config/mcp-allowlists.json +4 -0
- package/config/merge-quality-checks.json +6 -0
- package/config/model-candidates.json +312 -29
- package/config/model-tiers.json +18 -0
- package/config/post-deploy-marketing-pages.json +10 -0
- package/config/progressive/01-wire-only.json +11 -0
- package/config/progressive/02-dashboard-empty-ok.json +10 -0
- package/config/progressive/03-one-lesson.json +10 -0
- package/config/progressive/04-warn-fires.json +11 -0
- package/config/progressive/05-strict-optional.json +11 -0
- package/config/progressive/README.md +15 -0
- package/config/schemas/broker-execution-receipt.schema.json +139 -0
- package/config/schemas/provider-execution-attestation-v1.schema.json +58 -0
- package/conformance/provider-attestation/vectors.json +320 -0
- package/docs/specs/provider-execution-attestation-v1.md +69 -0
- package/openapi/openapi.yaml +15 -0
- package/package.json +390 -148
- package/public/about.html +2 -2
- package/public/ai-malpractice-prevention.html +7 -7
- package/public/blog/a-10-dollar-vps-is-not-a-computer.html +143 -0
- package/public/blog/a-receipt-is-not-world-state.html +388 -0
- package/public/blog/git-at-agent-scale.html +374 -0
- package/public/blog/no-llm-in-the-gate.html +133 -0
- package/public/blog.html +80 -0
- package/public/case-studies.html +16 -1
- package/public/compare.html +28 -0
- package/public/diagnostic.html +216 -7
- package/public/docs/connectors.html +39 -0
- package/public/federal.html +2 -2
- package/public/founders.html +639 -0
- package/public/index.html +87 -9
- package/public/install.html +8 -8
- package/public/learn.html +39 -0
- package/public/numbers.html +2 -2
- package/public/peter.html +310 -0
- package/public/platform-partners.html +119 -0
- package/public/pricing.html +24 -3
- package/public/privacy.html +117 -0
- package/public/pro.html +17 -0
- package/public/support.html +62 -0
- package/public/terms.html +130 -0
- package/public/third-party-notices.html +95 -0
- package/public/yt.html +351 -0
- package/scripts/action-receipts.js +133 -3
- package/scripts/adaptive-governance-arena.js +349 -0
- package/scripts/admin-override.js +205 -0
- package/scripts/agent-action-inventory.js +869 -0
- package/scripts/agent-audit-trace.js +42 -2
- package/scripts/agent-egress-policy.js +1117 -0
- package/scripts/agent-memory-lifecycle.js +141 -2
- package/scripts/agent-operations-planner.js +441 -1
- package/scripts/agent-readiness.js +68 -0
- package/scripts/agent-security-central.js +647 -0
- package/scripts/allowlist-bridge-honesty.js +417 -0
- package/scripts/async-job-runner.js +102 -11
- package/scripts/audit-trail.js +212 -0
- package/scripts/billing.js +1 -1
- package/scripts/broker-execution-receipts.js +719 -0
- package/scripts/budget-aware-gates-proof.js +423 -0
- package/scripts/claude-feedback-sync.js +29 -3
- package/scripts/claw-harness-production.js +237 -0
- package/scripts/cli-schema.js +163 -1
- package/scripts/codex-runbook-flywheel.js +318 -0
- package/scripts/context-footprint.js +186 -0
- package/scripts/contextfs.js +143 -61
- package/scripts/dashboard.js +251 -32
- package/scripts/deepseek-v4-runtime-guardrails.js +72 -6
- package/scripts/docker-sandbox-planner.js +18 -0
- package/scripts/double-blind-eval-protocol.js +252 -0
- package/scripts/edotenv-rl-gateway.js +259 -0
- package/scripts/ensure-production-search-corpus.js +162 -0
- package/scripts/eval-holdout.js +311 -0
- package/scripts/feedback-aggregate.js +21 -2
- package/scripts/feedback-loop.js +87 -5
- package/scripts/feedback-quality.js +9 -0
- package/scripts/file-ledger-lock.js +4 -1
- package/scripts/financial-control-plane.js +41 -1
- package/scripts/find-dormant-requires.js +118 -0
- package/scripts/fs-utils.js +84 -8
- package/scripts/gates-engine.js +810 -63
- package/scripts/generate-case-study-outreach.js +24 -15
- package/scripts/git-at-scale.js +628 -0
- package/scripts/governance-conflict-audit.js +1650 -0
- package/scripts/governance-difficulty-curriculum.js +328 -0
- package/scripts/graphrag-retrieval.js +275 -0
- package/scripts/gurobi-optimizer.js +324 -0
- package/scripts/gurobi_optimizer.py +485 -0
- package/scripts/harness-selector.js +82 -1
- package/scripts/hidden-entry-points.js +284 -0
- package/scripts/human-escalation.js +199 -1
- package/scripts/hybrid-feedback-context.js +152 -19
- package/scripts/intent-governed-execution.js +602 -0
- package/scripts/intervention-policy.js +123 -20
- package/scripts/jit-harness-compose.js +628 -0
- package/scripts/jsonl-watcher.js +10 -0
- package/scripts/lesson-embedding-index.js +95 -12
- package/scripts/lesson-retrieval.js +105 -19
- package/scripts/local-model-profile.js +19 -2
- package/scripts/mailer/resend-mailer.js +1 -1
- package/scripts/matryoshka-embedding.js +235 -0
- package/scripts/mcp-oauth.js +42 -4
- package/scripts/mcp-session-handles.js +1016 -0
- package/scripts/mcp-wiring-doctor.js +314 -0
- package/scripts/memory-firewall.js +115 -2
- package/scripts/memory-scope-readiness.js +299 -0
- package/scripts/memory-vs-rag-route.js +161 -0
- package/scripts/model-tier-router.js +148 -21
- package/scripts/nvidia-specdecode-al-doctor.js +536 -0
- package/scripts/openui-catalog-compose-honesty.js +593 -0
- package/scripts/operational-integrity.js +19 -1
- package/scripts/override-audit.js +213 -0
- package/scripts/package-manager-honesty-doctor.js +458 -0
- package/scripts/pr-manager.js +63 -1
- package/scripts/prove-herdr-adapter.js +52 -0
- package/scripts/prove-memory-pyramid-and-symbolic-canvas.js +95 -0
- package/scripts/prove-workos.js +73 -0
- package/scripts/provider-attestation-conformance.js +192 -0
- package/scripts/provider-receipt-contract.js +136 -0
- package/scripts/qwen38-max-cost-optimizer.js +401 -0
- package/scripts/radware-threat-defense.js +280 -0
- package/scripts/rag-embedding-identity.js +221 -0
- package/scripts/rag-precision-guardrails.js +112 -2
- package/scripts/remote-feedback-capture.js +159 -0
- package/scripts/research-agent-harness.js +256 -0
- package/scripts/rsi-safety-hillclimb.js +200 -0
- package/scripts/rule-sprawl.js +188 -0
- package/scripts/schedule-manager.js +147 -0
- package/scripts/self-heal.js +8 -0
- package/scripts/session-lease.js +415 -0
- package/scripts/simatree-data-governance.js +347 -0
- package/scripts/slo-alert-engine.js +172 -7
- package/scripts/solver-parity.js +539 -0
- package/scripts/stealth-memory-injection-gate.js +333 -0
- package/scripts/switchyard-router.js +366 -0
- package/scripts/telemetry-analytics.js +84 -27
- package/scripts/temporal-decay-weighting.js +138 -0
- package/scripts/test-all.js +165 -0
- package/scripts/token-savings.js +42 -0
- package/scripts/tool-kpi-tracker.js +108 -5
- package/scripts/tool-registry.js +193 -5
- package/scripts/universal-claim-evaluator.js +14 -2
- package/scripts/vector-store.js +279 -9
- package/scripts/workflow-notebook.js +391 -0
- package/scripts/workflow-sentinel.js +111 -12
- package/scripts/workos-production-guard.js +260 -0
- package/scripts/workspace-search-route.js +515 -0
- package/server.json +2 -2
- package/src/agent-identity-boundary.js +76 -0
- package/src/agent-retrieval-cache.js +155 -0
- package/src/alert-noise-ledger.js +502 -0
- package/src/api/server.js +724 -153
- package/src/git-fast-cache.js +220 -0
- package/src/git-wal-sync.js +156 -0
- package/src/hash-anchored-edit.js +82 -0
- package/src/hermes-platform-protocol.js +475 -0
- package/src/hermes-sync-plane.js +241 -0
- package/src/index.js +30 -1
- package/src/iso42001-compliance-guard.js +97 -0
- package/src/latency-budget.js +244 -0
- package/src/mcp-writeguard.js +316 -0
- package/src/miminions-adapter.js +106 -0
- package/src/pipeline-compass.js +104 -0
- package/src/ppl-alert-pipeline.js +284 -0
- package/src/rendezvous-router.js +90 -0
- package/src/security-questionnaire.js +195 -0
package/scripts/audit-trail.js
CHANGED
|
@@ -27,6 +27,200 @@ function getAuditLogPath() {
|
|
|
27
27
|
return path.join(resolveFeedbackDir(), AUDIT_LOG_FILENAME);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
/**
|
|
31
|
+
* Resolve the acting non-human identity for audit attribution. Sessions and
|
|
32
|
+
* worktree leases export THUMBGATE_SESSION_AGENT; THUMBGATE_AGENT_ID is the
|
|
33
|
+
* generic override. Null when the caller cannot be attributed — audit records
|
|
34
|
+
* must never invent an identity.
|
|
35
|
+
*/
|
|
36
|
+
function resolveAuditAgentId() {
|
|
37
|
+
return process.env.THUMBGATE_SESSION_AGENT
|
|
38
|
+
|| process.env.THUMBGATE_AGENT_ID
|
|
39
|
+
|| null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
// Agent identity store — registry + observed-agent stream
|
|
44
|
+
//
|
|
45
|
+
// Lives here (not in org-dashboard) because the gates-engine identity gate and
|
|
46
|
+
// audit attribution are public runtime surfaces, while org-dashboard stays out
|
|
47
|
+
// of the npm tarball. org-dashboard re-exports these for its Pro reporting.
|
|
48
|
+
// ---------------------------------------------------------------------------
|
|
49
|
+
|
|
50
|
+
const REGISTRY_FILENAME = 'agent-registry.jsonl';
|
|
51
|
+
const OBSERVED_FILENAME = 'observed-agents.jsonl';
|
|
52
|
+
const OBSERVED_COMPACT_BYTES = 512 * 1024;
|
|
53
|
+
|
|
54
|
+
function getRegistryPath() {
|
|
55
|
+
return path.join(resolveFeedbackDir(), REGISTRY_FILENAME);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function getObservedAgentsPath() {
|
|
59
|
+
return path.join(resolveFeedbackDir(), OBSERVED_FILENAME);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Register an agent session. Called on MCP server startup or agent bootstrap.
|
|
64
|
+
*/
|
|
65
|
+
function registerAgent({ agentId, source, project, branch, metadata } = {}) {
|
|
66
|
+
const id = agentId || `agent_${Date.now()}_${crypto.randomUUID().slice(0, 8)}`;
|
|
67
|
+
const record = {
|
|
68
|
+
id,
|
|
69
|
+
registeredAt: new Date().toISOString(),
|
|
70
|
+
lastSeenAt: new Date().toISOString(),
|
|
71
|
+
source: source || 'unknown',
|
|
72
|
+
project: project || path.basename(process.cwd()),
|
|
73
|
+
branch: branch || null,
|
|
74
|
+
toolCalls: 0,
|
|
75
|
+
gateBlocks: 0,
|
|
76
|
+
gateWarns: 0,
|
|
77
|
+
metadata: { lifecycleStatus: 'active', ...(metadata || {}) },
|
|
78
|
+
};
|
|
79
|
+
const registryPath = getRegistryPath();
|
|
80
|
+
ensureDir(path.dirname(registryPath));
|
|
81
|
+
fs.appendFileSync(registryPath, JSON.stringify(record) + '\n');
|
|
82
|
+
return record;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Record agent activity — called after each tool call evaluation.
|
|
87
|
+
*/
|
|
88
|
+
function recordAgentActivity(agentId, decision) {
|
|
89
|
+
const registryPath = getRegistryPath();
|
|
90
|
+
if (!fs.existsSync(registryPath)) return;
|
|
91
|
+
const lines = fs.readFileSync(registryPath, 'utf-8').trim().split('\n');
|
|
92
|
+
const updated = [];
|
|
93
|
+
let found = false;
|
|
94
|
+
for (const line of lines) {
|
|
95
|
+
try {
|
|
96
|
+
const record = JSON.parse(line);
|
|
97
|
+
if (record.id === agentId && !found) {
|
|
98
|
+
record.lastSeenAt = new Date().toISOString();
|
|
99
|
+
record.toolCalls = (record.toolCalls || 0) + 1;
|
|
100
|
+
if (decision === 'deny') record.gateBlocks = (record.gateBlocks || 0) + 1;
|
|
101
|
+
if (decision === 'warn') record.gateWarns = (record.gateWarns || 0) + 1;
|
|
102
|
+
found = true;
|
|
103
|
+
}
|
|
104
|
+
updated.push(JSON.stringify(record));
|
|
105
|
+
} catch {
|
|
106
|
+
updated.push(line);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
fs.writeFileSync(registryPath, updated.join('\n') + '\n');
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Load all registered agent sessions.
|
|
114
|
+
*/
|
|
115
|
+
function loadAgentRegistry() {
|
|
116
|
+
const registryPath = getRegistryPath();
|
|
117
|
+
if (!fs.existsSync(registryPath)) return [];
|
|
118
|
+
const raw = fs.readFileSync(registryPath, 'utf-8').trim();
|
|
119
|
+
if (!raw) return [];
|
|
120
|
+
const records = [];
|
|
121
|
+
for (const line of raw.split('\n')) {
|
|
122
|
+
try {
|
|
123
|
+
records.push(JSON.parse(line));
|
|
124
|
+
} catch {
|
|
125
|
+
// Skip corrupt rows; identity checks fail open, never crash.
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return records;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Retire an agent identity. A retired agent that keeps acting is flagged by
|
|
133
|
+
* the gates-engine identity gate (deny under strict enforcement).
|
|
134
|
+
*/
|
|
135
|
+
function retireAgent(agentId, reason) {
|
|
136
|
+
const registryPath = getRegistryPath();
|
|
137
|
+
if (!fs.existsSync(registryPath)) return false;
|
|
138
|
+
const lines = fs.readFileSync(registryPath, 'utf-8').trim().split('\n');
|
|
139
|
+
const updated = [];
|
|
140
|
+
let found = false;
|
|
141
|
+
for (const line of lines) {
|
|
142
|
+
try {
|
|
143
|
+
const record = JSON.parse(line);
|
|
144
|
+
if (record.id === agentId) {
|
|
145
|
+
record.metadata = record.metadata || {};
|
|
146
|
+
record.metadata.lifecycleStatus = 'retired';
|
|
147
|
+
record.metadata.retiredAt = new Date().toISOString();
|
|
148
|
+
if (reason) record.metadata.retireReason = String(reason);
|
|
149
|
+
found = true;
|
|
150
|
+
}
|
|
151
|
+
updated.push(JSON.stringify(record));
|
|
152
|
+
} catch {
|
|
153
|
+
updated.push(line);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
if (found) fs.writeFileSync(registryPath, updated.join('\n') + '\n');
|
|
157
|
+
return found;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Record one observation of an acting agent — the producer side of shadow-AI
|
|
162
|
+
* detection, called from the gates-engine evaluation path on every attributed
|
|
163
|
+
* tool call. Appends are plain (never lost to a busy lock); compaction runs
|
|
164
|
+
* only under the cross-process ledger lock so a concurrent agent's append can
|
|
165
|
+
* never be truncated by the read-aggregate-rewrite window.
|
|
166
|
+
*/
|
|
167
|
+
function recordObservedAgent(agentId) {
|
|
168
|
+
const id = String(agentId || '').trim();
|
|
169
|
+
if (!id) return null;
|
|
170
|
+
const observedPath = getObservedAgentsPath();
|
|
171
|
+
ensureDir(path.dirname(observedPath));
|
|
172
|
+
const event = { id, seenAt: new Date().toISOString() };
|
|
173
|
+
fs.appendFileSync(observedPath, JSON.stringify(event) + '\n');
|
|
174
|
+
try {
|
|
175
|
+
if (fs.statSync(observedPath).size > OBSERVED_COMPACT_BYTES) {
|
|
176
|
+
const { withFileLedgerLock } = require('./file-ledger-lock');
|
|
177
|
+
withFileLedgerLock(observedPath + '.lock', () => {
|
|
178
|
+
const compacted = loadObservedAgents()
|
|
179
|
+
.map((row) => JSON.stringify(row))
|
|
180
|
+
.join('\n');
|
|
181
|
+
fs.writeFileSync(observedPath, compacted + '\n');
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
} catch {
|
|
185
|
+
// Busy lock or read error: skip compaction, never drop the observation.
|
|
186
|
+
}
|
|
187
|
+
return event;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Aggregate observation events into one row per agent id:
|
|
192
|
+
* { id, firstSeenAt, lastSeenAt, observations }.
|
|
193
|
+
*/
|
|
194
|
+
function loadObservedAgents() {
|
|
195
|
+
const observedPath = getObservedAgentsPath();
|
|
196
|
+
if (!fs.existsSync(observedPath)) return [];
|
|
197
|
+
const byId = new Map();
|
|
198
|
+
const raw = fs.readFileSync(observedPath, 'utf-8').trim();
|
|
199
|
+
if (!raw) return [];
|
|
200
|
+
for (const line of raw.split('\n')) {
|
|
201
|
+
let event;
|
|
202
|
+
try {
|
|
203
|
+
event = JSON.parse(line);
|
|
204
|
+
} catch {
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
const id = String(event.id || '').trim();
|
|
208
|
+
if (!id) continue;
|
|
209
|
+
const seenAt = event.seenAt || event.lastSeenAt || new Date().toISOString();
|
|
210
|
+
const row = byId.get(id) || {
|
|
211
|
+
id,
|
|
212
|
+
firstSeenAt: event.firstSeenAt || seenAt,
|
|
213
|
+
lastSeenAt: seenAt,
|
|
214
|
+
observations: 0,
|
|
215
|
+
};
|
|
216
|
+
if (seenAt < row.firstSeenAt) row.firstSeenAt = seenAt;
|
|
217
|
+
if (seenAt > row.lastSeenAt) row.lastSeenAt = seenAt;
|
|
218
|
+
row.observations += Number(event.observations) > 0 ? Number(event.observations) : 1;
|
|
219
|
+
byId.set(id, row);
|
|
220
|
+
}
|
|
221
|
+
return [...byId.values()];
|
|
222
|
+
}
|
|
223
|
+
|
|
30
224
|
|
|
31
225
|
// ---------------------------------------------------------------------------
|
|
32
226
|
// Core audit record
|
|
@@ -53,6 +247,7 @@ function recordAuditEvent(params = {}) {
|
|
|
53
247
|
timestamp: new Date().toISOString(),
|
|
54
248
|
toolName: params.toolName || 'unknown',
|
|
55
249
|
toolInput: sanitizeToolInput(params.toolInput || {}),
|
|
250
|
+
agentId: params.agentId || resolveAuditAgentId(),
|
|
56
251
|
decision: params.decision || 'allow',
|
|
57
252
|
gateId: params.gateId || null,
|
|
58
253
|
message: params.message || null,
|
|
@@ -61,6 +256,13 @@ function recordAuditEvent(params = {}) {
|
|
|
61
256
|
source: params.source || 'gates-engine',
|
|
62
257
|
};
|
|
63
258
|
|
|
259
|
+
// Typed override payload (see scripts/override-audit.js). Carried verbatim so
|
|
260
|
+
// an override is filterable by decision === 'override' rather than having to
|
|
261
|
+
// be inferred from toolName, which cannot distinguish it from a normal call.
|
|
262
|
+
if (params.override && typeof params.override === 'object') {
|
|
263
|
+
record.override = params.override;
|
|
264
|
+
}
|
|
265
|
+
|
|
64
266
|
// Safe stringify: never let circular/toxic tool inputs crash the gate path
|
|
65
267
|
// (Antithesis-style invariant: evaluation + audit must not throw).
|
|
66
268
|
let line;
|
|
@@ -353,6 +555,16 @@ module.exports = {
|
|
|
353
555
|
recordAuditEvent,
|
|
354
556
|
auditToFeedback,
|
|
355
557
|
readAuditLog,
|
|
558
|
+
registerAgent,
|
|
559
|
+
recordAgentActivity,
|
|
560
|
+
loadAgentRegistry,
|
|
561
|
+
retireAgent,
|
|
562
|
+
recordObservedAgent,
|
|
563
|
+
loadObservedAgents,
|
|
564
|
+
getRegistryPath,
|
|
565
|
+
getObservedAgentsPath,
|
|
566
|
+
REGISTRY_FILENAME,
|
|
567
|
+
OBSERVED_FILENAME,
|
|
356
568
|
auditStats,
|
|
357
569
|
latencyStats,
|
|
358
570
|
skillAdherence,
|
package/scripts/billing.js
CHANGED
|
@@ -110,7 +110,7 @@ const CONFIG = {
|
|
|
110
110
|
},
|
|
111
111
|
RESEND_API_KEY: process.env.RESEND_API_KEY || process.env.THUMBGATE_RESEND_API_KEY || '',
|
|
112
112
|
TRIAL_EMAIL_FROM: process.env.THUMBGATE_TRIAL_EMAIL_FROM || process.env.RESEND_FROM_EMAIL || process.env.RESEND_FROM || 'onboarding@resend.dev',
|
|
113
|
-
TRIAL_EMAIL_REPLY_TO: process.env.THUMBGATE_TRIAL_EMAIL_REPLY_TO || '
|
|
113
|
+
TRIAL_EMAIL_REPLY_TO: process.env.THUMBGATE_TRIAL_EMAIL_REPLY_TO || 'support@thumbgate.ai',
|
|
114
114
|
CREDIT_PACKS: {}
|
|
115
115
|
};
|
|
116
116
|
|